commit
9a394345b9
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
An agent helps you process user sentences (unstructure data) into structure data that you can use to return an appropriate response.
|
||||
|
||||
Agent is a collection that contains prompt words and function Json Schema definitions, few-shot examples and knowledge base data. You can create multiple different Agents to perform specific operations in specific domains. BotSharp has built-in maintenance for Agents, including creating, updating and deleting, importing and exporting.
|
||||
Agent is a collection that contains prompt words and function Json Schema definitions, few-shot examples and knowledge base data. You can create multiple different Agents to perform specific operations in specific domains. BotSharp has built-in maintenance for Agents, including creating, updating and deleting, importing and exporting. Agents are divided into `task agents`, `routing (non-task) agents`, `evaluating agents` and `static agents`. Business domain agents belong to task agents, and routers belong to non-task agents, static agents don't have capabilities to interact with external environment.
|
||||
|
||||
## My Agent
|
||||
After creating the platform account, you can start to enter the steps of creating the Agent.
|
||||
|
|
|
|||
|
|
@ -14,4 +14,8 @@ For simple questions raised by users, the ordinary routing function can already
|
|||
|
||||

|
||||
|
||||
For more **Routing** related information, please go to [Agent Routing](../agent/router.md).
|
||||
For more **Routing** related information, please go to [Agent Routing](../agent/router.md).
|
||||
|
||||
## Profile
|
||||
|
||||
There is an array field called `Profile` in the Agent data model, which is used to store the current profiles. When this attribute is set in the `Router`, only matching Task Agents can be included in the routing candidate Agents list, which means that the Task Agent also To set the same profile name. Profiles allows you to enter multiple profiles, and the system will automatically combine them for processing.
|
||||
|
|
@ -7,7 +7,7 @@ public enum AgentField
|
|||
Description,
|
||||
IsPublic,
|
||||
Disabled,
|
||||
AllowRouting,
|
||||
Type,
|
||||
Profiles,
|
||||
RoutingRule,
|
||||
Instruction,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
namespace BotSharp.Abstraction.Agents.Enums;
|
||||
|
||||
public class AgentType
|
||||
{
|
||||
/// <summary>
|
||||
/// Routing Agent
|
||||
/// </summary>
|
||||
public const string Routing = "routing";
|
||||
|
||||
public const string Evaluating = "evaluating";
|
||||
|
||||
/// <summary>
|
||||
/// Routable task agent with capability of interaction with external environment
|
||||
/// </summary>
|
||||
public const string Task = "task";
|
||||
|
||||
/// <summary>
|
||||
/// Agent that cannot use external tools
|
||||
/// </summary>
|
||||
public const string Static = "static";
|
||||
}
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ public interface IAgentService
|
|||
{
|
||||
Task<Agent> CreateAgent(Agent agent);
|
||||
Task RefreshAgents();
|
||||
Task<List<Agent>> GetAgents(AgentFilter filter);
|
||||
Task<PagedItems<Agent>> GetAgents(AgentFilter filter);
|
||||
|
||||
/// <summary>
|
||||
/// Load agent configurations and trigger hooks
|
||||
|
|
@ -29,7 +29,7 @@ public interface IAgentService
|
|||
/// <param name="id"></param>
|
||||
/// <returns>Original agent information</returns>
|
||||
Task<Agent> GetAgent(string id);
|
||||
|
||||
|
||||
Task<bool> DeleteAgent(string id);
|
||||
Task UpdateAgent(Agent agent, AgentField updateField);
|
||||
Task UpdateAgentFromFile(string id);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ public class Agent
|
|||
public string Id { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Agent Type
|
||||
/// </summary>
|
||||
public string Type { get; set; } = AgentType.Task;
|
||||
public DateTime CreatedDateTime { get; set; }
|
||||
public DateTime UpdatedDateTime { get; set; }
|
||||
|
||||
|
|
@ -16,7 +20,8 @@ public class Agent
|
|||
/// Default LLM settings
|
||||
/// </summary>
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public AgentLlmConfig? LlmConfig { get; set; }
|
||||
public AgentLlmConfig LlmConfig { get; set; }
|
||||
= new AgentLlmConfig();
|
||||
|
||||
/// <summary>
|
||||
/// Instruction
|
||||
|
|
@ -58,7 +63,7 @@ public class Agent
|
|||
public bool IsPublic { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsRouter { get; set; }
|
||||
public bool IsHost { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public PluginDef Plugin { get; set; }
|
||||
|
|
@ -66,11 +71,6 @@ public class Agent
|
|||
[JsonIgnore]
|
||||
public bool Installed => Plugin.Enabled;
|
||||
|
||||
/// <summary>
|
||||
/// Allow to be routed
|
||||
/// </summary>
|
||||
public bool AllowRouting { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default is True, user will enable this by installing appropriate plugin.
|
||||
/// </summary>
|
||||
|
|
@ -104,6 +104,7 @@ public class Agent
|
|||
Id = agent.Id,
|
||||
Name = agent.Name,
|
||||
Description = agent.Description,
|
||||
Type = agent.Type,
|
||||
Instruction = agent.Instruction,
|
||||
Functions = agent.Functions,
|
||||
Responses = agent.Responses,
|
||||
|
|
@ -111,7 +112,6 @@ public class Agent
|
|||
Knowledges = agent.Knowledges,
|
||||
IsPublic = agent.IsPublic,
|
||||
Disabled = agent.Disabled,
|
||||
AllowRouting = agent.AllowRouting,
|
||||
Profiles = agent.Profiles,
|
||||
RoutingRules = agent.RoutingRules,
|
||||
LlmConfig = agent.LlmConfig,
|
||||
|
|
@ -180,9 +180,9 @@ public class Agent
|
|||
return this;
|
||||
}
|
||||
|
||||
public Agent SetAllowRouting(bool allowRouting)
|
||||
public Agent SetAgentType(string type)
|
||||
{
|
||||
AllowRouting = allowRouting;
|
||||
Type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,4 +21,7 @@ public class AgentLlmConfig
|
|||
[JsonPropertyName("model")]
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Model { get; set; }
|
||||
|
||||
[JsonPropertyName("max_recursion_depth")]
|
||||
public int MaxRecursionDepth { get; set; } = 3;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Models;
|
||||
|
||||
public class ConversationStateLogModel
|
||||
{
|
||||
[JsonPropertyName("conversation_id")]
|
||||
public string ConvsersationId { get; set; }
|
||||
[JsonPropertyName("states")]
|
||||
public string States { get; set; }
|
||||
[JsonPropertyName("created_at")]
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
|
|
@ -53,12 +53,6 @@ public class RoleDialogModel : ITrackableMessage
|
|||
[JsonIgnore(Condition = JsonIgnoreCondition.Always)]
|
||||
public bool StopCompletion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Router routed to a wrong agent.
|
||||
/// Set this flag as True will force router to re-route current request to a new agent.
|
||||
/// </summary>
|
||||
public bool UnmatchedAgent { get; set; }
|
||||
|
||||
public FunctionCallFromLlm Instruction { get; set; }
|
||||
|
||||
private RoleDialogModel()
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace BotSharp.Abstraction.Functions.Models;
|
|||
public class FunctionParametersDef
|
||||
{
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; } = "string";
|
||||
public string Type { get; set; } = "object";
|
||||
|
||||
/// <summary>
|
||||
/// ParameterPropertyDef
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ public class StreamingLogModel
|
|||
{
|
||||
[JsonPropertyName("conversation_id")]
|
||||
public string ConversationId { get; set; }
|
||||
[JsonPropertyName("name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[JsonPropertyName("content")]
|
||||
public string Content { get; set; }
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@ namespace BotSharp.Abstraction.Repositories.Filters;
|
|||
|
||||
public class AgentFilter
|
||||
{
|
||||
public Pagination Pager { get; set; } = new Pagination();
|
||||
public string? AgentName { get; set; }
|
||||
public bool? Disabled { get; set; }
|
||||
public bool? Installed { get; set; }
|
||||
public bool? AllowRouting { get; set; }
|
||||
public string? Type { get; set; }
|
||||
public bool? IsPublic { get; set; }
|
||||
public bool? IsRouter { get; set; }
|
||||
public bool? IsEvaluator { get; set; }
|
||||
public List<string>? AgentIds { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
namespace BotSharp.Abstraction.Routing.Enums;
|
||||
|
||||
public class RuleType
|
||||
{
|
||||
/// <summary>
|
||||
/// Fallback to redirect agent
|
||||
/// </summary>
|
||||
public const string Fallback = "fallback";
|
||||
|
||||
/// <summary>
|
||||
/// Redirect to other agent if data validation failed
|
||||
/// </summary>
|
||||
public const string DataValidation = "data-validation";
|
||||
|
||||
/// <summary>
|
||||
/// The planning approach name for next step
|
||||
/// </summary>
|
||||
public const string Planner = "planner";
|
||||
}
|
||||
|
|
@ -5,10 +5,29 @@ namespace BotSharp.Abstraction.Routing;
|
|||
public interface IRoutingService
|
||||
{
|
||||
Agent Router { get; }
|
||||
RoutingItem[] GetRoutingItems();
|
||||
RoutingRule[] GetRulesByName(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Get routable agents
|
||||
/// </summary>
|
||||
/// <param name="profiles">router's profile</param>
|
||||
/// <returns></returns>
|
||||
RoutableAgent[] GetRoutableAgents(List<string> profiles);
|
||||
|
||||
/// <summary>
|
||||
/// Get rules by agent name
|
||||
/// </summary>
|
||||
/// <param name="name">agent name</param>
|
||||
/// <returns></returns>
|
||||
RoutingRule[] GetRulesByAgentName(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Get rules by agent id
|
||||
/// </summary>
|
||||
/// <param name="id">agent id </param>
|
||||
/// <returns></returns>
|
||||
RoutingRule[] GetRulesByAgentId(string id);
|
||||
List<RoutingHandlerDef> GetHandlers();
|
||||
|
||||
List<RoutingHandlerDef> GetHandlers(Agent router);
|
||||
void ResetRecursiveCounter();
|
||||
Task<bool> InvokeAgent(string agentId, List<RoleDialogModel> dialogs);
|
||||
Task<bool> InvokeFunction(string name, RoleDialogModel message);
|
||||
|
|
@ -20,5 +39,5 @@ public interface IRoutingService
|
|||
/// <param name="agent"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
Task<RoleDialogModel> ExecuteDirectly(Agent agent, RoleDialogModel message);
|
||||
Task<RoleDialogModel> InstructDirect(Agent agent, RoleDialogModel message);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using BotSharp.Abstraction.Functions.Models;
|
|||
|
||||
namespace BotSharp.Abstraction.Routing.Models;
|
||||
|
||||
public class RoutingItem
|
||||
public class RoutableAgent
|
||||
{
|
||||
[JsonPropertyName("agent_id")]
|
||||
public string AgentId { get; set; } = string.Empty;
|
||||
|
|
@ -13,6 +13,10 @@ public class RoutingItem
|
|||
[JsonPropertyName("description")]
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("profiles")]
|
||||
public List<string> Profiles { get; set; }
|
||||
= new List<string>();
|
||||
|
||||
[JsonPropertyName("required_fields")]
|
||||
public List<ParameterPropertyDef> RequiredFields { get; set; } = new List<ParameterPropertyDef>();
|
||||
|
||||
|
|
@ -1,12 +1,19 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Routing.Settings;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BotSharp.Abstraction.Routing.Models;
|
||||
|
||||
public class RoutingContext
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly RoutingSettings _setting;
|
||||
public RoutingContext(RoutingSettings setting)
|
||||
private string[] _routerAgentIds;
|
||||
|
||||
public RoutingContext(IServiceProvider services, RoutingSettings setting)
|
||||
{
|
||||
_services = services;
|
||||
_setting = setting;
|
||||
}
|
||||
|
||||
|
|
@ -22,7 +29,22 @@ public class RoutingContext
|
|||
/// Agent that can handle user original goal.
|
||||
/// </summary>
|
||||
public string OriginAgentId
|
||||
=> _stack.Where(x => !_setting.AgentIds.Contains(x)).Last();
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_routerAgentIds == null)
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
_routerAgentIds = agentService.GetAgents(new AgentFilter
|
||||
{
|
||||
Type = AgentType.Routing
|
||||
}).Result.Items
|
||||
.Select(x => x.Id).ToArray();
|
||||
}
|
||||
|
||||
return _stack.Where(x => !_routerAgentIds.Contains(x)).Last();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEmpty => !_stack.Any();
|
||||
public string GetCurrentAgentId()
|
||||
|
|
@ -46,6 +68,19 @@ public class RoutingContext
|
|||
_stack.Pop();
|
||||
}
|
||||
|
||||
public void Replace(string agentId)
|
||||
{
|
||||
if (_stack.Count == 0)
|
||||
{
|
||||
_stack.Push(agentId);
|
||||
}
|
||||
else if (_stack.Peek() != agentId)
|
||||
{
|
||||
_stack.Pop();
|
||||
_stack.Push(agentId);
|
||||
}
|
||||
}
|
||||
|
||||
public void Empty()
|
||||
{
|
||||
_stack.Clear();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using BotSharp.Abstraction.Routing.Enums;
|
||||
|
||||
namespace BotSharp.Abstraction.Routing.Models;
|
||||
|
||||
public class RoutingRule
|
||||
|
|
@ -8,12 +10,15 @@ public class RoutingRule
|
|||
[JsonIgnore]
|
||||
public string AgentName { get; set; }
|
||||
|
||||
public string Type { get; set; } = RuleType.DataValidation;
|
||||
|
||||
public string Field { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Field type: string, number, object
|
||||
/// </summary>
|
||||
public string Type { get; set; } = "string";
|
||||
public string FieldType { get; set; } = "string";
|
||||
|
||||
public bool Required { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,4 @@ namespace BotSharp.Abstraction.Routing.Settings;
|
|||
|
||||
public class RoutingSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Router Agent Id
|
||||
/// </summary>
|
||||
public string[] AgentIds { get; set; } = new string[0];
|
||||
|
||||
public string Planner { get; set; } = string.Empty;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public partial class AgentService
|
|||
.SetDescription(foundAgent.Description)
|
||||
.SetIsPublic(foundAgent.IsPublic)
|
||||
.SetDisabled(foundAgent.Disabled)
|
||||
.SetAllowRouting(foundAgent.AllowRouting)
|
||||
.SetAgentType(foundAgent.Type)
|
||||
.SetProfiles(foundAgent.Profiles)
|
||||
.SetRoutingRules(foundAgent.RoutingRules)
|
||||
.SetInstruction(foundAgent.Instruction)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ public partial class AgentService
|
|||
#if !DEBUG
|
||||
[MemoryCache(10 * 60)]
|
||||
#endif
|
||||
public async Task<List<Agent>> GetAgents(AgentFilter filter)
|
||||
public async Task<PagedItems<Agent>> GetAgents(AgentFilter filter)
|
||||
{
|
||||
var agents = _db.GetAgents(filter);
|
||||
|
||||
|
|
@ -17,13 +17,23 @@ public partial class AgentService
|
|||
var routeSetting = _services.GetRequiredService<RoutingSettings>();
|
||||
foreach (var agent in agents)
|
||||
{
|
||||
agent.IsRouter = routeSetting.AgentIds.Contains(agent.Id);
|
||||
agent.Plugin = GetPlugin(agent.Id);
|
||||
}
|
||||
|
||||
agents = agents.Where(x => x.Installed).ToList();
|
||||
// Set IsHost
|
||||
var agentSetting = _services.GetRequiredService<AgentSettings>();
|
||||
foreach (var agent in agents)
|
||||
{
|
||||
agent.IsHost = agentSetting.HostAgentId == agent.Id;
|
||||
}
|
||||
|
||||
return agents;
|
||||
agents = agents.Where(x => x.Installed).ToList();
|
||||
var pager = filter?.Pager ?? new Pagination();
|
||||
return new PagedItems<Agent>
|
||||
{
|
||||
Items = agents.Skip(pager.Offset).Take(pager.Size),
|
||||
Count = agents.Count()
|
||||
};
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
|
|
@ -47,9 +57,6 @@ public partial class AgentService
|
|||
profile.LlmConfig.IsInherit = true;
|
||||
}
|
||||
|
||||
// Set IsRouter
|
||||
var routeSetting = _services.GetRequiredService<RoutingSettings>();
|
||||
profile.IsRouter = routeSetting.AgentIds.Contains(profile.Id);
|
||||
profile.Plugin = GetPlugin(profile.Id);
|
||||
|
||||
return profile;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public partial class AgentService
|
|||
record.Description = agent.Description ?? string.Empty;
|
||||
record.IsPublic = agent.IsPublic;
|
||||
record.Disabled = agent.Disabled;
|
||||
record.AllowRouting = agent.AllowRouting;
|
||||
record.Type = agent.Type;
|
||||
record.Profiles = agent.Profiles ?? new List<string>();
|
||||
record.RoutingRules = agent.RoutingRules ?? new List<RoutingRule>();
|
||||
record.Instruction = agent.Instruction ?? string.Empty;
|
||||
|
|
@ -60,7 +60,7 @@ public partial class AgentService
|
|||
.SetDescription(foundAgent.Description)
|
||||
.SetIsPublic(foundAgent.IsPublic)
|
||||
.SetDisabled(foundAgent.Disabled)
|
||||
.SetAllowRouting(foundAgent.AllowRouting)
|
||||
.SetAgentType(foundAgent.Type)
|
||||
.SetProfiles(foundAgent.Profiles)
|
||||
.SetRoutingRules(foundAgent.RoutingRules)
|
||||
.SetInstruction(foundAgent.Instruction)
|
||||
|
|
|
|||
|
|
@ -50,8 +50,9 @@
|
|||
<None Remove="data\agents\01e2fc5c-2c89-4ec7-8470-7688608b496c\instruction.liquid" />
|
||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\agent.json" />
|
||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\instruction.liquid" />
|
||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\next_step_prompt.hf_planner.liquid" />
|
||||
<None Remove="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\next_step_prompt.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.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\welcome.liquid" />
|
||||
<None Remove="data\plugins\config.json" />
|
||||
|
|
@ -70,10 +71,13 @@
|
|||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\instruction.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\next_step_prompt.hf_planner.liquid">
|
||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.sequential.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\next_step_prompt.liquid">
|
||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.hf.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\planner_prompt.naive.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a\templates\response_with_function.liquid">
|
||||
|
|
|
|||
|
|
@ -59,9 +59,9 @@ public partial class ConversationService
|
|||
var routing = _services.GetRequiredService<IRoutingService>();
|
||||
var settings = _services.GetRequiredService<RoutingSettings>();
|
||||
|
||||
response = settings.AgentIds.Contains(agentId) ?
|
||||
response = agent.Type == AgentType.Routing ?
|
||||
await routing.InstructLoop(message) :
|
||||
await routing.ExecuteDirectly(agent, message);
|
||||
await routing.InstructDirect(agent, message);
|
||||
|
||||
routing.ResetRecursiveCounter();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ using BotSharp.Abstraction.Planning;
|
|||
using BotSharp.Abstraction.Repositories;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using BotSharp.Abstraction.Routing.Settings;
|
||||
using BotSharp.Abstraction.Templating;
|
||||
|
||||
namespace BotSharp.Core.Planning;
|
||||
|
|
@ -43,6 +42,7 @@ public class HFPlanner : IPlaner
|
|||
{
|
||||
new RoleDialogModel(AgentRole.User, next)
|
||||
{
|
||||
FunctionName = nameof(NaivePlanner),
|
||||
MessageId = messageId
|
||||
}
|
||||
};
|
||||
|
|
@ -91,7 +91,7 @@ public class HFPlanner : IPlaner
|
|||
|
||||
private string GetNextStepPrompt(Agent router)
|
||||
{
|
||||
var template = router.Templates.First(x => x.Name == "next_step_prompt.hf_planner").Content;
|
||||
var template = router.Templates.First(x => x.Name == "planner_prompt.hf").Content;
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
var prompt = render.Render(template, router.TemplateDict);
|
||||
return prompt.Trim();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ using BotSharp.Abstraction.Functions.Models;
|
|||
using BotSharp.Abstraction.Planning;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using BotSharp.Abstraction.Routing.Settings;
|
||||
using BotSharp.Abstraction.Templating;
|
||||
|
||||
namespace BotSharp.Core.Planning;
|
||||
|
|
@ -49,6 +48,7 @@ public class NaivePlanner : IPlaner
|
|||
{
|
||||
new RoleDialogModel(AgentRole.User, next)
|
||||
{
|
||||
FunctionName = nameof(NaivePlanner),
|
||||
MessageId = messageId
|
||||
}
|
||||
};
|
||||
|
|
@ -93,7 +93,7 @@ public class NaivePlanner : IPlaner
|
|||
var unmatchedAgentId = context.GetCurrentAgentId();
|
||||
|
||||
// Exclude the wrong routed agent
|
||||
var agents = router.TemplateDict["routing_agents"] as RoutingItem[];
|
||||
var agents = router.TemplateDict["routing_agents"] as RoutableAgent[];
|
||||
router.TemplateDict["routing_agents"] = agents.Where(x => x.AgentId != unmatchedAgentId).ToArray();
|
||||
|
||||
// Handover to Router;
|
||||
|
|
@ -108,7 +108,7 @@ public class NaivePlanner : IPlaner
|
|||
|
||||
private string GetNextStepPrompt(Agent router)
|
||||
{
|
||||
var template = router.Templates.First(x => x.Name == "next_step_prompt").Content;
|
||||
var template = router.Templates.First(x => x.Name == "planner_prompt.naive").Content;
|
||||
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
return render.Render(template, new Dictionary<string, object>
|
||||
|
|
@ -125,8 +125,8 @@ public class NaivePlanner : IPlaner
|
|||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agents = agentService.GetAgents(new AgentFilter
|
||||
{
|
||||
AllowRouting = true
|
||||
}).Result;
|
||||
Type = AgentType.Task
|
||||
}).Result.Items.ToList();
|
||||
var malformed = false;
|
||||
|
||||
// Sometimes it populate malformed Function in Agent name
|
||||
|
|
|
|||
113
src/Infrastructure/BotSharp.Core/Planning/SequentialPlanner.cs
Normal file
113
src/Infrastructure/BotSharp.Core/Planning/SequentialPlanner.cs
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Planning;
|
||||
using BotSharp.Abstraction.Routing;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using BotSharp.Abstraction.Templating;
|
||||
|
||||
namespace BotSharp.Core.Planning;
|
||||
|
||||
public class SequentialPlanner : IPlaner
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public SequentialPlanner(IServiceProvider services, ILogger<NaivePlanner> logger)
|
||||
{
|
||||
_services = services;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId)
|
||||
{
|
||||
var next = GetNextStepPrompt(router);
|
||||
|
||||
var inst = new FunctionCallFromLlm();
|
||||
|
||||
// text completion
|
||||
/*var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var instruction = agentService.RenderedInstruction(router);
|
||||
var content = $"{instruction}\r\n###\r\n{next}";
|
||||
content = content + "\r\nResponse: ";
|
||||
var completion = CompletionProvider.GetTextCompletion(_services);*/
|
||||
|
||||
// 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);
|
||||
var dialogs = new List<RoleDialogModel>
|
||||
{
|
||||
new RoleDialogModel(AgentRole.User, next)
|
||||
{
|
||||
FunctionName = nameof(NaivePlanner),
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
var context = _services.GetRequiredService<RoutingContext>();
|
||||
|
||||
if (message.StopCompletion)
|
||||
{
|
||||
context.Empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handover to Router;
|
||||
context.Pop();
|
||||
|
||||
var routing = _services.GetRequiredService<IRoutingService>();
|
||||
routing.ResetRecursiveCounter();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private string GetNextStepPrompt(Agent router)
|
||||
{
|
||||
var template = router.Templates.First(x => x.Name == "planner_prompt.sequential").Content;
|
||||
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
return render.Render(template, new Dictionary<string, object>
|
||||
{
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -28,8 +28,8 @@ namespace BotSharp.Core.Repository
|
|||
case AgentField.Disabled:
|
||||
UpdateAgentDisabled(agent.Id, agent.Disabled);
|
||||
break;
|
||||
case AgentField.AllowRouting:
|
||||
UpdateAgentAllowRouting(agent.Id, agent.AllowRouting);
|
||||
case AgentField.Type:
|
||||
UpdateAgentType(agent.Id, agent.Type);
|
||||
break;
|
||||
case AgentField.Profiles:
|
||||
UpdateAgentProfiles(agent.Id, agent.Profiles);
|
||||
|
|
@ -112,12 +112,12 @@ namespace BotSharp.Core.Repository
|
|||
File.WriteAllText(agentFile, json);
|
||||
}
|
||||
|
||||
private void UpdateAgentAllowRouting(string agentId, bool allowRouting)
|
||||
private void UpdateAgentType(string agentId, string type)
|
||||
{
|
||||
var (agent, agentFile) = GetAgentFromFile(agentId);
|
||||
if (agent == null) return;
|
||||
|
||||
agent.AllowRouting = allowRouting;
|
||||
agent.Type = type;
|
||||
agent.UpdatedDateTime = DateTime.UtcNow;
|
||||
var json = JsonSerializer.Serialize(agent, _options);
|
||||
File.WriteAllText(agentFile, json);
|
||||
|
|
@ -260,7 +260,7 @@ namespace BotSharp.Core.Repository
|
|||
agent.Description = inputAgent.Description;
|
||||
agent.IsPublic = inputAgent.IsPublic;
|
||||
agent.Disabled = inputAgent.Disabled;
|
||||
agent.AllowRouting = inputAgent.AllowRouting;
|
||||
agent.Type = inputAgent.Type;
|
||||
agent.Profiles = inputAgent.Profiles;
|
||||
agent.RoutingRules = inputAgent.RoutingRules;
|
||||
agent.LlmConfig = inputAgent.LlmConfig;
|
||||
|
|
@ -336,9 +336,9 @@ namespace BotSharp.Core.Repository
|
|||
query = query.Where(x => x.Disabled == filter.Disabled);
|
||||
}
|
||||
|
||||
if (filter.AllowRouting.HasValue)
|
||||
if (filter.Type != null)
|
||||
{
|
||||
query = query.Where(x => x.AllowRouting == filter.AllowRouting);
|
||||
query = query.Where(x => x.Type == filter.Type);
|
||||
}
|
||||
|
||||
if (filter.IsPublic.HasValue)
|
||||
|
|
@ -346,22 +346,6 @@ namespace BotSharp.Core.Repository
|
|||
query = query.Where(x => x.IsPublic == filter.IsPublic);
|
||||
}
|
||||
|
||||
if (filter.IsRouter.HasValue)
|
||||
{
|
||||
var route = _services.GetRequiredService<RoutingSettings>();
|
||||
query = filter.IsRouter.Value ?
|
||||
query.Where(x => route.AgentIds.Contains(x.Id)) :
|
||||
query.Where(x => !route.AgentIds.Contains(x.Id));
|
||||
}
|
||||
|
||||
if (filter.IsEvaluator.HasValue)
|
||||
{
|
||||
var evaluate = _services.GetRequiredService<EvaluatorSetting>();
|
||||
query = filter.IsEvaluator.Value ?
|
||||
query.Where(x => x.Id == evaluate.AgentId) :
|
||||
query.Where(x => x.Id != evaluate.AgentId);
|
||||
}
|
||||
|
||||
if (filter.AgentIds != null)
|
||||
{
|
||||
query = query.Where(x => filter.AgentIds.Contains(x.Id));
|
||||
|
|
|
|||
|
|
@ -204,10 +204,10 @@ namespace BotSharp.Core.Repository
|
|||
{
|
||||
var records = new List<Conversation>();
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir);
|
||||
var pager = filter?.Pager ?? new Pagination();
|
||||
var totalDirs = Directory.GetDirectories(dir);
|
||||
var dirs = totalDirs.Skip(filter.Pager.Offset).Take(filter.Pager.Size).ToList();
|
||||
|
||||
foreach (var d in dirs)
|
||||
foreach (var d in totalDirs)
|
||||
{
|
||||
var path = Path.Combine(d, CONVERSATION_FILE);
|
||||
if (!File.Exists(path)) continue;
|
||||
|
|
@ -217,20 +217,20 @@ namespace BotSharp.Core.Repository
|
|||
if (record == null) continue;
|
||||
|
||||
var matched = true;
|
||||
if (filter.Id != null) matched = matched && record.Id == filter.Id;
|
||||
if (filter.AgentId != null) matched = matched && record.AgentId == filter.AgentId;
|
||||
if (filter.Status != null) matched = matched && record.Status == filter.Status;
|
||||
if (filter.Channel != null) matched = matched && record.Channel == filter.Channel;
|
||||
if (filter.UserId != null) matched = matched && record.UserId == filter.UserId;
|
||||
if (filter?.Id != null) matched = matched && record.Id == filter.Id;
|
||||
if (filter?.AgentId != null) matched = matched && record.AgentId == filter.AgentId;
|
||||
if (filter?.Status != null) matched = matched && record.Status == filter.Status;
|
||||
if (filter?.Channel != null) matched = matched && record.Channel == filter.Channel;
|
||||
if (filter?.UserId != null) matched = matched && record.UserId == filter.UserId;
|
||||
|
||||
if (!matched) continue;
|
||||
records.Add(record);
|
||||
}
|
||||
|
||||
|
||||
return new PagedItems<Conversation>
|
||||
{
|
||||
Items = records.OrderByDescending(x => x.CreatedTime),
|
||||
Count = totalDirs.Count(),
|
||||
Items = records.OrderByDescending(x => x.CreatedTime).Skip(pager.Offset).Take(pager.Size),
|
||||
Count = records.Count(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
using BotSharp.Abstraction.Functions;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using BotSharp.Abstraction.Routing;
|
||||
|
||||
namespace BotSharp.Core.Routing.Functions;
|
||||
|
||||
public class FallbackToRouterFn : IFunctionCallback
|
||||
{
|
||||
public string Name => "fallback_to_router";
|
||||
private readonly IServiceProvider _services;
|
||||
public FallbackToRouterFn(IServiceProvider services)
|
||||
{
|
||||
_services = services;
|
||||
}
|
||||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
var args = JsonSerializer.Deserialize<RoutingArgs>(message.FunctionArgs);
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agents = await agentService.GetAgents(new AgentFilter
|
||||
{
|
||||
AgentName = args.AgentName
|
||||
});
|
||||
var targetAgent = agents.Items.FirstOrDefault();
|
||||
if (targetAgent == null)
|
||||
{
|
||||
message.Content = $"Can't find routing agent {args.AgentName}";
|
||||
return false;
|
||||
}
|
||||
|
||||
var routing = _services.GetRequiredService<RoutingContext>();
|
||||
routing.Replace(targetAgent.Id);
|
||||
|
||||
var router = _services.GetRequiredService<IRoutingService>();
|
||||
message.CurrentAgentId = targetAgent.Id;
|
||||
var response = await router.InstructLoop(message);
|
||||
|
||||
message.Content = response.Content;
|
||||
message.StopCompletion = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -91,7 +91,7 @@ public class RouteToAgentFn : IFunctionCallback
|
|||
var args = JsonSerializer.Deserialize<RoutingArgs>(message.FunctionArgs);
|
||||
var routing = _services.GetRequiredService<IRoutingService>();
|
||||
|
||||
var routingRules = routing.GetRulesByName(args.AgentName);
|
||||
var routingRules = routing.GetRulesByAgentName(args.AgentName);
|
||||
|
||||
if (routingRules == null || !routingRules.Any())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
|||
|
||||
var response = _dialogs.Last();
|
||||
inst.Response = response.Content;
|
||||
inst.UnmatchedAgent = response.UnmatchedAgent;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Routing;
|
||||
using BotSharp.Abstraction.Routing.Enums;
|
||||
using BotSharp.Abstraction.Routing.Settings;
|
||||
using System.Diagnostics.Metrics;
|
||||
|
||||
namespace BotSharp.Core.Routing.Hooks;
|
||||
|
||||
|
|
@ -17,26 +19,69 @@ public class RoutingAgentHook : AgentHookBase
|
|||
|
||||
public override bool OnInstructionLoaded(string template, Dictionary<string, object> dict)
|
||||
{
|
||||
if (!_routingSetting.AgentIds.Contains(_agent.Id))
|
||||
if (_agent.Type != AgentType.Routing)
|
||||
{
|
||||
return base.OnInstructionLoaded(template, dict);
|
||||
}
|
||||
dict["router"] = _agent;
|
||||
|
||||
var routing = _services.GetRequiredService<IRoutingService>();
|
||||
dict["routing_agents"] = routing.GetRoutingItems();
|
||||
dict["routing_handlers"] = routing.GetHandlers();
|
||||
var agents = routing.GetRoutableAgents(_agent.Profiles);
|
||||
dict["routing_agents"] = agents;
|
||||
dict["routing_handlers"] = routing.GetHandlers(_agent);
|
||||
|
||||
return base.OnInstructionLoaded(template, dict);
|
||||
}
|
||||
|
||||
public override bool OnFunctionsLoaded(List<FunctionDef> functions)
|
||||
{
|
||||
/*functions.Add(new FunctionDef
|
||||
if (_agent.Type == AgentType.Task)
|
||||
{
|
||||
Name = "fallback_to_router",
|
||||
Description = "If the user's request is beyond your capabilities, you can call this function for help."
|
||||
});*/
|
||||
// check if enabled the routing rule
|
||||
var routing = _services.GetRequiredService<IRoutingService>();
|
||||
var rule = routing.GetRulesByAgentId(_agent.Id)
|
||||
.FirstOrDefault(x => x.Type == RuleType.Fallback);
|
||||
if (rule != null)
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var redirectAgent = agentService.GetAgent(rule.RedirectTo).Result;
|
||||
|
||||
var json = JsonSerializer.Serialize(new
|
||||
{
|
||||
user_goal_agent = new
|
||||
{
|
||||
type = "string",
|
||||
description = $"{_agent.Name}"
|
||||
},
|
||||
next_action_agent = new
|
||||
{
|
||||
type = "string",
|
||||
description = $"{redirectAgent.Name}"
|
||||
},
|
||||
reason = new
|
||||
{
|
||||
type = "string",
|
||||
description = $"the reason why you need to fallback to [{redirectAgent.Name}] from [{_agent.Name}]"
|
||||
},
|
||||
});
|
||||
functions.Add(new FunctionDef
|
||||
{
|
||||
Name = "fallback_to_router",
|
||||
Description = $"If the user's request is beyond your capabilities, you can call this function to handle by other agent ({redirectAgent.Name}).",
|
||||
Parameters =
|
||||
{
|
||||
Properties = JsonSerializer.Deserialize<JsonDocument>(json),
|
||||
Required = new List<string>
|
||||
{
|
||||
"user_goal_agent",
|
||||
"next_action_agent",
|
||||
"reason"
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return base.OnFunctionsLoaded(functions);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,14 +37,6 @@ public class RoutingPlugin : IBotSharpPlugin
|
|||
|
||||
services.AddScoped<NaivePlanner>();
|
||||
services.AddScoped<HFPlanner>();
|
||||
services.AddScoped<IPlaner>(provider =>
|
||||
{
|
||||
var settingService = provider.GetRequiredService<ISettingService>();
|
||||
var routingSettings = settingService.Bind<RoutingSettings>("Router");
|
||||
if (routingSettings.Planner == nameof(HFPlanner))
|
||||
return provider.GetRequiredService<HFPlanner>();
|
||||
else
|
||||
return provider.GetRequiredService<NaivePlanner>();
|
||||
});
|
||||
services.AddScoped<SequentialPlanner>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Planning;
|
||||
using BotSharp.Abstraction.Routing.Enums;
|
||||
using BotSharp.Core.Planning;
|
||||
|
||||
namespace BotSharp.Core.Routing;
|
||||
|
||||
public partial class RoutingService
|
||||
{
|
||||
public IPlaner GetPlanner(Agent router)
|
||||
{
|
||||
var planner = router.RoutingRules.FirstOrDefault(x => x.Type == RuleType.Planner);
|
||||
|
||||
if (planner?.Field == nameof(HFPlanner))
|
||||
return _services.GetRequiredService<HFPlanner>();
|
||||
else if (planner?.Field == nameof(SequentialPlanner))
|
||||
return _services.GetRequiredService<SequentialPlanner>();
|
||||
else
|
||||
return _services.GetRequiredService<NaivePlanner>();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.MLTasks.Settings;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using BotSharp.Abstraction.Templating;
|
||||
|
||||
|
|
@ -7,20 +6,19 @@ namespace BotSharp.Core.Routing;
|
|||
|
||||
public partial class RoutingService
|
||||
{
|
||||
const int MAXIMUM_RECURSION_DEPTH = 3;
|
||||
private int _currentRecursionDepth = 0;
|
||||
public async Task<bool> InvokeAgent(string agentId, List<RoleDialogModel> dialogs)
|
||||
{
|
||||
_currentRecursionDepth++;
|
||||
if (_currentRecursionDepth > MAXIMUM_RECURSION_DEPTH)
|
||||
{
|
||||
_logger.LogWarning($"Current recursive call depth greater than {MAXIMUM_RECURSION_DEPTH}, which will cause unexpected result.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(agentId);
|
||||
|
||||
_currentRecursionDepth++;
|
||||
if (_currentRecursionDepth > agent.LlmConfig.MaxRecursionDepth)
|
||||
{
|
||||
_logger.LogWarning($"Current recursive call depth greater than {agent.LlmConfig.MaxRecursionDepth}, which will cause unexpected result.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var chatCompletion = CompletionProvider.GetChatCompletion(_services,
|
||||
agentConfig: agent.LlmConfig);
|
||||
|
||||
|
|
@ -59,21 +57,11 @@ public partial class RoutingService
|
|||
// Call functions
|
||||
await conversationService.CallFunctions(message);
|
||||
|
||||
// Router selected the wrong agent, handle this excluding the agent
|
||||
if (message.UnmatchedAgent)
|
||||
{
|
||||
// Save to memory dialogs
|
||||
var msg = RoleDialogModel.From(message,
|
||||
role: AgentRole.Function,
|
||||
content: message.Content);
|
||||
msg.UnmatchedAgent = true;
|
||||
dialogs.Add(msg);
|
||||
}
|
||||
// Pass execution result to LLM to get response
|
||||
else if (!message.StopCompletion)
|
||||
if (!message.StopCompletion)
|
||||
{
|
||||
var routing = _services.GetRequiredService<RoutingContext>();
|
||||
|
||||
|
||||
// Find response template
|
||||
var templateService = _services.GetRequiredService<IResponseTemplateService>();
|
||||
var responseTemplate = await templateService.RenderFunctionResponse(message.CurrentAgentId, message);
|
||||
|
|
@ -86,8 +74,8 @@ public partial class RoutingService
|
|||
else
|
||||
{
|
||||
// Save to memory dialogs
|
||||
dialogs.Add(RoleDialogModel.From(message,
|
||||
role: AgentRole.Function,
|
||||
dialogs.Add(RoleDialogModel.From(message,
|
||||
role: AgentRole.Function,
|
||||
content: message.Content));
|
||||
|
||||
// Send to Next LLM
|
||||
|
|
@ -97,8 +85,8 @@ public partial class RoutingService
|
|||
}
|
||||
else
|
||||
{
|
||||
dialogs.Add(RoleDialogModel.From(message,
|
||||
role: AgentRole.Assistant,
|
||||
dialogs.Add(RoleDialogModel.From(message,
|
||||
role: AgentRole.Assistant,
|
||||
content: message.Content));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public partial class RoutingService : IRoutingService
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<RoleDialogModel> ExecuteDirectly(Agent agent, RoleDialogModel message)
|
||||
public async Task<RoleDialogModel> InstructDirect(Agent agent, RoleDialogModel message)
|
||||
{
|
||||
var handlers = _services.GetServices<IRoutingHandler>();
|
||||
|
||||
|
|
@ -73,9 +73,10 @@ public partial class RoutingService : IRoutingService
|
|||
var dialogs = conv.GetDialogHistory();
|
||||
|
||||
var context = _services.GetRequiredService<RoutingContext>();
|
||||
var planner = _services.GetRequiredService<IPlaner>();
|
||||
var executor = _services.GetRequiredService<IExecutor>();
|
||||
|
||||
var planner = GetPlanner(_router);
|
||||
|
||||
context.Push(_router.Id);
|
||||
|
||||
int loopCount = 0;
|
||||
|
|
@ -85,7 +86,6 @@ public partial class RoutingService : IRoutingService
|
|||
|
||||
var conversation = await GetConversationContent(dialogs);
|
||||
_router.TemplateDict["conversation"] = conversation;
|
||||
_router.TemplateDict["planner"] = _settings.Planner;
|
||||
|
||||
// Get instruction from Planner
|
||||
var inst = await planner.GetNextInstruction(_router, message.MessageId);
|
||||
|
|
@ -109,9 +109,9 @@ public partial class RoutingService : IRoutingService
|
|||
return response;
|
||||
}
|
||||
|
||||
public List<RoutingHandlerDef> GetHandlers()
|
||||
public List<RoutingHandlerDef> GetHandlers(Agent router)
|
||||
{
|
||||
var planer = _services.GetRequiredService<IPlaner>();
|
||||
var planer = GetPlanner(router);
|
||||
|
||||
return _services.GetServices<IRoutingHandler>()
|
||||
.Where(x => x.Planers == null || x.Planers.Contains(planer.GetType().Name))
|
||||
|
|
@ -134,7 +134,7 @@ public partial class RoutingService : IRoutingService
|
|||
var filter = new AgentFilter
|
||||
{
|
||||
Disabled = false,
|
||||
AllowRouting = true
|
||||
Type = AgentType.Task
|
||||
};
|
||||
var agents = db.GetAgents(filter);
|
||||
var records = agents.SelectMany(x =>
|
||||
|
|
@ -147,52 +147,62 @@ public partial class RoutingService : IRoutingService
|
|||
return x.RoutingRules;
|
||||
}).ToArray();
|
||||
|
||||
// Filter agents by profile
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
var channel = state.GetState("channel");
|
||||
var specifiedProfile = agents.FirstOrDefault(x => x.Profiles.Contains(channel));
|
||||
if (specifiedProfile != null)
|
||||
{
|
||||
records = records.Where(x => specifiedProfile.Profiles.Contains(channel)).ToArray();
|
||||
}
|
||||
|
||||
return records;
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
[MemoryCache(10 * 60)]
|
||||
#endif
|
||||
public RoutingItem[] GetRoutingItems()
|
||||
public RoutableAgent[] GetRoutableAgents(List<string> profiles)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
|
||||
var filter = new AgentFilter
|
||||
{
|
||||
Disabled = false,
|
||||
AllowRouting = true
|
||||
Type = AgentType.Task
|
||||
};
|
||||
|
||||
var agents = db.GetAgents(filter);
|
||||
return agents.Select(x => new RoutingItem
|
||||
var routableAgents = agents.Select(x => new RoutableAgent
|
||||
{
|
||||
AgentId = x.Id,
|
||||
Description = x.Description,
|
||||
Name = x.Name,
|
||||
Profiles = x.Profiles,
|
||||
RequiredFields = x.RoutingRules
|
||||
.Where(p => p.Required)
|
||||
.Select(p => new ParameterPropertyDef(p.Field, p.Description, type: p.Type)
|
||||
.Select(p => new ParameterPropertyDef(p.Field, p.Description, type: p.FieldType)
|
||||
{
|
||||
Required = p.Required
|
||||
}).ToList(),
|
||||
OptionalFields = x.RoutingRules
|
||||
.Where(p => !p.Required)
|
||||
.Select(p => new ParameterPropertyDef(p.Field, p.Description, type: p.Type)
|
||||
.Select(p => new ParameterPropertyDef(p.Field, p.Description, type: p.FieldType)
|
||||
{
|
||||
Required = p.Required
|
||||
}).ToList()
|
||||
}).ToArray();
|
||||
|
||||
// Handle profile.
|
||||
// Router profile must match the agent profile
|
||||
if (routableAgents.Length > 0 && profiles.Count > 0)
|
||||
{
|
||||
routableAgents = routableAgents.Where(x => x.Profiles != null &&
|
||||
x.Profiles.Exists(x1 => profiles.Exists(y => x1 == y)))
|
||||
.ToArray();
|
||||
}
|
||||
else if (profiles == null || profiles.Count == 0)
|
||||
{
|
||||
routableAgents = routableAgents.Where(x => x.Profiles == null ||
|
||||
x.Profiles.Count == 0)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
return routableAgents;
|
||||
}
|
||||
|
||||
public RoutingRule[] GetRulesByName(string name)
|
||||
public RoutingRule[] GetRulesByAgentName(string name)
|
||||
{
|
||||
return GetRoutingRecords()
|
||||
.Where(x => x.AgentName.ToLower() == name.ToLower())
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ public class TemplateRender : ITemplateRender
|
|||
_options.MemberAccessStrategy.Register<ParameterPropertyDef>();
|
||||
_options.MemberAccessStrategy.Register<RoleDialogModel>();
|
||||
_options.MemberAccessStrategy.Register<Agent>();
|
||||
_options.MemberAccessStrategy.Register<RoutingItem>();
|
||||
_options.MemberAccessStrategy.Register<RoutableAgent>();
|
||||
_options.MemberAccessStrategy.Register<RoutingHandlerDef>();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
{
|
||||
"id": "01e2fc5c-2c89-4ec7-8470-7688608b496c",
|
||||
"name": "Chatbot",
|
||||
"description": "AI chatbot that can do variaty of tasks",
|
||||
"type": "task",
|
||||
"createdDateTime": "2024-01-15T10:39:32Z",
|
||||
"updatedDateTime": "2024-01-15T14:39:32Z",
|
||||
"id": "01e2fc5c-2c89-4ec7-8470-7688608b496c",
|
||||
"iconUrl": "/images/users/bot.png",
|
||||
"disabled": false,
|
||||
"isPublic": true
|
||||
"isPublic": true,
|
||||
"profiles": [ "standalone" ]
|
||||
}
|
||||
|
|
@ -1,10 +1,18 @@
|
|||
{
|
||||
"id": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a",
|
||||
"name": "AI Assistant",
|
||||
"description": "AI assistant that can complete many different tasks",
|
||||
"type": "routing",
|
||||
"createdDateTime": "2023-08-18T10:39:32.2349685Z",
|
||||
"updatedDateTime": "2023-08-18T14:39:32.2349686Z",
|
||||
"id": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a",
|
||||
"iconUrl": "https://cdn.iconscout.com/icon/premium/png-256-thumb/route-1613278-1368497.png",
|
||||
"disabled": false,
|
||||
"isPublic": true
|
||||
"isPublic": true,
|
||||
"profiles": [ "default" ],
|
||||
"routingRules": [
|
||||
{
|
||||
"type": "planner",
|
||||
"field": "HFPlanner"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ You're {{router.name}} ({{router.description}}). Follow these steps to handle us
|
|||
3. Determine which agent is suitable to handle this conversation.
|
||||
4. Re-think on whether the function you chose matches the reason.
|
||||
5. For agent required arguments, leave it as blank object if user doesn't provide it.
|
||||
6. Response must be in JSON format.
|
||||
|
||||
[FUNCTIONS]
|
||||
{% for handler in routing_handlers %}
|
||||
|
|
@ -36,4 +37,4 @@ Optional args:
|
|||
{% endfor %}
|
||||
|
||||
[CONVERSATION]
|
||||
{{ conversation }}
|
||||
{{ conversation }}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Break down the user’s most recent needs and figure out the next steps. Response must be in appropriate JSON format.
|
||||
Break down the user’s most recent needs and figure out the next steps.
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
What is the next step based on the CONVERSATION?
|
||||
Response must be in required JSON format without any other contents.
|
||||
Route to the Agent that last handled the conversation if necessary.
|
||||
If user wants to speak to customer service, use function human_intervention_needed.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
In order to execute the instructions listed by the user in the order specified by the user.
|
||||
What is the next step based on the CONVERSATION?
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
||||
[Authorize]
|
||||
|
|
@ -28,10 +30,20 @@ public class AgentController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpGet("/agents")]
|
||||
public async Task<List<AgentViewModel>> GetAgents([FromQuery] AgentFilter filter)
|
||||
public async Task<PagedItems<AgentViewModel>> GetAgents([FromQuery] AgentFilter filter)
|
||||
{
|
||||
var agents = await _agentService.GetAgents(filter);
|
||||
return agents.Select(x => AgentViewModel.FromAgent(x)).ToList();
|
||||
var pagedAgents = await _agentService.GetAgents(filter);
|
||||
var items = new List<Agent>();
|
||||
foreach (var agent in pagedAgents.Items)
|
||||
{
|
||||
var renderedAgent = await _agentService.LoadAgent(agent.Id);
|
||||
items.Add(renderedAgent);
|
||||
}
|
||||
return new PagedItems<AgentViewModel>
|
||||
{
|
||||
Items = items.Select(x => AgentViewModel.FromAgent(x)).ToList(),
|
||||
Count = pagedAgents.Count
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("/agent")]
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ public class ConversationController : ControllerBase
|
|||
return ConversationViewModel.FromSession(conv);
|
||||
}
|
||||
|
||||
[HttpPost("/conversations")]
|
||||
public async Task<PagedItems<ConversationViewModel>> GetConversations([FromBody] ConversationFilter filter)
|
||||
[HttpGet("/conversations")]
|
||||
public async Task<PagedItems<ConversationViewModel>> GetConversations([FromQuery] ConversationFilter filter)
|
||||
{
|
||||
var service = _services.GetRequiredService<IConversationService>();
|
||||
var conversations = await service.GetConversations(filter);
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ public class PluginController : ControllerBase
|
|||
_settings = settings;
|
||||
}
|
||||
|
||||
[HttpPost("/plugins")]
|
||||
public PagedItems<PluginDef> GetPlugins([FromBody] PluginFilter filter)
|
||||
[HttpGet("/plugins")]
|
||||
public PagedItems<PluginDef> GetPlugins([FromQuery] PluginFilter filter)
|
||||
{
|
||||
var loader = _services.GetRequiredService<PluginLoader>();
|
||||
return loader.GetPagedPlugins(_services, filter);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ public class AgentCreationModel
|
|||
{
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Type { get; set; } = AgentType.Task;
|
||||
|
||||
/// <summary>
|
||||
/// LLM default system instructions
|
||||
|
|
@ -57,7 +58,7 @@ public class AgentCreationModel
|
|||
Responses = Responses,
|
||||
Samples = Samples,
|
||||
IsPublic = IsPublic,
|
||||
AllowRouting = AllowRouting,
|
||||
Type = Type,
|
||||
Disabled = Disabled,
|
||||
Profiles = Profiles,
|
||||
RoutingRules = RoutingRules?
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ public class AgentUpdateModel
|
|||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
public string Type { get; set; } = AgentType.Task;
|
||||
/// <summary>
|
||||
/// Instruction
|
||||
/// </summary>
|
||||
|
|
@ -62,7 +62,7 @@ public class AgentUpdateModel
|
|||
Description = Description ?? string.Empty,
|
||||
IsPublic = IsPublic,
|
||||
Disabled = Disabled,
|
||||
AllowRouting = AllowRouting,
|
||||
Type = Type,
|
||||
Profiles = Profiles ?? new List<string>(),
|
||||
RoutingRules = RoutingRules?
|
||||
.Select(x => RoutingRuleUpdateModel.ToDomainElement(x))?
|
||||
|
|
|
|||
|
|
@ -11,23 +11,26 @@ public class AgentViewModel
|
|||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Type { get; set; } = AgentType.Task;
|
||||
public string Instruction { get; set; }
|
||||
public List<AgentTemplate> Templates { get; set; }
|
||||
public List<FunctionDef> Functions { get; set; }
|
||||
public List<AgentResponse> Responses { get; set; }
|
||||
public List<string> Samples { get; set; }
|
||||
|
||||
[JsonPropertyName("is_public")]
|
||||
public bool IsPublic { get; set; }
|
||||
|
||||
[JsonPropertyName("is_router")]
|
||||
public bool IsRouter { get; set; }
|
||||
[JsonPropertyName("is_host")]
|
||||
public bool IsHost { get; set; }
|
||||
|
||||
[JsonPropertyName("allow_routing")]
|
||||
public bool AllowRouting { get; set; }
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
[JsonPropertyName("icon_url")]
|
||||
public string IconUrl { get; set; }
|
||||
|
||||
public List<string> Profiles { get; set; }
|
||||
= new List<string>();
|
||||
|
||||
[JsonPropertyName("routing_rules")]
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
|
|
@ -52,17 +55,17 @@ public class AgentViewModel
|
|||
Id = agent.Id,
|
||||
Name = agent.Name,
|
||||
Description = agent.Description,
|
||||
Type = agent.Type,
|
||||
Instruction = agent.Instruction,
|
||||
Templates = agent.Templates,
|
||||
Functions = agent.Functions,
|
||||
Responses = agent.Responses,
|
||||
Samples = agent.Samples,
|
||||
IsPublic= agent.IsPublic,
|
||||
IsRouter = agent.IsRouter,
|
||||
IsHost = agent.IsHost,
|
||||
Disabled = agent.Disabled,
|
||||
IconUrl = agent.IconUrl,
|
||||
AllowRouting = agent.AllowRouting,
|
||||
Profiles = agent.Profiles,
|
||||
Profiles = agent.Profiles ?? new List<string>(),
|
||||
RoutingRules = agent.RoutingRules,
|
||||
LlmConfig = agent.LlmConfig,
|
||||
Plugin = agent.Plugin,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ public class UserViewModel
|
|||
public string Role { get; set; } = UserRole.Client;
|
||||
[JsonPropertyName("full_name")]
|
||||
public string FullName => $"{FirstName} {LastName}";
|
||||
[JsonPropertyName("external_id")]
|
||||
public string? ExternalId { get; set; }
|
||||
[JsonPropertyName("create_date")]
|
||||
public DateTime CreateDate { get; set; }
|
||||
[JsonPropertyName("update_date")]
|
||||
public DateTime UpdateDate { get; set; }
|
||||
|
||||
public static UserViewModel FromUser(User user)
|
||||
{
|
||||
|
|
@ -36,7 +42,10 @@ public class UserViewModel
|
|||
FirstName = user.FirstName,
|
||||
LastName = user.LastName,
|
||||
Email = user.Email,
|
||||
Role = user.Role
|
||||
Role = user.Role,
|
||||
ExternalId = user.ExternalId,
|
||||
CreateDate = user.CreatedTime,
|
||||
UpdateDate = user.UpdatedTime
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,7 +235,11 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
}
|
||||
else if (message.Role == ChatRole.User)
|
||||
{
|
||||
chatCompletionsOptions.Messages.Add(new ChatRequestUserMessage(message.Content));
|
||||
chatCompletionsOptions.Messages.Add(new ChatRequestUserMessage(message.Content)
|
||||
{
|
||||
// To display Planner name in log
|
||||
Name = message.FunctionName
|
||||
});
|
||||
}
|
||||
else if (message.Role == ChatRole.Assistant)
|
||||
{
|
||||
|
|
@ -268,6 +272,11 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
.Where(x => x.Role == AgentRole.System)
|
||||
.Select(x => x as ChatRequestSystemMessage).Select(x =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(x.Name))
|
||||
{
|
||||
// To display Agent name in log
|
||||
return $"[{x.Name}]: {x.Content}";
|
||||
}
|
||||
return $"{x.Role}: {x.Content}";
|
||||
}));
|
||||
prompt += $"{verbose}\r\n";
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@ public class ChatHubPlugin : IBotSharpPlugin
|
|||
// Register hooks
|
||||
services.AddScoped<IConversationHook, ChatHubConversationHook>();
|
||||
services.AddScoped<IContentGeneratingHook, StreamingLogHook>();
|
||||
services.AddScoped<IConversationHook, StreamingLogHook>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ public class ChatHubConversationHook : ConversationHookBase
|
|||
public override async Task OnResponseGenerated(RoleDialogModel message)
|
||||
{
|
||||
var conv = _services.GetRequiredService<IConversationService>();
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
|
||||
var json = JsonSerializer.Serialize(new ChatResponseModel()
|
||||
{
|
||||
|
|
@ -115,7 +116,20 @@ public class ChatHubConversationHook : ConversationHookBase
|
|||
}
|
||||
}, _serializerOptions);
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnMessageReceivedFromAssistant", json);
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnConversateStatesGenerated", BuildConversationStates(conv.ConversationId, state.GetStates()));
|
||||
|
||||
await base.OnResponseGenerated(message);
|
||||
}
|
||||
|
||||
private string BuildConversationStates(string conversationId, Dictionary<string, string> states)
|
||||
{
|
||||
var model = new ConversationStateLogModel
|
||||
{
|
||||
ConvsersationId = conversationId,
|
||||
States = JsonSerializer.Serialize(states, _serializerOptions),
|
||||
CreateTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
return JsonSerializer.Serialize(model, _serializerOptions);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,21 +5,27 @@ using Microsoft.AspNetCore.SignalR;
|
|||
|
||||
namespace BotSharp.Plugin.ChatHub.Hooks;
|
||||
|
||||
public class StreamingLogHook : IContentGeneratingHook
|
||||
public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook
|
||||
{
|
||||
private readonly ConversationSetting _convSettings;
|
||||
private readonly JsonSerializerOptions _serializerOptions;
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly IHubContext<SignalRHub> _chatHub;
|
||||
private readonly JsonSerializerOptions _serializerOptions;
|
||||
private readonly IConversationStateService _state;
|
||||
private readonly IUserIdentity _user;
|
||||
|
||||
public StreamingLogHook(
|
||||
ConversationSetting convSettings,
|
||||
IServiceProvider serivces,
|
||||
IHubContext<SignalRHub> chatHub)
|
||||
IHubContext<SignalRHub> chatHub,
|
||||
IConversationStateService state,
|
||||
IUserIdentity user)
|
||||
{
|
||||
_convSettings = convSettings;
|
||||
_services = serivces;
|
||||
_chatHub = chatHub;
|
||||
_state = state;
|
||||
_user = user;
|
||||
_serializerOptions = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
|
|
@ -27,17 +33,27 @@ public class StreamingLogHook : IContentGeneratingHook
|
|||
AllowTrailingCommas = true
|
||||
};
|
||||
}
|
||||
public override async Task OnMessageReceived(RoleDialogModel message)
|
||||
{
|
||||
var conversationId = _state.GetConversationId();
|
||||
var log = $"MessageId: {message.MessageId} ==>\r\n{message.Role}: {message.Content}";
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, _user.UserName, log));
|
||||
}
|
||||
|
||||
public async Task BeforeGenerating(Agent agent, List<RoleDialogModel> conversations)
|
||||
{
|
||||
if (!_convSettings.ShowVerboseLog) return;
|
||||
|
||||
var user = _services.GetRequiredService<IUserIdentity>();
|
||||
var states = _services.GetRequiredService<IConversationStateService>();
|
||||
var conversationId = states.GetConversationId();
|
||||
/*var _state = _services.GetRequiredService<IConversationStateService>();
|
||||
var conversationId = _state.GetConversationId();
|
||||
var dialog = conversations.Last();
|
||||
var log = $"{dialog.Role}: {dialog.Content} [msg_id: {dialog.MessageId}] ==>";
|
||||
await _chatHub.Clients.User(user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, log));
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, log));*/
|
||||
}
|
||||
|
||||
public override async Task OnFunctionExecuted(RoleDialogModel message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public async Task AfterGenerated(RoleDialogModel message, TokenStatsModel tokenStats)
|
||||
|
|
@ -45,24 +61,24 @@ public class StreamingLogHook : IContentGeneratingHook
|
|||
if (!_convSettings.ShowVerboseLog) return;
|
||||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var states = _services.GetRequiredService<IConversationStateService>();
|
||||
var conversationId = states.GetConversationId();
|
||||
var conversationId = _state.GetConversationId();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, agent?.Name, tokenStats.Prompt));
|
||||
|
||||
var log = message.Role == AgentRole.Function ?
|
||||
$"[{agent?.Name}]: {message.FunctionName}({message.FunctionArgs})" :
|
||||
$"[{agent?.Name}]: {message.Content}" + $" <== [msg_id: {message.MessageId}]";
|
||||
|
||||
var user = _services.GetRequiredService<IUserIdentity>();
|
||||
await _chatHub.Clients.User(user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, tokenStats.Prompt));
|
||||
await _chatHub.Clients.User(user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, log));
|
||||
$"[{agent?.Name}]: {message.Content}";
|
||||
log += $"\r\n<== MessageId: {message.MessageId}";
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, agent?.Name, log));
|
||||
}
|
||||
|
||||
private string BuildLog(string conversationId, string content)
|
||||
private string BuildLog(string conversationId, string? name, string content)
|
||||
{
|
||||
var log = new StreamingLogModel
|
||||
{
|
||||
ConversationId = conversationId,
|
||||
Name = name,
|
||||
Content = content,
|
||||
CreateTime = DateTime.UtcNow
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ public class SearchKnowledgesFn : IFunctionCallback
|
|||
if (string.IsNullOrEmpty(knowledge))
|
||||
{
|
||||
message.Content = "Can't find any relevant data in local knowledge base.";
|
||||
message.UnmatchedAgent = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ public class AgentDocument : MongoBase
|
|||
{
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string? IconUrl { get; set; }
|
||||
public string Instruction { get; set; }
|
||||
public List<AgentTemplateMongoElement> Templates { get; set; }
|
||||
|
|
@ -13,7 +14,6 @@ public class AgentDocument : MongoBase
|
|||
public List<AgentResponseMongoElement> Responses { get; set; }
|
||||
public List<string> Samples { get; set; }
|
||||
public bool IsPublic { get; set; }
|
||||
public bool AllowRouting { get; set; }
|
||||
public bool Disabled { get; set; }
|
||||
public List<string> Profiles { get; set; }
|
||||
public List<RoutingRuleMongoElement> RoutingRules { get; set; }
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ public partial class MongoRepository
|
|||
case AgentField.Disabled:
|
||||
UpdateAgentDisabled(agent.Id, agent.Disabled);
|
||||
break;
|
||||
case AgentField.AllowRouting:
|
||||
UpdateAgentAllowRouting(agent.Id, agent.AllowRouting);
|
||||
case AgentField.Type:
|
||||
UpdateAgentType(agent.Id, agent.Type);
|
||||
break;
|
||||
case AgentField.Profiles:
|
||||
UpdateAgentProfiles(agent.Id, agent.Profiles);
|
||||
|
|
@ -109,11 +109,11 @@ public partial class MongoRepository
|
|||
_dc.Agents.UpdateOne(filter, update);
|
||||
}
|
||||
|
||||
private void UpdateAgentAllowRouting(string agentId, bool allowRouting)
|
||||
private void UpdateAgentType(string agentId, string type)
|
||||
{
|
||||
var filter = Builders<AgentDocument>.Filter.Eq(x => x.Id, agentId);
|
||||
var update = Builders<AgentDocument>.Update
|
||||
.Set(x => x.AllowRouting, allowRouting)
|
||||
.Set(x => x.Type, type)
|
||||
.Set(x => x.UpdatedTime, DateTime.UtcNow);
|
||||
|
||||
_dc.Agents.UpdateOne(filter, update);
|
||||
|
|
@ -225,7 +225,7 @@ public partial class MongoRepository
|
|||
.Set(x => x.Name, agent.Name)
|
||||
.Set(x => x.Description, agent.Description)
|
||||
.Set(x => x.Disabled, agent.Disabled)
|
||||
.Set(x => x.AllowRouting, agent.AllowRouting)
|
||||
.Set(x => x.Type, agent.Type)
|
||||
.Set(x => x.Profiles, agent.Profiles)
|
||||
.Set(x => x.RoutingRules, agent.RoutingRules.Select(r => RoutingRuleMongoElement.ToMongoElement(r)).ToList())
|
||||
.Set(x => x.Instruction, agent.Instruction)
|
||||
|
|
@ -267,7 +267,7 @@ public partial class MongoRepository
|
|||
Samples = agent.Samples ?? new List<string>(),
|
||||
IsPublic = agent.IsPublic,
|
||||
Disabled = agent.Disabled,
|
||||
AllowRouting = agent.AllowRouting,
|
||||
Type = agent.Type,
|
||||
Profiles = agent.Profiles,
|
||||
RoutingRules = !agent.RoutingRules.IsNullOrEmpty() ? agent.RoutingRules
|
||||
.Select(r => RoutingRuleMongoElement.ToDomainElement(agent.Id, agent.Name, r))
|
||||
|
|
@ -292,9 +292,9 @@ public partial class MongoRepository
|
|||
filters.Add(builder.Eq(x => x.Disabled, filter.Disabled.Value));
|
||||
}
|
||||
|
||||
if (filter.AllowRouting.HasValue)
|
||||
if (filter.Type != null)
|
||||
{
|
||||
filters.Add(builder.Eq(x => x.AllowRouting, filter.AllowRouting.Value));
|
||||
filters.Add(builder.Eq(x => x.Type, filter.Type));
|
||||
}
|
||||
|
||||
if (filter.IsPublic.HasValue)
|
||||
|
|
@ -302,32 +302,6 @@ public partial class MongoRepository
|
|||
filters.Add(builder.Eq(x => x.IsPublic, filter.IsPublic.Value));
|
||||
}
|
||||
|
||||
if (filter.IsRouter.HasValue)
|
||||
{
|
||||
var route = _services.GetRequiredService<RoutingSettings>();
|
||||
if (filter.IsRouter.Value)
|
||||
{
|
||||
filters.Add(builder.In(x => x.Id, route.AgentIds));
|
||||
}
|
||||
else
|
||||
{
|
||||
filters.Add(builder.Nin(x => x.Id, route.AgentIds));
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.IsEvaluator.HasValue)
|
||||
{
|
||||
var evaluate = _services.GetRequiredService<EvaluatorSetting>();
|
||||
if (filter.IsEvaluator.Value)
|
||||
{
|
||||
filters.Add(builder.Eq(x => x.Id, evaluate.AgentId));
|
||||
}
|
||||
else
|
||||
{
|
||||
filters.Add(builder.Ne(x => x.Id, evaluate.AgentId));
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.AgentIds != null)
|
||||
{
|
||||
filters.Add(builder.In(x => x.Id, filter.AgentIds));
|
||||
|
|
@ -354,7 +328,7 @@ public partial class MongoRepository
|
|||
Samples = x.Samples ?? new List<string>(),
|
||||
IsPublic = x.IsPublic,
|
||||
Disabled = x.Disabled,
|
||||
AllowRouting = x.AllowRouting,
|
||||
Type = x.Type,
|
||||
Profiles = x.Profiles,
|
||||
RoutingRules = !x.RoutingRules.IsNullOrEmpty() ? x.RoutingRules
|
||||
.Select(r => RoutingRuleMongoElement.ToDomainElement(x.Id, x.Name, r))
|
||||
|
|
@ -418,7 +392,7 @@ public partial class MongoRepository
|
|||
.ToList() ?? new List<AgentResponseMongoElement>(),
|
||||
Samples = x.Samples ?? new List<string>(),
|
||||
IsPublic = x.IsPublic,
|
||||
AllowRouting = x.AllowRouting,
|
||||
Type = x.Type,
|
||||
Disabled = x.Disabled,
|
||||
Profiles = x.Profiles,
|
||||
RoutingRules = x.RoutingRules?
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ public partial class MongoRepository
|
|||
var builder = Builders<ConversationDocument>.Filter;
|
||||
var filters = new List<FilterDefinition<ConversationDocument>>() { builder.Empty };
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.Id)) filters.Add(builder.Eq(x => x.Id, filter.Id));
|
||||
if (!string.IsNullOrEmpty(filter.AgentId)) filters.Add(builder.Eq(x => x.AgentId, filter.AgentId));
|
||||
if (!string.IsNullOrEmpty(filter.Status)) filters.Add(builder.Eq(x => x.Status, filter.Status));
|
||||
if (!string.IsNullOrEmpty(filter.Channel)) filters.Add(builder.Eq(x => x.Channel, filter.Channel));
|
||||
|
|
@ -217,7 +218,8 @@ public partial class MongoRepository
|
|||
|
||||
var filterDef = builder.And(filters);
|
||||
var sortDefinition = Builders<ConversationDocument>.Sort.Descending(x => x.CreatedTime);
|
||||
var conversationDocs = _dc.Conversations.Find(filterDef).Sort(sortDefinition).Skip(filter.Pager.Offset).Limit(filter.Pager.Size).ToList();
|
||||
var pager = filter?.Pager ?? new Pagination();
|
||||
var conversationDocs = _dc.Conversations.Find(filterDef).Sort(sortDefinition).Skip(pager.Offset).Limit(pager.Size).ToList();
|
||||
var count = _dc.Conversations.CountDocuments(filterDef);
|
||||
|
||||
foreach (var conv in conversationDocs)
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public partial class MongoRepository
|
|||
.ToList() ?? new List<AgentResponseMongoElement>(),
|
||||
Samples = x.Samples ?? new List<string>(),
|
||||
IsPublic = x.IsPublic,
|
||||
AllowRouting = x.AllowRouting,
|
||||
Type = x.Type,
|
||||
Disabled = x.Disabled,
|
||||
Profiles = x.Profiles,
|
||||
RoutingRules = x.RoutingRules?
|
||||
|
|
@ -77,7 +77,7 @@ public partial class MongoRepository
|
|||
.Set(x => x.Responses, agent.Responses)
|
||||
.Set(x => x.Samples, agent.Samples)
|
||||
.Set(x => x.IsPublic, agent.IsPublic)
|
||||
.Set(x => x.AllowRouting, agent.AllowRouting)
|
||||
.Set(x => x.Type, agent.Type)
|
||||
.Set(x => x.Disabled, agent.Disabled)
|
||||
.Set(x => x.Profiles, agent.Profiles)
|
||||
.Set(x => x.RoutingRules, agent.RoutingRules)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public class RoutingConversationHook: ConversationHookBase
|
|||
public override async Task OnResponseGenerated(RoleDialogModel message)
|
||||
{
|
||||
var routerSettings = _services.GetRequiredService<RoutingSettings>();
|
||||
bool saveFlag = !routerSettings.AgentIds.Contains(message.CurrentAgentId);
|
||||
bool saveFlag = _agent.Type != AgentType.Routing;
|
||||
|
||||
if (saveFlag)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>$(MSBuildProjectName.Replace(" ", "_"))s</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Infrastructure\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using BotSharp.Plugin.WebDriver.Services;
|
||||
using System.Threading;
|
||||
|
||||
namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
|
||||
|
||||
|
|
@ -10,22 +11,49 @@ public partial class PlaywrightWebDriver
|
|||
var body = await _instance.Page.QuerySelectorAsync("body");
|
||||
|
||||
var str = new List<string>();
|
||||
var inputs = await body.QuerySelectorAllAsync("input");
|
||||
var inputs = await body.QuerySelectorAllAsync("select");
|
||||
foreach (var input in inputs)
|
||||
{
|
||||
var text = await input.TextContentAsync();
|
||||
var html = "<select";
|
||||
var id = await input.GetAttributeAsync("id");
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
html += $" id='{id}'";
|
||||
}
|
||||
var name = await input.GetAttributeAsync("name");
|
||||
var type = await input.GetAttributeAsync("type");
|
||||
str.Add($"<input name='{name}' type='{type}'>{text}</input>");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
html += $" name='{id}'";
|
||||
}
|
||||
html += ">";
|
||||
|
||||
inputs = await body.QuerySelectorAllAsync("textarea");
|
||||
foreach (var input in inputs)
|
||||
{
|
||||
var text = await input.TextContentAsync();
|
||||
var name = await input.GetAttributeAsync("name");
|
||||
var type = await input.GetAttributeAsync("type");
|
||||
str.Add($"<textarea name='{name}' type='{type}'>{text}</textarea>");
|
||||
var options = await input.QuerySelectorAllAsync("option");
|
||||
if (options != null)
|
||||
{
|
||||
foreach (var option in options)
|
||||
{
|
||||
html += "<option";
|
||||
var value = await option.GetAttributeAsync("value");
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
html += $" value='{value}'";
|
||||
}
|
||||
html += ">";
|
||||
var text = await option.TextContentAsync();
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
html += text;
|
||||
}
|
||||
else
|
||||
{
|
||||
html += "'<NULL>'";
|
||||
}
|
||||
html += "</option>";
|
||||
}
|
||||
}
|
||||
|
||||
html += "</select>";
|
||||
str.Add(html);
|
||||
}
|
||||
|
||||
var driverService = _services.GetRequiredService<WebDriverService>();
|
||||
|
|
@ -36,10 +64,52 @@ public partial class PlaywrightWebDriver
|
|||
throw new Exception($"Can't locate the web element {context.ElementName}.");
|
||||
}
|
||||
|
||||
var element = _instance.Page.Locator(htmlElementContextOut.TagName).Nth(htmlElementContextOut.Index);
|
||||
ILocator element = default;
|
||||
if (!string.IsNullOrEmpty(htmlElementContextOut.ElementId))
|
||||
{
|
||||
// await _instance.Page.WaitForSelectorAsync($"#{htmlElementContextOut.ElementId}", new PageWaitForSelectorOptions { Timeout = 3 });
|
||||
element = _instance.Page.Locator($"#{htmlElementContextOut.ElementId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
element = _instance.Page.Locator(htmlElementContextOut.TagName).Nth(htmlElementContextOut.Index);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await element.FillAsync(context.InputText);
|
||||
var isVisible = await element.IsVisibleAsync();
|
||||
|
||||
if (!isVisible)
|
||||
{
|
||||
// Select the element you want to make visible (replace with your own selector)
|
||||
var control = await _instance.Page.QuerySelectorAsync($"#{htmlElementContextOut.ElementId}");
|
||||
|
||||
// Show the element by modifying its CSS styles
|
||||
await _instance.Page.EvaluateAsync(@"(element) => {
|
||||
element.style.display = 'block';
|
||||
element.style.visibility = 'visible';
|
||||
}", control);
|
||||
}
|
||||
|
||||
await element.FocusAsync();
|
||||
await element.SelectOptionAsync(new SelectOptionValue
|
||||
{
|
||||
Label = context.UpdateValue
|
||||
});
|
||||
|
||||
// Click on the blank area to activate posting
|
||||
// await body.ClickAsync();
|
||||
if (!isVisible)
|
||||
{
|
||||
// Select the element you want to make visible (replace with your own selector)
|
||||
var control = await _instance.Page.QuerySelectorAsync($"#{htmlElementContextOut.ElementId}");
|
||||
|
||||
// Show the element by modifying its CSS styles
|
||||
await _instance.Page.EvaluateAsync(@"(element) => {
|
||||
element.style.display = 'none';
|
||||
element.style.visibility = 'hidden';
|
||||
}", control);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ public partial class PlaywrightWebDriver
|
|||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly PlaywrightInstance _instance;
|
||||
public PlaywrightInstance Instance => _instance;
|
||||
|
||||
public PlaywrightWebDriver(IServiceProvider services, PlaywrightInstance instance)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,9 +23,10 @@ public class ChangeListValueFn : IFunctionCallback
|
|||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.Instance.Page.WaitForLoadStateAsync(LoadState.Load);
|
||||
await _driver.ChangeListValue(agent, args, message.MessageId);
|
||||
|
||||
message.Content = "Update successfully.";
|
||||
message.Content = $"Updat the value of \"${args.ElementName}\" to \"{args.UpdateValue}\" successfully.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,10 @@ public class ClickButtonFn : IFunctionCallback
|
|||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.Instance.Page.WaitForLoadStateAsync(LoadState.Load);
|
||||
await _driver.ClickElement(agent, args, message.MessageId);
|
||||
|
||||
message.Content = "Executed successfully.";
|
||||
message.Content = $"Click button {args.ElementName} successfully.";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ public class ExtractDataFn : IFunctionCallback
|
|||
var args = JsonSerializer.Deserialize<BrowsingContextIn>(message.FunctionArgs);
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.Instance.Page.WaitForLoadStateAsync(LoadState.Load);
|
||||
message.Content = await _driver.ExtractData(agent, args, message.MessageId);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ public class InputUserPasswordFn : IFunctionCallback
|
|||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.Instance.Page.WaitForLoadStateAsync(LoadState.Load);
|
||||
await _driver.InputUserPassword(agent, args, message.MessageId);
|
||||
|
||||
message.Content = "Input password successfully";
|
||||
|
|
|
|||
|
|
@ -23,9 +23,11 @@ public class InputUserTextFn : IFunctionCallback
|
|||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
await _driver.Instance.Page.WaitForLoadStateAsync(LoadState.Load);
|
||||
await _driver.InputUserText(agent, args, message.MessageId);
|
||||
|
||||
message.Content = "Input text successfully.";
|
||||
message.Content = $"Input text \"{args.InputText}\" successfully.";
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@ public class OpenBrowserFn : IFunctionCallback
|
|||
{
|
||||
var args = JsonSerializer.Deserialize<BrowsingContextIn>(message.FunctionArgs);
|
||||
var browser = await _driver.LaunchBrowser(args.Url);
|
||||
message.Content = string.IsNullOrEmpty(args.Url) ? "Launch browser successfully." : $"Open website successfully.";
|
||||
message.Content += "\r\nWhat would you like to do next?";
|
||||
message.StopCompletion = true;
|
||||
message.Content = string.IsNullOrEmpty(args.Url) ? $"Launch browser with blank page successfully." : $"Open website {args.Url} successfully.";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ namespace BotSharp.Plugin.WebDriver.LlmContexts;
|
|||
|
||||
public class HtmlElementContextOut
|
||||
{
|
||||
[JsonPropertyName("element_id")]
|
||||
public string ElementId { get; set; }
|
||||
|
||||
[JsonPropertyName("tag_name")]
|
||||
public string TagName { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
{
|
||||
"name": "Web Driver",
|
||||
"description": "Perform a specific action on a web browser",
|
||||
"createdDateTime": "2024-01-02T00:00:00Z",
|
||||
"updatedDateTime": "2024-01-02T00:00:00Z",
|
||||
"id": "f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b",
|
||||
"allowRouting": true,
|
||||
"isPublic": true
|
||||
}
|
||||
"id": "f3ae2a0f-e6ba-4ee1-a0b9-75d7431ff32b",
|
||||
"name": "Web Driver",
|
||||
"description": "Perform a specific action on a web browser",
|
||||
"type": "task",
|
||||
"createdDateTime": "2024-01-02T00:00:00Z",
|
||||
"updatedDateTime": "2024-01-02T00:00:00Z",
|
||||
"isPublic": true,
|
||||
"llmConfig": {
|
||||
"max_recursion_depth": 10
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "website url."
|
||||
"description": "website url starts with https://"
|
||||
}
|
||||
},
|
||||
"required": ["url"]
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
"properties": {
|
||||
"element_name": {
|
||||
"type": "string",
|
||||
"description": "the html input box element name."
|
||||
"description": "the html selection element name."
|
||||
},
|
||||
"update_value": {
|
||||
"type": "string",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ You are a Web Driver that can manipulate web elements through automation tools.
|
|||
Follow below steps to response:
|
||||
1. Analyze user's latest request in the conversation.
|
||||
2. Call appropriate function to execute the instruction.
|
||||
3. If user requests execute multiple steps, execute them sequentially.
|
||||
|
||||
Additional response requirements:
|
||||
* Call function input_user_password if user wants to input password.
|
||||
* Call function input_user_password if user wants to input password.
|
||||
* Don't do extra steps if user didn't ask.
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
{{ html_content }}
|
||||
|
||||
=== According to above HTML ===
|
||||
Find the html element tag name of "{{ element_name }}".
|
||||
Output in JSON format {"tag_name": "", "index": -1} with appropriate values, the "index" starts with 0.
|
||||
Find the html element in the similar meaning of "{{ element_name }}".
|
||||
Output in JSON format {"tag_name": "", "element_id": "populated if element has id", "index": -1} with appropriate values.
|
||||
The index is the position of the element which starts with 0.
|
||||
|
|
@ -60,10 +60,6 @@
|
|||
],
|
||||
|
||||
"Router": {
|
||||
"AgentIds": [
|
||||
"01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a"
|
||||
],
|
||||
"Planner": "NaivePlanner"
|
||||
},
|
||||
|
||||
"Evaluator": {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
|
|
@ -35,13 +35,9 @@
|
|||
<None Remove="data\agents\fe8c60aa-b114-4ef3-93cb-a8efeac80f75\agent.json" />
|
||||
<None Remove="data\agents\fe8c60aa-b114-4ef3-93cb-a8efeac80f75\functions.json" />
|
||||
<None Remove="data\agents\fe8c60aa-b114-4ef3-93cb-a8efeac80f75\instruction.liquid" />
|
||||
<None Remove="data\users\10d12798-08fb-4aa6-977b-5dd94d82dbfe\agents.json" />
|
||||
<None Remove="data\users\10d12798-08fb-4aa6-977b-5dd94d82dbfe\user.json" />
|
||||
<None Remove="data\users\456e35c5-caf0-4d45-9084-b44a8ca717e4\agents.json" />
|
||||
<None Remove="data\users\456e35c5-caf0-4d45-9084-b44a8ca717e4\user.json" />
|
||||
<None Remove="data\users\d0e6680d-03d5-4ed8-bdcd-aa7d86f2a1bc\agents.json" />
|
||||
<None Remove="data\users\d0e6680d-03d5-4ed8-bdcd-aa7d86f2a1bc\user.json" />
|
||||
<None Remove="data\users\e465af5f-044f-414b-b670-92834929b96c\agents.json" />
|
||||
<None Remove="data\users\e465af5f-044f-414b-b670-92834929b96c\user.json" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
@ -91,27 +87,15 @@
|
|||
<Content Include="data\agents\fe8c60aa-b114-4ef3-93cb-a8efeac80f75\instruction.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\users\10d12798-08fb-4aa6-977b-5dd94d82dbfe\agents.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\users\10d12798-08fb-4aa6-977b-5dd94d82dbfe\user.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\users\456e35c5-caf0-4d45-9084-b44a8ca717e4\agents.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\users\456e35c5-caf0-4d45-9084-b44a8ca717e4\user.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\users\d0e6680d-03d5-4ed8-bdcd-aa7d86f2a1bc\agents.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\users\d0e6680d-03d5-4ed8-bdcd-aa7d86f2a1bc\user.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\users\e465af5f-044f-414b-b670-92834929b96c\agents.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\users\e465af5f-044f-414b-b670-92834929b96c\user.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
"id": "b284db86-e9c2-4c25-a59e-4649797dd130",
|
||||
"allowRouting": true,
|
||||
"isPublic": true,
|
||||
"profiles": [ "pizza" ],
|
||||
"routingRules": [
|
||||
{
|
||||
"field": "order_number",
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@
|
|||
"updatedDateTime": "2023-07-26T02:29:25.123274Z",
|
||||
"id": "c2b57a74-ae4e-4c81-b3ad-9ac5bff982bd",
|
||||
"allowRouting": true,
|
||||
"isPublic": true
|
||||
"isPublic": true,
|
||||
"profiles": [ "pizza" ]
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[
|
||||
]
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
[
|
||||
{
|
||||
"userId": "456e35c5-caf0-4d45-9084-b44a8ca717e4",
|
||||
"agentId": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a",
|
||||
"updatedTime": "2023-08-14T18:14:11.6833783Z",
|
||||
"createdTime": "2023-08-14T18:14:11.6829767Z",
|
||||
"editable": true,
|
||||
"id": "1273379c-4419-460a-b0a2-5695afd097f5"
|
||||
}
|
||||
]
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[
|
||||
]
|
||||
Loading…
Reference in a new issue