Add user_goal_agent to track user's original task.

This commit is contained in:
hchen 2023-10-12 16:42:39 -05:00
parent 34e22ce35f
commit 985e0501de
9 changed files with 39 additions and 24 deletions

View file

@ -5,7 +5,7 @@ namespace BotSharp.Abstraction.Routing;
public interface IRoutingService
{
List<RoleDialogModel> Dialogs { get; }
Task<FunctionCallFromLlm> GetNextInstruction(string prompt);
Task<FunctionCallFromLlm> GetNextInstruction();
Task<RoleDialogModel> InvokeAgent(string agentId);
Task<RoleDialogModel> InstructLoop();
Task<RoleDialogModel> ExecuteOnce(Agent agent);

View file

@ -6,13 +6,16 @@ public class RoutingArgs
public string Function { get; set; } = string.Empty;
[JsonPropertyName("reason")]
public string Reason { get; set; } = string.Empty;
public string Reason { get; set; } = "the reason why you select this function or agent";
[JsonPropertyName("answer")]
public string Answer { get; set; } = string.Empty;
[JsonPropertyName("agent")]
public string AgentName { get; set; } = string.Empty;
[JsonPropertyName("next_action_agent")]
public string AgentName { get; set; } = "agent for next action based on user's latest response";
[JsonPropertyName("user_goal_agent")]
public string OriginalAgent { get; set; } = "agent who can achieve user's original goal";
public override string ToString()
{

View file

@ -19,6 +19,11 @@ public partial class AgentService
}
var agent = await GetAgent(id);
if (agent == null)
{
throw new Exception($"Can't load agent by id: {id}");
}
var templateDict = new Dictionary<string, object>();
PopulateState(templateDict);

View file

@ -63,8 +63,4 @@
<ProjectReference Include="..\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Routing\Functions\" />
</ItemGroup>
</Project>

View file

@ -25,8 +25,21 @@ public class RouteToAgentFn : IFunctionCallback
{
var args = JsonSerializer.Deserialize<RoutingArgs>(message.FunctionArgs);
// Push to routing stack
_context.Push(message.CurrentAgentId);
// Push original task agent
if (!string.IsNullOrEmpty(args.OriginalAgent) && args.OriginalAgent.Length < 32)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
var originalAgent = db.Agents.FirstOrDefault(x => x.Name.ToLower() == args.OriginalAgent.ToLower());
if (originalAgent != null)
{
_context.Push(originalAgent.Id);
}
}
else
{
// Push current agent to routing stack
_context.Push(message.CurrentAgentId);
}
if (string.IsNullOrEmpty(args.AgentName))
{

View file

@ -15,8 +15,9 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
public List<NameDesc> Parameters => new List<NameDesc>
{
new NameDesc("agent", "the name of the agent"),
new NameDesc("reason", "why route to this agent"),
new NameDesc("next_action_agent", "the name of the next action's agent"),
new NameDesc("user_goal_agent", "the agent who can achieve user's original goal"),
new NameDesc("reason", "the reason why you select this function or agent"),
new NameDesc("args", "the agent required parameters")
};
@ -33,10 +34,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
var message = new RoleDialogModel(AgentRole.Function, inst.Question)
{
FunctionName = inst.Function,
FunctionArgs = JsonSerializer.Serialize(new RoutingArgs
{
AgentName = inst.AgentName
}),
FunctionArgs = JsonSerializer.Serialize(inst),
CurrentAgentId = routing.Dialogs.Last().CurrentAgentId
};
@ -44,7 +42,8 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
var context = _services.GetRequiredService<RoutingContext>();
var result = await routing.InvokeAgent(context.CurrentAgentId);
// Keep last message data for debug
result.ExecutionData = result.ExecutionData ?? message.ExecutionData;
return result;
}
}

View file

@ -7,8 +7,9 @@ namespace BotSharp.Core.Routing;
public partial class RoutingService
{
public async Task<FunctionCallFromLlm> GetNextInstruction(string prompt)
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

View file

@ -76,9 +76,7 @@ public partial class RoutingService : IRoutingService
{
loopCount++;
var prompt = _settings.EnableReasoning ? "Tell me the next step?" : "Which agent is suitable to handle user's request based on the CONVERSATION?";
prompt += " Or you can handle without asking specific agent.";
var inst = await GetNextInstruction(prompt);
var inst = await GetNextInstruction();
inst.Question = inst.Question ?? message;
var handler = handlers.FirstOrDefault(x => x.Name == inst.Function);

View file

@ -81,14 +81,14 @@ public class MemVectorDatabase : IVectorDb
return simiMatix;
}
public int[] CalCosineSimilarityTopK(float[] vec, List<VecRecord> records, int topK = 10, float filterProb = 0.75f)
public (int, float)[] CalCosineSimilarityTopK(float[] vec, List<VecRecord> records, int topK = 10, float filterProb = 0.75f)
{
var simiMatix = CalCosineSimilarity(vec, records);
topK = Math.Min(topK, records.Count);
var topIndex = np.argsort(simiMatix)["::-1"][$":{topK}"];
var resIndex = new List<int>();
var resIndex = new List<(int, float)>();
for (int i = 0; i < topK; i++)
{
@ -97,7 +97,7 @@ public class MemVectorDatabase : IVectorDb
if (value > filterProb)
{
resIndex.Add(topIndex[i]);
resIndex.Add((topIndex[i], value));
}
}