记一次WPF集成SemanticKernel+OneAPI+讯飞星火认知大模型实践
开启OneAPI服务
OneAPI介绍
OpenAI 接口管理 & 分发系统,支持 Azure、Anthropic Claude、Google PaLM 2 & Gemini、智谱 ChatGLM、百度文心一言、讯飞星火认知、阿里通义千问、360 智脑以及腾讯混元,可用于二次分发管理 key,仅单可执行文件,已打包好 Docker 镜像,一键部署,开箱即用. OpenAI key management & redistribution system, using a single API for all LLMs, and features an English UI.
项目地址:https://github.com/songquanpeng/one-api
使用OneAPI
基于docker部署:
# 使用 SQLite 的部署命令:
docker run --name one-api -d --restart always -p 3000:3000 -e TZ=Asia/Shanghai -v /home/ubuntu/data/one-api:/data justsong/one-api
# 使用 MySQL 的部署命令,在上面的基础上添加 `-e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi"`,请自行修改数据库连接参数,不清楚如何修改请参见下面环境变量一节。
# 例如:
docker run --name one-api -d --restart always -p 3000:3000 -e SQL_DSN="root:123456@tcp(localhost:3306)/oneapi" -e TZ=Asia/Shanghai -v /home/ubuntu/data/one-api:/data justsong/one-api
部署完成后,打开本地3000端口,如下所示:
初始账户为root,密码为123456。
登录之后,会提示修改密码。
点击渠道,创建新的渠道:
填入自己的大模型密钥。
添加令牌:
测试OneAPI服务是否可用
使用Postman查看接口是否可用:
注意事项:
接口地址
:http://<你的IP地址>:3000/v1/chat/completions
ip地址可通过cmd输入ipconfig查到。
在请求中加入令牌
:
在红框位置输入OneAPI中的令牌。
测试的json
:
{
"model":"SparkDesk",
"messages":[
{
"role":"user",
"content":"你是谁"
}
],
"temperature":0.7
}
星火大模型的响应
:
{
"id": "",
"object": "chat.completion",
"created": 1709004732,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "您好,我是科大讯飞研发的认知智能大模型,我的名字叫讯飞星火认知大模型。我可以和人类进行自然交流,解答问题,高效完成各领域认知智能需求。"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 2,
"completion_tokens": 40,
"total_tokens": 42
}
}
创建WPF项目
SemanticKernel简介
Semantic Kernel 是一个开源 SDK,可让您轻松构建可以调用现有代码的代理。作为高度可扩展的 SDK,可以将语义内核与 OpenAI、Azure OpenAI、Hugging Face 等模型一起使用!通过将现有的 C#、Python 和 Java 代码与这些模型相结合,可以生成用于回答问题和自动执行流程的代理。
安装SemanticKernel
在SemanticKernel中使用星火大模型
创建一个OpenAIHttpClientHandler类
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 = "http",
Host = "你的ip地址",
Port = 3000,
Path = "v1/chat/completions",
};
request.RequestUri = uriBuilder.Uri;
break;
}
// 接着,调用基类的 SendAsync 方法将你的修改后的请求发出去
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
int n = 0;
while ((int)response.StatusCode == 500 && n < 10)
{
response = await base.SendAsync(request, cancellationToken);
n++;
}
return response;
}
}
使用dotenv.net存储敏感数据
在dotenv.net.dll同一路径下,创建一个.env文件:
在.env文件中存储敏感数据:
模型ID要写SparkDesk,注意不要有空格,试过了有空格会报错。
APIKey就是写之前在OneAPI中复制的令牌。
测试能不能用
测试代码如下:
// 加载环境变量
DotEnv.Load();
// 读取环境变量
var envVars = DotEnv.Read();
// Create kernel
var builder = Kernel.CreateBuilder();
var handler = new OpenAIHttpClientHandler();
builder.AddOpenAIChatCompletion(
modelId: envVars["ModeId"],
apiKey: envVars["APIKey"],
httpClient: new HttpClient(handler));
var kernel = builder.Build();
// Create chat history
ChatHistory history = [];
// Get chat completion service
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
// Start the conversation
history.AddUserMessage("你是谁?");
// Enable auto function calling
OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
{
ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
};
// Get the response from the AI
var result = await chatCompletionService.GetChatMessageContentAsync(
history,
executionSettings: openAIPromptExecutionSettings,
kernel: kernel);
// Print the results
Console.WriteLine("Assistant > " + result);
// Add the message from the agent to the chat history
history.AddMessage(result.Role, result.Content);
}
查看结果:
第一次请求失败,为了解决这个问题,我们加了下面这段代码:
int n = 0;
while ((int)response.StatusCode == 500 && n < 10)
{
response = await base.SendAsync(request, cancellationToken);
n++;
}
再请求一遍就成功了。
收到了星火认知大模型的回答。
使用HandyControl构建页面
xaml如下:
<Window x:Class="SK_Wpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:local="clr-namespace:SK_Wpf"
mc:Ignorable="d"
Title="SK_WPF" Height="450" Width="800"
Loaded="Window_Loaded">
<StackPanel Margin="32">
<hc:Row Margin="0,20,0,0">
<hc:Col Span="11">
<StackPanel>
<Button Style="{StaticResource ButtonPrimary}" Content="问AI" Width="80"
Click="Button_Click_1"/>
<hc:TextBox x:Name="textBox1"
Margin="0,20,0,0"
Width="300" Height="200"
AcceptsReturn="True"/>
</StackPanel>
</hc:Col>
<hc:Col Span="2">
<Grid >
<hc:LoadingCircle x:Name="loading1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="Hidden"/>
</Grid>
</hc:Col>
<hc:Col Span="11">
<StackPanel>
<hc:Tag ShowCloseButton="False" Content="AI回答"/>
<RichTextBox x:Name="richTextBox2"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="0,20,0,0"
Width="300" Height="200">
</RichTextBox>
</StackPanel>
</hc:Col>
</hc:Row>
</StackPanel>
</Window>
实现效果如下:
在WPF中集成SK+OneAPI+星火认知大模型
cs如下:
using dotenv.net;
using HandyControl.Controls;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
using SK_Wpf.Plugins;
using System.Net.Http;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SK_Wpf
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : System.Windows.Window
{
IDictionary<string, string>? envVars;
Kernel? kernel;
ChatHistory history = [];
IChatCompletionService chatCompletionService;
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// 加载环境变量
DotEnv.Load();
// 读取环境变量
envVars = DotEnv.Read();
// Create kernel
var builder = Kernel.CreateBuilder();
var handler = new OpenAIHttpClientHandler();
builder.AddOpenAIChatCompletion(
modelId: envVars["ModeId"],
apiKey: envVars["APIKey"],
httpClient: new HttpClient(handler));
builder.Plugins.AddFromType<HelloPlugin>("helloPlugin");
var kernel = builder.Build();
// Get chat completion service
chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
}
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
loading1.Visibility = Visibility.Visible;
string question = textBox1.Text;
// Get user input
history.AddUserMessage(question);
// Enable auto function calling
OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
{
ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
};
// Get the response from the AI
var result = await chatCompletionService.GetChatMessageContentAsync(
history,
executionSettings: openAIPromptExecutionSettings,
kernel: kernel);
// Print the results
richTextBox2.AppendText(result.ToString());
// Add the message from the agent to the chat history
history.AddMessage(result.Role, result.Content);
loading1.Visibility = Visibility.Hidden;
}
}
}
实现效果如下所示:
总结
本文是一次在WPF使用SemanticKernel基于OneAPI集成讯飞星火认知大模型的实践,没有申请OpenAIAPIKey的可以使用讯飞星火认知大模型,现在个人身份认证有送200万token,个人使用可以用很久了。但是效果上肯定和OpenAI还有差别,经过测试,自动本地函数调用,用OpenAI可以用星火认知大模型不行。下期可以写一下两个模型回答的对比。
最后感谢大佬们的分享,见参考。
参考
1、想学Semantic Kernel,没有OpenAI接口该怎么办? (qq.com)
2、实战教学:用Semantic Kernel框架集成腾讯混元大模型应用 (qq.com)