mirror of
https://github.com/jcreek/jcreek.github.io.git
synced 2026-07-13 02:53:50 +00:00
1577 lines
67 KiB
HTML
1577 lines
67 KiB
HTML
|
|
<!doctype html>
|
|
<html lang="en" class="no-js">
|
|
<head>
|
|
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
|
|
|
|
|
|
<link rel="canonical" href="https://www.jcreek.co.uk/web-dev/dotnet-csharp/semantic-kernel-vector-database/">
|
|
|
|
|
|
|
|
|
|
<link rel="icon" href="../../../img/favicon.ico">
|
|
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.12">
|
|
|
|
|
|
|
|
<title>Semantic Kernel (GPT with C#) - using a vector database to store embeddings - Josh Creek's Blog</title>
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="../../../assets/stylesheets/main.2afb09e1.min.css">
|
|
|
|
|
|
<link rel="stylesheet" href="../../../assets/stylesheets/palette.06af60db.min.css">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
|
|
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
|
|
|
|
|
|
|
<script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script id="__analytics">function __md_analytics(){function e(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],e("js",new Date),e("config","G-MYNBTM1YQW"),document.addEventListener("DOMContentLoaded",(function(){document.forms.search&&document.forms.search.query.addEventListener("blur",(function(){this.value&&e("event","search",{search_term:this.value})}));document$.subscribe((function(){var t=document.forms.feedback;if(void 0!==t)for(var a of t.querySelectorAll("[type=submit]"))a.addEventListener("click",(function(a){a.preventDefault();var n=document.location.pathname,d=this.getAttribute("data-md-value");e("event","feedback",{page:n,data:d}),t.firstElementChild.disabled=!0;var r=t.querySelector(".md-feedback__note [data-md-value='"+d+"']");r&&(r.hidden=!1)})),t.hidden=!1})),location$.subscribe((function(t){e("config","G-MYNBTM1YQW",{page_path:t.pathname})}))}));var t=document.createElement("script");t.async=!0,t.src="https://www.googletagmanager.com/gtag/js?id=G-MYNBTM1YQW",document.getElementById("__analytics").insertAdjacentElement("afterEnd",t)}</script>
|
|
|
|
<script>if("undefined"!=typeof __md_analytics){var consent=__md_get("__consent");consent&&consent.analytics&&__md_analytics()}</script>
|
|
|
|
|
|
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="amber" data-md-color-accent="amber">
|
|
|
|
|
|
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
|
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
|
<label class="md-overlay" for="__drawer"></label>
|
|
<div data-md-component="skip">
|
|
|
|
|
|
<a href="#semantic-kernel-gpt-with-c-using-a-vector-database-to-store-embeddings" class="md-skip">
|
|
Skip to content
|
|
</a>
|
|
|
|
</div>
|
|
<div data-md-component="announce">
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<header class="md-header md-header--shadow md-header--lifted" data-md-component="header">
|
|
<nav class="md-header__inner md-grid" aria-label="Header">
|
|
<a href="../../.." title="Josh Creek's Blog" class="md-header__button md-logo" aria-label="Josh Creek's Blog" data-md-component="logo">
|
|
|
|
<img src="../../../img/noogler-hat-edited-round.png" alt="logo">
|
|
|
|
</a>
|
|
<label class="md-header__button md-icon" for="__drawer">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
|
|
</label>
|
|
<div class="md-header__title" data-md-component="header-title">
|
|
<div class="md-header__ellipsis">
|
|
<div class="md-header__topic">
|
|
<span class="md-ellipsis">
|
|
Josh Creek's Blog
|
|
</span>
|
|
</div>
|
|
<div class="md-header__topic" data-md-component="header-topic">
|
|
<span class="md-ellipsis">
|
|
|
|
Semantic Kernel (GPT with C#) - using a vector database to store embeddings
|
|
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<form class="md-header__option" data-md-component="palette">
|
|
|
|
|
|
|
|
|
|
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="amber" data-md-color-accent="amber" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
|
|
|
|
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
|
|
</label>
|
|
|
|
|
|
|
|
|
|
|
|
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="amber" data-md-color-accent="amber" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
|
|
|
|
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
|
|
</label>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
|
|
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-header__button md-icon" for="__search">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
|
|
</label>
|
|
<div class="md-search" data-md-component="search" role="dialog">
|
|
<label class="md-search__overlay" for="__search"></label>
|
|
<div class="md-search__inner" role="search">
|
|
<form class="md-search__form" name="search">
|
|
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
|
|
<label class="md-search__icon md-icon" for="__search">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
|
|
</label>
|
|
<nav class="md-search__options" aria-label="Search">
|
|
|
|
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"/></svg>
|
|
</a>
|
|
|
|
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
|
|
</button>
|
|
</nav>
|
|
|
|
<div class="md-search__suggest" data-md-component="search-suggest"></div>
|
|
|
|
</form>
|
|
<div class="md-search__output">
|
|
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
|
|
<div class="md-search-result" data-md-component="search-result">
|
|
<div class="md-search-result__meta">
|
|
Initializing search
|
|
</div>
|
|
<ol class="md-search-result__list" role="presentation"></ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="md-header__source">
|
|
<a href="https://github.com/jcreek/jcreek.github.io" title="Go to repository" class="md-source" data-md-component="source">
|
|
<div class="md-source__icon md-icon">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg>
|
|
</div>
|
|
<div class="md-source__repository">
|
|
Spotted an issue?
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
|
|
<div class="md-grid">
|
|
<ul class="md-tabs__list">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../.." class="md-tabs__link">
|
|
|
|
|
|
|
|
|
|
|
|
Home
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../../deploying/docker-compose-for-asp-net-core-with-postgres-and-s3-backups/" class="md-tabs__link">
|
|
|
|
|
|
|
|
Containers & Deploying
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../../dev-team/git/" class="md-tabs__link">
|
|
|
|
|
|
|
|
Development Teams
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../../home-server/generative-ai/ollama/" class="md-tabs__link">
|
|
|
|
|
|
|
|
Home Server
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-tabs__item">
|
|
<a href="../../dev-environment-container-vscode/" class="md-tabs__link">
|
|
|
|
|
|
|
|
Web Development
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
|
|
|
|
</header>
|
|
|
|
<div class="md-container" data-md-component="container">
|
|
|
|
|
|
|
|
|
|
<main class="md-main" data-md-component="main">
|
|
<div class="md-main__inner md-grid">
|
|
|
|
|
|
|
|
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
|
<div class="md-sidebar__scrollwrap">
|
|
<div class="md-sidebar__inner">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<nav class="md-nav md-nav--primary md-nav--lifted md-nav--integrated" aria-label="Navigation" data-md-level="0">
|
|
<label class="md-nav__title" for="__drawer">
|
|
<a href="../../.." title="Josh Creek's Blog" class="md-nav__button md-logo" aria-label="Josh Creek's Blog" data-md-component="logo">
|
|
|
|
<img src="../../../img/noogler-hat-edited-round.png" alt="logo">
|
|
|
|
</a>
|
|
Josh Creek's Blog
|
|
</label>
|
|
|
|
<div class="md-nav__source">
|
|
<a href="https://github.com/jcreek/jcreek.github.io" title="Go to repository" class="md-source" data-md-component="source">
|
|
<div class="md-source__icon md-icon">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg>
|
|
</div>
|
|
<div class="md-source__repository">
|
|
Spotted an issue?
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../.." class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Home
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Containers & Deploying
|
|
|
|
</span>
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_2">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Containers & Deploying
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../deploying/docker-compose-for-asp-net-core-with-postgres-and-s3-backups/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Docker Compose for ASP.Net Core with Postgres + S3 backups
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../deploying/docker-compose-s3-postgres-backup-and-restore/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Docker Compose for S3 Backup and Restore of PostgreSQL
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../deploying/elasticsearch-and-kibana/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Docker Compose for Elasticsearch and Kibana 7.9
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Development Teams
|
|
|
|
</span>
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_3">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Development Teams
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../dev-team/git/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
The way I recommend using git in a dev team
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../dev-team/readme-files/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
How to write an excellent readme file
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Home Server
|
|
|
|
</span>
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_4">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Home Server
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_1" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_4_1" id="__nav_4_1_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Generative AI
|
|
|
|
</span>
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_1_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_4_1">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Generative AI
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../home-server/generative-ai/ollama/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
How to install Ollama with a ChatGPT-like web UI
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_2" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_4_2" id="__nav_4_2_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
TrueNAS Scale
|
|
|
|
</span>
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_2_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_4_2">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
TrueNAS Scale
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../home-server/truenas-scale/installing-homeassistant-on-truenas-scale/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Installing Home Assistant OS on Truenas Scale
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../../home-server/truenas-scale/mounting-smb-shares-at-boot-on-truenas-scale/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Mounting SMB shares at boot on Truenas Scale
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Web Development
|
|
|
|
</span>
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_5">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Web Development
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../dev-environment-container-vscode/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Setting up remote containers for IAC dev environments in dotnet 6 with postgres and SMTP
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../simple-vue-spa-in-asp-dotnet-core/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Creating a reactive SPA simply within an ASP.Net Core web app with Vue.js
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5_3" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_5_3" id="__nav_5_3_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Dotnet & C#
|
|
|
|
</span>
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_5_3_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_5_3">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Dotnet & C#
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../pattern-matching/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
C# 8 Pattern Matching
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="/web-dev/dotnet-csharp/semantic-kernel-vector-database/index.html" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Semantic Kernel (GPT with C#) - using a vector database to store embeddings
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../jsnlog-asp-net-6/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Adding JSNLog to ASP .Net 6 with Serilog
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5_4" >
|
|
|
|
|
|
<label class="md-nav__link" for="__nav_5_4" id="__nav_5_4_label" tabindex="0">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
Javascript & Typescript
|
|
|
|
</span>
|
|
|
|
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_5_4_label" aria-expanded="false">
|
|
<label class="md-nav__title" for="__nav_5_4">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Javascript & Typescript
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../js/node-js-typescript/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
How to set up a Node.js Typescript project well
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../js/node-js-web-typescript/" class="md-nav__link">
|
|
|
|
|
|
|
|
<span class="md-ellipsis">
|
|
How to set up a Node.js Typescript web project well
|
|
|
|
</span>
|
|
|
|
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="md-content" data-md-component="content">
|
|
<article class="md-content__inner md-typeset">
|
|
|
|
|
|
|
|
<nav class="md-tags" >
|
|
|
|
|
|
|
|
|
|
<span class="md-tag">AI</span>
|
|
|
|
|
|
|
|
|
|
|
|
<span class="md-tag">GPT</span>
|
|
|
|
|
|
|
|
|
|
|
|
<span class="md-tag">SK</span>
|
|
|
|
|
|
|
|
|
|
|
|
<span class="md-tag">c#</span>
|
|
|
|
|
|
|
|
|
|
|
|
<span class="md-tag">dotnet</span>
|
|
|
|
|
|
|
|
|
|
|
|
<span class="md-tag">semantic kernel</span>
|
|
|
|
|
|
|
|
|
|
|
|
<span class="md-tag">web development</span>
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<h1 id="semantic-kernel-gpt-with-c-using-a-vector-database-to-store-embeddings">Semantic Kernel (GPT with C#) - using a vector database to store embeddings</h1>
|
|
<p><em>2023-05-25</em></p>
|
|
<p>At the time of writing there isn't any documentation on using vector databases to store embeddings, so I'm sharing my notes from my time digging around in the semantic kernel code.</p>
|
|
<h2 id="a-brief-explanation">A brief explanation</h2>
|
|
<p>So, what am I even talking about? As the global phenomenon that is Chat GPT has shown, the OpenAI GPT models are capable of making some impressively powerful tools. However, even as an experienced developer, working with LLM AIs is not something I nor, most of my colleagues have experience of. This is where the semantic kernel comes in. It's essentially a wrapper that allows you to use the GPT models in a more familiar way, using C# (or Python). It's a great tool for developers who want to use the power of GPT, but don't want to have to learn how to use it directly. </p>
|
|
<p>There's some excellent resources available covering how you can create a text file that serves as a 'skill' - a set of prompts and responses that the AI can use to generate text - and for using volatile memory to store 'embeddings'. I won't go into those here, but the official Microsoft documentation is a great place to start.</p>
|
|
<p>Embeddings are essentially a way of storing a representation of a piece of text. The semantic kernel uses them to store the prompts and responses that you provide, and then uses them to find the most similar text to a given input. This is how it can generate responses to a given input. When you start trying to add context to a skill, you'll quickly find that the amount of prompts and responses you need to add to cover all the possible inputs is huge. This is where a vector database comes in.</p>
|
|
<p>A vector database is different to a relational or document database. I won't explain the differences here, but they can be used to store data in a way that best enables you to programmatically find the most similar data to a given input. In this case, I'm going to store contextual data that I want my skill to use to generate responses. I'll then use the vector database to provide this data to my skill, in a way that will not exceed the token limits of the GPT model.</p>
|
|
<h2 id="setting-up-a-console-app-to-make-use-of-semantic-kernel">Setting up a console app to make use of semantic kernel</h2>
|
|
<p>There's already excellent documentation on how to do this, so I won't go into it here. I'll assume you've already got a console app set up and ready to go, and that you've added the semantic kernel NuGet package using <code>dotnet add package Microsoft.SemanticKernel --version 0.14.547.1-preview</code> - take a look at the <a href="https://docs.microsoft.com/en-us/semantic-kernel/get-started">official documentation</a> if you haven't.</p>
|
|
<h2 id="setting-up-the-vector-database-to-store-embeddings">Setting up the vector database to store embeddings</h2>
|
|
<p>This is remarkably easy thanks to some NuGet packages that have been provided alongside the semantic kernel. I'm going to use the SQLite database, but there are other, more robust options available.</p>
|
|
<p>You'll need to install the relevant NuGet package, which in our case is the SQLite one - <code>dotnet add package Microsoft.SemanticKernel.Connectors.Memory.Sqlite --version 0.14.547.1-preview</code> will do that for you.</p>
|
|
<p>First, set up a new kernel, enabling embeddings, and connecting to your SQLite database. You'll need to provide a connection string, which is just a path to the database file. I've used a relative path here, but you can use an absolute path if you prefer. I've left in a commented out line to demonstrate what setting this up with a standard in-memory database would look like. </p>
|
|
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-1"> 1</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-2"> 2</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-3"> 3</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-4"> 4</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-5"> 5</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-6"> 6</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-7"> 7</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-8"> 8</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-9"> 9</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-10">10</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-11">11</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-12">12</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-13">13</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-14">14</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-15">15</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-16">16</a></span>
|
|
<span class="normal"><a href="#__codelineno-0-17">17</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="kt">var</span><span class="w"> </span><span class="n">kernel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">KernelBuilder</span><span class="p">()</span>
|
|
<a id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="w"> </span><span class="p">.</span><span class="n">Configure</span><span class="p">(</span><span class="n">c</span><span class="w"> </span><span class="o">=></span>
|
|
<a id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="w"> </span><span class="p">{</span>
|
|
<a id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">useAzureOpenAI</span><span class="p">)</span>
|
|
<a id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="w"> </span><span class="p">{</span>
|
|
<a id="__codelineno-0-6" name="__codelineno-0-6"></a><span class="w"> </span><span class="n">c</span><span class="p">.</span><span class="n">AddAzureTextEmbeddingGenerationService</span><span class="p">(</span><span class="s">"text-embedding-ada-002"</span><span class="p">,</span><span class="w"> </span><span class="n">azureEndpoint</span><span class="p">,</span><span class="w"> </span><span class="n">apiKey</span><span class="p">);</span>
|
|
<a id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="w"> </span><span class="n">c</span><span class="p">.</span><span class="n">AddAzureTextCompletionService</span><span class="p">(</span><span class="n">model</span><span class="p">,</span><span class="w"> </span><span class="n">azureEndpoint</span><span class="p">,</span><span class="w"> </span><span class="n">apiKey</span><span class="p">);</span>
|
|
<a id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="w"> </span><span class="p">}</span>
|
|
<a id="__codelineno-0-9" name="__codelineno-0-9"></a><span class="w"> </span><span class="k">else</span>
|
|
<a id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="w"> </span><span class="p">{</span>
|
|
<a id="__codelineno-0-11" name="__codelineno-0-11"></a><span class="w"> </span><span class="n">c</span><span class="p">.</span><span class="n">AddOpenAITextEmbeddingGenerationService</span><span class="p">(</span><span class="s">"text-embedding-ada-002"</span><span class="p">,</span><span class="w"> </span><span class="n">apiKey</span><span class="p">);</span>
|
|
<a id="__codelineno-0-12" name="__codelineno-0-12"></a><span class="w"> </span><span class="n">c</span><span class="p">.</span><span class="n">AddOpenAITextCompletionService</span><span class="p">(</span><span class="n">model</span><span class="p">,</span><span class="w"> </span><span class="n">apiKey</span><span class="p">,</span><span class="w"> </span><span class="n">orgId</span><span class="p">);</span>
|
|
<a id="__codelineno-0-13" name="__codelineno-0-13"></a><span class="w"> </span><span class="p">}</span>
|
|
<a id="__codelineno-0-14" name="__codelineno-0-14"></a><span class="w"> </span><span class="p">})</span>
|
|
<a id="__codelineno-0-15" name="__codelineno-0-15"></a><span class="w"> </span><span class="p">.</span><span class="n">WithMemoryStorage</span><span class="p">(</span><span class="k">await</span><span class="w"> </span><span class="n">SqliteMemoryStore</span><span class="p">.</span><span class="n">ConnectAsync</span><span class="p">(</span><span class="s">"memory.sqlite"</span><span class="p">))</span>
|
|
<a id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="w"> </span><span class="c1">// .WithMemoryStorage(new VolatileMemoryStore())</span>
|
|
<a id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="w"> </span><span class="p">.</span><span class="n">Build</span><span class="p">();</span>
|
|
</code></pre></div></td></tr></table></div>
|
|
<p>Next I'm going to set up a dictionary of GitHub URLs and their descriptions. I'm going to use these to demonstrate how to store embeddings in the vector database. I've used a dictionary here, but you could use any collection of key-value pairs.</p>
|
|
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-1-1"> 1</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-2"> 2</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-3"> 3</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-4"> 4</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-5"> 5</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-6"> 6</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-7"> 7</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-8"> 8</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-9"> 9</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-10">10</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-11">11</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-12">12</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-13">13</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-14">14</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-15">15</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-16">16</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-17">17</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-18">18</a></span>
|
|
<span class="normal"><a href="#__codelineno-1-19">19</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="k">const</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="n">memoryCollectionName</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"SKGitHub"</span><span class="p">;</span>
|
|
<a id="__codelineno-1-2" name="__codelineno-1-2"></a>
|
|
<a id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="kt">var</span><span class="w"> </span><span class="n">githubFiles</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Dictionary</span><span class="o"><</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="o">></span><span class="p">()</span>
|
|
<a id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="p">{</span>
|
|
<a id="__codelineno-1-5" name="__codelineno-1-5"></a><span class="w"> </span><span class="na">["https://github.com/microsoft/semantic-kernel/blob/main/README.md"]</span>
|
|
<a id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"README: Installation, getting started, and how to contribute"</span><span class="p">,</span>
|
|
<a id="__codelineno-1-7" name="__codelineno-1-7"></a><span class="w"> </span><span class="na">["https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb"]</span>
|
|
<a id="__codelineno-1-8" name="__codelineno-1-8"></a><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Jupyter notebook describing how to pass prompts from a file to a semantic skill or function"</span><span class="p">,</span>
|
|
<a id="__codelineno-1-9" name="__codelineno-1-9"></a><span class="w"> </span><span class="na">["https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/00-getting-started.ipynb"]</span>
|
|
<a id="__codelineno-1-10" name="__codelineno-1-10"></a><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Jupyter notebook describing how to get started with the Semantic Kernel"</span><span class="p">,</span>
|
|
<a id="__codelineno-1-11" name="__codelineno-1-11"></a><span class="w"> </span><span class="na">["https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT"]</span>
|
|
<a id="__codelineno-1-12" name="__codelineno-1-12"></a><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Sample demonstrating how to create a chat skill interfacing with ChatGPT"</span><span class="p">,</span>
|
|
<a id="__codelineno-1-13" name="__codelineno-1-13"></a><span class="w"> </span><span class="na">["https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel/Memory/Volatile/VolatileMemoryStore.cs"]</span>
|
|
<a id="__codelineno-1-14" name="__codelineno-1-14"></a><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"C# class that defines a volatile embedding store"</span><span class="p">,</span>
|
|
<a id="__codelineno-1-15" name="__codelineno-1-15"></a><span class="w"> </span><span class="na">["https://github.com/microsoft/semantic-kernel/tree/main/samples/dotnet/KernelHttpServer/README.md"]</span>
|
|
<a id="__codelineno-1-16" name="__codelineno-1-16"></a><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4"</span><span class="p">,</span>
|
|
<a id="__codelineno-1-17" name="__codelineno-1-17"></a><span class="w"> </span><span class="na">["https://github.com/microsoft/semantic-kernel/tree/main/samples/apps/chat-summary-webapp-react/README.md"]</span>
|
|
<a id="__codelineno-1-18" name="__codelineno-1-18"></a><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"README: README associated with a sample starter react-based chat summary webapp"</span><span class="p">,</span>
|
|
<a id="__codelineno-1-19" name="__codelineno-1-19"></a><span class="p">};</span>
|
|
</code></pre></div></td></tr></table></div>
|
|
<p>Obviously these have to be stored in the vector database before they can be used. I'm going to use the <code>SaveReferenceAsync</code> method to do this. This method takes a collection name, a description, the text to be stored, and an external ID and source name. The external ID is a unique identifier for the piece of text, and the source name is a string that identifies the source of the text. I'm using the GitHub URL as the external ID, and the source name as 'GitHub'. You can use whatever you like here, but it's important that the external ID is unique. I'm also going to print out a message for each URL that's saved, so I can see what's happening.</p>
|
|
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-2-1"> 1</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-2"> 2</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-3"> 3</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-4"> 4</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-5"> 5</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-6"> 6</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-7"> 7</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-8"> 8</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-9"> 9</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-10">10</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-11">11</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-12">12</a></span>
|
|
<span class="normal"><a href="#__codelineno-2-13">13</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1"></a><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">"Adding some GitHub file URLs and their descriptions to a volatile Semantic Memory."</span><span class="p">);</span>
|
|
<a id="__codelineno-2-2" name="__codelineno-2-2"></a><span class="kt">var</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
|
|
<a id="__codelineno-2-3" name="__codelineno-2-3"></a><span class="k">foreach</span><span class="w"> </span><span class="p">(</span><span class="kt">var</span><span class="w"> </span><span class="n">entry</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">githubFiles</span><span class="p">)</span>
|
|
<a id="__codelineno-2-4" name="__codelineno-2-4"></a><span class="p">{</span>
|
|
<a id="__codelineno-2-5" name="__codelineno-2-5"></a><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="n">kernel</span><span class="p">.</span><span class="n">Memory</span><span class="p">.</span><span class="n">SaveReferenceAsync</span><span class="p">(</span>
|
|
<a id="__codelineno-2-6" name="__codelineno-2-6"></a><span class="w"> </span><span class="n">collection</span><span class="p">:</span><span class="w"> </span><span class="n">memoryCollectionName</span><span class="p">,</span>
|
|
<a id="__codelineno-2-7" name="__codelineno-2-7"></a><span class="w"> </span><span class="n">description</span><span class="p">:</span><span class="w"> </span><span class="n">entry</span><span class="p">.</span><span class="n">Value</span><span class="p">,</span>
|
|
<a id="__codelineno-2-8" name="__codelineno-2-8"></a><span class="w"> </span><span class="n">text</span><span class="p">:</span><span class="w"> </span><span class="n">entry</span><span class="p">.</span><span class="n">Value</span><span class="p">,</span>
|
|
<a id="__codelineno-2-9" name="__codelineno-2-9"></a><span class="w"> </span><span class="n">externalId</span><span class="p">:</span><span class="w"> </span><span class="n">entry</span><span class="p">.</span><span class="n">Key</span><span class="p">,</span>
|
|
<a id="__codelineno-2-10" name="__codelineno-2-10"></a><span class="w"> </span><span class="n">externalSourceName</span><span class="p">:</span><span class="w"> </span><span class="s">"GitHub"</span>
|
|
<a id="__codelineno-2-11" name="__codelineno-2-11"></a><span class="w"> </span><span class="p">);</span>
|
|
<a id="__codelineno-2-12" name="__codelineno-2-12"></a><span class="w"> </span><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">$" URL {++i} saved"</span><span class="p">);</span>
|
|
<a id="__codelineno-2-13" name="__codelineno-2-13"></a><span class="p">}</span>
|
|
</code></pre></div></td></tr></table></div>
|
|
<h2 id="querying-the-vector-database">Querying the vector database</h2>
|
|
<p>Now that we've stored some data in the vector database, we can query it. I'm going to use the <code>SearchAsync</code> method to do this. This method takes a collection name, a query string, and a limit and minimum relevance score. The limit is the maximum number of results to return, and the minimum relevance score is the minimum relevance score that a result must have to be returned. I'm going to set the limit to 5, and the minimum relevance score to 0.77. I'm also going to print out the query string, so I can see what's happening.</p>
|
|
<p>The reason I want to limit the number of results is that the vector database will return all results that have a relevance score above the minimum relevance score. If I didn't limit the number of results, I'd get all the results that have a relevance score above 0.77, which would be all of them. It is critical to ensure that we stay below the token limit for the OpenAI API for the 'ask' that we're going to perform, and finding only a limited set of the most relevant data to use for the 'ask' is a good way to do this.</p>
|
|
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-3-1"> 1</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-2"> 2</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-3"> 3</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-4"> 4</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-5"> 5</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-6"> 6</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-7"> 7</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-8"> 8</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-9"> 9</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-10">10</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-11">11</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-12">12</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-13">13</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-14">14</a></span>
|
|
<span class="normal"><a href="#__codelineno-3-15">15</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1"></a><span class="kt">string</span><span class="w"> </span><span class="n">ask</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"I love Jupyter notebooks, how should I get started?"</span><span class="p">;</span>
|
|
<a id="__codelineno-3-2" name="__codelineno-3-2"></a><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">"===========================\n"</span><span class="w"> </span><span class="o">+</span>
|
|
<a id="__codelineno-3-3" name="__codelineno-3-3"></a><span class="w"> </span><span class="s">"Query: "</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">ask</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">"\n"</span><span class="p">);</span>
|
|
<a id="__codelineno-3-4" name="__codelineno-3-4"></a>
|
|
<a id="__codelineno-3-5" name="__codelineno-3-5"></a><span class="kt">var</span><span class="w"> </span><span class="n">memories</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">kernel</span><span class="p">.</span><span class="n">Memory</span><span class="p">.</span><span class="n">SearchAsync</span><span class="p">(</span><span class="n">memoryCollectionName</span><span class="p">,</span><span class="w"> </span><span class="n">ask</span><span class="p">,</span><span class="w"> </span><span class="n">limit</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w"> </span><span class="n">minRelevanceScore</span><span class="p">:</span><span class="w"> </span><span class="mf">0.77</span><span class="p">);</span>
|
|
<a id="__codelineno-3-6" name="__codelineno-3-6"></a>
|
|
<a id="__codelineno-3-7" name="__codelineno-3-7"></a><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
|
|
<a id="__codelineno-3-8" name="__codelineno-3-8"></a><span class="k">await</span><span class="w"> </span><span class="nf">foreach</span><span class="w"> </span><span class="p">(</span><span class="n">MemoryQueryResult</span><span class="w"> </span><span class="n">memory</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">memories</span><span class="p">)</span>
|
|
<a id="__codelineno-3-9" name="__codelineno-3-9"></a><span class="p">{</span>
|
|
<a id="__codelineno-3-10" name="__codelineno-3-10"></a><span class="w"> </span><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">$"Result {++i}:"</span><span class="p">);</span>
|
|
<a id="__codelineno-3-11" name="__codelineno-3-11"></a><span class="w"> </span><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">" URL: : "</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">memory</span><span class="p">.</span><span class="n">Metadata</span><span class="p">.</span><span class="n">Id</span><span class="p">);</span>
|
|
<a id="__codelineno-3-12" name="__codelineno-3-12"></a><span class="w"> </span><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">" Title : "</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">memory</span><span class="p">.</span><span class="n">Metadata</span><span class="p">.</span><span class="n">Description</span><span class="p">);</span>
|
|
<a id="__codelineno-3-13" name="__codelineno-3-13"></a><span class="w"> </span><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">" Relevance: "</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">memory</span><span class="p">.</span><span class="n">Relevance</span><span class="p">);</span>
|
|
<a id="__codelineno-3-14" name="__codelineno-3-14"></a><span class="w"> </span><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">();</span>
|
|
<a id="__codelineno-3-15" name="__codelineno-3-15"></a><span class="p">}</span>
|
|
</code></pre></div></td></tr></table></div>
|
|
<p>Running this ask gives the following results:</p>
|
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a>===========================
|
|
<a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a>Query: I love Jupyter notebooks, how should I get started?
|
|
<a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a>
|
|
<a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a>Result 1:
|
|
<a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a> URL: : https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/00-getting-started.ipynb
|
|
<a id="__codelineno-4-6" name="__codelineno-4-6" href="#__codelineno-4-6"></a> Title : Jupyter notebook describing how to get started with the Semantic Kernel
|
|
<a id="__codelineno-4-7" name="__codelineno-4-7" href="#__codelineno-4-7"></a> Relevance: 0.8678345730903347
|
|
<a id="__codelineno-4-8" name="__codelineno-4-8" href="#__codelineno-4-8"></a>
|
|
<a id="__codelineno-4-9" name="__codelineno-4-9" href="#__codelineno-4-9"></a>Result 2:
|
|
<a id="__codelineno-4-10" name="__codelineno-4-10" href="#__codelineno-4-10"></a> URL: : https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb
|
|
<a id="__codelineno-4-11" name="__codelineno-4-11" href="#__codelineno-4-11"></a> Title : Jupyter notebook describing how to pass prompts from a file to a semantic skill or function
|
|
<a id="__codelineno-4-12" name="__codelineno-4-12" href="#__codelineno-4-12"></a> Relevance: 0.8163350291107238
|
|
<a id="__codelineno-4-13" name="__codelineno-4-13" href="#__codelineno-4-13"></a>
|
|
<a id="__codelineno-4-14" name="__codelineno-4-14" href="#__codelineno-4-14"></a>Result 3:
|
|
<a id="__codelineno-4-15" name="__codelineno-4-15" href="#__codelineno-4-15"></a> URL: : https://github.com/microsoft/semantic-kernel/blob/main/README.md
|
|
<a id="__codelineno-4-16" name="__codelineno-4-16" href="#__codelineno-4-16"></a> Title : README: Installation, getting started, and how to contribute
|
|
<a id="__codelineno-4-17" name="__codelineno-4-17" href="#__codelineno-4-17"></a> Relevance: 0.8084409058091631
|
|
</code></pre></div>
|
|
<p>It has found the three GitHub URLs that are most relevant to the query string, and returned them in order of relevance. The first result is the Jupyter notebook that describes how to get started with the Semantic Kernel, which is exactly what I was looking for.</p>
|
|
<h2 id="conclusion">Conclusion</h2>
|
|
<p>This is only an incredibly basic example, but hopefully it's enough to get you kick-started with the Semantic Kernel and using a vector database to store embeddings. </p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</article>
|
|
</div>
|
|
|
|
|
|
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
|
|
</div>
|
|
|
|
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
|
|
Back to top
|
|
</button>
|
|
|
|
</main>
|
|
|
|
<footer class="md-footer">
|
|
|
|
<div class="md-footer-meta md-typeset">
|
|
<div class="md-footer-meta__inner md-grid">
|
|
<div class="md-copyright">
|
|
|
|
<div class="md-copyright__highlight">
|
|
Copyright © 2011 - 2025 Josh Creek
|
|
</div>
|
|
|
|
|
|
Made with
|
|
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
|
Material for MkDocs
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<div class="md-social">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<a href="https://github.com/jcreek" target="_blank" rel="noopener" title="github.com" class="md-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<a href="https://twitter.com/jcreek23" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<a href="https://www.linkedin.com/in/jrcreek" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3M135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5m282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9z"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<a href="https://www.instagram.com/scruffy238/" target="_blank" rel="noopener" title="www.instagram.com" class="md-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M224.1 141c-63.6 0-114.9 51.3-114.9 114.9s51.3 114.9 114.9 114.9S339 319.5 339 255.9 287.7 141 224.1 141m0 189.6c-41.1 0-74.7-33.5-74.7-74.7s33.5-74.7 74.7-74.7 74.7 33.5 74.7 74.7-33.6 74.7-74.7 74.7m146.4-194.3c0 14.9-12 26.8-26.8 26.8-14.9 0-26.8-12-26.8-26.8s12-26.8 26.8-26.8 26.8 12 26.8 26.8m76.1 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8M398.8 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1"/></svg>
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
</div>
|
|
<div class="md-dialog" data-md-component="dialog">
|
|
<div class="md-dialog__inner md-typeset"></div>
|
|
</div>
|
|
|
|
|
|
<div class="md-consent" data-md-component="consent" id="__consent" hidden>
|
|
<div class="md-consent__overlay"></div>
|
|
<aside class="md-consent__inner">
|
|
<form class="md-consent__form md-grid md-typeset" name="consent">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<h4>Cookie consent</h4>
|
|
<p>I use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of my documentation and whether users find what they're searching for. With your consent, you're helping me to make my documentation better.</p>
|
|
<input class="md-toggle" type="checkbox" id="__settings" checked>
|
|
<div class="md-consent__settings">
|
|
<ul class="task-list">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="task-list-item">
|
|
<label class="task-list-control">
|
|
<input type="checkbox" name="analytics" checked>
|
|
<span class="task-list-indicator"></span>
|
|
Google Analytics
|
|
</label>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="task-list-item">
|
|
<label class="task-list-control">
|
|
<input type="checkbox" name="github" checked>
|
|
<span class="task-list-indicator"></span>
|
|
GitHub
|
|
</label>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
</div>
|
|
<div class="md-consent__controls">
|
|
|
|
|
|
<button class="md-button md-button--primary">Accept</button>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
</form>
|
|
</aside>
|
|
</div>
|
|
<script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script>
|
|
|
|
|
|
|
|
<script id="__config" type="application/json">{"base": "../../..", "features": ["navigation.instant", "navigation.tracking", "navigation.tabs", "navigation.tabs.sticky", "navigation.sections", "toc.follow", "toc.integrate", "navigation.top", "search.suggest", "search.highlight", "search.share"], "search": "../../../assets/javascripts/workers/search.f8cc74c7.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
|
|
|
|
|
|
<script src="../../../assets/javascripts/bundle.c8b220af.min.js"></script>
|
|
|
|
|
|
</body>
|
|
</html> |