当前位置: 首页 > news >正文

RAG实现:.Net + Ollama + Qdrant 实现文本向量化,实现简单RAG

本文使用.Net + Ollama + 向量数据库Qdrant,实现简单RAG,代码仅实现基本演示功能。

文章目录

      • 一、Ollama如何安装使用
      • 二、新建.NetCore WebApi项目,并导入Nuget包
      • 三、文本向量化+保存Qdrant
      • 四、搜索向量数据库,将搜索到的结果交给大模型整理

在这里插入图片描述

一、Ollama如何安装使用

请移步:https://blog.csdn.net/MrTraum/article/details/139240885

二、新建.NetCore WebApi项目,并导入Nuget包

本项目使用.Net8构建。

引入以下包:
Microsoft.Extensions.AI
LangChain
LangChain.Core
LangChain.DocumentLoaders.Pdf
Microsoft.Extensions.VectorData.Abstractions
OllamaSharp
Microsoft.SemanticKernel.Connectors.Qdrant

三、文本向量化+保存Qdrant

向量化模型使用:Qwen3-Embedding-0.6B
文本从Pdf导入,使用 IFormFile 接收

public class Content
{[VectorStoreKey]public Guid Key { get; set; }[VectorStoreData]public string Text { get; set; }[VectorStoreData]public string Source { get; set; }[VectorStoreVector(1024)]public ReadOnlyMemory<float> Vector { get; set; }
}
IDocumentLoader wordLoader = new PdfPigPdfLoader();
var dataSource = DataSource.FromStream(file.File.OpenReadStream());
var documents = await wordLoader.LoadAsync(dataSource: dataSource
);
//使用LangChain进行大文本分块
//此处采用递归分块算法
ITextSplitter recursiveSplitter = new RecursiveCharacterTextSplitter(chunkSize: 500,chunkOverlap: 128,separators: new[] { "\n\n", "\n", "。", "!", "?", ";", " ", "" } // 分隔符优先级
);
var splitDocuments = recursiveSplitter.SplitDocuments(documents);var vectorStore = new QdrantVectorStore(new QdrantClient("192.168.4.9", 6334), true);
var ragVectorRecordCollection = vectorStore.GetCollection<Guid, Content>("Contents");
await ragVectorRecordCollection.EnsureCollectionExistsAsync();var uri = new Uri(OllamaUrl);
var ollama = new OllamaApiClient(uri, "dengcao/Qwen3-Embedding-0.6B:Q8_0");
List<Content> vectorRecords = new List<Content>();
//调用大模型进行文本向量化
var embeddings = await ollama.GenerateAndZipAsync(splitDocuments.Select(t => t.PageContent));
foreach (var doc in splitDocuments)
{ReadOnlyMemory<float> embedding = null;foreach (var item in embeddings){if (item.Value == doc.PageContent){embedding = item.Embedding.Vector;}}Content ctx = new Content(){Key = Guid.NewGuid(),Text = doc.PageContent,Source = doc.Metadata.TryGetValue("source", out var src) ? src?.ToString() : "unknown",Vector = embedding};vectorRecords.Add(ctx);
}
//保存如Qdrant
await ragVectorRecordCollection.UpsertAsync(vectorRecords, CancellationToken.None);

在这里插入图片描述

