{"id":2627,"date":"2024-05-10T13:44:20","date_gmt":"2024-05-10T20:44:20","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/semantic-kernel\/?p=2627"},"modified":"2024-05-10T13:44:20","modified_gmt":"2024-05-10T20:44:20","slug":"making-ai-powered-net-apps-more-consistent-and-intelligent-with-redis","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/agent-framework\/making-ai-powered-net-apps-more-consistent-and-intelligent-with-redis\/","title":{"rendered":"Making AI powered .NET apps more consistent and intelligent with Redis"},"content":{"rendered":"<p><span data-contrast=\"auto\">Hi everyone!<\/span><span data-ccp-props=\"{}\">\u00a0<\/span><\/p>\n<p>Today we\u2019re featuring a guest author from another team in Microsoft on our Semantic Kernel blog. Today\u2019s topic will cover how to use Azure Cache for Redis, which is an in-memory datastore that allows you to further expand the performance and scalability of your applications that are using AzureOpenAI. We will turn it over to Catherine Wang to dive into Making AI powered .NET apps more consistent and intelligent with Redis.<\/p>\n<p><a href=\"https:\/\/redis.com\/\" target=\"_blank\" rel=\"noopener\">Redis<\/a>\u00a0is a popular in-memory datastore that can be used to solve critical challenges for building and scaling intelligent applications. In this post, you will learn how Azure Cache for Redis can be used to improve the effectiveness of applications using Azure OpenAI.<\/p>\n<p>Azure cache for Redis is unaffected by the\u00a0<a href=\"https:\/\/azure.microsoft.com\/blog\/redis-license-update-what-you-need-to-know\/\" target=\"_blank\" rel=\"noopener\">recent Redis license updates<\/a>:<\/p>\n<blockquote><p>\u201cOur ongoing collaboration ensures that Azure customers can seamlessly utilize all tiers of Azure Cache for Redis. There will be no interruption to Azure Cache for Redis, Azure Cache for Redis Enterprise, and Enterprise Flash services and customers will receive timely updates and bug fixes to maintain optimal performance.\u201d \u2013 Julia Liuson, President, Developer Division<\/p><\/blockquote>\n<p>This blog includes two sample applications:<\/p>\n<p>The first is a\u00a0<a href=\"https:\/\/learn.microsoft.com\/semantic-kernel\/overview\/\" target=\"_blank\" rel=\"noopener\">Semantic Kernel<\/a>\u00a0demo chat application based on\u00a0<a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/demystifying-retrieval-augmented-generation-with-dotnet\/\">Demystifying Retrieval Augmented Generation with .NET<\/a>. I added features that use Redis for saving additional knowledge and enabling memories on chat history. The full sample is at\u00a0<a href=\"https:\/\/github.com\/CawaMS\/chatappredis\" target=\"_blank\" rel=\"noopener\">Chat App with Redis<\/a><\/p>\n<p>The second is a demo application that features\u00a0<a href=\"https:\/\/learn.microsoft.com\/aspnet\/core\/performance\/caching\/output?view=aspnetcore-8.0#redis-cache\" target=\"_blank\" rel=\"noopener\">Redis Output Caching<\/a>\u00a0in .NET 8 with\u00a0<a href=\"https:\/\/github.com\/redis\/redis-om-dotnet\" target=\"_blank\" rel=\"noopener\">Redis OM dotnet<\/a>\u00a0to improve consistency and resiliency with generative AI. The full sample is at\u00a0<a href=\"https:\/\/github.com\/CawaMS\/OutputCacheOpenAI\/tree\/main\" target=\"_blank\" rel=\"noopener\">Output Cache with OpenAI<\/a><\/p>\n<h2>Redis Gives OpenAI models Additional Knowledge<button class=\"linkicon\" title=\"\" aria-label=\"Copy Post URL\" data-id-href=\"https:\/\/devblogs.microsoft.com\/dotnet\/redis-makes-intelligent-apps-smarter-and-consistent\/#redis-gives-openai-models-additional-knowledge\" data-toggle=\"tooltip\" data-placement=\"right\" data-original-title=\"Copy Post URL\"><i class=\"fabric-icon fabric-icon--Link\"><\/i><\/button><\/h2>\n<p>OpenAI models like GPT are trained and knowledgeable in most scenarios, but there is no way for them to know your company\u2019s internal documentation or a very recent blog post. That\u2019s why you need Redis to be a semantic memory store for the additional knowledge.<\/p>\n<p>There are two basic requirements for a semantic memory store:<\/p>\n<ol>\n<li>Intelligent apps cannot directly read unstructured data like text blobs, images, videos, etc. The semantic memory store needs to support saving vector embeddings efficiently.<\/li>\n<li>Intelligent apps need to perform tasks like summarization, comparison, anomaly detection, etc. The semantic memory store needs to support search capabilities. This means indexing, distance algorithms, and search queries for finding relevant data.<\/li>\n<\/ol>\n<p>Redis Enterprise provides the\u00a0<a href=\"https:\/\/redis.io\/docs\/interact\/search-and-query\/advanced-concepts\/vectors\/\" target=\"_blank\" rel=\"noopener\">RediSearch<\/a>\u00a0module to meet these requirements. You can save vector embeddings in Redis with built-in FLAT and HNSW indexing algorithms, distance algorithms like COSINE, and KNN search queries.<\/p>\n<p><a href=\"https:\/\/learn.microsoft.com\/semantic-kernel\/memories\/\" target=\"_blank\" rel=\"noopener\">Semantic Kernel<\/a>\u00a0offers a\u00a0<a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\/blob\/main\/dotnet\/src\/Connectors\/Connectors.Memory.Redis\/README.md\" target=\"_blank\" rel=\"noopener\">connector for Redis semantic memory store<\/a>. The code for using Redis as semantic memory store in Semantic Kernel might look like the following (from\u00a0<a href=\"https:\/\/github.com\/CawaMS\/chatappredis\/blob\/main\/Program.cs\" target=\"_blank\" rel=\"noopener\">ChatAppRedis<\/a>):<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">\/\/Initialize the Redis connection\r\nConnectionMultiplexer connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(redisConnection);\r\nIDatabase database = connectionMultiplexer.GetDatabase();\r\n\r\n\/\/Create and use Redis semantic memory store\r\nRedisMemoryStore memoryStore = new RedisMemoryStore(database, vectorSize: 1536);\r\nvar memory = new SemanticTextMemory(\r\n    memoryStore,\r\n    new AzureOpenAITextEmbeddingGenerationService(aoaiEmbeddingModel, aoaiEndpoint, aoaiApiKey)\r\n    );\r\n\r\n\/\/Code for saving text strings into Redis Semantic Store\r\nawait memory.SaveInformationAsync(collectionName, $\"{your_text_blob}\", $\"{an_arbitrary_key}\");<\/code><\/pre>\n<h2>Redis Persists Chat History to Enable AI Memories<button class=\"linkicon\" title=\"\" aria-label=\"Copy Post URL\" data-id-href=\"https:\/\/devblogs.microsoft.com\/dotnet\/redis-makes-intelligent-apps-smarter-and-consistent\/#redis-persists-chat-history-to-enable-ai-memories\" data-toggle=\"tooltip\" data-placement=\"right\" data-original-title=\"Copy Post URL\"><i class=\"fabric-icon fabric-icon--Link\"><\/i><\/button><\/h2>\n<p>OpenAI models like GPT do not remember chat history. Semantic Kernel provides\u00a0<a href=\"https:\/\/learn.microsoft.com\/dotnet\/api\/microsoft.semantickernel.chatcompletion.chathistory?view=semantic-kernel-dotnet\" target=\"_blank\" rel=\"noopener\">Chat History<\/a>\u00a0for answering questions based on previous context. For example, you can ask the chat application to tell a joke. Then ask why the joke is funny. The answer to the second question will be related to the first, which is what Chat History enables.<\/p>\n<p>The Chat History object is stored in memory. Customers have asked to save it to an external store, for the following benefits:<\/p>\n<ul>\n<li><strong>Resource efficiency<\/strong>\u00a0\u2013 Memory is a scarce resource in the application server.<\/li>\n<li><strong>Application resiliency<\/strong>\u00a0\u2013 During server failover, we want to avoid in-memory data being lost and experiencing glitches.<\/li>\n<\/ul>\n<p>Redis is an ideal choice for saving Chat History, because:<\/p>\n<ul>\n<li><strong>Data expiration support<\/strong>\u00a0\u2013 The application can set expiration time on Chat History to keep its memory fresh.<\/li>\n<li><strong>Data structure<\/strong>\u00a0\u2013 Redis supports built-in data structures like Hash to easily query for related messages.<\/li>\n<li><strong>Resiliency<\/strong>\u00a0\u2013 If a session is interrupted due to a server failover, the chat can continue.<\/li>\n<\/ul>\n<p>Here is an example conversation. Without chat history persisted in Redis, I can\u2019t ask questions based on previous context.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/no-chat-history.png\"><img decoding=\"async\" class=\"alignnone wp-image-2632 size-full\" src=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/no-chat-history.png\" alt=\"Image no chat history\" width=\"1728\" height=\"308\" srcset=\"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/no-chat-history.png 1728w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/no-chat-history-300x53.png 300w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/no-chat-history-1024x183.png 1024w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/no-chat-history-768x137.png 768w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/no-chat-history-1536x274.png 1536w\" sizes=\"(max-width: 1728px) 100vw, 1728px\" \/><\/a><\/p>\n<p>With Chat History in Redis, I can continue the previous conversation as I start a new session.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/with-chat-history-in-redis.png\"><img decoding=\"async\" class=\"alignnone wp-image-2631 size-full\" src=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/with-chat-history-in-redis.png\" alt=\"Image with chat history in redis\" width=\"2944\" height=\"576\" srcset=\"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/with-chat-history-in-redis.png 2944w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/with-chat-history-in-redis-300x59.png 300w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/with-chat-history-in-redis-1024x200.png 1024w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/with-chat-history-in-redis-768x150.png 768w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/with-chat-history-in-redis-1536x301.png 1536w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/with-chat-history-in-redis-2048x401.png 2048w\" sizes=\"(max-width: 2944px) 100vw, 2944px\" \/><\/a><\/p>\n<p>The code for fetching user messages from Redis to a ChatHistory object might look like the following:<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">RedisValue[] userMsgList = await _redisConnection.BasicRetryAsync(\r\n    async(db) =&gt;(await db.HashValuesAsync(_userName + \":\" + userMessageSet)));\r\n\r\nif (userMsgList.Any()) {\r\n  foreach (var userMsg in userMsgList) {\r\n    chat.AddUserMessage(userMsg.ToString());\r\n  }\r\n}<\/code><\/pre>\n<p>The code for saving user messages to Redis might look like the following:<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">chat.AddUserMessage(question);\r\n\r\nawait _redisConnection.BasicRetryAsync(\r\n    async(_db) =&gt; _db.HashSetAsync($\"{_userName}:{userMessageSet}\", [\r\n      new HashEntry(new RedisValue(Utility.GetTimestamp()), question)\r\n    ]));\r\n<\/code><\/pre>\n<p>Redis Hash is used for user messages and assistant messages for each user.\u00a0<a href=\"https:\/\/redis.com\/redis-enterprise\/redis-insight\/\" target=\"_blank\" rel=\"noopener\">Redis Insight<\/a>\u00a0provides UI to view and manage saved Chat History data.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/saved-user-messages.png\"><img decoding=\"async\" class=\"alignnone wp-image-2638 size-full\" src=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/saved-user-messages.png\" alt=\"Image saved user messages\" width=\"1359\" height=\"694\" srcset=\"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/saved-user-messages.png 1359w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/saved-user-messages-300x153.png 300w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/saved-user-messages-1024x523.png 1024w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/saved-user-messages-768x392.png 768w\" sizes=\"(max-width: 1359px) 100vw, 1359px\" \/><\/a><\/p>\n<p>We can take this Chat History experience even further to convert it to vector embeddings to add consistency and relevancy for answering similar questions. The benefits are:<\/p>\n<ul>\n<li>Consistent answers to slightly different questions<\/li>\n<li>Cost saving by reduced API calls into OpenAI<\/li>\n<\/ul>\n<p>Using the\u00a0<a href=\"https:\/\/github.com\/CawaMS\/chatappredis\" target=\"_blank\" rel=\"noopener\">Chat App with Redis<\/a>\u00a0as a reference, the code for saving previous chat history in a Redis semantic memory store might look like the following:<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">\/\/Store user and assistant messages as vector embeddings in Redis. Only the previous session is saved.\r\nif (_historyContent.Length &gt; 0)\r\n{\r\n    await memory.SaveInformationAsync(_userName+\"_chathistory\", _historyContent, \"lastsession\");\r\n}<\/code><\/pre>\n<p>The code for searching previous chat history might look like the following:<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\"> await foreach (var result in memory.SearchAsync(_userName+\"_chathistory\", question, limit: 1))\r\n        stbuilder.Append(result.Metadata.Text);<\/code><\/pre>\n<p>I receive consistent responses on similar questions. i.e. \u201cWhere is French capital city?\u201d and \u201cWhere is the French capital city?\u201d<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/semantic-chathistory_redis.png\"><img decoding=\"async\" class=\"alignnone wp-image-2633 size-large\" src=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/semantic-chathistory_redis-1024x812.png\" alt=\"Image semantic chathistory redis\" width=\"640\" height=\"508\" srcset=\"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/semantic-chathistory_redis-1024x812.png 1024w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/semantic-chathistory_redis-300x238.png 300w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/semantic-chathistory_redis-768x609.png 768w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/semantic-chathistory_redis-1536x1217.png 1536w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/semantic-chathistory_redis.png 1596w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>My experimental code has limitations:<\/p>\n<ul>\n<li>It only saves history for the last chat session<\/li>\n<li>It does not divide the large history object into chunks based on logical grouping<\/li>\n<li>The code is messyThat\u2019s why we are adding official support for this experience in Semantic Kernel, see\u00a0<a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\/issues\/5436\" target=\"_blank\" rel=\"noopener\">microsoft\/semantic-kernel #5436<\/a>. Please share your feedback on the issue to help us design a great experience.<\/li>\n<\/ul>\n<h2>Redis Improves Web Application Performance<button class=\"linkicon\" title=\"\" aria-label=\"Copy Post URL\" data-id-href=\"https:\/\/devblogs.microsoft.com\/dotnet\/redis-makes-intelligent-apps-smarter-and-consistent\/#redis-improves-web-application-performance\" data-toggle=\"tooltip\" data-placement=\"right\" data-original-title=\"Copy Post URL\"><i class=\"fabric-icon fabric-icon--Link\"><\/i><\/button><\/h2>\n<p>.NET provides several caching abstractions to improve web application performance. These are still applicable with your overall intelligent applications. In addition, the caching abstractions complement semantic caching to provide performant and consistent web responses.<\/p>\n<h3>Web Page Output Caching<button class=\"linkicon\" title=\"\" aria-label=\"Copy Post URL\" data-id-href=\"https:\/\/devblogs.microsoft.com\/dotnet\/redis-makes-intelligent-apps-smarter-and-consistent\/#web-page-output-caching\" data-toggle=\"tooltip\" data-placement=\"right\" data-original-title=\"Copy Post URL\"><i class=\"fabric-icon fabric-icon--Link\"><\/i><\/button><\/h3>\n<p>Repeated web requests with the same parameters introduce unnecessary server utilization and dependency calls. In .NET 8, we introduced\u00a0<a href=\"https:\/\/learn.microsoft.com\/aspnet\/core\/performance\/caching\/output?view=aspnetcore-8.0#redis-cache\" target=\"_blank\" rel=\"noopener\">Redis Output Caching<\/a>\u00a0to improve a web application in the following aspects:<\/p>\n<ul>\n<li><strong>Consistency<\/strong>\u00a0\u2013 Output Caching ensures the same requests get consistent responses.<\/li>\n<li><strong>Performance<\/strong>\u00a0\u2013 Output Caching avoids repeated dependency calls into datastores or APIs, which accelerate overall web response time.<\/li>\n<li><strong>Resource efficiency<\/strong>\u00a0\u2013 Output Caching reduces CPU utilization to render webpages.<\/li>\n<\/ul>\n<p>Here is the earlier mentioned sample application for using Redis Output Caching to improve the performance calling into DALL-E to generate images based on a prompt.\u00a0<a href=\"https:\/\/github.com\/CawaMS\/OutputCacheOpenAI\" target=\"_blank\" rel=\"noopener\">Output Caching with OpenAI Image Generation<\/a>. It takes minimal coding to use Output Caching.<\/p>\n<p>The code snippet for using .NET 8 Redis output cache might look like the following:<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">app.MapGet(\"\/cached\/{prompt}\", async (HttpContext context, string prompt, IConfiguration config) =&gt; \r\n    { await GenerateImage.GenerateImageAsync(context, prompt, config); \r\n    }).CacheOutput();\r\n<\/code><\/pre>\n<h3>Adding Semantic Caching to Ensure Similar Prompts Receive Consistent Response<button class=\"linkicon\" title=\"\" aria-label=\"Copy Post URL\" data-id-href=\"https:\/\/devblogs.microsoft.com\/dotnet\/redis-makes-intelligent-apps-smarter-and-consistent\/#adding-semantic-caching-to-ensure-similar-prompts-receive-consistent-response\" data-toggle=\"tooltip\" data-placement=\"right\" data-original-title=\"Copy Post URL\"><i class=\"fabric-icon fabric-icon--Link\"><\/i><\/button><\/h3>\n<p><a href=\"https:\/\/github.com\/redis\/redis-om-dotnet\/tree\/main\" target=\"_blank\" rel=\"noopener\">Redis OM for dotnet<\/a>\u00a0just released Semantic Caching feature. It supports using Azure OpenAI embeddings to generate vectors. The following code snippet shows example usage. A full code sample can be found at\u00a0<a href=\"https:\/\/github.com\/CawaMS\/OutputCacheOpenAI\/blob\/main\/OutputCacheDallESample\/GenerateImageSC.cs\" target=\"_blank\" rel=\"noopener\">GenerateImageSC.cs in the OutputCacheOpenAI repo<\/a><\/p>\n<p>The code snippet for using Redis as semantic cache might look like the following:<\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">_provider = new RedisConnectionProvider(_config[\"SemanticCacheAzureProvider\"]);\r\nvar cache = _provider.AzureOpenAISemanticCache(\r\n    _config[\"apiKey\"], _config[\"AOAIResourceName\"],\r\n    _config[\"AOAIEmbeddingDeploymentName\"], 1536);\r\n\r\nif (cache.GetSimilar(_prompt).Length &gt; 0) {\r\n  imageURL = cache.GetSimilar(_prompt)[0];\r\n  await context.Response.WriteAsync(\r\n      \"&lt;!DOCTYPE html&gt;&lt;html&gt;&lt;body&gt; \" +\r\n      $\"&lt;img src=\\\"{imageURL}\\\" alt=\\\"AI Generated Picture {_prompt}\\\" width=\\\"460\\\" height=\\\"345\\\"&gt;\" +\r\n      \" &lt;\/body&gt; &lt;\/html&gt;\");\r\n}<\/code><\/pre>\n<p>This way, I can ensure that similar prompts from various users result in the same images for improved consistency and reduced API calls, thus reducing calls into DALL-E and improving the performance. The following screenshots demonstrate the same picture reused for similar prompts.<\/p>\n<p>This is the image returned from prompt \u201ca french garden in monet style\u201d.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_a-french-garden-in-monet-style_resized.png\"><img decoding=\"async\" class=\"alignnone wp-image-2630 size-full\" src=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_a-french-garden-in-monet-style_resized.png\" alt=\"Image sc a french garden in monet style resized\" width=\"542\" height=\"237\" srcset=\"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_a-french-garden-in-monet-style_resized.png 542w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_a-french-garden-in-monet-style_resized-300x131.png 300w\" sizes=\"(max-width: 542px) 100vw, 542px\" \/><\/a><\/p>\n<p>This is the image returned from prompt \u201ca monet style french garden\u201d. It is the same as above because previous entry has been semantically cached:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_a-monet-style-french-garden_resized.png\"><img decoding=\"async\" class=\"alignnone wp-image-2629 size-full\" src=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_a-monet-style-french-garden_resized.png\" alt=\"Image sc a monet style french garden resized\" width=\"550\" height=\"246\" srcset=\"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_a-monet-style-french-garden_resized.png 550w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_a-monet-style-french-garden_resized-300x134.png 300w\" sizes=\"(max-width: 550px) 100vw, 550px\" \/><\/a><\/p>\n<p>This is the entry in Redis semantic cache:<\/p>\n<h2><a href=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_one-entry-in-semantic-cache.png\"><img decoding=\"async\" class=\"alignnone wp-image-2628 size-full\" src=\"https:\/\/devblogs.microsoft.com\/semantic-kernel\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_one-entry-in-semantic-cache.png\" alt=\"Image sc one entry in semantic cache\" width=\"2849\" height=\"812\" srcset=\"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_one-entry-in-semantic-cache.png 2849w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_one-entry-in-semantic-cache-300x86.png 300w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_one-entry-in-semantic-cache-1024x292.png 1024w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_one-entry-in-semantic-cache-768x219.png 768w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_one-entry-in-semantic-cache-1536x438.png 1536w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2024\/05\/sc_one-entry-in-semantic-cache-2048x584.png 2048w\" sizes=\"(max-width: 2849px) 100vw, 2849px\" \/><\/a><\/h2>\n<p>The Redis Semantic Cache is complementary to Redis Output Cache because:<\/p>\n<ul>\n<li>Semantic Cache further reduces the API dependency calls to improve performance and cost.<\/li>\n<li>Output Cache reduces the CPU utilization for rendering web pages.<\/li>\n<\/ul>\n<p>In conclusion, Redis can be an key part of a solution and design for performant, consistent, and cost-efficient intelligent web applications.<\/p>\n<h2>Next Steps<\/h2>\n<p>The recently GA-ed Enterprise E5 SKU is cost-efficient for experimenting with the\u00a0<a href=\"https:\/\/redis.io\/docs\/interact\/search-and-query\/advanced-concepts\/vectors\/\" target=\"_blank\" rel=\"noopener\">RediSearch<\/a>\u00a0module. Check out\u00a0<a href=\"https:\/\/azure.microsoft.com\/products\/cache\/\" target=\"_blank\" rel=\"noopener\">Azure Cache for Redis<\/a>.<\/p>\n<p>Try out Redis in your intelligent application today! Leave feedback on your thoughts on these scenarios by commenting in the blog post \u2013 we would love to hear from you!<\/p>\n<p>From the Semantic Kernel team, we want to thank Catherine for her time. We\u2019re always interested in hearing from you. If you have feedback, questions or want to discuss further, feel free to reach out to us and the community on the <a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\/discussions\/categories\/general\" target=\"_blank\" rel=\"noopener\">Semantic Kernel GitHub Discussion Channel<\/a>! We would also love your support, if you\u2019ve enjoyed using Semantic Kernel, give us a star on\u00a0<a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\" target=\"_blank\" rel=\"noopener\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hi everyone!\u00a0 Today we\u2019re featuring a guest author from another team in Microsoft on our Semantic Kernel blog. Today\u2019s topic will cover how to use Azure Cache for Redis, which is an in-memory datastore that allows you to further expand the performance and scalability of your applications that are using AzureOpenAI. We will turn it [&hellip;]<\/p>\n","protected":false},"author":149071,"featured_media":2302,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[48,73,63,74,9],"class_list":["post-2627","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-semantic-kernel","tag-ai","tag-azure-redis","tag-microsoft-semantic-kernel","tag-redis","tag-semantic-kernel"],"acf":[],"blog_post_summary":"<p>Hi everyone!\u00a0 Today we\u2019re featuring a guest author from another team in Microsoft on our Semantic Kernel blog. Today\u2019s topic will cover how to use Azure Cache for Redis, which is an in-memory datastore that allows you to further expand the performance and scalability of your applications that are using AzureOpenAI. We will turn it [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/2627","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/users\/149071"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/comments?post=2627"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/2627\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media\/2302"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media?parent=2627"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/categories?post=2627"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/tags?post=2627"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}