• 基于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;
            }
            /// 
            /// 询问问题,流式调用response
            /// 返回结果表示调用成功还是失败,如果调用失败,则返回失败原因
            /// 
            /// 
            /// 
            /// 
            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
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
  • 相关阅读:
    计算机毕业设计Java大学生就业招聘系统(源码+系统+mysql数据库+lw文档)
    Android实战——一步一步实现流动的炫彩边框
    拍摄视频,真的帧率越高越好吗?
    使用xml、ftl模板生成word文档,下载到浏览器或指定位置
    依汇心理系统搭建平台模式
    K8S 在docker上部署 Selenium Grid (最新版)
    Linux服务器安装部署最新稳定版本mongoDB社区版- Ubuntu-20.04版本
    Android中如何通过perfetto抓取trace
    王道408计组汇编语言部分学习总结
    Debezium日常分享系列之:Debezium2.4版本之用于 MongoDB的Debezium 连接器
  • 原文地址:https://blog.csdn.net/lishuangquan1987/article/details/134363715