diff --git a/.github/workflows/jekyll-gh-pages.yml b/.github/workflows/jekyll-gh-pages.yml new file mode 100644 index 000000000..30881b562 --- /dev/null +++ b/.github/workflows/jekyll-gh-pages.yml @@ -0,0 +1,51 @@ +# Sample workflow for building and deploying a Jekyll site to GitHub Pages +name: Deploy Jekyll with GitHub Pages dependencies preinstalled + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Build with Jekyll + uses: actions/jekyll-build-pages@v1 + with: + source: ./docs/ + destination: ./_site + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.vscode/settings.json b/.vscode/settings.json index 410950e20..ca9b09296 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,7 +6,7 @@ "[csharp]": { "editor.defaultFormatter": "ms-dotnettools.csharp", "editor.codeActionsOnSave": { - "source.fixAll": true + "source.fixAll": "explicit" } }, "editor.bracketPairColorization.enabled": true, diff --git a/KernelMemory.sln b/KernelMemory.sln index 6a50b0bf6..47798b311 100644 --- a/KernelMemory.sln +++ b/KernelMemory.sln @@ -24,9 +24,31 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "clients", "clients", "{371B EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{7BA7F1B2-19E2-46EB-B000-513EE2F65769}" ProjectSection(SolutionItems) = preProject - docs\FAQ.md = docs\FAQ.md - docs\SECURITY_FILTERS.md = docs\SECURITY_FILTERS.md + docs\_config.local.yml = docs\_config.local.yml + docs\_config.yml = docs\_config.yml + docs\csharp.png = docs\csharp.png + docs\service.md = docs\service.md + docs\serverless.md = docs\serverless.md + docs\security.md = docs\security.md + docs\run.cmd = docs\run.cmd + docs\quickstart.md = docs\quickstart.md + docs\quickstart-swagger.png = docs\quickstart-swagger.png + docs\quickstart-dotnet-run.png = docs\quickstart-dotnet-run.png + docs\python.png = docs\python.png + docs\packages.md = docs\packages.md docs\network.png = docs\network.png + docs\logo.png = docs\logo.png + docs\java.png = docs\java.png + docs\index.md = docs\index.md + docs\how-tos.md = docs\how-tos.md + docs\Gemfile.lock = docs\Gemfile.lock + docs\Gemfile = docs\Gemfile + docs\features.md = docs\features.md + docs\favicon.png = docs\favicon.png + docs\FAQ.md = docs\FAQ.md + docs\extensions.md = docs\extensions.md + docs\concepts.md = docs\concepts.md + docs\404.html = docs\404.html EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{0A43C65C-6007-4BB4-B3FE-8D439FC91841}" diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..74e6925c1 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,6 @@ +_site +.sass-cache +.jekyll-cache +.jekyll-metadata +vendor +_setup.txt diff --git a/docs/404.html b/docs/404.html new file mode 100644 index 000000000..086a5c9ea --- /dev/null +++ b/docs/404.html @@ -0,0 +1,25 @@ +--- +permalink: /404.html +layout: default +--- + + + +
+

404

+ +

