基于C#+WPF编写的调用讯飞星火大模型工具

news/2025/2/6 1:57:32/

工具源码:https://github.com/lishuangquan1987/XFYun.SparkChat
工具效果截图:
在这里插入图片描述
支持流式输出:
在这里插入图片描述

其中ApiKey/ApiSecret/AppId需要自己到讯飞星火大模型官网去注册账号申请,免费的。
申请地址:https://xinghuo.xfyun.cn/
在这里插入图片描述
注册之后,在如下的服务管理里面即可看到自己的ApiKey/ApiSecret/AppId
在这里插入图片描述
在这里插入图片描述

拿到了那三个东西之后填入就可以进行聊天啦。
核心代码C#如下:

namespace XFYun.SparkChat.SDK
{public class SparkWebSDK{private string _appId;private string _apiSecret;private string _apiKey;private SparkVersions _version;private ClientWebSocket _webSocketClient;public SparkWebSDK(){}public void Setup(string appId, string apiSecret, string apiKey, SparkVersions version = SparkVersions.V3_0){this._apiKey = apiKey;this._apiSecret = apiSecret;this._appId = appId;this._version = version;}private string GetAuthUrl(string baseUrl, string apiSecret, string apiKey){string date = DateTime.UtcNow.ToString("r");Uri uri = new Uri(baseUrl);var str = $"host: {uri.Host}\ndate: {date}\nGET {uri.LocalPath} HTTP/1.1";//使用apisecret,HMACSHA256算法加密strvar sha256Bytes = new HMACSHA256(Encoding.UTF8.GetBytes(apiSecret)).ComputeHash(Encoding.UTF8.GetBytes(str));var sha256Str = Convert.ToBase64String(sha256Bytes);var authorization = $"api_key=\"{apiKey}\",algorithm=\"hmac-sha256\",headers=\"host date request-line\",signature=\"{sha256Str}\"";//date要做url处理date = Uri.EscapeDataString(date);string newUrl = $"ws://{uri.Host}{uri.LocalPath}?authorization={Convert.ToBase64String(Encoding.UTF8.GetBytes(authorization))}&date={date}&host={uri.Host}";return newUrl;}/// <summary>/// 询问问题,流式调用response/// 返回结果表示调用成功还是失败,如果调用失败,则返回失败原因/// </summary>/// <param name="question"></param>/// <param name="response"></param>/// <returns></returns>public async Task<(bool, string)> Ask(List<string> questions, CancellationToken token, Action<List<string>> responseHandler){try{string url = "";string domain = "";switch (this._version){case SparkVersions.V1_5:url = "ws://spark-api.xf-yun.com/v1.1/chat";domain = "general";break;case SparkVersions.V2_0:url = "ws://spark-api.xf-yun.com/v2.1/chat";domain = "generalv2";break;case SparkVersions.V3_0:url = "ws://spark-api.xf-yun.com/v3.1/chat";domain = "generalv3";break;}var newUrl = GetAuthUrl(url, this._apiSecret, this._apiKey);this._webSocketClient = new ClientWebSocket();await this._webSocketClient.ConnectAsync(new Uri(newUrl), token);var request = new JsonRequest(){Header = new RequestHeader(){AppId = this._appId,Uid = "123"},Parameter = new RequestParameter(){Chat = new RequestChat(){Domain = domain,Temperature = 0.5,MaxTokens = 1024,}},Payload = new RequestPayload(){Message = new RequestMessage(){Text = questions.Select(x => new ReuqestContent(){Role = "user",Content = x}).ToList()}}};var jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(request);await this._webSocketClient.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(jsonStr)), WebSocketMessageType.Text, true, token);var recvBuffer = new byte[1024];while (true){WebSocketReceiveResult result = await this._webSocketClient.ReceiveAsync(new ArraySegment<byte>(recvBuffer), token);if (result.CloseStatus.HasValue) return (true, "");if (result.MessageType == WebSocketMessageType.Text){string recvMsg = Encoding.UTF8.GetString(recvBuffer, 0, result.Count);var response = Newtonsoft.Json.JsonConvert.DeserializeObject<JsonResponse>(recvMsg);if (response.Header.Code != 0){return (false, response.Header.Message);}if (response.Payload.Choices.Status == 2)//最后一个消息{responseHandler?.Invoke(response.Payload.Choices.Text.Select(x => x.Content).ToList());return (true, "调用成功!");}responseHandler?.Invoke(response.Payload.Choices.Text.Select(x => x.Content).ToList());}else if (result.MessageType == WebSocketMessageType.Close){return (false, result.CloseStatusDescription);}}}catch (Exception e){return (false, e.Message);}finally{await this._webSocketClient?.CloseAsync( WebSocketCloseStatus.NormalClosure,"client raise close request",token);}}public async void Close(){if (_webSocketClient != null){await _webSocketClient.CloseAsync(WebSocketCloseStatus.NormalClosure, "正常关闭", new CancellationToken());}}}public enum SparkVersions{V1_5,V2_0,V3_0}}

http://www.ppmy.cn/news/1213736.html

相关文章

C++(20):自定义类型的自定义结构化绑定

C++17引入了map,tuple等类型的结构化绑定,不过有些限制 C++(17):结构化绑定_c++17结构化绑定_风静如云的博客-CSDN博客 C++20允许定制自定义类的结构化绑定,不过需要满足几个条件: 1.在类外实现get<int>(Type)函数、或在类内实现Type::get<int>()成员函数 2…

C++基础(2)——类和对象

目录 1. 类的引入&#xff1a; 2. 类的定义&#xff1a; 2.1类的定义以及基本结构&#xff1a; 2.2 类的访问限定符&#xff1a; 3. 类的声明与定义的分离&#xff1a; 4. 类的实例化&#xff1a; 5. 类的大小计算&#xff1a; 1. 类的引入&#xff1a; 在数据结构系列的…

ETW HOOK原理探析

ETW HOOK研究 文章目录 ETW HOOK研究前言原理探究内核开启ETW日志HOOK ETW修改ETW日志上下文代理GetCpuClock函数寻找SSDT和SSDT Shadow 总结参考 前言 关于ETW是什么我就不多说了&#xff0c;可以通过微软的相关文档了解到。据网上得知这项技术最早被披露于2345的驱动中&…

混合A Star算法

混合A Star算法就是将A*与Lattice Graph相关联。 State Lattice Planner(状态栅格规划) 普通栅格&#xff0c;直接给定栅格距离等就生成了&#xff0c;但是两点之间的路径&#xff0c;机器人并不一定能通过。 状态栅格在普通的栅格化地图的基础上&#xff0c;加多了机器人运…

【博士每天一篇文献-算法】Imposing Connectome-Derived Topology on an Echo State Network

阅读时间&#xff1a;2023-11-5 1 介绍 年份&#xff1a;2022 作者&#xff1a;Jacob Morra, Mark Daley 西部大学 期刊&#xff1a;2022 International Joint Conference on Neural Networks (IJCNN) 引用量&#xff1a;3 研究了果蝇连接图的拓扑结构对混沌时间序列预测中回…

“艾迪-东软杯”第六届武汉理工大学新生程序设计竞赛

A.Capoos Acronym Zero 题目描述 yz 和他的朋友 ea 和 zech 一起养了一群 Capoo。 这些 Capoo 非常聪明&#xff0c;但不知道为什么&#xff0c;它们并没有从三人那里学到怎么写算法题&#xff0c;而是出于某种原因开始研究语言学&#xff0c;并发明了一套自己的暗语。这门暗语…

【JavaEESpring】认识Spring

认识Spring 1. 什么是框架2. SpringBoot 介绍2.1 Spring 的介绍2.2 SpringBoot 1. 什么是框架 框架(Framework) &#xff0c;意思是框架、机制、准则。通俗的来讲: 框架是实现某种功能的半成品, 他提供了⼀些常⽤的⼯具类, 我们在框架的基础上, 可以更加⾼效的进⾏开发 后端框…

C++ 模板保姆级详解——template<class T>(什么是模板?模板分哪几类?模板如何应用?)

目录 一、前言 二、 什么是C模板 &#x1f4a6;泛型编程的思想 &#x1f4a6;C模板的分类 三、函数模板 &#x1f4a6;函数模板概念 &#x1f4a6;函数模板格式 &#x1f4a6;函数模板的原理 &#x1f4a6;函数模板的实例化 &#x1f34e;隐式实例化 &#x1f349;显式实…