四、搜索向量数据库,将搜索到的结果交给大模型整理

        [HttpGet]public async Task<string> Query([FromQuery] string query, [FromQuery] int top = 10){var vectorStore = new QdrantVectorStore(new QdrantClient("192.168.4.9", 6334), true);var ragVectorRecordCollection = vectorStore.GetCollection<Guid, Content>("Contents");await ragVectorRecordCollection.EnsureCollectionExistsAsync();var uri = new Uri(OllamaUrl);var ollama = new OllamaApiClient(uri, "dengcao/Qwen3-Embedding-0.6B:Q8_0");var searchVector = await ollama.GenerateVectorAsync(query);//以下代码,写不写都可以。默认会根据VectorStoreVector标签匹配VectorSearchOptions<Content> vectorSearchOptions = new VectorSearchOptions<Content>(){VectorProperty = m => m.Vector,};//查询向量数据库var searchResult = ragVectorRecordCollection.SearchAsync(searchVector, top, vectorSearchOptions);var resultsList = new List<VectorSearchResult<Content>>();await foreach (var result in searchResult){resultsList.Add(result);}// 如果没有找到结果if (!resultsList.Any()){return "没有找到相关的信息。";}// 构建精确控制的提示词var promptBuilder = new StringBuilder();// 角色定义(严格模式)promptBuilder.AppendLine(@"你是一个知识检索系统,必须遵守以下规则:
1. 回答范围:仅使用下方<!--reference-->标记的内容
2. 禁止行为:禁止联想、推测或添加任何外部知识
3. 免责声明:当参考内容不匹配时必须声明");// 结构化参考内容promptBuilder.AppendLine("<!--reference-->");foreach (var item in resultsList.OrderByDescending(x => x.Score)){promptBuilder.AppendLine($"| 内容:{item.Record.Text?.Trim()}");promptBuilder.AppendLine($"| 元数据:{item.Record.Source?.Trim()}");promptBuilder.AppendLine($"| 相似度:{item.Score:F4}");promptBuilder.AppendLine("|--"); }promptBuilder.AppendLine("<!--end-reference-->");// 问题与约束条件promptBuilder.AppendLine($"用户问题:{query?.Trim()}");promptBuilder.AppendLine(@"响应要求:1. 相似度高的条目优先2. 描述中必须包含问题关键词的直系近义词3. 采用以下响应模板:- 当匹配成功时:『根据参考内容,搜索到以下内容。』- 当匹配失败时:『根据提供的信息,未找到明确匹配的内容。』");// 调用大模型整理结果var chatRequest = new ChatRequest{Model = ModelName,Stream = false,Think = false,//禁止思考模式Messages = new List<Message>(){new Message { Role = OllamaSharp.Models.Chat.ChatRole.System, Content = promptBuilder.ToString() },new Message { Role = OllamaSharp.Models.Chat.ChatRole.User, Content = query }}};var modelResponse = await ollama.ChatAsync(chatRequest).StreamToEndAsync();return modelResponse.Message.Content;}
http://www.dtcms.com/a/320471.html

相关文章:

  • 【优选算法】BFS解决拓扑排序
  • Spring Boot + ECharts 极简整合指南:从零实现动态数据可视化大屏
  • Java Stream API 详解与实战案例
  • 广东省省考备考(第七十天8.8)——言语、判断推理(强化训练)
  • Ubuntu 22.04 安装 Docker 完整指南
  • flutter TLS protocol versions: (TLSv1.2, TLSv1.3)
  • flutter开发(一)flutter命令行工具
  • Flutter开发 多孩子布局组件
  • 在 Debian 系统上安装 Redis服务
  • VRTE 的应用程序部署到Ubuntu上 报错:bash: ./rb_exmd: No such file or directory
  • Korg 电子琴 2025 高级电子琴手机版:专业的音乐创作与演奏工具
  • 平板探测器的主要技术指标
  • 电脑IP地址是“169.254.x.x”而无法上网的原因
  • ubuntu 22.04 使用yaml文件 修改静态ip
  • 论文阅读:AAAI 2024 ExpeL: LLM Agents Are Experiential Learners
  • openpnp - 不连接设备,只大概测试一下摄像头是否好使
  • Zabbix网络发现:自动化监控新利器
  • TestComplete 如何打造高效UI测试体系?
  • Vue开发的3D全景图效果
  • linux信号量和日志
  • 算法训练之字符串
  • 复杂水文环境下识别精度↑86%!陌讯多模态融合算法在水位监测中的优化实践
  • 四、redis入门之集群部署
  • 富士 Instax 12 和 Instax Mini 11 有什么区别?推荐购买哪一款?
  • 【JMeter】调试取样器的使用
  • 全场景音频工作流实践:Melody如何打造音源管理闭环
  • git | git bash变慢解决
  • 基于 Modbus TCP 的飞升 FSH-CF计量泵多段速控制优化研究
  • pdf文件转word免费使用几个工具
  • react+echarts实现个性化评分展示(类进度条)