BotSharp/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs

138 lines
5 KiB
C#
Raw Normal View History

2025-08-04 19:21:11 +00:00
using BotSharp.Abstraction.Routing.Models;
using BotSharp.Abstraction.Templating;
namespace BotSharp.Core.Routing;
public partial class RoutingService
{
2025-07-24 22:22:07 +00:00
public async Task<bool> InvokeAgent(
string agentId,
List<RoleDialogModel> dialogs,
2025-08-04 19:21:11 +00:00
InvokeAgentOptions? options = null)
{
2025-08-04 19:21:11 +00:00
options ??= InvokeAgentOptions.Default();
2024-01-26 04:42:57 +00:00
var agentService = _services.GetRequiredService<IAgentService>();
var agent = await agentService.LoadAgent(agentId);
2024-10-29 19:59:46 +00:00
Context.IncreaseRecursiveCounter();
if (Context.CurrentRecursionDepth > agent.LlmConfig.MaxRecursionDepth)
{
2024-01-26 04:42:57 +00:00
_logger.LogWarning($"Current recursive call depth greater than {agent.LlmConfig.MaxRecursionDepth}, which will cause unexpected result.");
return false;
}
2024-05-13 21:53:41 +00:00
var provider = agent.LlmConfig.Provider;
2024-05-02 22:07:12 +00:00
var model = agent.LlmConfig.Model;
2024-05-13 21:53:41 +00:00
if (provider == null || model == null)
2024-05-02 22:07:12 +00:00
{
var agentSettings = _services.GetRequiredService<AgentSettings>();
2024-05-13 21:53:41 +00:00
provider = agentSettings.LlmConfig.Provider;
2024-05-02 22:07:12 +00:00
model = agentSettings.LlmConfig.Model;
}
2023-12-13 18:12:25 +00:00
var chatCompletion = CompletionProvider.GetChatCompletion(_services,
2024-05-13 21:53:41 +00:00
provider: provider,
2024-05-02 22:07:12 +00:00
model: model);
2023-10-30 16:48:18 +00:00
2025-06-24 02:43:25 +00:00
RoleDialogModel response;
2023-11-01 21:30:39 +00:00
var message = dialogs.Last();
2025-08-04 19:21:11 +00:00
if (options?.UseStream == true)
2025-06-24 02:43:25 +00:00
{
response = await chatCompletion.GetChatCompletionsStreamingAsync(agent, dialogs);
}
else
{
response = await chatCompletion.GetChatCompletions(agent, dialogs);
}
2023-09-27 20:49:44 +00:00
if (response.Role == AgentRole.Function)
{
2024-10-29 19:59:46 +00:00
message = RoleDialogModel.From(message, role: AgentRole.Function);
if (response.FunctionName != null && response.FunctionName.Contains("/"))
{
response.FunctionName = response.FunctionName.Split("/").Last();
}
2024-05-02 22:07:12 +00:00
message.ToolCallId = response.ToolCallId;
2023-11-01 21:30:39 +00:00
message.FunctionName = response.FunctionName;
message.FunctionArgs = response.FunctionArgs;
2025-01-09 22:30:25 +00:00
message.Indication = response.Indication;
2023-11-03 20:45:58 +00:00
message.CurrentAgentId = agent.Id;
2025-06-24 02:43:25 +00:00
message.IsStreaming = response.IsStreaming;
2024-04-30 21:25:58 +00:00
2025-08-04 19:21:11 +00:00
await InvokeFunction(message, dialogs, options);
}
else
{
2024-04-02 22:27:36 +00:00
// Handle output routing exception.
if (agent.Type == AgentType.Routing)
{
2025-02-25 04:35:22 +00:00
// Forgot about what situation needs to handle in this way
2025-02-28 18:44:59 +00:00
response.Content = "Apologies, I'm not quite sure I understand. Could you please provide additional clarification or context?";
2024-04-02 22:27:36 +00:00
}
2024-10-29 19:59:46 +00:00
message = RoleDialogModel.From(message, role: AgentRole.Assistant, content: response.Content);
2023-11-03 21:32:27 +00:00
message.CurrentAgentId = agent.Id;
2025-06-24 02:43:25 +00:00
message.IsStreaming = response.IsStreaming;
2023-11-03 21:32:27 +00:00
dialogs.Add(message);
2025-02-03 21:12:36 +00:00
Context.SetDialogs(dialogs);
}
return true;
}
2025-07-24 22:22:07 +00:00
private async Task<bool> InvokeFunction(
RoleDialogModel message,
List<RoleDialogModel> dialogs,
2025-08-04 19:21:11 +00:00
InvokeAgentOptions? options = null)
{
// execute function
// Save states
2023-11-01 01:48:12 +00:00
var states = _services.GetRequiredService<IConversationStateService>();
states.SaveStateByArgs(message.FunctionArgs?.JsonContent<JsonDocument>());
2024-03-01 05:44:57 +00:00
var routing = _services.GetRequiredService<IRoutingService>();
// Call functions
2025-08-04 19:21:11 +00:00
var funcOptions = options != null ? new InvokeFunctionOptions() { From = options.From } : null;
await routing.InvokeFunction(message.FunctionName, message, options: funcOptions);
// Pass execution result to LLM to get response
2024-01-27 01:14:14 +00:00
if (!message.StopCompletion)
{
// Find response template
var templateService = _services.GetRequiredService<IResponseTemplateService>();
var responseTemplate = await templateService.RenderFunctionResponse(message.CurrentAgentId, message);
if (!string.IsNullOrEmpty(responseTemplate))
2023-09-27 20:49:44 +00:00
{
2023-10-30 20:06:45 +00:00
dialogs.Add(RoleDialogModel.From(message,
role: AgentRole.Assistant,
content: responseTemplate));
2025-02-03 21:12:36 +00:00
Context.SetDialogs(dialogs);
2023-09-27 20:49:44 +00:00
}
else
{
2023-10-30 16:48:18 +00:00
// Save to memory dialogs
2024-03-28 19:09:53 +00:00
var msg = RoleDialogModel.From(message,
role: AgentRole.Function,
2024-03-28 19:09:53 +00:00
content: message.Content);
dialogs.Add(msg);
2025-02-03 21:12:36 +00:00
Context.SetDialogs(dialogs);
2023-10-30 16:48:18 +00:00
// Send to Next LLM
2025-03-14 16:13:13 +00:00
var curAgentId = routing.Context.GetCurrentAgentId();
2025-08-04 19:21:11 +00:00
await InvokeAgent(curAgentId, dialogs, options);
2023-09-27 20:49:44 +00:00
}
}
2023-10-30 19:27:12 +00:00
else
{
dialogs.Add(RoleDialogModel.From(message,
role: AgentRole.Assistant,
2023-10-30 20:06:45 +00:00
content: message.Content));
2025-02-03 21:12:36 +00:00
Context.SetDialogs(dialogs);
2023-10-30 19:27:12 +00:00
}
2023-10-30 16:48:18 +00:00
return true;
}
}