From 0ae8a2cfd4abf56179cd8d70ed53704b7bc42a68 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 15 Nov 2025 23:43:22 +0800 Subject: [PATCH] :bug: Fix function calls in thought --- .../Thought/ThoughtController.cs | 39 ++++++++----------- .../Thought/ThoughtProvider.cs | 25 ++++++------ 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/DysonNetwork.Insight/Thought/ThoughtController.cs b/DysonNetwork.Insight/Thought/ThoughtController.cs index c177e69..45c99dd 100644 --- a/DysonNetwork.Insight/Thought/ThoughtController.cs +++ b/DysonNetwork.Insight/Thought/ThoughtController.cs @@ -137,6 +137,8 @@ public class ThoughtController(ThoughtProvider provider, ThoughtService service) var result = new FunctionResultContent(part.FunctionResult!.CallId, resultString); chatHistory.Add(result.ToChatMessage()); break; + default: + throw new ArgumentOutOfRangeException(); } } @@ -149,7 +151,7 @@ public class ThoughtController(ThoughtProvider provider, ThoughtService service) var assistantMessage = new ChatMessageContent(AuthorRole.Assistant, textContent.ToString()); if (hasFunctionCalls) { - assistantMessage.Items = new ChatMessageContentItemCollection(); + assistantMessage.Items = []; foreach (var fc in functionCalls) { assistantMessage.Items.Add(fc); @@ -178,8 +180,10 @@ public class ThoughtController(ThoughtProvider provider, ThoughtService service) AuthorRole? authorRole = null; var functionCallBuilder = new FunctionCallContentBuilder(); - await foreach (var streamingContent in chatCompletionService.GetStreamingChatMessageContentsAsync( - chatHistory, executionSettings, kernel)) + await foreach ( + var streamingContent in chatCompletionService.GetStreamingChatMessageContentsAsync( + chatHistory, executionSettings, kernel) + ) { authorRole ??= streamingContent.Role; @@ -192,18 +196,7 @@ public class ThoughtController(ThoughtProvider provider, ThoughtService service) await Response.Body.FlushAsync(); } - if (streamingContent.Items.Count > 0) - { - functionCallBuilder.Append(streamingContent); - } - - foreach (var functionCallUpdate in streamingContent.Items.OfType()) - { - var messageJson = JsonSerializer.Serialize(new - { type = "function_call_update", data = functionCallUpdate }); - await Response.Body.WriteAsync(Encoding.UTF8.GetBytes($"data: {messageJson}\n\n")); - await Response.Body.FlushAsync(); - } + functionCallBuilder.Append(streamingContent); } var finalMessageText = textContentBuilder.ToString(); @@ -213,19 +206,21 @@ public class ThoughtController(ThoughtProvider provider, ThoughtService service) { Type = ThinkingMessagePartType.Text, Text = finalMessageText }); } - var functionCalls = functionCallBuilder.Build(); + var functionCalls = functionCallBuilder.Build() + .Where(fc => !string.IsNullOrEmpty(fc.Id)).ToList(); if (functionCalls.Count == 0) - { break; - } - var assistantMessage = new ChatMessageContent(authorRole ?? AuthorRole.Assistant, - string.IsNullOrEmpty(finalMessageText) ? null : finalMessageText); + var assistantMessage = new ChatMessageContent( + authorRole ?? AuthorRole.Assistant, + string.IsNullOrEmpty(finalMessageText) ? null : finalMessageText + ); foreach (var functionCall in functionCalls) { assistantMessage.Items.Add(functionCall); } + chatHistory.Add(assistantMessage); foreach (var functionCall in functionCalls) @@ -236,7 +231,7 @@ public class ThoughtController(ThoughtProvider provider, ThoughtService service) FunctionCall = new SnFunctionCall { Id = functionCall.Id!, - Name = functionCall.FunctionName!, + Name = functionCall.FunctionName, Arguments = JsonSerializer.Serialize(functionCall.Arguments) } }; @@ -263,7 +258,7 @@ public class ThoughtController(ThoughtProvider provider, ThoughtService service) Type = ThinkingMessagePartType.FunctionResult, FunctionResult = new SnFunctionResult { - CallId = resultContent.CallId, + CallId = resultContent.CallId!, Result = resultContent.Result!, IsError = resultContent.Result is Exception } diff --git a/DysonNetwork.Insight/Thought/ThoughtProvider.cs b/DysonNetwork.Insight/Thought/ThoughtProvider.cs index d4b96c2..040b2c0 100644 --- a/DysonNetwork.Insight/Thought/ThoughtProvider.cs +++ b/DysonNetwork.Insight/Thought/ThoughtProvider.cs @@ -73,21 +73,24 @@ public class ThoughtProvider throw new IndexOutOfRangeException("Unknown thinking provider: " + ModelProviderType); } - // Add gRPC clients for Thought Plugins - builder.Services.AddServiceDiscoveryCore(); - builder.Services.AddServiceDiscovery(); - builder.Services.AddAccountService(); - builder.Services.AddSphereService(); - - builder.Plugins.AddFromType(); - builder.Plugins.AddFromType(); - return builder.Build(); } [Experimental("SKEXP0050")] private void InitializeHelperFunctions() { + var accountPlugin = new SnAccountKernelPlugin(_accountClient); + var postPlugin = new SnPostKernelPlugin(_postClient); + + // Add Solar Network tools plugin + Kernel.ImportPluginFromFunctions("solar_network", [ + KernelFunctionFactory.CreateFromMethod(accountPlugin.GetAccount), + KernelFunctionFactory.CreateFromMethod(accountPlugin.GetAccountByName), + KernelFunctionFactory.CreateFromMethod(postPlugin.GetPost), + KernelFunctionFactory.CreateFromMethod(postPlugin.ListPosts), + KernelFunctionFactory.CreateFromMethod(postPlugin.ListPostsWithinTime) + ]); + // Add web search plugins if configured var bingApiKey = _configuration.GetValue("Thinking:BingApiKey"); if (!string.IsNullOrEmpty(bingApiKey)) @@ -116,12 +119,12 @@ public class ThoughtProvider case "ollama": return new OllamaPromptExecutionSettings { - FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() + FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: false) }; case "deepseek": return new OpenAIPromptExecutionSettings { - FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() + FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(autoInvoke: false) }; default: throw new InvalidOperationException("Unknown provider: " + ModelProviderType);