记一次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)
3、Create AI agents with Semantic Kernel | Microsoft Learn
记一次WPF集成SemanticKernel+OneAPI+讯飞星火认知大模型实践的更多相关文章
- Android Studio快速集成讯飞SDK实现文字朗读功能
今天,我们来学习一下怎么在Android Studio快速集成讯飞SDK实现文字朗读功能,先看一下效果图: 第一步 :了解TTS语音服务 TTS的全称为Text To Speech,即“从文本到语音” ...
- 讯飞语音唤醒SDK集成流程
唤醒功能,顾名思义,通过语音,唤醒服务,做我们想做的事情. 效果图(开启应用后说讯飞语音或者讯飞语点唤醒) 源码下载 地址:http://download.csdn.net/detail/q48788 ...
- iOS开发讯飞语音的集成
1.进入官网注册账号,登陆,注册,应用. 2,下载sdk 导入系统库. 3,关闭bitcode 4,初始化讯飞语音. NSString * initString = [[NSString alloc ...
- 集成讯飞听写iOS sdk到unity遇到的问题:weak成员和strong成员
在unity里集成讯飞语音听写iOS sdk的过程中,遇到一个问题,官方的demo中可以将多次onResults回调返回的结果累积拼接起来组成一个完整的结果,而我集成过来以后就不能累积了,只拿到最后一 ...
- UE4 集成讯飞听写插件
搞了几天,有些坑记录一下. 3个方面的知识需要学习 1.制作UE4插件 2.引入第三方库 3.讯飞听写的api 一看是参考 https://blog.csdn.net/u012793104/artic ...
- 一百元的智能家居——Asp.Net Mvc Api+讯飞语音+Android+Arduino
大半夜的,先说些废话提提神 如今智能家居已经不再停留在概念阶段,高大上的科技公司都已经推出了自己的部分或全套的智能家居解决方案,不过就目前的现状而言,大多还停留在展厅阶段,还没有广泛的推广起来,有人说 ...
- Android讯飞语音云语音听写学习
讯飞语音云语音听写学习 这几天两个舍友都买了iPhone 6S,玩起了"Hey, Siri",我依旧对我的Nexus 5喊着"OK,Google" ...
- iOS: 讯飞语音的使用
一.介绍: 讯飞语音做的相当不错,容错率达到90%多,如果需要做语音方面的功能,它绝对是一个不错的选择.讯飞语音的功能很多:语音听写.语音识别.语音合成等,但我们最常用的还是语音听写.讯飞语音中包含界 ...
- android讯飞语音开发常遇到的问题
场景:android项目中共使用了3个语音组件:在线语音听写.离线语音合成.离线语音识别 11208:遇到这个错误,授权应用失败,先检查装机量(3台测试权限),以及appid的申请时间(35天期限), ...
- 讯飞语音JavaWeb语音合成解决方案
在线语音合成 将文字信息转化为声音信息,给应用配上"嘴巴".我们提供了众多极具特色的发音人(音库)供您选择.其合成音在音色.自然度等方面的表现均接近甚至超过了人声.这种语音合成体验 ...
随机推荐
- [转帖]Skywalking介绍
https://www.jianshu.com/p/ffa7ddcda4ab 微服务架构已经是一个很通用的系统架构,常见的技术栈如下图所示,这张架构图基本涵括了当前微服务体系下的各种技术栈,可能不同的 ...
- [转帖]History of Web Browser Engines from 1990 until today
https://eylenburg.github.io/browser_engines.htm Many tried, few remain... Last updated: January 2023 ...
- [转帖]shell脚本变量详解(自定义变量、环境变量、变量赋值、变量运算、变量内容替换)
https://developer.aliyun.com/article/885658 简介: shell变量 shell变量是指用一个特定的字符串去表示不固定的内容 1.变量的类型 1.1自定义变量 ...
- fio test 简单查看一些系统的io性能结果
简单测试的脚本: echo "本次测试测试128k 16k 8k 1k 的 顺序读写 随机读写性能,每个脚本耗时约30s, 总计耗时大约8min左右完成: " fio -name= ...
- echarts轮训展示某个
//学校资产占比的配置 function schollAssets() { var myChart = window.$echarts.init( document.getElementById('s ...
- js解析上传APK文件的详细信息
前端解析APK版本信息 需要安装这个包,可以使用cnpm或者npm npm 安装 app-info-parser ( 命令:npm install app-info-parser) APKInfo为i ...
- Vue基础系列文章11---router基本使用
1.系统中引入路由js文件,加两个连接,分别到用户管理和用户注册页面 <router-link to="/user">用户列表</router-link> ...
- miniIO系列文章03---abpvext中集成
在Abp商业版本中已经提供了文件管理模块的,免费版本是没有的,本文将介绍如何使用Minio打造一个自己的文件管理模块. 在项目开始之前,需要先安装一个Minio服务,可以在本地pc或云主机中安装,具体 ...
- Xmind永久会员版本
Xmind软件不要多介绍了思维导图最好用的软件 PJ后可以直接使用高级版本功能如图 使用方式 下载我们提供的版本和.dll即可如图 点击Xmind安装默认C盘不可以自定义位置 安装完成后进入patch ...
- 手撕Vue-实现将数据代理到Vue实例
前言 经过上一篇文章的学习,完成了 v-on 指令的实现,接下来我们来实现将数据代理到 Vue 实例上. 为什么要完成这个功能呢?因为我们在使用 Vue 的时候,可以直接通过 this.xxx 的方式 ...