Return reason from HasMissingRequiredField.
This commit is contained in:
parent
a1ed7616d1
commit
ce7b495475
|
|
@ -44,5 +44,5 @@ public interface IRoutingService
|
||||||
|
|
||||||
Task<string> GetConversationContent(List<RoleDialogModel> dialogs, int maxDialogCount = 50);
|
Task<string> GetConversationContent(List<RoleDialogModel> dialogs, int maxDialogCount = 50);
|
||||||
|
|
||||||
bool HasMissingRequiredField(RoleDialogModel message, out string agentId);
|
(bool, string) HasMissingRequiredField(RoleDialogModel message, out string agentId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,12 +50,12 @@ public class RoutingArgs
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
public string UserGoal { get; set; }
|
public string UserGoal { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("user_message_in_english")]
|
|
||||||
public string UserMessageInEnglish { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("language")]
|
[JsonPropertyName("language")]
|
||||||
public string Language { get; set; } = LanguageType.ENGLISH;
|
public string Language { get; set; } = LanguageType.ENGLISH;
|
||||||
|
|
||||||
|
[JsonPropertyName("lastest_message_translated_to_english")]
|
||||||
|
public string UserMessageInEnglish { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
var route = string.IsNullOrEmpty(AgentName) ? "" : $"<Route to {AgentName.ToUpper()} because {NextActionReason}>";
|
var route = string.IsNullOrEmpty(AgentName) ? "" : $"<Route to {AgentName.ToUpper()} because {NextActionReason}>";
|
||||||
|
|
|
||||||
|
|
@ -83,11 +83,11 @@ public partial class RouteToAgentFn : IFunctionCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
var routing = _services.GetRequiredService<IRoutingService>();
|
var routing = _services.GetRequiredService<IRoutingService>();
|
||||||
var missingfield = routing.HasMissingRequiredField(message, out var agentId);
|
var (missingfield, reason) = routing.HasMissingRequiredField(message, out var agentId);
|
||||||
if (missingfield && message.CurrentAgentId != agentId)
|
if (missingfield && message.CurrentAgentId != agentId)
|
||||||
{
|
{
|
||||||
// Stack redirection agent
|
// Stack redirection agent
|
||||||
_context.Push(agentId, reason: $"REDIRECTION {message.Content}");
|
_context.Push(agentId, reason: $"REDIRECTION {reason}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,20 +11,20 @@ public class ResponseToUserRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
||||||
public List<ParameterPropertyDef> Parameters => new List<ParameterPropertyDef>
|
public List<ParameterPropertyDef> Parameters => new List<ParameterPropertyDef>
|
||||||
{
|
{
|
||||||
new ParameterPropertyDef("reason",
|
new ParameterPropertyDef("reason",
|
||||||
"why response to user directly without go to other agents"),
|
"why response to user directly without go to other agents."),
|
||||||
new ParameterPropertyDef("response",
|
new ParameterPropertyDef("response",
|
||||||
"response content to user in courteous words with language English. If the user wants to end the conversation, you must set conversation_end to true and response politely."),
|
"response content to user in courteous words with language English. If the user wants to end the conversation, you must set conversation_end to true and response politely."),
|
||||||
new ParameterPropertyDef("conversation_end",
|
new ParameterPropertyDef("conversation_end",
|
||||||
"whether to end this conversation",
|
"whether to end this conversation.",
|
||||||
type: "boolean"),
|
type: "boolean"),
|
||||||
new ParameterPropertyDef("task_completed ",
|
new ParameterPropertyDef("task_completed ",
|
||||||
"whether the user's task request has been completed.",
|
"whether the user's task request has been completed.",
|
||||||
type: "boolean"),
|
type: "boolean"),
|
||||||
new ParameterPropertyDef("user_message_in_english",
|
|
||||||
"Translate user message from non-English to English"),
|
|
||||||
new ParameterPropertyDef("language",
|
new ParameterPropertyDef("language",
|
||||||
"User prefered language, considering the whole conversation. Language could be English, Spanish or Chinese.",
|
"User preferred language, considering the whole conversation. Language could be English, Spanish or Chinese.",
|
||||||
required: true),
|
required: true),
|
||||||
|
new ParameterPropertyDef("lastest_message_translated_to_english",
|
||||||
|
"Translate user lastest message in [CONVERSATION] to English"),
|
||||||
};
|
};
|
||||||
|
|
||||||
public ResponseToUserRoutingHandler(IServiceProvider services, ILogger<ResponseToUserRoutingHandler> logger, RoutingSettings settings)
|
public ResponseToUserRoutingHandler(IServiceProvider services, ILogger<ResponseToUserRoutingHandler> logger, RoutingSettings settings)
|
||||||
|
|
|
||||||
|
|
@ -12,28 +12,28 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
||||||
public List<ParameterPropertyDef> Parameters => new List<ParameterPropertyDef>
|
public List<ParameterPropertyDef> Parameters => new List<ParameterPropertyDef>
|
||||||
{
|
{
|
||||||
new ParameterPropertyDef("next_action_reason",
|
new ParameterPropertyDef("next_action_reason",
|
||||||
"the reason why route to this virtual agent",
|
"the reason why route to this virtual agent.",
|
||||||
required: true),
|
required: true),
|
||||||
new ParameterPropertyDef("next_action_agent",
|
new ParameterPropertyDef("next_action_agent",
|
||||||
"agent for next action based on user latest response, if user is replying last agent's question, you must route to this agent",
|
"agent for next action based on user latest response, if user is replying last agent's question, you must route to this agent.",
|
||||||
required: true),
|
required: true),
|
||||||
|
new ParameterPropertyDef("args",
|
||||||
|
"useful parameters of next action agent, format: { }",
|
||||||
|
type: "object"),
|
||||||
new ParameterPropertyDef("user_goal_description",
|
new ParameterPropertyDef("user_goal_description",
|
||||||
"user goal based on user initial task.",
|
"user goal based on user initial task.",
|
||||||
required: true),
|
required: true),
|
||||||
new ParameterPropertyDef("user_goal_agent",
|
new ParameterPropertyDef("user_goal_agent",
|
||||||
"agent who can acheive user initial task, must align with user_goal_description.",
|
"agent who can acheive user initial task, must align with user_goal_description.",
|
||||||
required: true),
|
required: true),
|
||||||
new ParameterPropertyDef("args",
|
|
||||||
"useful parameters of next action agent, format: { }",
|
|
||||||
type: "object"),
|
|
||||||
new ParameterPropertyDef("is_new_task",
|
new ParameterPropertyDef("is_new_task",
|
||||||
"whether the user is requesting a new task that is different from the previous topic.",
|
"whether the user is requesting a new task that is different from the previous topic.",
|
||||||
type: "boolean"),
|
type: "boolean"),
|
||||||
new ParameterPropertyDef("user_message_in_english",
|
|
||||||
"Translate user message from non-English to English"),
|
|
||||||
new ParameterPropertyDef("language",
|
new ParameterPropertyDef("language",
|
||||||
"User prefered language, considering the whole conversation. Language could be English, Spanish or Chinese.",
|
"User preferred language, considering the whole conversation. Language could be English, Spanish or Chinese.",
|
||||||
required: true),
|
required: true),
|
||||||
|
new ParameterPropertyDef("lastest_message_translated_to_english",
|
||||||
|
"Translate lastest user message in [CONVERSATION] to English"),
|
||||||
};
|
};
|
||||||
|
|
||||||
public RouteToAgentRoutingHandler(IServiceProvider services, ILogger<RouteToAgentRoutingHandler> logger, RoutingSettings settings)
|
public RouteToAgentRoutingHandler(IServiceProvider services, ILogger<RouteToAgentRoutingHandler> logger, RoutingSettings settings)
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ public class RoutingContext : IRoutingContext
|
||||||
};
|
};
|
||||||
|
|
||||||
var routing = _services.GetRequiredService<IRoutingService>();
|
var routing = _services.GetRequiredService<IRoutingService>();
|
||||||
var missingfield = routing.HasMissingRequiredField(message, out agentId);
|
var (missingfield, _) = routing.HasMissingRequiredField(message, out agentId);
|
||||||
if (missingfield)
|
if (missingfield)
|
||||||
{
|
{
|
||||||
if (currentAgentId != agentId)
|
if (currentAgentId != agentId)
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ public partial class RoutingService
|
||||||
/// If the target agent needs some required fields but the
|
/// If the target agent needs some required fields but the
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool HasMissingRequiredField(RoleDialogModel message, out string agentId)
|
public (bool, string) HasMissingRequiredField(RoleDialogModel message, out string agentId)
|
||||||
{
|
{
|
||||||
|
var reason = string.Empty;
|
||||||
var args = JsonSerializer.Deserialize<RoutingArgs>(message.FunctionArgs);
|
var args = JsonSerializer.Deserialize<RoutingArgs>(message.FunctionArgs);
|
||||||
var routing = _services.GetRequiredService<IRoutingService>();
|
var routing = _services.GetRequiredService<IRoutingService>();
|
||||||
|
|
||||||
|
|
@ -20,7 +21,7 @@ public partial class RoutingService
|
||||||
if (routingRules == null || !routingRules.Any())
|
if (routingRules == null || !routingRules.Any())
|
||||||
{
|
{
|
||||||
agentId = message.CurrentAgentId;
|
agentId = message.CurrentAgentId;
|
||||||
return false;
|
return (false, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
agentId = routingRules.First().AgentId;
|
agentId = routingRules.First().AgentId;
|
||||||
|
|
@ -68,9 +69,13 @@ public partial class RoutingService
|
||||||
|
|
||||||
if (missingFields.Any())
|
if (missingFields.Any())
|
||||||
{
|
{
|
||||||
|
var logger = _services.GetRequiredService<ILogger<RouteToAgentFn>>();
|
||||||
|
|
||||||
// Add field to args
|
// Add field to args
|
||||||
message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, "missing_fields", missingFields);
|
message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, "missing_fields", missingFields);
|
||||||
message.Content = $"missing some information: {string.Join(", ", missingFields)}";
|
reason = $"missing some information: {string.Join(", ", missingFields)}";
|
||||||
|
// message.Content = reason;
|
||||||
|
logger.LogWarning(reason);
|
||||||
|
|
||||||
// Handle redirect
|
// Handle redirect
|
||||||
var routingRule = routingRules.FirstOrDefault(x => missingFields.Contains(x.Field));
|
var routingRule = routingRules.FirstOrDefault(x => missingFields.Contains(x.Field));
|
||||||
|
|
@ -82,7 +87,6 @@ public partial class RoutingService
|
||||||
// Add redirected agent
|
// Add redirected agent
|
||||||
message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, "redirect_to", record.Name);
|
message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, "redirect_to", record.Name);
|
||||||
agentId = routingRule.RedirectTo;
|
agentId = routingRule.RedirectTo;
|
||||||
var logger = _services.GetRequiredService<ILogger<RouteToAgentFn>>();
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Console.WriteLine($"*** Routing redirect to {record.Name.ToUpper()} ***", Color.Yellow);
|
Console.WriteLine($"*** Routing redirect to {record.Name.ToUpper()} ***", Color.Yellow);
|
||||||
#else
|
#else
|
||||||
|
|
@ -96,7 +100,7 @@ public partial class RoutingService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return missingFields.Any();
|
return (missingFields.Any(), reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string AppendPropertyToArgs(string args, string key, string value)
|
private string AppendPropertyToArgs(string args, string key, string value)
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,6 @@ namespace BotSharp.Core.Routing;
|
||||||
|
|
||||||
public partial class RoutingService
|
public partial class RoutingService
|
||||||
{
|
{
|
||||||
private List<FunctionCallingResponse> _functionCallStack = new List<FunctionCallingResponse>();
|
|
||||||
public List<FunctionCallingResponse> FunctionCallStack => _functionCallStack;
|
|
||||||
|
|
||||||
public async Task<bool> InvokeFunction(string name, RoleDialogModel message)
|
public async Task<bool> InvokeFunction(string name, RoleDialogModel message)
|
||||||
{
|
{
|
||||||
var function = _services.GetServices<IFunctionCallback>().FirstOrDefault(x => x.Name == name);
|
var function = _services.GetServices<IFunctionCallback>().FirstOrDefault(x => x.Name == name);
|
||||||
|
|
@ -38,14 +35,6 @@ public partial class RoutingService
|
||||||
{
|
{
|
||||||
result = await function.Execute(clonedMessage);
|
result = await function.Execute(clonedMessage);
|
||||||
|
|
||||||
_functionCallStack.Add(new FunctionCallingResponse
|
|
||||||
{
|
|
||||||
Role = AgentRole.Function,
|
|
||||||
FunctionName = clonedMessage.FunctionName,
|
|
||||||
Args = JsonDocument.Parse(clonedMessage.FunctionArgs ?? "{}"),
|
|
||||||
Content = clonedMessage.Content
|
|
||||||
});
|
|
||||||
|
|
||||||
// After functions have been executed
|
// After functions have been executed
|
||||||
foreach (var hook in hooks)
|
foreach (var hook in hooks)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -300,6 +300,7 @@ public class ChatCompletionProvider : IChatCompletion
|
||||||
}));
|
}));
|
||||||
prompt += $"{verbose}\r\n";
|
prompt += $"{verbose}\r\n";
|
||||||
|
|
||||||
|
prompt += "\r\n[CONVERSATION]\r\n";
|
||||||
verbose = string.Join("\r\n", chatCompletionsOptions.Messages
|
verbose = string.Join("\r\n", chatCompletionsOptions.Messages
|
||||||
.Where(x => x.Role != AgentRole.System).Select(x =>
|
.Where(x => x.Role != AgentRole.System).Select(x =>
|
||||||
{
|
{
|
||||||
|
|
@ -311,7 +312,7 @@ public class ChatCompletionProvider : IChatCompletion
|
||||||
else if (x.Role == ChatRole.User)
|
else if (x.Role == ChatRole.User)
|
||||||
{
|
{
|
||||||
var m = x as ChatRequestUserMessage;
|
var m = x as ChatRequestUserMessage;
|
||||||
return !string.IsNullOrEmpty(m.Name) ?
|
return !string.IsNullOrEmpty(m.Name) && m.Name != "route_to_agent" ?
|
||||||
$"{m.Name}: {m.Content}" :
|
$"{m.Name}: {m.Content}" :
|
||||||
$"{m.Role}: {m.Content}";
|
$"{m.Role}: {m.Content}";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue