技术速递|利用 Redis 使 AI 驱动的 .NET 应用程序更加一致和智能

作者:Catherine Wang
排版:Alan Wang

Redis 是一种流行的内存数据存储,可用于解决构建和扩展智能应用程序的关键挑战。在本文中,你将了解如何使用 Redis 的 Azure 缓存来提高使用 Azure OpenAI 的应用程序的效率。

Redis 的 Azure 缓存不受最近的 Redis 许可证更新的影响:

“我们将持续的合作以确保 Azure 客户能够无缝地利用 Azure Cache for Redis 的所有层级。Azure Cache
for Redis、Azure Cache for Redis Enterprise 和 Enterprise Flash
服务不会中断,客户将收到及时的更新和错误修复,以保持最佳性能。” – Julia Liuson,开发部总裁

本博客包括两个示例应用程序:

第一个是基于 .NET 揭秘检索增强生成的演示聊天 Semantic Kernel 应用程序。我添加了使用 Redis 保存额外知识并启用聊天历史记录的功能。完整示例位于 Chat App with Redis。
第二个是一个演示应用程序,它在 .NET 8 中使用 Redis OM dotnet 进行 Redis 输出缓存,以提高生成式 AI 的一致性和弹性。完整示例位于 OpenAI 的输出缓存中。

Redis 为 OpenAI 模型提供了额外的知识

像 GPT 这样的 OpenAI 模型在大多数情况下都经过训练且知识渊博,但它们无法了解您公司的内部文档或最近的博客文章。这就是为什么您需要 Redis 作为附加知识的语义内存存储。

语义内存存储有两个基本要求:

  1. 智能应用程序无法直接读取文本 blob、图像、视频等非结构化数据。语义内存存储需要支持向量嵌入的有效保存。
  2. 智能应用程序需要执行总结、比较、异常检测等任务。语义内存存储需要支持搜索功能。这意味着用于查找相关数据的索引、距离算法和搜索查询。

Redis Enterprise 提供了 RediSearch 模块来满足这些需求。您可以使用内置的 FLAT 和 HNSW 索引算法、余弦等距离算法以及 KNN 搜索查询在 Redis 中保存向量嵌入。

Semantic Kernel 为 Redis 语义内存存储提供了一个 连接器。在语义内核中使用 Redis 作为语义内存存储的代码可能如下所示(来自 ChatAppRedis):

//初始化Redis连接
ConnectionMultiplexer connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(redisConnection);
IDatabase database = connectionMultiplexer.GetDatabase();//创建和使用Redis语义内存存储
RedisMemoryStore memoryStore = new RedisMemoryStore(database, vectorSize: 1536);
var memory = new SemanticTextMemory(memoryStore,new AzureOpenAITextEmbeddingGenerationService(aoaiEmbeddingModel, aoaiEndpoint, aoaiApiKey));//将文本字符串保存到 Redis 语义存储中的代码
await memory.SaveInformationAsync(collectionName, $"{your_text_blob}", $"{an_arbitrary_key}");

Redis 保留聊天记录以启用 AI 记忆

像 GPT 这样的 OpenAI 模型不会记住聊天记录。Semantic Kernel 提供聊天记录,以回答基于先前上下文的问题。例如,您可以要求聊天应用程序讲一个笑话。然后问为什么这个笑话好笑。第二个问题的答案将与第一个问题相关,这就是聊天记录所启用的功能。

Chat History 对象存储在内存中。客户要求将其保存到外部存储,以获得以下好处:

  • 资源效率——内存是应用服务器中的稀缺资源。
  • 应用程序弹性——在服务器故障转移期间,我们希望避免内存中的数据丢失和出现故障。

Redis 是保存聊天记录的理想选择,因为:

  • 数据过期支持 - 应用程序可以设置聊天记录的过期时间,以保持其记忆犹新。
  • 数据结构——Redis 支持 Hash 等内置数据结构,可以轻松查询相关消息。
  • 弹性 – 如果会话由于服务器故障转移而中断,聊天可以继续。

下面是一个对话示例。如果没有在 Redis 中保留聊天记录,我就无法根据之前的上下文提出问题。
在这里插入图片描述
借助 Redis 中的聊天记录,我可以在开始新会话时继续之前的对话。
在这里插入图片描述
从 Redis 获取用户消息并转到 ChatHistory 对象的代码可能如下所示:

