Change interface GetAgentResponses.

This commit is contained in:
Haiping Chen 2023-09-09 15:13:19 -05:00
parent 5f27c9c93c
commit de82fac8e2
17 changed files with 73 additions and 57 deletions

View file

@ -55,7 +55,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.RoutingSpee
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RAGs", "RAGs", "{4F346DCE-087F-4368-AF88-EE9C720D0E69}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RAGs", "RAGs", "{4F346DCE-087F-4368-AF88-EE9C720D0E69}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.KnowledgeBase", "src\Plugins\BotSharp.Plugin.KnowledgeBase\BotSharp.Plugin.KnowledgeBase.csproj", "{298AC787-A104-414C-B114-82BE764FBD9C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.KnowledgeBase", "src\Plugins\BotSharp.Plugin.KnowledgeBase\BotSharp.Plugin.KnowledgeBase.csproj", "{298AC787-A104-414C-B114-82BE764FBD9C}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DataStorages", "DataStorages", "{5CD330E1-9E5A-4112-8346-6E31CA98EF78}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DataStorages", "DataStorages", "{5CD330E1-9E5A-4112-8346-6E31CA98EF78}"
EndProject EndProject
@ -205,6 +205,14 @@ Global
{298AC787-A104-414C-B114-82BE764FBD9C}.Release|Any CPU.Build.0 = Release|Any CPU {298AC787-A104-414C-B114-82BE764FBD9C}.Release|Any CPU.Build.0 = Release|Any CPU
{298AC787-A104-414C-B114-82BE764FBD9C}.Release|x64.ActiveCfg = Release|Any CPU {298AC787-A104-414C-B114-82BE764FBD9C}.Release|x64.ActiveCfg = Release|Any CPU
{298AC787-A104-414C-B114-82BE764FBD9C}.Release|x64.Build.0 = Release|Any CPU {298AC787-A104-414C-B114-82BE764FBD9C}.Release|x64.Build.0 = Release|Any CPU
{DB3DE37B-1208-4ED3-9615-A52AD0AAD69C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB3DE37B-1208-4ED3-9615-A52AD0AAD69C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB3DE37B-1208-4ED3-9615-A52AD0AAD69C}.Debug|x64.ActiveCfg = Debug|Any CPU
{DB3DE37B-1208-4ED3-9615-A52AD0AAD69C}.Debug|x64.Build.0 = Debug|Any CPU
{DB3DE37B-1208-4ED3-9615-A52AD0AAD69C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB3DE37B-1208-4ED3-9615-A52AD0AAD69C}.Release|Any CPU.Build.0 = Release|Any CPU
{DB3DE37B-1208-4ED3-9615-A52AD0AAD69C}.Release|x64.ActiveCfg = Release|Any CPU
{DB3DE37B-1208-4ED3-9615-A52AD0AAD69C}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -233,6 +241,7 @@ Global
{631D9C12-86C4-44F0-99C3-D32C0754BF37} = {51AFE054-AE99-497D-A593-69BAEFB5106F} {631D9C12-86C4-44F0-99C3-D32C0754BF37} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
{4F346DCE-087F-4368-AF88-EE9C720D0E69} = {2635EC9B-2E5F-4313-AC21-0B847F31F36C} {4F346DCE-087F-4368-AF88-EE9C720D0E69} = {2635EC9B-2E5F-4313-AC21-0B847F31F36C}
{298AC787-A104-414C-B114-82BE764FBD9C} = {4F346DCE-087F-4368-AF88-EE9C720D0E69} {298AC787-A104-414C-B114-82BE764FBD9C} = {4F346DCE-087F-4368-AF88-EE9C720D0E69}
{DB3DE37B-1208-4ED3-9615-A52AD0AAD69C} = {5CD330E1-9E5A-4112-8346-6E31CA98EF78}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19} SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19}

View file

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<LangVersion>10.0</LangVersion> <LangVersion>10.0</LangVersion>
<OutputPath>..\..\..\packages</OutputPath> <OutputPath>..\..\..\packages</OutputPath>
<PackageVersion>0.11.0</PackageVersion> <PackageVersion>0.12.0</PackageVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View file

@ -3,6 +3,6 @@ namespace BotSharp.Abstraction.Conversations;
public interface IConversationStorage public interface IConversationStorage
{ {
void InitStorage(string conversationId); void InitStorage(string conversationId);
void Append(string conversationId, string agentId, RoleDialogModel dialog); void Append(string conversationId, RoleDialogModel dialog);
List<RoleDialogModel> GetDialogs(string conversationId); List<RoleDialogModel> GetDialogs(string conversationId);
} }

View file

