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

工具源码: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算法加密str
            var 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
    }


}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/136522.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode—2469.温度转换【简单】

2023每日刷题&#xff08;二十六&#xff09; Leetcode—2469.温度转换 实现代码 /*** Note: The returned array must be malloced, assume caller calls free().*/ double* convertTemperature(double celsius, int* returnSize) {double* ans (double *)malloc(sizeof(do…

ValueError: ‘x‘ and ‘y‘ must have the same size

ValueError: ‘x’ and ‘y’ must have the same size 问题描述 出错代码 axes[0].errorbar(dates_of_observation, observed_lai, yerrstd_lai, fmt"o")X是观测的日期&#xff0c;16天&#xff0c;而且数据也是对应的16个&#xff0c;为什么不对应呢&#xff1f;…

字节面试:请说一下DDD的流程,用电商系统为场景

说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业字节、如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 谈谈你的DDD落地经验&#xff1f; 谈谈你对DDD的理解&…

C++语法---模板进阶知识

绪论​ “那些看似不起波澜的日复一日&#xff0c;会在某天让你看到坚持的意义。”本篇文章主要写到非类型的模板参数、模板的特化、模板的分离编译问题、以及适配器和仿函数的使用讲解&#xff0c;在之前已经将模板的基本使用进行了学习&#xff08;可见c模板&#xff09;话不…

fastANI-基因组平均核酸一致性(ANI)计算

文章目录 简介安装使用Many to Man-使用基因组路径作为输入One to One 结果其他参数说明可视化两个基因组之间的保守区域并行化 简介 FastANI 是为快速计算全基因组平均核苷酸同一性&#xff08;Average Nucleotide Identity&#xff0c;ANI&#xff09;而开发的&#xff0c;无…

【学习笔记】Understanding LSTM Networks

Understanding LSTM Networks 前言Recurrent Neural NetworksThe Problem of Long-Term DependenciesLSTM Networks The Core Idea Behind LSTMsStep-by-Step LSTM Walk ThroughForget Gate LayerInput Gate LayerOutput Gate Layer Variants on Long Short Term MemoryConclus…

java--JDBC学习

文章目录 今日内容0 复习昨日1 JDBC概述2 JDBC开发步骤2.1 创建java项目2.2 导入mysql驱动包2.2.1 复制粘贴版本2.2.2 idea导入类库版本 2.3 JDBC编程 3 完成增删改3.1 插入3.2 更新3.3 删除 4 查询结果集ResultSet【重要】5 登录案例【重要】6 作业 今日内容 0 复习昨日 1 JDB…

二十五、城市建成区结果制图——复杂图的制作

一、前言 有些时候看到一些参考文献中有些很复杂的图,例如多幅合并在一起,其实这种图本质上就是单一的图合并在一起,然后将其导出即可。 二、具体操作 其实对于制图必备要素的添加就不过多介绍,主要介绍有什么办法保持图形之间一致性,例如,其图例、指北针、比例尺统一…

vColorPicker与vue3-colorPicker——基于 Vue 的颜色选择器插件

文章目录 前言样例特点 一、使用步骤&#xff1f;1. 安装2.引入3.在项目中使用 vcolorpicker 二、选项三、事件四、问题反馈问题所在安装引入例子效果图 前言 vColorPicker——官网 vColorPicker——GitHub 样例 vColorPicker是基于 Vue 的一款颜色选择器插件&#xff0c;仿照…

自定义Graph Component:1-开发指南

可以使用自定义NLU组件和策略扩展Rasa&#xff0c;本文提供了如何开发自己的自定义Graph Component指南。   Rasa提供各种开箱即用的NLU组件和策略。可以使用自定义Graph Component对其进行自定义或从头开始创建自己的组件。   要在Rasa中使用自定义Graph Component&#x…

Oracle(2-1) Networking Overview

