From dd346571b4c017275c3bb4ddbbca73b61066d264 Mon Sep 17 00:00:00 2001
From: hchen2020 <101423@smsassist.com>
Date: Sat, 23 Sep 2023 16:33:05 -0500
Subject: [PATCH] Add Execute Once.
---
Directory.Build.props | 2 +-
.../Conversations/Models/RoleDialogModel.cs | 2 -
.../Functions/Models/FunctionCallFromLlm.cs | 2 +-
.../BotSharp.Abstraction/Models/NameDesc.cs | 13 ++
.../Routing/IRoutingHandler.cs | 21 ++-
.../Routing/IRoutingService.cs | 4 +-
.../Routing/Models/RoutingArgs.cs | 3 -
.../BotSharpServiceCollectionExtensions.cs | 1 -
...vice.GetChatCompletionsAsyncRecursively.cs | 159 ------------------
.../ConversationService.SendMessage.cs | 63 +++----
.../Services/ConversationStorage.cs | 3 +-
.../ContinueExecuteTaskRoutingHandler.cs | 6 +-
.../GetNextInstructionRoutingHandler.cs | 2 +-
.../InterruptTaskExecutionRoutingHandler.cs | 4 +-
.../Handlers/ResponseToUserRoutingHandler.cs | 7 +-
.../RetrieveDataFromAgentRoutingHandler.cs | 13 +-
.../Handlers/RouteToAgentRoutingHandler.cs | 16 +-
.../Routing/Handlers/RoutingHandlerBase.cs | 57 +++++--
.../Routing/Handlers/TaskEndRoutingHandler.cs | 2 +-
.../Handlers/TransferToCsrRoutingHandler.cs | 34 ----
.../BotSharp.Core/Routing/PromptConst.cs | 36 ++--
.../BotSharp.Core/Routing/RoutingService.cs | 51 ++++--
.../Providers/ChatCompletionProvider.cs | 6 +-
23 files changed, 182 insertions(+), 325 deletions(-)
create mode 100644 src/Infrastructure/BotSharp.Abstraction/Models/NameDesc.cs
delete mode 100644 src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs
delete mode 100644 src/Infrastructure/BotSharp.Core/Routing/Handlers/TransferToCsrRoutingHandler.cs
diff --git a/Directory.Build.props b/Directory.Build.props
index 81c66e4a..fffd5b8b 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,7 +2,7 @@
10.0
..\..\..\packages
- 0.14.6
+ 0.14.7
true
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs
index 9c3e2bc1..8a922b80 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs
@@ -1,5 +1,3 @@
-using BotSharp.Abstraction.Agents.Enums;
-
namespace BotSharp.Abstraction.Conversations.Models;
public class RoleDialogModel
diff --git a/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs b/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs
index 8d950258..07fd12d8 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs
@@ -15,7 +15,7 @@ public class FunctionCallFromLlm
public string? Question { get; set; }
[JsonPropertyName("answer")]
- public string? Answer { get; set; }
+ public string Answer { get; set; } = string.Empty;
[JsonPropertyName("args")]
public JsonDocument Arguments { get; set; } = JsonDocument.Parse("{}");
diff --git a/src/Infrastructure/BotSharp.Abstraction/Models/NameDesc.cs b/src/Infrastructure/BotSharp.Abstraction/Models/NameDesc.cs
new file mode 100644
index 00000000..f24eac9a
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Models/NameDesc.cs
@@ -0,0 +1,13 @@
+namespace BotSharp.Abstraction.Models;
+
+public class NameDesc
+{
+ public string Name { get; set; }
+ public string Description { get; set; }
+
+ public NameDesc(string name, string description)
+ {
+ Name = name;
+ Description = description;
+ }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs
index 60354ac7..944cd502 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingHandler.cs
@@ -6,12 +6,17 @@ public interface IRoutingHandler
{
string Name { get; }
string Description { get; }
- bool IsReasoning { get; }
- bool RequireAgent { get; }
- List Parameters { get; }
- void SetRouter(Agent router);
- void SetDialogs(List dialogs);
- Task GetNextInstructionFromReasoner(string prompt);
- Task GetResponseFromReasoner();
- Task Handle(FunctionCallFromLlm inst);
+ bool IsReasoning { get => false; }
+ bool Enabled { get => true; }
+ List Parameters { get => new List(); }
+
+ void SetRouter(Agent router) { }
+
+ void SetDialogs(List dialogs) { }
+
+ Task GetNextInstructionFromReasoner(string prompt)
+ => throw new NotImplementedException("");
+
+ Task Handle(FunctionCallFromLlm inst)
+ => throw new NotImplementedException("");
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs
index 13115557..fd2c2dd1 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Routing/IRoutingService.cs
@@ -4,5 +4,7 @@ public interface IRoutingService
{
Agent LoadRouter();
List Dialogs { get; }
- Task Enter(Agent agent, List whileDialogs);
+ void SetDialogs(List dialogs);
+ Task InstructLoop(Agent router);
+ Task ExecuteOnce(Agent agent);
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
index 2204d375..1208fdb4 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
@@ -2,9 +2,6 @@ namespace BotSharp.Abstraction.Routing.Models;
public class RoutingArgs
{
- [JsonPropertyName("user_goal")]
- public string UserGoal { get; set; } = string.Empty;
-
[JsonPropertyName("reason")]
public string Reason { get; set; } = string.Empty;
diff --git a/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs b/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs
index 082f07d2..a7f2763f 100644
--- a/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs
+++ b/src/Infrastructure/BotSharp.Core/BotSharpServiceCollectionExtensions.cs
@@ -67,7 +67,6 @@ public static class BotSharpServiceCollectionExtensions
services.AddScoped();
services.AddScoped();
services.AddScoped();
- services.AddScoped();
if (myDatabaseSettings.Default == "FileRepository")
{
diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs
deleted file mode 100644
index 71608749..00000000
--- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs
+++ /dev/null
@@ -1,159 +0,0 @@
-using BotSharp.Abstraction.Agents.Models;
-using BotSharp.Abstraction.Templating;
-
-namespace BotSharp.Core.Conversations.Services;
-
-public partial class ConversationService
-{
- int currentRecursiveDepth = 0;
-
- private async Task GetChatCompletionsAsyncRecursively(Agent agent,
- List wholeDialogs,
- Func onMessageReceived,
- Func onFunctionExecuting,
- Func onFunctionExecuted)
- {
- var chatCompletion = CompletionProvider.GetChatCompletion(_services);
-
- currentRecursiveDepth++;
- if (currentRecursiveDepth > _settings.MaxRecursiveDepth)
- {
- _logger.LogWarning($"Exceeded max recursive depth.");
-
- var latestResponse = wholeDialogs.Last();
- var text = latestResponse.Content;
- if (latestResponse.Role == AgentRole.Function)
- {
- text = latestResponse.Content.Split("=>").Last();
- }
-
- await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, text)
- {
- CurrentAgentId = agent.Id
- }, onMessageReceived);
-
- return false;
- }
-
- var result = await chatCompletion.GetChatCompletionsAsync(agent, wholeDialogs, async msg =>
- {
- await HandleAssistantMessage(msg, onMessageReceived);
- }, async fn =>
- {
- var preAgentId = agent.Id;
-
- await HandleFunctionMessage(fn, onFunctionExecuting, onFunctionExecuted);
-
- // Function executed has exception
- if (fn.ExecutionResult == null)
- {
- await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, fn.Content)
- {
- CurrentAgentId = fn.CurrentAgentId
- }, onMessageReceived);
-
- return;
- }
- else if (fn.StopCompletion)
- {
- await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, fn.Content)
- {
- CurrentAgentId = fn.CurrentAgentId,
- ExecutionData = fn.ExecutionData,
- ExecutionResult = fn.ExecutionResult
- }, onMessageReceived);
-
- return;
- }
-
- var content = fn.FunctionArgs.Replace("\r", " ").Replace("\n", " ").Trim() + " => " + fn.ExecutionResult;
- _logger.LogInformation(content);
-
- fn.Content = content;
-
- // Agent has been transferred
- if (fn.CurrentAgentId != preAgentId)
- {
- var agentService = _services.GetRequiredService();
- agent = await agentService.LoadAgent(fn.CurrentAgentId);
-
- if (fn.FunctionName != "route_to_agent")
- {
- wholeDialogs.Add(fn);
- }
-
- await GetChatCompletionsAsyncRecursively(agent,
- wholeDialogs,
- onMessageReceived,
- onFunctionExecuting,
- onFunctionExecuted);
- }
- else
- {
- // Find response template
- var templateService = _services.GetRequiredService();
- var response = await templateService.RenderFunctionResponse(agent.Id, fn);
- if (!string.IsNullOrEmpty(response))
- {
- await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, response)
- {
- CurrentAgentId = agent.Id
- }, onMessageReceived);
-
- return;
- }
-
- // Add to dialog history
- // The server had an error processing your request. Sorry about that!
- // _storage.Append(conversationId, preAgentId, fn);
-
- // After function is executed, pass the result to LLM to get a natural response
- if (fn.FunctionName != "route_to_agent")
- {
- wholeDialogs.Add(fn);
- }
-
- await GetChatCompletionsAsyncRecursively(agent,
- wholeDialogs,
- onMessageReceived,
- onFunctionExecuting,
- onFunctionExecuted);
- }
- });
-
- return result;
- }
-
- private async Task HandleAssistantMessage(RoleDialogModel message, Func onMessageReceived)
- {
- var hooks = _services.GetServices().ToList();
-
- // After chat completion hook
- foreach (var hook in hooks)
- {
- await hook.AfterCompletion(message);
- }
-
- var agent = await _services.GetRequiredService().GetAgent(message.CurrentAgentId);
-
- _logger.LogInformation($"[{agent?.Name ?? "Router"}] {message.Role}: {message.Content}");
-
- await onMessageReceived(message);
-
- // Add to dialog history
- _storage.Append(_conversationId, message);
- }
-
- private async Task HandleFunctionMessage(RoleDialogModel msg,
- Func onFunctionExecuting,
- Func onFunctionExecuted)
- {
- // Save states
- SaveStateByArgs(msg.FunctionArgs);
-
- // Call functions
- await onFunctionExecuting(msg);
- await CallFunctions(msg);
- await onFunctionExecuted(msg);
- }
-}
diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs
index a969c0f9..05e0727a 100644
--- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs
+++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs
@@ -51,41 +51,18 @@ public partial class ConversationService
}
// Routing with reasoning
+ var routing = _services.GetRequiredService();
var settings = _services.GetRequiredService();
- if (settings.RouterId == agent.Id)
- {
- var routing = _services.GetRequiredService();
- var reasonedContext = await routing.Enter(agent, wholeDialogs);
- if (reasonedContext.StopCompletion)
- {
- await HandleAssistantMessage(reasonedContext, onMessageReceived);
- return true;
- }
+ routing.SetDialogs(wholeDialogs);
- // Switch agent
- if (reasonedContext.CurrentAgentId != agent.Id)
- {
- agent = await agentService.LoadAgent(reasonedContext.CurrentAgentId);
- }
+ var response = settings.RouterId == agent.Id ?
+ await routing.InstructLoop(agent) :
+ await routing.ExecuteOnce(agent);
- routing.Dialogs.ForEach(x =>
- {
- wholeDialogs.Add(x);
- if (x.Content != null)
- {
- _storage.Append(_conversationId, x);
- }
- });
- }
+ await HandleAssistantMessage(response, onMessageReceived);
- var result = await GetChatCompletionsAsyncRecursively(agent,
- wholeDialogs,
- onMessageReceived,
- onFunctionExecuting,
- onFunctionExecuted);
-
- return result;
+ return true;
}
private async Task GetConversationRecord(string agentId)
@@ -106,19 +83,23 @@ public partial class ConversationService
return converation;
}
- private void SaveStateByArgs(string args)
+ private async Task HandleAssistantMessage(RoleDialogModel message, Func onMessageReceived)
{
- var stateService = _services.GetRequiredService();
- var jo = JsonSerializer.Deserialize