@ -26,7 +26,7 @@ public interface IBotSharpRepository
void DeleteRoutingProfiles(); void DeleteRoutingProfiles();
Agent GetAgent(string agentId); Agent GetAgent(string agentId);
List<string> GetAgentResponses(string agentId); List<string> GetAgentResponses(string agentId, string prefix, string intent);
void CreateNewConversation(Conversation conversation); void CreateNewConversation(Conversation conversation);
string GetConversationDialog(string conversationId); string GetConversationDialog(string conversationId);

View file

@ -11,8 +11,8 @@ public class RetrievalArgs : RoutingArgs
[JsonPropertyName("answer")] [JsonPropertyName("answer")]
public string Answer { get; set; } public string Answer { get; set; }
[JsonPropertyName("response")] [JsonPropertyName("reason")]
public string Response { get; set; } public string Reason { get; set; }
[JsonPropertyName("args")] [JsonPropertyName("args")]
public JsonDocument Arguments { get; set; } public JsonDocument Arguments { get; set; }

View file

@ -29,26 +29,18 @@ public partial class ConversationService
text = latestResponse.Content.Split("=>").Last(); text = latestResponse.Content.Split("=>").Last();
} }
var msg = new RoleDialogModel(AgentRole.Assistant, text) await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, text)
{ {
CurrentAgentId = agent.Id, CurrentAgentId = agent.Id,
Channel = wholeDialogs.Last().Channel Channel = wholeDialogs.Last().Channel
}; }, onMessageReceived);
await HandleAssistantMessage(msg, onMessageReceived);
// Add to dialog history
_storage.Append(_conversationId, agent.Id, msg);
return false; return false;
} }
var result = await chatCompletion.GetChatCompletionsAsync(agent, wholeDialogs, async msg => var result = await chatCompletion.GetChatCompletionsAsync(agent, wholeDialogs, async msg =>
{ {
await HandleAssistantMessage(msg, onMessageReceived); await HandleAssistantMessage(agent, msg, onMessageReceived);
// Add to dialog history
_storage.Append(_conversationId, agent.Id, msg);
}, async fn => }, async fn =>
{ {
var preAgentId = agent.Id; var preAgentId = agent.Id;
@ -58,26 +50,24 @@ public partial class ConversationService
// Function executed has exception // Function executed has exception
if (fn.ExecutionResult == null) if (fn.ExecutionResult == null)
{ {
await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, fn.Content) await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, fn.Content)
{ {
CurrentAgentId = fn.CurrentAgentId, CurrentAgentId = fn.CurrentAgentId,
Channel = fn.Channel Channel = fn.Channel
}, onMessageReceived); }, onMessageReceived);
return; return;
} }
else if (fn.StopCompletion) else if (fn.StopCompletion)
{ {
var message = new RoleDialogModel(AgentRole.Assistant, fn.Content) await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, fn.Content)
{ {
CurrentAgentId = fn.CurrentAgentId, CurrentAgentId = fn.CurrentAgentId,
Channel = fn.Channel, Channel = fn.Channel,
ExecutionData = fn.ExecutionData, ExecutionData = fn.ExecutionData,
ExecutionResult = fn.ExecutionResult ExecutionResult = fn.ExecutionResult
}; }, onMessageReceived);
await HandleAssistantMessage(message, onMessageReceived);
_storage.Append(_conversationId, agent.Id, message);
return; return;
} }
@ -104,7 +94,7 @@ public partial class ConversationService
var response = await templateService.RenderFunctionResponse(agent.Id, fn); var response = await templateService.RenderFunctionResponse(agent.Id, fn);
if (!string.IsNullOrEmpty(response)) if (!string.IsNullOrEmpty(response))
{ {
await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, response) await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, response)
{ {
CurrentAgentId = agent.Id, CurrentAgentId = agent.Id,
Channel = wholeDialogs.Last().Channel Channel = wholeDialogs.Last().Channel
@ -131,17 +121,22 @@ public partial class ConversationService
return result; return result;
} }
private async Task HandleAssistantMessage(RoleDialogModel msg, Func<RoleDialogModel, Task> onMessageReceived) private async Task HandleAssistantMessage(Agent agent, RoleDialogModel message, Func<RoleDialogModel, Task> onMessageReceived)
{ {
var hooks = _services.GetServices<IConversationHook>().ToList(); var hooks = _services.GetServices<IConversationHook>().ToList();
// After chat completion hook // After chat completion hook
foreach (var hook in hooks) foreach (var hook in hooks)
{ {
await hook.AfterCompletion(msg); await hook.AfterCompletion(message);
} }
await onMessageReceived(msg); _logger.LogInformation($"[{agent.Name}] {message.Role}: {message.Content}");
await onMessageReceived(message);
// Add to dialog history
_storage.Append(_conversationId, message);
} }
private async Task HandleFunctionMessage(RoleDialogModel msg, private async Task HandleFunctionMessage(RoleDialogModel msg,

View file

@ -25,7 +25,7 @@ public partial class ConversationService
var wholeDialogs = GetDialogHistory(); var wholeDialogs = GetDialogHistory();
wholeDialogs.Add(lastDialog); wholeDialogs.Add(lastDialog);
_storage.Append(_conversationId, agent.Id, lastDialog); _storage.Append(_conversationId, lastDialog);
var hooks = _services.GetServices<IConversationHook>().ToList(); var hooks = _services.GetServices<IConversationHook>().ToList();
@ -43,7 +43,7 @@ public partial class ConversationService
{ {
var response = new RoleDialogModel(AgentRole.Assistant, lastDialog.Content); var response = new RoleDialogModel(AgentRole.Assistant, lastDialog.Content);
await onMessageReceived(response); await onMessageReceived(response);
_storage.Append(_conversationId, agent.Id, response); _storage.Append(_conversationId, response);
return true; return true;
} }
} }
@ -57,20 +57,22 @@ public partial class ConversationService
if (reasonedContext.FunctionName == "interrupt_task_execution") if (reasonedContext.FunctionName == "interrupt_task_execution")
{ {
await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, reasonedContext.Content) await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, reasonedContext.Content)
{ {
CurrentAgentId = agent.Id, CurrentAgentId = agent.Id,
Channel = lastDialog.Channel Channel = lastDialog.Channel
}, onMessageReceived); }, onMessageReceived);
return true; return true;
} }
else if (reasonedContext.FunctionName == "response_to_user") else if (reasonedContext.FunctionName == "response_to_user")
{ {
await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, reasonedContext.Content) await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, reasonedContext.Content)
{ {
CurrentAgentId = agent.Id, CurrentAgentId = agent.Id,
Channel = lastDialog.Channel Channel = lastDialog.Channel
}, onMessageReceived); }, onMessageReceived);
return true; return true;
} }
else if (reasonedContext.FunctionName == "continue_execute_task") else if (reasonedContext.FunctionName == "continue_execute_task")
@ -86,7 +88,7 @@ public partial class ConversationService
wholeDialogs.Add(x); wholeDialogs.Add(x);
if (x.Content != null) if (x.Content != null)
{ {
_storage.Append(_conversationId, agent.Id, x); _storage.Append(_conversationId, x);
} }
}); });
} }

