Skip to content

Commit 5db1415

Browse files
authored
Merge pull request #321 from hchen2020/master
Add required flag.
2 parents f2c3123 + 866f412 commit 5db1415

File tree

28 files changed

+239
-88
lines changed

28 files changed

+239
-88
lines changed

src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@
1010
<OutputPath>$(SolutionDir)packages</OutputPath>
1111
</PropertyGroup>
1212

13-
<ItemGroup>
14-
<Compile Remove="Infrastructures\**" />
15-
<EmbeddedResource Remove="Infrastructures\**" />
16-
<None Remove="Infrastructures\**" />
17-
</ItemGroup>
18-
1913
<ItemGroup>
2014
<None Include="..\..\..\arts\Icon.png">
2115
<Pack>True</Pack>

src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,4 @@ public virtual Task OnConversationInitialized(Conversation conversation)
6969

7070
public virtual Task OnUserAgentConnectedInitially(Conversation conversation)
7171
=> Task.CompletedTask;
72-
73-
public virtual Task OnConversationRedirected(string toAgentId, RoleDialogModel message)
74-
=> Task.CompletedTask;
75-
76-
public virtual Task OnConversationRouting(FunctionCallFromLlm instruct, RoleDialogModel message)
77-
=> Task.CompletedTask;
7872
}

src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,20 +84,4 @@ public interface IConversationHook
8484
/// <param name="conversation"></param>
8585
/// <returns></returns>
8686
Task OnHumanInterventionNeeded(RoleDialogModel message);
87-
88-
/// <summary>
89-
/// Conversation is redirected to another agent
90-
/// </summary>
91-
/// <param name="toAgentId"></param>
92-
/// <param name="message"></param>
93-
/// <returns></returns>
94-
Task OnConversationRedirected(string toAgentId, RoleDialogModel message);
95-
96-
/// <summary>
97-
/// Routing instruction is received from Router
98-
/// </summary>
99-
/// <param name="instruct">routing instruction</param>
100-
/// <param name="message">message</param>
101-
/// <returns></returns>
102-
Task OnConversationRouting(FunctionCallFromLlm instruct, RoleDialogModel message);
10387
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace BotSharp.Abstraction.Infrastructures;
2+
3+
public class HookEmittedResult
4+
{
5+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace BotSharp.Abstraction.Routing;
2+
3+
public interface IRoutingContext
4+
{
5+
string GetCurrentAgentId();
6+
string OriginAgentId { get; }
7+
bool IsEmpty { get; }
8+
string IntentName { get; set; }
9+
void Push(string agentId);
10+
void Pop();
11+
void Replace(string agentId);
12+
void Empty();
13+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using BotSharp.Abstraction.Functions.Models;
2+
3+
namespace BotSharp.Abstraction.Routing;
4+
5+
public interface IRoutingHook
6+
{
7+
/// <summary>
8+
/// Conversation is redirected to another agent
9+
/// </summary>
10+
/// <param name="toAgentId"></param>
11+
/// <param name="message"></param>
12+
/// <returns></returns>
13+
Task OnConversationRedirected(string toAgentId, RoleDialogModel message);
14+
15+
/// <summary>
16+
/// Routing instruction is received from Router
17+
/// </summary>
18+
/// <param name="instruct">routing instruction</param>
19+
/// <param name="message">message</param>
20+
/// <returns></returns>
21+
Task OnConversationRouting(FunctionCallFromLlm instruct, RoleDialogModel message);
22+
23+
Task OnAgentEnqueued(string agentId, string preAgentId);
24+
25+
Task OnAgentDequeued(string agentId, string currentAgentId);
26+
27+
Task OnAgentReplaced(string fromAgentId, string toAgentId);
28+
29+
Task OnAgentQueueEmptied(string agentId);
30+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using BotSharp.Abstraction.Infrastructures;
2+
3+
namespace BotSharp.Core.Infrastructures;
4+
5+
public static class HookEmitter
6+
{
7+
public static async Task<HookEmittedResult> Emit<T>(IServiceProvider services, Action<T> action)
8+
{
9+
var logger = services.GetRequiredService<ILogger<T>>();
10+
var result = new HookEmittedResult();
11+
var hooks = services.GetServices<T>();
12+
13+
foreach (var hook in hooks)
14+
{
15+
try
16+
{
17+
action(hook);
18+
}
19+
catch (Exception ex)
20+
{
21+
logger.LogError(ex.ToString());
22+
}
23+
}
24+
25+
return result;
26+
}
27+
}

src/Infrastructure/BotSharp.Core/Routing/Functions/FallbackToRouterFn.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public async Task<bool> Execute(RoleDialogModel message)
2929
return false;
3030
}
3131

32-
var routing = _services.GetRequiredService<RoutingContext>();
32+
var routing = _services.GetRequiredService<IRoutingContext>();
3333
routing.Replace(targetAgent.Id);
3434

3535
var router = _services.GetRequiredService<IRoutingService>();

src/Infrastructure/BotSharp.Core/Routing/Functions/RouteToAgentFn.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ public class RouteToAgentFn : IFunctionCallback
1414
{
1515
public string Name => "route_to_agent";
1616
private readonly IServiceProvider _services;
17-
private readonly RoutingContext _context;
17+
private readonly IRoutingContext _context;
1818

19-
public RouteToAgentFn(IServiceProvider services, RoutingContext context)
19+
public RouteToAgentFn(IServiceProvider services, IRoutingContext context)
2020
{
2121
_services = services;
2222
_context = context;
@@ -153,11 +153,9 @@ private bool HasMissingRequiredField(RoleDialogModel message, out string agentId
153153
#else
154154
logger.LogInformation($"*** Routing redirect to {record.Name.ToUpper()} ***");
155155
#endif
156-
var hooks = _services.GetServices<IConversationHook>();
157-
foreach (var hook in hooks)
158-
{
159-
hook.OnConversationRedirected(routingRule.RedirectTo, message).Wait();
160-
}
156+
HookEmitter.Emit<IRoutingHook>(_services, async hook =>
157+
await hook.OnConversationRedirected(routingRule.RedirectTo, message)
158+
).Wait();
161159
}
162160
else
163161
{

src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public RetrieveDataFromAgentRoutingHandler(IServiceProvider services, ILogger<Re
3939

4040
public async Task<bool> Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message)
4141
{
42-
var context = _services.GetRequiredService<RoutingContext>();
42+
var context = _services.GetRequiredService<IRoutingContext>();
4343
var agentId = context.GetCurrentAgentId();
4444
var dialogs = new List<RoleDialogModel>
4545
{

src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,18 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
1414

1515
public List<ParameterPropertyDef> Parameters => new List<ParameterPropertyDef>
1616
{
17-
new ParameterPropertyDef("reason", "why route to agent"),
18-
new ParameterPropertyDef("next_action_agent", "agent for next action based on user latest response"),
19-
new ParameterPropertyDef("user_goal_agent", "agent who can achieve user original goal"),
17+
new ParameterPropertyDef("reason", "why route to agent")
18+
{
19+
Required = true
20+
},
21+
new ParameterPropertyDef("next_action_agent", "agent for next action based on user latest response")
22+
{
23+
Required = true
24+
},
25+
new ParameterPropertyDef("user_goal_agent", "agent who can achieve user original goal")
26+
{
27+
Required = true
28+
},
2029
new ParameterPropertyDef("args", "useful parameters of next action agent, format: { }")
2130
{
2231
Type = "object"
@@ -30,7 +39,7 @@ public RouteToAgentRoutingHandler(IServiceProvider services, ILogger<RouteToAgen
3039

3140
public async Task<bool> Handle(IRoutingService routing, FunctionCallFromLlm inst, RoleDialogModel message)
3241
{
33-
var context = _services.GetRequiredService<RoutingContext>();
42+
var context = _services.GetRequiredService<IRoutingContext>();
3443
var function = _services.GetServices<IFunctionCallback>().FirstOrDefault(x => x.Name == inst.Function);
3544
message.FunctionArgs = JsonSerializer.Serialize(inst);
3645
var ret = await function.Execute(message);

src/Infrastructure/BotSharp.Core/Routing/Planning/HFPlanner.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using BotSharp.Abstraction.Functions.Models;
33
using BotSharp.Abstraction.Repositories;
44
using BotSharp.Abstraction.Repositories.Filters;
5-
using BotSharp.Abstraction.Routing.Models;
5+
using BotSharp.Abstraction.Routing;
66
using BotSharp.Abstraction.Routing.Planning;
77
using BotSharp.Abstraction.Templating;
88

@@ -75,7 +75,7 @@ public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, R
7575
var filter = new AgentFilter { AgentName = inst.AgentName };
7676
var agent = db.GetAgents(filter).FirstOrDefault();
7777

78-
var context = _services.GetRequiredService<RoutingContext>();
78+
var context = _services.GetRequiredService<IRoutingContext>();
7979
context.Push(agent.Id);
8080
}
8181

@@ -84,7 +84,7 @@ public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, R
8484

8585
public async Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
8686
{
87-
var context = _services.GetRequiredService<RoutingContext>();
87+
var context = _services.GetRequiredService<IRoutingContext>();
8888
context.Empty();
8989
return true;
9090
}

src/Infrastructure/BotSharp.Core/Routing/Planning/NaivePlanner.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, R
8787

8888
public async Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
8989
{
90-
var context = _services.GetRequiredService<RoutingContext>();
90+
var context = _services.GetRequiredService<IRoutingContext>();
9191
if (inst.UnmatchedAgent)
9292
{
9393
var unmatchedAgentId = context.GetCurrentAgentId();

src/Infrastructure/BotSharp.Core/Routing/Planning/SequentialPlanner.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, R
140140

141141
public async Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
142142
{
143-
var context = _services.GetRequiredService<RoutingContext>();
143+
var context = _services.GetRequiredService<IRoutingContext>();
144144

145145
if (message.StopCompletion)
146146
{

src/Infrastructure/BotSharp.Core/Routing/Planning/TwoStagePlanner/TwoStagePlanner.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, R
155155

156156
public async Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
157157
{
158-
var context = _services.GetRequiredService<RoutingContext>();
158+
var context = _services.GetRequiredService<IRoutingContext>();
159159

160160
if (message.StopCompletion || _isTaskCompleted)
161161
{

src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingContext.cs renamed to src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
using BotSharp.Abstraction.Agents;
21
using BotSharp.Abstraction.Repositories.Filters;
32
using BotSharp.Abstraction.Routing.Settings;
4-
using Microsoft.Extensions.DependencyInjection;
53

6-
namespace BotSharp.Abstraction.Routing.Models;
4+
namespace BotSharp.Core.Routing;
75

8-
public class RoutingContext
6+
public class RoutingContext : IRoutingContext
97
{
108
private readonly IServiceProvider _services;
119
private readonly RoutingSettings _setting;
@@ -56,7 +54,12 @@ public void Push(string agentId)
5654
{
5755
if (_stack.Count == 0 || _stack.Peek() != agentId)
5856
{
57+
var preAgentId = _stack.Count == 0 ? agentId : _stack.Peek();
5958
_stack.Push(agentId);
59+
60+
HookEmitter.Emit<IRoutingHook>(_services, async hook =>
61+
await hook.OnAgentEnqueued(agentId, preAgentId)
62+
).Wait();
6063
}
6164
}
6265

@@ -65,24 +68,50 @@ public void Push(string agentId)
6568
/// </summary>
6669
public void Pop()
6770
{
68-
_stack.Pop();
71+
if (_stack.Count == 0)
72+
{
73+
return;
74+
}
75+
76+
var agentId = _stack.Pop();
77+
78+
HookEmitter.Emit<IRoutingHook>(_services, async hook =>
79+
await hook.OnAgentDequeued(agentId, _stack.Peek())
80+
).Wait();
6981
}
7082

7183
public void Replace(string agentId)
7284
{
85+
var fromAgent = agentId;
86+
var toAgent = agentId;
87+
7388
if (_stack.Count == 0)
7489
{
7590
_stack.Push(agentId);
7691
}
7792
else if (_stack.Peek() != agentId)
7893
{
94+
fromAgent = _stack.Peek();
7995
_stack.Pop();
8096
_stack.Push(agentId);
97+
98+
HookEmitter.Emit<IRoutingHook>(_services, async hook =>
99+
await hook.OnAgentReplaced(fromAgent, toAgent)
100+
).Wait();
81101
}
82102
}
83103

84104
public void Empty()
85105
{
106+
if (_stack.Count == 0)
107+
{
108+
return;
109+
}
110+
111+
var agentId = GetCurrentAgentId();
86112
_stack.Clear();
113+
HookEmitter.Emit<IRoutingHook>(_services, async hook =>
114+
await hook.OnAgentQueueEmptied(agentId)
115+
).Wait();
87116
}
88117
}

src/Infrastructure/BotSharp.Core/Routing/RoutingPlugin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public object GetNewSettingsInstance() =>
2323

2424
public void RegisterDI(IServiceCollection services, IConfiguration config)
2525
{
26-
services.AddScoped<RoutingContext>();
26+
services.AddScoped<IRoutingContext, RoutingContext>();
2727

2828
// Register router
2929
services.AddScoped(provider =>

src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ private async Task<bool> InvokeFunction(RoleDialogModel message, List<RoleDialog
6464
// Pass execution result to LLM to get response
6565
if (!message.StopCompletion)
6666
{
67-
var routing = _services.GetRequiredService<RoutingContext>();
67+
var routing = _services.GetRequiredService<IRoutingContext>();
6868

6969
// Find response template
7070
var templateService = _services.GetRequiredService<IResponseTemplateService>();

src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public async Task<bool> InvokeFunction(string name, RoleDialogModel message)
1212
var originalFunctionName = message.FunctionName;
1313
message.FunctionName = name;
1414
message.Role = AgentRole.Function;
15+
message.FunctionArgs = message.FunctionArgs;
1516
var result = await function.Execute(message);
1617

1718
// restore original function name

src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message)
8080
var conv = _services.GetRequiredService<IConversationService>();
8181
var dialogs = conv.GetDialogHistory();
8282

83-
var context = _services.GetRequiredService<RoutingContext>();
83+
var context = _services.GetRequiredService<IRoutingContext>();
8484
var executor = _services.GetRequiredService<IExecutor>();
8585

8686
var planner = GetPlanner(_router);
@@ -98,11 +98,9 @@ public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message)
9898
// Get instruction from Planner
9999
var inst = await planner.GetNextInstruction(_router, message.MessageId, dialogs);
100100

101-
var hooks = _services.GetServices<IConversationHook>();
102-
foreach (var hook in hooks)
103-
{
104-
await hook.OnConversationRouting(inst, message);
105-
}
101+
await HookEmitter.Emit<IRoutingHook>(_services, async hook =>
102+
await hook.OnConversationRouting(inst, message)
103+
);
106104

107105
// Save states
108106
states.SaveStateByArgs(inst.Arguments);

src/Infrastructure/BotSharp.Core/Templating/ResponseTemplateService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ public async Task<string> RenderIntentResponse(string agentId, RoleDialogModel m
6868
// .ToList();
6969

7070
var db = _services.GetRequiredService<IBotSharpRepository>();
71-
var context = _services.GetRequiredService<RoutingContext>();
72-
var responses = db.GetAgentResponses(agentId, "intent", context.IntentName);
71+
var routing = _services.GetRequiredService<IRoutingContext>();
72+
var responses = db.GetAgentResponses(agentId, "intent", routing.IntentName);
7373

7474
if (responses.Count == 0)
7575
{

0 commit comments

Comments
 (0)