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
@@ -1,8 +1,11 @@
using BotSharp.Abstraction.Routing.Models;

namespace BotSharp.Abstraction.Agents;

public interface IAgentRouting
{
string AgentId { get; }
Task<Agent> LoadRouter();
Task<Agent> LoadCurrentAgent();
RoutingRecord[] GetRoutingRecords();
RoutingRecord GetRecordByName(string name);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ public class AgentSettings
/// Router Agent Id
/// </summary>
public string RouterId { get; set; }

/// <summary>
/// Reasoner Agent Id
/// </summary>
public string ReasonerId { get; set; }

public string DataDir { get; set; }
public string TemplateFormat { get; set; }
public int MaxRecursiveDepth { get; set; } = 3;
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public override string ToString()
{
if (Role == AgentRole.Function)
{
return $"{Role}: {FunctionName}";
return $"{Role}: {FunctionName} => {ExecutionResult}";
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ public class ConversationSetting
public string ChatCompletion { get; set; }
public bool EnableKnowledgeBase { get; set; }
public bool ShowVerboseLog { get; set; }
public int MaxRecursiveDepth { get; set; } = 3;
public bool EnableReasoning { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using BotSharp.Abstraction.Routing.Models;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace BotSharp.Abstraction.Functions.Models;

public class FunctionCallFromLlm
{
[JsonPropertyName("function")]
public string Function { get; set; }

[JsonPropertyName("parameters")]
public RetrievalArgs Parameters { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Text.Json;
using System.Text.Json.Serialization;

namespace BotSharp.Abstraction.Routing.Models;

public class RetrievalArgs : RoutingArgs
{
[JsonPropertyName("question")]
public string Question { get; set; }

[JsonPropertyName("answer")]
public string Answer { get; set; }

[JsonPropertyName("reason")]
public string Reason { get; set; }

[JsonPropertyName("args")]
public JsonDocument Arguments { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;

namespace BotSharp.Abstraction.Agents.Models;
namespace BotSharp.Abstraction.Routing.Models;

public class RoutingArgs
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;

namespace BotSharp.Abstraction.Agents.Models;
namespace BotSharp.Abstraction.Routing.Models;

public class RoutingRecord
{
Expand All @@ -19,6 +19,9 @@ public class RoutingRecord
[JsonPropertyName("redirect_to")]
public string RedirectTo { get; set; }

[JsonPropertyName("disabled")]
public bool Disabled { get; set; }

public override string ToString()
{
return Name;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace BotSharp.Abstraction.Routing.Settings;

public class GPT4Settings
{
public string ApiKey { get; set; }
public string Endpoint { get; set; }
public string DeploymentModel { get; set; }
}
53 changes: 0 additions & 53 deletions src/Infrastructure/BotSharp.Core/Agents/Services/AgentRouter.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Functions;
using BotSharp.Core.Functions;
using BotSharp.Core.Hooks;
using BotSharp.Core.Routing;
using BotSharp.Core.Templating;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
Expand Down Expand Up @@ -41,13 +43,21 @@ public static IServiceCollection AddBotSharp(this IServiceCollection services, I
services.AddSingleton<TemplateRender>();

// Register router
services.AddScoped<IAgentRouting, AgentRouter>();
services.AddScoped<Router>();
services.AddScoped<Reasoner>();
services.AddScoped<IAgentRouting>(p =>
{
var setting = p.GetRequiredService<ConversationSetting>();
return setting.EnableReasoning ? p.GetRequiredService<Reasoner>() : p.GetRequiredService<Router>();
});

// Register function callback
services.AddScoped<IFunctionCallback, RouteToAgentFn>();

// Register Hooks
services.AddScoped<IAgentHook, AgentHook>();
services.AddScoped<IAgentHook, RoutingHook>();

services.AddScoped<Simulator>();

return services;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ private async Task<bool> GetChatCompletionsAsyncRecursively(IChatCompletion chat
string conversationId,
Agent agent,
List<RoleDialogModel> wholeDialogs,
int maxRecursiveDepth,
Func<RoleDialogModel, Task> onMessageReceived,
Func<RoleDialogModel, Task> onFunctionExecuting,
Func<RoleDialogModel, Task> onFunctionExecuted)
{
currentRecursiveDepth++;
if (currentRecursiveDepth > maxRecursiveDepth)
if (currentRecursiveDepth > _settings.MaxRecursiveDepth)
{
_logger.LogWarning($"Exceeded max recursive depth.");

Expand Down Expand Up @@ -65,7 +64,6 @@ await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, fn.Content
fn.Content = fn.FunctionArgs.Replace("\r", " ").Replace("\n", " ").Trim() + " => " + fn.ExecutionResult;

// Agent has been transferred
var agentSettings = _services.GetRequiredService<AgentSettings>();
if (fn.CurrentAgentId != preAgentId)
{
var agentService = _services.GetRequiredService<IAgentService>();
Expand All @@ -83,7 +81,6 @@ await GetChatCompletionsAsyncRecursively(chatCompletion,
conversationId,
agent,
wholeDialogs,
maxRecursiveDepth,
onMessageReceived,
onFunctionExecuting,
onFunctionExecuted);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.MLTasks;
using BotSharp.Core.Routing;

namespace BotSharp.Core.Conversations.Services;

Expand Down Expand Up @@ -31,7 +34,7 @@ public async Task<bool> SendMessage(string agentId, string conversationId,
stateService.SetState("channel", lastDialog.Channel);

var router = _services.GetRequiredService<IAgentRouting>();
var agent = await router.LoadRouter();
Agent agent = await router.LoadRouter();

_logger.LogInformation($"[{agent.Name}] {lastDialog.Role}: {lastDialog.Content}");

Expand Down Expand Up @@ -65,14 +68,51 @@ public async Task<bool> SendMessage(string agentId, string conversationId,
await hook.BeforeCompletion();
}

var agentSettings = _services.GetRequiredService<AgentSettings>();
// reasoning
if (_settings.EnableReasoning)
{
var simulator = _services.GetRequiredService<Simulator>();
var reasonedContext = await simulator.Enter(agent, wholeDialogs);

if (reasonedContext.FunctionName == "interrupt_task_execution")
{
await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, reasonedContext.Content)
{
CurrentAgentId = agent.Id,
Channel = lastDialog.Channel
}, onMessageReceived);
return true;
}
else if (reasonedContext.FunctionName == "response_to_user")
{
await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, reasonedContext.Content)
{
CurrentAgentId = agent.Id,
Channel = lastDialog.Channel
}, onMessageReceived);
return true;
}
else if (reasonedContext.FunctionName == "continue_execute_task")
{
if (reasonedContext.CurrentAgentId != agent.Id)
{
var agentService = _services.GetRequiredService<IAgentService>();
agent = await agentService.LoadAgent(reasonedContext.CurrentAgentId);
}
}

simulator.Dialogs.ForEach(x =>
{
wholeDialogs.Add(x);
_storage.Append(conversationId, agent.Id, x);
});
}

var chatCompletion = GetChatCompletion();
var result = await GetChatCompletionsAsyncRecursively(chatCompletion,
conversationId,
agent,
wholeDialogs,
agentSettings.MaxRecursiveDepth,
onMessageReceived,
onFunctionExecuting,
onFunctionExecuted);
Expand Down Expand Up @@ -101,4 +141,10 @@ public IChatCompletion GetChatCompletion()
var completions = _services.GetServices<IChatCompletion>();
return completions.FirstOrDefault(x => x.GetType().FullName.EndsWith(_settings.ChatCompletion));
}

public IChatCompletion GetGpt4ChatCompletion()
{
var completions = _services.GetServices<IChatCompletion>();
return completions.FirstOrDefault(x => x.GetType().FullName.EndsWith("GPT4CompletionProvider"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public List<RoleDialogModel> GetDialogs(string conversationId)
CurrentAgentId = currentAgentId,
FunctionName = funcName,
FunctionArgs = funcArgs,
ExecutionResult = text,
CreatedAt = createdAt
});
}
Expand Down
5 changes: 2 additions & 3 deletions src/Infrastructure/BotSharp.Core/Functions/RouteToAgentFn.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.Functions;
using BotSharp.Abstraction.Routing.Models;
using System.IO;

namespace BotSharp.Core.Functions;
Expand Down Expand Up @@ -51,8 +51,7 @@ private bool HasMissingRequiredField(RoleDialogModel message, out string agentId
{
var args = JsonSerializer.Deserialize<RoutingArgs>(message.FunctionArgs);
var router = _services.GetRequiredService<IAgentRouting>();
var records = router.GetRoutingRecords();
var routingRule = records.FirstOrDefault(x => x.Name.ToLower() == args.AgentName.ToLower());
var routingRule = router.GetRecordByName(args.AgentName);

if (routingRule == null)
{
Expand Down
14 changes: 14 additions & 0 deletions src/Infrastructure/BotSharp.Core/Hooks/ReasoningHook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace BotSharp.Core.Hooks;

public class ReasoningHook : AgentHookBase
{
public ReasoningHook(IServiceProvider services, AgentSettings settings)
: base(services, settings)
{
}

public override bool OnInstructionLoaded(string template, Dictionary<string, object> dict)
{
return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
namespace BotSharp.Core.Hooks;

public class AgentHook : AgentHookBase
public class RoutingHook : AgentHookBase
{
public AgentHook(IServiceProvider services, AgentSettings settings)
public RoutingHook(IServiceProvider services, AgentSettings settings)
: base(services, settings)
{
}

public override bool OnInstructionLoaded(string template, Dictionary<string, object> dict)
{
var router = _services.GetRequiredService<IAgentRouting>();
dict["routing_records"] = router.GetRoutingRecords();
dict["routing_records"] = router.GetRoutingRecords()
.Where(x => !x.Disabled)
.ToList();
return true;
}
}
12 changes: 12 additions & 0 deletions src/Infrastructure/BotSharp.Core/Routing/Reasoner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace BotSharp.Core.Routing;

public class Reasoner : Router
{
public override string AgentId => _settings.ReasonerId;

public Reasoner(IServiceProvider services,
ILogger<Reasoner> logger,
AgentSettings settings) : base(services, logger, settings)
{
}
}
Loading