Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ namespace BotSharp.Abstraction.Http;

public interface IHttpRequestHook
{
void OnAddHttpHeaders(HttpHeaders headers, Uri uri);
Task OnAddHttpHeaders(HttpHeaders headers, Uri uri);
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
Task<List<User>> GetUsersByAffiliateId(string affiliateId) => throw new NotImplementedException();
Task<User?> GetUserByUserName(string userName) => throw new NotImplementedException();
Task UpdateUserName(string userId, string userName) => throw new NotImplementedException();
Task<Dashboard?> GetDashboard(string id = null) => throw new NotImplementedException();

Check warning on line 51 in src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Cannot convert null literal to non-nullable reference type.

Check warning on line 51 in src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Cannot convert null literal to non-nullable reference type.

Check warning on line 51 in src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest)

Cannot convert null literal to non-nullable reference type.

Check warning on line 51 in src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest)

Cannot convert null literal to non-nullable reference type.

Check warning on line 51 in src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Cannot convert null literal to non-nullable reference type.

Check warning on line 51 in src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Cannot convert null literal to non-nullable reference type.
Task CreateUser(User user) => throw new NotImplementedException();
Task UpdateExistUser(string userId, User user) => throw new NotImplementedException();
Task UpdateUserVerified(string userId) => throw new NotImplementedException();
Expand All @@ -70,9 +70,7 @@
#region Agent
Task UpdateAgent(Agent agent, AgentField field)
=> throw new NotImplementedException();
Agent? GetAgent(string agentId, bool basicsOnly = false)
=> throw new NotImplementedException();
Task<Agent?> GetAgentAsync(string agentId, bool basicsOnly = false)
Task<Agent?> GetAgent(string agentId, bool basicsOnly = false)
=> throw new NotImplementedException();
Task<List<Agent>> GetAgents(AgentFilter filter)
=> throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ public interface IRoutingContext
bool IsEmpty { get; }
string IntentName { get; set; }
int AgentCount { get; }
void Push(string agentId, string? reason = null, bool updateLazyRouting = true);
void Pop(string? reason = null, bool updateLazyRouting = true);
void PopTo(string agentId, string reason, bool updateLazyRouting = true);
void Replace(string agentId, string? reason = null, bool updateLazyRouting = true);
void Empty(string? reason = null);
Task Push(string agentId, string? reason = null, bool updateLazyRouting = true);
Task Pop(string? reason = null, bool updateLazyRouting = true);
Task PopTo(string agentId, string reason, bool updateLazyRouting = true);
Task Replace(string agentId, string? reason = null, bool updateLazyRouting = true);
Task Empty(string? reason = null);


int CurrentRecursionDepth { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ public interface IRoutingService
/// </summary>
/// <param name="profiles">router's profile</param>
/// <returns></returns>
RoutableAgent[] GetRoutableAgents(List<string> profiles);
Task<RoutableAgent[]> GetRoutableAgents(List<string> profiles);

/// <summary>
/// Get rules by agent name
/// </summary>
/// <param name="name">agent name</param>
/// <returns></returns>
RoutingRule[] GetRulesByAgentName(string name);
Task<RoutingRule[]> GetRulesByAgentName(string name);

/// <summary>
/// Get rules by agent id
/// </summary>
/// <param name="id">agent id </param>
/// <returns></returns>
RoutingRule[] GetRulesByAgentId(string id);
Task<RoutingRule[]> GetRulesByAgentId(string id);

Task<bool> InvokeAgent(string agentId, List<RoleDialogModel> dialogs, InvokeAgentOptions? options = null);
Task<bool> InvokeFunction(string name, RoleDialogModel messages, InvokeFunctionOptions? options = null);
Expand All @@ -40,5 +40,5 @@ public interface IRoutingService

Task<string> GetConversationContent(List<RoleDialogModel> dialogs, int maxDialogCount = 100);

(bool, string) HasMissingRequiredField(RoleDialogModel message, out string agentId);
Task<(bool hasMissing, string reason, string agentId)> HasMissingRequiredField(RoleDialogModel message);
}
16 changes: 7 additions & 9 deletions src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,25 @@ public BasicAgentHook(IServiceProvider services, AgentSettings settings)
{
}

