2024-09-17 11:32:11 +00:00
using BotSharp.Abstraction.Planning ;
using BotSharp.Plugin.Planner.TwoStaging ;
2024-08-29 21:33:32 +00:00
using BotSharp.Plugin.Planner.TwoStaging.Models ;
namespace BotSharp.Plugin.Planner.Functions ;
public class SummaryPlanFn : IFunctionCallback
{
public string Name = > "plan_summary" ;
2024-09-04 16:04:19 +00:00
2024-08-29 21:33:32 +00:00
private readonly IServiceProvider _services ;
2024-09-04 16:04:19 +00:00
private readonly ILogger < SummaryPlanFn > _logger ;
2024-08-29 21:33:32 +00:00
2024-09-04 16:04:19 +00:00
public SummaryPlanFn (
IServiceProvider services ,
ILogger < SummaryPlanFn > logger )
2024-08-29 21:33:32 +00:00
{
_services = services ;
_logger = logger ;
}
public async Task < bool > Execute ( RoleDialogModel message )
{
2024-09-04 15:16:05 +00:00
var fn = _services . GetRequiredService < IRoutingService > ( ) ;
var agentService = _services . GetRequiredService < IAgentService > ( ) ;
2024-08-29 21:33:32 +00:00
var state = _services . GetRequiredService < IConversationStateService > ( ) ;
2024-09-04 16:04:19 +00:00
2024-08-29 21:33:32 +00:00
state . SetState ( "max_tokens" , "4096" ) ;
2024-09-05 01:11:25 +00:00
var currentAgent = await agentService . LoadAgent ( message . CurrentAgentId ) ;
2024-09-05 00:27:19 +00:00
var taskRequirement = state . GetState ( "requirement_detail" ) ;
2024-08-29 21:33:32 +00:00
2024-09-05 00:27:19 +00:00
// Get table names
2024-09-04 15:16:05 +00:00
var steps = message . Content . JsonArrayContent < SecondStagePlan > ( ) ;
2024-09-04 16:04:19 +00:00
var allTables = new List < string > ( ) ;
2024-09-13 17:06:06 +00:00
var ddlStatements = "" ;
var relevantKnowledge = message . Content ;
2024-09-04 15:16:05 +00:00
foreach ( var step in steps )
{
allTables . AddRange ( step . Tables ) ;
}
2024-09-13 17:06:06 +00:00
var distinctTables = allTables . Distinct ( ) . ToList ( ) ;
foreach ( var table in distinctTables )
{
var msgCopy = RoleDialogModel . From ( message ) ;
msgCopy . FunctionArgs = JsonSerializer . Serialize ( new
{
table = table ,
} ) ;
await fn . InvokeFunction ( "get_table_definition" , msgCopy ) ;
ddlStatements + = "\r\n" + msgCopy . Content ;
}
2024-09-04 16:04:19 +00:00
// Summarize and generate query
2024-09-05 01:11:25 +00:00
var summaryPlanPrompt = await GetSummaryPlanPrompt ( taskRequirement , relevantKnowledge , ddlStatements ) ;
2024-09-04 16:04:19 +00:00
_logger . LogInformation ( $"Summary plan prompt:\r\n{summaryPlanPrompt}" ) ;
2024-08-30 21:12:20 +00:00
2024-08-29 21:33:32 +00:00
var plannerAgent = new Agent
{
Id = BuiltInAgentId . Planner ,
2024-09-04 16:04:19 +00:00
Name = "Planner Summary" ,
Instruction = summaryPlanPrompt ,
2024-09-04 15:16:05 +00:00
LlmConfig = currentAgent . LlmConfig
2024-08-29 21:33:32 +00:00
} ;
2024-09-04 16:04:19 +00:00
var summary = await GetAiResponse ( plannerAgent ) ;
message . Content = summary . Content ;
2024-09-17 11:32:11 +00:00
await HookEmitter . Emit < IPlanningHook > ( _services , x = >
x . OnPlanningCompleted ( nameof ( TwoStageTaskPlanner ) , message ) ) ;
2024-08-29 21:33:32 +00:00
return true ;
}
2024-09-05 01:11:25 +00:00
private async Task < string > GetSummaryPlanPrompt ( string taskDescription , string relevantKnowledge , string ddlStatement )
2024-08-29 21:33:32 +00:00
{
var agentService = _services . GetRequiredService < IAgentService > ( ) ;
var render = _services . GetRequiredService < ITemplateRender > ( ) ;
2024-08-30 21:12:20 +00:00
2024-09-05 01:12:55 +00:00
var agent = await agentService . GetAgent ( BuiltInAgentId . Planner ) ;
var template = agent . Templates . FirstOrDefault ( x = > x . Name = = "two_stage.summarize" ) ? . Content ? ? string . Empty ;
2024-09-17 11:32:11 +00:00
var additionalRequirements = new List < string > ( ) ;
await HookEmitter . Emit < IPlanningHook > ( _services , async x = >
2024-08-29 21:33:32 +00:00
{
2024-09-17 11:32:11 +00:00
var requirement = await x . GetSummaryAdditionalRequirements ( nameof ( TwoStageTaskPlanner ) ) ;
additionalRequirements . Add ( requirement ) ;
2024-08-29 21:33:32 +00:00
} ) ;
return render . Render ( template , new Dictionary < string , object >
{
2024-09-05 00:27:19 +00:00
{ "task_description" , taskDescription } ,
2024-09-17 11:32:11 +00:00
{ "summary_requirements" , string . Join ( "\r\n" , additionalRequirements ) } ,
2024-09-05 00:27:19 +00:00
{ "relevant_knowledges" , relevantKnowledge } ,
2024-09-17 11:32:11 +00:00
{ "table_structure" , ddlStatement } ,
2024-08-29 21:33:32 +00:00
} ) ;
}
2024-08-30 21:12:20 +00:00
private async Task < RoleDialogModel > GetAiResponse ( Agent plannerAgent )
2024-08-29 21:33:32 +00:00
{
var conv = _services . GetRequiredService < IConversationService > ( ) ;
var wholeDialogs = conv . GetDialogHistory ( ) ;
2024-08-30 21:12:20 +00:00
2024-09-05 00:27:19 +00:00
// Append text
2024-09-17 11:32:11 +00:00
wholeDialogs . Last ( ) . Content + = "\n\nIf the table structure didn't mention auto incremental, the data field id needs to insert id manually and you need to use max(id).\nFor example, you should use SET @id = select max(id) from table;" ;
wholeDialogs . Last ( ) . Content + = "\n\nTry if you can generate a single query to fulfill the needs." ;
2024-08-29 21:33:32 +00:00
var completion = CompletionProvider . GetChatCompletion ( _services ,
provider : plannerAgent . LlmConfig . Provider ,
model : plannerAgent . LlmConfig . Model ) ;
return await completion . GetChatCompletions ( plannerAgent , wholeDialogs ) ;
}
}