View file

@ -22,8 +22,9 @@ public class ConversationStorage : IConversationStorage
_user = user; _user = user;
} }
public void Append(string conversationId, string agentId, RoleDialogModel dialog) public void Append(string conversationId, RoleDialogModel dialog)
{ {
var agentId = dialog.CurrentAgentId;
var db = _services.GetRequiredService<IBotSharpRepository>(); var db = _services.GetRequiredService<IBotSharpRepository>();
var dialogText = db.GetConversationDialog(conversationId); var dialogText = db.GetConversationDialog(conversationId);
var sb = new StringBuilder(dialogText); var sb = new StringBuilder(dialogText);

View file

@ -108,7 +108,7 @@ public class BotSharpDbContext : Database, IBotSharpRepository
throw new NotImplementedException(); throw new NotImplementedException();
} }
public List<string> GetAgentResponses(string agentId) public List<string> GetAgentResponses(string agentId, string prefix, string intent)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

View file

@ -338,7 +338,10 @@ public class FileRepository : IBotSharpRepository
throw new NotImplementedException(); throw new NotImplementedException();
} }
public List<string> GetAgentResponses(string agentId) #if !DEBUG
[MemoryCache(10 * 60)]
#endif
public List<string> GetAgentResponses(string agentId, string prefix, string intent)
{ {
var responses = new List<string>(); var responses = new List<string>();
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, "responses"); var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, "responses");
@ -346,7 +349,12 @@ public class FileRepository : IBotSharpRepository
foreach (var file in Directory.GetFiles(dir)) foreach (var file in Directory.GetFiles(dir))
{ {
responses.Add(File.ReadAllText(file)); if (file.Split(Path.DirectorySeparatorChar)
.Last()
.StartsWith(prefix + "." + intent))
{
responses.Add(File.ReadAllText(file));
}
} }
return responses; return responses;

View file

