diff --git a/ToolsForm/.idea/.idea.ToolsForm/.idea/workspace.xml b/ToolsForm/.idea/.idea.ToolsForm/.idea/workspace.xml
index cfdca45..e8de0fe 100644
--- a/ToolsForm/.idea/.idea.ToolsForm/.idea/workspace.xml
+++ b/ToolsForm/.idea/.idea.ToolsForm/.idea/workspace.xml
@@ -8,20 +8,17 @@
+
-
-
-
-
-
+
@@ -41,6 +38,7 @@
+
@@ -51,10 +49,14 @@
+
+
+
+
{
"customColor": "",
"associatedIndex": 1
@@ -67,32 +69,32 @@
- {
- "keyToString": {
- ".NET 项目.ToolsForm.executor": "Run",
- "ASKED_ADD_EXTERNAL_FILES": "true",
- "RunOnceActivity.ShowReadmeOnStart": "true",
- "XThreadsFramesViewSplitterKey": "0.5078125",
- "git-widget-placeholder": "main",
- "node.js.detected.package.eslint": "true",
- "node.js.detected.package.tslint": "true",
- "node.js.selected.package.eslint": "(autodetect)",
- "node.js.selected.package.tslint": "(autodetect)",
- "nodejs_package_manager_path": "npm",
- "settings.editor.selected.configurable": "preferences.pluginManager",
- "vue.rearranger.settings.migration": "true",
- "发布到文件夹.Publish ToolsForm to folder (1).executor": "Run",
- "发布到文件夹.Publish ToolsForm to folder (2).executor": "Run",
- "发布到文件夹.Publish ToolsForm to folder.executor": "Run"
+
+}]]>
@@ -147,7 +149,7 @@
-
+
@@ -225,32 +227,6 @@
-
- file://$PROJECT_DIR$/ToolsForm/Views/AIWindow.axaml.cs
- 49
-
-
-
-
-
-
-
-
-
-
-
- file://$PROJECT_DIR$/ToolsForm/Views/AIWindow.axaml.cs
- 23
-
-
-
-
-
-
-
-
-
-
diff --git a/ToolsForm/ToolsForm/Manager/SparkWebSDK.cs b/ToolsForm/ToolsForm/Manager/SparkWebSDK.cs
new file mode 100644
index 0000000..7e61f95
--- /dev/null
+++ b/ToolsForm/ToolsForm/Manager/SparkWebSDK.cs
@@ -0,0 +1,323 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Net.WebSockets;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using CommunityToolkit.Mvvm.Messaging.Messages;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace ToolsForm.Models;
+
+public class Header
+{
+ ///
+ ///
+ ///
+ public int code { get; set; }
+
+ ///
+ ///
+ ///
+ public string message { get; set; }
+
+ ///
+ ///
+ ///
+ public string sid { get; set; }
+
+ ///
+ ///
+ ///
+ public int status { get; set; }
+}
+
+public class TextItem
+{
+ ///
+ /// 我可以帮助你的吗?
+ ///
+ public string content { get; set; }
+
+ ///
+ ///
+ ///
+ public string role { get; set; }
+
+ ///
+ ///
+ ///
+ public int index { get; set; }
+}
+
+public class Choices
+{
+ ///
+ ///
+ ///
+ public int status { get; set; }
+
+ ///
+ ///
+ ///
+ public int seq { get; set; }
+
+ ///
+ ///
+ ///
+ public List text { get; set; }
+}
+
+public class Text
+{
+ ///
+ ///
+ ///
+ public int question_tokens { get; set; }
+
+ ///
+ ///
+ ///
+ public int prompt_tokens { get; set; }
+
+ ///
+ ///
+ ///
+ public int completion_tokens { get; set; }
+
+ ///
+ ///
+ ///
+ public int total_tokens { get; set; }
+}
+
+public class Usage
+{
+ ///
+ ///
+ ///
+ public Text text { get; set; }
+}
+
+public class Payload
+{
+ ///
+ ///
+ ///
+ public Choices choices { get; set; }
+
+ ///
+ ///
+ ///
+ public Usage usage { get; set; }
+}
+
+public class ResponseDatas
+{
+ ///
+ ///
+ ///
+ public Header header { get; set; }
+
+ ///
+ ///
+ ///
+ public Payload payload { get; set; }
+}
+
+public class SparkWebSDK
+{
+ string wsChatUrl = "ws://spark-api.xf-yun.com/v1.1/chat";
+ string chat_appid = "a83ddb30";
+ string chat_key = "df2f1b36593607691d184c2282977959";
+ string chat_secret = "ZDUwMjczZjM2YTI2YTVhZDU2MjljZDI4";
+ string clientId = System.Guid.NewGuid().ToString("N");
+ CancellationToken cancellation;
+
+
+ private ClientWebSocket _webSocketClient;
+
+ private string GetAuthUrl()
+ {
+ //当前时间戳,RFC1123格式
+ string date = DateTime.UtcNow.ToString("r");
+ //string date = "Thu, 15 Jun 2023 02:32:41 GMT";
+
+ string host = wsChatUrl.Split("://")[1].Split('/')[0];
+ string localPath = wsChatUrl.Split(host)[1];
+
+ string str = "host: " + host + "\n" + "date: " + date + "\n" + "GET " + localPath + " HTTP/1.1";
+
+ //hmac-sha256计算签名
+ string sha = HMACsha256(chat_secret, str);
+ //授权(api_key,授权算法,头部,签名)
+ //authorization格式:api_key="$api_key",algorithm="hmac-sha256",headers="host date request-line",signature="$signature"
+ string authorization = string.Format("api_key=\"{0}\", algorithm=\"{1}\", headers=\"{2}\", signature=\"{3}\"", chat_key, "hmac-sha256", "host date request-line", sha);
+ //System.Web.HttpUtility.UrlEncode
+
+ //鉴权参数(host,data,authorization):
+ //authorization使用base64编码的签名相关信息(签名基于hmac-sha256计算)
+ string path1 = "authorization" + "=" + Convert.ToBase64String(Encoding.UTF8.GetBytes(authorization));
+ date = date.Replace(" ", "%20").Replace(":", "%3A").Replace(",", "%2C");
+ string path2 = "date" + "=" + date;
+ string path3 = "host" + "=" + host;
+
+ string newurl = wsChatUrl + "?" + path1 + "&" + path2 + "&" + path3;
+ return newurl;
+ }
+
+ private string HMACsha256(string apiSecretIsKey, string buider)
+ {
+ byte[] bytes = Encoding.UTF8.GetBytes(apiSecretIsKey);
+ System.Security.Cryptography.HMACSHA256 hMACSHA256 = new System.Security.Cryptography.HMACSHA256(bytes);
+ byte[] date = Encoding.UTF8.GetBytes(buider);
+ date = hMACSHA256.ComputeHash(date);
+ hMACSHA256.Clear();
+
+ return Convert.ToBase64String(date);
+ }
+
+ // 接收消息方法,改为异步
+async Task ReciceChatAsync(ClientWebSocket ws, CancellationToken cancellationToken)
+{
+ string msgRecive = "";
+ // 全部消息容器
+ List bs = new List();
+ // 缓冲区
+ var buffer = new byte[1024 * 4];
+
+ while (ws.State == WebSocketState.Open)
+ {
+ // 等待接收消息
+ var result = await ws.ReceiveAsync(new ArraySegment(buffer), cancellationToken);
+
+ // 如果关闭了连接
+ if (result.CloseStatus.HasValue)
+ {
+ Console.WriteLine("接收关闭");
+ break;
+ }
+
+ if (result.MessageType == WebSocketMessageType.Text)
+ {
+ bs.AddRange(buffer.Take(result.Count));
+
+ // 判断消息是否已接收完全
+ if (result.EndOfMessage)
+ {
+ // 发送过来的消息
+ string userMsg = Encoding.UTF8.GetString(bs.ToArray(), 0, bs.Count);
+ bs = new List();
+
+ JObject jb = JObject.Parse(userMsg);
+ int code = jb["header"]["code"].ToObject();
+ string sid = jb["header"]["sid"].ToString();
+ int status = jb["header"]["status"].ToObject();
+ string message = jb["header"]["message"].ToString();
+
+ if (code == 0)
+ {
+ // 正常消息处理
+ JToken[] ja = jb["payload"]["choices"]["text"].ToArray();
+ foreach (var item in ja)
+ {
+ msgRecive += item["content"].ToString();
+ }
+
+ if (status == 2)
+ {
+ // 完成
+ Console.WriteLine("最后一条");
+ break;
+ }
+ }
+ else
+ {
+ // 出错
+ Console.WriteLine(message);
+ break;
+ }
+ }
+ }
+ }
+
+ Console.WriteLine("退出接收");
+ return msgRecive;
+}
+
+// 异步调用 API 方法
+ public async Task CallapiForChatAsync(JArray text, CancellationToken cancellationToken)
+ {
+ string response = null;
+
+ string url = GetAuthUrl();
+ using (var ws = new ClientWebSocket())
+ {
+ await ws.ConnectAsync(new Uri(url), cancellationToken);
+
+ if (ws.State == WebSocketState.Open)
+ {
+ // 发送消息
+ JObject data = new JObject();
+ JObject header = new JObject();
+ JObject parameter = new JObject();
+ JObject payload = new JObject();
+ data.Add("header", header);
+ data.Add("parameter", parameter);
+ data.Add("payload", payload);
+ header.Add("app_id", chat_appid);
+ header.Add("uid", clientId);
+ JObject chat = new JObject();
+ parameter.Add("chat", chat);
+ chat.Add("domain", "general");
+ chat.Add("max_tokens", 2048);
+ chat.Add("auditing", "default");
+
+ JObject message = new JObject();
+ payload.Add("message", message);
+ message.Add("text", text);
+
+ string da = data.ToString();
+ var frameData = Encoding.UTF8.GetBytes(da);
+
+ // 发送数据
+ await ws.SendAsync(new ArraySegment(frameData), WebSocketMessageType.Text, true, cancellationToken);
+
+ // 接收响应
+ string msgRecive = await ReciceChatAsync(ws, cancellationToken);
+ response = msgRecive;
+ }
+ else
+ {
+ response = "连接失败";
+ }
+ }
+
+ return response;
+ }
+
+
+
+ async Task ReciceChatAsync(ClientWebSocket ws)
+ {
+ var buffer = new byte[1024];
+ var timeoutTask = Task.Delay(2000); // 超过2秒就超时
+ var receiveTask = ws.ReceiveAsync(new ArraySegment(buffer), cancellation);
+
+ // 等待接收数据或超时,先完成的任务会继续
+ var completedTask = await Task.WhenAny(receiveTask, timeoutTask);
+
+ if (completedTask == timeoutTask)
+ {
+ Console.WriteLine("接收超时");
+ return null; // 或者处理超时逻辑
+ }
+
+ var result = await receiveTask; // 确保完成后再处理接收到的数据
+ return Encoding.UTF8.GetString(buffer, 0, result.Count);
+ }
+}
\ No newline at end of file
diff --git a/ToolsForm/ToolsForm/Views/AIWindow.axaml.cs b/ToolsForm/ToolsForm/Views/AIWindow.axaml.cs
index 42c3441..ba78a27 100644
--- a/ToolsForm/ToolsForm/Views/AIWindow.axaml.cs
+++ b/ToolsForm/ToolsForm/Views/AIWindow.axaml.cs
@@ -1,67 +1,87 @@
- using System.Linq;
- using Avalonia.Controls;
- using Avalonia.Input;
- using Avalonia.Interactivity;
- using Avalonia.Markup.Xaml;
- using ToolsForm.Models; // 引入模型命名空间
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Interactivity;
+using Avalonia.Markup.Xaml;
+using Newtonsoft.Json.Linq;
+using ToolsForm.Models; // 引入模型命名空间
- namespace ToolsForm.Views
+namespace ToolsForm.Views
+{
+ public partial class AIWindow : Window
{
- public partial class AIWindow : Window
+ private DialogueModel dialogueModel;
+ private TextBox inputTextBox;
+ private ItemsControl dialogueItems;
+ private ScrollViewer dialogueScrollViewer;
+
+ private SparkWebSDK _sparkWebSdk;
+
+ public AIWindow()
{
- private DialogueModel dialogueModel;
- private TextBox inputTextBox;
- private ItemsControl dialogueItems;
- private ScrollViewer dialogueScrollViewer;
- public AIWindow()
- {
- InitializeComponent();
- // 初始化控件
- inputTextBox = this.FindControl("InputTextBox");
- dialogueItems = this.FindControl("DialogueItems");
- dialogueScrollViewer= this.FindControl("DialogueScrollViewer");
- dialogueModel = new DialogueModel(); // 创建模型实例
- DataContext = dialogueModel; // 将数据上下文设置为模型
- }
- private void OnInputTextBoxKeyDown(object sender, KeyEventArgs e)
- {
- if (e.Key == Key.Enter) // 检查是否按下 Enter 键
- {
- OnSendButtonClick(sender, e); // 调用发送按钮的点击事件处理程序
- e.Handled = true; // 标记事件已处理,防止进一步处理
- }
- }
- private void OnSendButtonClick(object sender, RoutedEventArgs e)
- {
- var userMessage = inputTextBox.Text;
- if (!string.IsNullOrWhiteSpace(userMessage))
- {
- dialogueModel.AddUserMessage(userMessage);
- inputTextBox.Clear();
+ InitializeComponent();
+ // 初始化控件
+ inputTextBox = this.FindControl("InputTextBox");
+ dialogueItems = this.FindControl("DialogueItems");
+ dialogueScrollViewer = this.FindControl("DialogueScrollViewer");
+ dialogueModel = new DialogueModel(); // 创建模型实例
+ DataContext = dialogueModel; // 将数据上下文设置为模型
- // 发送 AI 回复
- var aiResponse = GenerateAIResponse(userMessage);
- dialogueModel.AddAIResponse(aiResponse);
- // // 自动滚动到最新消息
- // dialogueItems.ScrollIntoView(dialogueModel.Dialogues.Last());
- }
-
+ _sparkWebSdk = new SparkWebSDK();
+ }
+
+ private void OnInputTextBoxKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Key == Key.Enter) // 检查是否按下 Enter 键
+ {
+ OnSendButtonClick(sender, e); // 调用发送按钮的点击事件处理程序
+ e.Handled = true; // 标记事件已处理,防止进一步处理
+ }
+ }
+
+ private async void OnSendButtonClick(object sender, RoutedEventArgs e)
+ {
+ var userMessage = inputTextBox.Text;
+ if (!string.IsNullOrWhiteSpace(userMessage))
+ {
+ dialogueModel.AddUserMessage(userMessage);
+ inputTextBox.Clear();
+
+ // 发送 AI 回复并等待结果
+ var aiResponse = await GenerateAIResponse(userMessage);
+ dialogueModel.AddAIResponse(aiResponse);
+
+ // 自动滚动到最新消息
if (dialogueScrollViewer != null)
{
dialogueScrollViewer.ScrollToEnd();
}
}
-
- private string GenerateAIResponse(string message)
- {
- // TODO: 这里实现AI生成回复的逻辑
- return "这是AI的回复"; // 示例回复
- }
-
- private void InitializeComponent()
- {
- AvaloniaXamlLoader.Load(this);
- }
}
- }
\ No newline at end of file
+
+
+ private async Task GenerateAIResponse(string message)
+ {
+ string mess = "没有数据";
+
+ JArray text = new JArray();
+ JObject jb = new JObject();
+ jb.Add("role", "user");
+ jb.Add("content", message);
+ text.Add(jb);
+
+ // 直接等待 CallapiForChatAsync 返回结果
+ mess = await _sparkWebSdk.CallapiForChatAsync(text, CancellationToken.None);
+
+ return mess; // 返回 AI 回复
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.dll b/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.dll
index 23548ed..b5240a6 100644
Binary files a/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.dll and b/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.dll differ
diff --git a/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.exe b/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.exe
index de613dc..01e8079 100644
Binary files a/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.exe and b/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.exe differ
diff --git a/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.pdb b/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.pdb
index 682a60d..41aa757 100644
Binary files a/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.pdb and b/ToolsForm/ToolsForm/bin/Debug/net8.0/ToolsForm.pdb differ
diff --git a/ToolsForm/ToolsForm/obj/Debug/net8.0/Avalonia/ToolsForm.dll b/ToolsForm/ToolsForm/obj/Debug/net8.0/Avalonia/ToolsForm.dll
index 23548ed..b5240a6 100644
Binary files a/ToolsForm/ToolsForm/obj/Debug/net8.0/Avalonia/ToolsForm.dll and b/ToolsForm/ToolsForm/obj/Debug/net8.0/Avalonia/ToolsForm.dll differ
diff --git a/ToolsForm/ToolsForm/obj/Debug/net8.0/Avalonia/ToolsForm.pdb b/ToolsForm/ToolsForm/obj/Debug/net8.0/Avalonia/ToolsForm.pdb
index 682a60d..41aa757 100644
Binary files a/ToolsForm/ToolsForm/obj/Debug/net8.0/Avalonia/ToolsForm.pdb and b/ToolsForm/ToolsForm/obj/Debug/net8.0/Avalonia/ToolsForm.pdb differ
diff --git a/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.AssemblyInfo.cs b/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.AssemblyInfo.cs
index 85d4eba..880a2ce 100644
--- a/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.AssemblyInfo.cs
+++ b/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.AssemblyInfo.cs
@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("ToolsForm")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
-[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b5da1a7f7c82dcd20f0b21f742568b806e389d75")]
+[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+67f36bcc4da43ad28c0edee61033c6417823236c")]
[assembly: System.Reflection.AssemblyProductAttribute("ToolsForm")]
[assembly: System.Reflection.AssemblyTitleAttribute("ToolsForm")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
diff --git a/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.AssemblyInfoInputs.cache b/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.AssemblyInfoInputs.cache
index 5cc89f5..4744bc5 100644
--- a/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.AssemblyInfoInputs.cache
+++ b/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.AssemblyInfoInputs.cache
@@ -1 +1 @@
-7b96760f001b2471081ba691dfa0e836b351bee82672791a362c10b30535dedd
+b6d965a55222d82d427c73ab54d64fca1a5f960cb20160d77994e28bd488268d
diff --git a/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.csproj.CoreCompileInputs.cache b/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.csproj.CoreCompileInputs.cache
index 0d2f93a..bf4e9a8 100644
--- a/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.csproj.CoreCompileInputs.cache
+++ b/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.csproj.CoreCompileInputs.cache
@@ -1 +1 @@
-bf3fd6b20c8cdf001539f535b65b0d319f4b4f7c5c43d09955e03b2516849197
+9fb7436273386345ad7568271cc196a11cf18d5aadf391ba706c7b48ebe9b994
diff --git a/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.dll b/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.dll
index 989b914..1d49f68 100644
Binary files a/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.dll and b/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.dll differ
diff --git a/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.pdb b/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.pdb
index 813a6f2..0e5bc56 100644
Binary files a/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.pdb and b/ToolsForm/ToolsForm/obj/Debug/net8.0/ToolsForm.pdb differ
diff --git a/ToolsForm/ToolsForm/obj/Debug/net8.0/apphost.exe b/ToolsForm/ToolsForm/obj/Debug/net8.0/apphost.exe
index de613dc..01e8079 100644
Binary files a/ToolsForm/ToolsForm/obj/Debug/net8.0/apphost.exe and b/ToolsForm/ToolsForm/obj/Debug/net8.0/apphost.exe differ
diff --git a/ToolsForm/ToolsForm/obj/Debug/net8.0/ref/ToolsForm.dll b/ToolsForm/ToolsForm/obj/Debug/net8.0/ref/ToolsForm.dll
index 2f79b94..d950481 100644
Binary files a/ToolsForm/ToolsForm/obj/Debug/net8.0/ref/ToolsForm.dll and b/ToolsForm/ToolsForm/obj/Debug/net8.0/ref/ToolsForm.dll differ
diff --git a/ToolsForm/ToolsForm/obj/Debug/net8.0/refint/Avalonia/ToolsForm.dll b/ToolsForm/ToolsForm/obj/Debug/net8.0/refint/Avalonia/ToolsForm.dll
index 2f79b94..d950481 100644
Binary files a/ToolsForm/ToolsForm/obj/Debug/net8.0/refint/Avalonia/ToolsForm.dll and b/ToolsForm/ToolsForm/obj/Debug/net8.0/refint/Avalonia/ToolsForm.dll differ
diff --git a/ToolsForm/ToolsForm/obj/Debug/net8.0/refint/ToolsForm.dll b/ToolsForm/ToolsForm/obj/Debug/net8.0/refint/ToolsForm.dll
index aeb950d..8d781f7 100644
Binary files a/ToolsForm/ToolsForm/obj/Debug/net8.0/refint/ToolsForm.dll and b/ToolsForm/ToolsForm/obj/Debug/net8.0/refint/ToolsForm.dll differ