SemanticKernel/C#:检索增强生成(RAG)简易实践

news/2024/11/10 20:00:10/文章来源:https://www.cnblogs.com/mingupupu/p/18336055

检索增强生成(RAG)是什么?

RAG是“Reference-based Generative model with Attention”的缩写,也可以被称为“Retrieval-Augmented Generation”,是一种结合了检索技术和生成模型的方法,主要用于自然语言处理任务,如文本生成、对话系统、机器翻译等。RAG模型通过从外部知识库中检索相关信息,并将其与输入文本结合,以生成更准确、更丰富的输出。这种方法可以提高模型的准确性和可解释性,因为它可以明确地指出生成的文本与哪些外部知识相关。RAG模型在处理需要大量背景知识的任务时特别有用,如专业领域的问答系统或对话代理。

本示例实现的效果

在使用大语言模型的过程中,会发现大语言模型在通用知识上很强,但是如果你问的是跟私有数据有关的事情,它就不知道了。比如有一段私有文本数据如下所示:

小X于2000年创建了一家名为“小X的世界”的公司,公司总部在湖北武汉,员工有300人。小X最喜欢的编程语言是C#,小X最喜欢的书是《平凡的世界》。

这只是个简单的例子,所以文本先取的很短,实际上可以换成是你的一些私有文档,然后让大语言模型根据你的私有文档进行回答,现在你如果问大语言模型,“小X创建的公司叫什么?”、”小X最喜欢的编程语言是什么?“等等一些根据私有文档才能回答的问题,大语言模型是不知道的,但是通过RAG就可以让大语言模型回答诸如此类的需要根据私有文档才能回答的问题。

image-20240801082308221

image-20240801082408638

实现的思路是通过嵌入模型将文本转化为向量,将向量存入数据库,检索时基于输入查询的向量表示,从知识库中检索出最相关的文档或片段。将获取的相关片段,嵌入到Prompt中,让大语言模型根据获取到的片段进行回答。

开始实践

安装所需的nuget包:

image-20240801082520136

首先先初始化一个Kernel,这里我使用的大语言模型是硅基流动平台提供的开源的Qwen/Qwen2-7B-Instruct。

 private readonly Kernel _kernel;public SemanticKernelService(){var handler = new OpenAIHttpClientHandler();var builder = Kernel.CreateBuilder().AddOpenAIChatCompletion(modelId: "Qwen/Qwen2-7B-Instruct",apiKey: "api key",httpClient: new HttpClient(handler));         var kernel = builder.Build();_kernel = kernel;}

