From 23c60b9c34267bbef1aea9bf165e66bbfcaf69da Mon Sep 17 00:00:00 2001 From: PeterZhong Date: Sat, 31 May 2025 21:39:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=8E=A8=E7=90=86=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=EF=BC=8C=E8=BF=81=E7=A7=BB=E8=87=B3qwen3=E5=BC=80?= =?UTF-8?q?=E6=BA=90=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/tool/ArcGisPro.cs | 17 ++++++++++++++--- common/HttpRequest.cs | 4 ++-- host/Gateway.cs | 13 ++++++++++++- host/llm/Bailian.cs | 16 +++++++++++----- host/llm/Llm.cs | 3 ++- host/llm/entity/LlmJsonContent.cs | 9 +++++++++ host/llm/entity/stream/LlmStreamChat.cs | 2 ++ server/JsonRpcResultEntity.cs | 2 +- ui/dockpane/TestDockpane.xaml.cs | 12 +++++++++--- ui/message/MessageListItem.cs | 1 + 10 files changed, 63 insertions(+), 16 deletions(-) diff --git a/client/tool/ArcGisPro.cs b/client/tool/ArcGisPro.cs index f1b9866..52994b0 100644 --- a/client/tool/ArcGisPro.cs +++ b/client/tool/ArcGisPro.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Text; using System.Threading.Tasks; using ArcGIS.Core.Data; using ArcGIS.Core.Data.Raster; @@ -33,7 +34,7 @@ public class ArcGisPro Error = new Error() { Code = results.ErrorCode, - Message = JsonConvert.SerializeObject(results.ErrorMessages) + Message = GetMessagesString(results.ErrorMessages) } }; }else if(results.HasWarnings) @@ -41,7 +42,7 @@ public class ArcGisPro log.Warn(results.Messages); jsonRpcResultEntity = new JsonRpcSuccessEntity { - Result = JsonConvert.SerializeObject(results.Messages) + Result = GetMessagesString(results.Messages) }; } else @@ -49,7 +50,7 @@ public class ArcGisPro log.Info("success gp tool"); jsonRpcResultEntity = new JsonRpcSuccessEntity { - Result = JsonConvert.SerializeObject(results.Messages) + Result = GetMessagesString(results.Messages) }; } return jsonRpcResultEntity; @@ -135,4 +136,14 @@ public class ArcGisPro }; return result; } + + private static string GetMessagesString(IEnumerable messages) + { + StringBuilder messagesStr = new StringBuilder(); + foreach (var gpMessage in messages) + { + messagesStr.AppendLine(gpMessage.Text); + } + return messagesStr.ToString(); + } } \ No newline at end of file diff --git a/common/HttpRequest.cs b/common/HttpRequest.cs index 16c9383..5d42052 100644 --- a/common/HttpRequest.cs +++ b/common/HttpRequest.cs @@ -67,7 +67,7 @@ public class HttpRequest return null; } - public static async IAsyncEnumerable PostWithStreamingResponseAsync( + public static async IAsyncEnumerable PostWithStreamingResponseAsync( string url, string body, string apiKey, @@ -114,7 +114,7 @@ public class HttpRequest if (dataObj is not null) { - yield return dataObj.Choices[0].Delta.Content; + yield return dataObj; } } } diff --git a/host/Gateway.cs b/host/Gateway.cs index f13f3ff..58dc92e 100644 --- a/host/Gateway.cs +++ b/host/Gateway.cs @@ -32,6 +32,7 @@ using Newtonsoft.Json.Schema; using Newtonsoft.Json.Schema.Generation; using Tool = LinkToolAddin.host.mcp.Tool; using LinkToolAddin.common; +using LinkToolAddin.host.llm.entity.stream; namespace LinkToolAddin.host; @@ -303,12 +304,22 @@ public class Gateway goOn = false; break; } - await foreach(var chunk in bailian.SendChatStreamAsync(jsonContent)) + await foreach(LlmStreamChat llmStreamChat in bailian.SendChatStreamAsync(jsonContent)) { if (!goOn) { break; } + + string chunk = llmStreamChat.Choices[0].Delta.Content; + MessageListItem reasonMessageListItem = new ChatMessageItem() + { + content = llmStreamChat.Choices[0].Delta.ResoningContent, + role = "assistant", + type = MessageType.REASON_MESSAGE, + id = (timestamp-1).ToString() + }; + callback?.Invoke(reasonMessageListItem); messageContent = chunk; var (matched, remaining) = ExtractMatchedPart(chunk, toolPattern); if (matched == "") diff --git a/host/llm/Bailian.cs b/host/llm/Bailian.cs index b43eed0..6d7d273 100644 --- a/host/llm/Bailian.cs +++ b/host/llm/Bailian.cs @@ -6,6 +6,7 @@ using System.Text; using System.Threading.Tasks; using LinkToolAddin.common; using LinkToolAddin.host.llm.entity; +using LinkToolAddin.host.llm.entity.stream; using Newtonsoft.Json; namespace LinkToolAddin.host.llm; @@ -18,17 +19,22 @@ public class Bailian : Llm public string max_tokens { get; set; } public string app_id { get; set; } public string api_key { get; set; } - public async IAsyncEnumerable SendChatStreamAsync(LlmJsonContent jsonContent) + public async IAsyncEnumerable SendChatStreamAsync(LlmJsonContent jsonContent) { jsonContent.Stream = true; - StringBuilder builder = new StringBuilder(); - await foreach (var chunk in HttpRequest.PostWithStreamingResponseAsync( + StringBuilder contentBuilder = new StringBuilder(); + StringBuilder reasonBuilder = new StringBuilder(); + await foreach (LlmStreamChat chunk in HttpRequest.PostWithStreamingResponseAsync( "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions", JsonConvert.SerializeObject(jsonContent), api_key)) { - builder.Append(chunk); - yield return builder.ToString(); + contentBuilder.Append(chunk.Choices[0].Delta.Content); + reasonBuilder.Append(chunk.Choices[0].Delta.ResoningContent); + LlmStreamChat fullChunk = chunk; + fullChunk.Choices[0].Delta.Content = contentBuilder.ToString(); + fullChunk.Choices[0].Delta.ResoningContent = reasonBuilder.ToString(); + yield return fullChunk; } } diff --git a/host/llm/Llm.cs b/host/llm/Llm.cs index 1807b9d..bb3ba53 100644 --- a/host/llm/Llm.cs +++ b/host/llm/Llm.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using LinkToolAddin.host.llm.entity; +using LinkToolAddin.host.llm.entity.stream; namespace LinkToolAddin.host.llm; @@ -11,7 +12,7 @@ public interface Llm public string top_p { get; set; } public string max_tokens { get; set; } - public IAsyncEnumerable SendChatStreamAsync(LlmJsonContent jsonContent); + public IAsyncEnumerable SendChatStreamAsync(LlmJsonContent jsonContent); public IAsyncEnumerable SendApplicationStreamAsync(string message); public Task SendChatAsync(LlmJsonContent jsonContent); public Task SendApplicationAsync(CommonInput commonInput); diff --git a/host/llm/entity/LlmJsonContent.cs b/host/llm/entity/LlmJsonContent.cs index 5b53edf..c38382f 100644 --- a/host/llm/entity/LlmJsonContent.cs +++ b/host/llm/entity/LlmJsonContent.cs @@ -25,6 +25,15 @@ namespace LinkToolAddin.host.llm.entity [JsonProperty("top_k")] public int TopK { get; set; } = 40; + + [JsonProperty("enable_thinking")] + public bool EnableThinking { get; set; } = true; + + [JsonProperty("thinking_budget")] + public long ThinkingBudget { get; set; } = 1200; + + [JsonProperty("incremental_output")] + public bool IncrementalOutput { get; set; } = true; } public partial class Message diff --git a/host/llm/entity/stream/LlmStreamChat.cs b/host/llm/entity/stream/LlmStreamChat.cs index 6991982..6813e7e 100644 --- a/host/llm/entity/stream/LlmStreamChat.cs +++ b/host/llm/entity/stream/LlmStreamChat.cs @@ -50,5 +50,7 @@ { [JsonProperty("content")] public string Content { get; set; } + [JsonProperty("reasoning_content")] + public string ResoningContent { get; set; } } } \ No newline at end of file diff --git a/server/JsonRpcResultEntity.cs b/server/JsonRpcResultEntity.cs index 5d80803..f97442a 100644 --- a/server/JsonRpcResultEntity.cs +++ b/server/JsonRpcResultEntity.cs @@ -7,7 +7,7 @@ namespace LinkToolAddin.server public partial class JsonRpcResultEntity { [JsonProperty("jsonrpc")] - public string Jsonrpc { get; set; } + public string Jsonrpc { get; set; } = "2.0"; [JsonProperty("id")] public long Id { get; set; } diff --git a/ui/dockpane/TestDockpane.xaml.cs b/ui/dockpane/TestDockpane.xaml.cs index 08e3f67..1b2c1ea 100644 --- a/ui/dockpane/TestDockpane.xaml.cs +++ b/ui/dockpane/TestDockpane.xaml.cs @@ -198,8 +198,8 @@ namespace LinkToolAddin.ui.dockpane private void PromptTestButton_OnClick(object sender, RoutedEventArgs e) { string userPrompt = PromptTestTextBox.Text; - // Gateway.SendMessage(userPrompt,"qwen-max","C:/Project/test.gdb",AddReply); - Gateway.SendMessageStream(userPrompt,"qwen-max", "D:\\01_Project\\20250305_LinkTool\\20250420_AiDemoProject\\20250420_AiDemoProject.gdb", AddReplyStream); + // model可选值:qwen3-235b-a22b,qwen-max,deepseek-r1 + Gateway.SendMessageStream(userPrompt,"qwen3-235b-a22b", "D:\\01_Project\\20250305_LinkTool\\20250420_AiDemoProject\\20250420_AiDemoProject.gdb", AddReplyStream); } public void AddReplyStream(MessageListItem msg) @@ -219,7 +219,13 @@ namespace LinkToolAddin.ui.dockpane foreach (KeyValuePair pair in messageDict) { MessageListItem msgItem = pair.Value; - builder.AppendLine(msgItem.content); + string content = msgItem.content; + if (msgItem.type == MessageType.REASON_MESSAGE) + { + content = "" + content + ""; + } + builder.AppendLine(content); + builder.AppendLine(); ReplyTextBox.Text = builder.ToString(); ReplyTextBox.ScrollToEnd(); } diff --git a/ui/message/MessageListItem.cs b/ui/message/MessageListItem.cs index 1c58cbd..9b97709 100644 --- a/ui/message/MessageListItem.cs +++ b/ui/message/MessageListItem.cs @@ -4,6 +4,7 @@ public enum MessageType { TOOL_MESSAGE, CHAT_MESSAGE, + REASON_MESSAGE, } public interface MessageListItem