public override Task OnAgentUtilityLoaded(Agent agent)
public override async Task OnAgentUtilityLoaded(Agent agent)
{
var conv = _services.GetRequiredService<IConversationService>();
var isConvMode = conv.IsConversationMode();
if (!isConvMode) return Task.CompletedTask;
if (!isConvMode) return;

agent.Utilities ??= [];
agent.SecondaryFunctions ??= [];
agent.SecondaryInstructions ??= [];

var (functions, templates) = GetUtilityContent(agent);
var (functions, templates) = await GetUtilityContent(agent);

agent.SecondaryFunctions = agent.SecondaryFunctions.Concat(functions).DistinctBy(x => x.Name, StringComparer.OrdinalIgnoreCase).ToList();
var contents = templates.Select(x => x.Content);
agent.SecondaryInstructions = agent.SecondaryInstructions.Concat(contents).Distinct(StringComparer.OrdinalIgnoreCase).ToList();

return Task.CompletedTask;
}


private (IEnumerable<FunctionDef>, IEnumerable<AgentTemplate>) GetUtilityContent(Agent agent)
private async Task<(IEnumerable<FunctionDef>, IEnumerable<AgentTemplate>)> GetUtilityContent(Agent agent)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
var (functionNames, templateNames) = FilterUtilityContent(agent.Utilities, agent);
Expand All @@ -42,14 +40,14 @@ public override Task OnAgentUtilityLoaded(Agent agent)
var entryAgentId = routing.EntryAgentId;
if (!string.IsNullOrEmpty(entryAgentId))
{
var entryAgent = db.GetAgent(entryAgentId, basicsOnly: true);
var entryAgent = await db.GetAgent(entryAgentId, basicsOnly: true);
var (fns, tps) = FilterUtilityContent(entryAgent?.Utilities, agent);
functionNames = functionNames.Concat(fns).Distinct().ToList();
templateNames = templateNames.Concat(tps).Distinct().ToList();
}
}

var ua = db.GetAgent(BuiltInAgentId.UtilityAssistant);
var ua = await db.GetAgent(BuiltInAgentId.UtilityAssistant);
var functions = ua?.Functions?.Where(x => functionNames.Contains(x.Name, StringComparer.OrdinalIgnoreCase))?.ToList() ?? [];
var templates = ua?.Templates?.Where(x => templateNames.Contains(x.Name, StringComparer.OrdinalIgnoreCase))?.ToList() ?? [];
return (functions, templates);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public async Task<Agent> GetAgent(string id)
return null;
}

var profile = await _db.GetAgentAsync(id);
var profile = await _db.GetAgent(id);
if (profile == null)
{
_logger.LogError($"Can't find agent {id}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public async Task UpdateAgent(Agent agent, AgentField updateField)
return;
}

var record = await _db.GetAgentAsync(agent.Id);
var record = await _db.GetAgent(agent.Id);
if (record == null) return;

record.Name = agent.Name ?? string.Empty;
Expand Down Expand Up @@ -65,7 +65,7 @@ public async Task<string> PatchAgentTemplate(Agent agent)
return patchResult;
}

