From eaf647677e524d4b55c6b5212ec1fe3446713190 Mon Sep 17 00:00:00 2001 From: Joanna Ren <101223@smsassist.com> Date: Wed, 16 Oct 2024 17:05:59 -0500 Subject: [PATCH] Add knowledge generation refine --- .../Knowledges/Models/GenerateKnowledge.cs | 19 ++++++++++++ .../BotSharp.Plugin.KnowledgeBase.csproj | 4 +++ .../Functions/GenerateKnowledgeFn.cs | 31 +++++++++++++++++-- .../templates/knowledge.generation.liquid | 2 +- .../knowledge.generation.refine.liquid | 15 +++++++++ .../functions/sql_dictionary_lookup.json | 6 +++- 6 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/GenerateKnowledge.cs create mode 100644 src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/templates/knowledge.generation.refine.liquid diff --git a/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/GenerateKnowledge.cs b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/GenerateKnowledge.cs new file mode 100644 index 000000000..a5698dc0e --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Knowledges/Models/GenerateKnowledge.cs @@ -0,0 +1,19 @@ +namespace BotSharp.Abstraction.Knowledges.Models; + +public class GenerateKnowledge +{ + [JsonPropertyName("question")] + public string Question { get; set; } = string.Empty; + + [JsonPropertyName("answer")] + public string Answer { get; set; } = string.Empty; + + [JsonPropertyName("refined_collection")] + public string RefinedCollection { get; set; } = string.Empty; + + [JsonPropertyName("refine_answer")] + public Boolean RefineAnswer { get; set; } = false; + + [JsonPropertyName("existing_answer")] + public string ExistingAnswer { get; set; } = string.Empty; +} diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj b/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj index 1cd8144fe..3216564ed 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/BotSharp.Plugin.KnowledgeBase.csproj @@ -22,6 +22,7 @@ + @@ -38,6 +39,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/GenerateKnowledgeFn.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/GenerateKnowledgeFn.cs index cd43fca1d..114ce7e43 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/GenerateKnowledgeFn.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Functions/GenerateKnowledgeFn.cs @@ -1,5 +1,6 @@ using BotSharp.Abstraction.Templating; using BotSharp.Core.Infrastructures; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace BotSharp.Plugin.KnowledgeBase.Functions; @@ -20,14 +21,23 @@ public GenerateKnowledgeFn(IServiceProvider services, KnowledgeBaseSettings sett public async Task Execute(RoleDialogModel message) { - var args = JsonSerializer.Deserialize(message.FunctionArgs ?? "{}"); + var args = JsonSerializer.Deserialize(message.FunctionArgs ?? "{}"); var agentService = _services.GetRequiredService(); var llmAgent = await agentService.GetAgent(BuiltInAgentId.Planner); - var generateKnowledgePrompt = await GetGenerateKnowledgePrompt(args.Question, args.Answer); + var refineKnowledge = args.RefinedCollection; + String generateKnowledgePrompt; + if (args.RefineAnswer == true) + { + generateKnowledgePrompt = await GetRefineKnowledgePrompt(args.Question, args.Answer, args.ExistingAnswer); + } + else + { + generateKnowledgePrompt = await GetGenerateKnowledgePrompt(args.Question, args.Answer); + } var agent = new Agent { Id = message.CurrentAgentId ?? string.Empty, - Name = "sqlDriver_DictionarySearch", + Name = "knowledge_generator", Instruction = generateKnowledgePrompt, LlmConfig = llmAgent.LlmConfig }; @@ -51,6 +61,21 @@ private async Task GetGenerateKnowledgePrompt(string userQuestions, stri { "sql_answer", sqlAnswer }, }); } + private async Task GetRefineKnowledgePrompt(string userQuestion, string sqlAnswer, string existionAnswer) + { + var agentService = _services.GetRequiredService(); + var render = _services.GetRequiredService(); + + var agent = await agentService.GetAgent(BuiltInAgentId.Learner); + var template = agent.Templates.FirstOrDefault(x => x.Name == "knowledge.generation.refine")?.Content ?? string.Empty; + + return render.Render(template, new Dictionary + { + { "user_question", userQuestion }, + { "new_answer", sqlAnswer }, + { "existing_answer", existionAnswer} + }); + } private async Task GetAiResponse(Agent agent) { var text = "Generate question and answer pair"; diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/templates/knowledge.generation.liquid b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/templates/knowledge.generation.liquid index 49e374a1f..2792595a8 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/templates/knowledge.generation.liquid +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/templates/knowledge.generation.liquid @@ -1,4 +1,4 @@ -You are a knowledge generator for knowledge base. Extract the answer in "SQL Answer" to answer the User Questions. +You are a knowledge extractor for knowledge base. Extract the answer in "SQL Answer" to answer the User Questions. * Replace alias with the actual table name. Output json array only, formatting as [{"question":"string", "answer":""}]. * Skip the question/answer for tmp table. * Don't include tmp table in the answer. diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/templates/knowledge.generation.refine.liquid b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/templates/knowledge.generation.refine.liquid new file mode 100644 index 000000000..4a7af975b --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/data/agents/01acc3e5-0af7-49e6-ad7a-a760bd12dc40/templates/knowledge.generation.refine.liquid @@ -0,0 +1,15 @@ +You are a knowledge extractor for knowledge base. Utilize the new answer and existing answer to generate the final integrated answer. +Output json array only, formatting as [{"question":"", "answer":""}]. Replace the new line with \r\n. +* Don't loss any knowledge in the existing answer. + +===== +User Question: +{{ user_question }} + +===== +New Answer: +{{ new_answer }} + +===== +Existing Answer: +{{ existing_answer }} diff --git a/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/sql_dictionary_lookup.json b/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/sql_dictionary_lookup.json index 6ad2a9179..3dc21e013 100644 --- a/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/sql_dictionary_lookup.json +++ b/src/Plugins/BotSharp.Plugin.SqlDriver/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/sql_dictionary_lookup.json @@ -1,6 +1,6 @@ { "name": "verify_dictionary_term", - "description": "Get id from dictionary table by keyword. Call this function only if need_lookup_dictionary is True", + "description": "Get id from dictionary table by keyword. Call this function only if need_lookup_dictionary is true and is_insert is false", "parameters": { "type": "object", "properties": { @@ -12,6 +12,10 @@ "type": "string", "description": "the reason why you need to call verify_dictionary_term" }, + "is_insert": { + "type": "boolean", + "description": "if SQL statement is inserting." + }, "tables": { "type": "array", "description": "all related tables",