@ -45,8 +45,8 @@ public class Simulator
} }
else if (args.Function == "interrupt_task_execution") else if (args.Function == "interrupt_task_execution")
{ {
response.Content = args.Parameters.Response; response.Content = args.Parameters.Reason;
response.ExecutionResult = args.Parameters.Response; response.ExecutionResult = args.Parameters.Reason;
} }
else if (args.Function == "response_to_user") else if (args.Function == "response_to_user")
{ {

View file

@ -26,7 +26,7 @@ public class ResponseTemplateService : IResponseTemplateService
// .ToList(); // .ToList();
var db = _services.GetRequiredService<IBotSharpRepository>(); var db = _services.GetRequiredService<IBotSharpRepository>();
var responses = db.GetAgentResponses(agentId); var responses = db.GetAgentResponses(agentId, "func", message.FunctionName);
if (responses.Count == 0) if (responses.Count == 0)
{ {
@ -71,7 +71,7 @@ public class ResponseTemplateService : IResponseTemplateService
// .ToList(); // .ToList();
var db = _services.GetRequiredService<IBotSharpRepository>(); var db = _services.GetRequiredService<IBotSharpRepository>();
var responses = db.GetAgentResponses(agentId); var responses = db.GetAgentResponses(agentId, "intent", message.IntentName);
if (responses.Count == 0) if (responses.Count == 0)
{ {

View file

@ -451,13 +451,14 @@ public class MongoRepository : IBotSharpRepository
}).ToList(); }).ToList();
} }
public List<string> GetAgentResponses(string agentId) public List<string> GetAgentResponses(string agentId, string prefix, string intent)
{ {
var responses = new List<string>(); var responses = new List<string>();
var agent = Agents.FirstOrDefault(x => x.Id == agentId); var agent = Agents.FirstOrDefault(x => x.Id == agentId);
if (agent == null) return responses; if (agent == null) return responses;
return agent.Responses; // Should use name to filter by prefix
return agent.Responses.Where(x => x.StartsWith(prefix + "." + intent)).ToList();
} }
public Agent GetAgent(string agentId) public Agent GetAgent(string agentId)

View file

@ -32,6 +32,11 @@ public class RoutingConversationHook: ConversationHookBase
// Utilize local discriminative model to predict intent // Utilize local discriminative model to predict intent
var predText = intentClassifier.Predict(vector); var predText = intentClassifier.Predict(vector);
if (string.IsNullOrEmpty(predText))
{
return;
}
message.IntentName = predText; message.IntentName = predText;
// Render by template // Render by template

View file

@ -42,11 +42,6 @@ builder.Services.AddScoped<IUserIdentity, UserIdentity>();
// Add BotSharp // Add BotSharp
builder.Services.AddBotSharp(builder.Configuration); builder.Services.AddBotSharp(builder.Configuration);
// Change below if you want to use other data storage.
// builder.Services.UsingSqlServer(builder.Configuration);
// Default is using File Storage
//builder.Services.UsingFileRepository(builder.Configuration);
builder.Services.AddCors(options => builder.Services.AddCors(options =>
{ {
options.AddPolicy("MyCorsPolicy", options.AddPolicy("MyCorsPolicy",

View file

@ -86,15 +86,15 @@
"WeixinAppSecret": "#{WeixinAppSecret}#" "WeixinAppSecret": "#{WeixinAppSecret}#"
}, },
"KnowledgeBase": { "KnowledgeBase": {
"VectorDb": "MemVectorDatabase", "VectorDb": "MemVectorDatabase",
// "VectorDb": "QdrantDb", // "VectorDb": "QdrantDb",
"TextEmbedding": "fastTextEmbeddingProvider", "TextEmbedding": "fastTextEmbeddingProvider",
// "TextEmbedding": "LLamaSharp.TextEmbeddingProvider", // "TextEmbedding": "LLamaSharp.TextEmbeddingProvider",
"TextCompletion": "AzureOpenAI.Providers.TextCompletionProvider", "TextCompletion": "AzureOpenAI.Providers.TextCompletionProvider",
// "TextCompletion": "LLamaSharp.TextCompletionProvider", // "TextCompletion": "LLamaSharp.TextCompletionProvider",
"Pdf2TextConverter": "PaddleSharp.Providers.Pdf2TextConverter" "Pdf2TextConverter": "PaddleSharp.Providers.Pdf2TextConverter"
}, },
"PluginLoader": { "PluginLoader": {
"Assemblies": [ "Assemblies": [

View file

@ -10,7 +10,7 @@ public class GetPizzaPricesFn : IFunctionCallback
{ {
message.ExecutionData = new message.ExecutionData = new
{ {
cheese = "3.5" cheese_unit_price = "$3.5"
}; };
message.ExecutionResult = "Pepperoni Pizza: $3.5/slice, Cheese Pizza: $2.5/slice, Margherita Pizza: $3.0/slice"; message.ExecutionResult = "Pepperoni Pizza: $3.5/slice, Cheese Pizza: $2.5/slice, Margherita Pizza: $3.0/slice";
return true; return true;