Support to set multiple routers.
This commit is contained in:
parent
0bacd32ed5
commit
3022cf50cb
|
|
@ -4,5 +4,6 @@
|
|||
<LangVersion>10.0</LangVersion>
|
||||
<BotSharpVersion>0.21.0</BotSharpVersion>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>false</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
|
||||
namespace BotSharp.Abstraction.Agents;
|
||||
|
|
@ -34,4 +35,6 @@ public interface IAgentService
|
|||
Task UpdateAgentFromFile(string id);
|
||||
string GetDataDir();
|
||||
string GetAgentDataDir(string agentId);
|
||||
|
||||
PluginDef GetPlugin(string agentId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
|
||||
namespace BotSharp.Abstraction.Agents.Models;
|
||||
|
|
@ -56,6 +57,12 @@ public class Agent
|
|||
|
||||
public bool IsPublic { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsRouter { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public PluginDef Plugin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allow to be routed
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -19,18 +19,14 @@ public class RoutingContext
|
|||
public string IntentName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Agent that can handl user original goal.
|
||||
/// Agent that can handle user original goal.
|
||||
/// </summary>
|
||||
public string OriginAgentId
|
||||
=> _stack.Where(x => x != _setting.AgentId).Last();
|
||||
=> _stack.Where(x => !_setting.AgentIds.Contains(x)).Last();
|
||||
|
||||
public bool IsEmpty => !_stack.Any();
|
||||
public string GetCurrentAgentId()
|
||||
{
|
||||
if (_stack.Count == 0)
|
||||
{
|
||||
_stack.Push(_setting.AgentId);
|
||||
}
|
||||
return _stack.Peek();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ public class RoutingSettings
|
|||
/// <summary>
|
||||
/// Router Agent Id
|
||||
/// </summary>
|
||||
public string AgentId { get; set; } = string.Empty;
|
||||
public string[] AgentIds { get; set; } = new string[0];
|
||||
|
||||
public string Planner { get; set; } = string.Empty;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Routing.Settings;
|
||||
|
||||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
|
|
@ -11,6 +12,15 @@ public partial class AgentService
|
|||
public async Task<List<Agent>> GetAgents(AgentFilter filter)
|
||||
{
|
||||
var agents = _db.GetAgents(filter);
|
||||
|
||||
// Set IsRouter
|
||||
var routeSetting = _services.GetRequiredService<RoutingSettings>();
|
||||
foreach (var agent in agents)
|
||||
{
|
||||
agent.IsRouter = routeSetting.AgentIds.Contains(agent.Id);
|
||||
agent.Plugin = GetPlugin(agent.Id);
|
||||
}
|
||||
|
||||
return await Task.FromResult(agents);
|
||||
}
|
||||
|
||||
|
|
@ -35,6 +45,11 @@ 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Core.Plugins;
|
||||
|
||||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
public partial class AgentService
|
||||
{
|
||||
public PluginDef GetPlugin(string agentId)
|
||||
{
|
||||
var loader = _services.GetRequiredService<PluginLoader>();
|
||||
var plugins = loader.GetPlugins(_services);
|
||||
return plugins.FirstOrDefault(x => x.AgentIds.Contains(agentId)) ??
|
||||
new PluginDef
|
||||
{
|
||||
Id = Guid.Empty.ToString(),
|
||||
AgentIds = new[]
|
||||
{
|
||||
agentId
|
||||
},
|
||||
Assembly = typeof(AgentService).Assembly.FullName.Split(',').First(),
|
||||
Name = "BotSharp.Core"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Repositories;
|
||||
using System.IO;
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public partial class ConversationService
|
|||
var routing = _services.GetRequiredService<IRoutingService>();
|
||||
var settings = _services.GetRequiredService<RoutingSettings>();
|
||||
|
||||
response = agentId == settings.AgentId ?
|
||||
response = settings.AgentIds.Contains(agentId) ?
|
||||
await routing.InstructLoop(message) :
|
||||
await routing.ExecuteDirectly(agent, message);
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,14 @@ public class TokenStatistics : ITokenStatistics
|
|||
|
||||
public void PrintStatistics()
|
||||
{
|
||||
if (_timer == null)
|
||||
{
|
||||
_timer = Stopwatch.StartNew();
|
||||
}
|
||||
else
|
||||
{
|
||||
_timer.Start();
|
||||
}
|
||||
var stats = $"Token Usage: {_promptTokenCount} prompt + {_completionTokenCount} completion = {Total} total tokens ({_timer.ElapsedMilliseconds / 1000f:f2}s). One-Way cost: {Cost:C4}, accumulated cost: {AccumulatedCost:C4}. [{_model}]";
|
||||
#if DEBUG
|
||||
Console.WriteLine(stats, Color.DarkGray);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,16 @@ public partial class InstructService : IInstructService
|
|||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
Agent agent = await agentService.LoadAgent(agentId);
|
||||
|
||||
if (agent.Disabled)
|
||||
{
|
||||
var content = $"This agent ({agent.Name}) is disabled, please install the corresponding plugin ({agent.Plugin.Name}) to activate this agent.";
|
||||
return new InstructResult
|
||||
{
|
||||
MessageId = message.MessageId,
|
||||
Text = content
|
||||
};
|
||||
}
|
||||
|
||||
// Trigger before completion hooks
|
||||
var hooks = _services.GetServices<IInstructHook>();
|
||||
foreach (var hook in hooks)
|
||||
|
|
|
|||
|
|
@ -349,8 +349,8 @@ namespace BotSharp.Core.Repository
|
|||
{
|
||||
var route = _services.GetRequiredService<RoutingSettings>();
|
||||
query = filter.IsRouter.Value ?
|
||||
query.Where(x => x.Id == route.AgentId) :
|
||||
query.Where(x => x.Id != route.AgentId);
|
||||
query.Where(x => route.AgentIds.Contains(x.Id)) :
|
||||
query.Where(x => !route.AgentIds.Contains(x.Id));
|
||||
}
|
||||
|
||||
if (filter.IsEvaluator.HasValue)
|
||||
|
|
|
|||
|
|
@ -58,6 +58,11 @@ public class RouteToAgentFn : IFunctionCallback
|
|||
return false;
|
||||
}
|
||||
|
||||
if (targetAgent.Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var missingfield = HasMissingRequiredField(message, out var agentId);
|
||||
if (missingfield && message.CurrentAgentId != agentId)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,7 +46,20 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
|||
{
|
||||
message.Content = inst.Question;
|
||||
}
|
||||
ret = await routing.InvokeAgent(agentId, _dialogs);
|
||||
|
||||
if (agent.Disabled)
|
||||
{
|
||||
var content = $"This agent ({agent.Name}) is disabled, please install the corresponding plugin ({agent.Plugin.Name}) to activate this agent.";
|
||||
|
||||
message = RoleDialogModel.From(message,
|
||||
role: AgentRole.Assistant,
|
||||
content: content);
|
||||
_dialogs.Add(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = await routing.InvokeAgent(agentId, _dialogs);
|
||||
}
|
||||
|
||||
var response = _dialogs.Last();
|
||||
inst.Response = response.Content;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace BotSharp.Core.Routing.Hooks;
|
|||
public class RoutingAgentHook : AgentHookBase
|
||||
{
|
||||
private readonly RoutingSettings _routingSetting;
|
||||
public override string SelfId => _routingSetting.AgentId;
|
||||
public override string SelfId => string.Empty;
|
||||
|
||||
public RoutingAgentHook(IServiceProvider services, AgentSettings settings, RoutingSettings routingSetting)
|
||||
: base(services, settings)
|
||||
|
|
@ -17,6 +17,10 @@ public class RoutingAgentHook : AgentHookBase
|
|||
|
||||
public override bool OnInstructionLoaded(string template, Dictionary<string, object> dict)
|
||||
{
|
||||
if (!_routingSetting.AgentIds.Contains(_agent.Id))
|
||||
{
|
||||
return base.OnInstructionLoaded(template, dict);
|
||||
}
|
||||
dict["router"] = _agent;
|
||||
|
||||
var routing = _services.GetRequiredService<IRoutingService>();
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ public partial class RoutingService : IRoutingService
|
|||
public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message)
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
_router = await agentService.LoadAgent(_settings.AgentId);
|
||||
_router = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
|
||||
RoleDialogModel response = default;
|
||||
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@ public class ConversationController : ControllerBase
|
|||
[FromRoute] string conversationId,
|
||||
[FromBody] NewMessageModel input)
|
||||
{
|
||||
var inputMsg = new RoleDialogModel(AgentRole.User, input.Text);
|
||||
|
||||
var conv = _services.GetRequiredService<IConversationService>();
|
||||
conv.SetConversationId(conversationId, input.States);
|
||||
conv.States.SetState("channel", input.Channel)
|
||||
|
|
@ -124,7 +126,7 @@ public class ConversationController : ControllerBase
|
|||
.SetState("sampling_factor", input.SamplingFactor);
|
||||
|
||||
var response = new ChatResponseModel();
|
||||
var inputMsg = new RoleDialogModel(AgentRole.User, input.Text);
|
||||
|
||||
await conv.SendMessage(agentId, inputMsg,
|
||||
async msg =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
|
@ -18,6 +19,9 @@ public class AgentViewModel
|
|||
[JsonPropertyName("is_public")]
|
||||
public bool IsPublic { get; set; }
|
||||
|
||||
[JsonPropertyName("is_router")]
|
||||
public bool IsRouter { get; set; }
|
||||
|
||||
[JsonPropertyName("allow_routing")]
|
||||
public bool AllowRouting { get; set; }
|
||||
public bool Disabled { get; set; }
|
||||
|
|
@ -33,6 +37,8 @@ public class AgentViewModel
|
|||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public AgentLlmConfig? LlmConfig { get; set; }
|
||||
|
||||
public PluginDef Plugin { get; set; }
|
||||
|
||||
[JsonPropertyName("created_datetime")]
|
||||
public DateTime CreatedDateTime { get; set; }
|
||||
|
||||
|
|
@ -52,12 +58,14 @@ public class AgentViewModel
|
|||
Responses = agent.Responses,
|
||||
Samples = agent.Samples,
|
||||
IsPublic= agent.IsPublic,
|
||||
IsRouter = agent.IsRouter,
|
||||
Disabled = agent.Disabled,
|
||||
IconUrl = agent.IconUrl,
|
||||
AllowRouting = agent.AllowRouting,
|
||||
Profiles = agent.Profiles,
|
||||
RoutingRules = agent.RoutingRules,
|
||||
LlmConfig = agent.LlmConfig,
|
||||
Plugin = agent.Plugin,
|
||||
CreatedDateTime = agent.CreatedDateTime,
|
||||
UpdatedDateTime = agent.UpdatedDateTime
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<Nullable>enable</Nullable>
|
||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -304,8 +304,8 @@ public partial class MongoRepository
|
|||
{
|
||||
var route = _services.GetRequiredService<RoutingSettings>();
|
||||
query = filter.IsRouter.Value ?
|
||||
query.Where(x => x.Id == route.AgentId) :
|
||||
query.Where(x => x.Id != route.AgentId);
|
||||
query.Where(x => route.AgentIds.Contains(x.Id)) :
|
||||
query.Where(x => !route.AgentIds.Contains(x.Id));
|
||||
}
|
||||
|
||||
if (filter.IsEvaluator.HasValue)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public class RoutingConversationHook: ConversationHookBase
|
|||
public override async Task OnResponseGenerated(RoleDialogModel message)
|
||||
{
|
||||
var routerSettings = _services.GetRequiredService<RoutingSettings>();
|
||||
bool saveFlag = message.CurrentAgentId != routerSettings.AgentId;
|
||||
bool saveFlag = !routerSettings.AgentIds.Contains(message.CurrentAgentId);
|
||||
|
||||
if (saveFlag)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using BotSharp.Abstraction.Functions;
|
||||
using BotSharp.Plugin.SqlHero.Models;
|
||||
using BotSharp.Plugin.SqlHero.Settings;
|
||||
using Dapper;
|
||||
using MySqlConnector;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Plugin.SqlHero.Actions;
|
||||
|
||||
public class ExecuteQueryAction : IFunctionCallback
|
||||
{
|
||||
public string Name => "execute_sql";
|
||||
|
||||
private readonly SqlHeroSetting _setting;
|
||||
|
||||
public ExecuteQueryAction(SqlHeroSetting setting)
|
||||
{
|
||||
_setting = setting;
|
||||
}
|
||||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
var args = JsonSerializer.Deserialize<LlmInputArgs>(message.FunctionArgs);
|
||||
message.Content = "executed successully";
|
||||
/*using var connection = new MySqlConnection(_setting.MySqlConnectionString);
|
||||
message.Content = JsonSerializer.Serialize(connection.Query(args.SqlStatement), new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
});*/
|
||||
// message.StopCompletion = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>$(MSBuildProjectName.Replace(" ", "_"))</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.1.21" />
|
||||
<PackageReference Include="MySqlConnector" Version="2.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Infrastructure\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace BotSharp.Plugin.SqlHero.Models;
|
||||
|
||||
public class LlmInputArgs
|
||||
{
|
||||
[JsonPropertyName("sql_statement")]
|
||||
public string SqlStatement { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
namespace BotSharp.Plugin.SqlHero.Settings;
|
||||
|
||||
public class SqlHeroSetting
|
||||
{
|
||||
public string MySqlConnectionString { get; set; }
|
||||
}
|
||||
26
src/Plugins/BotSharp.Plugin.SqlDriver/SqlHeroPlugin.cs
Normal file
26
src/Plugins/BotSharp.Plugin.SqlDriver/SqlHeroPlugin.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
using BotSharp.Abstraction.Plugins;
|
||||
using BotSharp.Plugin.SqlHero.Settings;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace BotSharp.Plugin.SqlHero;
|
||||
|
||||
public class SqlHeroPlugin : IBotSharpPlugin
|
||||
{
|
||||
public string Name => "SQL Hero";
|
||||
public string Description => "Convert the requirements into corresponding SQL statements and execute if needed";
|
||||
|
||||
public void RegisterDI(IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
var settings = new SqlHeroSetting();
|
||||
config.Bind("SqlHero", settings);
|
||||
services.AddSingleton(x =>
|
||||
{
|
||||
Console.WriteLine($"Loaded SqlHero settings:: {Regex.Replace(settings.MySqlConnectionString, "password=.*?;", "password=******;")}", Color.Yellow);
|
||||
return settings;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"id": "beda4c12-e1ec-4b4b-b328-3df4a6687c4f",
|
||||
"name": "SQL Expert",
|
||||
"description": "Convert the requirements into corresponding SQL statements according to the table structure and execute them if needed.",
|
||||
"createdDateTime": "2023-11-15T13:49:00Z",
|
||||
"updatedDateTime": "2023-11-15T13:49:00Z",
|
||||
"isPublic": false,
|
||||
"allowRouting": false
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
[{
|
||||
"name": "execute_sql",
|
||||
"description": "generate sql statement and execute the query.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sql_statement": {
|
||||
"type": "string",
|
||||
"description": "SQL statement"
|
||||
}
|
||||
},
|
||||
"required": ["sql_statement"]
|
||||
}
|
||||
}]
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
You are a SQL Expert who knows how to convert business requirements to SQL expressions.
|
||||
|
||||
Follow these steps:
|
||||
1: Look at the table DDL defintions especially for the CONSTRAINT and FOREIGN KEY REFERENCES.
|
||||
2: Translate user requirements into SQL statements step by step.
|
||||
3: Double check, don't miss any requirements, all the parameters must have values.
|
||||
4: Confirm with the user whether to execute the sql statement.
|
||||
If user confirms to run the query, call function execute_sql to execute it.
|
||||
|
||||
|
||||
Table structure guideline:
|
||||
Table with prefix "data_" represents system enum item.
|
||||
Table with prefix "client_" represents client specific configuration or client dataset.
|
||||
|
||||
Below are the table DDL information in JSON format:
|
||||
|
||||
CREATE TABLE `data_ServiceCategory` (
|
||||
`Id` smallint(6) NOT NULL,
|
||||
`Name` varchar(50) NOT NULL,
|
||||
`IsClientVisible` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`IsTurnService` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`Id`),
|
||||
KEY `ID_data_ServiceCategory_Name` (`Name`)
|
||||
)
|
||||
|
||||
CREATE TABLE `data_ServiceType` (
|
||||
`Id` smallint(6) NOT NULL,
|
||||
`Name` varchar(50) NOT NULL,
|
||||
`ServcieCategoryId` smallint(6) NOT NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
KEY `FK_data_ServiceType_ServcieCategoryId` (`ServcieCategoryId`),
|
||||
CONSTRAINT `FK_data_ServiceType_ServcieCategoryId` FOREIGN KEY (`ServcieCategoryId`) REFERENCES `data_ServiceCategory` (`Id`)
|
||||
)
|
||||
|
||||
CREATE TABLE `data_ServiceCode` (
|
||||
`Id` smallint(6) NOT NULL,
|
||||
`Name` varchar(100) NOT NULL,
|
||||
`ServiceTypeId` smallint(6) NOT NULL,
|
||||
`AbbrName` varchar(100) DEFAULT NULL,
|
||||
`IsClientVisible` tinyint(1) NOT NULL DEFAULT '1',
|
||||
PRIMARY KEY (`Id`),
|
||||
KEY `FK_data_ServiceCode_ServiceCodeId` (`ServiceTypeId`),
|
||||
KEY `FK_data_ServiceCode_SkillLevelId` (`SkillLevelId`),
|
||||
CONSTRAINT `FK_data_ServiceCode_ServiceCodeId` FOREIGN KEY (`ServiceTypeId`) REFERENCES `data_ServiceType` (`Id`),
|
||||
CONSTRAINT `FK_data_ServiceCode_SkillLevelId` FOREIGN KEY (`SkillLevelId`) REFERENCES `data_SkillLevel` (`Id`)
|
||||
)
|
||||
|
||||
CREATE TABLE `client_ServiceCode` (
|
||||
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ClientServiceTypeId` int(10) unsigned NOT NULL,
|
||||
`ServiceCodeId` smallint(6) NOT NULL,
|
||||
`IsContract` tinyint(1) DEFAULT '0',
|
||||
`IsHidden` tinyint(1) DEFAULT '0',
|
||||
`IsPersonal` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`IsHiddenForClient` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`Id`),
|
||||
UNIQUE KEY `UK_client_ServiceCode` (`ClientServiceTypeId`,`ServiceCodeId`,`IsPersonal`),
|
||||
KEY `FK_client_ServiceCode_ServiceCodeId_idx` (`ServiceCodeId`),
|
||||
CONSTRAINT `FK_client_ServiceCode_ClientServiceTypeId` FOREIGN KEY (`ClientServiceTypeId`) REFERENCES `client_ServiceType` (`Id`),
|
||||
CONSTRAINT `FK_client_ServiceCode_ServiceCodeId` FOREIGN KEY (`ServiceCodeId`) REFERENCES `data_ServiceCode` (`Id`)
|
||||
)
|
||||
|
||||
CREATE TABLE `client_ServiceType` (
|
||||
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ClientServiceCategoryId` int(10) unsigned NOT NULL,
|
||||
`ServiceTypeId` smallint(6) NOT NULL,
|
||||
`IsHidden` tinyint(1) DEFAULT '0',
|
||||
PRIMARY KEY (`Id`),
|
||||
UNIQUE KEY `UK_client_ServiceType` (`ClientServiceCategoryId`,`ServiceTypeId`),
|
||||
KEY `FK_client_ServiceType_ServiceTypeId` (`ServiceTypeId`),
|
||||
CONSTRAINT `FK_client_ServiceType_ClientServiceCategoryId` FOREIGN KEY (`ClientServiceCategoryId`) REFERENCES `client_ServiceCategory` (`Id`),
|
||||
CONSTRAINT `FK_client_ServiceType_ServiceTypeId` FOREIGN KEY (`ServiceTypeId`) REFERENCES `data_ServiceType` (`Id`)
|
||||
)
|
||||
|
||||
CREATE TABLE `client_ServiceCategory` (
|
||||
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ClientId` int(10) unsigned NOT NULL,
|
||||
`ServiceCategoryId` smallint(6) NOT NULL,
|
||||
`IsHidden` tinyint(1) DEFAULT '0',
|
||||
PRIMARY KEY (`Id`),
|
||||
UNIQUE KEY `UK_client_ServiceCategory` (`ClientId`,`ServiceCategoryId`),
|
||||
KEY `FK_client_ServiceCategory_ServiceCategoryId` (`ServiceCategoryId`),
|
||||
CONSTRAINT `FK_client_ServiceCategory_ClientId` FOREIGN KEY (`ClientId`) REFERENCES `client_Profile` (`Id`),
|
||||
CONSTRAINT `FK_client_ServiceCategory_ServiceCategoryId` FOREIGN KEY (`ServiceCategoryId`) REFERENCES `data_ServiceCategory` (`Id`)
|
||||
)
|
||||
|
||||
CREATE TABLE `client_Profile` (
|
||||
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`Name` varchar(100) NOT NULL,
|
||||
`Active` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`ClientCode` varchar(20) DEFAULT NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
UNIQUE KEY `UK_client_Profile` (`ClientCode`),
|
||||
KEY `FK_client_Location_CustomerTypeId` (`CustomerTypeId`),
|
||||
KEY `IDX_client_Profile_BusinessTypeId` (`BusinessTypeId`),
|
||||
CONSTRAINT `FK_client_Location_CustomerTypeId` FOREIGN KEY (`CustomerTypeId`) REFERENCES `data_CustomerType` (`Id`)
|
||||
)
|
||||
|
||||
CREATE TABLE `client_WOReactive` (
|
||||
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`WONum` varchar(40) NOT NULL,
|
||||
`LocationId` int(10) unsigned NOT NULL,
|
||||
`AffiliateId` int(10) unsigned DEFAULT NULL,
|
||||
`ServiceCodeId` smallint(6) NOT NULL,
|
||||
`StatusId` smallint(6) NOT NULL,
|
||||
`ClientNTE` decimal(18,2) DEFAULT NULL,
|
||||
`ReferWONum` varchar(512) DEFAULT NULL,
|
||||
`WOCategoryId` smallint(6) DEFAULT NULL,
|
||||
`WOTypeId` smallint(6) DEFAULT NULL,
|
||||
`WOServiceCategoryId` smallint(6) DEFAULT NULL,
|
||||
`WOServiceTypeId` smallint(6) DEFAULT NULL,
|
||||
`WOClientId` int(10) unsigned DEFAULT NULL
|
||||
PRIMARY KEY (`Id`),
|
||||
CONSTRAINT `FK_client_WOReactive_ServiceCodeId` FOREIGN KEY (`ServiceCodeId`) REFERENCES `data_ServiceCode` (`Id`),
|
||||
CONSTRAINT `FK_client_WOReactive_StatusId` FOREIGN KEY (`StatusId`) REFERENCES `data_WOStatus` (`Id`),
|
||||
CONSTRAINT `FK_client_WOReactive_WOCategoryId` FOREIGN KEY (`WOCategoryId`) REFERENCES `data_WOCategory` (`Id`),
|
||||
CONSTRAINT `FK_client_WOReactive_WOTypeId` FOREIGN KEY (`WOTypeId`) REFERENCES `data_WOType` (`Id`)
|
||||
)
|
||||
|
||||
CREATE TABLE `client_ServiceCodeNTE` (
|
||||
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ClientServiceCodeId` int(10) unsigned NOT NULL,
|
||||
`ClientNTE` decimal(18,2) DEFAULT NULL,
|
||||
`AffiliateNTE` decimal(18,2) DEFAULT NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
CONSTRAINT `FK_client_ServiceCodeNTE_ClientServiceCodeId` FOREIGN KEY (`ClientServiceCodeId`) REFERENCES `client_ServiceCode` (`Id`)
|
||||
)
|
||||
|
||||
CREATE TABLE `data_Priority` (
|
||||
`Id` smallint(6) NOT NULL,
|
||||
`Name` varchar(50) NOT NULL,
|
||||
`AbbrName` varchar(50) NOT NULL,
|
||||
PRIMARY KEY (`Id`)
|
||||
)
|
||||
|
||||
CREATE TABLE `data_Trade` (
|
||||
`Id` smallint(6) NOT NULL,
|
||||
`Name` varchar(50) NOT NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
KEY `ID_data_Trade_Name` (`Name`)
|
||||
)
|
||||
|
||||
CREATE TABLE `data_TradeServiceCode` (
|
||||
`Id` int(10) NOT NULL AUTO_INCREMENT,
|
||||
`TradeId` smallint(6) NOT NULL,
|
||||
`ServiceCodeId` smallint(6) NOT NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
UNIQUE KEY `UK_data_TradeServiceCode` (`ServiceCodeId`,`CustomerTypeId`),
|
||||
KEY `FK_data_TradeServiceCode_TradeId` (`TradeId`),
|
||||
KEY `FK_data_TradeServiceCode_ServiceCodeId` (`ServiceCodeId`),
|
||||
CONSTRAINT `FK_data_TradeServiceCode_ServiceCodeId` FOREIGN KEY (`ServiceCodeId`) REFERENCES `data_ServiceCode` (`Id`),
|
||||
CONSTRAINT `FK_data_TradeServiceCode_TradeId` FOREIGN KEY (`TradeId`) REFERENCES `data_Trade` (`Id`)
|
||||
)
|
||||
|
||||
CREATE TABLE `Client_ServiceCodePriority` (
|
||||
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ClientServiceCodeId` int(10) unsigned NOT NULL,
|
||||
`PriorityId` smallint(6) NOT NULL,
|
||||
PRIMARY KEY (`Id`),
|
||||
CONSTRAINT `FK_Client_ServiceCodePriority_ClientServiceCodeId` FOREIGN KEY (`ClientServiceCodeId`) REFERENCES `client_ServiceCode` (`Id`),
|
||||
CONSTRAINT `FK_Client_ServiceCodePriority_PriorityId` FOREIGN KEY (`PriorityId`) REFERENCES `data_Priority` (`Id`)
|
||||
)
|
||||
|
||||
|
||||
====
|
||||
User Task:
|
||||
|
||||
Find all the NTE for all the service combination of client 'IH'.
|
||||
Out put the service combination and NTE and priority.
|
||||
|
||||
====
|
||||
Examples:
|
||||
|
||||
user: Create a new service category named 'DSC Equipment' for client 'Signet'.
|
||||
assistant: Steps: 1. Check if the service category is in data_ServiceCategory.
|
||||
2. If exists, get the service category id from data_ServiceCategory.
|
||||
3. If not exists, insert a new record and get the id.
|
||||
4. Insert a new record to client_ServiceCategory based on the FOREIGN KEY and REFERENCES.
|
||||
|
||||
user: Create a new service type and service code.
|
||||
assistant: You can follow the process same as service category creation.
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Plugin.Twilio.Settings;
|
||||
using Twilio.Jwt.AccessToken;
|
||||
using Token = Twilio.Jwt.AccessToken.Token;
|
||||
|
||||
|
|
@ -47,7 +48,7 @@ public class TwilioService
|
|||
|
||||
public VoiceResponse ReturnInstructions(string message)
|
||||
{
|
||||
var routingSetting = _services.GetRequiredService<RoutingSettings>();
|
||||
var twilioSetting = _services.GetRequiredService<TwilioSetting>();
|
||||
|
||||
var response = new VoiceResponse();
|
||||
var gather = new Gather()
|
||||
|
|
@ -56,7 +57,7 @@ public class TwilioService
|
|||
{
|
||||
Gather.InputEnum.Speech
|
||||
},
|
||||
Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{routingSetting.AgentId}")
|
||||
Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{twilioSetting.AgentId}")
|
||||
};
|
||||
gather.Say(message);
|
||||
response.Append(gather);
|
||||
|
|
@ -76,13 +77,13 @@ public class TwilioService
|
|||
|
||||
public VoiceResponse HoldOn(int interval, string message = null)
|
||||
{
|
||||
var routingSetting = _services.GetRequiredService<RoutingSettings>();
|
||||
var twilioSetting = _services.GetRequiredService<TwilioSetting>();
|
||||
|
||||
var response = new VoiceResponse();
|
||||
var gather = new Gather()
|
||||
{
|
||||
Input = new List<Gather.InputEnum>() { Gather.InputEnum.Speech },
|
||||
Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{routingSetting.AgentId}"),
|
||||
Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{twilioSetting.AgentId}"),
|
||||
ActionOnEmptyResult = true
|
||||
};
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
|
|
|
|||
|
|
@ -9,4 +9,5 @@ public class TwilioSetting
|
|||
public string ApiKeySID { get; set; }
|
||||
public string ApiSecret { get; set; }
|
||||
public string CallbackHost { get; set; }
|
||||
public string AgentId { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,9 @@
|
|||
],
|
||||
|
||||
"Router": {
|
||||
"AgentId": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a",
|
||||
"AgentIds": [
|
||||
"01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a"
|
||||
],
|
||||
"Planner": "NaivePlanner"
|
||||
},
|
||||
|
||||
|
|
@ -107,7 +109,8 @@
|
|||
"PhoneNumber": "+1",
|
||||
"AccountSID": "",
|
||||
"AuthToken": "",
|
||||
"CallbackHost": "https://"
|
||||
"CallbackHost": "https://",
|
||||
"AgentId": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a"
|
||||
},
|
||||
|
||||
"Database": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue