Move next step prompt to liquid template.

This commit is contained in:
Haiping 2023-10-13 18:36:57 -05:00
parent bf151a0d09
commit 1c0fe993ba
7 changed files with 62 additions and 27 deletions

View file

@ -15,13 +15,13 @@ public class FunctionCallFromLlm : RoutingArgs
{
var route = string.IsNullOrEmpty(AgentName) ? "" : $"<Route to {AgentName.ToUpper()} because {Reason}>";
if (string.IsNullOrEmpty(Answer))
if (string.IsNullOrEmpty(Response))
{
return $"[{Function} {route} {JsonSerializer.Serialize(Arguments)}]: {Question}";
}
else
{
return $"[{Function} {route} {JsonSerializer.Serialize(Arguments)}]: {Question} => {Answer}";
return $"[{Function} {route} {JsonSerializer.Serialize(Arguments)}]: {Question} => {Response}";
}
}
}

View file

@ -5,29 +5,41 @@ public class RoutingArgs
[JsonPropertyName("function")]
public string Function { get; set; }
/// <summary>
/// The reason why you select this function or agent
/// </summary>
[JsonPropertyName("reason")]
public string Reason { get; set; } = "the reason why you select this function or agent";
public string Reason { get; set; } = string.Empty;
[JsonPropertyName("answer")]
public string Answer { get; set; } = "the content of response to user";
/// <summary>
/// The content of replying to user
/// </summary>
[JsonPropertyName("response")]
public string Response { get; set; }
/// <summary>
/// Agent for next action based on user latest response
/// </summary>
[JsonPropertyName("next_action_agent")]
public string AgentName { get; set; } = "agent for next action based on user latest response";
public string AgentName { get; set; }
/// <summary>
/// Agent who can achieve user original goal
/// </summary>
[JsonPropertyName("user_goal_agent")]
public string OriginalAgent { get; set; } = "agent who can achieve user original goal";
public string OriginalAgent { get; set; }
public override string ToString()
{
var route = string.IsNullOrEmpty(AgentName) ? "" : $"<Route to {AgentName.ToUpper()} because {Reason}>";
if (string.IsNullOrEmpty(Answer))
if (string.IsNullOrEmpty(Response))
{
return $"[{Function} {route}]";
}
else
{
return $"[{Function} {route}] => {Answer}";
return $"[{Function} {route}] => {Response}";
}
}
}

View file

@ -8,7 +8,7 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
{
public string Name => "conversation_end";
public string Description => "User wants to end the conversation.";
public string Description => "User completed his task and wants to end the conversation.";
public bool IsReasoning => false;
@ -19,11 +19,11 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
public async Task<RoleDialogModel> Handle(IRoutingService routing, FunctionCallFromLlm inst)
{
var result = new RoleDialogModel(AgentRole.Assistant, inst.Answer)
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
{
CurrentAgentId = _settings.RouterId,
FunctionName = inst.Function,
StopCompletion = true
ExecutionData = inst
};
return result;
}

View file

@ -20,10 +20,11 @@ public class ResponseToUserRoutingHandler : RoutingHandlerBase, IRoutingHandler
public async Task<RoleDialogModel> Handle(IRoutingService routing, FunctionCallFromLlm inst)
{
var result = new RoleDialogModel(AgentRole.Assistant, inst.Answer)
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
{
CurrentAgentId = _settings.RouterId,
FunctionName = inst.Function,
ExecutionData = inst,
StopCompletion = true
};
return result;

View file

@ -34,7 +34,7 @@ public class RetrieveDataFromAgentRoutingHandler : RoutingHandlerBase, IRoutingH
var record = db.Agents.First(x => x.Name.ToLower() == inst.AgentName.ToLower());
var response = await routing.InvokeAgent(record.Id);
inst.Answer = response.Content;
inst.Response = response.Content;
/*_dialogs.Add(new RoleDialogModel(AgentRole.Assistant, inst.Parameters.Question)
{

View file

@ -1,6 +1,8 @@
using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.Routing.Models;
using BotSharp.Abstraction.Templating;
using System.Drawing;
using System.IO;
using System.Text.RegularExpressions;
namespace BotSharp.Core.Routing;
@ -9,17 +11,7 @@ public partial class RoutingService
{
public async Task<FunctionCallFromLlm> GetNextInstruction()
{
var prompt = "Which is the next step based on the CONVERSATION? Or you can handle without asking specific agent.";
var responseFormat = _settings.EnableReasoning ?
JsonSerializer.Serialize(new FunctionCallFromLlm()) :
JsonSerializer.Serialize(new RoutingArgs
{
Function = "route_to_agent"
});
var content = $"{prompt} Response must be in JSON format {responseFormat}.";
content += " Set function as conversation_end with courtesy greeting if user is willing to end conversation";
var state = _services.GetRequiredService<IConversationStateService>();
var content = GetNextStepPrompt();
RoleDialogModel response = default;
var args = new FunctionCallFromLlm();
@ -50,7 +42,7 @@ public partial class RoutingService
{
_logger.LogError($"{ex.Message}: {response.Content}");
args.Function = "response_to_user";
args.Answer = ex.Message;
args.Response = ex.Message;
args.AgentName = "Router";
content += "\r\nPlease response in JSON format.";
}
@ -86,7 +78,7 @@ public partial class RoutingService
{
_logger.LogError($"{ex.Message}: {response.Content}");
args.Function = "response_to_user";
args.Answer = ex.Message;
args.Response = ex.Message;
args.AgentName = "Router";
content += "\r\nPlease response in JSON format.";
}
@ -135,4 +127,24 @@ public partial class RoutingService
return args;
}
#if !DEBUG
[MemoryCache(60 * 60)]
#endif
private string GetNextStepPrompt()
{
var agentService = _services.GetRequiredService<IAgentService>();
var agentSettings = _services.GetRequiredService<AgentSettings>();
var filePath = Path.Combine(agentService.GetAgentDataDir(_routerInstance.AgentId), $"next_step_prompt.{agentSettings.TemplateFormat}");
var template = File.ReadAllText(filePath);
// If enabled reasoning
// JsonSerializer.Serialize(new FunctionCallFromLlm());
var render = _services.GetRequiredService<ITemplateRender>();
return render.Render(template, new Dictionary<string, object>
{
{ "enabled_reasoning", false }
});
}
}

View file

@ -0,0 +1,10 @@
What is the next step based on the CONVERSATION? Or you can handle without asking specific agent.
Response must be in JSON format
{% if enabled_reasoning -%}
{"function":"route_to_agent"}
{%- else -%}
{"function":"route_to_agent","reason":"the reason why you select this function or agent","response":"content of replying to user","next_action_agent":"agent for next action based on user latest response","user_goal_agent":"agent who can achieve user original goal"}
{%- endif %}
If the user has no other tasks need help with, set function as conversation_end with reason and reply user courteously.