基于Microsoft.Extensions.VectorData实现语义搜索

大家好,我是Edison。

上周水了一篇 Microsoft.Extensions.AI 的介绍文章,很多读者反馈想要了解更多。很多时候,除了集成LLM实现聊天对话,还会有很多语义搜索和RAG的使用场景,那么今天就给大家介绍一下如何完成语义搜索。

Microsoft.Extensions.VectorData介绍

语义搜索正在改变应用程序查找和解释数据的方式,它专注于语义关联,而不仅仅是关键字匹配。

Microsoft.Extensions.VectorData 是一组 .NET代码库,旨在管理 .NET 应用程序中基于向量的数据。这些库为与向量存储交互提供了一个统一的 C# 抽象层,使开发人员能够有效地处理嵌入并执行向量相似性查询。

更多该代码库的内容请参考:Luis 《Introducting Microsoft.Extensions.VectorData》

在接下来的demo中,我们会使用以下工具:

(1) Qdrant 作为 VectorStore

(2) Ollama 运行 all-minilm 模型 作为 Emedding生成器

ollama pull all-minilm

Qdrant向量搜索引擎

Qdrant是一个向量相似性搜索引擎,它提供了一个生产就绪的服务,拥有便捷的 API来存储、搜索和管理带有额外负载的点(即向量)。它非常适合需要高效相似性搜索的应用程序。我们可以在 Docker 容器中运行 它,这也使它成为对开发人员友好的选择。

容器运行Qdrant:

docker run -p 6333:6333 -p 6334:6334 \
-v $(pwd)/qdrant_storage:/qdrant/storage \
qdrant/qdrant

验证Qdrant运行:访问 server:6333/dashboard

开始DEMO案例

安装NuGet包:

Microsoft.Extensions.AI (preview)
Microsoft.Extensions.Ollama (preivew)
Microsoft.Extensions.AI.OpenAI (preivew)
Microsoft.Extensions.VectorData.Abstractions (preivew)
Microsoft.SemanticKernel.Connectors.Qdrant (preivew)

这里我们假设做一个CloudService的语义搜索,分下面一些步骤来实现它。

Step1. 配置文件appsettings.json:

{"Embedding": {"EndPoint": "http://localhost:11434","Model": "all-minilm"},"Qdrant": {"Host": "edt-dev-server","Port": 6334}
}

Step2. 加载配置:

var config = new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build();

Step3. 初始化Embedding生成器:这里我们使用的是本地的Ollama运行all-minilm模型来做。

var generator =new OllamaEmbeddingGenerator(new Uri(config["Embedding:EndPoint"]), config["Embedding:Model"]);

此外,我们也可以使用OpenAI的Embedding服务:

var generator = new OpenAIClient(new ApiKeyCredential(config["OneAPI:ApiKey"]), new OpenAIClientOptions() { Endpoint = new Uri(config["OneAPI:EndPoint"]) }).AsEmbeddingGenerator(modelId: config["Embedding:ModelId"]);

Step4. 初始化Qdrant向量存储

var vectorStore = new QdrantVectorStore(new QdrantClient(config["Qdrant:Host"], int.Parse(config["Qdrant:Port"])));
// Get the collection if it exist in qdrant
var cloudServicesStore = vectorStore.GetCollection<ulong, CloudService>("cloudServices");
// Create the collection if it doesn't exist yet.
await cloudServicesStore.CreateCollectionIfNotExistsAsync();

Step5. 插入测试数据:

