初步体验通过 Semantic Kernel 与自己部署的通义千问开源大模型进行对话

春节之前被 Semantic Kernel 所吸引,开始了解它,学习它。

在写这篇博文之前读了一些英文博文,顺便在这里分享一下:

为了方便学习与体验以及写代码实践 Semantic Kernel,打算自己部署一个对中文友好的开源大模型,于是选择了通义千问

根据通义千问开源仓库中的 README,经过一番折腾,终于部署成功,详见博文 以容器方式部署通义千问 Qwen

紧接着就是尝试通过 Semantic Kernel 与自己部署的通义千问进行对话,在昨天晚上睡觉前初步尝试成功,通过这篇博文记录一下。

主要面临的问题是 Semantic Kernel 与通义千问之间互不支持(内置支持),Semantic Kernel 目前只内置支持 OpenAI 与 Azure OpenAI。幸运的是,通义千问实现了一个四两拔千斤的巧妙能力------提供了兼容 OpenAI api 的 api,于是这个大问题迎刃而解为一个小问题------如何欺骗 Semantic Kernel 让它在请求 OpenAI api 时改道请求自己部署的通义千问模型服务?

在 Semantic Kernel github issue 的一个评论中发现了一个移花接木的巧妙方法------通过 DelegatingHandler 修改 HttpClient 请求的 url。

对应到这里的场景就是修改所请求的 OpenAI api url 中的 schemehost,也就是将 https://api.openai.com 替换为 http://localhost:8901,实现代码如下

cs 复制代码
class QwenRedirectingHandler() : DelegatingHandler(new HttpClientHandler())
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.RequestUri = new UriBuilder(request.RequestUri!) { Scheme = "http", Host = "localhost", Port = 8901 }.Uri;
        return base.SendAsync(request, cancellationToken);
    }
}

移花接木之后本以为初步体验小功告成,却遇到一个小挫折,在用下面的代码发送 prompt 时报错

cs 复制代码
var prompt = @"博客园是什么网站";
var result = await kernel.InvokePromptAsync(prompt);
Console.WriteLine(result);

错误来自通义千问的响应

text 复制代码
{"detail":"Invalid request: Expecting at least one user message."}

后来参考公众号文章利用阿里通义千问和Semantic Kernel,10分钟搭建知识助手中的代码解决了

cs 复制代码
var prompt = @"<message role=""user"">博客园是什么网站</message>";
var summarize = kernel.CreateFunctionFromPrompt(prompt);
var result = kernel.InvokeStreamingAsync(summarize);

await foreach (var item in result)
{
    Console.Write(item.ToString());
}

解决这个问题后,控制台就能看到来自通义千问慢吞吞的吐字回答:

博客园(CNG.cn)是中国最大的IT社区,也是一个专业的程序员学习交流的平台。它提供了一个可以让程序员交流思想、分享经验的环境,并且有多重功能支持用户创建个人博客和参与讨论。

注:这里使用的通义千问模型版本是 Qwen-7B-Chat

到此,初步体验 Semantic Kernel 就小功告成了,下面是完整代码。

cs 复制代码
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;

var builder = Kernel.CreateBuilder();
builder.AddOpenAIChatCompletion("gpt-3.5-turbo", "***");
builder.Services.ConfigureHttpClientDefaults(b =>
    b.ConfigurePrimaryHttpMessageHandler(() => new QwenRedirectingHandler()));

var kernel = builder.Build();

var prompt = @"<message role=""user"">博客园是什么网站</message>";
var summarize = kernel.CreateFunctionFromPrompt(prompt);
var result = kernel.InvokeStreamingAsync(summarize);

await foreach (var item in result)
{
    Console.Write(item.ToString());
}

class QwenRedirectingHandler() : DelegatingHandler(new HttpClientHandler())
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.RequestUri = new UriBuilder(request.RequestUri!) { Scheme = "http", Host = "localhost", Port = 8901 }.Uri;
        return base.SendAsync(request, cancellationToken);
    }
}
相关推荐
j_xxx404_2 小时前
MySQL表操作硬核解析:从 CREATE TABLE 到磁盘文件、ALTER TABLE 与 DDL 风险
运维·服务器·数据库·c++·mysql·adb·ai
周易宅2 小时前
Hermes Agent 内部/后端命令速查表
ai·agent·hermes
Jackeyzhe3 小时前
让 3 个 AI 一起写公众号:一篇 Hermes 多 Agent 实操
ai
AI导出鸭PC端4 小时前
智谱清言怎么生成word文档?AI导出鸭终结乱码烦恼
人工智能·ai·c#·word·豆包·ai导出鸭
iChochy4 小时前
通过 ZenMux 使用 Claude Code CLI 解锁更多 AI 模型,包括 Claude 所有模型
ai·claude
Nile4 小时前
Claude Code-Dynamic Workflows:1.为什么用工作流?
人工智能·ai·ai编程·ai-native
j_xxx404_5 小时前
MySQL库操作硬核解析:字符集、校验规则、大小写比较、备份恢复与连接排查
运维·服务器·数据库·人工智能·mysql·ai·oracle
龙骑士baby5 小时前
重建 AI 认知第 4 篇:Skill——提示词的系统化封装
ai·大模型·llm·prompt·skill
xixixi777776 小时前
空天地通信、高速光模块、AI 智能体攻击、同态加密芯片四大事件解读:AI 算力底座攻防与全域通信同步升级
大数据·人工智能·深度学习·ai·大模型·光模块·智能体
天工开物开源基金会6 小时前
中国首个!OPC AI开源生态孵化中心落地武汉,打通“人才+赛事+认证+孵化”完整闭环
ai·opc·武汉