RedisValue[] userMsgList = await _redisConnection.BasicRetryAsync(async(db) =>(await db.HashValuesAsync(_userName + ":" + userMessageSet)));if (userMsgList.Any()) {foreach (var userMsg in userMsgList) {chat.AddUserMessage(userMsg.ToString());}
}

将用户消息保存到 Redis 的代码可能如下所示:

chat.AddUserMessage(question);await _redisConnection.BasicRetryAsync(async(_db) => _db.HashSetAsync($"{_userName}:{userMessageSet}", [new HashEntry(new RedisValue(Utility.GetTimestamp()), question)]));

Redis Hash 用于每个用户的用户消息和辅助消息。Redis Insight 提供 UI 来查看和管理保存的聊天记录数据。
在这里插入图片描述
我们可以进一步利用这种聊天记录体验,将其转换为向量嵌入,以提高回答类似问题的一致性和相关性。好处是:

  • 对略有不同的问题给出一致的答案
  • 通过减少对 OpenAI 的 API 调用来节省成本

把带有 Redis 的聊天应用程序作为参考,将以前的聊天记录保存在 Redis 语义内存存储中的代码可能如下所示:

//将用户和助理消息作为向量嵌入存储在 Redis 中。 仅保存前一个会话。
if (_historyContent.Length > 0)
{await memory.SaveInformationAsync(_userName+"_chathistory", _historyContent, "lastsession");
}

用于搜索以前的聊天记录的代码可能如下所示:

await foreach (var result in memory.SearchAsync(_userName+"_chathistory", question, limit: 1))stbuilder.Append(result.Metadata.Text);

我收到了关于类似问题的一致答复。即“法国首都在哪里?” 和“哪里是法国首都?”
在这里插入图片描述
我的实验代码有局限性:

  • 它只保存最后一次聊天会话的历史记录
  • 它不会根据逻辑分组将大型历史对象划分为块
  • 代码很乱

这就是我们在语义内核中添加对此体验的官方支持的原因,请参阅 microsoft/semantic-kernel #5436。请分享您对此问题的反馈,以帮助我们设计出色的体验。

Redis 提高 Web 应用程序性能

.NET 提供了多种缓存抽象来提高 Web 应用程序性能。这些仍然适用于您的整体智能应用。 此外,缓存抽象与语义缓存相辅相成,以提供高性能且一致的 Web 响应。

网页输出缓存

使用相同参数的重复 Web 请求会引入不必要的服务器利用率和依赖项调用。在 .NET 8 中,我们引入了 Redis 输出缓存来改进以下领域的 Web 应用程序:

  • 一致性——输出缓存确保相同的请求得到一致的响应。
  • 性能 – 输出缓存避免了对数据存储或 API 的重复依赖调用,从而加快了整体 Web 响应时间。
  • 资源效率 – 输出缓存可降低渲染网页时的 CPU 利用率。

下面是前面提到的示例应用程序,它使用 Redis 输出缓存来提高调用 DALL-E 以根据提示生成图像的性能。使用 OpenAI 图像生成进行输出缓存。使用输出缓存所需最少的编码。

使用 .NET 8 Redis 输出缓存的代码片段可能如下所示:

app.MapGet("/cached/{prompt}", async (HttpContext context, string prompt, IConfiguration config) => { await GenerateImage.GenerateImageAsync(context, prompt, config); }).CacheOutput();

添加语义缓存以确保类似的提示收到一致的响应

Redis OM for dotnet 刚刚发布了语义缓存功能。它支持使用 Azure OpenAI 嵌入来生成向量。 以下代码片段显示了示例用法。完整的代码示例可以在 OutputCacheOpenAI 存储库中的 GenerateImageSC.cs 中找到。

使用 Redis 作为语义缓存的代码片段可能如下所示:

_provider = new RedisConnectionProvider(_config["SemanticCacheAzureProvider"]);
var cache = _provider.AzureOpenAISemanticCache(_config["apiKey"], _config["AOAIResourceName"],_config["AOAIEmbeddingDeploymentName"], 1536);if (cache.GetSimilar(_prompt).Length > 0) {imageURL = cache.GetSimilar(_prompt)[0];await context.Response.WriteAsync("<!DOCTYPE html><html><body> " +$"<img src=\"{imageURL}\" alt=\"AI Generated Picture {_prompt}\" width=\"460\" height=\"345\">" +" </body> </html>");
}

这样,我就可以确保来自不同用户的类似提示会产生相同的图像,从而提高一致性并减少 API 调用,从而减少对 DALL-E 的调用并提高性能。下面的屏幕截图演示了类似提示重复使用的相同图片。

