SQL Driver
This commit is contained in:
parent
89a8bf4dff
commit
35e322c336
|
|
@ -14,6 +14,7 @@ public static class HookEmitter
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
logger.LogInformation($"Emit hook action on {action.Method.Name}({hook.GetType().Name})");
|
||||||
action(hook);
|
action(hook);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,13 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\agent.json" />
|
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\agent.json" />
|
||||||
|
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\functions\plan_primary_stage.json" />
|
||||||
|
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\functions\plan_secondary_stage.json" />
|
||||||
|
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\functions\plan_summary.json" />
|
||||||
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\instructions\instruction.liquid" />
|
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\instructions\instruction.liquid" />
|
||||||
|
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.1st.next.liquid" />
|
||||||
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.2nd.plan.liquid" />
|
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.2nd.plan.liquid" />
|
||||||
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.summarize.liquid" />
|
<None Remove="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.summarize.liquid" />
|
||||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\plan_primary_stage.json" />
|
|
||||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\plan_secondary_stage.json" />
|
|
||||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\plan_summary.json" />
|
|
||||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\planner_prompt.two_stage.1st.plan.liquid" />
|
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\planner_prompt.two_stage.1st.plan.liquid" />
|
||||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\plan_primary_stage.fn.liquid" />
|
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\plan_primary_stage.fn.liquid" />
|
||||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\plan_secondary_stage.fn.liquid" />
|
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\plan_secondary_stage.fn.liquid" />
|
||||||
|
|
@ -28,27 +29,30 @@
|
||||||
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\agent.json">
|
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\agent.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\functions\plan_primary_stage.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\functions\plan_secondary_stage.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\functions\plan_summary.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\instructions\instruction.liquid">
|
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\instructions\instruction.liquid">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.1st.next.liquid">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.2nd.plan.liquid">
|
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.2nd.plan.liquid">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.summarize.liquid">
|
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.summarize.liquid">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\plan_secondary_stage.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\plan_primary_stage.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.1st.plan.liquid">
|
<Content Include="data\agents\282a7128-69a1-44b0-878c-a9159b88f3b9\templates\two_stage.1st.plan.liquid">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\plan_summary.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\plan_secondary_stage.fn.liquid">
|
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\plan_secondary_stage.fn.liquid">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
using BotSharp.Abstraction.MLTasks;
|
using BotSharp.Abstraction.Infrastructures.Enums;
|
||||||
using BotSharp.Abstraction.Routing.Planning;
|
using BotSharp.Abstraction.Routing.Planning;
|
||||||
using BotSharp.Core.Routing.Planning;
|
using BotSharp.Core.Routing.Planning;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace BotSharp.Plugin.Planner.TwoStaging;
|
namespace BotSharp.Plugin.Planner.TwoStaging;
|
||||||
|
|
||||||
|
|
@ -10,12 +9,6 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
|
||||||
private readonly IServiceProvider _services;
|
private readonly IServiceProvider _services;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
public int MaxLoopCount => 10;
|
public int MaxLoopCount => 10;
|
||||||
private bool _isTaskCompleted;
|
|
||||||
|
|
||||||
private Queue<FirstStagePlan> _plan1st = new Queue<FirstStagePlan>();
|
|
||||||
private Queue<SecondStagePlan> _plan2nd = new Queue<SecondStagePlan>();
|
|
||||||
|
|
||||||
private List<string> _executionContext = new List<string>();
|
|
||||||
|
|
||||||
public TwoStageTaskPlanner(IServiceProvider services, ILogger<TwoStageTaskPlanner> logger)
|
public TwoStageTaskPlanner(IServiceProvider services, ILogger<TwoStageTaskPlanner> logger)
|
||||||
{
|
{
|
||||||
|
|
@ -25,78 +18,36 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
|
||||||
|
|
||||||
public async Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId, List<RoleDialogModel> dialogs)
|
public async Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId, List<RoleDialogModel> dialogs)
|
||||||
{
|
{
|
||||||
// push agent to routing context
|
var nextStepPrompt = await GetNextStepPrompt(router);
|
||||||
var routing = _services.GetRequiredService<IRoutingService>();
|
var inst = new FunctionCallFromLlm();
|
||||||
routing.Context.Push(BuiltInAgentId.Planner, "Make plan in TwoStage planner");
|
|
||||||
return new FunctionCallFromLlm
|
// chat completion
|
||||||
|
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||||
|
provider: router?.LlmConfig?.Provider,
|
||||||
|
model: router?.LlmConfig?.Model);
|
||||||
|
|
||||||
|
// text completion
|
||||||
|
dialogs = new List<RoleDialogModel>
|
||||||
{
|
{
|
||||||
AgentName = router.Name,
|
new RoleDialogModel(AgentRole.User, nextStepPrompt)
|
||||||
Response = dialogs.Last().Content,
|
|
||||||
Function = "route_to_agent"
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*FirstStagePlan[] items = await GetFirstStagePlanAsync(router, messageId, dialogs);
|
|
||||||
|
|
||||||
foreach (var item in items)
|
|
||||||
{
|
|
||||||
_plan1st.Enqueue(item);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get Second Stage Plan
|
|
||||||
if (_plan2nd.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
var plan1 = _plan1st.Dequeue();
|
|
||||||
|
|
||||||
if (plan1.ContainMultipleSteps)
|
|
||||||
{
|
{
|
||||||
SecondStagePlan[] items = await GetSecondStagePlanAsync(router, messageId, plan1, dialogs);
|
FunctionName = nameof(TwoStageTaskPlanner),
|
||||||
|
MessageId = messageId
|
||||||
foreach (var item in items)
|
|
||||||
{
|
|
||||||
_plan2nd.Enqueue(item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
_plan2nd.Enqueue(new SecondStagePlan
|
|
||||||
{
|
|
||||||
Description = plan1.Task,
|
|
||||||
Tables = plan1.Tables,
|
|
||||||
Parameters = plan1.Parameters,
|
|
||||||
Results = plan1.Results,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var plan2 = _plan2nd.Dequeue();
|
|
||||||
|
|
||||||
var secondStagePrompt = GetSecondStageTaskPrompt(router, plan2);
|
|
||||||
var inst = new FunctionCallFromLlm
|
|
||||||
{
|
|
||||||
AgentName = "SQL Driver",
|
|
||||||
Response = secondStagePrompt,
|
|
||||||
Function = "route_to_agent"
|
|
||||||
};
|
};
|
||||||
|
var response = await completion.GetChatCompletions(router, dialogs);
|
||||||
|
|
||||||
inst.HandleDialogsByPlanner = true;
|
inst = response.Content.JsonContent<FunctionCallFromLlm>();
|
||||||
_isTaskCompleted = _plan1st.IsNullOrEmpty() && _plan2nd.IsNullOrEmpty();
|
|
||||||
|
|
||||||
return inst;*/
|
// Fix LLM malformed response
|
||||||
|
PlannerHelper.FixMalformedResponse(_services, inst);
|
||||||
|
|
||||||
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RoleDialogModel> BeforeHandleContext(FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
public List<RoleDialogModel> BeforeHandleContext(FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||||
{
|
{
|
||||||
var question = inst.Response;
|
var question = inst.Response;
|
||||||
if (_executionContext.Count > 0)
|
|
||||||
{
|
|
||||||
var content = GetContext();
|
|
||||||
question = $"CONTEXT:\r\n{content}\r\n" + inst.Response;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
question = $"CONTEXT:\r\n{question}";
|
|
||||||
}
|
|
||||||
|
|
||||||
var taskAgentDialogs = new List<RoleDialogModel>
|
var taskAgentDialogs = new List<RoleDialogModel>
|
||||||
{
|
{
|
||||||
|
|
@ -113,14 +64,14 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
|
||||||
{
|
{
|
||||||
dialogs.AddRange(taskAgentDialogs.Skip(1));
|
dialogs.AddRange(taskAgentDialogs.Skip(1));
|
||||||
|
|
||||||
// Keep execution context
|
|
||||||
_executionContext.Add(taskAgentDialogs.Last().Content);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
|
||||||
{
|
{
|
||||||
|
// Set user content as Planner's question
|
||||||
|
message.FunctionName = inst.Function;
|
||||||
|
message.FunctionArgs = inst.Arguments == null ? "{}" : JsonSerializer.Serialize(inst.Arguments);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,7 +79,7 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
|
||||||
{
|
{
|
||||||
var context = _services.GetRequiredService<IRoutingContext>();
|
var context = _services.GetRequiredService<IRoutingContext>();
|
||||||
|
|
||||||
if (message.StopCompletion || _isTaskCompleted)
|
if (message.StopCompletion)
|
||||||
{
|
{
|
||||||
context.Empty(reason: $"Agent queue is cleared by {nameof(TwoStageTaskPlanner)}");
|
context.Empty(reason: $"Agent queue is cleared by {nameof(TwoStageTaskPlanner)}");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -145,16 +96,6 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetContext()
|
|
||||||
{
|
|
||||||
var content = "";
|
|
||||||
foreach (var c in _executionContext)
|
|
||||||
{
|
|
||||||
content += $"* {c}\r\n";
|
|
||||||
}
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<string> GetFirstStagePlanPrompt(Agent router)
|
private async Task<string> GetFirstStagePlanPrompt(Agent router)
|
||||||
{
|
{
|
||||||
var template = router.Templates.First(x => x.Name == "two_stage.1st.plan").Content;
|
var template = router.Templates.First(x => x.Name == "two_stage.1st.plan").Content;
|
||||||
|
|
@ -180,63 +121,20 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetFirstStageNextPrompt(Agent router)
|
private async Task<string> GetNextStepPrompt(Agent router)
|
||||||
{
|
{
|
||||||
var template = router.Templates.First(x => x.Name == "first_stage.next").Content;
|
var agentService = _services.GetRequiredService<IAgentService>();
|
||||||
var responseFormat = JsonSerializer.Serialize(new FirstStagePlan
|
var planner = await agentService.LoadAgent(BuiltInAgentId.Planner);
|
||||||
{
|
var template = planner.Templates.First(x => x.Name == "two_stage.1st.next").Content;
|
||||||
});
|
var states = _services.GetRequiredService<IConversationStateService>();
|
||||||
var render = _services.GetRequiredService<ITemplateRender>();
|
var render = _services.GetRequiredService<ITemplateRender>();
|
||||||
return render.Render(template, new Dictionary<string, object>
|
return render.Render(template, new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "response_format", responseFormat },
|
{ StateConst.EXPECTED_ACTION_AGENT, states.GetState(StateConst.EXPECTED_ACTION_AGENT) },
|
||||||
|
{ StateConst.EXPECTED_GOAL_AGENT, states.GetState(StateConst.EXPECTED_GOAL_AGENT) }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<SecondStagePlan[]> GetSecondStagePlanAsync(Agent router, string messageId, FirstStagePlan plan1st, List<RoleDialogModel> dialogs)
|
|
||||||
{
|
|
||||||
var secondStagePrompt = GetSecondStagePlanPrompt(router, plan1st);
|
|
||||||
var firstStageSystemPrompt = await GetFirstStagePlanPrompt(router);
|
|
||||||
|
|
||||||
var plan = new SecondStagePlan[0];
|
|
||||||
|
|
||||||
var llmProviderService = _services.GetRequiredService<ILlmProviderService>();
|
|
||||||
var model = llmProviderService.GetProviderModel("azure-openai", "gpt-4");
|
|
||||||
|
|
||||||
// chat completion
|
|
||||||
var completion = CompletionProvider.GetChatCompletion(_services,
|
|
||||||
provider: "azure-openai",
|
|
||||||
model: model.Name);
|
|
||||||
|
|
||||||
string text = string.Empty;
|
|
||||||
|
|
||||||
var conversations = dialogs.Where(x => x.Role != AgentRole.Function).ToList();
|
|
||||||
conversations.Add(new RoleDialogModel(AgentRole.User, secondStagePrompt)
|
|
||||||
{
|
|
||||||
CurrentAgentId = router.Id,
|
|
||||||
MessageId = messageId,
|
|
||||||
});
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = await completion.GetChatCompletions(new Agent
|
|
||||||
{
|
|
||||||
Id = router.Id,
|
|
||||||
Name = nameof(TwoStageTaskPlanner),
|
|
||||||
Instruction = firstStageSystemPrompt
|
|
||||||
}, conversations);
|
|
||||||
|
|
||||||
text = response.Content;
|
|
||||||
plan = response.Content.JsonArrayContent<SecondStagePlan>();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError($"{ex.Message}: {text}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return plan;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetSecondStageTaskPrompt(Agent router, SecondStagePlan plan)
|
private string GetSecondStageTaskPrompt(Agent router, SecondStagePlan plan)
|
||||||
{
|
{
|
||||||
var template = router.Templates.First(x => x.Name == "planner_prompt.two_stage.2nd.task").Content;
|
var template = router.Templates.First(x => x.Name == "planner_prompt.two_stage.2nd.task").Content;
|
||||||
|
|
@ -249,22 +147,4 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
|
||||||
{ "output_results", JsonSerializer.Serialize(plan.Results) },
|
{ "output_results", JsonSerializer.Serialize(plan.Results) },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetSecondStagePlanPrompt(Agent router, FirstStagePlan plan)
|
|
||||||
{
|
|
||||||
var template = router.Templates.First(x => x.Name == "planner_prompt.two_stage.2nd.plan").Content;
|
|
||||||
var responseFormat = JsonSerializer.Serialize(new SecondStagePlan
|
|
||||||
{
|
|
||||||
Tool = "tool name if task solution provided",
|
|
||||||
Parameters = new JsonDocument[] { JsonDocument.Parse("{}") },
|
|
||||||
Results = new string[] { "" }
|
|
||||||
});
|
|
||||||
var context = GetContext();
|
|
||||||
var render = _services.GetRequiredService<ITemplateRender>();
|
|
||||||
return render.Render(template, new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "task_description", plan.Task },
|
|
||||||
{ "response_format", responseFormat }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "282a7128-69a1-44b0-878c-a9159b88f3b9",
|
"id": "282a7128-69a1-44b0-878c-a9159b88f3b9",
|
||||||
"name": "Planner",
|
"name": "Planner",
|
||||||
"description": "Plan feasible implementation steps for complex problems",
|
"description": "Plan feasible implementation steps for user task request",
|
||||||
"type": "task",
|
"type": "task",
|
||||||
"createdDateTime": "2023-08-27T10:39:00Z",
|
"createdDateTime": "2023-08-27T10:39:00Z",
|
||||||
"updatedDateTime": "2023-08-27T14:39:00Z",
|
"updatedDateTime": "2023-08-27T14:39:00Z",
|
||||||
|
|
@ -11,7 +11,8 @@
|
||||||
"profiles": [ "planning" ],
|
"profiles": [ "planning" ],
|
||||||
"utilities": [ "two-stage-planner" ],
|
"utilities": [ "two-stage-planner" ],
|
||||||
"llmConfig": {
|
"llmConfig": {
|
||||||
"provider": "openai",
|
"provider": "anthropic",
|
||||||
"model": "gpt-4o-mini"
|
"model": "claude-3-5-sonnet-20240620",
|
||||||
|
"max_recursion_depth": 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
Use the TwoStagePlanner approach to plan the overall implementation steps, call plan_primary_stage.
|
Use the TwoStagePlanner approach to plan the overall implementation steps, call plan_primary_stage.
|
||||||
If need_additional_information is true, call plan_secondary_stage for the specific primary stage.
|
If need_additional_information is true, call plan_secondary_stage for the specific primary stage.
|
||||||
You must Call plan_summary as the last step to summarize the final planning steps.
|
You must call plan_summary as the last planning step to summarize the final query.
|
||||||
|
You must generate the final sql statement from function of plan_summary.
|
||||||
|
|
||||||
{% if global_knowledges != empty -%}
|
{% if global_knowledges != empty -%}
|
||||||
=====
|
=====
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
What is the next step based on the CONVERSATION?
|
||||||
|
Route to the last handling agent in priority.
|
||||||
|
{% if expected_next_action_agent != empty -%}
|
||||||
|
Expected next action agent is {{ expected_next_action_agent }}.
|
||||||
|
{%- else -%}
|
||||||
|
Next action agent is inferred based on user lastest response.
|
||||||
|
{%- endif %}
|
||||||
|
{% if expected_user_goal_agent != empty -%}
|
||||||
|
Expected user goal agent is {{ expected_user_goal_agent }}.
|
||||||
|
{%- else -%}
|
||||||
|
User goal agent is inferred based on user initial request.
|
||||||
|
{%- endif %}
|
||||||
|
Always route to planner first.
|
||||||
|
|
@ -11,7 +11,9 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\get_table_definition.json" />
|
||||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\sql_select.json" />
|
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\sql_select.json" />
|
||||||
|
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\get_table_definition.fn.liquid" />
|
||||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\sql_executor.fn.liquid" />
|
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\sql_executor.fn.liquid" />
|
||||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\agent.json" />
|
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\agent.json" />
|
||||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions\get_table_columns.json" />
|
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions\get_table_columns.json" />
|
||||||
|
|
@ -23,6 +25,12 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\get_table_definition.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\get_table_definition.fn.liquid">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\agent.json">
|
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\agent.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
using BotSharp.Plugin.SqlDriver.Models;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MySqlConnector;
|
using MySqlConnector;
|
||||||
using static Dapper.SqlMapper;
|
|
||||||
|
|
||||||
namespace BotSharp.Plugin.SqlDriver.Functions;
|
namespace BotSharp.Plugin.SqlDriver.Functions;
|
||||||
|
|
||||||
|
|
@ -20,16 +20,16 @@ public class GetTableDefinitionFn : IFunctionCallback
|
||||||
|
|
||||||
public async Task<bool> Execute(RoleDialogModel message)
|
public async Task<bool> Execute(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
|
var args = JsonSerializer.Deserialize<SqlStatement>(message.FunctionArgs);
|
||||||
|
var tables = new string[] { args.Table };
|
||||||
var agentService = _services.GetRequiredService<IAgentService>();
|
var agentService = _services.GetRequiredService<IAgentService>();
|
||||||
var sqlDriver = _services.GetRequiredService<SqlDriverService>();
|
var sqlDriver = _services.GetRequiredService<SqlDriverService>();
|
||||||
var settings = _services.GetRequiredService<SqlDriverSetting>();
|
var settings = _services.GetRequiredService<SqlDriverSetting>();
|
||||||
|
|
||||||
// Get table DDL from database
|
// Get table DDL from database
|
||||||
var tables = message.Data as IEnumerable<string>;
|
|
||||||
if (tables.IsNullOrEmpty()) return false;
|
|
||||||
|
|
||||||
var tableDdls = new List<string>();
|
var tableDdls = new List<string>();
|
||||||
using var connection = new MySqlConnection(settings.MySqlConnectionString);
|
using var connection = new MySqlConnection(settings.MySqlExecutionConnectionString);
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
foreach (var table in tables)
|
foreach (var table in tables)
|
||||||
|
|
|
||||||
|
|
@ -17,39 +17,33 @@ public class SqlSelect : IFunctionCallback
|
||||||
public async Task<bool> Execute(RoleDialogModel message)
|
public async Task<bool> Execute(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
var args = JsonSerializer.Deserialize<SqlStatement>(message.FunctionArgs);
|
var args = JsonSerializer.Deserialize<SqlStatement>(message.FunctionArgs);
|
||||||
var sqlDriver = _services.GetRequiredService<SqlDriverService>();
|
|
||||||
|
if (args.GeneratedWithoutTableDefinition)
|
||||||
|
{
|
||||||
|
message.Content = $"Get the table definition first.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// check if need to instantely
|
// check if need to instantely
|
||||||
var execNow = !args.Parameters.Any(x => x.Value.StartsWith("@"));
|
var settings = _services.GetRequiredService<SqlDriverSetting>();
|
||||||
if (execNow)
|
using var connection = new MySqlConnection(settings.MySqlExecutionConnectionString);
|
||||||
|
var dictionary = new Dictionary<string, object>();
|
||||||
|
foreach(var p in args.Parameters)
|
||||||
{
|
{
|
||||||
var settings = _services.GetRequiredService<SqlDriverSetting>();
|
dictionary["@" + p.Name] = p.Value;
|
||||||
using var connection = new MySqlConnection(settings.MySqlConnectionString);
|
}
|
||||||
var dictionary = new Dictionary<string, object>();
|
var result = connection.Query(args.Statement, dictionary);
|
||||||
foreach(var p in args.Parameters)
|
|
||||||
{
|
|
||||||
dictionary["@" + p.Name] = p.Value;
|
|
||||||
}
|
|
||||||
var result = connection.QueryFirstOrDefault(args.Statement, dictionary);
|
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
message.Content = "Record not found";
|
message.Content = "Record not found";
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
message.Content = JsonSerializer.Serialize(result);
|
|
||||||
args.Return.Value = message.Content;
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlDriver.Enqueue(args);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sqlDriver.Enqueue(args);
|
message.Content = JsonSerializer.Serialize(result);
|
||||||
message.Content = $"The {args.Return.Name} is saved to @{args.Return.Alias}";
|
args.Return.Value = message.Content;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ public class SqlExecutorHook : AgentHookBase, IAgentHook
|
||||||
private const string SQL_EXECUTOR_TEMPLATE = "sql_executor.fn";
|
private const string SQL_EXECUTOR_TEMPLATE = "sql_executor.fn";
|
||||||
private IEnumerable<string> _targetSqlExecutorFunctions = new List<string>
|
private IEnumerable<string> _targetSqlExecutorFunctions = new List<string>
|
||||||
{
|
{
|
||||||
"sql_select"
|
"sql_select",
|
||||||
|
"get_table_definition",
|
||||||
};
|
};
|
||||||
|
|
||||||
public override string SelfId => string.Empty;
|
public override string SelfId => string.Empty;
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,22 @@ namespace BotSharp.Plugin.SqlDriver.Models;
|
||||||
public class SqlStatement
|
public class SqlStatement
|
||||||
{
|
{
|
||||||
[JsonPropertyName("sql_statement")]
|
[JsonPropertyName("sql_statement")]
|
||||||
public string Statement { get; set; }
|
public string Statement { get; set; } = null!;
|
||||||
|
|
||||||
[JsonPropertyName("reason")]
|
[JsonPropertyName("reason")]
|
||||||
public string Reason { get; set; }
|
public string Reason { get; set; } = null!;
|
||||||
|
|
||||||
[JsonPropertyName("table")]
|
[JsonPropertyName("table")]
|
||||||
public string Table { get; set; }
|
public string Table { get; set; } = null!;
|
||||||
|
|
||||||
[JsonPropertyName("parameters")]
|
[JsonPropertyName("parameters")]
|
||||||
public SqlParameter[] Parameters { get; set; } = new SqlParameter[0];
|
public SqlParameter[] Parameters { get; set; } = [];
|
||||||
|
|
||||||
[JsonPropertyName("return_field")]
|
[JsonPropertyName("return_field")]
|
||||||
public SqlReturn Return { get; set; }
|
public SqlReturn Return { get; set; } = new SqlReturn();
|
||||||
|
|
||||||
|
[JsonPropertyName("generated_without_table_definition")]
|
||||||
|
public bool GeneratedWithoutTableDefinition { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ namespace BotSharp.Plugin.SqlHero.Settings;
|
||||||
|
|
||||||
public class SqlDriverSetting
|
public class SqlDriverSetting
|
||||||
{
|
{
|
||||||
public string MySqlConnectionString { get; set; }
|
public string MySqlConnectionString { get; set; } = null!;
|
||||||
public string SqlServerConnectionString { get; set; }
|
public string MySqlExecutionConnectionString { get; set; } = null!;
|
||||||
public string SqlLiteConnectionString { get; set; }
|
public string SqlServerConnectionString { get; set; } = null!;
|
||||||
|
public string SqlLiteConnectionString { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,6 @@
|
||||||
"table": {
|
"table": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "table need to check"
|
"description": "table need to check"
|
||||||
},
|
|
||||||
"return_field": {
|
|
||||||
"type": "object",
|
|
||||||
"description": "the name and alias for the return field",
|
|
||||||
"properties": {
|
|
||||||
"ddl": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "DDL for the table"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [ "table" ]
|
"required": [ "table" ]
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,10 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "related table"
|
"description": "related table"
|
||||||
},
|
},
|
||||||
|
"generated_without_table_definition": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "sql is generated before retrieving table definition"
|
||||||
|
},
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "data criteria for the query",
|
"description": "data criteria for the query",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Call get_table_definition to get the table definition of the table you want to query.
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
You are connecting to {{ db_type }} database. Please generate SQL statements following {{ db_type }} rules.
|
You are connecting to {{ db_type }} database. You can run provided SQL statements by following {{ db_type }} rules.
|
||||||
|
|
||||||
Please call function sql_select if user wants to get or retrieve data from data tables.
|
Please call function sql_select if user wants to get or retrieve data from data tables.
|
||||||
If there are any parameters, please add them in the WHERE clause, each of which starts with "@".
|
If there are any parameters, please add them in the WHERE clause, each of which starts with "@".
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "beda4c12-e1ec-4b4b-b328-3df4a6687c4f",
|
"id": "beda4c12-e1ec-4b4b-b328-3df4a6687c4f",
|
||||||
"name": "SQL Driver",
|
"name": "SQL Driver",
|
||||||
"description": "Convert the requirements into corresponding SQL statements according to the table structure.",
|
"description": "Runs the specified SQL statement and returns the result.",
|
||||||
"type": "task",
|
"type": "task",
|
||||||
"createdDateTime": "2023-11-15T13:49:00Z",
|
"createdDateTime": "2023-11-15T13:49:00Z",
|
||||||
"updatedDateTime": "2023-11-15T13:49:00Z",
|
"updatedDateTime": "2023-11-15T13:49:00Z",
|
||||||
|
|
@ -9,8 +9,15 @@
|
||||||
"isPublic": true,
|
"isPublic": true,
|
||||||
"profiles": [ "database" ],
|
"profiles": [ "database" ],
|
||||||
"llmConfig": {
|
"llmConfig": {
|
||||||
"model": "gpt-4-0125",
|
"provider": "openai",
|
||||||
"model3": "gpt-35-turbo-1106",
|
"model": "gpt-4o-mini"
|
||||||
"max_recursion_depth": 10
|
},
|
||||||
}
|
"routingRules": [
|
||||||
|
{
|
||||||
|
"field": "sql_statement",
|
||||||
|
"required": true,
|
||||||
|
"field_type": "string",
|
||||||
|
"description": "SQL statement"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue