Redis 现在与内核内存集成,允许任何开发人员使用 Semantic Kernel 构建高性能 AI 应用程序。
Semantic Kernel 是微软的开发者工具包,用于将 LLM 集成到您的应用程序中。您可以将 Semantic Kernel 视为一种操作系统,其中 LLM 是 CPU,LLM 的上下文窗口是 L1 缓存,您的向量存储是 RAM 中的内容。 内核内存 是 Semantic Kernel 的一个组件项目,充当内存控制器,而 Redis 在此处发挥作用,充当物理内存。
作为一项 AI 服务,内核内存允许您索引和检索非结构化的多模态数据。您可以使用 KM 轻松实现常见的 LLM 设计模式,例如检索增强生成 (RAG)。当您的应用程序需要高性能和可靠性时,Redis 是内核内存后端的自然选择。
在这篇文章中,我们将了解如何使用 Semantic Kernel 和 Redis 轻松构建 AI 聊天应用程序。
您可以通过两种方式运行内核内存
如果您直接在应用程序中运行内核内存,您将被限制在 .NET 生态系统中(对于 .NET 开发人员来说这不是什么大问题),但将内核内存作为独立服务运行的优势在于,任何能够发出 HTTP 请求的语言都可以访问它。
为了说明内核内存的平台中立性,我们提供了两个示例,一个是用 Python 编写的,另一个是用 .NET 编写的。在实践中,任何可以运行 HTTP 服务器的语言都可以轻松地替换为运行此示例。
要克隆 .NET 示例,请运行以下命令
git clone --recurse-submodules https://github.com/redis-developer/redis-rag-chat-dotnet
要克隆 python 示例,请运行
git clone --recurse-submodules https://github.com/redis-developer/redis-rag-chat-python
这些示例应用程序依赖于 OpenAI 的完成和嵌入 API。首先,获取 OpenAI API 密钥。然后将 API 密钥传递给 docker-compose。这将启动
OpenAIApiKey=<YOUR_OPENAI_API_KEY> docker compose up
我们有一个预构建的啤酒信息数据集,我们可以将其添加到内核内存中(并要求其提供推荐)。要添加该数据集,只需运行
./common/scripts/setup_beers.sh
要访问前端,请导航到 https://#:3000。从那里,您可以向机器人请求推荐
此演示包含几个部分
Redis 启用了向量数据库,这是 Redis、Redis 云 和 Azure 缓存 for Redis(企业版) 提供的功能。这些选项中的任何一个都可以使用。我们的前端是一个简单的 React 应用程序。内核内存需要一些配置,我们将在下面介绍。插件和 HTTP 调用驱动我们的后端,因此我们也将介绍它们。
要使用 Redis 启动并运行内核内存,您需要对以下内容进行一些小的更新
common/kernel-memory/appsettings.json file. Start with the template
common/kernel-memory/appsettings.json.
Rename this file to appsettings.json.
请注意,在此文件中有一个 Retrieval 对象
"Retrieval": {
"MemoryDbType": "Redis",
"EmbeddingGeneratorType": "OpenAI",
"SearchClient": {
"MaxAskPromptSize": -1,
"MaxMatchesCount": 100,
"AnswerTokens": 300,
"EmptyAnswer": "INFO NOT FOUND"
}
}
这会告诉检索器使用哪个 Embedding Generator(OpenAI)以及使用哪个 MemoryDbType(Redis)。
还有一个 Redis 对象:
"Redis": {
"Tags": {
"user": ",",
"email": "|"
},
"ConnectionString": "redis-km:6379",
"AppPrefix":"redis-rag-chat-"
}
此 Redis 对象映射出内核内存中 Redis 连接器的重要配置参数
我们基本上想对内核内存做两件事
当然,内核内存还有更多功能,包括信息提取、分区、管道、嵌入生成、摘要等等,但我们已经配置了所有这些功能,并且它们都用于这两个目标。
要与内核内存交互,您可以使用 HTTP 接口。该接口有几个前端
要上传文档,请调用 IKernelMemory 的一个 Import 函数。在 .NET 示例中,我们使用了一个简单的文档导入,使用文件流,但您也可以导入网页和文本
[HttpPost("upload")]
public async Task<IActionResult> AddDocument(IFormFile file)
{
await using var fileStream = file.OpenReadStream();
var document = new Document().AddStream(file.FileName, fileStream);
var res = await _kernelMemory.ImportDocumentAsync(document);
return Ok(res);
}
在 Python 中,还没有内核内存客户端,但您可以简单地使用 Upload 端点
@app.post("/documents/upload")
async def upload_document(file: UploadFile = File(...)):
file_content = await file.read()
data = {
"index": "km-py",
"id": str(uuid.uuid4())
}
files = {'file': (file.filename, file_content, file.content_type)}
response = requests.post(f"{kernel_memory_url}/upload", files=files, data=data)
response.raise_for_status()
return {"status": response.status_code, "response_data": response.text}
要查询内核内存,您可以使用 Search 或 Ask 端点。Search 端点会对索引进行搜索,并返回与您最相关的文档,而 Ask 端点会执行搜索,然后将结果传递到 LLM。
内核内存 .NET 客户端带有它自己的插件,允许您从提示调用它
{{$systemPrompt}}
The following is the answer generated by kernel memory, put it into your own words:
Result:{{memory.ask $intent}}
上面的提示将总结对内核内存 Ask 端点的响应,该响应基于提供的系统提示(以及从聊天历史记录和管道中更早的最新消息生成的意图)。要使该插件本身正常工作,您需要将 Memory Plugin 添加到内核。以下是 .NET 项目的 Program.cs 中的一些摘录
var kmEndpoint = builder.Configuration["KernelMemoryEndpoint"];
var kernelMemory = new MemoryWebClient(kmEndpoint);
builder.Services.AddSingleton(kernelMemory);
var kernelBuilder = builder.Services.AddKernel();
kernelBuilder.AddOpenAIChatCompletion(builder.Configuration["OpenAICompletionModelId"]!, builder.Configuration["OpenAIApiKey"]!);
kernelBuilder.Plugins.AddFromObject(new MemoryPlugin(kernelMemory), "memory");
这会将内核内存注入 DI 容器,然后添加 Semantic Kernel,最后将 MemoryPlugin 从内核内存客户端添加到 Semantic Kernel。
当然,您也可以从 HTTP 端点调用这些查询函数。在 Python 示例中,我们只调用了 search 端点(然后格式化结果)
def get_memories(question: str) -> str:
data = {
"index": "km-py",
"query": question,
"limit": 5
}
response = requests.post(f"{kernel_memory_url}/search", json=data)
if response.status_code == 200:
response_json = response.json()
memories = response_json.get('results',[])
res = ""
for memory in memories:
res += "memory:"
for partition in memory['partitions']:
res += partition['text']
res += '\n'
print(res)
return res
raise Exception(response.text)
然后可以将这些记忆馈送到我们的 LLM,以便在回答问题时提供更多上下文。
Semantic Kernel 提供了一种简单的方法来管理语义计算机的构建块,而内核内存提供了一种直观且灵活的方式来与 Semantic Kernel 的内存层交互。正如我们在这里所观察到的,将内核内存与 Redis 集成就像在配置文件中添加几行代码一样简单。