这是从提示“a french garden in monet style””返回的图像。
在这里插入图片描述
这是从提示“a monet style french garden”返回的图像。它与上面相同,因为先前的条目已被语义缓存:
在这里插入图片描述
这是 Redis 语义缓存中的条目:
在这里插入图片描述
Redis 语义缓存是 Redis 输出缓存的补充,因为:

  • 语义缓存进一步减少了 API 依赖调用,从而提高性能和降低成本。
  • 输出缓存可降低渲染网页时的 CPU 利用率。

总之,Redis 可以成为高性能、一致且低成本的智能 Web 应用程序解决方案和设计的关键部分。

下一步计划

最近发布的 Enterprise E5 SKU 对于试验 RediSearch 模块来说具有成本效益。请查看用于 Redis 的 Azure 缓存。

今天就可以在您的智能应用程序中试用 Redis!通过在博文中发表评论,分享您对这些场景的想法和反馈 - 我们很乐意听取您的意见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/829729.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

西电超算使用方法-简易版

一、引言 西电超算不错&#xff0c;我很喜欢。本文仅供自己学习使用。 二、环境搭建 搭建环境需要有一些依赖库&#xff0c;但是其实西电超算说明手册并没有写的非常清楚。因此&#xff0c;这次实战演示一下&#xff0c;写一个运行sh文件脚本并提交作业。 1、选择GPU还是CP…

AI赋能分层模式,解构未来,智领风潮

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自热榜文章&#x1f525;&#xff1a;探索设计模式的魅力&#xff1a;AI赋能分…

人脸识别概念解析

目录 1. 概述 2. 人脸检测 3. 人脸跟踪 4. 质量评价 5. 活体检测 6. 特征提取 7. 人脸验证 8. 人脸辨识 1. 概述 人脸识别在我们的生活中随处可见&#xff0c;例如在大楼门禁系统中&#xff0c;它取代了传统的门禁卡或密码&#xff0c;提高了进出的便捷性和安全性。在商…

【Linux】基础指令

文章目录 基础指令1. pwd 指令2. cd 指令3. ls 指令4. touch 指令5. mkdir 指令6. rmdir 和 rm 指令7. man 指令8. cp 指令9. mv 指令10. cat 指令11. more 和 less 指令12. head 和 tail 指令13. date 指令14. cal 指令15. find 指令16. grep 指令18. zip 和 unzip 指令19. ta…

Jenkins - macOS 上安装

文章目录 关于 JenkinsmacOS 上安装 Jenkins方式一&#xff1a;brew方式二&#xff1a;tomcat Jenkins war 关于 Jenkins 官网上下载Jenkins并将其安装到持续集成服务器 https://jenkins.io/download/ macOS 上安装 Jenkins 现在本 macOS 上测试 https://www.jenkins.io/do…

[蓝桥杯2024]-PWN:fd解析(命令符转义,标准输出重定向)

查看保护 查看ida 这里有一次栈溢出&#xff0c;并且题目给了我们system函数。 这里的知识点没有那么复杂 完整exp&#xff1a; from pwn import* pprocess(./pwn) pop_rdi0x400933 info0x601090 system0x400778payloadb"ca\\t flag 1>&2" print(len(paylo…

消息服务应用1——java项目使用websocket

在当前微服务项目中&#xff0c;由于业务模块众多&#xff0c;消息服务的使用场景变得异常活跃。而WebSocket由于其自身的可靠性强&#xff0c;实时性好&#xff0c;带宽占用更小的优势&#xff0c;在实时通讯应用场景中独占鳌头&#xff0c;加上HTML5标准的普及流行&#xff0…

分类神经网络3:DenseNet模型复现

目录 DenseNet网络架构 DenseNet部分实现代码 DenseNet网络架构 论文原址&#xff1a;https://arxiv.org/pdf/1608.06993.pdf 稠密连接神经网络&#xff08;DenseNet&#xff09;实质上是ResNet的进阶模型&#xff08;了解ResNet模型请点击&#xff09;&#xff0c;二者均是…

Java面试八股文-2024

面试指南 TMD&#xff0c;一个后端为什么要了解那么多的知识&#xff0c;真是服了。啥啥都得了解 MySQL MySQL索引可能在以下几种情况下失效&#xff1a; 不遵循最左匹配原则&#xff1a;在联合索引中&#xff0c;如果没有使用索引的最左前缀&#xff0c;即查询条件中没有包含…

Altera FPGA 配置flash读写

目录 一、读写控制器的配置 二、生成flash的配置文件 三、关于三种配置文件的大小 四、其他 一、读写控制器的配置 Altera ASMI Parallel&#xff08;下文简称ASMI)这个IP就仅仅是个Flash读写控制器&#xff0c;可以自由的设计数据来源。 关于这个IP的使用&#xff0c;可以…

MAC有没有免费NTFS tuxera激活码 tuxera破解 tuxera for mac2023序列号直装版 ntfs formac教程

Tuxera NTFS 2023破解版是一款非常好用的在线磁盘读写工具&#xff0c;该软件允许mac用户在Windows NTFS格式的硬盘上进行读写操作&#xff0c;Mac的文件系统是HFS&#xff0c;而Windows则使用NTFS格式&#xff0c;这导致在Mac系统上不能直接读写Windows格式的硬盘。然而&#…

程序员:写好代码就行了,为什么要学写作

&#x1f341; 展望&#xff1a;关注我, AI 学习之旅上&#xff0c;我与您一同成长&#xff01; 一、引言 在当今这个信息爆炸的时代&#xff0c;程序员们往往沉浸在代码的世界里&#xff0c;用代码来解决问题。然而&#xff0c;你是否曾想过&#xff0c;除了代码&#xff0c;…

INSTEAD OF 触发器的创建

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 INSTEAD OF 触发器&#xff0c;也称替换触发器&#xff0c;是一种特殊的触发器&#xff0c;和其他建立在数据表上的触发器不同&#xff0c;INSTEAD OF 触发器建立在视图上。…

Podman入门全指南:安装、配置与运行容器

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 Podman入门全指南&#xff1a;安装、配置与运行容器 前言Podman简介什么是 Podman&#xff1f;Podman 与 Docker 的主要区别 安装Podman支持的操作系统和环境安装步骤详解LinuxUbuntuCentOS/RHEL MacO…

双系统下删除ubuntu

絮絮叨叨 由于我在安装Ubuntu的时候没有自定义安装位置&#xff0c;而是使用与window共存的方式让Ubuntu自己选择安装位置&#xff0c;导致卸载时我不知道去格式化哪个分区&#xff0c;查阅多方资料后无果&#xff0c;后在大佬帮助下找到解决方案 解决步骤 1、 插上Ubuntu安…

Axure如何调起浏览器的打印功能

Axure如何调起浏览器的打印功能 答&#xff1a;javascript:window.print(); 不明白的继续往下看 应用场景&#xff1a; 原型设计中&#xff0c;页面上的打印按钮&#xff0c;需要模拟操作演示&#xff0c;需要点击指定的按钮时&#xff0c;唤起浏览器的打印功能&#xff08…

使用Pandas从Excel文件中提取满足条件的数据并生成新的文件

目录 一、引言 二、环境准备 三、读取Excel文件 四、数据筛选 五、保存为新的Excel文件 六、案例与代码总结 七、进阶用法与注意事项 八、结语 在数据处理的日常工作中&#xff0c;我们经常需要从大量数据中筛选出满足特定条件的数据集。Pandas是一个强大的Python数据分…

比 PSD.js 更强的下一代 PSD 解析器,支持 WebAssembly

比 PSD.js 更强的下一代 PSD 解析器&#xff0c;支持 WebAssembly 1.什么是 webtoon/ps webtoon/ps 是 Typescript 中轻量级 Adobe Photoshop .psd/.psb 文件解析器&#xff0c;对 Web 浏览器和 NodeJS 环境提供支持&#xff0c;且做到零依赖。 Fast zero-dependency PSD par…

2024 年最好的免费数据恢复软件,您可以尝试的几个数据恢复软件

由于系统崩溃而丢失数据可能会给用户带来麻烦。我们将重要的宝贵数据和个人数据保存在我们的 PC、笔记本电脑和其他数字设备上。您可能会因分区丢失、意外删除文件和文件夹、格式化硬盘驱动器而丢失数据。数据丢失是不幸的&#xff0c;如果您不小心从系统中删除了文件或数据&am…

深入理解 Srping IOC

什么是 Spring IOC&#xff1f; IOC 全称&#xff1a;Inversion of Control&#xff0c;翻译为中文就是控制反转&#xff0c;IOC 是一种设计思想&#xff0c;IOC 容器是 Spring 框架的核心&#xff0c;它通过控制和管理对象之间的依赖关系来实现依赖注入&#xff08;Dependenc…