RoutingSettings.Provider and Model.

This commit is contained in:
hchen 2023-09-20 17:08:14 -05:00
parent a56d770e27
commit 18eb9d677c
13 changed files with 44 additions and 29 deletions

11
docs/agent/router.md Normal file
View file

@ -0,0 +1,11 @@
# Router
This section will explain in detail the usage of Router. Router has a dedicated configuration node for customization.
```json
"Router": {
"RouterId": "",
"Provider": "azure-openai",
"Model": "gpt-4"
}
```

View file

@ -1,3 +1,16 @@
# Routing
Routing is an important function that allows multiple Agents to work together to complete enterprise-level tasks. When you apply LLM to your business system, it is inevitable to develop agents with different functions. How to effectively manage so many agents with different responsibilities is a challenging task. From an engineering perspective, each Different teams are responsible for the development of different Agents, and the teams will face the problem of mutual isolation between Agents. The ideal situation is that they can be developed independently but cooperate with each other.
Routing is an important function that allows multiple Agents to work together to complete enterprise-level tasks. When you apply LLM to your business system, it is inevitable to develop agents with different functions. How to effectively manage so many agents with different responsibilities is a challenging task. From an engineering perspective, each Different teams are responsible for the development of different Agents, and the teams will face the problem of mutual isolation between Agents. The ideal situation is that they can be developed independently but cooperate with each other.
## Router
The Routing feature is the core technology used by BotSharp to manage multiple Agents. BotSharp has a built-in intelligent Agent called `Router`. When you enable this function, all user requests will be pre-processed by the Router to determine which Agent to distribute the request to for processing. The advantage of Routing technology is that it can isolate different Agents and allow them to work together to achieve the user's goals. The adoption of `Routing` ensures that Agent can be scalable, flexible and robust enough in enterprise applications.
## Reasoner
For simple questions raised by users, the ordinary routing function can already handle it. However, for the scenario where the user has a long description and needs to disassemble the task, ordinary routing cannot handle it. At this time, the `Reasoning` feature needs to be turned on, and LLM will respond according to the problem. The complexity is broken down into different small tasks. These small tasks can be processed by the corresponding Agent. During the processing process, the Router will constantly adjust the next step plan to deal with the different results returned by the Agent.
### How to register agent to router?
When you add a new Agent, the Router can automatically read the Agent's configuration, but in order for the Router to distribute the Request to the new Agent, you must set the `AllowRouting` attribute to `True`. For more information on how to use Router, please refer to the Agent/Router chapter.

View file

@ -52,6 +52,7 @@ The main documentation for the site is organized into the following sections:
agent/intro
agent/conversation
agent/state
agent/router
.. _integration-docs:

View file

@ -1,5 +1,3 @@
using System.Text.Json.Serialization;
namespace BotSharp.Abstraction.Conversations.Models;
public class IncomingMessageModel

View file

@ -1,6 +1,4 @@
using BotSharp.Abstraction.Routing.Models;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace BotSharp.Abstraction.Functions.Models;

View file

@ -1,5 +1,4 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace BotSharp.Abstraction.Routing.Models;
@ -19,6 +18,6 @@ public class RetrievalArgs : RoutingArgs
public override string ToString()
{
return $" [{AgentName}]: {Question} ({JsonSerializer.Serialize(Arguments)}) => {Answer} ({Reason})";
return $"[{AgentName}, {Reason}]: ({JsonSerializer.Serialize(Arguments)}) {Question}";
}
}

View file

@ -8,4 +8,8 @@ public class RoutingSettings
public string RouterId { get; set; } = string.Empty;
public bool EnableReasoning { get; set; } = false;
public string Provider { get; set; } = string.Empty;
public string Model { get; set; } = string.Empty;
}

View file

@ -126,7 +126,7 @@ public class ConversationStateService : IConversationStateService, IDisposable
_states[name] = defaultValue ?? "";
}
if (_states[name] == null)
if (string.IsNullOrEmpty(_states[name]))
{
return defaultValue;
}

View file

@ -10,12 +10,12 @@ public class CompletionProvider
var state = services.GetRequiredService<IConversationStateService>();
if (provider == null)
if (string.IsNullOrEmpty(provider))
{
provider = state.GetState("provider", "azure-openai");
}
if (model == null)
if (string.IsNullOrEmpty(model))
{
model = state.GetState("model", "gpt-3.5-turbo");
}

View file

@ -11,6 +11,7 @@ You're a Agent Router with reasoning, you can dispatch request to different agen
Route request to appropriate agent.
Parameters:
1. agent_name: the name of the agent;
2. reason: why route to this agent;
# task_end
Call this function when current task is completed.

View file

@ -1,14 +0,0 @@
namespace BotSharp.Core.Routing;
public class ReasoningHook : AgentHookBase
{
public ReasoningHook(IServiceProvider services, AgentSettings settings)
: base(services, settings)
{
}
public override bool OnInstructionLoaded(string template, Dictionary<string, object> dict)
{
return true;
}
}

View file

@ -103,6 +103,7 @@ public class RouteToAgentFn : IFunctionCallback
// Add field to args
message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, "missing_fields", missingFields);
message.ExecutionResult = $"missing some information: {string.Join(',', missingFields)}";
message.Content = message.ExecutionResult;
// Handle redirect
var routingRule = routingRules.FirstOrDefault(x => missingFields.Contains(x.Field));
@ -113,6 +114,7 @@ public class RouteToAgentFn : IFunctionCallback
// Add redirected agent
message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, "redirect_to", record.Name);
agentId = routingRule.RedirectTo;
}
else
{

View file

@ -32,7 +32,7 @@ public class RoutingService : IRoutingService
_dialogs = new List<RoleDialogModel>();
RoleDialogModel result = new RoleDialogModel(AgentRole.Assistant, "not handled");
foreach (var dialog in whileDialogs.TakeLast(10))
foreach (var dialog in whileDialogs.TakeLast(20))
{
agent.Instruction += $"\r\n{dialog.Role}: {dialog.Content}";
}
@ -120,13 +120,15 @@ public class RoutingService : IRoutingService
private async Task<FunctionCallFromLlm> GetNextInstructionFromReasoner(Agent reasoner)
{
var responseFormat = "{\"function\": \"\", \"parameters\": {\"agent_name\": \"\", \"args\":{}}";
var responseFormat = "{\"function\": \"\", \"parameters\": {\"agent_name\": \"\", \"reason\":\"\", \"args\":{}}";
var wholeDialogs = new List<RoleDialogModel>
{
new RoleDialogModel(AgentRole.User, $"What's the next step? Response in JSON format {responseFormat}.")
new RoleDialogModel(AgentRole.System, $"What's the next step? Response in JSON format {responseFormat}.")
};
var chatCompletion = CompletionProvider.GetChatCompletion(_services);
var chatCompletion = CompletionProvider.GetChatCompletion(_services,
provider: _settings.Provider,
model: _settings.Model);
RoleDialogModel response = null;
await chatCompletion.GetChatCompletionsAsync(reasoner, wholeDialogs, async msg
@ -142,7 +144,7 @@ public class RoutingService : IRoutingService
args.Function = args.Function.Split('.').Last();
_logger.LogInformation($"Next Instruction: {args}");
_logger.LogInformation($"*** Next Instruction *** {args}");
return args;
}