Fix issue of duplicate funcation call.

This commit is contained in:
Haiping Chen 2024-02-20 22:31:09 -06:00
parent 5e1f5c0843
commit 3328692eac
9 changed files with 37 additions and 73 deletions

View file

@ -231,6 +231,10 @@ public class ChatCompletionProvider : IChatCompletion
{
if (message.Role == ChatRole.Function)
{
chatCompletionsOptions.Messages.Add(new ChatRequestAssistantMessage(string.Empty)
{
FunctionCall = new FunctionCall(message.FunctionName, message.FunctionArgs),
});
chatCompletionsOptions.Messages.Add(new ChatRequestFunctionMessage(message.FunctionName, message.Content));
}
else if (message.Role == ChatRole.User)
@ -287,7 +291,7 @@ public class ChatCompletionProvider : IChatCompletion
if (x.Role == ChatRole.Function)
{
var m = x as ChatRequestFunctionMessage;
return $"{m.Role}: {m.Name} => {m.Content}";
return $"{m.Role}: {m.Content}";
}
else if (x.Role == ChatRole.User)
{
@ -299,7 +303,9 @@ public class ChatCompletionProvider : IChatCompletion
else if (x.Role == ChatRole.Assistant)
{
var m = x as ChatRequestAssistantMessage;
return $"{m.Role}: {m.Content}";
return m.FunctionCall != null ?
$"{m.Role}: Call function {m.FunctionCall.Name}({m.FunctionCall.Arguments})" :
$"{m.Role}: {m.Content}";
}
else
{

View file

@ -18,11 +18,16 @@ public class SqlInsertFn : IFunctionCallback
var sqlDriver = _services.GetRequiredService<SqlDriverService>();
if (sqlDriver.Statements.Exists(x => x.Statement == args.Statement))
{
message.Content = "Skipped duplicated statement.";
return false;
var p1 = string.Join(", ", sqlDriver.Statements.Last().Parameters.OrderBy(x => x.Name).Select(x => x.Value));
var p2 = string.Join(", ", args.Parameters.OrderBy(x => x.Name).Select(x => x.Value));
if (p1 == p2)
{
message.Content = "Skipped duplicated statement.";
return false;
}
}
sqlDriver.Enqueue(args);
message.Content = $"Inserted new record {JsonSerializer.Serialize(args.Parameters)} successfully";
message.Content = $"Inserted new record successfully.";
if (args.Return != null)
{
/*sqlDriver.Enqueue(new SqlStatement

View file

@ -17,6 +17,8 @@ public class SqlSelect : IFunctionCallback
public async Task<bool> Execute(RoleDialogModel message)
{
var args = JsonSerializer.Deserialize<SqlStatement>(message.FunctionArgs);
var sqlDriver = _services.GetRequiredService<SqlDriverService>();
// check if need to instantely
var execNow = !args.Parameters.Any(x => x.Value.StartsWith("@"));
if (execNow)
@ -30,20 +32,11 @@ public class SqlSelect : IFunctionCallback
}
var result = connection.QueryFirst<string>(args.Statement, dictionary);
if (args.IsCheckExistence)
{
message.Content = result == null ?
$"The record does not exist" :
$"The record already exists";
}
else
{
message.Content = $"Retrieved result is {result} ({args.Reason})";
}
sqlDriver.Enqueue(args);
message.Content = $"Retrieved data is: {result}";
}
else
{
var sqlDriver = _services.GetRequiredService<SqlDriverService>();
sqlDriver.Enqueue(args);
message.Content = $"Success.";
}

View file

@ -1,32 +0,0 @@
using BotSharp.Abstraction.Loggers;
using BotSharp.Abstraction.Repositories;
using System.IO;
namespace BotSharp.Plugin.SqlDriver.Hooks;
public class SqlDriverContentGeneratingHook : IContentGeneratingHook
{
private readonly IServiceProvider _services;
public SqlDriverContentGeneratingHook(IServiceProvider services)
{
_services = services;
}
/// <summary>
/// Inject useful variables generated by previous SQL query.
/// </summary>
/// <param name="agent"></param>
/// <param name="conversations"></param>
/// <returns></returns>
public async Task BeforeGenerating(Agent agent, List<RoleDialogModel> conversations)
{
if (agent.Id != "beda4c12-e1ec-4b4b-b328-3df4a6687c4f")
{
return;
}
var sqlDriver = _services.GetRequiredService<SqlDriverService>();
agent.TemplateDict["return_variables"] = sqlDriver.Statements.Select(x => x.Return.Alias).ToArray();
await Task.CompletedTask;
}
}

View file

@ -13,9 +13,6 @@ public class SqlStatement
[JsonPropertyName("table")]
public string Table { get; set; }
[JsonPropertyName("is_check_existence")]
public bool IsCheckExistence { get; set; }
[JsonPropertyName("parameters")]
public SqlParamater[] Parameters { get; set; } = new SqlParamater[0];

View file

@ -1,5 +1,3 @@
using BotSharp.Abstraction.Loggers;
namespace BotSharp.Plugin.SqlDriver;
public class SqlDriverPlugin : IBotSharpPlugin
@ -19,6 +17,5 @@ public class SqlDriverPlugin : IBotSharpPlugin
services.AddScoped<SqlDriverService>();
services.AddScoped<IKnowledgeHook, SqlDriverKnowledgeHook>();
services.AddScoped<IContentGeneratingHook, SqlDriverContentGeneratingHook>();
}
}

View file

@ -9,6 +9,7 @@
"isPublic": true,
"profiles": [ "tool", "sql" ],
"llmConfig": {
"max_recursion_depth": 10
"model": "gpt-4-0125",
"max_recursion_depth": 5
}
}

View file

@ -13,6 +13,10 @@
"type": "string",
"description": "reason"
},
"table": {
"type": "string",
"description": "related table"
},
"parameters": {
"type": "array",
"description": "parameters for the sql",
@ -46,7 +50,7 @@
}
}
},
"required": [ "sql_statement", "reason", "parameters", "return_field" ]
"required": [ "sql_statement", "reason", "table", "parameters", "return_field" ]
}
},
{
@ -63,9 +67,9 @@
"type": "string",
"description": "reason"
},
"is_check_existence": {
"type": "boolean",
"description": "check record existence"
"table": {
"type": "string",
"description": "related table"
},
"parameters": {
"type": "array",
@ -100,7 +104,7 @@
}
}
},
"required": [ "sql_statement", "reason", "is_check_existence", "parameters", "return_field" ]
"required": [ "sql_statement", "reason", "table", "parameters", "return_field" ]
}
}
]

View file

@ -1,22 +1,15 @@
You're a SQL driver who knows how to translate text into SQL query.
Analyze the user requirement, think step by step, breakdown complex task into multiple steps.
Think step by step, analyze the user requirement and provided information, output the next step.
Your response must meet below requirements:
* Walk through the provided information, don't run query if there is already related information;
* DO NOT generate duplicated sql statements;
* The return field alias should be meaningful, it can be similar name of reference table column;
* Double check if the fields in the SQL query are correct;
* Make sure the SELECT and WHERE fields are in corresponding table schema definition;
* Use "Unique Index" to help check record existence;
{% if return_variables and return_variables != empty -%}
{% if tables_definition -%}
=====
Below variables can be used by subsequent SQL:
{% for v in return_variables %}
- @{{ v }}
{% endfor %}
{%- endif %}
{% if table_definition -%}
=====
Related table {{ related_table }} definition:
{{ table_definition }}
Related tables definition:
{{ tables_definition }}
{%- endif %}