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-18 02:27:47 +00:00
public string Indication = > "Organizing and summarizing the final output results." ;
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-24 15:45:57 +00:00
var states = _services . GetRequiredService < IConversationStateService > ( ) ;
var steps = states . GetState ( "planning_result" ) . JsonArrayContent < SecondStagePlan > ( ) ;
2024-09-04 16:04:19 +00:00
var allTables = new List < string > ( ) ;
2024-09-30 23:25:32 +00:00
var ddlStatements = string . Empty ;
2024-09-24 15:45:57 +00:00
var relevantKnowledge = states . GetState ( "planning_result" ) ;
2024-09-30 20:14:37 +00:00
var dictionaryItems = states . GetState ( "dictionary_items" ) ;
2024-10-04 21:44:01 +00:00
var excelImportResult = states . GetState ( "excel_import_result" ) ;
2024-09-24 15:45:57 +00:00
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 ( ) ;
2024-09-30 23:25:32 +00:00
2024-10-04 21:44:01 +00:00
var msgCopy = RoleDialogModel . From ( message ) ;
msgCopy . FunctionArgs = JsonSerializer . Serialize ( new
2024-09-13 17:06:06 +00:00
{
2024-10-04 21:44:01 +00:00
tables = distinctTables ,
} ) ;
await fn . InvokeFunction ( "sql_table_definition" , msgCopy ) ;
ddlStatements + = "\r\n" + msgCopy . Content ;
2024-09-04 16:04:19 +00:00
// Summarize and generate query
2024-10-10 14:59:42 +00:00
var summaryPlanPrompt = await GetSummaryPlanPrompt ( msgCopy , taskRequirement , relevantKnowledge , dictionaryItems , ddlStatements , excelImportResult ) ;
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-10-10 14:59:42 +00:00
private async Task < string > GetSummaryPlanPrompt ( RoleDialogModel message , string taskDescription , string relevantKnowledge , string dictionaryItems , string ddlStatement , string excelImportResult )
2024-08-29 21:33:32 +00:00
{
var agentService = _services . GetRequiredService < IAgentService > ( ) ;
var render = _services . GetRequiredService < ITemplateRender > ( ) ;
2024-10-10 14:59:42 +00:00
var knowledgeHooks = _services . GetServices < IKnowledgeHook > ( ) ;
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
} ) ;
2024-10-10 14:59:42 +00:00
var globalKnowledges = new List < string > ( ) ;
foreach ( var hook in knowledgeHooks )
{
var k = await hook . GetGlobalKnowledges ( message ) ;
globalKnowledges . AddRange ( k ) ;
}
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-30 23:25:32 +00:00
{ "summary_requirements" , string . Join ( "\r\n" , additionalRequirements ) } ,
2024-10-10 14:59:42 +00:00
{ "global_knowledges" , globalKnowledges } ,
2024-09-05 00:27:19 +00:00
{ "relevant_knowledges" , relevantKnowledge } ,
2024-10-01 06:18:11 +00:00
{ "dictionary_items" , dictionaryItems } ,
2024-09-17 11:32:11 +00:00
{ "table_structure" , ddlStatement } ,
2024-10-04 21:44:01 +00:00
{ "excel_import_result" , excelImportResult }
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 ) ;
}
}