resolve conflicts
This commit is contained in:
commit
c2b870b655
|
|
@ -18,6 +18,7 @@ public class PrimaryStagePlanFn : IFunctionCallback
|
|||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
// Debug
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
var knowledgeService = _services.GetRequiredService<IKnowledgeService>();
|
||||
var knowledgeSettings = _services.GetRequiredService<KnowledgeBaseSettings>();
|
||||
|
|
@ -28,16 +29,14 @@ public class PrimaryStagePlanFn : IFunctionCallback
|
|||
|
||||
// Get knowledge from vectordb
|
||||
var collectionName = knowledgeSettings.Default.CollectionName ?? KnowledgeCollectionName.BotSharp; ;
|
||||
var knowledges = await knowledgeService.SearchVectorKnowledge(task.Question, collectionName, new VectorSearchOptions
|
||||
var knowledges = await knowledgeService.SearchVectorKnowledge(task.Requirements, collectionName, new VectorSearchOptions
|
||||
{
|
||||
Confidence = 0.1f
|
||||
});
|
||||
message.Content = string.Join("\r\n\r\n=====\r\n", knowledges.Select(x => x.ToQuestionAnswer()));
|
||||
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var currentAgent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
|
||||
// Send knowledge to AI to refine and summarize the primary planning
|
||||
var currentAgent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
var firstPlanningPrompt = await GetFirstStagePlanPrompt(task, message);
|
||||
var plannerAgent = new Agent
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,11 +5,13 @@ namespace BotSharp.Plugin.Planner.Functions;
|
|||
public class SummaryPlanFn : IFunctionCallback
|
||||
{
|
||||
public string Name => "plan_summary";
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ILogger _logger;
|
||||
private object aiAssistant;
|
||||
|
||||
public SummaryPlanFn(IServiceProvider services, ILogger<PrimaryStagePlanFn> logger)
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ILogger<SummaryPlanFn> _logger;
|
||||
|
||||
public SummaryPlanFn(
|
||||
IServiceProvider services,
|
||||
ILogger<SummaryPlanFn> logger)
|
||||
{
|
||||
_services = services;
|
||||
_logger = logger;
|
||||
|
|
@ -17,32 +19,51 @@ public class SummaryPlanFn : IFunctionCallback
|
|||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
//debug
|
||||
var fn = _services.GetRequiredService<IRoutingService>();
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
|
||||
var currentAgent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
state.SetState("max_tokens", "4096");
|
||||
|
||||
var task = state.GetState("requirement_detail");
|
||||
|
||||
// summarize and generate query
|
||||
var summaryPlanningPrompt = await GetPlanSummaryPrompt(task, message);
|
||||
_logger.LogInformation(summaryPlanningPrompt);
|
||||
// Get DDL
|
||||
var steps = message.Content.JsonArrayContent<SecondStagePlan>();
|
||||
|
||||
// Get all the related tables
|
||||
var allTables = new List<string>();
|
||||
foreach (var step in steps)
|
||||
{
|
||||
allTables.AddRange(step.Tables);
|
||||
}
|
||||
message.Data = allTables.Distinct().ToList();
|
||||
|
||||
// Get table DDL and stores in content
|
||||
var msgCopy = RoleDialogModel.From(message);
|
||||
await fn.InvokeFunction("get_table_definition", msgCopy);
|
||||
var ddlStatements = msgCopy.Content;
|
||||
|
||||
// Summarize and generate query
|
||||
var summaryPlanPrompt = await GetPlanSummaryPrompt(task, message.Content, ddlStatements);
|
||||
_logger.LogInformation($"Summary plan prompt:\r\n{summaryPlanPrompt}");
|
||||
|
||||
var plannerAgent = new Agent
|
||||
{
|
||||
Id = BuiltInAgentId.Planner,
|
||||
Name = "planner_summary",
|
||||
Instruction = summaryPlanningPrompt,
|
||||
TemplateDict = new Dictionary<string, object>()
|
||||
Name = "Planner Summary",
|
||||
Instruction = summaryPlanPrompt,
|
||||
LlmConfig = currentAgent.LlmConfig
|
||||
};
|
||||
var response_summary = await GetAiResponse(plannerAgent);
|
||||
|
||||
message.Content = response_summary.Content;
|
||||
var summary = await GetAiResponse(plannerAgent);
|
||||
message.Content = summary.Content;
|
||||
message.StopCompletion = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<string> GetPlanSummaryPrompt(string task, RoleDialogModel message)
|
||||
private async Task<string> GetPlanSummaryPrompt(string task, string knowledge, string ddlStatement)
|
||||
{
|
||||
// save to knowledge base
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
|
|
@ -58,9 +79,9 @@ public class SummaryPlanFn : IFunctionCallback
|
|||
|
||||
return render.Render(template, new Dictionary<string, object>
|
||||
{
|
||||
{ "table_structure", message.SecondaryContent }, ////check
|
||||
{ "task_description", task},
|
||||
{ "relevant_knowledges", message.Content },
|
||||
{ "table_structure", ddlStatement },
|
||||
{ "task_description", task },
|
||||
{ "relevant_knowledges", knowledge },
|
||||
{ "response_format", responseFormat }
|
||||
});
|
||||
}
|
||||
|
|
@ -69,17 +90,17 @@ public class SummaryPlanFn : IFunctionCallback
|
|||
var conv = _services.GetRequiredService<IConversationService>();
|
||||
var wholeDialogs = conv.GetDialogHistory();
|
||||
|
||||
//add "test" to wholeDialogs' last element
|
||||
// Add "test" to wholeDialogs' last element
|
||||
if (plannerAgent.Name == "planner_summary")
|
||||
{
|
||||
//add "test" to wholeDialogs' last element in a new paragraph
|
||||
// Add "test" to wholeDialogs' last element in a new paragraph
|
||||
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) instead of LAST_INSERT_ID function.\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";
|
||||
}
|
||||
|
||||
if (plannerAgent.Name == "planning_1st")
|
||||
{
|
||||
//add "test" to wholeDialogs' last element in a new paragraph
|
||||
// Add "test" to wholeDialogs' last element in a new paragraph
|
||||
wholeDialogs.Last().Content += "\n\nYou must analyze the table description to infer the table relations.";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
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.
|
||||
Call plan_summary to summarize the final planning steps.
|
||||
You must Call plan_summary as the last step to summarize the final planning steps.
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
using BotSharp.Abstraction.Routing;
|
||||
using BotSharp.Core.Infrastructures;
|
||||
using MySqlConnector;
|
||||
using static Dapper.SqlMapper;
|
||||
using BotSharp.Abstraction.Agents.Enums;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BotSharp.Plugin.Planner.Functions;
|
||||
|
||||
public class AddDatabaseKnowledgeFn : IFunctionCallback
|
||||
{
|
||||
public string Name => "add_database_knowledge";
|
||||
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ILogger<AddDatabaseKnowledgeFn> _logger;
|
||||
|
||||
public AddDatabaseKnowledgeFn(
|
||||
IServiceProvider services,
|
||||
ILogger<AddDatabaseKnowledgeFn> logger)
|
||||
{
|
||||
_services = services;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var sqlDriver = _services.GetRequiredService<SqlDriverService>();
|
||||
var fn = _services.GetRequiredService<IRoutingService>();
|
||||
var settings = _services.GetRequiredService<SqlDriverSetting>();
|
||||
|
||||
|
||||
var allTables = new HashSet<string>();
|
||||
using var connection = new MySqlConnection(settings.MySqlConnectionString);
|
||||
|
||||
var sql = $"select table_name from information_schema.tables;";
|
||||
var results = connection.Query(sql, new Dictionary<string, object>());
|
||||
|
||||
foreach (var item in results)
|
||||
{
|
||||
if (item == null) continue;
|
||||
|
||||
allTables.Add(item.TABLE_NAME);
|
||||
}
|
||||
message.Data = allTables.ToList();
|
||||
|
||||
var currentAgent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
var errorNote = string.Empty;
|
||||
|
||||
foreach (var table in allTables)
|
||||
{
|
||||
message.Data = new List<string> { table };
|
||||
|
||||
await fn.InvokeFunction("get_table_definition", message);
|
||||
var planningPrompt = await GetPrompt(message);
|
||||
var plannerAgent = new Agent
|
||||
{
|
||||
Id = string.Empty,
|
||||
Name = "Database Knowledge",
|
||||
Instruction = planningPrompt,
|
||||
LlmConfig = currentAgent.LlmConfig
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var response = await GetAiResponse(plannerAgent);
|
||||
var knowledges = response.Content.JsonArrayContent<ExtractedKnowledge>();
|
||||
foreach (var k in knowledges)
|
||||
{
|
||||
try
|
||||
{
|
||||
message.FunctionArgs = JsonSerializer.Serialize(new ExtractedKnowledge
|
||||
{
|
||||
Question = k.Question,
|
||||
Answer = k.Answer
|
||||
});
|
||||
await fn.InvokeFunction("memorize_knowledge", message);
|
||||
message.SecondaryContent += $"Table: {table}, Question: {k.Question}, {message.Content}\r\n";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var note = $"Error processing table {table}: {e.Message}\r\n{e.InnerException}";
|
||||
errorNote += note;
|
||||
_logger.LogWarning(note);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
errorNote += $"Error processing table {table}: {e.Message}\r\n{e.InnerException}\r\n";
|
||||
_logger.LogWarning(errorNote);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<RoleDialogModel> GetAiResponse(Agent plannerAgent)
|
||||
{
|
||||
var conv = _services.GetRequiredService<IConversationService>();
|
||||
var wholeDialogs = conv.GetDialogHistory();
|
||||
|
||||
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||
provider: plannerAgent.LlmConfig.Provider,
|
||||
model: plannerAgent.LlmConfig.Model);
|
||||
|
||||
return await completion.GetChatCompletions(plannerAgent, wholeDialogs);
|
||||
}
|
||||
|
||||
private async Task<string> GetPrompt(RoleDialogModel message)
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
|
||||
var aiAssistant = await agentService.GetAgent(BuiltInAgentId.AIAssistant);
|
||||
var template = aiAssistant.Templates.FirstOrDefault(x => x.Name == "database_knowledge")?.Content ?? string.Empty;
|
||||
|
||||
return render.Render(template, new Dictionary<string, object>
|
||||
{
|
||||
{ "table_structure", message.Content }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using MySqlConnector;
|
||||
using static Dapper.SqlMapper;
|
||||
|
||||
|
|
@ -7,10 +8,14 @@ public class GetTableDefinitionFn : IFunctionCallback
|
|||
{
|
||||
public string Name => "get_table_definition";
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ILogger<GetTableDefinitionFn> _logger;
|
||||
|
||||
public GetTableDefinitionFn(IServiceProvider services)
|
||||
public GetTableDefinitionFn(
|
||||
IServiceProvider services,
|
||||
ILogger<GetTableDefinitionFn> logger)
|
||||
{
|
||||
_services = services;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
|
|
@ -20,37 +25,47 @@ public class GetTableDefinitionFn : IFunctionCallback
|
|||
var settings = _services.GetRequiredService<SqlDriverSetting>();
|
||||
|
||||
// Get table DDL from database
|
||||
var tables = message.Data as List<string>;
|
||||
if (tables.IsNullOrEmpty()) return false;
|
||||
|
||||
var tableDdls = new List<string>();
|
||||
using var connection = new MySqlConnection(settings.MySqlConnectionString);
|
||||
connection.Open();
|
||||
|
||||
foreach (var table in (List<string>)message.Data)
|
||||
foreach (var table in tables)
|
||||
{
|
||||
var escapedTableName = MySqlHelper.EscapeString(table);
|
||||
|
||||
var sql = $"select * from information_schema.tables where table_name = @tableName";
|
||||
var result = connection.QueryFirstOrDefault(sql, new
|
||||
try
|
||||
{
|
||||
tableName = escapedTableName
|
||||
});
|
||||
var escapedTableName = MySqlHelper.EscapeString(table);
|
||||
|
||||
if (result == null) continue;
|
||||
var sql = $"select * from information_schema.tables where table_name = @tableName";
|
||||
var result = connection.QueryFirstOrDefault(sql, new
|
||||
{
|
||||
tableName = escapedTableName
|
||||
});
|
||||
|
||||
sql = $"SHOW CREATE TABLE `{escapedTableName}`";
|
||||
using var command = new MySqlCommand(sql, connection);
|
||||
using var reader = command.ExecuteReader();
|
||||
if (reader.Read())
|
||||
{
|
||||
result = reader.GetString(1);
|
||||
tableDdls.Add(result);
|
||||
if (result == null) continue;
|
||||
|
||||
sql = $"SHOW CREATE TABLE `{escapedTableName}`";
|
||||
using var command = new MySqlCommand(sql, connection);
|
||||
using var reader = command.ExecuteReader();
|
||||
if (reader.Read())
|
||||
{
|
||||
result = reader.GetString(1);
|
||||
tableDdls.Add(result);
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
command.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning($"Error when getting ddl statement of table {table}.");
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
command.Dispose();
|
||||
}
|
||||
|
||||
connection.Close();
|
||||
message.Content = string.Join("\r\n", tableDdls);
|
||||
message.Content = string.Join("\r\n\r\n", tableDdls);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ public class DbKnowledgeService
|
|||
using var connection = new MySqlConnection(settings.MySqlConnectionString);
|
||||
connection.Open();
|
||||
|
||||
var result = string.Empty;
|
||||
var ddl = string.Empty;
|
||||
var escapedTableName = MySqlHelper.EscapeString(table);
|
||||
var sql = $"SHOW CREATE TABLE `{escapedTableName}`";
|
||||
|
||||
|
|
@ -102,13 +102,13 @@ public class DbKnowledgeService
|
|||
using var reader = command.ExecuteReader();
|
||||
if (reader.Read())
|
||||
{
|
||||
result = reader.GetString(1);
|
||||
ddl = reader.GetString(1);
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
command.Dispose();
|
||||
connection.Close();
|
||||
return result;
|
||||
return ddl;
|
||||
}
|
||||
|
||||
private async Task<string> GetPrompt(string content)
|
||||
|
|
|
|||
Loading…
Reference in a new issue