// Define the test data
var cloudServices = new List<CloudService>()
{new CloudService{Key=1,Name="Azure App Service",Description="Host .NET, Java, Node.js, and Python web applications and APIs in a fully managed Azure service. You only need to deploy your code to Azure. Azure takes care of all the infrastructure management like high availability, load balancing, and autoscaling."},new CloudService{Key=2,Name="Azure Service Bus",Description="A fully managed enterprise message broker supporting both point to point and publish-subscribe integrations. It's ideal for building decoupled applications, queue-based load leveling, or facilitating communication between microservices."},new CloudService{Key=3,Name="Azure Blob Storage",Description="Azure Blob Storage allows your applications to store and retrieve files in the cloud. Azure Storage is highly scalable to store massive amounts of data and data is stored redundantly to ensure high availability."},new CloudService{Key=4,Name="Microsoft Entra ID",Description="Manage user identities and control access to your apps, data, and resources.."},new CloudService{Key=5,Name="Azure Key Vault",Description="Store and access application secrets like connection strings and API keys in an encrypted vault with restricted access to make sure your secrets and your application aren't compromised."},new CloudService{Key=6,Name="Azure AI Search",Description="Information retrieval at scale for traditional and conversational search applications, with security and options for AI enrichment and vectorization."}
};
// Insert test data into the collection in qdrant
foreach (var service in cloudServices)
{service.Vector = await generator.GenerateEmbeddingVectorAsync(service.Description);await cloudServicesStore.UpsertAsync(service);
}

其中,CloudService的定义如下:

public class CloudService
{[VectorStoreRecordKey]public ulong Key { get; set; }[VectorStoreRecordData]public string Name { get; set; }[VectorStoreRecordData]public string Description { get; set; }[VectorStoreRecordVector(384, DistanceFunction.CosineSimilarity)]public ReadOnlyMemory<float> Vector { get; set; }
}

Step6. 生成查询Emedding并从Qdrant中执行查询:

// Generate query embedding
var query = "Which Azure service should I use to store my Word documents?";
var queryEmbedding = await generator.GenerateEmbeddingVectorAsync(query);
// Query from vector data store
var searchOptions = new VectorSearchOptions()
{Top = 1, // Only return the Top 1 record from QdrantVectorPropertyName = "Vector"
};
var results = await cloudServicesStore.VectorizedSearchAsync(queryEmbedding, searchOptions);
await foreach (var result in results.Results)
{Console.WriteLine($"Name: {result.Record.Name}");Console.WriteLine($"Description: {result.Record.Description}");Console.WriteLine($"Vector match score: {result.Score}");Console.WriteLine();
}

首先,验证下Qdrant中是否新增了数据:

其次,查看运行结果显示:返回最匹配的一个数据返回,因为我们设置的Top1记录。

完整的代码示例请参考该示例代码的GitHub仓库。

小结

本文介绍了Microsoft.Extensions.Vector的基本概念 和 基本使用,结合Embedding Model(如all-minilm) 和 VectorStore(如Qdrant),我们可以快速实现语义搜索,而不仅仅是关键字匹配。

如果你也是.NET程序员希望参与AI应用的开发,那就快快了解和使用基于Microsoft.Extensioins.AI的生态组件库吧。

参考内容

Eddie Chen,《探索Microsoft.Extensions.VectorData与Qdrant和Azure AI搜索的使用》

Luis,《Introducting Microsoft.Extensions.VectorData》

路边石,《Microsoft.Extensions.AI.OpenAI官方代码示例》

推荐内容

Microsoft Learn

eShopSupport

devblogs

 

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

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

相关文章

KubeSphere 企业版 v4.1.3 发布!可观测性深度优化,管理策略更灵活更安全

KubeSphere 企业版始终致力于为企业提供安全、稳定、高效的云原生全栈管理能力。在 4.1.3 版本中,KubeSphere 聚焦可观测性深度优化、策略管理灵活升级与安全隔离能力增强,推出多项新特性与优化,进一步释放企业云原生基础设施的潜力,助力业务高效运行与智能管理! 核心升级…

[MoE] Deepseek的All-to-all通信: DeepEP代码解读

[MoE] Deepseek的All-to-all通信: DeepEP代码解读 前言 最近,Deepseek开源了一系列MoE的优化技术,让我们看到了AI infra的强大之处。其中,第二天发布的DeepEP则是针对MoE中EP的all-to-all通信进行了优化。 我最近也在关注MoE和all-to-all,之前的MoE普遍使用NCCL的p2p通信进…