由于硅基流动平台已经提供了与OpenAI兼容的格式,只需要在传入一个HttpClient将请求转发到硅基流动平台的api即可,OpenAIHttpClientHandler类如下所示:

 public class OpenAIHttpClientHandler : HttpClientHandler{protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken){UriBuilder uriBuilder;switch (request.RequestUri?.LocalPath){case "/v1/chat/completions":uriBuilder = new UriBuilder(request.RequestUri){// 这里是你要修改的 URLScheme = "https",Host = "api.siliconflow.cn",Path = "v1/chat/completions",};request.RequestUri = uriBuilder.Uri;break;case "/v1/embeddings":uriBuilder = new UriBuilder(request.RequestUri){// 这里是你要修改的 URLScheme = "https",Host = "api.siliconflow.cn",Path = "v1/embeddings",};request.RequestUri = uriBuilder.Uri;break;}HttpResponseMessage response = await base.SendAsync(request, cancellationToken);return response;}}

现在需要将文本转化为向量,需要先构建一个ISemanticTextMemory:

image-20240801083237027

现在先来看看如何构建一个ISemanticTextMemory:

  public async Task<ISemanticTextMemory> GetTextMemory2(){var memoryBuilder = new MemoryBuilder();memoryBuilder.WithOpenAITextEmbeddingGeneration("text-embedding-ada-002", "api key");           IMemoryStore memoryStore = await SqliteMemoryStore.ConnectAsync("memstore.db");memoryBuilder.WithMemoryStore(memoryStore);var textMemory = memoryBuilder.Build();return textMemory;}

首先需要有一个嵌入模型,这里使用的是OpenAI的text-embedding-ada-002模型,也尝试过使用硅基流动平台提供的嵌入模型,生成向量是没有问题的,但是在搜索的时候会报错,还没有解决。

使用SQLite来存储生成的向量。

 var lines = TextChunker.SplitPlainTextLines(input, 100);var paragraphs = TextChunker.SplitPlainTextParagraphs(lines, 1000);foreach (var para in paragraphs){await textMemory.SaveInformationAsync(index, id: Guid.NewGuid().ToString(), text: para, cancellationToken: default);}

将文本分段,本示例文本内容很少,只有一段。

查看数据库:

image-20240801084335696

已经将向量数据存入数据库了。

现在根据问题,搜索最相关的片段:

image-20240801084459909

以“小X最喜欢的编程语言是什么?”这个问题为例。

image-20240801084808470

将问题转化为向量并利用余弦相似度进行检索搜索最相关的片段:

image-20240801085241311

将获取到的最相关的文本与问题嵌入到Prompt中,让大语言模型回答:

image-20240801085445873

大语言模型的回答结果:

image-20240801085524229

以上就基于SemanticKernel实现了一个简单的RAG应用。

下一步探索方向

虽然说我的电脑本地运行大语言模型不太行,但是在本地运行大语言模型还是有很多需求场景的,下一步探索如何在SemanticKernel中使用本地的大语言模型与嵌入模型。如果大语言模型运行不太行的话,再换成国内的平台,嵌入模型我试过,本地运行也还可以的。

本地运行使用的是Ollama,官方也有计划发布一个Ollama Connector:

image-20240801090623386

image-20240801090825349

网上查了一些资料,有些大佬已经实现了在SemanticKernel中使用Ollama中的对话模型与嵌入模型。可以等官方支持,也可以根据大佬们的分享,自己去实践一下。

Local Memory: C# Semantic Kernel, Ollama and SQLite to manage Chat Memories locally | by John Kane | Medium

Using local LLM with Ollama and Semantic Kernel - Learnings in IT (sachinsu.github.io)

Use Custom and Local AI Models with the Semantic Kernel SDK for .NET | Microsoft Learn

参考

1、https://github.com/microsoft/semantic-kernel/blob/main/dotnet/notebooks/06-memory-and-embeddings.ipynb

2、https://github.com/microsoft/semantic-kernel/blob/main/dotnet/notebooks/09-memory-with-chroma.ipynb

3、https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Memory/MemoryStore_CustomReadOnly.cs

4、https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Memory/SemanticTextMemory_Building.cs

5、https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Memory/TextChunkingAndEmbedding.cs

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

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

相关文章

docker-compose搭建elk

一、准备检查自己的docker 和 docker-compose是否安装完毕,切换docker的镜像源二、安装本次安装的主要组件 包括es 、filebeat、kibana、logstash2.1 先配置组件的挂载点 2.2 配置各组件的相关配置文件es-->config---&g…

save-all-resources | 将指定页面的所有资源存到本地 | chrome插件推荐

save-all-resources https://chromewebstore.google.com/detail/save-all-resources/abpdnfjocnmdomablahdcfnoggeeiedb使用方法: F12 右边选择 ResourceSaver点击右边的 Save All Resources 按钮即可--------------------------------------------- 生活的意义就是你自己知道…

低代码如何借助 K8s 实现高并发支持?

引言 在当今这个数字化时代,互联网的普及和技术的飞速发展使得应用程序面临着前所未有的挑战,其中最为显著的就是高并发访问的需求。随着用户数量的激增和业务规模的扩大,如何确保应用在高并发场景下依然能够稳定运行、快速响应,成为了所有开发者和技术团队必须面对的重要课…

02.计算器存储器的原理

02.计算器存储器的原理 目录介绍01.什么是存储器1.1 了解存储器是什么 1.2 存储器类型02.存储器系统设计2.1 存储器分层设计 2.2 存储器层次结构 2.3 高速缓存设计思想 2.4 虚拟内存访问内存03.存储器类型3.1 按照材质划分 3.2 按芯片类型划分 3.3 内存 vs CPU 3.4 存储器访问权…

自动化生成测试报告(Jemeter)

点击查看代码 E:\apache-jmeter-5.6.3\work>E:\apache-jmeter-5.6.3\bin\jmeter -n -t 模块控制器.jmx -l report.jtl -o E:\apache-jmeter-5.6.3\report

UDS学习总结

1 UDS简介 1.1 什么是UDS UDS (Unified Diagnostic Services) 统一诊断服务,是车辆诊断的一种应用层协议,面向整车所有ECU ,UDS协议ISO 14229定义了应用层和会话层,在协议里面定义了诊断的请求,诊断响应的报文格式,以及ECU怎样处理诊断请求报文,以及诊断服务的应用。它不…

PHP转Go系列 | Carbon 时间处理工具的使用姿势

在日常的开发过程中经常会遇到对时间的处理,比如将时间戳进行格式化、获取昨天或上周或上个月的时间、基于当前时间进行加减等场景的使用大家好,我是码农先森。 在日常的开发过程中经常会遇到对时间的处理,比如将时间戳进行格式化、获取昨天或上周或上个月的时间、基于当前时…

idea设置了maven会自动变回C盘那个

IDE支持Maven包装器,IDEA会将其用于项目,如果不想从包装器中使用Maven。需要将项目中.mvn/wrapper/下的maven-wrapper.properties从项目中删除。 原文链接:https://blog.csdn.net/qq_45972323/article/details/138044146

不知道如何通过OPC文件传输管控,助力企业提高效率与竞争力?

OPC(Open Platform Communications)是一种用于工业自动化和控制系统中设备与软件之间数据交换的通信协议。以下是一些会涉及到OPC文件传输的行业: 工业自动化:用于实现设备、控制系统和软件之间的数据交换,提高生产效率和灵活性。 楼宇自控:用于设备控制和数据通信,确保…

canvas实现截图功能

开篇 最近在做一个图片截图的功能。 因为工作时间很紧张, 当时是使用的是一个截图插件。 周末两天无所事事,来写一个简单版本的截图功能。 因为写的比较简单,如果写的不好,求大佬轻一点喷读取图片并获取图片的宽度和高度思路 首先读取文件我们使用input中类型是file。 我们需…

BI 工具助力企业解锁数字化工厂,开启工业智能新视界

背景 在 2022 年公布的《“十四五”数字经济发展规划》中,政府不断增加对制造业数字化转型的政策支持力度,积极倡导制造企业采用最新技术,提升自动化、数字化和智能化水平。这一举措旨在强化国际竞争力,推动制造业由制造大国向制造强国转变。 然而,在制造业数字化和智能化…

接口依赖处理(Jemeter添加JSON提取器)

操作 1、在对应请求下添加JSON提取器 2、设置想要提取的参数的参数名以及路径 3、将提取到的参数值关联到其他接口 语法格式 1、提取路径格式:$(代表最外层的花括号).K.K 2、关联到其他接口:${K}