{"id":3974,"date":"2024-10-06T12:05:47","date_gmt":"2024-10-06T11:05:47","guid":{"rendered":"https:\/\/jamiemaguire.net\/?p=3974"},"modified":"2024-10-06T12:05:47","modified_gmt":"2024-10-06T11:05:47","slug":"semantic-kernel-using-memories-to-create-intelligent-ai-agents","status":"publish","type":"post","link":"https:\/\/jamiemaguire.net\/index.php\/2024\/10\/06\/semantic-kernel-using-memories-to-create-intelligent-ai-agents\/","title":{"rendered":"Semantic Kernel: Using Memories to Create Intelligent AI Agents"},"content":{"rendered":"<p>Agentic AI continues to evolve at pace.\u00a0 State management is an important aspect in most applications, and this is also the case for developing intelligent agents.<\/p>\n<p>&nbsp;<\/p>\n<p>Semantic Kernel has the concept of a memory.<\/p>\n<p>&nbsp;<\/p>\n<p>Memories let you store and recall relevant information from past interactions, thereby enabling it to make informed decisions and provide context-aware responses. Memories help the agent learn from experience, improve its understanding of user preferences, and adapt its behaviour over time.<\/p>\n<p>&nbsp;<\/p>\n<p>This lets you create more personalized, coherent, and effective interactions, thereby enhancing the agent&#8217;s usefulness and making it easier for you to create a better user experience.<\/p>\n<p>&nbsp;<\/p>\n<p>In this blog post, we examine agentic memory.\u00a0 We see how memories can be used in Semantic Kernel.<\/p>\n<p>Other topics include:<\/p>\n<ul>\n<li>What is a memory<\/li>\n<li>Memory storage options<\/li>\n<li>Memory storage mechanisms<\/li>\n<li>Semantic Memory<\/li>\n<li>Kernel Memory<\/li>\n<li>Where memories fit within an existing Semantic Kernel solution<\/li>\n<li>Deciding between Semantic Kernel Memory and Kernel Memory<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>This blog post is more conceptual.\u00a0 Future blog posts will contain in-depth examples of memory in action.\u00a0 Read on for more details<\/p>\n<p style=\"text-align: center;\">~<\/p>\n<h2>What is a Memory?<\/h2>\n<p>A Memory is a mechanism that allows an AI agent to store, retrieve, and utilise information from past interactions or experiences. Memories can hold various types of data, such as conversation history, facts, or user preferences.<\/p>\n<p>This lets the agent create context-aware and adaptive behaviours.<\/p>\n<p>By leveraging memories, an agent can recall relevant details during future interactions, improve its ability to generate coherent responses, personalize its behaviour, and provide more intelligent, and, over time, consistent user experiences.<\/p>\n<p>&nbsp;<\/p>\n<p>You can find the object definition and properties for a memory object <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/microsoft.semantickernel.memory.memoryrecord?view=semantic-kernel-dotnet\">here<\/a>.<\/p>\n<p style=\"text-align: center;\">~<\/p>\n<h2>Memory Storage Options<\/h2>\n<p>In Semantic Kernel, there two storage mechanisms for memories.\u00a0 Volatile Memory and Non-Volatile Memory.\u00a0 A description of each follow.<\/p>\n<p><strong>\u00a0<\/strong><\/p>\n<p><strong>Volatile Memory<\/strong>:<\/p>\n<p>This type of memory is temporary and short-term. It holds data for the duration of a session or interaction but is not retained after the session ends. Volatile memory is useful for handling immediate context, such as conversation flow or task-related data that doesn\u2019t need to be recalled later.<\/p>\n<p>Use volatile memory when creating prototypes or one-shot interactions.<\/p>\n<p><strong>\u00a0<\/strong><\/p>\n<p><strong>Non-Volatile Memory<\/strong>:<\/p>\n<p>Non-volatile memory is persistent, meaning it is stored long-term and can be accessed across different sessions. This memory is useful for maintaining user preferences, important facts, or other data that needs to be retained and recalled in future interactions.<\/p>\n<p>Use non-volatile memory when you need to create feature rich agents that can handle several use cases.<\/p>\n<p>&nbsp;<\/p>\n<p>Each of the above memory storage mechanisms allow agents to manage both short-term and long-term information to provide richer, and more intelligent user interactions.<\/p>\n<p style=\"text-align: center;\">~<\/p>\n<h2>Memory Storage Mechanisms<\/h2>\n<p>At the time of writing, there are two ways to store agentic memory.<\/p>\n<ol>\n<li>Semantic Memory<\/li>\n<li>Kernel Memory<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>An overview of each of these follows.<\/p>\n<h2>Semantic Memory<\/h2>\n<p>Semantic memory refers to the structured storage of knowledge and concepts that the agent can reference and use. It often involves storing data in ways that allow the agent to draw insights, make connections between facts, and use this knowledge contextually in interactions.<\/p>\n<p>Within the content of Semantic Kernel, Semantic Memory is a library within the Semantic Kernel SDK. It creates a wrapper between your application and database, thereby making it easier to store and retrieve text using embeddings.<\/p>\n<p>Learn more about Semantic Memory <a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\/blob\/main\/dotnet\/samples\/Concepts\/Memory\/SemanticTextMemory_Building.cs\">here<\/a>.<\/p>\n<h2>Kernel Memory<\/h2>\n<p>Kernel Memory is a service that can run in the background.\u00a0 Remember the old ASP.NET State Server?\u00a0 You can think of it like that.\u00a0 Kernel Memory is exposed via a set of REST API endpoints that let you easily build a RAG orchestration layer for your agentic AI solution.<\/p>\n<p>Kernel Memory provides a more comprehensive memory management layer. It combines multiple types of memories (short-term, long-term, etc.) to manage context and state within your application. It provides a unified API and extensible framework for integrating different memory types.<\/p>\n<p>Learn more about Kernel Memory <a href=\"https:\/\/github.com\/microsoft\/kernel-memory\/\">here<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h2>Semantic Memory v Kernel Memory<\/h2>\n<p>At a high-level, the fundamental difference between Semantic Memory and Kernel Memory (KM) is that KM is a service that you can deploy and use whereas Semantic Memory (SM)is not really a deployable service.\u00a0 SM forms part of your Semantic Kernel solution.<\/p>\n<p>&nbsp;<\/p>\n<p>The following table contains a feature comparison between Semantic Memory and Kernel Memory.<\/p>\n<table>\n<thead>\n<tr>\n<td><strong>Feature<\/strong><\/td>\n<td><strong>Kernel Memory<\/strong><\/td>\n<td><strong>Semantic Memory<\/strong><\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Data formats<\/td>\n<td>Web pages, PDF, Images, Word, PowerPoint, Excel, Markdown, Text, JSON, HTML<\/td>\n<td>Text only<\/td>\n<\/tr>\n<tr>\n<td>Search<\/td>\n<td>Cosine similarity, Hybrid search with filters (AND\/OR conditions)<\/td>\n<td>Cosine similarity<\/td>\n<\/tr>\n<tr>\n<td>Language support<\/td>\n<td>Any language, command line tools, browser extensions, low-code\/no-code apps, chatbots, assistants, etc.<\/td>\n<td>C#, Python, Java<\/td>\n<\/tr>\n<tr>\n<td>Storage engines<\/td>\n<td><a href=\"https:\/\/azure.microsoft.com\/products\/ai-services\/ai-search\">Azure AI Search<\/a>,\u00a0<a href=\"https:\/\/www.nuget.org\/packages\/FreeMindLabs.KernelMemory.Elasticsearch\">Elasticsearch<\/a>,\u00a0<a href=\"https:\/\/www.mongodb.com\/atlas\/database\">MongoDB Atlas<\/a>,\u00a0<a href=\"https:\/\/github.com\/microsoft\/kernel-memory\/extensions\/postgres\">Postgres+pgvector<\/a>,\u00a0<a href=\"https:\/\/qdrant.tech\/\">Qdrant<\/a>,\u00a0<a href=\"https:\/\/redis.io\/\">Redis<\/a>,\u00a0<a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.KernelMemory.MemoryDb.SQLServer\/\">SQL Server<\/a>, In memory KNN, On disk KNN.<\/td>\n<td>Azure AI Search, Chroma, DuckDB, Kusto, Milvus, MongoDB, Pinecone, Postgres, Qdrant, Redis, SQLite, Weaviate<\/td>\n<\/tr>\n<tr>\n<td>File storage<\/td>\n<td>Disk,\u00a0<a href=\"https:\/\/learn.microsoft.com\/azure\/storage\/blobs\/storage-blobs-introduction\">Azure Blobs<\/a>,\u00a0<a href=\"https:\/\/aws.amazon.com\/s3\">AWS S3<\/a>,\u00a0<a href=\"https:\/\/www.mongodb.com\/atlas\/database\">MongoDB Atlas<\/a>, In memory (volatile)<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<tr>\n<td>RAG<\/td>\n<td>Yes, with sources lookup<\/td>\n<td>Yes, with additional libraries<\/td>\n<\/tr>\n<tr>\n<td>Summarization<\/td>\n<td>Yes<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<tr>\n<td>OCR<\/td>\n<td>Yes via\u00a0<a href=\"https:\/\/azure.microsoft.com\/products\/ai-services\/ai-document-intelligence\">Azure Document Intelligence<\/a><\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<tr>\n<td>Security Filters<\/td>\n<td>Yes<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<tr>\n<td>Large document ingestion<\/td>\n<td>Yes, including async processing using queues (<a href=\"https:\/\/learn.microsoft.com\/azure\/storage\/queues\/storage-queues-introduction\">Azure Queues<\/a>,\u00a0<a href=\"https:\/\/www.rabbitmq.com\/\">RabbitMQ<\/a>, File based or In memory queues)<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<tr>\n<td>Document storage<\/td>\n<td>Yes<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<tr>\n<td>Custom storage schema<\/td>\n<td>some DBs<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<tr>\n<td>Vector DBs with internal embedding<\/td>\n<td>Yes<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<tr>\n<td>Concurrent write to multiple vector DBs<\/td>\n<td>Yes<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<tr>\n<td>LLMs<\/td>\n<td><a href=\"https:\/\/learn.microsoft.com\/azure\/ai-services\/openai\/concepts\/models\">Azure OpenAI<\/a>,\u00a0<a href=\"https:\/\/platform.openai.com\/docs\/models\">OpenAI<\/a>,\u00a0<a href=\"https:\/\/www.anthropic.com\/\">Anthropic<\/a>,\u00a0<a href=\"https:\/\/ollama.com\/\">Ollama<\/a>,\u00a0<a href=\"https:\/\/github.com\/SciSharp\/LLamaSharp\">LLamaSharp<\/a>,\u00a0<a href=\"https:\/\/lmstudio.ai\/\">LM Studio<\/a>, Semantic Kernel connectors<\/td>\n<td>Azure OpenAI, OpenAI, Gemini, Hugging Face, ONNX, custom.<\/td>\n<\/tr>\n<tr>\n<td>LLMs with dedicated tokenization<\/td>\n<td>Yes<\/td>\n<td>No<\/td>\n<\/tr>\n<tr>\n<td>Cloud deployment<\/td>\n<td>Yes<\/td>\n<td>Yes, but custom. Local SLM\/LLM etc.<\/td>\n<\/tr>\n<tr>\n<td>Web service with OpenAPI<\/td>\n<td>Yes<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><em>(table from Microsoft)<\/em><\/p>\n<p style=\"text-align: center;\">~<\/p>\n<h2>Should I Use Semantic Memory or Kernel Memory<\/h2>\n<p>As always, it depends on your requirements. The comparison table (see above) will help you decide which technology to use.<\/p>\n<p>If you are looking to quickly get started and build a quick prototype, I would recommend using Semantic Memory.\u00a0 Build your foundational knowledge and create a simple agent and iterate from there.<\/p>\n<p>If you are looking to build an enterprise grade solution and implement an orchestration layer \/ pipeline than can ingest, parse, and process content for agentic AI use, or need data format, additional storage options \/ search capabilities, Kernel Memory may be a more suitable option for you.<\/p>\n<p style=\"text-align: center;\">~<\/p>\n<h2>Where Do Memories Fit in With an Existing Semantic Kernel Solution<\/h2>\n<p>A simple implementation of Semantic Memory can be written in about 100 lines of code.<\/p>\n<p>The main steps involve:<\/p>\n<ol>\n<li>Creating a new memory system.<\/li>\n<li>Choosing a text embedding model<\/li>\n<li>Choosing a memory storage mechanism (in-memory\/volatile is good for testing)<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>You can see this here:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">var memoryWithCustomDb = new MemoryBuilder()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 .WithOpenAITextEmbeddingGeneration(\"text-embedding-ada-002\", apiKey)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 .WithMemoryStore(new VolatileMemoryStore())\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 .Build();<\/pre>\n<p>&nbsp;<\/p>\n<p>Next, you must add contents to the memory store.\u00a0 You can see this being done here.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">private async Task StoreMemoryAsync(ISemanticTextMemory memory)\r\n\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0 Dictionary d = new Dictionary&lt;string, string&gt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 [\"somePage.html\"]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 = \u201csomeDesc\u201d\u201d,\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 };\r\n\r\n\u00a0\u00a0\u00a0\u00a0 var counter = 0;\r\n\r\n\u00a0\u00a0\u00a0\u00a0 foreach (var c in d)\r\n\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 await memory.SaveReferenceAsync(\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 collection: \u201cYourMemoryCollectionName\u201d,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 externalSourceName: \"SourceName\",\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 externalId: entry.Key,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 description: entry.Value,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 text: entry.Value);\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Console.Write($\" #{++i} saved.\");\r\n\u00a0\u00a0\u00a0\u00a0 }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>Note: there a 2 methods to add contents to memory.<\/p>\n<ul>\n<li>SaveReferenceAsync<\/li>\n<li>SaveInformatonAsync<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Learn more about these two methods in one of my <a href=\"https:\/\/jamiemaguire.net\/index.php\/2024\/09\/01\/semantic-kernel-implementing-100-local-rag-using-phi-3-with-local-embeddings\/\">earlier blog posts<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>With the content added to Memory, it can now be searched.\u00a0 The following code show how this can be done:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">private async Task SearchMemoryAsync(ISemanticTextMemory memory, string query)\r\n\u00a0{\r\n\r\n\u00a0\u00a0\u00a0\u00a0 var memoryResults = memory.SearchAsync(MemoryCollectionName, query, limit: 2, minRelevanceScore: 0.5);\r\n\r\n\r\n\r\n\u00a0\u00a0\u00a0\u00a0 int i = 0;\r\n\r\n\u00a0\u00a0\u00a0\u00a0 await foreach (MemoryQueryResult memoryResult in memoryResults)\r\n\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Console.WriteLine($\"Result {++i}:\");\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Console.WriteLine(\"\u00a0 URL:\u00a0\u00a0\u00a0\u00a0 : \" + memoryResult.Metadata.Id);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Console.WriteLine(\"\u00a0 Title\u00a0\u00a0\u00a0 : \" + memoryResult.Metadata.Description);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Console.WriteLine(\"\u00a0 Relevance: \" + memoryResult.Relevance);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Console.WriteLine();\r\n\u00a0\u00a0\u00a0\u00a0 }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>That\u2019s it.<\/p>\n<p style=\"text-align: center;\">~<\/p>\n<h2>Summary<\/h2>\n<p>In this blog post, we\u2019ve looked at the concept of agentic memory within Semantic Kernel.<\/p>\n<p>We examined the contents of a memory and the sort of data you might choose to store.<\/p>\n<p>We also introduced the options you currently have available for creating, searching, and integrating agentic memories within Semantic Kernel.<\/p>\n<p>In future blog posts, we will see further examples of Semantic Memory and Kernel Memory in action.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Agentic AI continues to evolve at pace.\u00a0 State management is an important aspect in most applications, and this is also the case for developing intelligent agents. &nbsp; Semantic Kernel has the concept of a memory&#8230;.<\/p>\n","protected":false},"author":1,"featured_media":3975,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[126,81,121],"tags":[],"class_list":["post-3974","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-agentic-ai","category-ai","category-semantic-kernel"],"_links":{"self":[{"href":"https:\/\/jamiemaguire.net\/index.php\/wp-json\/wp\/v2\/posts\/3974","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jamiemaguire.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jamiemaguire.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jamiemaguire.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jamiemaguire.net\/index.php\/wp-json\/wp\/v2\/comments?post=3974"}],"version-history":[{"count":0,"href":"https:\/\/jamiemaguire.net\/index.php\/wp-json\/wp\/v2\/posts\/3974\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jamiemaguire.net\/index.php\/wp-json\/wp\/v2\/media\/3975"}],"wp:attachment":[{"href":"https:\/\/jamiemaguire.net\/index.php\/wp-json\/wp\/v2\/media?parent=3974"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jamiemaguire.net\/index.php\/wp-json\/wp\/v2\/categories?post=3974"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jamiemaguire.net\/index.php\/wp-json\/wp\/v2\/tags?post=3974"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}