Semantic Kernel:用Embedding做客服(RAG)

RAG(Retrieval-Augmented Generation)是一种结合信息检索和生成模型的自然语言处理方法。它通过检索相关文档片段作为生成模型的上下文,提高生成文本的准确性和相关性。RAG广泛应用于问答系统、对话系统和文本摘要等领域,兼具高效性和灵活性。公司的客户机器人都特别适合。

下面的案例是使用GPT的embedding来向量化相关信息,然后通过关键字检索,最后把这些信息,结合用户问题送给gpt-4o,得到一个相对友好的回复结果。

具体实现如下:

using Azure.AI.OpenAI;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using Microsoft.SemanticKernel.Connectors.Redis;
using Microsoft.SemanticKernel.Memory;
using StackExchange.Redis;
using System.Runtime.CompilerServices;
using System.Text;

var chatModelId = “gpt-4o”;
var embeddingId = “text-embedding-ada-002”;
var key = File.ReadAllText(@”C:\GPT\key.txt”);

pragma warning disable SKEXP0020

pragma warning disable SKEXP0010

pragma warning disable SKEXP0001

var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion(chatModelId, key)
.Build();

var connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(new ConfigurationOptions
{
EndPoints = { “localhost:6379” },
ConnectTimeout = 10000,
ConnectRetry = 3

});
var database = connectionMultiplexer.GetDatabase();
var store = new RedisMemoryStore(database, vectorSize: 1536);
var embeddingGenerator = new OpenAITextEmbeddingGenerationService(embeddingId, key);
var memory = new SemanticTextMemory(store, embeddingGenerator);
var dic = new Dictionary
{
{“name”,”我的名字是桂素伟” },
{“age”,”我今年30岁” },
{“job”,”我是一位.net高级讲师” },
{“experience”,”我有10年的.net开发经验” },
{“skill”,”我精通.net core、asp.net core、微服务、docker、k8s等技术” },
{“hobby”,”我喜欢阅读、写作、旅行” },
{“motto”,”我的座右铭是:行成于思,毁于随” }
};
foreach (var item in dic)
{
await memory.SaveInformationAsync(“ask”, id: item.Key, text: item.Value);
}

var chatHistory = new ChatHistory();
var chat = kernel.GetRequiredService();
var settings = new PromptExecutionSettings
{
ExtensionData = new Dictionary
{
[“max_tokens”] = 1000,
[“temperature”] = 0.2,
[“top_p”] = 0.8,
[“presence_penalty”] = 0.0,
[“frequency_penalty”] = 0.0
}
};
while (true)
{
Console.ResetColor();
Console.WriteLine(“———-学生提问:———-“);
var ask = Console.ReadLine();
chatHistory.Clear();
chatHistory.AddSystemMessage(“基于下面的信息回复问题:”);
await foreach (var answer in memory.SearchAsync(
collection: “ask”,
query: ask,
limit: 3,
minRelevanceScore: 0.65d,
withEmbeddings: true))
{
chatHistory.AddSystemMessage(answer.Metadata.Text);
};

chatHistory.AddUserMessage(ask);
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine( "==========讲师回答:==========");
AuthorRole? role = AuthorRole.Assistant;
var contentBuilder = new StringBuilder();
await foreach (var reply in chat.GetStreamingChatMessageContentsAsync(chatHistory, settings))
{
    if (reply.Role.HasValue && role != reply.Role)
    {
        role = reply.Role;
    }
    Console.Write(reply.Content);
    contentBuilder.Append(reply.Content);
}
chatHistory.AddMessage(role.Value, contentBuilder.ToString());
Console.WriteLine();

}
用户提问后,第一步,把问题送给memory,在67行,利用Search来查看结果,SemanticTextMemory会把相关的几个(取决于配置参数)结果返回,74行添加到chatHistory中。第二步77行再把用户的问题结合进来,一起送给GPT,就相当于把答案相关的信息和问题一些送给GPT,GPT汇总结果后返回。

虽然RAG在一定程序上能把私用化个体化的数据,结合LLM的能力返回,但毕竟这是固定映射,也就是向量化的数据进去是什么,在Seach后,只是把语意相近的返回,但对于一些需要大量上下文才能得出结果的查询就无能为力,或效果很差了。

最近比较多的GraphRAG,就是一个很好的解决方案,不过就是在建立和查询检索时有点小贵,相信随着技术的成熟和时间的推移,有更完善的方案出现。

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/419293.html

(0)
联系我们
联系我们
分享本页
返回顶部