Optimize InstructLoop
This commit is contained in:
parent
4298e466db
commit
5ff7079470
|
|
@ -32,7 +32,7 @@ public interface IRoutingService
|
|||
|
||||
Task<bool> InvokeAgent(string agentId, List<RoleDialogModel> dialogs);
|
||||
Task<bool> InvokeFunction(string name, RoleDialogModel messages);
|
||||
Task<RoleDialogModel> InstructLoop(RoleDialogModel message, List<RoleDialogModel> dialogs);
|
||||
Task<RoleDialogModel> InstructLoop(Agent agent, RoleDialogModel message, List<RoleDialogModel> dialogs);
|
||||
|
||||
/// <summary>
|
||||
/// Talk to a specific Agent directly, bypassing the Router
|
||||
|
|
@ -40,7 +40,7 @@ public interface IRoutingService
|
|||
/// <param name="agent"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
Task<RoleDialogModel> InstructDirect(Agent agent, RoleDialogModel message);
|
||||
Task<RoleDialogModel> InstructDirect(Agent agent, RoleDialogModel message, List<RoleDialogModel> dialogs);
|
||||
|
||||
Task<string> GetConversationContent(List<RoleDialogModel> dialogs, int maxDialogCount = 100);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,17 +38,6 @@ public partial class ConversationService
|
|||
var routing = _services.GetRequiredService<IRoutingService>();
|
||||
routing.Context.SetMessageId(_conversationId, message.MessageId);
|
||||
|
||||
// Check the routing mode
|
||||
var states = _services.GetRequiredService<IConversationStateService>();
|
||||
var routingMode = states.GetState(StateConst.ROUTING_MODE, "hard");
|
||||
routing.Context.Push(agent.Id, reason: "request started", updateLazyRouting: false);
|
||||
|
||||
if (routingMode == "lazy")
|
||||
{
|
||||
message.CurrentAgentId = states.GetState(StateConst.LAZY_ROUTING_AGENT_ID, message.CurrentAgentId);
|
||||
routing.Context.Push(message.CurrentAgentId, reason: "lazy routing", updateLazyRouting: false);
|
||||
}
|
||||
|
||||
// Save payload in order to assign the payload before hook is invoked
|
||||
if (replyMessage != null && !string.IsNullOrEmpty(replyMessage.Payload))
|
||||
{
|
||||
|
|
@ -91,11 +80,22 @@ public partial class ConversationService
|
|||
|
||||
if (agent.Type == AgentType.Routing)
|
||||
{
|
||||
response = await routing.InstructLoop(message, dialogs);
|
||||
// Check the routing mode
|
||||
var states = _services.GetRequiredService<IConversationStateService>();
|
||||
var routingMode = states.GetState(StateConst.ROUTING_MODE, "eager");
|
||||
routing.Context.Push(agent.Id, reason: "request started", updateLazyRouting: false);
|
||||
|
||||
if (routingMode == "lazy")
|
||||
{
|
||||
message.CurrentAgentId = states.GetState(StateConst.LAZY_ROUTING_AGENT_ID, message.CurrentAgentId);
|
||||
routing.Context.Push(message.CurrentAgentId, reason: "lazy routing", updateLazyRouting: false);
|
||||
}
|
||||
|
||||
response = await routing.InstructLoop(agent, message, dialogs);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = await routing.InstructDirect(agent, message);
|
||||
response = await routing.InstructDirect(agent, message, dialogs);
|
||||
}
|
||||
|
||||
routing.Context.ResetRecursiveCounter();
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ public class RoutingContext : IRoutingContext
|
|||
|
||||
// Set next handling agent for lazy routing mode
|
||||
var states = _services.GetRequiredService<IConversationStateService>();
|
||||
var routingMode = states.GetState(StateConst.ROUTING_MODE, "hard");
|
||||
var routingMode = states.GetState(StateConst.ROUTING_MODE, "eager");
|
||||
if (routingMode == "lazy")
|
||||
{
|
||||
var agentId = GetCurrentAgentId();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace BotSharp.Core.Routing;
|
|||
|
||||
public partial class RoutingService
|
||||
{
|
||||
public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||
public async Task<RoleDialogModel> InstructLoop(Agent agent, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||
{
|
||||
RoleDialogModel response = default;
|
||||
|
||||
|
|
@ -15,8 +15,6 @@ public partial class RoutingService
|
|||
var convService = _services.GetRequiredService<IConversationService>();
|
||||
var storage = _services.GetRequiredService<IConversationStorage>();
|
||||
|
||||
_router = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
|
||||
var states = _services.GetRequiredService<IConversationStateService>();
|
||||
var executor = _services.GetRequiredService<IExecutor>();
|
||||
|
||||
|
|
|
|||
|
|
@ -26,31 +26,36 @@ public partial class RoutingService : IRoutingService
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<RoleDialogModel> InstructDirect(Agent agent, RoleDialogModel message)
|
||||
public async Task<RoleDialogModel> InstructDirect(Agent agent, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||
{
|
||||
var conv = _services.GetRequiredService<IConversationService>();
|
||||
var storage = _services.GetRequiredService<IConversationStorage>();
|
||||
storage.Append(conv.ConversationId, message);
|
||||
|
||||
var dialogs = conv.GetDialogHistory();
|
||||
dialogs.Add(message);
|
||||
Context.SetDialogs(dialogs);
|
||||
|
||||
var inst = new FunctionCallFromLlm
|
||||
{
|
||||
Function = "route_to_agent",
|
||||
Question = message.Content,
|
||||
NextActionReason = message.Content,
|
||||
AgentName = agent.Name,
|
||||
OriginalAgent = agent.Name,
|
||||
ExecutingDirectly = true
|
||||
};
|
||||
var routing = _services.GetRequiredService<IRoutingService>();
|
||||
routing.Context.Push(agent.Id, "instruct directly");
|
||||
var agentId = routing.Context.GetCurrentAgentId();
|
||||
|
||||
message.Instruction = inst;
|
||||
var result = await InvokeFunction("route_to_agent", message);
|
||||
// Update next action agent's name
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
|
||||
if (agent.Disabled)
|
||||
{
|
||||
var content = $"This agent ({agent.Name}) is disabled, please install the corresponding plugin ({agent.Plugin.Name}) to activate this agent.";
|
||||
|
||||
message = RoleDialogModel.From(message, role: AgentRole.Assistant, content: content);
|
||||
dialogs.Add(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ret = await routing.InvokeAgent(agentId, dialogs);
|
||||
}
|
||||
|
||||
var response = dialogs.Last();
|
||||
response.MessageId = message.MessageId;
|
||||
response.Instruction = inst;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public class TemplateRender : ITemplateRender
|
|||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning(error);
|
||||
_logger.LogError(error);
|
||||
return template;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public class VerboseLogHook : IContentGeneratingHook
|
|||
if (dialog != null)
|
||||
{
|
||||
var log = $"{dialog.Role}: {dialog.Content} [msg_id: {dialog.MessageId}] ==>";
|
||||
_logger.LogInformation(log);
|
||||
_logger.LogDebug(log);
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
|
@ -44,7 +44,7 @@ public class VerboseLogHook : IContentGeneratingHook
|
|||
$"[{agent?.Name}]: {message.Indication} {message.FunctionName}({message.FunctionArgs})" :
|
||||
$"[{agent?.Name}]: {message.Content}" + $" <== [msg_id: {message.MessageId}]";
|
||||
|
||||
_logger.LogInformation(tokenStats.Prompt);
|
||||
_logger.LogInformation(log);
|
||||
_logger.LogDebug(tokenStats.Prompt);
|
||||
_logger.LogDebug(log);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ public class TwilioInboundController : TwilioController
|
|||
AgentId = request.AgentId,
|
||||
Channel = ConversationChannel.Phone,
|
||||
ChannelId = request.CallSid,
|
||||
Title = $"Incoming phone call from {request.From}",
|
||||
Title = request.Intent ?? $"Incoming phone call from {request.From}",
|
||||
Tags = [],
|
||||
};
|
||||
|
||||
|
|
@ -161,6 +161,15 @@ public class TwilioInboundController : TwilioController
|
|||
new("twilio_call_sid", request.CallSid),
|
||||
};
|
||||
|
||||
var requestStates = ParseStates(request.States);
|
||||
foreach (var s in requestStates)
|
||||
{
|
||||
if (!states.Any(x => x.Key == s.Key))
|
||||
{
|
||||
states.Add(new MessageState(s.Key, s.Value));
|
||||
}
|
||||
}
|
||||
|
||||
if (request.InitAudioFile != null)
|
||||
{
|
||||
states.Add(new("init_audio_file", request.InitAudioFile));
|
||||
|
|
@ -173,7 +182,20 @@ public class TwilioInboundController : TwilioController
|
|||
{
|
||||
states.Add(new(StateConst.ROUTING_MODE, agent.Mode));
|
||||
}
|
||||
|
||||
convService.SetConversationId(conversation.Id, states);
|
||||
|
||||
if (!string.IsNullOrEmpty(request.Intent))
|
||||
{
|
||||
var storage = _services.GetRequiredService<IConversationStorage>();
|
||||
|
||||
storage.Append(conversation.Id, new RoleDialogModel(AgentRole.User, request.Intent)
|
||||
{
|
||||
CurrentAgentId = conversation.Id,
|
||||
CreatedAt = DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
|
||||
convService.SaveStates();
|
||||
|
||||
// reload agent rendering with states
|
||||
|
|
|
|||
|
|
@ -17,7 +17,10 @@ public class ConversationalVoiceRequest : VoiceRequest
|
|||
public int AIResponseWaitTime { get; set; } = 0;
|
||||
public string? AIResponseErrorMessage { get; set; } = string.Empty;
|
||||
|
||||
public string Intent { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Initial intent when incoming call connected
|
||||
/// </summary>
|
||||
public string? Intent { get; set; }
|
||||
|
||||
[FromQuery(Name = "init-audio-file")]
|
||||
public string? InitAudioFile { get; set; }
|
||||
|
|
|
|||
Loading…
Reference in a new issue