如何使用用于微软语义内核(Microsoft Semantic Kernel)的Elasticsearch矢量存储连接器进行人工智能代理开发
微软语义内核(Microsoft Semantic Kernel)是一款轻量级开源开发工具包,可让您轻松构建人工智能代理,并将最新的人工智能模型集成到您的 C#、Python 或 Java 代码库中。随着Semantic Kernel Elasticsearch向量存储连接器(Elasticsearch Vector Store Connector)的发布,使用Semantic Kernel构建人工智能代理的开发人员现在可以将Elasticsearch作为可扩展的企业级向量存储插件,同时继续使用Semantic Kernel抽象。
我们与 微软语义内核 ( Microsoft Semantic Kernel )团队合作,宣布面向 微软语义内核 (.NET)用户推出 Semantic Kernel Elasticsearch矢量存储连接器(Vector Store Connector )。语义内核(Semantic Kernel)简化了企业级人工智能代理的构建过程,包括利用来自矢量存储库(Vector Store)的更多相关数据驱动响应来增强大型语言模型(LLM)的能力。语义内核(Semantic Kernel)为与Elasticsearch等矢量存储进行交互提供了一个无缝的抽象层,可提供创建、列出和删除记录集合以及上传、检索和删除单条记录等基本功能。
开箱即用的Semantic Kernel Elasticsearch向量存储连接器(Vector Store Connector)支持Semantic Kernel向量存储抽象,这使得开发人员在构建人工智能代理时能够非常容易地将Elasticsearch作为向量存储插件。
Elasticsearch 在开源社区拥有坚实的基础,最近采用了AGPL 许可证。这些工具与开源的微软语义内核(Microsoft Semantic Kernel)相结合,可提供强大的企业级解决方案。您可以通过运行此命令curl -fsSL https://elastic.co/start-local | sh ,在几分钟内启动 Elasticsearch(详情请参考start-local),然后在生产人工智能代理的同时,迁移到云托管或自托管版本。
在本篇博客中,我们将探讨在使用Semantic Kernel(语义内核)时,如何使用Semantic Kernel Elasticsearch向量存储连接器。该连接器的 Python 版本将在未来推出。
高级应用场景:利用 Semantic Kernel& Elasticsearch 构建 RAG 应用程序
下面我们将举例说明。在高层次上,我们正在构建一个 RAG(检索增强生成)应用程序,它将用户的问题作为输入,并返回一个答案。我们将使用 Azure OpenAI ( 也可使用 本地 LLM )作为 LLM,Elasticsearch 作为向量存储,Semantic Kernel (.net) 作为将所有组件连接在一起的框架。
如果您不熟悉 RAG 架构,可以通过以下文章快速了解: https://www.elastic.co/search-labs/blog/retrieval-augmented-generation-rag。
答案由 LLM 生成,LLM 从 Elasticsearch 向量存储中获取与问题相关的上下文。答复还包括法律硕士用作背景的资料来源。
RAG 示例
在这个具体例子中,我们创建了一个应用程序,允许用户就内部酒店数据库中存储的酒店提出问题。例如,用户可以根据不同标准搜索特定酒店,或要求提供酒店列表。
在示例数据库中,我们生成了一个包含 100 个条目的酒店列表。为了让您尽可能轻松地试用连接器演示,我们特意设置了较小的样本量。在实际应用中,Elasticsearch 连接器将显示出其优于其他选项(如 "InMemory "向量存储实现)的优势,尤其是在处理超大数据量时。
完整的演示应用程序可在 Elasticsearch 向量存储连接器存储库中找到。
让我们先将所需的 NuGet 软件包和指令添加到项目中:
dotnet add package "Elastic.Clients.Elasticsearch" -v 8.16.2
dotnet add package "Elastic.SemanticKernel.Connectors.Elasticsearch" -v 0.1.2
dotnet add package "Microsoft.Extensions.Hosting" -v 9.0.0
dotnet add package "Microsoft.SemanticKernel.Connectors.AzureOpenAI" -v 1.30.0
dotnet add package "Microsoft.SemanticKernel.PromptTemplates.Handlebars" -v 1.30.0using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Elastic.Clients.Elasticsearch;
using Elastic.Transport;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Data;
using Microsoft.SemanticKernel.Embeddings;
using Microsoft.SemanticKernel.PromptTemplates.Handlebars;现在,我们可以创建我们的数据模型,并为其提供语义内核(Semantic Kernel)的特定属性,以定义存储模型模式和文本搜索的一些提示:
/// <summary>
/// Data model for storing a "hotel" with a name, a description, a description embedding and an optional reference link.
/// </summary>
public sealed record Hotel
{
[VectorStoreRecordKey]
public required string HotelId { get; set; }
[TextSearchResultName]
[VectorStoreRecordData(IsFilterable = true)]
public required string HotelName { get; set; }
[TextSearchResultValue]
[VectorStoreRecordData(IsFullTextSearchable = true)]
public required string Description { get; set; }
[VectorStoreRecordVector(Dimensions: 1536, DistanceFunction.CosineSimilarity, IndexKind.Hnsw)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
[TextSearchResultLink]
[VectorStoreRecordData]
public string? ReferenceLink { get; set; }
}存储模型模式属性(`VectorStore*`)与 Elasticsearch 向量存储连接器的实际使用最为相关,即
VectorStoreRecordKey来标记记录类上的一个属性,作为记录存储在向量存储中的键。VectorStoreRecordData将记录类的一个属性标记为 "数据"。VectorStoreRecordVector将记录类的一个属性标记为矢量。
所有这些属性都接受各种可选参数,可用于进一步定制存储模型。以VectorStoreRecordKey 为例,可以指定不同的距离函数或不同的索引类型。
文本搜索属性 (TextSearch*) 在本示例的最后一步中非常重要。我们稍后再谈。
下一步,我们将初始化语义内核引擎,并获取核心服务的引用。在实际应用中,应使用依赖注入而不是直接访问服务集合。同样的道理也适用于硬编码的配置和秘密,它们应该使用配置提供程序来读取:
var builder = Host.CreateApplicationBuilder(args);
// Register AI services.
var kernelBuilder = builder.Services.AddKernel();
kernelBuilder.AddAzureOpenAIChatCompletion("gpt-4o", "https://my-service.openai.azure.com", "my_token");
kernelBuilder.AddAzureOpenAITextEmbeddingGeneration("ada-002", "https://my-service.openai.azure.com", "my_token");
// Register text search service.
kernelBuilder.AddVectorStoreTextSearch<Hotel>();
// Register Elasticsearch vector store.
var elasticsearchClientSettings = new ElasticsearchClientSettings(new Uri("https://my-elasticsearch-instance.cloud"))
.Authentication(new BasicAuthentication("elastic", "my_password"));
kernelBuilder.AddElasticsearchVectorStoreRecordCollection<string, Hotel>("skhotels", elasticsearchClientSettings);
// Build the host.
using var host = builder.Build();
// For demo purposes, we access the services directly without using a DI context.
var kernel = host.Services.GetService<Kernel>()!;
var embeddings = host.Services.GetService<ITextEmbeddingGenerationService>()!;
var vectorStoreCollection = host.Services.GetService<IVectorStoreRecordCollection<string, Hotel>>()!;
// Register search plugin.
var textSearch = host.Services.GetService<VectorStoreTextSearch<Hotel>>()!;
kernel.Plugins.Add(textSearch.CreateWithGetTextSearchResults("SearchPlugin"));现在可以使用vectorStoreCollection 服务创建数据集,并摄取一些演示记录:
await vectorStoreCollection.CreateCollectionIfNotExistsAsync();
// CSV format: ID;Hotel Name;Description;Reference Link
var hotels = (await File.ReadAllLinesAsync("hotels.csv"))
.Select(x => x.Split(';'));
foreach (var chunk in hotels.Chunk(25))
{
var descriptionEmbeddings = await embeddings.GenerateEmbeddingsAsync(chunk.Select(x => x[2]).ToArray());
for (var i = 0; i < chunk.Length; ++i)
{
var hotel = chunk[i];
await vectorStoreCollection.UpsertAsync(new Hotel
{
HotelId = hotel[0],
HotelName = hotel[1],
Description = hotel[2],
DescriptionEmbedding = descriptionEmbeddings[i],
ReferenceLink = hotel[3]
});
}
}由此可见,语义内核(Semantic Kernel)是如何将向量存储的使用及其复杂性简化为几个简单的方法调用的。
在 Elasticsearch 中创建一个新索引,并创建所有必要的属性映射。然后,我们的数据集会完全透明地映射到存储模型中,并最终存储到索引中。下面是映射在 Elasticsearch 中的显示方式。
{
"mappings": {
"properties": {
"descriptionEmbedding": {
"dims": 1536,
"index": true,
"index_options": {
"type": "hnsw"
},
"similarity": "cosine",
"type": "dense_vector"
},
"hotelName": {
"type": "keyword"
},
"description": {
"type": "text"
}
}
}
}embeddings.GenerateEmbeddingsAsync() 会透明地调用已配置的 Azure AI 嵌入生成服务。
在这个演示的最后一个步骤中,我们还可以看到更多的神奇之处。
当用户就数据提问时,只需调用InvokePromptAsync ,就能执行以下所有操作:
1.为用户的问题生成嵌入代码
2.在矢量存储器中搜索相关条目
3.将查询结果插入提示模板
4.最终提示形式的实际查询将发送到人工智能聊天完成服务
// Invoke the LLM with a template that uses the search plugin to
// 1. get related information to the user query from the vector store
// 2. add the information to the LLM prompt.
var response = await kernel.InvokePromptAsync(
promptTemplate: """
Please use this information to answer the question:
{{#with (SearchPlugin-GetTextSearchResults question)}}
{{#each this}}
Name: {{Name}}
Value: {{Value}}
Source: {{Link}}
-----------------
{{/each}}
{{/with}}
Include the source of relevant information in the response.
Question: {{question}}
""",
arguments: new KernelArguments
{
{ "question", "Please show me all hotels that have a rooftop bar." },
},
templateFormat: "handlebars",
promptTemplateFactory: new HandlebarsPromptTemplateFactory());还记得我们之前在数据模型上定义的TextSearch* 属性吗?有了这些属性,我们就能在提示模板中使用相应的占位符,这些占位符会根据向量存储中的条目信息自动填充。
对于我们的问题",请告诉我所有拥有屋顶酒吧的酒店。" ,最终答复如下:
Console.WriteLine(response.ToString());
// > The hotel that has a rooftop bar is Skyline Suites. You can find more information about this hotel [here](https://example.com/yz567).正确答案是指 hotels.csv 中的以下条目
9;
Skyline Suites;
Offering panoramic city views from every suite, this hotel is perfect for those who love the urban landscape. Enjoy luxurious amenities, a rooftop bar, and close proximity to attractions. Luxurious and contemporary.;
https://example.com/yz567这个例子很好地说明了微软语义内核的使用是如何通过其深思熟虑的抽象功能大大降低复杂性,并实现高度灵活性的。例如,只需修改一行代码,就可以更换向量存储或所使用的人工智能服务,而无需重构代码的任何其他部分。
同时,该框架还提供了大量高级功能,如 "InvokePrompt "函数或模板或搜索插件系统。
完整的演示应用程序可在 Elasticsearch 向量存储连接器存储库中找到。
Elasticsearch 还能做什么
Elasticsearch& Semantic Kernel(语义内核):下一步是什么?
我们展示了在.NET中构建GenAI应用时,如何将Elasticsearch向量存储轻松插入Semantic Kernel。敬请期待下一步的 Python 集成。
由于Semantic Kernel(语义内核)为混合搜索等高级搜索功能建立了抽象,Elasticsearch连接将使.NET开发人员能够在使用Semantic Kernel(语义内核)的同时轻松实现这些功能。
常见问题
什么是微软语义内核?
微软语义内核(Microsoft Semantic Kernel)是一款轻量级开源开发工具包,可让您轻松构建人工智能代理,并将最新的人工智能模型集成到您的 C#、Python 或 Java 代码库中。




