diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs index 2aa8a72fc..c8b997ec7 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs @@ -55,5 +55,5 @@ Task SendMessage(string agentId, /// Task UpdateBreakpoint(bool resetStates = false, string? reason = null, params string[] excludedStates); - Task GetConversationSummary(string conversationId); + Task GetConversationSummary(IEnumerable conversationId); } diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs index 25d754d66..533020f0e 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs @@ -5,31 +5,51 @@ namespace BotSharp.Core.Conversations.Services; public partial class ConversationService { - public async Task GetConversationSummary(string conversationId) + public async Task GetConversationSummary(IEnumerable conversationIds) { - if (string.IsNullOrEmpty(conversationId)) return string.Empty; + if (conversationIds.IsNullOrEmpty()) return string.Empty; var routing = _services.GetRequiredService(); var agentService = _services.GetRequiredService(); - var dialogs = _storage.GetDialogs(conversationId); - if (dialogs.IsNullOrEmpty()) return string.Empty; + var contents = new List(); + foreach ( var conversationId in conversationIds) + { + if (string.IsNullOrEmpty(conversationId)) continue; + + var dialogs = _storage.GetDialogs(conversationId); + + if (dialogs.IsNullOrEmpty()) continue; + + var content = GetConversationContent(dialogs); + contents.Add(content); + } var router = await agentService.LoadAgent(AIAssistant); - var prompt = GetPrompt(router); - var summary = await Summarize(router, prompt, dialogs); + var prompt = GetPrompt(router, contents); + var summary = await Summarize(router, prompt); return summary; } - private string GetPrompt(Agent agent) + private string GetPrompt(Agent agent, List contents) { var template = agent.Templates.First(x => x.Name == "conversation.summary").Content; var render = _services.GetRequiredService(); - return render.Render(template, new Dictionary { }); + + var texts = string.Empty; + for (int i = 0; i < contents.Count; i++) + { + texts += $"[Conversation {i+1}]\r\n{contents[i]}"; + } + + return render.Render(template, new Dictionary + { + { "texts", texts } + }); } - private async Task Summarize(Agent agent, string prompt, List dialogs) + private async Task Summarize(Agent agent, string prompt) { var provider = "openai"; string? model; @@ -60,8 +80,29 @@ private async Task Summarize(Agent agent, string prompt, List + { + new RoleDialogModel(AgentRole.User, "Please summarize the conversations.") + }); return response.Content; } + + private string GetConversationContent(List dialogs, int maxDialogCount = 50) + { + var conversation = ""; + + foreach (var dialog in dialogs.TakeLast(maxDialogCount)) + { + var role = dialog.Role; + if (role != AgentRole.User) + { + role = AgentRole.Assistant; + } + + conversation += $"{role}: {dialog.Payload ?? dialog.Content}\r\n"; + } + + return conversation + "\r\n"; + } } diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/conversation.summary.liquid b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/conversation.summary.liquid index e2ffe5db1..bb4e764fb 100644 --- a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/conversation.summary.liquid +++ b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/conversation.summary.liquid @@ -1,8 +1,14 @@ -Please summarize the conversation. +Please read each conversation in the [CONVERSATIONS] section and provide a summary. -*** Super Important! Please consider the entire conversation. Do not only consider the recent sentences. *** +*** Super Important! Please consider every conversation. Do not only consider the recent sentences. *** ** Please do not respond to the latest conversation. -** If there are different topics in the conversation, please summarize each topic in different sentences and list them with bullets. +** If there are different topics in the conversations, please summarize each topic in different sentences and list them in bullets. * Please use concise sentences to summarize each topic. * Please do not include excessive details in the summaries. -* Please use 'user' instead of 'you', 'he' or 'she'. \ No newline at end of file +* Please use 'user' instead of 'you', 'he' or 'she'. + +[CONVERSATIONS] + +{% for text in texts -%} +{{ text }}{{ "\r\n" }} +{%- endfor %} \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs index a2c2b3b06..adc37636a 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs @@ -152,11 +152,11 @@ public async Task> GetDialogs([FromRoute] string return result; } - [HttpGet("/conversation/{conversationId}/summary")] - public async Task GetConversationSummary([FromRoute] string conversationId) + [HttpPost("/conversation/summary")] + public async Task GetConversationSummary([FromBody] ConversationSummaryModel input) { var service = _services.GetRequiredService(); - return await service.GetConversationSummary(conversationId); + return await service.GetConversationSummary(input.ConversationIds); } [HttpGet("/conversation/{conversationId}/user")] diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationSummaryModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationSummaryModel.cs new file mode 100644 index 000000000..0854ab2af --- /dev/null +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationSummaryModel.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +namespace BotSharp.OpenAPI.ViewModels.Conversations; + +public class ConversationSummaryModel +{ + [JsonPropertyName("conversation_ids")] + public List ConversationIds { get; set; } = new List(); +}