首页 > 编程语言 >SemanticKernel/C#:检索增强生成(RAG)简易实践

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

时间:2024-08-01 10:09:49浏览次数:11  
标签:RAG 语言 kernel C# 模型 var 文本 SemanticKernel

检索增强生成(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)
                 {
                     // 这里是你要修改的 URL
                     Scheme = "https",
                     Host = "api.siliconflow.cn",
                     Path = "v1/chat/completions",
                 };
                 request.RequestUri = uriBuilder.Uri;
                 break;

             case "/v1/embeddings":
                 uriBuilder = new UriBuilder(request.RequestUri)
                 {
                     // 这里是你要修改的 URL
                     Scheme = "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

标签:RAG,语言,kernel,C#,模型,var,文本,SemanticKernel
From: https://www.cnblogs.com/mingupupu/p/18336055

相关文章

  • 数学四则运算批计算软件Four mathematical operations Batch Software Cmpt4 download
    数学四则运算批计算软件FourmathematicaloperationsBatchSoftwareCmpt4download该软件能批量计算输入数据的自定义的四则计算。算是一个小型的数学自动化计算的软件。本软件是共享软件,支持Windows64位系统,也可以在兼容WinXP的32位系统上运行。本软件注册费用是48人民币......
  • LeetCode 2024/8 每日一题合集
    2024-7-1LCP40.心算挑战代码实现classSolution{public:intmaxmiumScore(vector<int>&cards,intcnt){intn=size(cards);std::sort(cards.rbegin(),cards.rend());intsum=std::accumulate(cards.begin(),cards.begin()......
  • CodeForces 908C New Year and Curling
    题目链接:CodeForces908C【NewYearandCurling】思路    模拟,考虑到两个圆盘可能出现y值相同且相接的情况,所以在判断当前圆盘的y值时循环的范围从在前圆盘的x值左右浮动2r,依次遍历这个范围内的数组y(存储的是当前已经移动了圆盘中的横坐标为i的圆盘的最大的y值),然后可......
  • hashCode方法 和 equals()方法
    packagecom.coding.spring.mvc;importjava.util.HashSet;publicclassUser{privateStringname;publicUser(Stringname){this.name=name;}@Overridepublicbooleanequals(Objectobj){Useruser=(User)obj;......
  • DevExpress WPF中文教程:如何将GridControl的更改发布到数据库?
    DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。无论是Office办公软件的衍伸产品,还是以数据为中心......
  • save-all-resources | 将指定页面的所有资源存到本地 | chrome插件推荐
    save-all-resourceshttps://chromewebstore.google.com/detail/save-all-resources/abpdnfjocnmdomablahdcfnoggeeiedb使用方法:F12右边选择ResourceSaver点击右边的SaveAllResources按钮即可推荐一个three.js撒筛子的demohttps://codepen.io/fuzionix/pen/KKjgVa......
  • debian 或ubuntu安装使用tigervnc
    一、tigervnc官网https://tigervnc.org/二、安装tigervnc注意:tigervnc需要系统具有桌面环境,如果没有桌面环境需要先安装aptinstalltigervnc-standalone-server三、设置连接密码vncpasswd四、启动tigervnctigervncserver:1-localhostno-geometry1920x1080#......
  • P7215 [JOISC2020] 首都]
    P7215[JOISC2020]首都考虑对于颜色\(c_i\),若在此颜色集合内所有节点之间的路径上出现了其他颜色(如\(c_j\)),那我们则不得不将这两种颜色合并在一起,操作数加一。即对于颜色\(c_i\),若设其为首都,其答案(操作数)为所有颜色为\(c_i\)的节点之间的路径上的颜色种类......
  • docker-compose搭建elk
    一、准备检查自己的docker和docker-compose是否安装完毕,切换docker的镜像源 二、安装本次安装的主要组件包括es、filebeat、kibana、logstash   2.1先配置组件的挂载点                       ......
  • CSP-J2019公交换乘
    马上CSP2024了,做题ing...(题目描述戳它思路1.用结构体双端队列存票,用双端队列的原因是后面要遍历2.结构体元素:price+time+used3.过期的票要及时pop4.不要一边遍历一边pop,用used标记代码#include<bits/stdc++.h>usingnamespacestd;structTicket{intprice......