var record = await _db.GetAgentAsync(agent.Id);
var record = await _db.GetAgent(agent.Id);
if (record == null)
{
patchResult = $"Cannot find agent {agent.Id}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public async Task<bool> SendMessage(string agentId,
if (message.StopCompletion)
{
stopCompletion = true;
routing.Context.Pop();
await routing.Context.Pop();
break;
}
}
Expand All @@ -83,12 +83,12 @@ public async Task<bool> SendMessage(string agentId,
// Check the routing mode
var states = _services.GetRequiredService<IConversationStateService>();
var routingMode = states.GetState(StateConst.ROUTING_MODE, agent.Mode ?? RoutingMode.Eager);
routing.Context.Push(agent.Id, reason: "request started", updateLazyRouting: false);
await routing.Context.Push(agent.Id, reason: "request started", updateLazyRouting: false);

if (routingMode == RoutingMode.Lazy)
{
message.CurrentAgentId = states.GetState(StateConst.LAZY_ROUTING_AGENT_ID, message.CurrentAgentId);
routing.Context.Push(message.CurrentAgentId, reason: "lazy routing", updateLazyRouting: false);
await routing.Context.Push(message.CurrentAgentId, reason: "lazy routing", updateLazyRouting: false);
}

response = await routing.InstructLoop(agent, message, dialogs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ public bool IsConversationMode()

if (string.IsNullOrEmpty(routingCtx.EntryAgentId)) return null;

var agent = await db.GetAgentAsync(routingCtx.EntryAgentId, basicsOnly: true);
var agent = await db.GetAgent(routingCtx.EntryAgentId, basicsOnly: true);
return agent?.MaxMessageCount;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,14 +564,14 @@ public async Task<List<string>> GetAgentResponses(string agentId, string prefix,
return responses;
}

public Agent? GetAgent(string agentId, bool basicsOnly = false)
public async Task<Agent?> GetAgent(string agentId, bool basicsOnly = false)
{
var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir);
var dir = Directory.EnumerateDirectories(agentDir).FirstOrDefault(x => x.Split(Path.DirectorySeparatorChar).Last() == agentId);

if (!string.IsNullOrEmpty(dir))
{
var json = File.ReadAllText(Path.Combine(dir, AGENT_FILE));
var json = await File.ReadAllTextAsync(Path.Combine(dir, AGENT_FILE));
if (string.IsNullOrEmpty(json))
{
return null;
Expand All @@ -593,23 +593,18 @@ public async Task<List<string>> GetAgentResponses(string agentId, string prefix,
var samples = FetchSamples(dir);
var templates = FetchTemplates(dir);
var responses = FetchResponses(dir);
return record.SetInstruction(defaultInstruction)
var result = record.SetInstruction(defaultInstruction)
.SetChannelInstructions(channelInstructions)
.SetFunctions(functions)
.SetTemplates(templates)
.SetSamples(samples)
.SetResponses(responses);
return result;
}

return null;
}

public Task<Agent?> GetAgentAsync(string agentId, bool basicsOnly = false)
{
var agent = GetAgent(agentId, basicsOnly);
return Task.FromResult(agent);
}

public Task<List<Agent>> GetAgents(AgentFilter filter)
{
if (filter == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public async Task<bool> Execute(RoleDialogModel message)
{
var args = JsonSerializer.Deserialize<FallbackArgs>(message.FunctionArgs);
var routing = _services.GetRequiredService<IRoutingService>();
routing.Context.PopTo(routing.Context.EntryAgentId, "pop to entry agent");
await routing.Context.PopTo(routing.Context.EntryAgentId, "pop to entry agent");
message.Content = args.Reason;

return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ public async Task<bool> Execute(RoleDialogModel message)
var originalAgent = (await db.GetAgents(filter)).FirstOrDefault();
if (originalAgent != null)
{
_context.Push(originalAgent.Id, $"user goal agent{(correctToOriginalAgent ? " " + originalAgent.Name + " & is corrected" : "")}");
await _context.Push(originalAgent.Id, $"user goal agent{(correctToOriginalAgent ? " " + originalAgent.Name + " & is corrected" : "")}");
}
}

// Push next action agent
if (!string.IsNullOrEmpty(args.AgentName) && args.AgentName.Length < 32)
{
_context.Push(args.AgentName, args.NextActionReason);
await _context.Push(args.AgentName, args.NextActionReason);
states.SetState(StateConst.NEXT_ACTION_AGENT, args.AgentName, isNeedVersion: true);
}

Expand All @@ -83,11 +83,11 @@ public async Task<bool> Execute(RoleDialogModel message)
}

var routing = _services.GetRequiredService<IRoutingService>();
var (missingfield, reason) = routing.HasMissingRequiredField(message, out var agentId);
var (missingfield, reason, agentId) = await routing.HasMissingRequiredField(message);
if (missingfield && message.CurrentAgentId != agentId)
{
// Stack redirection agent
_context.Push(agentId, reason: $"REDIRECTION {reason}");
await _context.Push(agentId, reason: $"REDIRECTION {reason}");
message.Content = reason;
states.SetState(StateConst.AGENT_REDIRECTION_REASON, reason, isNeedVersion: false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public override async Task<bool> OnInstructionLoaded(string template, IDictionar
dict["router"] = _agent;

var routing = _services.GetRequiredService<IRoutingService>();
var agents = routing.GetRoutableAgents(_agent.Profiles);
var agents = await routing.GetRoutableAgents(_agent.Profiles);

// 过滤 Planner
// filter Planner
var planningRule = _agent.RoutingRules.FirstOrDefault(x => x.Type == "planner");
if (planningRule != null)
{
Expand Down Expand Up @@ -68,8 +68,8 @@ public override async Task<bool> OnFunctionsLoaded(List<FunctionDef> functions)
{
// check if enabled the routing rule
var routing = _services.GetRequiredService<IRoutingService>();
var rule = routing.GetRulesByAgentId(_agent.Id)
.FirstOrDefault(x => x.Type == RuleType.Fallback);
var rules = await routing.GetRulesByAgentId(_agent.Id);
var rule = rules.FirstOrDefault(x => x.Type == RuleType.Fallback);
if (rule != null)
{
var agentService = _services.GetRequiredService<IAgentService>();
Expand Down
10 changes: 5 additions & 5 deletions src/Infrastructure/BotSharp.Core/Routing/Reasoning/HFReasoner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public async Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string m
var inst = response.Content.JsonContent<FunctionCallFromLlm>();

// Fix LLM malformed response
ReasonerHelper.FixMalformedResponse(_services, inst);
await ReasonerHelper.FixMalformedResponse(_services, inst);

return inst;
}
Expand All @@ -69,7 +69,7 @@ public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, R
var agent = (await db.GetAgents(filter)).FirstOrDefault();

var context = _services.GetRequiredService<IRoutingContext>();
context.Push(agent.Id, reason: inst.NextActionReason);
await context.Push(agent.Id, reason: inst.NextActionReason);

// Set user content as Planner's question
message.FunctionName = inst.Function;
Expand All @@ -79,11 +79,11 @@ public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, R
return true;
}

public Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
public async Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
{
var context = _services.GetRequiredService<IRoutingContext>();
context.Empty(reason: $"Agent queue is cleared by {nameof(HFReasoner)}");
return Task.FromResult(true);
await context.Empty(reason: $"Agent queue is cleared by {nameof(HFReasoner)}");
return true;
}

private string GetNextStepPrompt(Agent router)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public async Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string m
var inst = (response.FunctionArgs ?? response.Content).JsonContent<FunctionCallFromLlm>();

// Fix LLM malformed response
ReasonerHelper.FixMalformedResponse(_services, inst);
await ReasonerHelper.FixMalformedResponse(_services, inst);

return inst;
}
Expand All @@ -73,7 +73,7 @@ public Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDia
return Task.FromResult(true);
}

public Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
public async Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
{
var context = _services.GetRequiredService<IRoutingContext>();
if (inst.UnmatchedAgent)
Expand All @@ -85,14 +85,14 @@ public Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDial
router.TemplateDict["routing_agents"] = agents.Where(x => x.AgentId != unmatchedAgentId).ToArray();

// Handover to Router;
context.Pop();
await context.Pop();
}
else
{
context.Empty(reason: $"Agent queue is cleared by {nameof(NaiveReasoner)}");
await context.Empty(reason: $"Agent queue is cleared by {nameof(NaiveReasoner)}");
// context.Push(inst.OriginalAgent, "Push user goal agent");
}
return Task.FromResult(true);
return true;
}

private string GetNextStepPrompt(Agent router)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public async Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string m
var inst = response.Content.JsonContent<FunctionCallFromLlm>();

// Fix LLM malformed response
ReasonerHelper.FixMalformedResponse(_services, inst);
await ReasonerHelper.FixMalformedResponse(_services, inst);

return inst;
}
Expand All @@ -80,7 +80,7 @@ public Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDia
return Task.FromResult(true);
}

public Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
public async Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
{
var context = _services.GetRequiredService<IRoutingContext>();
if (inst.UnmatchedAgent)
Expand All @@ -92,14 +92,14 @@ public Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDial
router.TemplateDict["routing_agents"] = agents.Where(x => x.AgentId != unmatchedAgentId).ToArray();

// Handover to Router;
context.Pop();
await context.Pop();
}
else
{
context.Empty(reason: $"Agent queue is cleared by {nameof(OneStepForwardReasoner)}");
await context.Empty(reason: $"Agent queue is cleared by {nameof(OneStepForwardReasoner)}");
// context.Push(inst.OriginalAgent, "Push user goal agent");
}
return Task.FromResult(true);
return true;
}

private string GetNextStepPrompt(Agent router)
Expand Down
Loading
Loading