Page not found :(

+

The requested page could not be found.

+
diff --git a/docs/FAQ.md b/docs/FAQ.md index 646906e2f..800ac8f60 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -1,3 +1,10 @@ +--- +nav_order: 90 +has_children: false +title: F.A.Q. +permalink: /faq +layout: default +--- # Kernel Memory F.A.Q. ### How do I integrate Kernel Memory with my application? diff --git a/docs/Gemfile b/docs/Gemfile new file mode 100644 index 000000000..fe3e3c2a7 --- /dev/null +++ b/docs/Gemfile @@ -0,0 +1,48 @@ +source "https://rubygems.org" +# Hello! This is where you manage which Jekyll version is used to run. +# When you want to use a different version, change it below, save the +# file and run `bundle install`. Run Jekyll with `bundle exec`, like so: +# +# bundle exec jekyll serve +# +# This will help ensure the proper Jekyll version is running. +# Happy Jekylling! +gem "jekyll", "~> 4.3.3" +# This is the default theme for new Jekyll sites. You may change this to anything you like. +gem "minima", "~> 2.5" +# If you want to use GitHub Pages, remove the "gem "jekyll"" above and +# uncomment the line below. To upgrade, run `bundle update github-pages`. +# gem "github-pages", group: :jekyll_plugins +# If you have any plugins, put them here! +group :jekyll_plugins do + gem "jekyll-feed", "~> 0.12" +end + +# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem +# and associated library. +platforms :mingw, :x64_mingw, :mswin, :jruby do + gem "tzinfo", ">= 1", "< 3" + gem "tzinfo-data" +end + +# Performance-booster for watching directories on Windows +gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin] + +# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem +# do not have a Java counterpart. +gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby] + +gem "just-the-docs", "~> 0.7.0" + +# ==================================== +# source "https://rubygems.org" +# gemspec + +# gem "jekyll", "~> 4.3.3" +# gem "just-the-docs", "~> 0.7.0" + +# gem "jekyll-github-metadata", ">= 2.15" + +# gem "jekyll-include-cache", group: :jekyll_plugins + +# gem "html-proofer", "~> 5.0", :group => :development diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock new file mode 100644 index 000000000..7426d2da4 --- /dev/null +++ b/docs/Gemfile.lock @@ -0,0 +1,98 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.8.6) + public_suffix (>= 2.0.2, < 6.0) + colorator (1.1.0) + concurrent-ruby (1.2.2) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + eventmachine (1.2.7) + ffi (1.16.3) + forwardable-extended (2.6.0) + google-protobuf (3.25.1) + google-protobuf (3.25.1-x86_64-darwin) + http_parser.rb (0.8.0) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + jekyll (4.3.3) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 1.0) + jekyll-sass-converter (>= 2.0, < 4.0) + jekyll-watch (~> 2.0) + kramdown (~> 2.3, >= 2.3.1) + kramdown-parser-gfm (~> 1.0) + liquid (~> 4.0) + mercenary (>= 0.3.6, < 0.5) + pathutil (~> 0.9) + rouge (>= 3.0, < 5.0) + safe_yaml (~> 1.0) + terminal-table (>= 1.8, < 4.0) + webrick (~> 1.7) + jekyll-feed (0.17.0) + jekyll (>= 3.7, < 5.0) + jekyll-include-cache (0.2.1) + jekyll (>= 3.7, < 5.0) + jekyll-sass-converter (3.0.0) + sass-embedded (~> 1.54) + jekyll-seo-tag (2.8.0) + jekyll (>= 3.8, < 5.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + just-the-docs (0.7.0) + jekyll (>= 3.8.5) + jekyll-include-cache + jekyll-seo-tag (>= 2.0) + rake (>= 12.3.1) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.4) + listen (3.8.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.4.0) + minima (2.5.1) + jekyll (>= 3.5, < 5.0) + jekyll-feed (~> 0.9) + jekyll-seo-tag (~> 2.1) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (5.0.4) + rake (13.1.0) + rb-fsevent (0.11.2) + rb-inotify (0.10.1) + ffi (~> 1.0) + rexml (3.2.6) + rouge (4.2.0) + safe_yaml (1.0.5) + sass-embedded (1.69.6) + google-protobuf (~> 3.25) + rake (>= 13.0.0) + sass-embedded (1.69.6-x86_64-darwin) + google-protobuf (~> 3.25) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + unicode-display_width (2.5.0) + webrick (1.8.1) + +PLATFORMS + ruby + x86_64-darwin-23 + +DEPENDENCIES + http_parser.rb (~> 0.6.0) + jekyll (~> 4.3.3) + jekyll-feed (~> 0.12) + just-the-docs (~> 0.7.0) + minima (~> 2.5) + tzinfo (>= 1, < 3) + tzinfo-data + wdm (~> 0.1.1) + +BUNDLED WITH + 2.5.3 diff --git a/docs/_config.local.yml b/docs/_config.local.yml new file mode 100644 index 000000000..5d454a981 --- /dev/null +++ b/docs/_config.local.yml @@ -0,0 +1,82 @@ +# Config for local Jekyll tests +theme: just-the-docs + +# ================================================== +# == everything below is the same as _config.yaml == +# ================================================== + +title: Kernel Memory +description: >- + Index and query any data using LLM and natural language, tracking sources and + showing citations. Kernel Memory (KM) is a multi-modal AI Service specialized + in the efficient indexing of datasets through custom continuous data hybrid + pipelines, with support for Retrieval Augmented Generation (RAG), synthetic + memory, prompt engineering, and custom semantic memory processing. +baseurl: "/kernel-memory" +url: "" + +favicon_ico: "/favicon.png" +enable_copy_code_button: true +heading_anchors: true +color_scheme: custom + +callouts: + highlight: + color: yellow + console: + color: green + important: + title: Important + color: blue + new: + title: New + color: green + note: + title: Note + color: purple + warning: + title: Warning + color: red + +nav_external_links: + - title: KM on GitHub + url: https://github.com/microsoft/kernel-memory + - title: KM on Discord + url: https://aka.ms/KMDiscord + +aux_links: + "GitHub": + - "https://github.com/microsoft/kernel-memory" + "Discord": + - "https://aka.ms/KMDiscord" + +back_to_top: false +back_to_top_text: "Back to top" + +gh_edit_link: true +gh_edit_link_text: "Edit this page" +gh_edit_repository: "https://github.com/microsoft/kernel-memory" +gh_edit_branch: "main" +gh_edit_source: docs +gh_edit_view_mode: "tree" + +search_enabled: true +search: + # Split pages into sections that can be searched individually # Supports 1 - 6, default: 6 + heading_level: 6 + # Maximum amount of previews per search result # Default: 3 + previews: 3 + # Maximum amount of words to display before a matched word in the preview # Default: 5 + preview_words_before: 6 + # Maximum amount of words to display after a matched word in the preview # Default: 10 + preview_words_after: 10 + # Set the search token separator # Default: /[\s\-/]+/ # Example: enable support for hyphenated search words + tokenizer_separator: /[\s/]+/ + # Display the relative url in search results # Supports true (default) or false + rel_url: false + # Enable or disable the search button that appears in the bottom right corner of every page # Supports true or false (default) + button: true + +mermaid: + # See https://cdn.jsdelivr.net/npm/mermaid/ + version: "10.6.1" diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 000000000..48fc73f71 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,82 @@ +# Config for GitHub Pages +remote_theme: just-the-docs/just-the-docs@v0.7.0 + +# ======================================================== +# == everything below is the same as _config.local.yaml == +# ======================================================== + +title: Kernel Memory +description: >- + Index and query any data using LLM and natural language, tracking sources and + showing citations. Kernel Memory (KM) is a multi-modal AI Service specialized + in the efficient indexing of datasets through custom continuous data hybrid + pipelines, with support for Retrieval Augmented Generation (RAG), synthetic + memory, prompt engineering, and custom semantic memory processing. +baseurl: "/kernel-memory" +url: "" + +favicon_ico: "/favicon.png" +enable_copy_code_button: true +heading_anchors: true +color_scheme: custom + +callouts: + highlight: + color: yellow + console: + color: green + important: + title: Important + color: blue + new: + title: New + color: green + note: + title: Note + color: purple + warning: + title: Warning + color: red + +nav_external_links: + - title: KM on GitHub + url: https://github.com/microsoft/kernel-memory + - title: KM on Discord + url: https://aka.ms/KMDiscord + +aux_links: + "GitHub": + - "https://github.com/microsoft/kernel-memory" + "Discord": + - "https://aka.ms/KMDiscord" + +back_to_top: false +back_to_top_text: "Back to top" + +gh_edit_link: true +gh_edit_link_text: "Edit this page" +gh_edit_repository: "https://github.com/microsoft/kernel-memory" +gh_edit_branch: "main" +gh_edit_source: docs +gh_edit_view_mode: "tree" + +search_enabled: true +search: + # Split pages into sections that can be searched individually # Supports 1 - 6, default: 6 + heading_level: 6 + # Maximum amount of previews per search result # Default: 3 + previews: 3 + # Maximum amount of words to display before a matched word in the preview # Default: 5 + preview_words_before: 6 + # Maximum amount of words to display after a matched word in the preview # Default: 10 + preview_words_after: 10 + # Set the search token separator # Default: /[\s\-/]+/ # Example: enable support for hyphenated search words + tokenizer_separator: /[\s/]+/ + # Display the relative url in search results # Supports true (default) or false + rel_url: false + # Enable or disable the search button that appears in the bottom right corner of every page # Supports true or false (default) + button: true + +mermaid: + # See https://cdn.jsdelivr.net/npm/mermaid/ + version: "10.6.1" diff --git a/docs/_includes/mermaid_config.js b/docs/_includes/mermaid_config.js new file mode 100644 index 000000000..3dba19874 --- /dev/null +++ b/docs/_includes/mermaid_config.js @@ -0,0 +1,3 @@ +{ + "theme": "forest" +} \ No newline at end of file diff --git a/docs/_includes/nav_footer_custom.html b/docs/_includes/nav_footer_custom.html new file mode 100644 index 000000000..d29ae7d06 --- /dev/null +++ b/docs/_includes/nav_footer_custom.html @@ -0,0 +1 @@ +
 
\ No newline at end of file diff --git a/docs/_sass/color_schemes/custom.scss b/docs/_sass/color_schemes/custom.scss new file mode 100644 index 000000000..57c04152c --- /dev/null +++ b/docs/_sass/color_schemes/custom.scss @@ -0,0 +1,6 @@ +@import "./color_schemes/light"; + +// $link-color: $purple-100; +$link-color: $blue-100; +// $link-color: $green-200; +// $link-color: $red-300; diff --git a/docs/concepts.md b/docs/concepts.md new file mode 100644 index 000000000..3012b631a --- /dev/null +++ b/docs/concepts.md @@ -0,0 +1,11 @@ +--- +nav_order: 18 +has_children: true +title: Concepts +permalink: /concepts +layout: default +--- +# Concepts + +{: .highlight } +documentation under development diff --git a/docs/concepts/LLM.md b/docs/concepts/LLM.md new file mode 100644 index 000000000..525874fe1 --- /dev/null +++ b/docs/concepts/LLM.md @@ -0,0 +1,19 @@ +--- +nav_order: 5 +parent: Concepts +title: LLM +permalink: /concepts/llm +layout: default +--- +# LLM + +When setting up Kernel Memory you will have to select one or more AI provider, required +to extract meaning from documents and to generate sentences when asking questions. + +AI providers like Azure offer a wide selection of Large Language Models, such as +GPT-4, Whisper, and Ada-2 that KM leverages internally to analyze data and produce +content. + +Kernel Memory has been designed to work well with GPT-4, GPT 3.5 for text generation, +and Ada-2 for [semantic extraction with embeddings](/concepts/embedding). However, +you can also setup KM to use models like Phi, LLama, Mixtral, Hugging Face, etc. diff --git a/docs/concepts/cosine-similarity.md b/docs/concepts/cosine-similarity.md new file mode 100644 index 000000000..00e6e9df3 --- /dev/null +++ b/docs/concepts/cosine-similarity.md @@ -0,0 +1,68 @@ +--- +nav_order: 7 +parent: Concepts +title: Cosine Similarity +permalink: /concepts/cosine-similarity +layout: default +--- +# Cosine Similarity + +Cosine similarity is a measure of the degree of similarity between two vectors in +a multidimensional space. It is commonly used in artificial intelligence and natural +language processing to compare [embeddings](/concepts/embedding), +which are numerical representations of +words or other objects. + +The cosine similarity between two vectors is calculated by taking the +[dot product](/concepts/dot-product) of the two vectors and dividing it by the product +of their magnitudes. This results in a value between -1 and 1, where 1 indicates +that the two vectors are identical, 0 indicates that they are orthogonal +(i.e., have no correlation), and -1 indicates that they are opposite. + +Cosine similarity is particularly useful when working with high-dimensional data +such as word embeddings because it takes into account both the magnitude and direction +of each vector. This makes it more robust than other measures like +[Euclidean distance](/concepts/euclidean-distance), which only considers the magnitude. + +One common use case for cosine similarity is to find similar words based on their +embeddings. For example, given an embedding for "cat", we can use cosine similarity +to find other words with similar embeddings, such as "kitten" or "feline". This +can be useful for tasks like text classification or sentiment analysis where we +want to group together semantically related words. + +Another application of cosine similarity is in recommendation systems. By representing +items (e.g., movies, products) as vectors, we can use cosine similarity to find +items that are similar to each other or to a particular item of interest. This +allows us to make personalized recommendations based on a user's past behavior +or preferences. + +Overall, cosine similarity is an essential tool for developers working with AI +and embeddings. Its ability to capture both magnitude and direction makes it well +suited for high-dimensional data, and its applications in natural language +processing and recommendation systems make it a valuable tool for building +intelligent applications. + +## Applications + +Some examples about cosine similarity applications. + +1. Recommender Systems: Cosine similarity can be used to find similar items or users + in a recommendation system, based on their embedding vectors. + +2. Document Similarity: Cosine similarity can be used to compare the similarity of + two documents by representing them as embedding vectors and calculating the cosine + similarity between them. + +3. Image Recognition: Cosine similarity can be used to compare the embeddings of + two images, which can help with image recognition tasks. + +4. Natural Language Processing: Cosine similarity can be used to measure the semantic + similarity between two sentences or paragraphs by comparing their embedding vectors. + +5. Clustering: Cosine similarity can be used as a distance metric for clustering + algorithms, helping group similar data points together. + +6. Anomaly Detection: Cosine similarity can be used to identify anomalies in a dataset + by finding data points that have a low cosine similarity with other data points in + the dataset. + diff --git a/docs/concepts/document.md b/docs/concepts/document.md new file mode 100644 index 000000000..15c6fa39f --- /dev/null +++ b/docs/concepts/document.md @@ -0,0 +1,24 @@ +--- +nav_order: 2 +parent: Concepts +title: Document +permalink: /concepts/document +layout: default +--- +# Document + +When uploading information into KM, the data is always packaged as a document. + +A document can consist of a URL to a web page to download, one or more files, +including images, or just a string to be stored. + +Regardless of source and format, a client stores documents. + +When searching and asking questions, you can specify the scope of the search, +e.g. whether to consider an entire index, just a document, or maybe just one of +the files in a document. + +One important aspect to highlight is that documents have one unique ID, that you +can either assign or is automatically assigned by the system. This ID allows to +update the same files, without the risk of duplicating memories, and to delete +the information at any moment. diff --git a/docs/concepts/dot-product.md b/docs/concepts/dot-product.md new file mode 100644 index 000000000..1fabccd62 --- /dev/null +++ b/docs/concepts/dot-product.md @@ -0,0 +1,60 @@ +--- +nav_order: 8 +parent: Concepts +title: Dot Product +permalink: /concepts/dot-product +layout: default +nav_exclude: true +--- +# Dot Product + +Dot product is a mathematical operation that takes two equal-length vectors and +returns a single scalar value. It is also known as the scalar product or inner +product. The dot product of two vectors is calculated by multiplying corresponding +elements of each vector and then summing the results. + +The dot product has many applications in computer science, particularly in artificial +intelligence and machine learning. One common use case for the dot product is to +measure the similarity between two vectors, such as word [embeddings](/concepts/embedding) +or image embeddings. This can be useful when trying to find similar words or images +in a dataset. + +In AI, the dot product can be used to calculate the +[cosine similarity](/concepts/cosine-similarity) between two vectors. Cosine similarity +measures the angle between two vectors, with a smaller angle indicating greater +similarity. This can be useful when working with high-dimensional data where +[Euclidean distance](/concepts/euclidean-distance) may not be an accurate measure of similarity. + +Another application of the dot product in AI is in neural networks, where it can +be used to calculate the weighted sum of inputs to a neuron. This calculation is +essential for forward propagation in neural networks. + +Overall, the dot product is an important operation for software developers working +with AI and embeddings. It provides a simple yet powerful way to measure similarity +between vectors and perform calculations necessary for neural networks. + +## Applications + +Some examples about dot product applications. + +1. Recommender systems: Dot product can be used to measure the similarity between + two vectors representing users or items in a recommender system, helping to identify + which items are most likely to be of interest to a particular user. + +2. Natural Language Processing (NLP): In NLP, dot product can be used to find the + cosine similarity between word embeddings, which is useful for tasks such as + finding synonyms or identifying related words. + +3. Image recognition: Dot product can be used to compare image embeddings, allowing + for more accurate image classification and object detection. + +4. Collaborative filtering: By taking the dot product of user and item embeddings, + collaborative filtering algorithms can predict how much a particular user will + like a particular item. + +5. Clustering: Dot product can be used as a distance metric when clustering data + points in high-dimensional spaces, such as when working with text or image embeddings. + +6. Anomaly detection: By comparing the dot product of an embedding with those of + its nearest neighbors, it is possible to identify data points that are significantly + different from others in their local neighborhood, indicating potential anomalies. diff --git a/docs/concepts/embedding.md b/docs/concepts/embedding.md new file mode 100644 index 000000000..6c9bae381 --- /dev/null +++ b/docs/concepts/embedding.md @@ -0,0 +1,108 @@ +--- +nav_order: 6 +parent: Concepts +title: Embedding +permalink: /concepts/embedding +layout: default +--- +# Embedding + +Although in use for quite some time, embeddings have become more popular since the +launch of GPT-3 thanks to OpenAI LLMs ability to accurately capture the "similarity" +of sentences, even across different languages. + +For instance, using embeddings and [cosine similarity](cosine-similarity), LLMs can infer that +"*the sun is a star*", "*the moon is a satellite*" and "*la Terre est un corps céleste*" +are three sentences with a lot in common, they are "close", while a sentence like +"*fire is a form of energy*" is less similar instead, less _close_. + +Embeddings are a powerful tool for software developers working with artificial intelligence +and natural language processing. They allow computers to understand the meaning of +words in a more sophisticated way, by representing them as high-dimensional vectors +rather than simple strings of characters. Embeddings come in the form of **numerical +vectors**, e.g. a list of **hundreds of floating numbers**, that KM stores in vector DBs +such as Azure AI Search, Qdrant, PostgreSQL, etc. + +Embeddings work by splitting each word in smaller "tokens", and mapping each known token +in a vocabulary to a point in a **high-dimensional space**. +This space and the token vocabulary are designed so that **words with similar meanings are +located near each other**. +This allows algorithms to identify relationships between words, such as synonyms or antonyms, +without needing explicit rules or human supervision. + +One important aspect to consider is that for a given sentence, each LLM produces different +embeddings, that are not compatible across AI models. So for instance, embeddings generated +by OpenAI Ada cannot be compared with those generated by Mistral, Cohere, etc. +Also, LLMs' ability to extract meaning and detect similarity varies a lot from model to model, +and **some embeddings should not be used for text comparison**, to avoid incoherent results. + +Consider looking at [Hugging Face Massive Text Embedding Benchmark (MTEB)](https://huggingface.co/spaces/mteb/leaderboard) +to discover a list of suitable models, e.g. the Clustering table shows how well models +can group similar sentences and paragraphs. We recommend starting with **OpenAI Ada2** ("text-embedding-ada-002"), +currently at position #10 on MTEB, because it's easy to setup and works well across multiple +languages. + +> ![img.png](img.png) +> +> [_MTEB leaderboard, Clustering, January 2024._] + +One popular method for creating embeddings is +Word2Vec [[1]](https://arxiv.org/abs/1301.3781)[[2]](https://arxiv.org/abs/1310.4546), +which uses neural networks to learn the relationships between words from large amounts +of text data. Other methods include GloVe and +[FastText](https://research.facebook.com/downloads/fasttext/). These methods +all have different strengths and weaknesses, but they share the common goal of creating +meaningful representations of words that can be used in machine learning models. + +Embeddings can be used in many different applications, including sentiment analysis, +document classification, and recommendation systems. They are particularly useful +when working with unstructured text data where traditional methods like bag-of-words +models struggle, and are a fundamental part of Kernel Memory. + +Kernel Memory attempts to emulate how the human brain stores and retrieves knowledge about +the world. Embeddings are used to create a semantic map by **representing concepts +or entities as vectors in a high-dimensional space**. This approach allows KM +to learn relationships between concepts and make inferences based on similarity or +distance between vector representations. + +Software developers can use pre-trained embedding model, or train their one with their +own custom datasets. Pre-trained embedding models have been trained on large amounts +of data and can be used out-of-the-box for many applications. Custom embedding models +may be necessary when working with specialized vocabularies or domain-specific language. + +Overall, embeddings are an essential tool for software developers working with AI +and natural language processing. They provide a powerful way to represent and understand +the meaning of words in a computationally efficient manner. + +## Applications + +Some examples about embeddings applications. + +1. Generative Memory: Embeddings can be used to store memory and generate content, + by which a machine can learn to understand the meanings of words and sentences, + can understand the relationships between them and synthesize new content. + +2. Natural Language Processing (NLP): Embeddings can be used to represent words or + sentences in NLP tasks such as sentiment analysis, named entity recognition, and + text classification. + +3. Recommender systems: Embeddings can be used to represent the items in a recommender + system, allowing for more accurate recommendations based on similarity between items. + +4. Image recognition: Embeddings can be used to represent images in computer vision + tasks such as object detection and image classification. + +5. Anomaly detection: Embeddings can be used to represent data points in high-dimensional + datasets, making it easier to identify outliers or anomalous data points. + +6. Graph analysis: Embeddings can be used to represent nodes in a graph, allowing + for more efficient graph analysis and visualization. + +7. Personalization: Embeddings can be used to represent users in personalized recommendation + systems or personalized search engines. + +## Vector Operations used with Embeddings + + - [Cosine Similarity](cosine-similarity) + - [Dot Product](dot-product) + - [Euclidean Distance](euclidean-distance) diff --git a/docs/concepts/euclidean-distance.md b/docs/concepts/euclidean-distance.md new file mode 100644 index 000000000..7c75a62db --- /dev/null +++ b/docs/concepts/euclidean-distance.md @@ -0,0 +1,64 @@ +--- +nav_order: 8 +parent: Concepts +title: Euclidean distance +permalink: /concepts/euclidean-distance +layout: default +nav_exclude: true +--- +# Euclidean distance + +Euclidean distance is a mathematical concept that measures the straight-line distance +between two points in a Euclidean space. It is named after the ancient Greek mathematician +Euclid, who is often referred to as the "father of geometry". The formula for calculating +Euclidean distance is based on the Pythagorean theorem and can be expressed as: + + d = √(x2 - x1)² + (y2 - y1)² + +In higher dimensions, this formula can be generalized to: + + d = √(x2 - x1)² + (y2 - y1)² + ... + (zn - zn-1)² + +Euclidean distance has many applications in computer science and artificial intelligence, +particularly when working with [embeddings](/concepts/embedding). Embeddings are numerical +representations of data that capture the underlying structure and relationships +between different data points. They are commonly used in natural language processing, +computer vision, and recommendation systems. + +When working with embeddings, it is often necessary to measure the similarity or +dissimilarity between different data points. This is where Euclidean distance comes +into play. By calculating the Euclidean distance between two embeddings, we can +determine how similar or dissimilar they are. + +One common use case for Euclidean distance in AI is in clustering algorithms such +as K-means. In this algorithm, data points are grouped together based on their proximity +to one another in a multi-dimensional space. The Euclidean distance between each +point and the centroid of its cluster is used to determine which points belong to +which cluster. + +Another use case for Euclidean distance is in recommendation systems. By calculating +the Euclidean distance between different items' embeddings, we can determine how +similar they are and make recommendations based on that information. + +Overall, Euclidean distance is an essential tool for software developers working +with AI and embeddings. It provides a simple yet powerful way to measure the similarity +or dissimilarity between different data points in a multi-dimensional space. + +## Applications + +Some examples about Euclidean distance applications. + +1. Recommender systems: Euclidean distance can be used to measure the similarity + between items in a recommender system, helping to provide more accurate recommendations. + +2. Image recognition: By calculating the Euclidean distance between image embeddings, + it is possible to identify similar images or detect duplicates. + +3. Natural Language Processing: Measuring the distance between word embeddings can + help with tasks such as semantic similarity and word sense disambiguation. + +4. Clustering: Euclidean distance is commonly used as a metric for clustering algorithms, + allowing them to group similar data points together. + +5. Anomaly detection: By calculating the distance between data points, it is possible + to identify outliers or anomalies in a dataset. diff --git a/docs/concepts/img.png b/docs/concepts/img.png new file mode 100644 index 000000000..8a56bfa78 Binary files /dev/null and b/docs/concepts/img.png differ diff --git a/docs/concepts/indexes.md b/docs/concepts/indexes.md new file mode 100644 index 000000000..076592cae --- /dev/null +++ b/docs/concepts/indexes.md @@ -0,0 +1,22 @@ +--- +nav_order: 1 +parent: Concepts +title: Index +permalink: /concepts/indexes +layout: default +--- +# Index + +Kernel Memory leverages vector storage to save the meaning of the documents +ingested into the service, solutions like Azure AI Search, Qdrant, Elastic Search, +Redis etc. + +Typically, storage solutions offer a maximum capacity for each collection, and +often one needs to clearly separate data over distinct collections for security, +privacy or other important reasons. + +In KM terms, these collection are called "indexes". + +When storing information, when searching, and when asking questions, KM is always +working within the boundaries of one index. Data in one index never leaks into +other indexes. diff --git a/docs/concepts/memory.md b/docs/concepts/memory.md new file mode 100644 index 000000000..6891136e4 --- /dev/null +++ b/docs/concepts/memory.md @@ -0,0 +1,19 @@ +--- +nav_order: 3 +parent: Concepts +title: Memory +permalink: /concepts/memory +layout: default +--- +# Memory + +The term "memory" is used in two separate ways. + +First, KM is meant to offer a Long Term Memory solution for your apps, mimic-ing +the human memory ability to store information. KM offers also an experimental approach +for Short Term Memory, that can be leveraged for LLM prompts. KM can be leveraged +also for Procedural Memory, storing plugins, skills, capabilities. + +Second, when uploading documents, KM extracts many small pieces of information, +potentially thousands. Often these pieces are referred to as "memories" or "memory records". +Very similar to human memories if you like. diff --git a/docs/concepts/tag.md b/docs/concepts/tag.md new file mode 100644 index 000000000..a3a1f5cdf --- /dev/null +++ b/docs/concepts/tag.md @@ -0,0 +1,49 @@ +--- +nav_order: 4 +parent: Concepts +title: Tag +permalink: /concepts/tag +layout: default +--- +# Tag + +Although the human brain can organize information in categories, assign labels, tag +data with multiple keywords, "tagging" doesn't have much to do with human memory per-se, +and is more oriented to flexibility when searching and asking questions. + +Tagging is very similar to the use of embeddings, although there are important differences: + +* Embedding are automatically generated by LLMs, and the embedding vector is very + opaque, pretty much impossible to interpret, or read. +* Tags are defined manually by users, and have specific meaning, easy to interpret, + e.g. one can define a tag named "type" assigning values like "email", "user", "report", etc. +* Embeddings are compared using cosine similarity. +* Tags are compare using exact tag value match, e.g. "type is email". + +Tags offer the ability to apply custom labels to documents, so that for example search +can be scoped to a specific tag or tags. + +Tags can be used to organize memories in collections similarly to indexes, however +indexes offer a stronger separation and tags offer the ability to mutate values +without relocating data. + +Tags are key-value pairs, such as "type:news", "user:u038", "year:2025", and each +tag key can have multiple values, e.g. it's perfectly fine using two tags like +"user:u038" and "user:u944" to assign a memory to two users, or "type:mail" and "type:work" +to specify a record was extracted from an email received at work. + +Some important highlights about Tags and Indexes: + +1. Read and Write operations always work within the boundaries of a single index. +2. One memory cannot be stored in two or more indexes, unless the memory record is + written once in each index, and these records are not linked in any way. +3. A record cannot be moved from one index to another, unless one manually + copies the record and delete the previous one. The new record is a completely + new record, unrelated from the previous. +4. Tags can be modified and can have multiple values. +5. Creating an index can be an expensive operation, and many vector DBs limit + the total number of indexes to only a few. +6. Tags are not created, and there is no limit to the number of tags one can use. + The only limit is the underlying storage availability. +7. Indexes can be listed, one can ask KM to return a list of all the available indexes. +8. Tags cannot be listed. diff --git a/docs/concepts/tokens.md b/docs/concepts/tokens.md new file mode 100644 index 000000000..97507da4e --- /dev/null +++ b/docs/concepts/tokens.md @@ -0,0 +1,11 @@ +--- +nav_order: 9 +parent: Concepts +title: Tokens +permalink: /concepts/tokens +layout: default +--- +# Tokens + +{: .highlight } +documentation under development diff --git a/docs/concepts/vector-search.md b/docs/concepts/vector-search.md new file mode 100644 index 000000000..58bebbe46 --- /dev/null +++ b/docs/concepts/vector-search.md @@ -0,0 +1,11 @@ +--- +nav_order: 8 +parent: Concepts +title: Vector Search +permalink: /concepts/vector-search +layout: default +--- +# Vector Search + +{: .highlight } +documentation under development diff --git a/docs/csharp.png b/docs/csharp.png new file mode 100644 index 000000000..c02ee3fe7 Binary files /dev/null and b/docs/csharp.png differ diff --git a/docs/extensions.md b/docs/extensions.md new file mode 100644 index 000000000..b8d59a79f --- /dev/null +++ b/docs/extensions.md @@ -0,0 +1,11 @@ +--- +nav_order: 14 +has_children: true +title: Extensions +permalink: /extensions +layout: default +--- +# Extensions + +{: .highlight } +documentation under development diff --git a/docs/extensions/AI.md b/docs/extensions/AI.md new file mode 100644 index 000000000..a47e26fcb --- /dev/null +++ b/docs/extensions/AI.md @@ -0,0 +1,12 @@ +--- +nav_order: 2 +has_children: true +parent: Extensions +title: AI +permalink: /extensions/ai +layout: default +--- +# AI / LLM backends + +{: .highlight } +documentation under development diff --git a/docs/extensions/ai/azure-openai.md b/docs/extensions/ai/azure-openai.md new file mode 100644 index 000000000..963ae5ff5 --- /dev/null +++ b/docs/extensions/ai/azure-openai.md @@ -0,0 +1,12 @@ +--- +nav_order: 1 +grand_parent: Extensions +parent: AI +title: Azure OpenAI +permalink: /extensions/ai/azure-openai +layout: default +--- +# Azure OpenAI + +{: .highlight } +documentation under development diff --git a/docs/extensions/ai/llama.md b/docs/extensions/ai/llama.md new file mode 100644 index 000000000..abb419199 --- /dev/null +++ b/docs/extensions/ai/llama.md @@ -0,0 +1,12 @@ +--- +nav_order: 3 +grand_parent: Extensions +parent: AI +title: LLama +permalink: /extensions/ai/llama +layout: default +--- +# LLama + +{: .highlight } +documentation under development diff --git a/docs/extensions/ai/openai.md b/docs/extensions/ai/openai.md new file mode 100644 index 000000000..6591ca854 --- /dev/null +++ b/docs/extensions/ai/openai.md @@ -0,0 +1,12 @@ +--- +nav_order: 2 +grand_parent: Extensions +parent: AI +title: OpenAI +permalink: /extensions/ai/openai +layout: default +--- +# OpenAI + +{: .highlight } +documentation under development diff --git a/docs/extensions/content-storage.md b/docs/extensions/content-storage.md new file mode 100644 index 000000000..f71bedd2b --- /dev/null +++ b/docs/extensions/content-storage.md @@ -0,0 +1,12 @@ +--- +nav_order: 5 +has_children: true +parent: Extensions +title: Content storage +permalink: /extensions/content-storage +layout: default +--- +# Content storage + +{: .highlight } +documentation under development diff --git a/docs/extensions/content-storage/azure-blobs.md b/docs/extensions/content-storage/azure-blobs.md new file mode 100644 index 000000000..15ad31c23 --- /dev/null +++ b/docs/extensions/content-storage/azure-blobs.md @@ -0,0 +1,12 @@ +--- +nav_order: 1 +grand_parent: Extensions +parent: Content storage +title: Azure Blobs +permalink: /extensions/content-storage/azure-blobs +layout: default +--- +# Azure Blobs + +{: .highlight } +documentation under development diff --git a/docs/extensions/content-storage/dev-tools.md b/docs/extensions/content-storage/dev-tools.md new file mode 100644 index 000000000..97f033d81 --- /dev/null +++ b/docs/extensions/content-storage/dev-tools.md @@ -0,0 +1,12 @@ +--- +nav_order: 2 +grand_parent: Extensions +parent: Content storage +title: Simple storage +permalink: /extensions/dev-tools/simple-storage +layout: default +--- +# Simple storage (dev/test tool) + +{: .highlight } +documentation under development diff --git a/docs/extensions/data-format/azure-ai-doc-intel.md b/docs/extensions/data-format/azure-ai-doc-intel.md new file mode 100644 index 000000000..9ffbb3a61 --- /dev/null +++ b/docs/extensions/data-format/azure-ai-doc-intel.md @@ -0,0 +1,12 @@ +--- +nav_order: 1 +grand_parent: Extensions +parent: Data formats +title: Azure AI Document Intelligence +permalink: /extensions/data-formats/azure-ai-doc-intel +layout: default +--- +# Azure AI Document Intelligence + +{: .highlight } +documentation under development diff --git a/docs/extensions/data-formats.md b/docs/extensions/data-formats.md new file mode 100644 index 000000000..9b15ec1a7 --- /dev/null +++ b/docs/extensions/data-formats.md @@ -0,0 +1,20 @@ +--- +nav_order: 3 +has_children: true +parent: Extensions +title: Data formats +permalink: /extensions/data-formats +layout: default +--- +# Data formats + +* MS Word documents +* MS Excel spreadsheets +* MS PowerPoint presentations +* PDF documents +* Web pages +* JPG/PNG/TIFF Images with text via OCR +* MarkDown +* JSON +* Raw plain text +* [..] more coming :-) diff --git a/docs/extensions/memory-db/azure-ai-search.md b/docs/extensions/memory-db/azure-ai-search.md new file mode 100644 index 000000000..552bff66c --- /dev/null +++ b/docs/extensions/memory-db/azure-ai-search.md @@ -0,0 +1,12 @@ +--- +nav_order: 1 +grand_parent: Extensions +parent: Memory DBs +title: Azure AI Search +permalink: /extensions/memory-db/azure-ai-search +layout: default +--- +# Azure AI Search + +{: .highlight } +documentation under development diff --git a/docs/extensions/memory-db/dev-tools.md b/docs/extensions/memory-db/dev-tools.md new file mode 100644 index 000000000..322e63f22 --- /dev/null +++ b/docs/extensions/memory-db/dev-tools.md @@ -0,0 +1,12 @@ +--- +nav_order: 100 +grand_parent: Extensions +parent: Memory DBs +title: Simple memory +permalink: /extensions/dev-tools/simple-memory +layout: default +--- +# Simple memory (dev/test tool) + +{: .highlight } +documentation under development diff --git a/docs/extensions/memory-db/elastic-search.md b/docs/extensions/memory-db/elastic-search.md new file mode 100644 index 000000000..6d796040c --- /dev/null +++ b/docs/extensions/memory-db/elastic-search.md @@ -0,0 +1,12 @@ +--- +nav_order: 4 +grand_parent: Extensions +parent: Memory DBs +title: Elastic Search +permalink: /extensions/memory-db/elastic-search +layout: default +--- +# Elastic Search + +{: .highlight } +documentation under development diff --git a/docs/extensions/memory-db/postgres.md b/docs/extensions/memory-db/postgres.md new file mode 100644 index 000000000..673e30086 --- /dev/null +++ b/docs/extensions/memory-db/postgres.md @@ -0,0 +1,185 @@ +--- +nav_order: 3 +grand_parent: Extensions +parent: Memory DBs +title: PostgreSQL +permalink: /extensions/memory-db/postgres +layout: default +--- + +# Kernel Memory with Postgres + pgvector + +[![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.MemoryDb.Postgres)](https://www.nuget.org/packages/Microsoft.KernelMemory.MemoryDb.Postgres/) + +The [Postgres](https://www.postgresql.org) adapter allows to use Kernel Memory with [Postgres+pgvector](https://github.com/pgvector/pgvector). + +{: .important } +> Your Postgres instance must support vectors. You can run this SQL to see the list of +> extensions **installed** and **enabled**: +> +> SELECT * FROM pg_extension +> +> To enable the extension this should suffice: +> +> CREATE EXTENSION vector +> +> For more information, check: +> * [Using pgvector on Azure PostgreSQL](https://learn.microsoft.com/azure/postgresql/flexible-server/how-to-use-pgvector) +> * [pg_vector extension documentation](https://github.com/pgvector/pgvector). + +To use Postgres with Kernel Memory: + +1. Have a PostgreSQL instance ready, e.g. + checkout [Azure Database for PostgreSQL](https://learn.microsoft.com/en-us/azure/postgresql/) +2. Verify your Postgres instance supports vectors, e.g. run `SELECT * FROM pg_extension` + +[//]: # (2. install the [Microsoft.KernelMemory.Postgres](https://www.nuget.org/packages/Microsoft.KernelMemory.Postgres) package) + +3. Add Postgres connection string to appsettings.json (or appsettings.development.json), for example: + + ```json + { + "KernelMemory": { + "Services": { + "Postgres": { + "ConnectionString": "Host=localhost;Port=5432;Username=myuser;Password=mypassword" + } + } + } + } + ``` +4. Configure KM builder to store memories in Postgres, for example: + ```csharp + // using Microsoft.KernelMemory; + // using Microsoft.KernelMemory.Postgres; + // using Microsoft.Extensions.Configuration; + + var postgresConfig = new PostgresConfig(); + + new ConfigurationBuilder() + .AddJsonFile("appsettings.json") + .AddJsonFile("appsettings.Development.json", optional: true) + .Build() + .BindSection("KernelMemory:Services:Postgres", postgresConfig); + + var memory = new KernelMemoryBuilder() + .WithPostgres(postgresConfig) + .WithAzureOpenAITextGeneration(azureOpenAIConfig) + .WithAzureOpenAITextEmbeddingGeneration(azureOpenAIConfig) + .Build(); + ``` + +## Neighbor search indexes, quality and performance + +The connector does not create IVFFlat or HNSW indexes on Postgres tables, and +uses exact nearest neighbor search. HNSW (_Hierarchical Navigable Small World_) +has been introduced in pgvector 0.5.0 and is not available in some Postgres +instances. + +Depending on your scenario you might want to create these indexes manually, +considering precision and performance trade-offs, or you can customize the +SQL used to create tables via configuration. + +{: .note } +> An **IVFFlat** index divides vectors into lists, and then searches a subset +> of those lists that are closest to the query vector. It has **faster build times** +> and uses **less memory** than HNSW, but has **lower query performance** +> (in terms of speed-recall tradeoff). + +SQL to add IVFFlat: `CREATE INDEX ON %%table_name%% USING ivfflat (embedding vector_cosine_ops) WITH (lists = 1000);` + +{: .note } +> An **HNSW** index creates a multilayer graph. It has **slower build times** +> and uses **more memory** than IVFFlat, but has **better query performance** +> (in terms of speed-recall tradeoff). There’s no training step like IVFFlat, +> so the index can be created without any data in the table. + +SQL to add HNSW: `CREATE INDEX ON %%table_name%% USING hnsw (embedding vector_cosine_ops);` + +See https://github.com/pgvector/pgvector for more information. + +## Memory Indexes and Postgres tables + +The Postgres memory connector will create "memory indexes" automatically, one +DB table for each memory index. + +Table names have a configurable **prefix**, used to filter out other tables that +might be present. The prefix is mandatory, cannot be empty, we suggest using +the default `km-` prefix. Note that the Postgres connector automatically converts +`_` underscores to `-` dashes to have a consistent behavior with other storage +types supported by Kernel Memory. + +Overall we recommend not mixing external tables in the same DB used for +Kernel Memory. + +## Column names and table schema + +The connector uses a default schema with predefined columns and indexes. + +You can change the field names, and if you need to add additional columns +or indexes, you can also customize the `CREATE TABLE` SQL statement. You +can use this approach, for example, to use IVFFlat or HNSW. + +See `PostgresConfig` class for more details. + +Here's an example where `PostgresConfig` is stored in `appsettings.json` and +the table schema is customized, with custom names and additional fields. + +The SQL statement requires two special **placeholders**: + +* `%%table_name%%`: replaced at runtime with the table name +* `%%vector_size%%`: replaced at runtime with the embedding vectors size + +There's a third optional placeholder we recommend using, to better handle +concurrency, e.g. in combination with `pg_advisory_xact_lock` (_exclusive transaction +level advisory locks_): + +* `%%lock_id%%`: replaced at runtime with a number + +Also: + +* `TableNamePrefix` is mandatory string added to all KM tables +* `Columns` is a required map describing where KM will store its data. If you have + additional columns you don't need to list them here, only in SQL statement. +* `CreateTableSql` is your optional custom SQL statement used to create tables. The + column names must match those used in `Columns`. + +```json +{ + "KernelMemory": { + "Services": { + "Postgres": { + + "TableNamePrefix": "memory_", + + "Columns": { + "id": "_pk", + "embedding": "embedding", + "tags": "labels", + "content": "chunk", + "payload": "extras" + }, + + "CreateTableSql": [ + "BEGIN; ", + "SELECT pg_advisory_xact_lock(%%lock_id%%); ", + "CREATE TABLE IF NOT EXISTS %%table_name%% ( ", + " _pk TEXT NOT NULL PRIMARY KEY, ", + " embedding vector(%%vector_size%%), ", + " labels TEXT[] DEFAULT '{}'::TEXT[] NOT NULL, ", + " chunk TEXT DEFAULT '' NOT NULL, ", + " extras JSONB DEFAULT '{}'::JSONB NOT NULL, ", + " my_field1 TEXT DEFAULT '', ", + " _update TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ", + "); ", + "CREATE INDEX ON %%table_name%% USING GIN(labels); ", + "CREATE INDEX ON %%table_name%% USING ivfflat (embedding vector_cosine_ops); ", + "COMMIT; " + ] + + } + } + } +} +``` + diff --git a/docs/extensions/memory-db/qdrant.md b/docs/extensions/memory-db/qdrant.md new file mode 100644 index 000000000..a5ad708dd --- /dev/null +++ b/docs/extensions/memory-db/qdrant.md @@ -0,0 +1,18 @@ +--- +nav_order: 2 +grand_parent: Extensions +parent: Memory DBs +title: Qdrant +permalink: /extensions/memory-db/qdrant +layout: default +--- +# Qdrant + +[![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.MemoryDb.Qdrant)](https://www.nuget.org/packages/Microsoft.KernelMemory.MemoryDb.Qdrant/) + +The [Qdrant](https://qdrant.tech) adapter allowa to use Kernel Memory with Qdrant. + +{: .note } +Qdrant record keys (point IDs) are limited to GUID or INT formats. Kernel Memory uses custom string +keys, adding to each point a custom "id" payload field used to identify records. This approach +requires one extra request during upsert operations, to obtain the point ID required. diff --git a/docs/extensions/memory-db/redis.md b/docs/extensions/memory-db/redis.md new file mode 100644 index 000000000..3df0b226f --- /dev/null +++ b/docs/extensions/memory-db/redis.md @@ -0,0 +1,12 @@ +--- +nav_order: 5 +grand_parent: Extensions +parent: Memory DBs +title: Redis +permalink: /extensions/memory-db/redis +layout: default +--- +# Redis + +{: .highlight } +documentation under development diff --git a/docs/extensions/memory-dbs.md b/docs/extensions/memory-dbs.md new file mode 100644 index 000000000..d8d69ccbf --- /dev/null +++ b/docs/extensions/memory-dbs.md @@ -0,0 +1,12 @@ +--- +nav_order: 1 +has_children: true +parent: Extensions +title: Memory DBs +permalink: /extensions/memory-db +layout: default +--- +# Memory DBs + +{: .highlight } +documentation under development diff --git a/docs/extensions/orchestration.md b/docs/extensions/orchestration.md new file mode 100644 index 000000000..45e7b7f78 --- /dev/null +++ b/docs/extensions/orchestration.md @@ -0,0 +1,12 @@ +--- +nav_order: 4 +has_children: true +parent: Extensions +title: Orchestration +permalink: /extensions/orchestration +layout: default +--- +# Ingestion pipelines orchestration + +{: .highlight } +documentation under development diff --git a/docs/extensions/orchestration/azure-queues.md b/docs/extensions/orchestration/azure-queues.md new file mode 100644 index 000000000..2ebcd0065 --- /dev/null +++ b/docs/extensions/orchestration/azure-queues.md @@ -0,0 +1,12 @@ +--- +nav_order: 1 +grand_parent: Extensions +parent: Orchestration +title: Azure Queues +permalink: /extensions/orchestration/azure-queues +layout: default +--- +# Azure Queues + +{: .highlight } +documentation under development diff --git a/docs/extensions/orchestration/dev-tools.md b/docs/extensions/orchestration/dev-tools.md new file mode 100644 index 000000000..8e6251b16 --- /dev/null +++ b/docs/extensions/orchestration/dev-tools.md @@ -0,0 +1,12 @@ +--- +nav_order: 100 +grand_parent: Extensions +parent: Orchestration +title: Simple queues +permalink: /extensions/dev-tools/simple-queues +layout: default +--- +# Simple queues (dev/test tool) + +{: .highlight } +documentation under development diff --git a/docs/extensions/orchestration/rabbitmq.md b/docs/extensions/orchestration/rabbitmq.md new file mode 100644 index 000000000..728312a0d --- /dev/null +++ b/docs/extensions/orchestration/rabbitmq.md @@ -0,0 +1,12 @@ +--- +nav_order: 2 +grand_parent: Extensions +parent: Orchestration +title: RabbitMQ +permalink: /extensions/orchestration/rabbitMQ +layout: default +--- +# RabbitMQ + +{: .highlight } +documentation under development diff --git a/docs/favicon.png b/docs/favicon.png new file mode 100644 index 000000000..9e70e976f Binary files /dev/null and b/docs/favicon.png differ diff --git a/docs/features.md b/docs/features.md new file mode 100644 index 000000000..38b60c087 --- /dev/null +++ b/docs/features.md @@ -0,0 +1,23 @@ +--- +nav_order: 13 +has_children: true +title: Memory API +permalink: /functions +layout: default +--- +# Memory API + +{: .highlight } +documentation under development + +Memory API: + +* ImportDocumentAsync +* ImportTextAsync +* ImportWebPageAsync +* ListIndexesAsync +* DeleteDocumentAsync +* IsDocumentReadyAsync +* GetDocumentStatusAsync +* **SearchAsync** +* **AskAsync** \ No newline at end of file diff --git a/docs/features/answer-questions.md b/docs/features/answer-questions.md new file mode 100644 index 000000000..3dd71e5e9 --- /dev/null +++ b/docs/features/answer-questions.md @@ -0,0 +1,11 @@ +--- +nav_order: 2 +parent: Memory API +title: Answer questions (RAG) +permalink: /functions/answer-questions +layout: default +--- +# API: answering questions + +{: .highlight } +documentation under development diff --git a/docs/features/search-memory.md b/docs/features/search-memory.md new file mode 100644 index 000000000..4c57a05fd --- /dev/null +++ b/docs/features/search-memory.md @@ -0,0 +1,11 @@ +--- +nav_order: 3 +parent: Memory API +title: Search memory +permalink: /functions/search-memory +layout: default +--- +# API: searching memory + +{: .highlight } +documentation under development diff --git a/docs/features/store-memory.md b/docs/features/store-memory.md new file mode 100644 index 000000000..f1cf2fee2 --- /dev/null +++ b/docs/features/store-memory.md @@ -0,0 +1,11 @@ +--- +nav_order: 1 +parent: Memory API +title: Store memory +permalink: /functions/store-memory +layout: default +--- +# API: storing memories + +{: .highlight } +documentation under development diff --git a/docs/how-to/custom-pipelines.md b/docs/how-to/custom-pipelines.md new file mode 100644 index 000000000..0c8234288 --- /dev/null +++ b/docs/how-to/custom-pipelines.md @@ -0,0 +1,11 @@ +--- +nav_order: 2 +parent: How-to guides +title: Custom pipelines +permalink: /how-to/custom-pipelines +layout: default +--- +# Custom pipelines + +{: .highlight } +documentation under development diff --git a/docs/how-to/custom-prompts.md b/docs/how-to/custom-prompts.md new file mode 100644 index 000000000..719fb5bff --- /dev/null +++ b/docs/how-to/custom-prompts.md @@ -0,0 +1,11 @@ +--- +nav_order: 1 +parent: How-to guides +title: Custom prompts +permalink: /how-to/custom-prompts +layout: default +--- +# Custom prompts + +{: .highlight } +documentation under development diff --git a/docs/how-to/hugging-face.md b/docs/how-to/hugging-face.md new file mode 100644 index 000000000..623a30fbb --- /dev/null +++ b/docs/how-to/hugging-face.md @@ -0,0 +1,11 @@ +--- +nav_order: 3 +parent: How-to guides +title: Hugging Face models +permalink: /how-to/hugging-face +layout: default +--- +# Using Hugging Face models + +{: .highlight } +documentation under development diff --git a/docs/how-tos.md b/docs/how-tos.md new file mode 100644 index 000000000..cf7cabcb5 --- /dev/null +++ b/docs/how-tos.md @@ -0,0 +1,11 @@ +--- +nav_order: 17 +has_children: true +title: How-to guides +permalink: /how-to +layout: default +--- +# How-to guides + +{: .highlight } +documentation under development diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..11ddae609 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,47 @@ +--- +nav_order: 1 +has_children: false +title: Overview +permalink: / +layout: default +--- +# Kernel Memory + +[![License: MIT](https://img.shields.io/github/license/microsoft/kernel-memory)](https://github.com/microsoft/kernel-memory/blob/main/LICENSE) +[![Discord](https://img.shields.io/discord/1063152441819942922?label=Discord&logo=discord&logoColor=white&color=d82679)](https://aka.ms/KMdiscord) + +**Kernel Memory** (KM) is a **multi-modal [AI Service](service/Service/README.md)** +specialized in the efficient indexing of documents and information through custom continuous data +pipelines, with support for +**[Retrieval Augmented Generation](https://en.wikipedia.org/wiki/Prompt_engineering#Retrieval-augmented_generation)** (RAG), +synthetic memory, prompt engineering, and custom semantic memory processing. + +KM supports PDF and Word documents, PowerPoint presentations, Images, Spreadsheets [and more](extensions/data-formats), +extracting information and generating memories by leveraging Large Language Models (LLMs), Embeddings and Vector +storage. + +![image](https://github.com/microsoft/kernel-memory/assets/371009/31894afa-d19e-4e9b-8d0f-cb889bf5c77f) + +Utilizing advanced embeddings, LLMs and prompt engineering, the system enables Natural Language +**querying for obtaining answers** from the information stored, complete with citations +and links to the original sources. + +![image](https://github.com/microsoft/kernel-memory/assets/371009/c5f0f6c3-814f-45bf-b055-063f23ed80ea) + +Kernel Memory is designed for seamless integration with any programming language, providing a +web service that can also be consumed as an [OpenAPI endpoint for ChatGPT](https://openai.com/blog/chatgpt-plugins), +web clients ready to use, and a Plugin +for [Microsoft Copilot](https://www.microsoft.com/microsoft-365/blog/2023/05/23/empowering-every-developer-with-plugins-for-microsoft-365-copilot) +and [Semantic Kernel](https://github.com/microsoft/semantic-kernel). + +# Topics + +* [Quickstart: test KM in few minutes](quickstart) +* [**Memory service**, web clients and plugins](service) +* [**Memory API**, memory ingestion and information retrieval](functions) +* [KM **Extensions**: vector DBs, AI models, Data formats, Orchestration, Content storage](extensions) +* [Embedding **serverless** memory in .NET apps](serverless) +* [**Security**, service and users](security) +* [**How-to guides**, customizing KM and examples](how-to) +* [**Concepts**, KM glossary](concepts) +* [KM packages](packages) \ No newline at end of file diff --git a/docs/java.png b/docs/java.png new file mode 100644 index 000000000..da4c9789c Binary files /dev/null and b/docs/java.png differ diff --git a/docs/logo.png b/docs/logo.png new file mode 100644 index 000000000..24326877d Binary files /dev/null and b/docs/logo.png differ diff --git a/docs/packages.md b/docs/packages.md new file mode 100644 index 000000000..27112878d --- /dev/null +++ b/docs/packages.md @@ -0,0 +1,89 @@ +--- +nav_order: 91 +has_children: false +title: Packages +permalink: /packages +layout: default +--- +# .NET packages + +* **Microsoft.KernelMemory.WebClient:** The web client library, can be used to call + a running instance of the Memory web service. .NET Standard 2.0 compatible. + + [![Nuget package](https://img.shields.io/nuget/vpre/Microsoft.KernelMemory.WebClient)](https://www.nuget.org/packages/Microsoft.KernelMemory.WebClient/) + [![Example code](https://img.shields.io/badge/example-code-blue)](examples/002-dotnet-WebClient) + +* **Microsoft.KernelMemory.SemanticKernelPlugin:** a Memory plugin for Semantic Kernel, + replacing the original Semantic Memory available in SK. .NET Standard 2.0 compatible. + + [![Nuget package](https://img.shields.io/nuget/vpre/Microsoft.KernelMemory.SemanticKernelPlugin)](https://www.nuget.org/packages/Microsoft.KernelMemory.SemanticKernelPlugin/) + [![Example code](https://img.shields.io/badge/example-code-blue)](examples/011-dotnet-using-MemoryPlugin) + +* **Microsoft.KernelMemory.Abstractions:** The internal interfaces and models + shared by all packages, used to extend KM to support third party services. + .NET Standard 2.0 compatible. + + [![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.Abstractions)](https://www.nuget.org/packages/Microsoft.KernelMemory.Abstractions/) + +* **Microsoft.KernelMemory.MemoryDb.AzureAISearch:** Memory storage using + **[Azure AI Search](extensions/AzureAISearch)**. + + [![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.MemoryDb.AzureAISearch)](https://www.nuget.org/packages/Microsoft.KernelMemory.MemoryDb.AzureAISearch/) + +* **Microsoft.KernelMemory.MemoryDb.Postgres:** Memory storage using + **[PostgreSQL](extensions/Postgres)**. + + [![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.MemoryDb.Postgres)](https://www.nuget.org/packages/Microsoft.KernelMemory.MemoryDb.Postgres/) + +* **Microsoft.KernelMemory.MemoryDb.Qdrant:** Memory storage using + **[Qdrant](extensions/Qdrant)**. + + [![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.MemoryDb.Qdrant)](https://www.nuget.org/packages/Microsoft.KernelMemory.MemoryDb.Qdrant/) + +* **Microsoft.KernelMemory.AI.AzureOpenAI:** Integration with **[Azure OpenAI](extensions/OpenAI)** LLMs. + + [![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.AI.AzureOpenAI)](https://www.nuget.org/packages/Microsoft.KernelMemory.AI.AzureOpenAI/) + +* **Microsoft.KernelMemory.AI.LlamaSharp:** Integration with **[LLama](extensions/LlamaSharp)** LLMs. + + [![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.AI.LlamaSharp)](https://www.nuget.org/packages/Microsoft.KernelMemory.AI.LlamaSharp/) + +* **Microsoft.KernelMemory.AI.OpenAI:** Integration with **[OpenAI](extensions/OpenAI)** LLMs. + + [![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.AI.OpenAI)](https://www.nuget.org/packages/Microsoft.KernelMemory.AI.OpenAI/) + +* **Microsoft.KernelMemory.DataFormats.AzureAIDocIntel:** Integration with + [Azure AI Document Intelligence](extensions/AzureAIDocIntel). + + [![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.DataFormats.AzureAIDocIntel)](https://www.nuget.org/packages/Microsoft.KernelMemory.DataFormats.AzureAIDocIntel/) + +* **Microsoft.KernelMemory.Orchestration.AzureQueues:** Ingestion and synthetic memory + pipelines via [Azure Queue Storage](extensions/AzureQueues). + + [![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.Orchestration.AzureQueues)](https://www.nuget.org/packages/Microsoft.KernelMemory.Orchestration.AzureQueues/) + +* **Microsoft.KernelMemory.Orchestration.RabbitMQ:** Ingestion and synthetic memory + pipelines via [RabbitMQ](extensions/RabbitMQ). + + [![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.Orchestration.RabbitMQ)](https://www.nuget.org/packages/Microsoft.KernelMemory.Orchestration.RabbitMQ/) + +* **Microsoft.KernelMemory.ContentStorage.AzureBlobs:** Used to store content on + [Azure Storage Blobs](extensions/AzureBlobs). + + [![Nuget package](https://img.shields.io/nuget/v/Microsoft.KernelMemory.ContentStorage.AzureBlobs)](https://www.nuget.org/packages/Microsoft.KernelMemory.ContentStorage.AzureBlobs/) + +* **Microsoft.KernelMemory.Core:** The core library, can be used to build custom + pipelines and handlers, and contains a serverless client to use memory in a + synchronous way, without the web service. .NET 6+. + + [![Nuget package](https://img.shields.io/nuget/vpre/Microsoft.KernelMemory.Core)](https://www.nuget.org/packages/Microsoft.KernelMemory.Core/) + [![Example code](https://img.shields.io/badge/example-code-blue)](examples/001-dotnet-Serverless) + +### Packages for Python, Java and other languages + +Kernel Memory service offers a **Web API** out of the box, including the **OpenAPI +swagger** documentation that you can leverage to test the API and create custom +web clients. For instance, after starting the service locally, see http://127.0.0.1:9001/swagger/index.html. + +A python package with a Web Client and Semantic Kernel plugin will soon be available. +We also welcome PR contributions to support more languages. diff --git a/docs/python.png b/docs/python.png new file mode 100644 index 000000000..708d81076 Binary files /dev/null and b/docs/python.png differ diff --git a/docs/quickstart-dotnet-run.png b/docs/quickstart-dotnet-run.png new file mode 100644 index 000000000..92c7fb271 Binary files /dev/null and b/docs/quickstart-dotnet-run.png differ diff --git a/docs/quickstart-swagger.png b/docs/quickstart-swagger.png new file mode 100644 index 000000000..a829779cf Binary files /dev/null and b/docs/quickstart-swagger.png differ diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 000000000..f83663a3e --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,377 @@ +--- +nav_order: 2 +has_children: false +title: Quickstart +permalink: /quickstart +layout: default +--- +# Quickstart, local deployment + +This guide assumes you're familiar with web services, docker and OpenAI settings. + +In this quickstart tour, we'll start the service and try the Memory API from a Bash command line +and a .NET application. + +## Requirements + +* [.NET 6+](https://dotnet.microsoft.com/download) +* Either an [OpenAI API Key](https://platform.openai.com/api-keys) or + [Azure OpenAI deployment](https://azure.microsoft.com/products/ai-services/openai-service). If you are familiar + with llama.cpp or LLamaSharp you can also use a LLama model, although in that case the AI code will be + considerably slower, depending on your device. +* A vector DB, such as Azure AI Search, Qdrant, or Postgres. You can also use KM SimpleVectorDb for basic tests. +* A copy of [KM repository](https://github.com/microsoft/kernel-memory). + +## Configuration + +KM service requires a configuration file to start, usually `appsettings.development.json` when working locally, +or `appsettings.production.json` when running in Production environment. The exact config file is automatically +loaded, by checking the `ASPNETCORE_ENVIRONMENT` environment variable. + +KM repository includes a wizard to quickly generate your first `appsettings.development.json`: + + cd service/Service + dotnet run setup + +Follow the questions on screen to create/edit the file. You can run the command multiple times if necessary. + +{: .console } +> _Run the web service (upload and search endpoints)_? **YES** +> +> _Protect the web service with API Keys_? **NO** +> ------ you can leave this off for this test + +> _Enable OpenAPI swagger doc at /swagger/index.html_? **YES** + +> _Run the .NET pipeline handlers as a service_? **YES** +> +> _How should memory ingestion be orchestrated_? **Using asynchronous distributed queues** +> +> _Which queue service will be used_? **SimpleQueues** +> ------ this will use volatile queues in memory, suitable only for tests +> +> Directory where to store queue messages: _tmp_queues +> +> _Where should the service store files_? **SimpleFileStorage** +> ------ this will use volatile storage in memory, suitable only for tests. You can manually edit appsettings.development.json to persist files on disk. +> +> Directory where to store files: _tmp_files +> +> _Which service should be used to extract text from images_? **None** +> +> _When importing data, generate embeddings_? **YES** +> +> _When searching for text and/or answers, which embedding generator should be used_? **Azure OpenAI or OpenAI** +> +> OpenAI [current: gpt-3.5-turbo-16k]: Press ENTER to use default +> OpenAI [current: text-embedding-ada-002]: Press ENTER to use default +> OpenAI : sk-********************************* +> +> _When searching for answers, which memory DB service contains the records?_ **SimpleVectorDb** +> ------ this will use volatile storage in memory, suitable only for tests. You can manually edit +appsettings.development.json to persist files on disk, or choose one of the available options suggested. +> +> Directory where to store vectors: _tmp_vectors +> +> _When generating answers and synthetic data, which LLM text generator should be used?_ **Azure OpenAI or OpenAI** +> +> _Log level_? **Information** + +Great! If you completed the wizard, you should be ready to start the service and run the examples below. + +{: .important } +> * If you selected any of the "simpleXYZ" dependency, then data will be stored in memory only, and automatically discarded +> when the service stops. Edit the configuration file manually to persist data on disk. [More information here](service/configuration). +> * The configuration wizard uses some default settings that you might want to change. After running the examples, take +> a look at the included [appsettings.json](https://github.com/microsoft/kernel-memory/blob/main/service/Service/appsettings.json) +> to see all the available options, and read the [Service Configuration doc](service/configuration) for more information. + +## Start the service + + cd service/Service + dotnet run + +You should see something similar in your console: + +![quickstart-dotnet-run.png](quickstart-dotnet-run.png) + +## Check OpenAPI swagger + +In your browser open [http://127.0.0.1:9001/swagger/index.html](http://127.0.0.1:9001/swagger/index.html) + +You should see the usual Swagger UI: + +![quickstart-swagger.png](quickstart-swagger.png) + +# Python + +## Upload a document + +The following script performs the same operation, uploading a file: + +```python +import requests + +files = { + "file1": ("README.md", open("README.md", "rb")), +} + +data = { + "documentId": "doc01", +} + +response = requests.post("http://127.0.0.1:9001/upload", files=files, data=data) + +print(response.text) +``` + +## Query + +```python +import requests +import json + +data = {"question": "Name one tool that I can use from command line"} + +response = requests.post( + "http://127.0.0.1:9001/ask", + headers={"Content-Type": "application/json"}, + data=json.dumps(data), +).json() + +if "text" in response: + print(response["text"]) +else: + print("Response does not contain a 'text' property.") +``` + +If you run the scripts, the output will look similar to: + +{: .console } +> _You can use the "upload-file.sh", "ask.sh", and "search.sh" tools from the command line._ + +# C# + +## Upload a document and answer questions + +Create a new .NET Console app and add package `Microsoft.KernelMemory.WebClient`, then add this code: + +```csharp +using Microsoft.KernelMemory; + +var memory = new MemoryWebClient("http://127.0.0.1:9001/"); + +await memory.ImportWebPageAsync( + "https://raw.githubusercontent.com/microsoft/kernel-memory/main/README.md", + documentId: "doc02"); + +Console.WriteLine("Waiting for memory ingestion to complete..."); +while (!await memory.IsDocumentReadyAsync(documentId: "doc02")) +{ + await Task.Delay(TimeSpan.FromMilliseconds(1500)); +} + +var answer = await memory.AskAsync("Is there a Kernel Memory community and how can I join?"); + +Console.WriteLine($"\nAnswer: {answer.Result}"); +``` + +Run the application, and you should see: + +{: .console } +> Answer: Yes, there is a Kernel Memory community. You can join the community by joining +> the [Kernel Memory Discord server](https://aka.ms/KMdiscord). + +# Command line (bash, curl) + +## Upload a document + +Open a Bash console in the folder where you cloned Kernel Memory repository. The repository contains +a **tools** folder with a few scripts, in particular `upload-file.sh` and `ask.sh` that you can use to send +requests to the web service. You can also use `curl` if you prefer, the syntax is pretty simple, and the web service +replies with JSON. + +Run the following commands: + + cd tools + ./upload-file.sh -f README.md -i doc01 -s http://127.0.0.1:9001 + +or: + + curl -F 'file1=@"README.md"' -F 'documentId="doc01"' http://127.0.0.1:9001/upload + +You should see a confirmation message: + +{: .console } +> ```json +> {"index":"","documentId":"doc01","message":"Document upload completed, ingestion pipeline started"} +> ``` + +## Query + + cd tools + ./ask.sh -q "Can I use KM from command line?" -s http://127.0.0.1:9001 + +or: + + curl -d'{"question":"Can I use KM from command line?"}' -H 'Content-Type: application/json' http://127.0.0.1:9001/ask + +The script will show the JSON returned by the web service, and among other details you should see the answer: + +{: .console } +> _Yes, you can use Kernel Memory (KM) from the command line. There are several scripts provided, such +as `upload-file.sh`, +> `ask.sh`, and `search.sh`, that allow you to interact with KM from the command line. These scripts provide +functionality +> for uploading files, asking questions about your documents, and searching your indexed documents, respectively. +> Additionally, there is a script called `run-qdrant.sh` that starts Qdrant, which is used to store and search vectors +in KM._ + +# Java + +## Upload a document + +Create a `FileUploadExample.java` file, with this code: + +```java +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; + +public class FileUploadExample { + + public static void main(String[] args) throws IOException { + String url = "http://127.0.0.1:9001/upload"; + String filename = "README.md"; + String documentId = "doc01"; + + // Set up the file and form data + File file = new File(filename); + String boundary = "----WebKitFormBoundary" + Long.toHexString(System.currentTimeMillis()); + String CRLF = "\r\n"; + String charset = StandardCharsets.UTF_8.name(); + + // Create the HTTP connection + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setDoOutput(true); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); + + // Write the request body + try (OutputStream output = connection.getOutputStream(); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true)) { + // Add file data + writer.append("--" + boundary).append(CRLF); + writer.append("Content-Disposition: form-data; name=\"file1\"; filename=\"" + file.getName() + "\"").append(CRLF); + writer.append("Content-Type: " + Files.probeContentType(file.toPath())).append(CRLF); // Use probeContentType + writer.append(CRLF).flush(); + Files.copy(file.toPath(), output); + output.flush(); + writer.append(CRLF).flush(); + + // Add form data + writer.append("--" + boundary).append(CRLF); + writer.append("Content-Disposition: form-data; name=\"documentId\"").append(CRLF); + writer.append(CRLF).append(documentId).append(CRLF).flush(); + + // End of request + writer.append("--" + boundary + "--").append(CRLF).flush(); + } + + // Get the response + try (InputStream responseStream = connection.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(responseStream))) { + String line; + StringBuilder response = new StringBuilder(); + while ((line = reader.readLine()) != null) { + response.append(line); + } + System.out.println(response.toString()); + } finally { + connection.disconnect(); + } + } +} +``` + +Build and run the code: + + javac FileUploadExample.java + java FileUploadExample + +and you should see the successful output: + +{: .console } +> ```json +> {"index":"","documentId":"doc01","message":"Document upload completed, ingestion pipeline started"} +> ``` + +## Query + +Create a `AskQuestionExample.java` file, with this code: + +```java +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +public class AskQuestionExample { + + public static void main(String[] args) throws IOException { + String url = "http://127.0.0.1:9001/ask"; + String jsonInputString = "{\"question\":\"Can I use KM from the command line?\"}"; + + // Create the HTTP connection + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setDoOutput(true); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + + // Write the request body + try (OutputStream os = connection.getOutputStream()) { + byte[] input = jsonInputString.getBytes("utf-8"); + os.write(input, 0, input.length); + } + + // Get the response + try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) { + StringBuilder response = new StringBuilder(); + String responseLine; + while ((responseLine = br.readLine()) != null) { + response.append(responseLine.trim()); + } + System.out.println(response.toString()); + } finally { + connection.disconnect(); + } + } +} + +``` + +Build and run the code: + + javac AskQuestionExample.java + java AskQuestionExample + +and you should see the successful output: + +{: .console } +> ```json +> {"question":"Can I use KM from the command line?","noResult":false,"text":"Yes, you can use Kernel Memory (KM) from the command line. There are several scripts provided in the repository that allow you to interact with KM from the command line.\n\nThe `upload-file.sh` script is a client for command line uploads to Kernel Mem... +> ``` + +# More examples + +The repository contains more documentation and examples, here's some suggestions: + +* [KM concepts: Indexes, Documents, Tags and more](concepts) +* [Memory API](functions) +* [Collection of Jupyter notebooks with various scenarios](https://github.com/microsoft/kernel-memory/examples/000-notebooks) +* [Using Kernel Memory web service to upload documents and answer questions](https://github.com/microsoft/kernel-memory/examples/001-dotnet-WebClient) +* [Summarizing documents](https://github.com/microsoft/kernel-memory/examples/106-dotnet-retrieve-synthetics) \ No newline at end of file diff --git a/docs/run.cmd b/docs/run.cmd new file mode 100755 index 000000000..42a8c0c18 --- /dev/null +++ b/docs/run.cmd @@ -0,0 +1 @@ +bundle exec jekyll serve --config _config.local.yml --baseurl="/kernel-memory" --host localhost --port 4000 --livereload diff --git a/docs/security.md b/docs/security.md new file mode 100644 index 000000000..825e59b65 --- /dev/null +++ b/docs/security.md @@ -0,0 +1,12 @@ +--- +nav_order: 16 +has_children: true +title: Security +permalink: /security +layout: default +--- +# Security + +{: .highlight } +documentation under development + diff --git a/docs/SECURITY_FILTERS.md b/docs/security/security-filters.md similarity index 99% rename from docs/SECURITY_FILTERS.md rename to docs/security/security-filters.md index e0d7b16ae..2a057e80e 100644 --- a/docs/SECURITY_FILTERS.md +++ b/docs/security/security-filters.md @@ -1,3 +1,10 @@ +--- +nav_order: 1 +parent: Security +title: Security Filters +permalink: /security/filters +layout: default +--- # Security Filters This document provides some guidance about how to organize your documents in diff --git a/docs/security/service-api-keys.md b/docs/security/service-api-keys.md new file mode 100644 index 000000000..50c5681b5 --- /dev/null +++ b/docs/security/service-api-keys.md @@ -0,0 +1,11 @@ +--- +nav_order: 4 +parent: Security +title: Service API Keys +permalink: /security/service-api-keys +layout: default +--- +# Service API keys + +{: .highlight } +documentation under development diff --git a/docs/serverless.md b/docs/serverless.md new file mode 100644 index 000000000..5bb9a6d1d --- /dev/null +++ b/docs/serverless.md @@ -0,0 +1,71 @@ +--- +nav_order: 15 +has_children: true +title: Serverless (.NET) +permalink: /serverless +layout: default +--- +# Serverless memory (.NET only) + +Kernel Memory works and scales at best when running as a service, allowing to +ingest thousands of documents and information without blocking your app. However, +you can also embed the `MemoryServerless` class in your app, using `KernelMemoryBuilder`. + +**`MemoryServerless` and `MemoryWebClient` implement the same interface +and offer the same API**, so you can easily switch from one to the other. + +> {: .important } +The embedded serverless mode is available only for .NET applications, by +running the KM codebase inside the same process of your .NET application. + +> {: .warning } +By default the serverless memory is **volatile** and keeps all data only in memory, +without persistence on disk. Follow the configuration instructions to persist memory +across multiple executions. + + + + + +> ### Importing documents into your Kernel Memory can be as simple as this: +> +> ```csharp +> var memory = new KernelMemoryBuilder() +> .WithOpenAIDefaults(Env.Var("OPENAI_API_KEY")) +> .Build(); +> +> // Import a file +> await memory.ImportDocumentAsync("meeting-transcript.docx", tags: new() { { "user", "Blake" } }); +> +> // Import multiple files and apply multiple tags +> await memory.ImportDocumentAsync(new Document("file001") +> .AddFile("business-plan.docx") +> .AddFile("project-timeline.pdf") +> .AddTag("user", "Blake") +> .AddTag("collection", "business") +> .AddTag("collection", "plans") +> .AddTag("fiscalYear", "2023")); +> ``` + +> ### Asking questions: +> +> ```csharp +> var answer1 = await memory.AskAsync("How many people attended the meeting?"); +> +> var answer2 = await memory.AskAsync("what's the project timeline?", filter: new MemoryFilter().ByTag("user", "Blake")); +> ``` + +The code leverages the default documents ingestion pipeline: + +1. Extract text: recognize the file format and extract the information +2. Partition the text in small chunks, to optimize search +3. Extract embedding using an LLM embedding generator +4. Save embedding into a vector index such as + [Azure AI Search](https://learn.microsoft.com/azure/search/vector-search-overview), + [Qdrant](https://qdrant.tech/) or other DBs. + +Documents are organized by users, safeguarding their private information. +Furthermore, memories can be categorized and structured using **tags**, enabling +efficient search and retrieval through faceted navigation. + +# Topics \ No newline at end of file diff --git a/docs/serverless/components.md b/docs/serverless/components.md new file mode 100644 index 000000000..98916a608 --- /dev/null +++ b/docs/serverless/components.md @@ -0,0 +1,11 @@ +--- +nav_order: 1 +parent: Serverless (.NET) +title: Components +permalink: /serverless/components +layout: default +--- +# Components of serverless memory + +{: .highlight } +documentation under development diff --git a/docs/serverless/kernel-builder.md b/docs/serverless/kernel-builder.md new file mode 100644 index 000000000..ced4d4c1e --- /dev/null +++ b/docs/serverless/kernel-builder.md @@ -0,0 +1,11 @@ +--- +nav_order: 3 +parent: Serverless (.NET) +title: Kernel Builder +permalink: /serverless/kernel-builder +layout: default +--- +# Kernel Builder + +{: .highlight } +documentation under development diff --git a/docs/serverless/plugin.md b/docs/serverless/plugin.md new file mode 100644 index 000000000..b9398e687 --- /dev/null +++ b/docs/serverless/plugin.md @@ -0,0 +1,12 @@ +--- +nav_order: 4 +parent: Serverless (.NET) +title: SK Plugin +permalink: /serverless/sk-plugin-serverless +layout: default +--- + +# Semantic Kernel plugin (serverless) + +{: .highlight } +documentation under development diff --git a/docs/serverless/volatile-memory.md b/docs/serverless/volatile-memory.md new file mode 100644 index 000000000..aea3873e9 --- /dev/null +++ b/docs/serverless/volatile-memory.md @@ -0,0 +1,11 @@ +--- +nav_order: 2 +parent: Serverless (.NET) +title: Volatile memory +permalink: /serverless/volatile-memory +layout: default +--- +# Serverless memory volatility + +{: .highlight } +documentation under development diff --git a/docs/service.md b/docs/service.md new file mode 100644 index 000000000..ccd61ef35 --- /dev/null +++ b/docs/service.md @@ -0,0 +1,24 @@ +--- +nav_order: 10 +has_children: true +title: Service +permalink: /service +layout: default +--- + +# Kernel Memory service + +KM service offers the best performing, most secure and scalable approach to +Memory organization and usage with RAG. + +By using KM service, as opposed to the embedded serverless mode, you get these benefits: + +* KM can be used from **any language**, such as Python, C#, Java, **and platforms**, + simply by sending HTTP requests. +* KM service can be **distributed over multiple machines**, and run long ingestion + processes without blocking your client applications. This includes the need + to **retry in case of errors and throttling** by external services like OpenAI. +* Only the service needs **credentials** to access AI models, storage and other + dependencies, so secrets are not exposed via client apps. +* You can run the service locally, getting all the benefits also during tests + and development. \ No newline at end of file diff --git a/docs/service/architecture.md b/docs/service/architecture.md new file mode 100644 index 000000000..895c041aa --- /dev/null +++ b/docs/service/architecture.md @@ -0,0 +1,11 @@ +--- +nav_order: 1 +parent: Service +title: Architecture +permalink: /service/architecture +layout: default +--- +# Service architecture + +{: .highlight } +documentation under development diff --git a/docs/service/configuration.md b/docs/service/configuration.md new file mode 100644 index 000000000..8e4f5677a --- /dev/null +++ b/docs/service/configuration.md @@ -0,0 +1,11 @@ +--- +nav_order: 2 +parent: Service +title: Configuration +permalink: /service/configuration +layout: default +--- +# Service Configuration + +{: .highlight } +documentation under development diff --git a/docs/service/openapi.md b/docs/service/openapi.md new file mode 100644 index 000000000..3b11f5d6c --- /dev/null +++ b/docs/service/openapi.md @@ -0,0 +1,11 @@ +--- +nav_order: 3 +parent: Service +title: OpenAPI - Web API +permalink: /service/openapi +layout: default +--- +# Web service OpenAPI + +{: .highlight } +documentation under development diff --git a/docs/service/plugin.md b/docs/service/plugin.md new file mode 100644 index 000000000..e4a2de3a9 --- /dev/null +++ b/docs/service/plugin.md @@ -0,0 +1,12 @@ +--- +nav_order: 6 +parent: Service +title: SK Plugin +permalink: /service/sk-plugin +layout: default +--- + +# Semantic Kernel plugin + +{: .highlight } +documentation under development diff --git a/docs/service/web-client.md b/docs/service/web-client.md new file mode 100644 index 000000000..41b73d75e --- /dev/null +++ b/docs/service/web-client.md @@ -0,0 +1,11 @@ +--- +nav_order: 5 +parent: Service +title: Web Client +permalink: /service/web-client +layout: default +--- +# Web Client + +{: .highlight } +documentation under development diff --git a/docs/test-page.md b/docs/test-page.md new file mode 100644 index 000000000..edf370628 --- /dev/null +++ b/docs/test-page.md @@ -0,0 +1,309 @@ +--- +nav_order: 1000 +has_children: false +title: Test Page +permalink: /test +layout: default +nav_exclude: true +--- + +# Test + +{: .important } +Important note Important note Important note +Important note Important note Important note + +{: .highlight } +highlight note highlight note highlight note +highlight note highlight note highlight note + +{: .new } +new note new note new note +new note new note new note + +{: .note } +note note note note note note +note note note note note note + +{: .warning } +Warning note Warning note Warning note +Warning note Warning note Warning note + +> {: .important } +Important note Important note Important note +Important note Important note Important note +Important note Important note Important note + +{: .important } +> Important note Important note Important note +> +> Important note Important note Important note + + +```csharp +public class Foo { + public static void Main() { + // test + } +} +``` + +Default label +{: .label } + +Blue label +{: .label .label-blue } + +Stable +{: .label .label-green } + +New release +{: .label .label-purple } + +Coming soon +{: .label .label-yellow } + +Deprecated +{: .label .label-red } + + + +note note note note note note +note note note note note note +{: .label .label-yellow } + +### Backends + +* 🧠 AI + * [Azure OpenAI](https://learn.microsoft.com/azure/ai-services/openai/concepts/models) + * [OpenAI](https://platform.openai.com/docs/models) + * LLama - thanks to [llama.cpp](https://github.com/ggerganov/llama.cpp) + and [LLamaSharp](https://github.com/SciSharp/LLamaSharp) + * [Azure Document Intelligence](https://azure.microsoft.com/products/ai-services/ai-document-intelligence) + +* ↗️ Vector storage + * [Azure AI Search](https://azure.microsoft.com/products/ai-services/ai-search) + * [Postgres+pgvector](https://github.com/microsoft/kernel-memory/extensions/postgres) + * [Qdrant](https://qdrant.tech) + * Redis: [work in progress](https://github.com/microsoft/kernel-memory/pull/208) + * In memory KNN vectors (volatile) + +* 📀 Content storage + * [Azure Blobs](https://learn.microsoft.com/azure/storage/blobs/storage-blobs-introduction) + * Local file system + * In memory, volatile content + +* ⏳ Orchestration + * [Azure Queues](https://learn.microsoft.com/azure/storage/queues/storage-queues-introduction) + * [RabbitMQ](https://www.rabbitmq.com) + * Local file based queue + * In memory queues (volatile) + +# Kernel Memory in serverless mode + +Kernel Memory works and scales at best when running as a service, allowing to +ingest thousands of documents and information without blocking your app, from +any programming language, via HTTP requests. + +However, you can use Kernel Memory also serverless, [embedding the `MemoryServerless` +class in your .NET applications](/serverless). + +# Data lineage, citations + +All memories and answers are fully correlated to the data provided. When +producing an answer, Kernel Memory includes all the information needed +to verify its accuracy: + +```csharp +await memory.ImportFileAsync("NASA-news.pdf"); + +var answer = await memory.AskAsync("Any news from NASA about Orion?"); + +Console.WriteLine(answer.Result + "/n"); + +foreach (var x in answer.RelevantSources) +{ + Console.WriteLine($" * {x.SourceName} -- {x.Partitions.First().LastUpdate:D}"); +} +``` + +> Yes, there is news from NASA about the Orion spacecraft. NASA has invited the +> media to see a new test version of the Orion spacecraft and the hardware that +> will be used to recover the capsule and astronauts upon their return from +> space during the Artemis II mission. The event is scheduled to take place at +> Naval Base San Diego on Wednesday, August 2, at 11 a.m. PDT. Personnel from +> NASA, the U.S. Navy, and the U.S. Air Force will be available to speak with +> the media. Teams are currently conducting tests in the Pacific Ocean to +> demonstrate and evaluate the processes, procedures, and hardware for recovery +> operations for crewed Artemis missions. These tests will help prepare the +> team for Artemis II, which will be NASA's first crewed mission under the +> Artemis program. The Artemis II crew, consisting of NASA astronauts Reid +> Wiseman, Victor Glover, and Christina Koch, and Canadian Space Agency +> astronaut Jeremy Hansen, will participate in recovery testing at sea next +> year. For more information about the Artemis program, you can visit the NASA +> website. +> +> - **NASA-news.pdf -- Tuesday, August 1, 2023** + +## Using Kernel Memory Service + +Depending on your scenarios, you might want to run all the code **locally +inside your process, or remotely through an asynchronous service.** + +If you're importing small files, and need only C# and can block +the process during the import, local-in-process execution can be fine, using +the **MemoryServerless** seen above. + +However, if you are in one of these scenarios: + +* I'd just like a web service to import data and send queries to answer +* My app is written in **TypeScript, Java, Rust, or some other language** +* I want to define **custom pipelines mixing multiple languages** + like Python, TypeScript, etc +* I'm importing **big documents that can require minutes to process**, and + I don't want to block the user interface +* I need memory import to **run independently, supporting failures and retry + logic** + +then you can deploy Kernel Memory as a service, plugging in the +default handlers or your custom Python/TypeScript/Java/etc. handlers, +and leveraging the asynchronous non-blocking memory encoding process, +sending documents and asking questions using the **MemoryWebClient**. + +[Here](service/Service/README.md) you can find a complete set of instruction +about [how to run the Kernel Memory service](service/Service/README.md). + +If you want to give the service a quick test, use the following command +to **start the Kernel Memory Service**: + +> ### On WSL / Linux / MacOS: +> +> ```shell +> cd service/Service +> ./setup.sh +> ./run.sh +> ``` + +> ### On Windows: +> +> ```shell +> cd service\Service +> setup.cmd +> run.cmd +> ``` + +> ### To import files using Kernel Memory **web service**, use `MemoryWebClient`: +> +> ```csharp +> #reference clients/WebClient/WebClient.csproj +> +> var memory = new MemoryWebClient("http://127.0.0.1:9001"); // <== URL where the web service is running +> +> // Import a file (default user) +> await memory.ImportDocumentAsync("meeting-transcript.docx"); +> +> // Import a file specifying a Document ID, User and Tags +> await memory.ImportDocumentAsync("business-plan.docx", +> new DocumentDetails("user@some.email", "file001") +> .AddTag("collection", "business") +> .AddTag("collection", "plans") +> .AddTag("fiscalYear", "2023")); +> ``` + +> ### Getting answers via the web service +> ``` +> curl http://127.0.0.1:9001/ask -d'{"query":"Any news from NASA about Orion?"}' -H 'Content-Type: application/json' +> ``` +> ```json +> { +> "Query": "Any news from NASA about Orion?", +> "Text": "Yes, there is news from NASA about the Orion spacecraft. NASA has invited the media to see a new test version of the Orion spacecraft and the hardware that will be used to recover the capsule and astronauts upon their return from space during the Artemis II mission. The event is scheduled to take place at Naval Base San Diego on August 2nd at 11 a.m. PDT. Personnel from NASA, the U.S. Navy, and the U.S. Air Force will be available to speak with the media. Teams are currently conducting tests in the Pacific Ocean to demonstrate and evaluate the processes, procedures, and hardware for recovery operations for crewed Artemis missions. These tests will help prepare the team for Artemis II, which will be NASA's first crewed mission under the Artemis program. The Artemis II crew, consisting of NASA astronauts Reid Wiseman, Victor Glover, and Christina Koch, and Canadian Space Agency astronaut Jeremy Hansen, will participate in recovery testing at sea next year. For more information about the Artemis program, you can visit the NASA website.", +> "RelevantSources": [ +> { +> "Link": "...", +> "SourceContentType": "application/pdf", +> "SourceName": "file5-NASA-news.pdf", +> "Partitions": [ +> { +> "Text": "Skip to main content\nJul 28, 2023\nMEDIA ADVISORY M23-095\nNASA Invites Media to See Recovery Craft for\nArtemis Moon Mission\n(/sites/default/files/thumbnails/image/ksc-20230725-ph-fmx01_0003orig.jpg)\nAboard the USS John P. Murtha, NASA and Department of Defense personnel practice recovery operations for Artemis II in July. A\ncrew module test article is used to help verify the recovery team will be ready to recovery the Artemis II crew and the Orion spacecraft.\nCredits: NASA/Frank Michaux\nMedia are invited to see the new test version of NASA’s Orion spacecraft and the hardware teams will use\nto recover the capsule and astronauts upon their return from space during the Artemis II\n(http://www.nasa.gov/artemis-ii) mission. The event will take place at 11 a.m. PDT on Wednesday, Aug. 2,\nat Naval Base San Diego.\nPersonnel involved in recovery operations from NASA, the U.S. Navy, and the U.S. Air Force will be\navailable to speak with media.\nU.S. media interested in attending must RSVP by 4 p.m., Monday, July 31, to the Naval Base San Diego\nPublic Affairs (mailto:nbsd.pao@us.navy.mil) or 619-556-7359.\nOrion Spacecraft (/exploration/systems/orion/index.html)\nNASA Invites Media to See Recovery Craft for Artemis Moon Miss... https://www.nasa.gov/press-release/nasa-invites-media-to-see-recov...\n1 of 3 7/28/23, 4:51 PMTeams are currently conducting the first in a series of tests in the Pacific Ocean to demonstrate and\nevaluate the processes, procedures, and hardware for recovery operations (https://www.nasa.gov\n/exploration/systems/ground/index.html) for crewed Artemis missions. The tests will help prepare the\nteam for Artemis II, NASA’s first crewed mission under Artemis that will send four astronauts in Orion\naround the Moon to checkout systems ahead of future lunar missions.\nThe Artemis II crew – NASA astronauts Reid Wiseman, Victor Glover, and Christina Koch, and CSA\n(Canadian Space Agency) astronaut Jeremy Hansen – will participate in recovery testing at sea next year.\nFor more information about Artemis, visit:\nhttps://www.nasa.gov/artemis (https://www.nasa.gov/artemis)\n-end-\nRachel Kraft\nHeadquarters, Washington\n202-358-1100\nrachel.h.kraft@nasa.gov (mailto:rachel.h.kraft@nasa.gov)\nMadison Tuttle\nKennedy Space Center, Florida\n321-298-5868\nmadison.e.tuttle@nasa.gov (mailto:madison.e.tuttle@nasa.gov)\nLast Updated: Jul 28, 2023\nEditor: Claire O’Shea\nTags:  Artemis (/artemisprogram),Ground Systems (http://www.nasa.gov/exploration/systems/ground\n/index.html),Kennedy Space Center (/centers/kennedy/home/index.html),Moon to Mars (/topics/moon-to-\nmars/),Orion Spacecraft (/exploration/systems/orion/index.html)\nNASA Invites Media to See Recovery Craft for Artemis Moon Miss... https://www.nasa.gov/press-release/nasa-invites-media-to-see-recov...\n2 of 3 7/28/23, 4:51 PM", +> "Relevance": 0.8430657, +> "SizeInTokens": 863, +> "LastUpdate": "2023-08-01T08:15:02-07:00" +> } +> ] +> } +> ] +> } +> ``` + +You can find a [full example here](examples/002-dotnet-WebClient/README.md). + +## Custom memory ingestion pipelines + +On the other hand, if you need a custom data pipeline, you can also +customize the steps, which will be handled by your custom business logic: + +```csharp +// Memory setup, e.g. how to calculate and where to store embeddings +var memoryBuilder = new KernelMemoryBuilder().WithOpenAIDefaults(Env.Var("OPENAI_API_KEY")); +memoryBuilder.Build(); +var orchestrator = memoryBuilder.GetOrchestrator(); + +// Define custom .NET handlers +var step1 = new MyHandler1("step1", orchestrator); +var step2 = new MyHandler2("step2", orchestrator); +var step3 = new MyHandler3("step3", orchestrator); +await orchestrator.AddHandlerAsync(step1); +await orchestrator.AddHandlerAsync(step2); +await orchestrator.AddHandlerAsync(step3); + +// Instantiate a custom pipeline +var pipeline = orchestrator + .PrepareNewFileUploadPipeline("user-id-1", "mytest", new[] { "memory-collection" }) + .AddUploadFile("file1", "file1.docx", "file1.docx") + .AddUploadFile("file2", "file2.pdf", "file2.pdf") + .Then("step1") + .Then("step2") + .Then("step3") + .Build(); + +// Execute in process, process all files with all the handlers +await orchestrator.RunPipelineAsync(pipeline); +``` + +# Web API specs + +The API schema is available at http://127.0.0.1:9001/swagger/index.html when +running the service locally with OpenAPI enabled. + +# Examples and Tools + +## Examples + +1. [Collection of Jupyter notebooks with various scenarios](examples/000-notebooks) +2. [Using Kernel Memory web service to upload documents and answer questions](examples/001-dotnet-WebClient) +3. [Using KM Plugin for Semantic Kernel](examples/002-dotnet-SemanticKernelPlugin) +4. [Importing files and asking question without running the service (serverless mode)](examples/003-dotnet-Serverless) +5. [Processing files with custom steps](examples/004-dotnet-ServerlessCustomPipeline) +6. [Upload files and ask questions from command line using curl](examples/005-curl-calling-webservice) +7. [Customizing RAG and summarization prompts](examples/101-dotnet-custom-Prompts) +8. [Custom partitioning/text chunking options](examples/102-dotnet-custom-partitioning-options) +9. [Using a custom embedding/vector generator](examples/103-dotnet-custom-EmbeddingGenerator) +10. [Using custom LLMs](examples/104-dotnet-custom-LLM) +11. [Using LLama](examples/105-dotnet-serverless-llamasharp) +12. [Summarizing documents](examples/106-dotnet-retrieve-synthetics) +11. [Natural language to SQL examples](examples/200-dotnet-nl2sql) +12. [Writing and using a custom ingestion handler](examples/201-dotnet-InProcessMemoryWithCustomHandler) +13. [Running a single asynchronous pipeline handler as a standalone service](examples/202-dotnet-CustomHandlerAsAService) +14. [Test project linked to KM package from nuget.org](examples/203-dotnet-using-core-nuget) +15. [Integrating Memory with ASP.NET applications and controllers](examples/204-dotnet-ASP.NET-MVC-integration) +16. [Sample code showing how to extract text from files](examples/205-dotnet-extract-text-from-docs) + +## Tools + +1. [Curl script to upload files](tools/upload-file.sh) +2. [Curl script to ask questions](tools/ask.sh) +3. [Curl script to search documents](tools/search.sh) +4. [Script to start Qdrant for development tasks](tools/run-qdrant.sh) +5. [Script to start RabbitMQ for development tasks](tools/run-rabbitmq.sh) +6. [.NET appsettings.json generator](tools/InteractiveSetup) diff --git a/service/Core/WebService/HttpDocumentUploadRequest.cs b/service/Core/WebService/HttpDocumentUploadRequest.cs index cb5fa6e86..9fa4f013d 100644 --- a/service/Core/WebService/HttpDocumentUploadRequest.cs +++ b/service/Core/WebService/HttpDocumentUploadRequest.cs @@ -72,10 +72,15 @@ public class HttpDocumentUploadRequest { if (tag == null) { continue; } - var keyValue = tag.Split(Constants.ReservedEqualsChar, 2); - string key = keyValue[0]; + var keyValue = tag.Trim().Split(Constants.ReservedEqualsChar, 2); + string key = keyValue[0].Trim(); + if (string.IsNullOrWhiteSpace(key)) { continue; } + ValidateTagName(key); - string? value = keyValue.Length == 1 ? null : keyValue[1]; + + string? value = keyValue.Length == 1 ? null : keyValue[1].Trim(); + if (string.IsNullOrWhiteSpace(value)) { value = null; } + result.Tags.Add(key, value); } } @@ -93,7 +98,7 @@ public class HttpDocumentUploadRequest } } - result.Index = indexes[0]!; + result.Index = indexes.FirstOrDefault()?.Trim() ?? string.Empty; result.DocumentId = documentId; result.Files = form.Files; diff --git a/tools/upload-file.sh b/tools/upload-file.sh index 5c354de4f..c0c12687c 100755 --- a/tools/upload-file.sh +++ b/tools/upload-file.sh @@ -102,12 +102,7 @@ readParameters "$@" validateParameters # Prepare curl command -CMD="curl -v -F 'file1=@\"${FILENAME}\"' -F 'index=\"${INDEXNAME}\"' -F 'documentId=\"${DOCUMENT_ID}\"'" - -# Handle list of tags -for TAG in $TAGS; do - CMD="$CMD -F '${TAG}'" -done +CMD="curl -v -F 'file1=@\"${FILENAME}\"' -F 'index=\"${INDEXNAME}\"' -F 'documentId=\"${DOCUMENT_ID}\"' -F 'tags=\"${TAGS}\"'" # Add URL CMD="$CMD $SERVICE_URL/upload"