文章目录 一、基础知识1、Network Environ Challenges 网络环境挑战2、Simple Network :2-Tier 简单的两层网络3、Simple to Complex : N-Tier 简单到复杂&#xff1a;N层网络4、Oracle Network Solutions Oracle网络解决方案5、Key Features of Oracle Net Oracle Net的主要功…

Linux必备:这十个流程图让你变的更强!

图是我们与信息联系并处理其重要性的绝佳方法&#xff1b;它们有助于传达关系和抽取信息&#xff0c;并使我们能够可视化概念。 从基本工作流程图到复杂的网络图&#xff0c;组织图&#xff0c;BPMN&#xff08;业务过程模型和符号&#xff09;&#xff0c;UML图等等&#xff0…

关于值传递和引用传递的问题记录

目录 1. 问题概述 1.1 测试 1.2 结果 2. ArrayList和Arrays.ArrayList 1. 问题概述 最近忙着写论文很久没更新了&#xff0c;趁现在有时间简单记录一下最近遇到的一个坑。 对于Java中的List<>类型的对象&#xff0c;按我以前理解是引用传递&#xff0c;但有一点要注…

第一百七十回 Material3中的IconButton

文章目录 1. 概念介绍2. 使用方法2.1 filled风格2.2 filledTonal风格2.3 outlined风格 3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"如何修改NavigationBar组件的形状"相关的内容&#xff0c;本章回中将 介绍IconButtion组件.闲话休…

【入门Flink】- 10基于时间的双流联合(join)

统计固定时间内两条流数据的匹配情况&#xff0c;需要自定义来实现——可以用窗口&#xff08;window&#xff09;来表示。为了更方便地实现基于时间的合流操作&#xff0c;Flink 的 DataStrema API 提供了内置的 join 算子。 窗口联结&#xff08;Window Join&#xff09; 一…

数据结构—内部排序(上)

文章目录 8.内部排序(上)(1).排序基础#1.为什么是内部排序#2.排序的稳定性 (2).冒泡排序#1.算法思想#2.代码实现#3.稳定性与时间复杂度分析 (3).选择排序#1.算法思想#2.代码实现#3.稳定性与时间复杂度分析 (4).插入排序#1.算法思想#2.代码实现#3.稳定性与时间复杂度分析 (5).希…

vue+mongodb+nodejs实现表单增删改查

ExpressMongodbVue实现增删改查 效果图 前言 最近一直想学下node,毕竟会node的前端更有市场。但是光看不练&#xff0c;感觉还是少了点什么&#xff0c;就去github上看别人写的项目&#xff0c;收获颇丰&#xff0c;于是准备自己照葫芦画瓢写一个。 作为程序员&#xff0c;一…

Flutter:改变手机状态栏颜色,与appBar状态颜色抱持一致

前言 最近在搞app的开发&#xff0c;本来没怎么注意appBar与手机状态栏颜色的问题。但是朋友一说才注意到这两种的颜色是不一样的。 我的app 京东 qq音乐 这样一对比发现是有的丑啊&#xff0c;那么如何实现呢&#xff1f; 实现 怎么说呢&#xff0c;真不会。百度到的一些是…

Android开发之apk瘦身计划

为什么apk越来越大&#xff1f; 1.项目不断发展&#xff0c;功能越多&#xff0c;代码量增加的同时&#xff0c;资源文件也在不断的增多。 2.app支持的主流dpi越来越多&#xff0c;如ldpi、mdpi、hdpi、xh xxh xxxh等等&#xff0c;间接导致资源增多。 3.引入的第三方sdk或开…

软件测试面试-银行篇

今天参加了一场比较正式的面试&#xff0c;汇丰银行的视频面试。在这里把面试的流程记录一下&#xff0c;结果还不确定&#xff0c;但是面试也是自我学习和成长的过程&#xff0c;所以记录下来大家也可以互相探讨一下。 请你做一下自我介绍&#xff1f;&#xff08;汇丰要求英…