Merge branch 'master' into hdongDev
This commit is contained in:
commit
312c58fd3e
|
|
@ -33,7 +33,7 @@
|
|||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.Memory.Data" Version="8.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.4" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Rougamo.Fody" Version="4.0.0" />
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ public interface IConversationService
|
|||
Task<Conversation> GetConversation(string id);
|
||||
Task<PagedItems<Conversation>> GetConversations(ConversationFilter filter);
|
||||
Task<Conversation> UpdateConversationTitle(string id, string title);
|
||||
Task<bool> UpdateConversationMessage(string conversationId, UpdateMessageRequest request);
|
||||
Task<List<Conversation>> GetLastConversations();
|
||||
Task<List<string>> GetIdleConversations(int batchSize, int messageLimit, int bufferHours, IEnumerable<string> excludeAgentIds);
|
||||
Task<bool> DeleteConversations(IEnumerable<string> ids);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Models;
|
||||
|
||||
public class UpdateMessageRequest
|
||||
{
|
||||
public DialogElement Message { get; set; } = null!;
|
||||
public int InnderIndex { get; set; }
|
||||
}
|
||||
|
|
@ -5,6 +5,6 @@ public class InstructResult : ITrackableMessage
|
|||
[JsonPropertyName("message_id")]
|
||||
public string MessageId { get; set; }
|
||||
public string Text { get; set; }
|
||||
public object Data { get; set; }
|
||||
public Dictionary<string, string> States { get; set; }
|
||||
public object? Data { get; set; }
|
||||
public Dictionary<string, string>? States { get; set; } = new();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,4 +7,7 @@ public class ExtractedKnowledge
|
|||
|
||||
[JsonPropertyName("answer")]
|
||||
public string Answer { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("refined_collection")]
|
||||
public string RefinedCollection { get; set; } = string.Empty;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ public interface IBotSharpRepository
|
|||
Conversation GetConversation(string conversationId);
|
||||
PagedItems<Conversation> GetConversations(ConversationFilter filter);
|
||||
void UpdateConversationTitle(string conversationId, string title);
|
||||
bool UpdateConversationMessage(string conversationId, UpdateMessageRequest request);
|
||||
void UpdateConversationBreakpoint(string conversationId, ConversationBreakpoint breakpoint);
|
||||
ConversationBreakpoint? GetConversationBreakpoint(string conversationId);
|
||||
List<Conversation> GetLastConversations();
|
||||
|
|
|
|||
|
|
@ -50,6 +50,13 @@ public partial class ConversationService : IConversationService
|
|||
var conversation = db.GetConversation(id);
|
||||
return conversation;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateConversationMessage(string conversationId, UpdateMessageRequest request)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
return db.UpdateConversationMessage(conversationId, request);
|
||||
}
|
||||
|
||||
public async Task<Conversation> GetConversation(string id)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
|
|
|
|||
|
|
@ -156,22 +156,25 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
=> throw new NotImplementedException();
|
||||
|
||||
public void AppendConversationDialogs(string conversationId, List<DialogElement> dialogs)
|
||||
=> new NotImplementedException();
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void UpdateConversationTitle(string conversationId, string title)
|
||||
=> new NotImplementedException();
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public bool UpdateConversationMessage(string conversationId, UpdateMessageRequest request)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void UpdateConversationBreakpoint(string conversationId, ConversationBreakpoint breakpoint)
|
||||
=> new NotImplementedException();
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public ConversationBreakpoint? GetConversationBreakpoint(string conversationId)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void UpdateConversationStates(string conversationId, List<StateKeyValue> states)
|
||||
=> new NotImplementedException();
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public void UpdateConversationStatus(string conversationId, string status)
|
||||
=> new NotImplementedException();
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public IEnumerable<string> TruncateConversation(string conversationId, string messageId, bool cleanLog = false)
|
||||
=> throw new NotImplementedException();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using BotSharp.Abstraction.Loggers.Models;
|
|||
using BotSharp.Abstraction.Repositories.Models;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace BotSharp.Core.Repository
|
||||
{
|
||||
|
|
@ -133,6 +134,38 @@ namespace BotSharp.Core.Repository
|
|||
}
|
||||
}
|
||||
|
||||
public bool UpdateConversationMessage(string conversationId, UpdateMessageRequest request)
|
||||
{
|
||||
if (string.IsNullOrEmpty(conversationId)) return false;
|
||||
|
||||
var dialogs = GetConversationDialogs(conversationId);
|
||||
var candidates = dialogs.Where(x => x.MetaData.MessageId == request.Message.MetaData.MessageId
|
||||
&& x.MetaData.Role == request.Message.MetaData.Role).ToList();
|
||||
|
||||
var found = candidates.Where((_, idx) => idx == request.InnderIndex).FirstOrDefault();
|
||||
if (found == null) return false;
|
||||
|
||||
found.Content = request.Message.Content;
|
||||
found.RichContent = request.Message.RichContent;
|
||||
|
||||
if (!string.IsNullOrEmpty(found.SecondaryContent))
|
||||
{
|
||||
found.SecondaryContent = request.Message.Content;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(found.SecondaryRichContent))
|
||||
{
|
||||
found.SecondaryRichContent = request.Message.RichContent;
|
||||
}
|
||||
|
||||
var convDir = FindConversationDirectory(conversationId);
|
||||
if (string.IsNullOrEmpty(convDir)) return false;
|
||||
|
||||
var dialogFile = Path.Combine(convDir, DIALOG_FILE);
|
||||
File.WriteAllText(dialogFile, JsonSerializer.Serialize(dialogs, _options));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void UpdateConversationBreakpoint(string conversationId, ConversationBreakpoint breakpoint)
|
||||
{
|
||||
var convDir = FindConversationDirectory(conversationId);
|
||||
|
|
|
|||
|
|
@ -13,9 +13,12 @@ public class FirstStagePlan
|
|||
[JsonPropertyName("step")]
|
||||
public int Step { get; set; } = -1;
|
||||
|
||||
[JsonPropertyName("need_additional_information")]
|
||||
[JsonPropertyName("need_breakdown_task")]
|
||||
public bool ContainMultipleSteps { get; set; } = false;
|
||||
|
||||
[JsonPropertyName("need_lookup_dictionary")]
|
||||
public bool NeedLookupDictionary { get; set; } = false;
|
||||
|
||||
[JsonPropertyName("related_tables")]
|
||||
public string[] Tables { get; set; } = new string[0];
|
||||
|
||||
|
|
|
|||
|
|
@ -560,6 +560,11 @@ public class UserService : IUserService
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((record.UserName.Substring(0, 3) == "+86" || record.FirstName.Substring(0, 3) == "+86") && phone.Substring(0, 3) != "+86")
|
||||
{
|
||||
phone = $"+86{phone}";
|
||||
}
|
||||
|
||||
db.UpdateUserPhone(record.Id, phone);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,6 +221,29 @@ public class ConversationController : ControllerBase
|
|||
return response != null;
|
||||
}
|
||||
|
||||
[HttpPut("/conversation/{conversationId}/update-message")]
|
||||
public async Task<bool> UpdateConversationMessage([FromRoute] string conversationId, [FromBody] UpdateMessageModel model)
|
||||
{
|
||||
var conversationService = _services.GetRequiredService<IConversationService>();
|
||||
var request = new UpdateMessageRequest
|
||||
{
|
||||
Message = new DialogElement
|
||||
{
|
||||
MetaData = new DialogMetaData
|
||||
{
|
||||
MessageId = model.Message.MessageId,
|
||||
Role = model.Message.Sender?.Role
|
||||
},
|
||||
Content = model.Message.Text,
|
||||
RichContent = JsonSerializer.Serialize(model.Message.RichContent, _jsonOptions),
|
||||
},
|
||||
InnderIndex = model.InnerIndex
|
||||
};
|
||||
|
||||
return await conversationService.UpdateConversationMessage(conversationId, request);
|
||||
}
|
||||
|
||||
|
||||
[HttpDelete("/conversation/{conversationId}")]
|
||||
public async Task<bool> DeleteConversation([FromRoute] string conversationId)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace BotSharp.OpenAPI.ViewModels.Conversations;
|
||||
|
||||
public class UpdateMessageModel
|
||||
{
|
||||
[JsonPropertyName("message")]
|
||||
public ChatResponseModel Message { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("inner_index")]
|
||||
public int InnerIndex { get; set; }
|
||||
}
|
||||
|
|
@ -5,11 +5,11 @@ namespace BotSharp.OpenAPI.ViewModels.Users;
|
|||
|
||||
public class UserViewModel
|
||||
{
|
||||
public string Id { get; set; } = null!;
|
||||
public string Id { get; set; } = string.Empty;
|
||||
[JsonPropertyName("user_name")]
|
||||
public string UserName { get; set; } = null!;
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
[JsonPropertyName("first_name")]
|
||||
public string FirstName { get; set; } = null!;
|
||||
public string FirstName { get; set; } = string.Empty;
|
||||
[JsonPropertyName("last_name")]
|
||||
public string? LastName { get; set; }
|
||||
public string? Email { get; set; }
|
||||
|
|
@ -18,7 +18,7 @@ public class UserViewModel
|
|||
public string Role { get; set; } = UserRole.User;
|
||||
[JsonPropertyName("full_name")]
|
||||
public string FullName => $"{FirstName} {LastName}".Trim();
|
||||
public string Source { get; set; }
|
||||
public string? Source { get; set; }
|
||||
[JsonPropertyName("external_id")]
|
||||
public string? ExternalId { get; set; }
|
||||
public string Avatar { get; set; } = "/user/avatar";
|
||||
|
|
|
|||
|
|
@ -41,13 +41,22 @@ public class WelcomeHook : ConversationHookBase
|
|||
});
|
||||
var richContentService = _services.GetRequiredService<IRichContentService>();
|
||||
var messages = richContentService.ConvertToMessages(content);
|
||||
var guid = Guid.NewGuid().ToString();
|
||||
|
||||
foreach (var message in messages)
|
||||
{
|
||||
var richContent = new RichContent<IRichMessage>(message);
|
||||
var dialog = new RoleDialogModel(AgentRole.Assistant, message.Text)
|
||||
{
|
||||
MessageId = guid,
|
||||
CurrentAgentId = agent.Id,
|
||||
RichContent = richContent
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(new ChatResponseModel()
|
||||
{
|
||||
ConversationId = conversation.Id,
|
||||
MessageId = dialog.MessageId,
|
||||
Text = message.Text,
|
||||
RichContent = richContent,
|
||||
Sender = new UserViewModel()
|
||||
|
|
@ -60,12 +69,7 @@ public class WelcomeHook : ConversationHookBase
|
|||
|
||||
await Task.Delay(300);
|
||||
|
||||
_storage.Append(conversation.Id, new RoleDialogModel(AgentRole.Assistant, message.Text)
|
||||
{
|
||||
MessageId = conversation.Id,
|
||||
CurrentAgentId = agent.Id,
|
||||
RichContent = richContent
|
||||
});
|
||||
_storage.Append(conversation.Id, dialog);
|
||||
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnMessageReceivedFromAssistant", json);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ namespace BotSharp.Plugin.ExcelHandler.Services
|
|||
}
|
||||
private string CreateDBTableSqlString(string tableName, List<string> headerColumns, List<string>? columnTypes = null, bool isMemory = false)
|
||||
{
|
||||
_columnTypes = columnTypes.IsNullOrEmpty() ? headerColumns.Select(x => "VARCHAR(512)").ToList() : columnTypes;
|
||||
_columnTypes = columnTypes.IsNullOrEmpty() ? headerColumns.Select(x => "VARCHAR(128)").ToList() : columnTypes;
|
||||
|
||||
/*if (!headerColumns.Any(x => x.Equals("id", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
<None Remove="data\agents\01acc3e5-0af7-49e6-ad7a-a760bd12dc40\functions\confirm_knowledge_persistence.json" />
|
||||
<None Remove="data\agents\01acc3e5-0af7-49e6-ad7a-a760bd12dc40\functions\memorize_knowledge.json" />
|
||||
<None Remove="data\agents\01acc3e5-0af7-49e6-ad7a-a760bd12dc40\instructions\instruction.liquid" />
|
||||
<None Remove="data\agents\01acc3e5-0af7-49e6-ad7a-a760bd12dc40\templates\knowledge.generation.liquid" />
|
||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\knowledge_retrieval.fn.liquid" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
@ -37,6 +38,9 @@
|
|||
<Content Include="data\agents\01acc3e5-0af7-49e6-ad7a-a760bd12dc40\instructions\instruction.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\01acc3e5-0af7-49e6-ad7a-a760bd12dc40\templates\knowledge.generation.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\knowledge_retrieval.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
using BotSharp.Abstraction.Templating;
|
||||
using BotSharp.Core.Infrastructures;
|
||||
|
||||
namespace BotSharp.Plugin.KnowledgeBase.Functions;
|
||||
|
||||
public class GenerateKnowledgeFn : IFunctionCallback
|
||||
{
|
||||
public string Name => "generate_knowledge";
|
||||
|
||||
public string Indication => "generating knowledge";
|
||||
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly KnowledgeBaseSettings _settings;
|
||||
|
||||
public GenerateKnowledgeFn(IServiceProvider services, KnowledgeBaseSettings settings)
|
||||
{
|
||||
_services = services;
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
var args = JsonSerializer.Deserialize<ExtractedKnowledge>(message.FunctionArgs ?? "{}");
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var llmAgent = await agentService.GetAgent(BuiltInAgentId.Planner);
|
||||
var generateKnowledgePrompt = await GetGenerateKnowledgePrompt(args.Question, args.Answer);
|
||||
var agent = new Agent
|
||||
{
|
||||
Id = message.CurrentAgentId ?? string.Empty,
|
||||
Name = "sqlDriver_DictionarySearch",
|
||||
Instruction = generateKnowledgePrompt,
|
||||
LlmConfig = llmAgent.LlmConfig
|
||||
};
|
||||
var response = await GetAiResponse(agent);
|
||||
message.Data = response.Content.JsonArrayContent<ExtractedKnowledge>();
|
||||
message.Content = response.Content;
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<string> GetGenerateKnowledgePrompt(string userQuestions, string sqlAnswer)
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
|
||||
var agent = await agentService.GetAgent(BuiltInAgentId.Learner);
|
||||
var template = agent.Templates.FirstOrDefault(x => x.Name == "knowledge.generation")?.Content ?? string.Empty;
|
||||
|
||||
return render.Render(template, new Dictionary<string, object>
|
||||
{
|
||||
{ "user_questions", userQuestions },
|
||||
{ "sql_answer", sqlAnswer },
|
||||
});
|
||||
}
|
||||
private async Task<RoleDialogModel> GetAiResponse(Agent agent)
|
||||
{
|
||||
var text = "Generate question and answer pair";
|
||||
var message = new RoleDialogModel(AgentRole.User, text);
|
||||
|
||||
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||
provider: agent.LlmConfig.Provider,
|
||||
model: agent.LlmConfig.Model);
|
||||
|
||||
return await completion.GetChatCompletions(agent, new List<RoleDialogModel> { message });
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,9 @@ public class MemorizeKnowledgeFn : IFunctionCallback
|
|||
{
|
||||
var args = JsonSerializer.Deserialize<ExtractedKnowledge>(message.FunctionArgs ?? "{}");
|
||||
|
||||
var collectionName = _settings.Default.CollectionName ?? KnowledgeCollectionName.BotSharp;
|
||||
var collectionName = !string.IsNullOrEmpty(args.RefinedCollection)
|
||||
? args.RefinedCollection
|
||||
: _settings.Default.CollectionName ?? KnowledgeCollectionName.BotSharp;
|
||||
var knowledgeService = _services.GetRequiredService<IKnowledgeService>();
|
||||
var result = await knowledgeService.CreateVectorCollectionData(collectionName, new VectorCreateModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
You are a knowledge generator 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":"string/sql statement"}].
|
||||
Skip the question/answer for tmp table.
|
||||
Don't include tmp table in the answer.
|
||||
|
||||
=====
|
||||
User Questions:
|
||||
{{ user_questions }}
|
||||
|
||||
=====
|
||||
SQL Answer:
|
||||
{{ sql_answer }}
|
||||
|
|
@ -108,6 +108,42 @@ public partial class MongoRepository
|
|||
_dc.Conversations.UpdateOne(filterConv, updateConv);
|
||||
}
|
||||
|
||||
public bool UpdateConversationMessage(string conversationId, UpdateMessageRequest request)
|
||||
{
|
||||
if (string.IsNullOrEmpty(conversationId)) return false;
|
||||
|
||||
var filter = Builders<ConversationDialogDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var foundDialog = _dc.ConversationDialogs.Find(filter).FirstOrDefault();
|
||||
if (foundDialog == null || foundDialog.Dialogs.IsNullOrEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var dialogs = foundDialog.Dialogs;
|
||||
var candidates = dialogs.Where(x => x.MetaData.MessageId == request.Message.MetaData.MessageId
|
||||
&& x.MetaData.Role == request.Message.MetaData.Role).ToList();
|
||||
|
||||
var found = candidates.Where((_, idx) => idx == request.InnderIndex).FirstOrDefault();
|
||||
if (found == null) return false;
|
||||
|
||||
found.Content = request.Message.Content;
|
||||
found.RichContent = request.Message.RichContent;
|
||||
|
||||
if (!string.IsNullOrEmpty(found.SecondaryContent))
|
||||
{
|
||||
found.SecondaryContent = request.Message.Content;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(found.SecondaryRichContent))
|
||||
{
|
||||
found.SecondaryRichContent = request.Message.RichContent;
|
||||
}
|
||||
|
||||
var update = Builders<ConversationDialogDocument>.Update.Set(x => x.Dialogs, dialogs);
|
||||
_dc.ConversationDialogs.UpdateOne(filter, update);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void UpdateConversationBreakpoint(string conversationId, ConversationBreakpoint breakpoint)
|
||||
{
|
||||
if (string.IsNullOrEmpty(conversationId)) return;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using BotSharp.Plugin.Planner.TwoStaging.Models;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Plugin.Planner.Functions;
|
||||
|
||||
|
|
@ -27,14 +28,18 @@ public class SecondaryStagePlanFn : IFunctionCallback
|
|||
var planPrimary = states.GetState("planning_result");
|
||||
|
||||
var taskSecondary = JsonSerializer.Deserialize<SecondaryBreakdownTask>(msgSecondary.FunctionArgs);
|
||||
|
||||
// Search knowledgebase
|
||||
var knowledges = await knowledgeService.SearchVectorKnowledge(taskSecondary.SolutionQuestion, collectionName, new VectorSearchOptions
|
||||
{
|
||||
Confidence = 0.6f
|
||||
});
|
||||
|
||||
var knowledgeResults = string.Join("\r\n\r\n=====\r\n", knowledges.Select(x => x.ToQuestionAnswer()));
|
||||
// Search knowledgebase
|
||||
var hooks = _services.GetServices<IKnowledgeHook>();
|
||||
var knowledges = new List<string>();
|
||||
foreach (var hook in hooks)
|
||||
{
|
||||
var k = await hook.GetRelevantKnowledges(message, taskSecondary.SolutionQuestion);
|
||||
knowledges.AddRange(k);
|
||||
}
|
||||
knowledges = knowledges.Distinct().ToList();
|
||||
|
||||
var knowledgeResults = string.Join("\r\n\r\n=====\r\n", knowledges);
|
||||
|
||||
// Get second stage planning prompt
|
||||
var currentAgent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
using BotSharp.Abstraction.Planning;
|
||||
using BotSharp.Plugin.Planner.TwoStaging;
|
||||
using BotSharp.Plugin.Planner.TwoStaging.Models;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
|
||||
namespace BotSharp.Plugin.Planner.Functions;
|
||||
|
||||
|
|
@ -54,7 +53,7 @@ public class SummaryPlanFn : IFunctionCallback
|
|||
ddlStatements += "\r\n" + msgCopy.Content;
|
||||
|
||||
// Summarize and generate query
|
||||
var summaryPlanPrompt = await GetSummaryPlanPrompt(taskRequirement, relevantKnowledge, dictionaryItems, ddlStatements, excelImportResult);
|
||||
var summaryPlanPrompt = await GetSummaryPlanPrompt(msgCopy, taskRequirement, relevantKnowledge, dictionaryItems, ddlStatements, excelImportResult);
|
||||
_logger.LogInformation($"Summary plan prompt:\r\n{summaryPlanPrompt}");
|
||||
|
||||
var plannerAgent = new Agent
|
||||
|
|
@ -74,10 +73,11 @@ public class SummaryPlanFn : IFunctionCallback
|
|||
return true;
|
||||
}
|
||||
|
||||
private async Task<string> GetSummaryPlanPrompt(string taskDescription, string relevantKnowledge, string dictionaryItems, string ddlStatement, string excelImportResult)
|
||||
private async Task<string> GetSummaryPlanPrompt(RoleDialogModel message, string taskDescription, string relevantKnowledge, string dictionaryItems, string ddlStatement, string excelImportResult)
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
var knowledgeHooks = _services.GetServices<IKnowledgeHook>();
|
||||
|
||||
var agent = await agentService.GetAgent(BuiltInAgentId.Planner);
|
||||
var template = agent.Templates.FirstOrDefault(x => x.Name == "two_stage.summarize")?.Content ?? string.Empty;
|
||||
|
|
@ -89,10 +89,18 @@ public class SummaryPlanFn : IFunctionCallback
|
|||
additionalRequirements.Add(requirement);
|
||||
});
|
||||
|
||||
var globalKnowledges = new List<string>();
|
||||
foreach (var hook in knowledgeHooks)
|
||||
{
|
||||
var k = await hook.GetGlobalKnowledges(message);
|
||||
globalKnowledges.AddRange(k);
|
||||
}
|
||||
|
||||
return render.Render(template, new Dictionary<string, object>
|
||||
{
|
||||
{ "task_description", taskDescription },
|
||||
{ "summary_requirements", string.Join("\r\n", additionalRequirements) },
|
||||
{ "global_knowledges", globalKnowledges },
|
||||
{ "relevant_knowledges", relevantKnowledge },
|
||||
{ "dictionary_items", dictionaryItems },
|
||||
{ "table_structure", ddlStatement },
|
||||
|
|
|
|||
|
|
@ -2,13 +2,32 @@ namespace BotSharp.Plugin.Planner.Hooks;
|
|||
|
||||
public class PlannerAgentHook : AgentHookBase
|
||||
{
|
||||
public override string SelfId => string.Empty;
|
||||
public override string SelfId => BuiltInAgentId.Planner;
|
||||
|
||||
public PlannerAgentHook(IServiceProvider services, AgentSettings settings)
|
||||
: base(services, settings)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool OnInstructionLoaded(string template, Dictionary<string, object> dict)
|
||||
{
|
||||
var knowledgeHooks = _services.GetServices<IKnowledgeHook>();
|
||||
|
||||
// Get global knowledges
|
||||
var Knowledges = new List<string>();
|
||||
foreach (var hook in knowledgeHooks)
|
||||
{
|
||||
var k = hook.GetGlobalKnowledges(new RoleDialogModel(AgentRole.User, template)
|
||||
{
|
||||
CurrentAgentId = BuiltInAgentId.Planner
|
||||
}).Result;
|
||||
Knowledges.AddRange(k);
|
||||
}
|
||||
dict["global_knowledges"] = Knowledges;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnAgentLoaded(Agent agent)
|
||||
{
|
||||
var conv = _services.GetRequiredService<IConversationService>();
|
||||
|
|
|
|||
|
|
@ -11,9 +11,12 @@ public class FirstStagePlan
|
|||
[JsonPropertyName("step")]
|
||||
public int Step { get; set; } = -1;
|
||||
|
||||
[JsonPropertyName("need_additional_information")]
|
||||
[JsonPropertyName("need_breakdown_task")]
|
||||
public bool NeedAdditionalInformation { get; set; } = false;
|
||||
|
||||
[JsonPropertyName("need_lookup_dictionary")]
|
||||
public bool NeedLookupDictionary { get; set; } = false;
|
||||
|
||||
[JsonPropertyName("related_tables")]
|
||||
public string[] Tables { get; set; } = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ public class SecondStagePlan
|
|||
[JsonPropertyName("related_tables")]
|
||||
public string[] Tables { get; set; } = [];
|
||||
|
||||
[JsonPropertyName("need_lookup_dictionary")]
|
||||
public bool NeedLookupDictionary { get; set; } = false;
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
The user is dealing with a complex problem, and you need to break this complex problem into several small tasks to more easily solve the user's needs.
|
||||
Use the TwoStagePlanner approach to plan the overall implementation steps, follow the below steps strictly.
|
||||
|
||||
1. Call plan_primary_stage to generate the primary plan.
|
||||
2. If need_additional_information is true, call plan_secondary_stage for the specific primary stage.
|
||||
3. Repeat step 2 until you processed all the primary stages.
|
||||
4. If need_lookup_dictionary is true, call sql_dictionary_lookup to verify or get the enum/term/dictionary value. Pull id and name.
|
||||
If you've already got the plan to meet the user goal, directly go to step 5.
|
||||
2. If need_lookup_dictionary is True, call verify_dictionary_term to verify or get the enum/term/dictionary value. Pull id and name.
|
||||
If you no items retured, you can pull all the list and find the match.
|
||||
If need_lookup_dictionary is False, skip calling verify_dictionary_term.
|
||||
3. If need_breakdown_task is true, call plan_secondary_stage for the specific primary stage.
|
||||
4. Repeat step 3 until you processed all the primary stages.
|
||||
5. You must call plan_summary for you final planned output.
|
||||
|
||||
*** IMPORTANT ***
|
||||
|
|
@ -13,6 +17,7 @@ Don't run the planning process repeatedly if you have already got the result of
|
|||
{% if global_knowledges != empty -%}
|
||||
=====
|
||||
Global Knowledge:
|
||||
Current date time is: {{ "now" | date: "%Y-%m-%d %H:%M" }}
|
||||
{% for k in global_knowledges %}
|
||||
{{ k }}
|
||||
{% endfor %}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ Thinking process:
|
|||
1. Reference to "Task Knowledge" if there is relevant knowledge;
|
||||
2. Breakdown task into subtasks.
|
||||
- The subtask should contain all needed parameters for subsequent steps.
|
||||
- If limited information provided and there are furture information needed, or miss relationship between steps, set the need_additional_information to true.
|
||||
- If there is extra knowledge or relationship needed between steps, set the need_additional_information to true for both steps.
|
||||
- If the solution mentioned "related solutions" is needed, set the need_additional_information to true.
|
||||
- You should find the relationships between data structure based on the task knowledge strictly. If lack of information, set the need_additional_information to true.
|
||||
- If you need to lookup the dictionary to verify or get the enum/term/dictionary value, set the need_additional_information to true.
|
||||
- If limited information provided and there are furture information needed, or miss relationship between steps, set the need_breakdown_task to true.
|
||||
- If there is extra knowledge or relationship needed between steps, set the need_breakdown_task to true for both steps.
|
||||
- If the solution mentioned "related solutions" is needed, set the need_breakdown_task to true.
|
||||
- You should find the relationships between data structure based on the task knowledge strictly. If lack of information, set the need_breakdown_task to true.
|
||||
- If you need to lookup the dictionary to verify or get the enum/term/dictionary value, set the need_lookup_dictionary to true.
|
||||
- Seperate the dictionary lookup and need additional information/knowledge into different subtask.
|
||||
3. Input argument must reference to corresponding variable name that retrieved by previous steps, variable name must start with '@';
|
||||
4. Output all the subtasks as much detail as possible in JSON: [{{ response_format }}]
|
||||
5. You can NOT generate the final query before calling function plan_summary.
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@ Reference to "Primary Planning" and the additional knowledge included. Breakdown
|
|||
* The parameters can be extracted from the original task.
|
||||
* You need to list all the steps in detail. Finding relationships should also be a step.
|
||||
* When generate the steps, you should find the relationships between data structure based on the provided knowledge strictly.
|
||||
* If need_lookup_dictionary is true, call sql_dictionary_lookup to verify or get the enum/term/dictionary value. Pull id and name/code.
|
||||
* If need_lookup_dictionary is true, call verify_dictionary_term to verify or get the enum/term/dictionary value. Pull id and name/code.
|
||||
* Output all the steps as much detail as possible in JSON: [{{ response_format }}]
|
||||
|
||||
|
||||
Additional Requirements:
|
||||
* "output_results" is variable name that needed to be used in the next step.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@ Requirements:
|
|||
Task description:
|
||||
{{ task_description }}
|
||||
|
||||
=====
|
||||
Global Knowledges:
|
||||
{{ global_knowledges }}
|
||||
|
||||
=====
|
||||
Relevant Knowledges:
|
||||
{{ relevant_knowledges }}
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
For every primary step, if need_additional_information is true, you have to call plan_secondary_stage to plan the detail steps to complete the primary step.
|
||||
if need_lookup_dictionary is true, you have to call sql_dictionary_lookup to verify or get the enum/term/dictionary value. Pull id and name/code.
|
||||
For every primary step, if need_breakdown_task is true, you have to call plan_secondary_stage to plan the detail steps to complete the primary step.
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\functions\sql_select.json" />
|
||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\instructions\instruction.liquid" />
|
||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\templates\query_result_formatting.liquid" />
|
||||
<None Remove="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\templates\sql_statement_correctness.liquid" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -69,6 +70,9 @@
|
|||
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\sql_executor.fn.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\templates\sql_statement_correctness.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\beda4c12-e1ec-4b4b-b328-3df4a6687c4f\templates\query_result_formatting.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using BotSharp.Abstraction.Agents.Enums;
|
||||
using BotSharp.Abstraction.Routing;
|
||||
using BotSharp.Core.Infrastructures;
|
||||
using BotSharp.Plugin.SqlDriver.Models;
|
||||
using Dapper;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MySqlConnector;
|
||||
|
||||
namespace BotSharp.Plugin.SqlDriver.Functions;
|
||||
|
|
@ -13,31 +15,47 @@ public class ExecuteQueryFn : IFunctionCallback
|
|||
public string Indication => "Performing data retrieval operation.";
|
||||
private readonly SqlDriverSetting _setting;
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public ExecuteQueryFn(IServiceProvider services, SqlDriverSetting setting)
|
||||
public ExecuteQueryFn(IServiceProvider services, SqlDriverSetting setting, ILogger<ExecuteQueryFn> logger)
|
||||
{
|
||||
_services = services;
|
||||
_setting = setting;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
var args = JsonSerializer.Deserialize<ExecuteQueryArgs>(message.FunctionArgs);
|
||||
var settings = _services.GetRequiredService<SqlDriverSetting>();
|
||||
var results = settings.DatabaseType switch
|
||||
{
|
||||
"MySql" => RunQueryInMySql(args.SqlStatements),
|
||||
"SqlServer" => RunQueryInSqlServer(args.SqlStatements),
|
||||
_ => throw new NotImplementedException($"Database type {settings.DatabaseType} is not supported.")
|
||||
};
|
||||
|
||||
if (results.Count() == 0)
|
||||
{
|
||||
message.Content = "No record found";
|
||||
return true;
|
||||
}
|
||||
|
||||
message.Content = JsonSerializer.Serialize(results);
|
||||
var refinedArgs = await RefineSqlStatement(message, args);
|
||||
|
||||
var settings = _services.GetRequiredService<SqlDriverSetting>();
|
||||
|
||||
try
|
||||
{
|
||||
var results = settings.DatabaseType switch
|
||||
{
|
||||
"MySql" => RunQueryInMySql(refinedArgs.SqlStatements),
|
||||
"SqlServer" => RunQueryInSqlServer(refinedArgs.SqlStatements),
|
||||
_ => throw new NotImplementedException($"Database type {settings.DatabaseType} is not supported.")
|
||||
};
|
||||
|
||||
if (results.Count() == 0)
|
||||
{
|
||||
message.Content = "No record found";
|
||||
return true;
|
||||
}
|
||||
|
||||
message.Content = JsonSerializer.Serialize(results);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occurred while executing SQL query.");
|
||||
message.Content = "Error occurred while retrieving information.";
|
||||
message.StopCompletion = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.FormattingResult)
|
||||
{
|
||||
|
|
@ -59,6 +77,7 @@ public class ExecuteQueryFn : IFunctionCallback
|
|||
});
|
||||
|
||||
message.Content = result.Content;
|
||||
message.StopCompletion = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -77,4 +96,54 @@ public class ExecuteQueryFn : IFunctionCallback
|
|||
using var connection = new SqlConnection(settings.SqlServerExecutionConnectionString ?? settings.SqlServerConnectionString);
|
||||
return connection.Query(string.Join("\r\n", sqlTexts));
|
||||
}
|
||||
|
||||
private async Task<ExecuteQueryArgs> RefineSqlStatement(RoleDialogModel message, ExecuteQueryArgs args)
|
||||
{
|
||||
// get table DDL
|
||||
var fn = _services.GetRequiredService<IRoutingService>();
|
||||
var msg = RoleDialogModel.From(message);
|
||||
await fn.InvokeFunction("sql_table_definition", msg);
|
||||
|
||||
// refine SQL
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var currentAgent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
var dictionarySqlPrompt = await GetDictionarySQLPrompt(string.Join("\r\n\r\n", args.SqlStatements), msg.Content);
|
||||
var agent = new Agent
|
||||
{
|
||||
Id = message.CurrentAgentId ?? string.Empty,
|
||||
Name = "sqlDriver_ExecuteQuery",
|
||||
Instruction = dictionarySqlPrompt,
|
||||
TemplateDict = new Dictionary<string, object>(),
|
||||
LlmConfig = currentAgent.LlmConfig
|
||||
};
|
||||
|
||||
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||
provider: agent.LlmConfig.Provider,
|
||||
model: agent.LlmConfig.Model);
|
||||
|
||||
var refinedMessage = await completion.GetChatCompletions(agent, new List<RoleDialogModel>
|
||||
{
|
||||
new RoleDialogModel(AgentRole.User, "Check and output the correct SQL statements")
|
||||
});
|
||||
|
||||
return refinedMessage.Content.JsonContent<ExecuteQueryArgs>();
|
||||
}
|
||||
|
||||
private async Task<string> GetDictionarySQLPrompt(string originalSql, string tableStructure)
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var render = _services.GetRequiredService<ITemplateRender>();
|
||||
var knowledgeHooks = _services.GetServices<IKnowledgeHook>();
|
||||
|
||||
var agent = await agentService.GetAgent(BuiltInAgentId.SqlDriver);
|
||||
var template = agent.Templates.FirstOrDefault(x => x.Name == "sql_statement_correctness")?.Content ?? string.Empty;
|
||||
var responseFormat = JsonSerializer.Serialize(new ExecuteQueryArgs { });
|
||||
|
||||
return render.Render(template, new Dictionary<string, object>
|
||||
{
|
||||
{ "original_sql", originalSql },
|
||||
{ "table_structure", tableStructure },
|
||||
{ "response_format", responseFormat }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace BotSharp.Plugin.SqlDriver.Functions;
|
|||
|
||||
public class LookupDictionaryFn : IFunctionCallback
|
||||
{
|
||||
public string Name => "sql_dictionary_lookup";
|
||||
public string Name => "verify_dictionary_term";
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public LookupDictionaryFn(IServiceProvider services)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public class SqlDictionaryLookupHook : AgentHookBase, IAgentHook
|
|||
private const string SQL_EXECUTOR_TEMPLATE = "sql_dictionary_lookup.fn";
|
||||
private IEnumerable<string> _targetSqlExecutorFunctions = new List<string>
|
||||
{
|
||||
"sql_dictionary_lookup",
|
||||
"verify_dictionary_term",
|
||||
};
|
||||
|
||||
public override string SelfId => BuiltInAgentId.Planner;
|
||||
|
|
|
|||
|
|
@ -33,20 +33,25 @@ public class SqlDriverPlanningHook : IPlanningHook
|
|||
var conv = _services.GetRequiredService<IConversationService>();
|
||||
var wholeDialogs = conv.GetDialogHistory();
|
||||
wholeDialogs.Add(RoleDialogModel.From(msg));
|
||||
wholeDialogs.Add(RoleDialogModel.From(msg, AgentRole.User, "use execute_sql to run query"));
|
||||
|
||||
var agent = await _services.GetRequiredService<IAgentService>().LoadAgent("beda4c12-e1ec-4b4b-b328-3df4a6687c4f");
|
||||
wholeDialogs.Add(RoleDialogModel.From(msg, AgentRole.User, $"call execute_sql to run query, set formatting_result as {settings.FormattingResult}"));
|
||||
|
||||
var agent = await _services.GetRequiredService<IAgentService>().LoadAgent(BuiltInAgentId.SqlDriver);
|
||||
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||
provider: agent.LlmConfig.Provider,
|
||||
model: agent.LlmConfig.Model);
|
||||
|
||||
var response = await completion.GetChatCompletions(agent, wholeDialogs);
|
||||
|
||||
// Invoke "execute_sql"
|
||||
var routing = _services.GetRequiredService<IRoutingService>();
|
||||
await routing.InvokeFunction(response.FunctionName, response);
|
||||
msg.CurrentAgentId = agent.Id;
|
||||
msg.FunctionName = response.FunctionName;
|
||||
msg.FunctionArgs = response.FunctionArgs;
|
||||
msg.Content = response.Content;
|
||||
msg.StopCompletion = response.StopCompletion;
|
||||
|
||||
/*var routing = _services.GetRequiredService<IRoutingService>();
|
||||
await routing.InvokeAgent(BuiltInAgentId.SqlDriver, wholeDialogs);*/
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,12 @@ public class ExecuteQueryArgs
|
|||
[JsonPropertyName("sql_statements")]
|
||||
public string[] SqlStatements { get; set; } = [];
|
||||
|
||||
[JsonPropertyName("tables")]
|
||||
public string[] Tables { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Beautifying query result
|
||||
/// </summary>
|
||||
[JsonPropertyName("formatting_result")]
|
||||
public bool FormattingResult { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,4 +10,5 @@ public class SqlDriverSetting
|
|||
public string SqlServerExecutionConnectionString { get; set; } = null!;
|
||||
public string SqlLiteConnectionString { get; set; } = null!;
|
||||
public bool ExecuteSqlSelectAutonomous { get; set; } = false;
|
||||
public bool FormattingResult { get; set; } = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "sql_dictionary_lookup",
|
||||
"name": "verify_dictionary_term",
|
||||
"description": "Get id from dictionary table by keyword if tool or solution mentioned this approach",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"description": "the reason why you need to call sql_dictionary_lookup"
|
||||
"description": "the reason why you need to call verify_dictionary_term"
|
||||
},
|
||||
"tables": {
|
||||
"type": "array",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
Dictionary Lookup Rules:
|
||||
Dictionary Verification Rules:
|
||||
=====
|
||||
Please call function sql_dictionary_lookup if user wants to get or retrieve dictionary/enum/term from data tables.
|
||||
You must return the id and name/code. The table name must come from the planning in conversation.
|
||||
1. The table name must come from the planning in conversation.
|
||||
2. You must return the id and name/code.
|
||||
|
||||
You are connecting to {{ db_type }} database. You can run provided SQL statements by following {{ db_type }} rules.
|
||||
Dictionary table pattern is table name starting with "data_". You can only query the dictionary table without join other non-dictionary tables.
|
||||
|
||||
The dictionary table is identified by a name that begins with "data_". You are only allowed to query the dictionary table without joining it with other non-dictionary tables.
|
||||
|
||||
IMPORTANT: Don't generate insert SQL.
|
||||
=====
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
"profiles": [ "database" ],
|
||||
"llmConfig": {
|
||||
"provider": "openai",
|
||||
"model": "gpt-4o-mini"
|
||||
"model": "gpt-4o"
|
||||
},
|
||||
"routingRules": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,8 +11,22 @@
|
|||
"type": "string",
|
||||
"description": "sql statement"
|
||||
}
|
||||
},
|
||||
|
||||
"formatting_result": {
|
||||
"type": "boolean",
|
||||
"description": "formatting the results"
|
||||
},
|
||||
|
||||
"tables": {
|
||||
"type": "array",
|
||||
"description": "all related tables",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"description": "table name"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [ "sql_statement" ]
|
||||
"required": [ "sql_statement", "tables", "formatting_result" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1,5 @@
|
|||
Output in human readable format. If there is large amount of information, shape it in tabular.
|
||||
Output in human readable format. If there is large amount of rows, shape it in tabular, otherwise, output in plain text.
|
||||
Put user task description in the first line in the same language, for example, user is using Chinese, you have to output the result in Chinese.
|
||||
|
||||
User Task Description:
|
||||
{{ requirement_detail }}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
You are a sql statement corrector. You will need to refer to the table structure and rewrite the original sql statement so it's using the correct information, e.g. column name.
|
||||
Output the sql statement only without comments, in JSON format: {{ response_format }}
|
||||
Make sure all the column names are defined in the Table Structure.
|
||||
|
||||
=====
|
||||
Original SQL statements:
|
||||
{{ original_sql }}
|
||||
|
||||
=====
|
||||
Table Structure:
|
||||
{{ table_structure }}
|
||||
Loading…
Reference in a new issue