核心记忆
此仓库展示了针对特定AI和LLM应用场景的内存最佳实践和参考架构。请注意,提供的代码仅作为示范,并不是微软官方支持的产品。
核心记忆(KM)是一种多模态的AI服务,专注于通过自定义连续数据混合管道高效索引数据集,支持**检索增强生成**(RAG)、合成记忆、提示工程和自定义语义记忆处理。
KM可以作为Web服务、Docker容器、**插件**用于ChatGPT/Copilot/语义核心以及嵌入式应用的.NET库。
利用先进的嵌入和LLM,系统支持自然语言查询,以从索引的数据中获得答案,并附上引用和链接到原始来源。
设计用于与语义核心、Microsoft Copilot和ChatGPT无缝集成,核心记忆增强了为最流行AI平台构建的应用程序中的数据驱动功能。
同步记忆API(又称"无服务器")
核心记忆在运行为异步Web服务时效果最佳和具有最好的扩展性,允许在不阻塞您的应用的情况下摄取成千上万的文档和信息。
然而,核心记忆也可以在无服务器模式下运行,在.NET后端/控制台/桌面应用中以同步模式嵌入MemoryServerless
类实例。这种方法在ASP.NET Web API和Azure函数中也表现出色。每个请求会立即处理,不过调用客户端有责任处理瞬态错误。
将文档导入你的核心记忆可以像这样简单:
var memory = new KernelMemoryBuilder() .WithOpenAIDefaults(Environment.GetEnvironmentVariable("OPENAI_API_KEY")) .Build<MemoryServerless>(); // 导入一个文件 await memory.ImportDocumentAsync("meeting-transcript.docx", tags: new() { { "user", "Blake" } }); // 导入多个文件并应用多个标签 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"));
提问:
var answer1 = await memory.AskAsync("有多少人参加了会议?"); var answer2 = await memory.AskAsync("项目进度是怎样的?", filter: new MemoryFilter().ByTag("user", "Blake"));
这个示例利用了默认的文档摄取管道:
- 提取文本:识别文件格式并提取信息
- 将文本分割成小块,以优化搜索
- 使用LLM嵌入生成器提取嵌入
- 将嵌入保存到一个向量索引中,比如Azure AI Search、Qdrant或其他数据库
在示例中,通过标签将记忆按用户组织,保护私人信息。此外,记忆可以通过标签进行分类和结构化,使搜索和检索更加有效,通过分面导航实现。
数据谱系、引用、参考来源:
所有记忆和答案都完全与提供的数据相关联。在生成答案时,核心记忆包括所有验证其准确性所需的信息:
await memory.ImportFileAsync("NASA-news.pdf"); var answer = await memory.AskAsync("关于猎户座有NASA的最新消息吗?"); Console.WriteLine(answer.Result + "/n"); foreach (var x in answer.RelevantSources) { Console.WriteLine($" * {x.SourceName} -- {x.Partitions.First().LastUpdate:D}"); }
是的,关于猎户座航天器有NASA的最新消息。NASA已经邀请媒体参观一个新的测试版本[......]有关阿耳特弥斯计划的更多信息,可以访问NASA网站。
- NASA-news.pdf -- 2023年8月1日,星期二
记忆即服务 - 异步API
根据你的场景需求,你可能希望在本地进程内运行所有代码,或通过异步和可扩展的服务远程运行。
如果你正在导入小文件,并且只需要C#,并能在导入期间阻塞进程,那么本地进程内执行就可以像上面的MemoryServerless一样。
然而,如果你处于以下场景之一:
- 我只希望有一个Web服务来导入数据并发送查询以获取答案
- 我的应用程序是用TypeScript、Java、Rust或其他一些语言编写的
- 我正在导入需要几分钟处理的大文档,并且不希望阻塞用户界面
- 我希望记忆导入独立运行,支持失败和重试逻辑
- 我想定义混合多种语言的自定义管道,如Python、TypeScript等
那么你可以将核心记忆部署为后端服务,插入默认处理程序,或你的自定义Python/TypeScript/Java等处理程序,并利用异步非阻塞的记忆编码过程,发送文档和提问使用MemoryWebClient。
这里你可以找到完整的关于如何运行核心记忆服务的指令集。
核心记忆(KM)和SK语义记忆(SM)
核心记忆(KM)是一项服务,基于从开发语义核心(SK)和语义记忆(SM)中获得的反馈和经验,提供了许多需要手动开发的功能,如存储文件、从文件中提取文本、提供框架来保护用户数据等。KM代码库完全基于.NET,这减少了用多种语言编写和维护功能的需要。作为一种服务,KM可以从任何语言、工具或平台使用,例如浏览器扩展和ChatGPT助手。
语义记忆(SM)是一个用于C#、Python和Java的库,封装了对数据库的直接调用并支持向量搜索。它是语义核心(SK)项目的一部分,作为首个公开的长期记忆库。核心库用三种语言维护,而支持的存储引擎(称为"连接器")在各语言中有所不同。
以下是比较表:
功能 | 核心记忆 | 语义记忆 |
---|---|---|
数据格式 | 网页、PDF、图像、Word、PowerPoint、Excel、Markdown、文本、JSON、HTML | 仅文本 |
搜索 | 余弦相似性、带有过滤器(AND/OR条件)的混合搜索 | 余弦相似性 |
语言支持 | 任何语言、命令行工具、浏览器扩展、低代码/无代码应用、聊天机器人、助手等 | C#、Python、Java |
存储引擎 | Azure AI Search、Elasticsearch、MongoDB Atlas、Postgres+pgvector、Qdrant、Redis、SQL Server、内存KNN、磁盘KNN。 | Azure AI Search、Chroma、DuckDB、Kusto、Milvus、MongoDB、Pinecone、Postgres、Qdrant、Redis、SQLite、Weaviate |
文件存储 | 磁盘、Azure Blobs、AWS S3、MongoDB Atlas、内存(易失性) | - |
RAG | 是,带有来源查找 | - |
总结 | 是 | - |
OCR | 是,通过Azure Document Intelligence | - |
安全过滤器 | 是 | - |
大文档摄取 | 是,包括使用队列的异步处理(Azure Queues、RabbitMQ、基于文件或内存队列) | - |
文档存储 | 是 | - |
自定义存储模式 | 一些数据库 | - |
带内部嵌入的向量数据库 | 是 | - |
并发写入多个向量数据库 | 是 | - |
大型语言模型(LLMs) | Azure OpenAI、OpenAI、Anthropic、LLamaSharp通过llama.cpp、LM Studio、语义核心连接器 | Azure OpenAI、OpenAI、Gemini、Hugging Face、ONNX、自定义 |
带专用标记的LLMs | 是 | 否 |
云部署 | 是 | - |
带OpenAPI的Web服务 | 是 | - |
使用Docker镜像进行快速测试
如果你想快速测试此服务,使用以下命令使用OpenAI启动核心记忆服务:
docker run -e OPENAI_API_KEY="..." -it --rm -p 9001:9001 kernelmemory/service
如果你更喜欢使用自定义设置和服务,例如Azure OpenAI、Azure Document Intelligence等,你应该创建一个appsettings.Development.json
文件覆盖appsettings.json
中设置的默认值,或使用包含的配置向导:
cd service/Service
dotnet run setup
然后运行此命令使用刚刚创建的配置启动Docker镜像:
在Windows上:
docker run --volume .\appsettings.Development.json:/app/appsettings.Production.json -it --rm -p 9001:9001 kernelmemory/service
在macOS/Linux上:
docker run --volume ./appsettings.Development.json:/app/appsettings.Production.json -it --rm -p 9001:9001 kernelmemory/service
使用KM Web服务和MemoryWebClient
导入文件
#reference clients/WebClient/WebClient.csproj var memory = new MemoryWebClient("http://127.0.0.1:9001"); // <== Web服务运行的URL // 导入一个文件(默认用户) await memory.ImportDocumentAsync("meeting-transcript.docx"); // 导入一个文件并指定文档ID、用户和标签 await memory.ImportDocumentAsync("business-plan.docx", new DocumentDetails("user@some.email", "file001") .AddTag("collection", "business") .AddTag("collection", "plans") .AddTag("fiscalYear", "2023"));
通过Web服务获取答案
curl http://127.0.0.1:9001/ask -d'{"query":"最近有没有关于猎户座的NASA新闻?"}' -H 'Content-Type: application/json'
{ "Query": "最近有没有关于猎户座的NASA新闻?", "Text": "有的,NASA最近发布了一些关于猎户座航天器的新闻。NASA邀请媒体观看一个新的测试版本 [......] 若想了解更多关于Artemis计划的信息,可以访问NASA官网。", "RelevantSources": [ { "Link": "...", "SourceContentType": "application/pdf", "SourceName": "file5-NASA-news.pdf", "Partitions": [ { "Text": "跳转到主要内容\n2023年7月28日\n媒体公告 M23-095\nNASA邀请媒体观看阿尔忒弥斯月球任务的回收飞船\n(/sites/default/files/thumbnails/image/ksc-20230725-ph-fmx01_0003orig.jpg)\n登上 [......] 前往火星 (/topics/moon-to-\nmars/),猎户座航天器 (/exploration/systems/orion/index.html)\nNASA邀请媒体观看阿尔忒弥斯月球任务的回收飞船... https://www.nasa.gov/press-release/nasa-invites-media-to-see-recov...\n2 of 3 2023年7月28日, 下午4:51", "Relevance": 0.8430657, "SizeInTokens": 863, "LastUpdate": "2023-08-01T08:15:02-07:00" } ] } ] }
你可以在完整示例这里找到。
自定义内存提取管道
另一方面,如果你需要一个自定义数据管道,你也可以 自定义步骤,这些步骤将由你的自定义业务逻辑处理:
// 内存设置,例如计算方式和存储嵌入的位置
var memoryBuilder = new KernelMemoryBuilder()
.WithoutDefaultHandlers()
.WithOpenAIDefaults(Environment.GetEnvironmentVariable("OPENAI_API_KEY"));
var memory = memoryBuilder.Build();
// 插入自定义.NET处理程序
memory.Orchestrator.AddHandler<MyHandler1>("step1");
memory.Orchestrator.AddHandler<MyHandler2>("step2");
memory.Orchestrator.AddHandler<MyHandler3>("step3");
// 使用包含内存对象的自定义处理程序
await memory.ImportDocumentAsync(
new Document("mytest001")
.AddFile("file1.docx")
.AddFile("file2.pdf"),
steps: new[] { "step1", "step2", "step3" });
使用OpenAI swagger的Web API规范
在本地使用OpenAPI启用服务时,可以在http://127.0.0.1:9001/swagger/index.html找到API架构。
示例和工具
示例
- 包含各种用例的Jupyter笔记本集合
- 使用Kernel Memory网络服务上传文档并回答问题
- 在不运行服务的情况下导入文件并提问(无服务器模式)
- 使用Semantic Kernel的KM插件
- 在无服务器模式下使用自定义逻辑(自定义处理程序)处理文件
- 在异步模式下使用自定义逻辑(自定义处理程序)处理文件
- 使用curl从命令行上传文件并提问
- 定制RAG和摘要提示
- 定制的分区/文本分块选项
- 使用自定义嵌入/矢量生成器
- 使用自定义LLMs
- 使用LLama
- 综述文档,使用合成记忆
- 使用Semantic Kernel LLM连接器
- 使用自定义内容解码器
- 使用自定义网络爬虫获取网页
- 使用Anthropic LLMs生成答案
- 使用Azure AI Search的混合搜索
- 编写和使用自定义提取处理程序
- 将单个异步管道处理程序作为独立服务运行
- 使用nuget.org的KM包的测试项目
- 将内存与ASP.NET应用程序和控制器集成
- 展示如何从文件中提取文本的示例代码
- .NET配置和日志记录
- 在检索时扩展分区
- 通过LM Studio使用本地模型
- 在请求期间使用上下文参数定制RAG提示
- 在没有KernelMemoryBuilder的情况下创建Memory实例
工具
- .NET appsettings.json生成器
- 上传文件的curl脚本
- 提问的curl脚本
- 搜索文档的curl脚本
- 用于开发任务启动Qdrant的脚本
- 用于开发任务启动Elasticsearch的脚本
- 用于开发任务启动MS SQL Server的脚本
- 用于开发任务启动Redis的脚本
- 用于开发任务启动RabbitMQ的脚本
- 用于开发任务启动MongoDB Atlas的脚本
.NET包
-
Microsoft.KernelMemory.WebClient: 调用正在运行的Kernel Memory web服务的.NET客户端。
-
Microsoft.KernelMemory.Core: 包含所有扩展的Kernel Memory核心库,可用于构建自定义管道和处理程序, 还包含无需web服务即可同步使用内存的无服务器客户端。
-
Microsoft.KernelMemory.Service.AspNetCore: 一个用于将Kernel Memory加载到ASP.NET应用程序中的扩展。
-
Microsoft.KernelMemory.SemanticKernelPlugin: 一个用于Semantic Kernel的Memory插件, 替换原有的Semantic Memory。
适用于Python、Java和其他语言的包
Kernel Memory服务开箱即用提供Web API,包括OpenAPI swagger文档,您可以利用这些文档来测试API并创建自定义web客户端。例如,在本地启动服务后, 见http://127.0.0.1:9001/swagger/index.html。
提供了一个.NET Web客户端和一个Semantic Kernel插件,详见上面的nugets包。
即将提供带有Web客户端和Semantic Kernel插件的python包。 我们也欢迎PR贡献以支持更多语言。
贡献者
anthonypuppo | chaelli | cherchyk | coryisakson | crickman | dependabot[bot] |
:---: | :---: | :---: | :---: | :---: | :---: |
dluc | DM-98 | EelcoKoster | Foorcee | GraemeJones104 | jurepurgar |