diff --git a/BotSharp.sln b/BotSharp.sln index 38d47e55..a9a0e164 100644 --- a/BotSharp.sln +++ b/BotSharp.sln @@ -97,6 +97,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.OpenAI", "s EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.EmailHandler", "src\Plugins\BotSharp.Plugin.EmailHandler\BotSharp.Plugin.EmailHandler.csproj", "{A72B3BEB-E14B-4917-BE44-97EAE4E122D2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.FileHandler", "src\Plugins\BotSharp.Plugin.FileReader\BotSharp.Plugin.FileHandler.csproj", "{D0C5055E-4849-467F-A078-FB01F8DEC55A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -393,6 +395,14 @@ Global {A72B3BEB-E14B-4917-BE44-97EAE4E122D2}.Release|Any CPU.Build.0 = Release|Any CPU {A72B3BEB-E14B-4917-BE44-97EAE4E122D2}.Release|x64.ActiveCfg = Release|Any CPU {A72B3BEB-E14B-4917-BE44-97EAE4E122D2}.Release|x64.Build.0 = Release|Any CPU + {D0C5055E-4849-467F-A078-FB01F8DEC55A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D0C5055E-4849-467F-A078-FB01F8DEC55A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D0C5055E-4849-467F-A078-FB01F8DEC55A}.Debug|x64.ActiveCfg = Debug|Any CPU + {D0C5055E-4849-467F-A078-FB01F8DEC55A}.Debug|x64.Build.0 = Debug|Any CPU + {D0C5055E-4849-467F-A078-FB01F8DEC55A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D0C5055E-4849-467F-A078-FB01F8DEC55A}.Release|Any CPU.Build.0 = Release|Any CPU + {D0C5055E-4849-467F-A078-FB01F8DEC55A}.Release|x64.ActiveCfg = Release|Any CPU + {D0C5055E-4849-467F-A078-FB01F8DEC55A}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -439,6 +449,7 @@ Global {806A0B0E-FEFF-420E-B5B2-C9FCBF890A8C} = {D5293208-2BEF-42FC-A64C-5954F61720BA} {6507D336-3A4D-41D4-81C0-2B900173A5FE} = {D5293208-2BEF-42FC-A64C-5954F61720BA} {A72B3BEB-E14B-4917-BE44-97EAE4E122D2} = {51AFE054-AE99-497D-A593-69BAEFB5106F} + {D0C5055E-4849-467F-A078-FB01F8DEC55A} = {51AFE054-AE99-497D-A593-69BAEFB5106F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19} diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Enums/Utility.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Enums/UtilityName.cs similarity index 89% rename from src/Plugins/BotSharp.Plugin.EmailHandler/Enums/Utility.cs rename to src/Plugins/BotSharp.Plugin.EmailHandler/Enums/UtilityName.cs index 7fc65728..b84f9c5f 100644 --- a/src/Plugins/BotSharp.Plugin.EmailHandler/Enums/Utility.cs +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Enums/UtilityName.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace BotSharp.Plugin.EmailHandler.Enums { - public class Utility + public class UtilityName { public const string EmailHandler = "email-handler"; } diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs index 41c97eba..59d7baf9 100644 --- a/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerHook.cs @@ -26,7 +26,7 @@ public class EmailHandlerHook : AgentHookBase { var conv = _services.GetRequiredService(); var isConvMode = conv.IsConversationMode(); - var isEnabled = !agent.Utilities.IsNullOrEmpty() && agent.Utilities.Contains(Utility.EmailHandler); + var isEnabled = !agent.Utilities.IsNullOrEmpty() && agent.Utilities.Contains(UtilityName.EmailHandler); if (isConvMode && isEnabled) { diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs index 26d82ab0..1d801e66 100644 --- a/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs @@ -12,7 +12,7 @@ namespace BotSharp.Plugin.EmailHandler.Hooks { public void AddUtilities(List utilities) { - utilities.Add(Utility.EmailHandler); + utilities.Add(UtilityName.EmailHandler); } } } diff --git a/src/Plugins/BotSharp.Plugin.FileReader/BotSharp.Plugin.FileHandler.csproj b/src/Plugins/BotSharp.Plugin.FileReader/BotSharp.Plugin.FileHandler.csproj new file mode 100644 index 00000000..3b2a031a --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.FileReader/BotSharp.Plugin.FileHandler.csproj @@ -0,0 +1,23 @@ + + + + $(TargetFramework) + enable + $(LangVersion) + $(BotSharpVersion) + $(GeneratePackageOnBuild) + $(GenerateDocumentationFile) + $(SolutionDir)packages + + + + + + + + + + + + + diff --git a/src/Plugins/BotSharp.Plugin.FileReader/Enums/UtilityName.cs b/src/Plugins/BotSharp.Plugin.FileReader/Enums/UtilityName.cs new file mode 100644 index 00000000..f28bc9a6 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.FileReader/Enums/UtilityName.cs @@ -0,0 +1,7 @@ +namespace BotSharp.Plugin.FileHandler.Enums; + +public class UtilityName +{ + public const string ImageReader = "image-reader"; + public const string PdfReader = "pdf-reader"; +} diff --git a/src/Plugins/BotSharp.Plugin.FileReader/FileHandlerPlugin.cs b/src/Plugins/BotSharp.Plugin.FileReader/FileHandlerPlugin.cs new file mode 100644 index 00000000..2b5940fb --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.FileReader/FileHandlerPlugin.cs @@ -0,0 +1,25 @@ +using BotSharp.Abstraction.Settings; +using BotSharp.Plugin.FileHandler.Hooks; +using Microsoft.Extensions.Configuration; + +namespace BotSharp.Plugin.FileReader; + +public class FileHandlerPlugin : IBotSharpPlugin +{ + public string Id => "65be5aee-48df-4ff8-a50a-05c8bcd2a793"; + public string Name => "File Handler"; + public string Description => "AI reads files, such as image, pdf, excel"; + public string IconUrl => "https://lirp.cdn-website.com/6f8d6d8a/dms3rep/multi/opt/API_Icon-640w.png"; + public string[] AgentIds => []; + + public void RegisterDI(IServiceCollection services, IConfiguration config) + { + services.AddScoped(provider => + { + var settingService = provider.GetRequiredService(); + return settingService.Bind("FileHandler"); + }); + + services.AddScoped(); + services.AddScoped(); + } diff --git a/src/Plugins/BotSharp.Plugin.FileReader/Hooks/FileHandlerHook.cs b/src/Plugins/BotSharp.Plugin.FileReader/Hooks/FileHandlerHook.cs new file mode 100644 index 00000000..133bba2e --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.FileReader/Hooks/FileHandlerHook.cs @@ -0,0 +1,69 @@ +using BotSharp.Abstraction.Agents.Enums; +using BotSharp.Abstraction.Agents.Settings; +using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Repositories; + +namespace BotSharp.Plugin.FileHandler.Hooks; + +public class FileHandlerHook : AgentHookBase, IAgentHook +{ + private const string IMAGE_READER_FN = "image_reader"; + private const string PDF_READER_FN = "pdf_reader"; + + public override string SelfId => string.Empty; + + public FileHandlerHook(IServiceProvider services, AgentSettings settings) : base(services, settings) + { + } + + public override void OnAgentLoaded(Agent agent) + { + var conv = _services.GetRequiredService(); + var isConvMode = conv.IsConversationMode(); + + if (isConvMode) + { + AddUtility(agent, UtilityName.ImageReader, IMAGE_READER_FN); + AddUtility(agent, UtilityName.PdfReader, PDF_READER_FN); + } + + base.OnAgentLoaded(agent); + } + + private bool IsEnableUtility(Agent agent, string utility) + { + return !agent.Utilities.IsNullOrEmpty() && agent.Utilities.Contains(utility); + } + + private (string, FunctionDef?) GetPromptAndFunction(string functionName) + { + var db = _services.GetRequiredService(); + var agent = db.GetAgent(BuiltInAgentId.UtilityAssistant); + var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{functionName}.fn"))?.Content ?? string.Empty; + var loadAttachmentFn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(functionName)); + return (prompt, loadAttachmentFn); + } + + private void AddUtility(Agent agent, string utility, string functionName) + { + if (!IsEnableUtility(agent, utility)) return; + + var (prompt, fn) = GetPromptAndFunction(functionName); + if (fn != null) + { + if (!string.IsNullOrWhiteSpace(prompt)) + { + agent.Instruction += $"\r\n\r\n{prompt}\r\n\r\n"; + } + + if (agent.Functions == null) + { + agent.Functions = new List { fn }; + } + else + { + agent.Functions.Add(fn); + } + } + } +} diff --git a/src/Plugins/BotSharp.Plugin.FileReader/Hooks/FileHandlerUtilityHook.cs b/src/Plugins/BotSharp.Plugin.FileReader/Hooks/FileHandlerUtilityHook.cs new file mode 100644 index 00000000..f5ef469e --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.FileReader/Hooks/FileHandlerUtilityHook.cs @@ -0,0 +1,10 @@ +namespace BotSharp.Plugin.FileHandler.Hooks; + +public class FileHandlerUtilityHook : IAgentUtilityHook +{ + public void AddUtilities(List utilities) + { + utilities.Add(UtilityName.ImageReader); + utilities.Add(UtilityName.PdfReader); + } +} diff --git a/src/Plugins/BotSharp.Plugin.FileReader/Settings/FileHandlerSettings.cs b/src/Plugins/BotSharp.Plugin.FileReader/Settings/FileHandlerSettings.cs new file mode 100644 index 00000000..f9b8118a --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.FileReader/Settings/FileHandlerSettings.cs @@ -0,0 +1,5 @@ +namespace BotSharp.Plugin.FileHandler.Settings; + +public class FileHandlerSettings +{ +} diff --git a/src/Plugins/BotSharp.Plugin.FileReader/Using.cs b/src/Plugins/BotSharp.Plugin.FileReader/Using.cs new file mode 100644 index 00000000..f6089c7f --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.FileReader/Using.cs @@ -0,0 +1,20 @@ +global using System; +global using System.Collections.Generic; +global using System.Text; +global using System.Linq; +global using System.Text.Json; +global using System.Threading.Tasks; +global using BotSharp.Abstraction.Agents; +global using BotSharp.Abstraction.Conversations; +global using BotSharp.Abstraction.Plugins; +global using BotSharp.Abstraction.Conversations.Models; +global using BotSharp.Abstraction.Functions; +global using BotSharp.Abstraction.Agents.Models; +global using BotSharp.Abstraction.Templating; +global using Microsoft.Extensions.DependencyInjection; +global using BotSharp.Abstraction.Utilities; +global using BotSharp.Abstraction.Messaging; +global using BotSharp.Abstraction.Messaging.Models.RichContent; +global using BotSharp.Abstraction.Options; +global using BotSharp.Plugin.FileHandler.Enums; +global using BotSharp.Plugin.FileHandler.Settings; \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/Enums/Utility.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/Enums/UtilityName.cs similarity index 80% rename from src/Plugins/BotSharp.Plugin.HttpHandler/Enums/Utility.cs rename to src/Plugins/BotSharp.Plugin.HttpHandler/Enums/UtilityName.cs index 3389206a..2e0146bf 100644 --- a/src/Plugins/BotSharp.Plugin.HttpHandler/Enums/Utility.cs +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/Enums/UtilityName.cs @@ -1,6 +1,6 @@ namespace BotSharp.Plugin.HttpHandler.Enums; -public class Utility +public class UtilityName { public const string HttpHandler = "http-handler"; } diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs index e0c36f54..ef3ce916 100644 --- a/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/Functions/HandleHttpRequestFn.cs @@ -40,7 +40,6 @@ public class HandleHttpRequestFn : IFunctionCallback var response = await SendHttpRequest(url, method, content); var responseContent = await HandleHttpResponse(response); message.Content = responseContent; - message.StopCompletion = true; return true; } catch (Exception ex) @@ -48,7 +47,6 @@ public class HandleHttpRequestFn : IFunctionCallback var msg = $"Fail when sending http request. Url: {url}, method: {method}, content: {content}"; _logger.LogWarning($"{msg}\n(Error: {ex.Message})"); message.Content = msg; - message.StopCompletion = true; return false; } } diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerHook.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerHook.cs index 0d83719d..78ee2c09 100644 --- a/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerHook.cs +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerHook.cs @@ -21,11 +21,11 @@ public class HttpHandlerHook : AgentHookBase { var conv = _services.GetRequiredService(); var isConvMode = conv.IsConversationMode(); - var isEnabled = !agent.Utilities.IsNullOrEmpty() && agent.Utilities.Contains(Utility.HttpHandler); + var isEnabled = !agent.Utilities.IsNullOrEmpty() && agent.Utilities.Contains(UtilityName.HttpHandler); if (isConvMode && isEnabled) { - var (prompt, fn) = GetPromptAndFunction(); + var (prompt, fn) = GetPromptAndFunction(FUNCTION_NAME); if (fn != null) { if (!string.IsNullOrWhiteSpace(prompt)) @@ -47,12 +47,12 @@ public class HttpHandlerHook : AgentHookBase base.OnAgentLoaded(agent); } - private (string, FunctionDef?) GetPromptAndFunction() + private (string, FunctionDef?) GetPromptAndFunction(string functionName) { var db = _services.GetRequiredService(); var agent = db.GetAgent(BuiltInAgentId.UtilityAssistant); - var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{FUNCTION_NAME}.fn"))?.Content ?? string.Empty; - var loadAttachmentFn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(FUNCTION_NAME)); + var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{functionName}.fn"))?.Content ?? string.Empty; + var loadAttachmentFn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(functionName)); return (prompt, loadAttachmentFn); } } diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerUtilityHook.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerUtilityHook.cs index f1f8041e..17a38df5 100644 --- a/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerUtilityHook.cs @@ -6,6 +6,6 @@ public class HttpHandlerUtilityHook : IAgentUtilityHook { public void AddUtilities(List utilities) { - utilities.Add(Utility.HttpHandler); + utilities.Add(UtilityName.HttpHandler); } } diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/Using.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/Using.cs index beec51fe..06d409cf 100644 --- a/src/Plugins/BotSharp.Plugin.HttpHandler/Using.cs +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/Using.cs @@ -1,16 +1,16 @@ global using System; global using System.Collections.Generic; global using System.Text; +global using System.Linq; +global using System.Text.Json; +global using System.Threading.Tasks; global using BotSharp.Abstraction.Conversations; global using BotSharp.Abstraction.Plugins; -global using System.Text.Json; global using BotSharp.Abstraction.Conversations.Models; -global using System.Threading.Tasks; global using BotSharp.Abstraction.Functions; global using BotSharp.Abstraction.Agents.Models; global using BotSharp.Abstraction.Templating; global using Microsoft.Extensions.DependencyInjection; -global using System.Linq; global using BotSharp.Abstraction.Utilities; global using BotSharp.Abstraction.Messaging; global using BotSharp.Abstraction.Messaging.Models.RichContent; diff --git a/src/WebStarter/WebStarter.csproj b/src/WebStarter/WebStarter.csproj index 1601a898..c25cd262 100644 --- a/src/WebStarter/WebStarter.csproj +++ b/src/WebStarter/WebStarter.csproj @@ -29,6 +29,7 @@ + diff --git a/src/WebStarter/appsettings.json b/src/WebStarter/appsettings.json index efc8dbc8..c4d527fe 100644 --- a/src/WebStarter/appsettings.json +++ b/src/WebStarter/appsettings.json @@ -295,7 +295,8 @@ "BotSharp.Plugin.LLamaSharp", "BotSharp.Plugin.SparkDesk", "BotSharp.Plugin.MetaGLM", - "BotSharp.Plugin.HttpHandler" + "BotSharp.Plugin.HttpHandler", + "BotSharp.Plugin.FileHandler" ] } }