From 3c1c599b60628c51d189d2e25680296ee92f60ea Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Wed, 20 Aug 2025 11:30:09 -0500 Subject: [PATCH] add web intelligent search --- .../BotSharp.Core/BotSharp.Core.csproj | 9 +++ .../Conversations/ConversationPlugin.cs | 3 + .../Demo/Functions/GetFunEventsFn.cs | 1 - .../Functions/WebIntelligentSearchFn.cs | 68 +++++++++++++++++++ .../WebSearch/Hooks/WebSearchUtilityHook.cs | 22 ++++++ .../util-web-intelligent_search.json | 9 +++ .../util-web-intelligent_search.fn.liquid | 1 + .../Functions/ReadImageFn.cs | 2 +- 8 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Core/WebSearch/Functions/WebIntelligentSearchFn.cs create mode 100644 src/Infrastructure/BotSharp.Core/WebSearch/Hooks/WebSearchUtilityHook.cs create mode 100644 src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-web-intelligent_search.json create mode 100644 src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-web-intelligent_search.fn.liquid diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj index 6833fdfc..7b0e55ac 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj +++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj @@ -99,6 +99,9 @@ + + + @@ -215,6 +218,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + diff --git a/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs b/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs index 61c23d1b..64899ec4 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs @@ -16,6 +16,7 @@ using BotSharp.Core.Messaging; using BotSharp.Core.Routing.Reasoning; using BotSharp.Core.Templating; using BotSharp.Core.Translation; +using BotSharp.Core.WebSearch.Hooks; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; @@ -67,6 +68,8 @@ public class ConversationPlugin : IBotSharpPlugin services.AddScoped(); services.AddScoped(); services.AddScoped(); + + services.AddScoped(); } public bool AttachMenu(List menu) diff --git a/src/Infrastructure/BotSharp.Core/Demo/Functions/GetFunEventsFn.cs b/src/Infrastructure/BotSharp.Core/Demo/Functions/GetFunEventsFn.cs index 87ddb1ee..818d4e5a 100644 --- a/src/Infrastructure/BotSharp.Core/Demo/Functions/GetFunEventsFn.cs +++ b/src/Infrastructure/BotSharp.Core/Demo/Functions/GetFunEventsFn.cs @@ -1,6 +1,5 @@ using BotSharp.Abstraction.Functions; using BotSharp.Core.MessageHub; -using System.Text.Json.Serialization; namespace BotSharp.Core.Demo.Functions; diff --git a/src/Infrastructure/BotSharp.Core/WebSearch/Functions/WebIntelligentSearchFn.cs b/src/Infrastructure/BotSharp.Core/WebSearch/Functions/WebIntelligentSearchFn.cs new file mode 100644 index 00000000..138748fb --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/WebSearch/Functions/WebIntelligentSearchFn.cs @@ -0,0 +1,68 @@ +using BotSharp.Abstraction.Functions; +using BotSharp.Abstraction.MLTasks; + +namespace BotSharp.Core.WebSearch.Functions; + +public class WebIntelligentSearchFn : IFunctionCallback +{ + private readonly IServiceProvider _services; + private readonly ILogger _logger; + + public string Name => "util-web-intelligent_search"; + public string Indication => "Searching web"; + + public WebIntelligentSearchFn( + IServiceProvider services, + ILogger logger) + { + _services = services; + _logger = logger; + } + + public async Task Execute(RoleDialogModel message) + { + var conv = _services.GetRequiredService(); + var routingCtx = _services.GetRequiredService(); + var agentService = _services.GetRequiredService(); + + Agent? fromAgent = null; + if (!string.IsNullOrEmpty(message.CurrentAgentId)) + { + fromAgent = await agentService.GetAgent(message.CurrentAgentId); + } + + var agent = new Agent + { + Id = fromAgent?.Id ?? BuiltInAgentId.UtilityAssistant, + Name = fromAgent?.Name ?? "AI Agent", + Instruction = "Please search the websites to handle user's request." + }; + + var dialogs = routingCtx.GetDialogs(); + if (dialogs.IsNullOrEmpty()) + { + dialogs = conv.GetDialogHistory(); + } + + var response = await GetChatCompletion(agent, dialogs); + message.Content = response; + return true; + } + + private async Task GetChatCompletion(Agent agent, List dialogs) + { + try + { + var llmProviderService = _services.GetRequiredService(); + var completion = CompletionProvider.GetChatCompletion(_services, provider: "openai", model: "gpt-4o-search-preview"); + var response = await completion.GetChatCompletions(agent, dialogs); + return response.Content; + } + catch (Exception ex) + { + var error = $"Error when searching web."; + _logger.LogWarning(ex, $"{error}"); + return error; + } + } +} diff --git a/src/Infrastructure/BotSharp.Core/WebSearch/Hooks/WebSearchUtilityHook.cs b/src/Infrastructure/BotSharp.Core/WebSearch/Hooks/WebSearchUtilityHook.cs new file mode 100644 index 00000000..0fcaf6d3 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/WebSearch/Hooks/WebSearchUtilityHook.cs @@ -0,0 +1,22 @@ +namespace BotSharp.Core.WebSearch.Hooks; + +public class WebSearchUtilityHook : IAgentUtilityHook +{ + private const string WEB_INTELLIGENT_SEARCH_FN = "util-web-intelligent_search"; + + public void AddUtilities(List utilities) + { + utilities.Add(new AgentUtility + { + Category = "web", + Name = "intelligent.search", + Items = [ + new UtilityItem + { + FunctionName = WEB_INTELLIGENT_SEARCH_FN, + TemplateName = $"{WEB_INTELLIGENT_SEARCH_FN}.fn" + } + ] + }); + } +} diff --git a/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-web-intelligent_search.json b/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-web-intelligent_search.json new file mode 100644 index 00000000..bdad99fb --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-web-intelligent_search.json @@ -0,0 +1,9 @@ +{ + "name": "util-web-intelligent_search", + "description": "Search websites to handle user's request", + "parameters": { + "type": "object", + "properties": {}, + "required": [] + } +} \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-web-intelligent_search.fn.liquid b/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-web-intelligent_search.fn.liquid new file mode 100644 index 00000000..401a2e16 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-web-intelligent_search.fn.liquid @@ -0,0 +1 @@ +Please call "util-web-intelligent_search" if user wants you to search content from websites. \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs b/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs index 1a093797..f8a0f593 100644 --- a/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs +++ b/src/Plugins/BotSharp.Plugin.FileHandler/Functions/ReadImageFn.cs @@ -28,7 +28,7 @@ public class ReadImageFn : IFunctionCallback Agent? fromAgent = null; if (!string.IsNullOrEmpty(message.CurrentAgentId)) { - fromAgent = await agentService.LoadAgent(message.CurrentAgentId); + fromAgent = await agentService.GetAgent(message.CurrentAgentId); } var agent = new Agent