Java泛型上下界

有如下类的继承关系 // okFruit apple = new Apple(); List<Fruit> plate = new ArrayList<Apple>(); 它会在Idea里报红线,运行会报错:java: 不兼容的类型: java.util.ArrayList<Apple>无法转换为java.util.List<Fruit>,显然在集合间不存在继承引用…

Redis复习-通信协议、内存回收

通信协议 RESP协议 Redis是一个CS架构的软件,通信一般分两步(不包括pipeline和PubSub): 1.客户端(client)向服务端(server)发送一条命令 2.服务端解析并执行命令,返回响应结果给客户端 因此客户端发送命令的格式、服务端响应结果的格式必须有一个规范,这个规范就是通…

vi和vim快捷键

vi和vim常用的一些快捷键分类 快捷键 说明模式切换 i 进入插入模式(在光标前插入文本)。a 进入插入模式(在光标后插入文本)。o 在当前行下方插入新行并进入插入模式。O 在当前行上方插入新行并进入插入模式。Esc 退出插入模式,返回命令模式。: 进入命令模式(用于输入命令…

Go红队开发—语法补充

之前有师傅问这个系列好像跟红队没啥关系,前几期确实没啥关系,因为这都是进行红队工具开发的前置知识点,对于我个人强迫症而言只是想让这个系列更加完善而已,所以前置知识也加进去了,有GO只是的大佬可以等下一期哈!感谢支持。目录错误控制使用自定义错误类型错误包装erro…

Security认证失败逻辑

通过一系列的过滤器最终走到 FilterSecurityInterceptor package org.springframework.security.access.vote;public class AffirmativeBased extends AbstractAccessDecisionManager {public AffirmativeBased(List<AccessDecisionVoter<? extends Object>> deci…

关于书店管理系统的二次开发

一、来源 来自同学期末大作业。实现了基本的书店业务功能,包括书本信息管理、客户信息管理、购物车操作以及订单生成与保存等。 二、运行环境 + 运行结果的截图 操作系统:Windows 11 开发工具:Visual Studio 2022// BookStore.h点击查看代码 #ifndef BOOKSTORE_H #define BO…

CNC数控机床运行状态参数采集联网 对接软件MES 系统

IP 端口 TCP端口 流程任务 当前位置或者目标位置及描述 状态 需要接口内容 请求地址-AGV 请求AGV参数 请求AGV返回信息 PLC-地址 写入PLC值 读取PLC值 EDM-地址 写入EDM值 读取EDM值进入上下料进程 进入EDM上料台动作-动作 即将进入EDM上料台 "1.达…

Redis+Docker集群部署

机器故障了怎么办? Redis 是内存数据库,我们知道可以通过持久化机制,保存快照或者保存记录日志的方式,将数据持久化到磁盘。但是,如果机器故障了或磁盘坏了,数据就不就全没了吗?这种情况应该怎么办呢?别担心,考虑主从模式。 主从模式 给主节点 Master 配置一个从节点 …

【T20天正电气V10.0软件下载与安装教程】

1、安装包 扫描下方二维码关注「软知社」,后台回复【024】三位数字即可免费获取分享链接,无广告拒绝套路; 2、安装教程双击T20天正电气V10.0安装包,弹窗安装对话框选择我接收,点击下一步选择安装位置,点击下一步点击下一步等待安装进度完成安装完成,点击完成按钮点击下…

windows底层激活破解一步到位,TSforge也太暴力了!

windows底层激活破解一步到位,TSforge也太暴力了! windows底层激活破解一步到位,TSforge也太暴力了! 微软系统一直是需要收费的,也是电脑用户们经常遇到的问题,市面上也有很多工具, 但是今天的工具是最新的且**呼声最高、最彻底的**,需要的话赶紧保存下来,实际使用只需…