Merge pull request #765 from hchen2020/master
Refactor reasoner and planner
This commit is contained in:
commit
2b1fc9987f
|
|
@ -1,6 +1,7 @@
|
||||||
using BotSharp.Abstraction.Functions.Models;
|
using BotSharp.Abstraction.Functions.Models;
|
||||||
|
using BotSharp.Abstraction.Routing;
|
||||||
|
|
||||||
namespace BotSharp.Abstraction.Routing.Planning;
|
namespace BotSharp.Abstraction.Planning;
|
||||||
|
|
||||||
public interface IExecutor
|
public interface IExecutor
|
||||||
{
|
{
|
||||||
|
|
@ -1,9 +1,19 @@
|
||||||
|
using BotSharp.Abstraction.Functions.Models;
|
||||||
|
|
||||||
namespace BotSharp.Abstraction.Planning;
|
namespace BotSharp.Abstraction.Planning;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Planning process for Task Agent
|
/// Planning process for Task Agent
|
||||||
|
/// https://www.promptingguide.ai/techniques/cot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ITaskPlanner
|
public interface ITaskPlanner
|
||||||
{
|
{
|
||||||
|
Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId, List<RoleDialogModel> dialogs);
|
||||||
|
Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs);
|
||||||
|
Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs);
|
||||||
|
List<RoleDialogModel> BeforeHandleContext(FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||||
|
=> dialogs;
|
||||||
|
bool AfterHandleContext(List<RoleDialogModel> dialogs, List<RoleDialogModel> taskAgentDialogs)
|
||||||
|
=> true;
|
||||||
|
int MaxLoopCount => 5;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@ public class RuleType
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string DataValidation = "data-validation";
|
public const string DataValidation = "data-validation";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The reasoning approach name for next step
|
||||||
|
/// </summary>
|
||||||
|
public const string Reasoner = "reasoner";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The planning approach name for next step
|
/// The planning approach name for next step
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
using BotSharp.Abstraction.Functions.Models;
|
|
||||||
|
|
||||||
namespace BotSharp.Abstraction.Routing.Planning;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Task breakdown and execution plan
|
|
||||||
/// https://www.promptingguide.ai/techniques/cot
|
|
||||||
/// </summary>
|
|
||||||
public interface IRoutingPlaner
|
|
||||||
{
|
|
||||||
Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId, List<RoleDialogModel> dialogs);
|
|
||||||
Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs);
|
|
||||||
Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs);
|
|
||||||
List<RoleDialogModel> BeforeHandleContext(FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
|
||||||
=> dialogs;
|
|
||||||
bool AfterHandleContext(List<RoleDialogModel> dialogs, List<RoleDialogModel> taskAgentDialogs)
|
|
||||||
=> true;
|
|
||||||
int MaxLoopCount => 5;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
using BotSharp.Abstraction.Functions.Models;
|
||||||
|
|
||||||
|
namespace BotSharp.Abstraction.Routing.Reasoning;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reasoning approaches for large language models (LLMs) help enhance their ability to solve complex problems,
|
||||||
|
/// handle tasks requiring logic, and provide accurate and contextually appropriate responses.
|
||||||
|
/// </summary>
|
||||||
|
public interface IRoutingReasoner
|
||||||
|
{
|
||||||
|
string Name => "Unnamed Reasoner";
|
||||||
|
string Description => "Each of these approaches leverages the capabilities of LLMs to reason more effectively, " +
|
||||||
|
"ensuring better performance and more coherent outputs across various types of complex tasks.";
|
||||||
|
|
||||||
|
int MaxLoopCount => 5;
|
||||||
|
|
||||||
|
Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId, List<RoleDialogModel> dialogs);
|
||||||
|
|
||||||
|
Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||||
|
=> Task.FromResult(true);
|
||||||
|
|
||||||
|
Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||||
|
=> Task.FromResult(true);
|
||||||
|
|
||||||
|
List<RoleDialogModel> BeforeHandleContext(FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||||
|
=> dialogs;
|
||||||
|
|
||||||
|
bool AfterHandleContext(List<RoleDialogModel> dialogs, List<RoleDialogModel> taskAgentDialogs)
|
||||||
|
=> true;
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,6 @@ global using BotSharp.Abstraction.Agents.Enums;
|
||||||
global using BotSharp.Abstraction.Infrastructures.Enums;
|
global using BotSharp.Abstraction.Infrastructures.Enums;
|
||||||
global using BotSharp.Abstraction.Models;
|
global using BotSharp.Abstraction.Models;
|
||||||
global using BotSharp.Abstraction.Routing.Models;
|
global using BotSharp.Abstraction.Routing.Models;
|
||||||
global using BotSharp.Abstraction.Routing.Planning;
|
|
||||||
global using BotSharp.Abstraction.Templating;
|
global using BotSharp.Abstraction.Templating;
|
||||||
global using BotSharp.Abstraction.Translation.Attributes;
|
global using BotSharp.Abstraction.Translation.Attributes;
|
||||||
global using BotSharp.Abstraction.Messaging.Enums;
|
global using BotSharp.Abstraction.Messaging.Enums;
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,11 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\database_knowledge.liquid" />
|
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\database_knowledge.liquid" />
|
||||||
|
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\reasoner.hf.liquid" />
|
||||||
|
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\reasoner.naive.liquid" />
|
||||||
|
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\reasoner.one-step-forward.liquid" />
|
||||||
|
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\reasoner.sequential.get_remaining_task.liquid" />
|
||||||
|
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\reasoner.sequential.liquid" />
|
||||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\agent.json" />
|
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\agent.json" />
|
||||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\instructions\instruction.liquid" />
|
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\instructions\instruction.liquid" />
|
||||||
<None Remove="data\agents\01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b\agent.json" />
|
<None Remove="data\agents\01dcc3e5-0af7-49e6-ad7a-a760bd12dc4b\agent.json" />
|
||||||
|
|
@ -73,10 +78,6 @@
|
||||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\instructions\instruction.liquid" />
|
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\instructions\instruction.liquid" />
|
||||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\.welcome.liquid" />
|
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\.welcome.liquid" />
|
||||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\conversation.summary.liquid" />
|
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\conversation.summary.liquid" />
|
||||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.hf.liquid" />
|
|
||||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.naive.liquid" />
|
|
||||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.sequential.get_remaining_task.liquid" />
|
|
||||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.sequential.liquid" />
|
|
||||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\response_with_function.liquid" />
|
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\response_with_function.liquid" />
|
||||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\translation_prompt.liquid" />
|
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\translation_prompt.liquid" />
|
||||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\select_file_prompt.liquid" />
|
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\select_file_prompt.liquid" />
|
||||||
|
|
@ -120,16 +121,19 @@
|
||||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\database_knowledge.liquid">
|
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\database_knowledge.liquid">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.sequential.get_remaining_task.liquid">
|
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\reasoner.sequential.get_remaining_task.liquid">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.sequential.liquid">
|
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\reasoner.sequential.liquid">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.hf.liquid">
|
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\reasoner.hf.liquid">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.naive.liquid">
|
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\reasoner.naive.liquid">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\reasoner.one-step-forward.liquid">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\response_with_function.liquid">
|
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\response_with_function.liquid">
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
using BotSharp.Abstraction.Google.Settings;
|
using BotSharp.Abstraction.Google.Settings;
|
||||||
using BotSharp.Abstraction.Instructs;
|
using BotSharp.Abstraction.Instructs;
|
||||||
using BotSharp.Abstraction.Messaging;
|
using BotSharp.Abstraction.Messaging;
|
||||||
|
using BotSharp.Abstraction.Planning;
|
||||||
using BotSharp.Abstraction.Plugins.Models;
|
using BotSharp.Abstraction.Plugins.Models;
|
||||||
using BotSharp.Abstraction.Routing.Planning;
|
|
||||||
using BotSharp.Abstraction.Settings;
|
using BotSharp.Abstraction.Settings;
|
||||||
using BotSharp.Abstraction.Templating;
|
using BotSharp.Abstraction.Templating;
|
||||||
using BotSharp.Core.Instructs;
|
using BotSharp.Core.Instructs;
|
||||||
using BotSharp.Core.Messaging;
|
using BotSharp.Core.Messaging;
|
||||||
using BotSharp.Core.Routing.Planning;
|
using BotSharp.Core.Routing.Reasoning;
|
||||||
using BotSharp.Core.Templating;
|
using BotSharp.Core.Templating;
|
||||||
using BotSharp.Core.Translation;
|
using BotSharp.Core.Translation;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ using BotSharp.Abstraction.Repositories;
|
||||||
using BotSharp.Abstraction.Repositories.Filters;
|
using BotSharp.Abstraction.Repositories.Filters;
|
||||||
using BotSharp.Abstraction.Routing;
|
using BotSharp.Abstraction.Routing;
|
||||||
using BotSharp.Abstraction.Routing.Settings;
|
using BotSharp.Abstraction.Routing.Settings;
|
||||||
using BotSharp.Core.Routing.Planning;
|
using BotSharp.Core.Routing.Reasoning;
|
||||||
|
|
||||||
namespace BotSharp.Core.Routing.Handlers;
|
namespace BotSharp.Core.Routing.Handlers;
|
||||||
|
|
||||||
|
|
@ -27,7 +27,7 @@ public class ContinueExecuteTaskRoutingHandler : RoutingHandlerBase//, IRoutingH
|
||||||
|
|
||||||
public List<string> Planers => new List<string>
|
public List<string> Planers => new List<string>
|
||||||
{
|
{
|
||||||
nameof(HFPlanner)
|
nameof(HFReasoner)
|
||||||
};
|
};
|
||||||
|
|
||||||
public ContinueExecuteTaskRoutingHandler(IServiceProvider services, ILogger<ContinueExecuteTaskRoutingHandler> logger, RoutingSettings settings)
|
public ContinueExecuteTaskRoutingHandler(IServiceProvider services, ILogger<ContinueExecuteTaskRoutingHandler> logger, RoutingSettings settings)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
using BotSharp.Abstraction.Functions.Models;
|
using BotSharp.Abstraction.Functions.Models;
|
||||||
using BotSharp.Abstraction.Routing;
|
using BotSharp.Abstraction.Routing;
|
||||||
using BotSharp.Abstraction.Routing.Settings;
|
using BotSharp.Abstraction.Routing.Settings;
|
||||||
using BotSharp.Core.Routing.Planning;
|
using BotSharp.Core.Routing.Reasoning;
|
||||||
|
|
||||||
namespace BotSharp.Core.Routing.Handlers;
|
namespace BotSharp.Core.Routing.Handlers;
|
||||||
|
|
||||||
|
|
@ -19,7 +19,7 @@ public class InterruptTaskExecutionRoutingHandler : RoutingHandlerBase//, IRouti
|
||||||
|
|
||||||
public List<string> Planers => new List<string>
|
public List<string> Planers => new List<string>
|
||||||
{
|
{
|
||||||
nameof(HFPlanner)
|
nameof(HFReasoner)
|
||||||
};
|
};
|
||||||
|
|
||||||
public InterruptTaskExecutionRoutingHandler(IServiceProvider services, ILogger<InterruptTaskExecutionRoutingHandler> logger, RoutingSettings settings)
|
public InterruptTaskExecutionRoutingHandler(IServiceProvider services, ILogger<InterruptTaskExecutionRoutingHandler> logger, RoutingSettings settings)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
using BotSharp.Abstraction.Routing.Settings;
|
using BotSharp.Abstraction.Routing.Settings;
|
||||||
using BotSharp.Core.Routing.Planning;
|
using BotSharp.Core.Routing.Reasoning;
|
||||||
|
|
||||||
namespace BotSharp.Core.Routing.Handlers;
|
namespace BotSharp.Core.Routing.Handlers;
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@ public class RetrieveDataFromAgentRoutingHandler : RoutingHandlerBase//, IRoutin
|
||||||
|
|
||||||
public List<string> Planers => new List<string>
|
public List<string> Planers => new List<string>
|
||||||
{
|
{
|
||||||
nameof(HFPlanner)
|
nameof(HFReasoner)
|
||||||
};
|
};
|
||||||
|
|
||||||
public RetrieveDataFromAgentRoutingHandler(IServiceProvider services, ILogger<RetrieveDataFromAgentRoutingHandler> logger, RoutingSettings settings)
|
public RetrieveDataFromAgentRoutingHandler(IServiceProvider services, ILogger<RetrieveDataFromAgentRoutingHandler> logger, RoutingSettings settings)
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
public class FirstStagePlanParameter
|
|
||||||
{
|
|
||||||
[JsonPropertyName("input_args")]
|
|
||||||
public JsonDocument[] Parameters { get; set; } = new JsonDocument[0];
|
|
||||||
|
|
||||||
[JsonPropertyName("output_results")]
|
|
||||||
public string[] Results { get; set; } = new string[0];
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"INPUTS:\r\n{JsonSerializer.Serialize(Parameters)}\r\n\r\nOUTPUTS:\r\n{JsonSerializer.Serialize(Results)}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace BotSharp.Core.Routing.Planning;
|
|
||||||
|
|
||||||
public class SecondStagePlan
|
|
||||||
{
|
|
||||||
[JsonPropertyName("related_tables")]
|
|
||||||
public string[] Tables { get; set; } = new string[0];
|
|
||||||
|
|
||||||
[JsonPropertyName("description")]
|
|
||||||
public string Description { get; set; } = "";
|
|
||||||
|
|
||||||
[JsonPropertyName("tool_name")]
|
|
||||||
public string Tool { get; set; } = "";
|
|
||||||
|
|
||||||
[JsonPropertyName("input_args")]
|
|
||||||
public JsonDocument[] Parameters { get; set; } = new JsonDocument[0];
|
|
||||||
|
|
||||||
[JsonPropertyName("output_results")]
|
|
||||||
public string[] Results { get; set; } = new string[0];
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
public class SecondStagePlanParameter : FirstStagePlanParameter
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +1,33 @@
|
||||||
using BotSharp.Abstraction.Routing.Planning;
|
/*****************************************************************************
|
||||||
|
Copyright 2024 Written by Haiping Chen. All Rights Reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
using BotSharp.Abstraction.Routing.Reasoning;
|
||||||
using BotSharp.Abstraction.Templating;
|
using BotSharp.Abstraction.Templating;
|
||||||
|
|
||||||
namespace BotSharp.Core.Routing.Planning;
|
namespace BotSharp.Core.Routing.Reasoning;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Human feedback based planner
|
/// Human feedback based reasoner
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class HFPlanner : IRoutingPlaner
|
public class HFReasoner : IRoutingReasoner
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _services;
|
private readonly IServiceProvider _services;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public HFPlanner(IServiceProvider services, ILogger<HFPlanner> logger)
|
public HFReasoner(IServiceProvider services, ILogger<HFReasoner> logger)
|
||||||
{
|
{
|
||||||
_services = services;
|
_services = services;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
@ -37,7 +53,7 @@ public class HFPlanner : IRoutingPlaner
|
||||||
{
|
{
|
||||||
new RoleDialogModel(AgentRole.User, next)
|
new RoleDialogModel(AgentRole.User, next)
|
||||||
{
|
{
|
||||||
FunctionName = nameof(HFPlanner),
|
FunctionName = nameof(HFReasoner),
|
||||||
MessageId = messageId
|
MessageId = messageId
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -60,7 +76,7 @@ public class HFPlanner : IRoutingPlaner
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix LLM malformed response
|
// Fix LLM malformed response
|
||||||
PlannerHelper.FixMalformedResponse(_services, inst);
|
ReasonerHelper.FixMalformedResponse(_services, inst);
|
||||||
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
@ -87,13 +103,13 @@ public class HFPlanner : IRoutingPlaner
|
||||||
public async 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>();
|
var context = _services.GetRequiredService<IRoutingContext>();
|
||||||
context.Empty(reason: $"Agent queue is cleared by {nameof(HFPlanner)}");
|
context.Empty(reason: $"Agent queue is cleared by {nameof(HFReasoner)}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetNextStepPrompt(Agent router)
|
private string GetNextStepPrompt(Agent router)
|
||||||
{
|
{
|
||||||
var template = router.Templates.First(x => x.Name == "planner_prompt.hf").Content;
|
var template = router.Templates.First(x => x.Name == "reasoner.hf").Content;
|
||||||
var render = _services.GetRequiredService<ITemplateRender>();
|
var render = _services.GetRequiredService<ITemplateRender>();
|
||||||
// update states
|
// update states
|
||||||
var conv = _services.GetRequiredService<IConversationService>();
|
var conv = _services.GetRequiredService<IConversationService>();
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using BotSharp.Abstraction.Routing.Planning;
|
using BotSharp.Abstraction.Planning;
|
||||||
|
|
||||||
namespace BotSharp.Core.Routing.Planning;
|
namespace BotSharp.Core.Routing.Reasoning;
|
||||||
|
|
||||||
public class InstructExecutor : IExecutor
|
public class InstructExecutor : IExecutor
|
||||||
{
|
{
|
||||||
|
|
@ -1,16 +1,35 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
Copyright 2024 Written by Haiping Chen. All Rights Reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
using BotSharp.Abstraction.Infrastructures.Enums;
|
using BotSharp.Abstraction.Infrastructures.Enums;
|
||||||
using BotSharp.Abstraction.Routing.Models;
|
using BotSharp.Abstraction.Routing.Models;
|
||||||
using BotSharp.Abstraction.Routing.Planning;
|
using BotSharp.Abstraction.Routing.Reasoning;
|
||||||
using BotSharp.Abstraction.Templating;
|
using BotSharp.Abstraction.Templating;
|
||||||
|
|
||||||
namespace BotSharp.Core.Routing.Planning;
|
namespace BotSharp.Core.Routing.Reasoning;
|
||||||
|
|
||||||
public class NaivePlanner : IRoutingPlaner
|
/// <summary>
|
||||||
|
/// simple or unsophisticated methods used to decide which specialized model or module in a system to engage for a given task.
|
||||||
|
/// </summary>
|
||||||
|
public class NaiveReasoner : IRoutingReasoner
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _services;
|
private readonly IServiceProvider _services;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public NaivePlanner(IServiceProvider services, ILogger<NaivePlanner> logger)
|
public NaiveReasoner(IServiceProvider services, ILogger<NaiveReasoner> logger)
|
||||||
{
|
{
|
||||||
_services = services;
|
_services = services;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
@ -46,7 +65,7 @@ public class NaivePlanner : IRoutingPlaner
|
||||||
{
|
{
|
||||||
new RoleDialogModel(AgentRole.User, next)
|
new RoleDialogModel(AgentRole.User, next)
|
||||||
{
|
{
|
||||||
FunctionName = nameof(NaivePlanner),
|
FunctionName = nameof(NaiveReasoner),
|
||||||
MessageId = messageId
|
MessageId = messageId
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -69,7 +88,7 @@ public class NaivePlanner : IRoutingPlaner
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix LLM malformed response
|
// Fix LLM malformed response
|
||||||
PlannerHelper.FixMalformedResponse(_services, inst);
|
ReasonerHelper.FixMalformedResponse(_services, inst);
|
||||||
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
@ -99,7 +118,7 @@ public class NaivePlanner : IRoutingPlaner
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Empty(reason: $"Agent queue is cleared by {nameof(NaivePlanner)}");
|
context.Empty(reason: $"Agent queue is cleared by {nameof(NaiveReasoner)}");
|
||||||
// context.Push(inst.OriginalAgent, "Push user goal agent");
|
// context.Push(inst.OriginalAgent, "Push user goal agent");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -107,7 +126,7 @@ public class NaivePlanner : IRoutingPlaner
|
||||||
|
|
||||||
private string GetNextStepPrompt(Agent router)
|
private string GetNextStepPrompt(Agent router)
|
||||||
{
|
{
|
||||||
var template = router.Templates.First(x => x.Name == "planner_prompt.naive").Content;
|
var template = router.Templates.First(x => x.Name == "reasoner.naive").Content;
|
||||||
|
|
||||||
var states = _services.GetRequiredService<IConversationStateService>();
|
var states = _services.GetRequiredService<IConversationStateService>();
|
||||||
var render = _services.GetRequiredService<ITemplateRender>();
|
var render = _services.GetRequiredService<ITemplateRender>();
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
Copyright 2024 Written by Haiping Chen. All Rights Reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
using BotSharp.Abstraction.Infrastructures.Enums;
|
||||||
|
using BotSharp.Abstraction.Routing.Models;
|
||||||
|
using BotSharp.Abstraction.Routing.Reasoning;
|
||||||
|
using BotSharp.Abstraction.Templating;
|
||||||
|
|
||||||
|
namespace BotSharp.Core.Routing.Reasoning;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// One-step forward reasoning is a straightforward reasoning approach where the model or agent evaluates its current state
|
||||||
|
/// and takes the next best logical step toward the solution without extensive lookahead or planning.
|
||||||
|
/// This type of reasoning involves making a decision based on the current situation and immediate context
|
||||||
|
/// rather than considering multiple future steps or possibilities.
|
||||||
|
/// </summary>
|
||||||
|
public class OneStepForwardReasoner : IRoutingReasoner
|
||||||
|
{
|
||||||
|
public string Name => "one-step-forward";
|
||||||
|
|
||||||
|
private readonly IServiceProvider _services;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public OneStepForwardReasoner(IServiceProvider services, ILogger<NaiveReasoner> logger)
|
||||||
|
{
|
||||||
|
_services = services;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId, List<RoleDialogModel> dialogs)
|
||||||
|
{
|
||||||
|
var next = GetNextStepPrompt(router);
|
||||||
|
|
||||||
|
var inst = new FunctionCallFromLlm();
|
||||||
|
|
||||||
|
// chat completion
|
||||||
|
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||||
|
provider: router?.LlmConfig?.Provider,
|
||||||
|
model: router?.LlmConfig?.Model);
|
||||||
|
|
||||||
|
int retryCount = 0;
|
||||||
|
while (retryCount < 3)
|
||||||
|
{
|
||||||
|
string text = string.Empty;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// text completion
|
||||||
|
// text = await completion.GetCompletion(content, router.Id, messageId);
|
||||||
|
dialogs = new List<RoleDialogModel>
|
||||||
|
{
|
||||||
|
new RoleDialogModel(AgentRole.User, next)
|
||||||
|
{
|
||||||
|
FunctionName = Name,
|
||||||
|
MessageId = messageId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var response = await completion.GetChatCompletions(router, dialogs);
|
||||||
|
|
||||||
|
inst = response.Content.JsonContent<FunctionCallFromLlm>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError($"{ex.Message}: {text}");
|
||||||
|
inst.Function = "response_to_user";
|
||||||
|
inst.Response = ex.Message;
|
||||||
|
inst.AgentName = "Router";
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
retryCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix LLM malformed response
|
||||||
|
ReasonerHelper.FixMalformedResponse(_services, inst);
|
||||||
|
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||||
|
{
|
||||||
|
// Set user content as Planner's question
|
||||||
|
message.FunctionName = inst.Function;
|
||||||
|
message.FunctionArgs = inst.Arguments == null ? "{}" : JsonSerializer.Serialize(inst.Arguments);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||||
|
{
|
||||||
|
var context = _services.GetRequiredService<IRoutingContext>();
|
||||||
|
if (inst.UnmatchedAgent)
|
||||||
|
{
|
||||||
|
var unmatchedAgentId = context.GetCurrentAgentId();
|
||||||
|
|
||||||
|
// Exclude the wrong routed agent
|
||||||
|
var agents = router.TemplateDict["routing_agents"] as RoutableAgent[];
|
||||||
|
router.TemplateDict["routing_agents"] = agents.Where(x => x.AgentId != unmatchedAgentId).ToArray();
|
||||||
|
|
||||||
|
// Handover to Router;
|
||||||
|
context.Pop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Empty(reason: $"Agent queue is cleared by {nameof(NaiveReasoner)}");
|
||||||
|
// context.Push(inst.OriginalAgent, "Push user goal agent");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetNextStepPrompt(Agent router)
|
||||||
|
{
|
||||||
|
var template = router.Templates.First(x => x.Name == "reasoner.one-step-forward").Content;
|
||||||
|
|
||||||
|
var states = _services.GetRequiredService<IConversationStateService>();
|
||||||
|
var render = _services.GetRequiredService<ITemplateRender>();
|
||||||
|
return render.Render(template, new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ StateConst.EXPECTED_ACTION_AGENT, states.GetState(StateConst.EXPECTED_ACTION_AGENT) },
|
||||||
|
{ StateConst.EXPECTED_GOAL_AGENT, states.GetState(StateConst.EXPECTED_GOAL_AGENT) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
namespace BotSharp.Core.Routing.Planning;
|
namespace BotSharp.Core.Routing.Reasoning;
|
||||||
|
|
||||||
public static class PlannerHelper
|
public static class ReasonerHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sometimes LLM hallucinates and fails to set function names correctly.
|
/// Sometimes LLM hallucinates and fails to set function names correctly.
|
||||||
|
|
@ -1,11 +1,30 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
Copyright 2024 Written by Haiping Chen. All Rights Reserved.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
using BotSharp.Abstraction.MLTasks;
|
using BotSharp.Abstraction.MLTasks;
|
||||||
using BotSharp.Abstraction.Routing.Models;
|
using BotSharp.Abstraction.Routing.Models;
|
||||||
using BotSharp.Abstraction.Routing.Planning;
|
using BotSharp.Abstraction.Routing.Reasoning;
|
||||||
using BotSharp.Abstraction.Templating;
|
using BotSharp.Abstraction.Templating;
|
||||||
|
|
||||||
namespace BotSharp.Core.Routing.Planning;
|
namespace BotSharp.Core.Routing.Reasoning;
|
||||||
|
|
||||||
public class SequentialPlanner : IRoutingPlaner
|
/// <summary>
|
||||||
|
/// Sequential tasks focused reasoning approach
|
||||||
|
/// </summary>
|
||||||
|
public class SequentialReasoner : IRoutingReasoner
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _services;
|
private readonly IServiceProvider _services;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
@ -14,7 +33,7 @@ public class SequentialPlanner : IRoutingPlaner
|
||||||
public int MaxLoopCount => 100;
|
public int MaxLoopCount => 100;
|
||||||
private FunctionCallFromLlm _lastInst;
|
private FunctionCallFromLlm _lastInst;
|
||||||
|
|
||||||
public SequentialPlanner(IServiceProvider services, ILogger<NaivePlanner> logger)
|
public SequentialReasoner(IServiceProvider services, ILogger<NaiveReasoner> logger)
|
||||||
{
|
{
|
||||||
_services = services;
|
_services = services;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
@ -72,7 +91,7 @@ public class SequentialPlanner : IRoutingPlaner
|
||||||
{
|
{
|
||||||
new RoleDialogModel(AgentRole.User, next)
|
new RoleDialogModel(AgentRole.User, next)
|
||||||
{
|
{
|
||||||
FunctionName = nameof(SequentialPlanner),
|
FunctionName = nameof(SequentialReasoner),
|
||||||
MessageId = messageId
|
MessageId = messageId
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -139,7 +158,7 @@ public class SequentialPlanner : IRoutingPlaner
|
||||||
|
|
||||||
if (message.StopCompletion)
|
if (message.StopCompletion)
|
||||||
{
|
{
|
||||||
context.Empty(reason: $"Agent queue is cleared by {nameof(SequentialPlanner)}");
|
context.Empty(reason: $"Agent queue is cleared by {nameof(SequentialReasoner)}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,7 +173,7 @@ public class SequentialPlanner : IRoutingPlaner
|
||||||
|
|
||||||
private string GetNextStepPrompt(Agent router)
|
private string GetNextStepPrompt(Agent router)
|
||||||
{
|
{
|
||||||
var template = router.Templates.First(x => x.Name == "planner_prompt.sequential").Content;
|
var template = router.Templates.First(x => x.Name == "reasoner.sequential").Content;
|
||||||
|
|
||||||
var render = _services.GetRequiredService<ITemplateRender>();
|
var render = _services.GetRequiredService<ITemplateRender>();
|
||||||
return render.Render(template, new Dictionary<string, object>
|
return render.Render(template, new Dictionary<string, object>
|
||||||
|
|
@ -169,11 +188,11 @@ public class SequentialPlanner : IRoutingPlaner
|
||||||
var inst = new DecomposedStep();
|
var inst = new DecomposedStep();
|
||||||
|
|
||||||
var llmProviderService = _services.GetRequiredService<ILlmProviderService>();
|
var llmProviderService = _services.GetRequiredService<ILlmProviderService>();
|
||||||
var model = llmProviderService.GetProviderModel("azure-openai", "gpt-4");
|
var model = llmProviderService.GetProviderModel("openai", "gpt-4o");
|
||||||
|
|
||||||
// chat completion
|
// chat completion
|
||||||
var completion = CompletionProvider.GetChatCompletion(_services,
|
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||||
provider: "azure-openai",
|
provider: "openai",
|
||||||
model: model.Name);
|
model: model.Name);
|
||||||
|
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
|
|
@ -185,7 +204,7 @@ public class SequentialPlanner : IRoutingPlaner
|
||||||
var response = await completion.GetChatCompletions(new Agent
|
var response = await completion.GetChatCompletions(new Agent
|
||||||
{
|
{
|
||||||
Id = router.Id,
|
Id = router.Id,
|
||||||
Name = nameof(SequentialPlanner),
|
Name = nameof(SequentialReasoner),
|
||||||
Instruction = systemPrompt
|
Instruction = systemPrompt
|
||||||
}, dialogs);
|
}, dialogs);
|
||||||
|
|
||||||
|
|
@ -208,16 +227,11 @@ public class SequentialPlanner : IRoutingPlaner
|
||||||
|
|
||||||
private string GetDecomposeTaskPrompt(Agent router)
|
private string GetDecomposeTaskPrompt(Agent router)
|
||||||
{
|
{
|
||||||
var template = router.Templates.First(x => x.Name == "planner_prompt.sequential.get_remaining_task").Content;
|
var template = router.Templates.First(x => x.Name == "reasoner.sequential.get_remaining_task").Content;
|
||||||
|
|
||||||
var render = _services.GetRequiredService<ITemplateRender>();
|
var render = _services.GetRequiredService<ITemplateRender>();
|
||||||
return render.Render(template, new Dictionary<string, object>
|
return render.Render(template, new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
using BotSharp.Abstraction.Routing;
|
using BotSharp.Abstraction.Routing.Reasoning;
|
||||||
using BotSharp.Abstraction.Routing.Models;
|
|
||||||
using BotSharp.Abstraction.Routing.Planning;
|
|
||||||
using BotSharp.Abstraction.Routing.Settings;
|
using BotSharp.Abstraction.Routing.Settings;
|
||||||
using BotSharp.Abstraction.Settings;
|
using BotSharp.Abstraction.Settings;
|
||||||
using BotSharp.Core.Routing.Hooks;
|
using BotSharp.Core.Routing.Hooks;
|
||||||
using BotSharp.Core.Routing.Planning;
|
using BotSharp.Core.Routing.Reasoning;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace BotSharp.Core.Routing;
|
namespace BotSharp.Core.Routing;
|
||||||
|
|
@ -35,8 +33,10 @@ public class RoutingPlugin : IBotSharpPlugin
|
||||||
services.AddScoped<IRoutingService, RoutingService>();
|
services.AddScoped<IRoutingService, RoutingService>();
|
||||||
services.AddScoped<IAgentHook, RoutingAgentHook>();
|
services.AddScoped<IAgentHook, RoutingAgentHook>();
|
||||||
|
|
||||||
services.AddScoped<IRoutingPlaner, NaivePlanner>();
|
services.AddScoped<IRoutingReasoner, NaiveReasoner>();
|
||||||
services.AddScoped<IRoutingPlaner, HFPlanner>();
|
services.AddScoped<IRoutingReasoner, HFReasoner>();
|
||||||
services.AddScoped<IRoutingPlaner, SequentialPlanner>();
|
services.AddScoped<IRoutingReasoner, SequentialReasoner>();
|
||||||
|
|
||||||
|
services.AddScoped<IRoutingReasoner, OneStepForwardReasoner>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
using BotSharp.Abstraction.Routing.Enums;
|
|
||||||
using BotSharp.Abstraction.Routing.Planning;
|
|
||||||
using BotSharp.Core.Routing.Planning;
|
|
||||||
|
|
||||||
namespace BotSharp.Core.Routing;
|
|
||||||
|
|
||||||
public partial class RoutingService
|
|
||||||
{
|
|
||||||
public IRoutingPlaner GetPlanner(Agent router)
|
|
||||||
{
|
|
||||||
var rule = router.RoutingRules.FirstOrDefault(x => x.Type == RuleType.Planner);
|
|
||||||
|
|
||||||
var planner = _services.GetServices<IRoutingPlaner>().
|
|
||||||
FirstOrDefault(x => x.GetType().Name.EndsWith(rule.Field));
|
|
||||||
|
|
||||||
if (planner == null)
|
|
||||||
{
|
|
||||||
_logger.LogError($"Can't find specific planner named {rule.Field}");
|
|
||||||
return _services.GetRequiredService<NaivePlanner>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return planner;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
using BotSharp.Abstraction.Infrastructures.Enums;
|
||||||
|
using BotSharp.Abstraction.Planning;
|
||||||
|
using BotSharp.Abstraction.Routing.Enums;
|
||||||
|
using BotSharp.Abstraction.Routing.Reasoning;
|
||||||
|
using BotSharp.Core.Routing.Reasoning;
|
||||||
|
|
||||||
|
namespace BotSharp.Core.Routing;
|
||||||
|
|
||||||
|
public partial class RoutingService
|
||||||
|
{
|
||||||
|
public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||||
|
{
|
||||||
|
RoleDialogModel response = default;
|
||||||
|
|
||||||
|
var agentService = _services.GetRequiredService<IAgentService>();
|
||||||
|
var convService = _services.GetRequiredService<IConversationService>();
|
||||||
|
var storage = _services.GetRequiredService<IConversationStorage>();
|
||||||
|
|
||||||
|
_router = await agentService.LoadAgent(message.CurrentAgentId);
|
||||||
|
|
||||||
|
var states = _services.GetRequiredService<IConversationStateService>();
|
||||||
|
var executor = _services.GetRequiredService<IExecutor>();
|
||||||
|
|
||||||
|
var planner = GetReasoner(_router);
|
||||||
|
|
||||||
|
_context.Push(_router.Id);
|
||||||
|
|
||||||
|
// Handle multi-language for input
|
||||||
|
var agentSettings = _services.GetRequiredService<AgentSettings>();
|
||||||
|
if (agentSettings.EnableTranslator)
|
||||||
|
{
|
||||||
|
var translator = _services.GetRequiredService<ITranslationService>();
|
||||||
|
|
||||||
|
var language = states.GetState(StateConst.LANGUAGE, LanguageType.ENGLISH);
|
||||||
|
if (language != LanguageType.ENGLISH)
|
||||||
|
{
|
||||||
|
message.SecondaryContent = message.Content;
|
||||||
|
message.Content = await translator.Translate(_router, message.MessageId, message.Content,
|
||||||
|
language: LanguageType.ENGLISH,
|
||||||
|
clone: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogs.Add(message);
|
||||||
|
storage.Append(convService.ConversationId, message);
|
||||||
|
|
||||||
|
// Get first instruction
|
||||||
|
_router.TemplateDict["conversation"] = await GetConversationContent(dialogs);
|
||||||
|
var inst = await planner.GetNextInstruction(_router, message.MessageId, dialogs);
|
||||||
|
|
||||||
|
int loopCount = 1;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
await HookEmitter.Emit<IRoutingHook>(_services, async hook =>
|
||||||
|
await hook.OnRoutingInstructionReceived(inst, message)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save states
|
||||||
|
states.SaveStateByArgs(inst.Arguments);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
Console.WriteLine($"*** Next Instruction *** {inst}");
|
||||||
|
#else
|
||||||
|
_logger.LogInformation($"*** Next Instruction *** {inst}");
|
||||||
|
#endif
|
||||||
|
await planner.AgentExecuting(_router, inst, message, dialogs);
|
||||||
|
|
||||||
|
// Handover to Task Agent
|
||||||
|
if (inst.HandleDialogsByPlanner)
|
||||||
|
{
|
||||||
|
var dialogWithoutContext = planner.BeforeHandleContext(inst, message, dialogs);
|
||||||
|
response = await executor.Execute(this, inst, message, dialogWithoutContext);
|
||||||
|
planner.AfterHandleContext(dialogs, dialogWithoutContext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response = await executor.Execute(this, inst, message, dialogs);
|
||||||
|
}
|
||||||
|
|
||||||
|
await planner.AgentExecuted(_router, inst, response, dialogs);
|
||||||
|
|
||||||
|
if (loopCount >= planner.MaxLoopCount || _context.IsEmpty)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get next instruction from Planner
|
||||||
|
_router.TemplateDict["conversation"] = await GetConversationContent(dialogs);
|
||||||
|
inst = await planner.GetNextInstruction(_router, message.MessageId, dialogs);
|
||||||
|
loopCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IRoutingReasoner GetReasoner(Agent router)
|
||||||
|
{
|
||||||
|
var rule = router.RoutingRules.FirstOrDefault(x => x.Type == RuleType.Reasoner);
|
||||||
|
|
||||||
|
var reasoner = _services.GetServices<IRoutingReasoner>().
|
||||||
|
FirstOrDefault(x => x.GetType().Name.EndsWith(rule.Field));
|
||||||
|
|
||||||
|
if (reasoner == null)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Can't find specific planner named {rule.Field}");
|
||||||
|
// Default use NaiveReasoner
|
||||||
|
return _services.GetRequiredService<NaiveReasoner>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return reasoner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
using BotSharp.Abstraction.Infrastructures.Enums;
|
|
||||||
using BotSharp.Abstraction.Routing.Models;
|
using BotSharp.Abstraction.Routing.Models;
|
||||||
using BotSharp.Abstraction.Routing.Planning;
|
|
||||||
using BotSharp.Abstraction.Routing.Settings;
|
using BotSharp.Abstraction.Routing.Settings;
|
||||||
|
|
||||||
namespace BotSharp.Core.Routing;
|
namespace BotSharp.Core.Routing;
|
||||||
|
|
@ -75,97 +73,12 @@ public partial class RoutingService : IRoutingService
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message, List<RoleDialogModel> dialogs)
|
|
||||||
{
|
|
||||||
RoleDialogModel response = default;
|
|
||||||
|
|
||||||
var agentService = _services.GetRequiredService<IAgentService>();
|
|
||||||
var convService = _services.GetRequiredService<IConversationService>();
|
|
||||||
var storage = _services.GetRequiredService<IConversationStorage>();
|
|
||||||
|
|
||||||
_router = await agentService.LoadAgent(message.CurrentAgentId);
|
|
||||||
|
|
||||||
var states = _services.GetRequiredService<IConversationStateService>();
|
|
||||||
var executor = _services.GetRequiredService<IExecutor>();
|
|
||||||
|
|
||||||
var planner = GetPlanner(_router);
|
|
||||||
|
|
||||||
_context.Push(_router.Id);
|
|
||||||
|
|
||||||
// Handle multi-language for input
|
|
||||||
var agentSettings = _services.GetRequiredService<AgentSettings>();
|
|
||||||
if (agentSettings.EnableTranslator)
|
|
||||||
{
|
|
||||||
var translator = _services.GetRequiredService<ITranslationService>();
|
|
||||||
|
|
||||||
var language = states.GetState(StateConst.LANGUAGE, LanguageType.ENGLISH);
|
|
||||||
if (language != LanguageType.ENGLISH)
|
|
||||||
{
|
|
||||||
message.SecondaryContent = message.Content;
|
|
||||||
message.Content = await translator.Translate(_router, message.MessageId, message.Content,
|
|
||||||
language: LanguageType.ENGLISH,
|
|
||||||
clone: false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dialogs.Add(message);
|
|
||||||
storage.Append(convService.ConversationId, message);
|
|
||||||
|
|
||||||
// Get first instruction
|
|
||||||
_router.TemplateDict["conversation"] = await GetConversationContent(dialogs);
|
|
||||||
var inst = await planner.GetNextInstruction(_router, message.MessageId, dialogs);
|
|
||||||
|
|
||||||
int loopCount = 1;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
await HookEmitter.Emit<IRoutingHook>(_services, async hook =>
|
|
||||||
await hook.OnRoutingInstructionReceived(inst, message)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Save states
|
|
||||||
states.SaveStateByArgs(inst.Arguments);
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
Console.WriteLine($"*** Next Instruction *** {inst}");
|
|
||||||
#else
|
|
||||||
_logger.LogInformation($"*** Next Instruction *** {inst}");
|
|
||||||
#endif
|
|
||||||
await planner.AgentExecuting(_router, inst, message, dialogs);
|
|
||||||
|
|
||||||
// Handover to Task Agent
|
|
||||||
if (inst.HandleDialogsByPlanner)
|
|
||||||
{
|
|
||||||
var dialogWithoutContext = planner.BeforeHandleContext(inst, message, dialogs);
|
|
||||||
response = await executor.Execute(this, inst, message, dialogWithoutContext);
|
|
||||||
planner.AfterHandleContext(dialogs, dialogWithoutContext);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response = await executor.Execute(this, inst, message, dialogs);
|
|
||||||
}
|
|
||||||
|
|
||||||
await planner.AgentExecuted(_router, inst, response, dialogs);
|
|
||||||
|
|
||||||
if (loopCount >= planner.MaxLoopCount || _context.IsEmpty)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get next instruction from Planner
|
|
||||||
_router.TemplateDict["conversation"] = await GetConversationContent(dialogs);
|
|
||||||
inst = await planner.GetNextInstruction(_router, message.MessageId, dialogs);
|
|
||||||
loopCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<RoutingHandlerDef> GetHandlers(Agent router)
|
public List<RoutingHandlerDef> GetHandlers(Agent router)
|
||||||
{
|
{
|
||||||
var planer = GetPlanner(router);
|
var reasoner = GetReasoner(router);
|
||||||
|
|
||||||
return _services.GetServices<IRoutingHandler>()
|
return _services.GetServices<IRoutingHandler>()
|
||||||
.Where(x => x.Planers == null || x.Planers.Contains(planer.GetType().Name))
|
.Where(x => x.Planers == null || x.Planers.Contains(reasoner.GetType().Name))
|
||||||
.Where(x => !string.IsNullOrEmpty(x.Description))
|
.Where(x => !string.IsNullOrEmpty(x.Description))
|
||||||
.Select((x, i) => new RoutingHandlerDef
|
.Select((x, i) => new RoutingHandlerDef
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@
|
||||||
"profiles": [ "tool" ],
|
"profiles": [ "tool" ],
|
||||||
"routingRules": [
|
"routingRules": [
|
||||||
{
|
{
|
||||||
"type": "planner",
|
"type": "reasoner",
|
||||||
"field": "HFPlanner"
|
"field": "HFReasoner"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Analyze the user's problem. Which prerequisite task needs to be completed? Output the next step of routing instructions.
|
||||||
|
Check the job responsibilities of the routable Agent and do not transfer to an Agent that exceeds the scope of responsibility.
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
"updatedDateTime": "2024-11-23T00:00:00Z",
|
"updatedDateTime": "2024-11-23T00:00:00Z",
|
||||||
"disabled": false,
|
"disabled": false,
|
||||||
"isPublic": true,
|
"isPublic": true,
|
||||||
"profiles": [ "database" ],
|
"profiles": [ "coding" ],
|
||||||
"llmConfig": {
|
"llmConfig": {
|
||||||
"provider": "openai",
|
"provider": "openai",
|
||||||
"model": "gpt-4o",
|
"model": "gpt-4o",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using BotSharp.Abstraction.Routing.Planning;
|
using BotSharp.Abstraction.Planning;
|
||||||
using BotSharp.Plugin.Planner.TwoStaging;
|
using BotSharp.Plugin.Planner.TwoStaging;
|
||||||
|
|
||||||
namespace BotSharp.Plugin.Planner;
|
namespace BotSharp.Plugin.Planner;
|
||||||
|
|
@ -17,7 +17,7 @@ public class PlannerPlugin : IBotSharpPlugin
|
||||||
|
|
||||||
public void RegisterDI(IServiceCollection services, IConfiguration config)
|
public void RegisterDI(IServiceCollection services, IConfiguration config)
|
||||||
{
|
{
|
||||||
services.AddScoped<IRoutingPlaner, TwoStageTaskPlanner>();
|
services.AddScoped<ITaskPlanner, TwoStageTaskPlanner>();
|
||||||
services.AddScoped<IAgentHook, PlannerAgentHook>();
|
services.AddScoped<IAgentHook, PlannerAgentHook>();
|
||||||
services.AddScoped<IAgentUtilityHook, PlannerUtilityHook>();
|
services.AddScoped<IAgentUtilityHook, PlannerUtilityHook>();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
using BotSharp.Abstraction.Infrastructures.Enums;
|
using BotSharp.Abstraction.Infrastructures.Enums;
|
||||||
using BotSharp.Abstraction.Routing.Planning;
|
using BotSharp.Abstraction.Planning;
|
||||||
using BotSharp.Core.Routing.Planning;
|
using BotSharp.Core.Routing.Reasoning;
|
||||||
|
|
||||||
namespace BotSharp.Plugin.Planner.TwoStaging;
|
namespace BotSharp.Plugin.Planner.TwoStaging;
|
||||||
|
|
||||||
public partial class TwoStageTaskPlanner : IRoutingPlaner
|
public partial class TwoStageTaskPlanner : ITaskPlanner
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _services;
|
private readonly IServiceProvider _services;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
@ -40,7 +40,7 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
|
||||||
inst = response.Content.JsonContent<FunctionCallFromLlm>();
|
inst = response.Content.JsonContent<FunctionCallFromLlm>();
|
||||||
|
|
||||||
// Fix LLM malformed response
|
// Fix LLM malformed response
|
||||||
PlannerHelper.FixMalformedResponse(_services, inst);
|
ReasonerHelper.FixMalformedResponse(_services, inst);
|
||||||
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "beda4c12-e1ec-4b4b-b328-3df4a6687c4f",
|
"id": "beda4c12-e1ec-4b4b-b328-3df4a6687c4f",
|
||||||
"name": "SQL Driver",
|
"name": "SQL Driver",
|
||||||
"description": "Execute the sql query in database from the latest dialog.",
|
"description": "Transfer to this Agent is allowed only when executable SQL statements are provided in the context.",
|
||||||
"iconUrl": "https://cdn-icons-png.flaticon.com/512/3161/3161158.png",
|
"iconUrl": "https://cdn-icons-png.flaticon.com/512/3161/3161158.png",
|
||||||
"type": "task",
|
"type": "task",
|
||||||
"createdDateTime": "2023-11-15T13:49:00Z",
|
"createdDateTime": "2023-11-15T13:49:00Z",
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
"field": "sql_statement",
|
"field": "sql_statement",
|
||||||
"required": true,
|
"required": true,
|
||||||
"field_type": "string",
|
"field_type": "string",
|
||||||
"description": "SQL statement"
|
"description": "SQL statement provided in the context"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue