diff --git a/BotSharp.sln b/BotSharp.sln index bf96d2a9..63a3d6a0 100644 --- a/BotSharp.sln +++ b/BotSharp.sln @@ -241,6 +241,7 @@ Global {631D9C12-86C4-44F0-99C3-D32C0754BF37} = {51AFE054-AE99-497D-A593-69BAEFB5106F} {4F346DCE-087F-4368-AF88-EE9C720D0E69} = {2635EC9B-2E5F-4313-AC21-0B847F31F36C} {298AC787-A104-414C-B114-82BE764FBD9C} = {4F346DCE-087F-4368-AF88-EE9C720D0E69} + {5CD330E1-9E5A-4112-8346-6E31CA98EF78} = {2635EC9B-2E5F-4313-AC21-0B847F31F36C} {DB3DE37B-1208-4ED3-9615-A52AD0AAD69C} = {5CD330E1-9E5A-4112-8346-6E31CA98EF78} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/Directory.Build.props b/Directory.Build.props index de3640e4..a61058f4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ 10.0 ..\..\..\packages - 0.12.0 + 0.12.1 true \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs index a0171a85..a6982088 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs @@ -4,7 +4,7 @@ public interface IConversationService { IConversationStateService States { get; } Task NewConversation(Conversation conversation); - void SetConversationId(string conversationId, string channel); + void SetConversationId(string conversationId, List states); Task GetConversation(string id); Task> GetConversations(); Task DeleteConversation(string id); diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs index 72dc54f2..b28d662d 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs @@ -6,7 +6,7 @@ namespace BotSharp.Abstraction.Conversations; public interface IConversationStateService { ConversationState Load(string conversationId); - string GetState(string name); + string GetState(string name, string defaultValue = ""); ConversationState GetStates(); void SetState(string name, string value); void CleanState(); diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs index cc05fa7f..9c3e2bc1 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs @@ -11,9 +11,6 @@ public class RoleDialogModel public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public string Content { get; set; } public string CurrentAgentId { get; set; } - public string ModelName { get; set; } = "gpt-3.5-turbo"; - public float Temperature { get; set; } = 0.5f; - public float SamplingFactor { get; set; } = 0.5f; /// /// Function name if LLM response function call @@ -43,11 +40,6 @@ public class RoleDialogModel /// public bool StopCompletion { get; set; } - /// - /// Channel name - /// - public string Channel { get; set; } - public RoleDialogModel(string role, string text) { Role = role; diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs index cf9689e6..f125149d 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.GetChatCompletionsAsyncRecursively.cs @@ -1,7 +1,5 @@ using BotSharp.Abstraction.Agents.Enums; using BotSharp.Abstraction.Agents.Models; -using BotSharp.Abstraction.Conversations.Models; -using BotSharp.Abstraction.MLTasks; using BotSharp.Abstraction.Templating; namespace BotSharp.Core.Conversations.Services; @@ -16,7 +14,7 @@ public partial class ConversationService Func onFunctionExecuting, Func onFunctionExecuted) { - var chatCompletion = CompletionProvider.GetChatCompletion(_services, wholeDialogs.Last().ModelName); + var chatCompletion = CompletionProvider.GetChatCompletion(_services); currentRecursiveDepth++; if (currentRecursiveDepth > _settings.MaxRecursiveDepth) @@ -32,10 +30,7 @@ public partial class ConversationService await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, text) { - CurrentAgentId = agent.Id, - Channel = wholeDialogs.Last().Channel, - Temperature = wholeDialogs.Last().Temperature, - SamplingFactor = wholeDialogs.Last().SamplingFactor + CurrentAgentId = agent.Id }, onMessageReceived); return false; @@ -55,10 +50,7 @@ public partial class ConversationService { await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, fn.Content) { - CurrentAgentId = fn.CurrentAgentId, - Channel = fn.Channel, - Temperature = fn.Temperature, - SamplingFactor = fn.SamplingFactor + CurrentAgentId = fn.CurrentAgentId }, onMessageReceived); return; @@ -68,11 +60,8 @@ public partial class ConversationService await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, fn.Content) { CurrentAgentId = fn.CurrentAgentId, - Channel = fn.Channel, ExecutionData = fn.ExecutionData, - ExecutionResult = fn.ExecutionResult, - Temperature = fn.Temperature, - SamplingFactor = fn.SamplingFactor + ExecutionResult = fn.ExecutionResult }, onMessageReceived); return; @@ -106,10 +95,7 @@ public partial class ConversationService { await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, response) { - CurrentAgentId = agent.Id, - Channel = wholeDialogs.Last().Channel, - Temperature = wholeDialogs.Last().Temperature, - SamplingFactor = wholeDialogs.Last().SamplingFactor + CurrentAgentId = agent.Id }, onMessageReceived); return; diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs index 2b42dd48..9ed62d0f 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs @@ -43,10 +43,7 @@ public partial class ConversationService { var message = new RoleDialogModel(AgentRole.Assistant, lastDialog.Content) { - CurrentAgentId = agent.Id, - Channel = lastDialog.Channel, - Temperature = lastDialog.Temperature, - SamplingFactor = lastDialog.SamplingFactor + CurrentAgentId = agent.Id }; await onMessageReceived(message); _storage.Append(_conversationId, message); @@ -65,10 +62,7 @@ public partial class ConversationService { await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, reasonedContext.Content) { - CurrentAgentId = agent.Id, - Channel = lastDialog.Channel, - Temperature = lastDialog.Temperature, - SamplingFactor = lastDialog.SamplingFactor + CurrentAgentId = agent.Id }, onMessageReceived); return true; @@ -77,10 +71,7 @@ public partial class ConversationService { await HandleAssistantMessage(agent, new RoleDialogModel(AgentRole.Assistant, reasonedContext.Content) { - CurrentAgentId = agent.Id, - Channel = lastDialog.Channel, - Temperature = lastDialog.Temperature, - SamplingFactor = lastDialog.SamplingFactor + CurrentAgentId = agent.Id }, onMessageReceived); return true; diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs index 50ecfe5c..7212ab25 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs @@ -1,5 +1,4 @@ using BotSharp.Abstraction.Repositories; -using BotSharp.Abstraction.Repositories.Records; namespace BotSharp.Core.Conversations.Services; @@ -82,10 +81,10 @@ public partial class ConversationService : IConversationService .ToList(); } - public void SetConversationId(string conversationId, string channel) + public void SetConversationId(string conversationId, List states) { _conversationId = conversationId; _state.Load(_conversationId); - _state.SetState("channel", channel); + states.ForEach(x => _state.SetState(x.Split('=')[0], x.Split('=')[1])); } } diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs index b7a52f7a..d28c0bbf 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs @@ -112,11 +112,11 @@ public class ConversationStateService : IConversationStateService, IDisposable public ConversationState GetStates() => _states; - public string GetState(string name) + public string GetState(string name, string defaultValue = "") { if (!_states.ContainsKey(name)) { - _states[name] = ""; + _states[name] = defaultValue ?? ""; } return _states[name]; } diff --git a/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs b/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs index d2340135..18ecae76 100644 --- a/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs +++ b/src/Infrastructure/BotSharp.Core/Infrastructures/CompletionProvider.cs @@ -4,11 +4,13 @@ namespace BotSharp.Core.Infrastructures; public class CompletionProvider { - public static IChatCompletion GetChatCompletion(IServiceProvider services, string modelName = "gpt-3.5-turbo") + public static IChatCompletion GetChatCompletion(IServiceProvider services) { var completions = services.GetServices(); - var settings = services.GetRequiredService(); + // var settings = services.GetRequiredService(); // completions.FirstOrDefault(x => x.GetType().FullName.EndsWith(settings.ChatCompletion)); - return completions.FirstOrDefault(x => x.ModelName == modelName); + var state = services.GetRequiredService(); + var model = state.GetState("model", "gpt-3.5-turbo"); + return completions.FirstOrDefault(x => x.ModelName == model); } } diff --git a/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs b/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs index a6f2366f..242e027b 100644 --- a/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs +++ b/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs @@ -71,7 +71,7 @@ public partial class InstructService : IInstructService Func onFunctionExecuting, Func onFunctionExecuted) { - var chatCompletion = CompletionProvider.GetChatCompletion(_services, wholeDialogs.Last().ModelName); + var chatCompletion = CompletionProvider.GetChatCompletion(_services); var result = await chatCompletion.GetChatCompletionsAsync(agent, wholeDialogs, async msg => { diff --git a/src/Infrastructure/BotSharp.Core/Routing/Simulator.cs b/src/Infrastructure/BotSharp.Core/Routing/Simulator.cs index 60e52172..54d9ddc3 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Simulator.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Simulator.cs @@ -64,7 +64,7 @@ public class Simulator new RoleDialogModel(AgentRole.User, @"What's the next step, your response must be in JSON format with ""function"" and ""parameters"". ") }; - var chatCompletion = CompletionProvider.GetChatCompletion(_services, "gpt-4"); + var chatCompletion = CompletionProvider.GetChatCompletion(_services); RoleDialogModel response = null; await chatCompletion.GetChatCompletionsAsync(reasoner, wholeDialogs, async msg @@ -111,7 +111,7 @@ public class Simulator var agentService = _services.GetRequiredService(); var agent = await agentService.LoadAgent(agentId); - var chatCompletion = CompletionProvider.GetChatCompletion(_services, wholeDialogs.Last().ModelName); + var chatCompletion = CompletionProvider.GetChatCompletion(_services); RoleDialogModel response = null; await chatCompletion.GetChatCompletionsAsync(agent, wholeDialogs, async msg diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs index 77148d26..eabfb666 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs @@ -43,20 +43,17 @@ public class ConversationController : ControllerBase, IApiAdapter [FromBody] NewMessageModel input) { var conv = _services.GetRequiredService(); - conv.SetConversationId(conversationId, input.Channel); - input.States.ForEach(x => conv.States.SetState(x.Split('=')[0], x.Split('=')[1])); - + conv.SetConversationId(conversationId, input.States); + conv.States.SetState("channel", input.Channel); + conv.States.SetState("model", input.ModelName); + conv.States.SetState("temperature", input.Temperature.ToString()); + conv.States.SetState("sampling_factor", input.SamplingFactor.ToString()); + var response = new MessageResponseModel(); var stackMsg = new List(); await conv.SendMessage(agentId, - new RoleDialogModel("user", input.Text) - { - Channel = input.Channel, - ModelName = input.ModelName, - Temperature = input.Temperature, - SamplingFactor = input.SamplingFactor - }, + new RoleDialogModel("user", input.Text), async msg => { stackMsg.Add(msg); diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs index 18da09ac..3eeac672 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs @@ -36,10 +36,7 @@ public class InstructModeController : ControllerBase, IApiAdapter } return await instructor.ExecuteInstruction(agent, - new RoleDialogModel(AgentRole.User, input.Text) - { - ModelName = input.ModelName - }, + new RoleDialogModel(AgentRole.User, input.Text), fn => Task.CompletedTask, fn => Task.CompletedTask, fn => Task.CompletedTask); diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/InstructMessageModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/InstructMessageModel.cs index dffd3cf0..c11494bf 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/InstructMessageModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/InstructMessageModel.cs @@ -1,8 +1,8 @@ -using BotSharp.OpenAPI.ViewModels.Conversations; - +using BotSharp.Abstraction.Conversations.Models; namespace BotSharp.OpenAPI.ViewModels.Instructs; -public class InstructMessageModel : NewMessageModel +public class InstructMessageModel : IncomingMessageModel { + public override string Channel { get; set; } = "openapi"; public string? TemplateName { get; set; } } diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs index 819fb9dd..5ad763d9 100644 --- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs @@ -2,6 +2,7 @@ using Azure; using Azure.AI.OpenAI; using BotSharp.Abstraction.Agents.Enums; using BotSharp.Abstraction.Agents.Models; +using BotSharp.Abstraction.Conversations; using BotSharp.Abstraction.Conversations.Models; using BotSharp.Abstraction.Conversations.Settings; using BotSharp.Abstraction.Functions.Models; @@ -104,10 +105,7 @@ public class ChatCompletionProvider : IChatCompletion { CurrentAgentId = agent.Id, FunctionName = message.FunctionCall.Name, - FunctionArgs = message.FunctionCall.Arguments, - Channel = conversations.Last().Channel, - Temperature = conversations.Last().Temperature, - SamplingFactor = conversations.Last().SamplingFactor + FunctionArgs = message.FunctionCall.Arguments }; // Somethings LLM will generate a function name with agent name. @@ -125,10 +123,7 @@ public class ChatCompletionProvider : IChatCompletion var msg = new RoleDialogModel(AgentRole.Assistant, message.Content) { - CurrentAgentId= agent.Id, - Channel = conversations.Last().Channel, - Temperature = conversations.Last().Temperature, - SamplingFactor = conversations.Last().SamplingFactor + CurrentAgentId= agent.Id }; // Text response received @@ -230,8 +225,11 @@ public class ChatCompletionProvider : IChatCompletion } // https://community.openai.com/t/cheat-sheet-mastering-temperature-and-top-p-in-chatgpt-api-a-few-tips-and-tricks-on-controlling-the-creativity-deterministic-output-of-prompt-responses/172683 - chatCompletionsOptions.Temperature = conversations.Last().Temperature; - chatCompletionsOptions.NucleusSamplingFactor = conversations.Last().SamplingFactor; + var state = _services.GetRequiredService(); + var temperature = float.Parse(state.GetState("temperature", "0.5")); + var samplingFactor = float.Parse(state.GetState("sampling_factor", "0.5")); + chatCompletionsOptions.Temperature = temperature; + chatCompletionsOptions.NucleusSamplingFactor = samplingFactor; var convSetting = _services.GetRequiredService(); if (convSetting.ShowVerboseLog) diff --git a/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs b/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs index 0a8f3658..b8f178a4 100644 --- a/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs +++ b/src/Plugins/BotSharp.Plugin.ChatbotUI/ChatbotUiController.cs @@ -69,20 +69,17 @@ public class ChatbotUiController : ControllerBase, IApiAdapter Response.Headers.Add(HeaderNames.Connection, "keep-alive"); var outputStream = Response.Body; - var channel = "webchat"; var message = input.Messages .Where(x => x.Role == AgentRole.User) - .Select(x => new RoleDialogModel(x.Role, x.Content) - { - Channel = channel, - ModelName = input.ModelName, - Temperature = input.Temperature, - SamplingFactor = input.SamplingFactor - }).Last(); + .Select(x => new RoleDialogModel(x.Role, x.Content)) + .Last(); var conv = _services.GetRequiredService(); - conv.SetConversationId(input.ConversationId, channel); - input.States.ForEach(x => conv.States.SetState(x.Split('=')[0], x.Split('=')[1])); + conv.SetConversationId(input.ConversationId, input.States); + conv.States.SetState("model", input.ModelName); + conv.States.SetState("channel", "webchat"); + conv.States.SetState("temperature", "0.5"); + conv.States.SetState("sampling_factor", "0.5"); var result = await conv.SendMessage(input.AgentId, message, diff --git a/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs b/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs index 6440ac9f..937a6b17 100644 --- a/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs +++ b/src/Plugins/BotSharp.Plugin.MetaMessenger/Controllers/WebhookController.cs @@ -98,12 +98,12 @@ public class WebhookController : ControllerBase // Go to LLM var conv = _services.GetRequiredService(); - conv.SetConversationId(senderId, "messenger"); + conv.SetConversationId(senderId, new List + { + "channel=messenger" + }); - var result = await conv.SendMessage(agentId, new RoleDialogModel("user", input) - { - Channel = "messenger" - }, async msg => + var result = await conv.SendMessage(agentId, new RoleDialogModel("user", input), async msg => { reply.Text = msg.Content; }, async functionExecuting => diff --git a/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs b/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs index 529b2142..b3bc1e1f 100644 --- a/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs +++ b/src/Plugins/BotSharp.Plugin.WeChat/WeChatBackgroundService.cs @@ -1,16 +1,11 @@ -using BotSharp.Abstraction.Agents; using BotSharp.Abstraction.Conversations; using BotSharp.Abstraction.Conversations.Models; -using BotSharp.Abstraction.Models; -using BotSharp.Abstraction.Users; using BotSharp.Abstraction.Users.Models; using BotSharp.Plugin.WeChat.Users; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using Senparc.Weixin.Entities; using System; using System.Collections.Generic; using System.Linq; @@ -51,7 +46,10 @@ namespace BotSharp.Plugin.WeChat var latestConversationId = (await conversationService.GetConversations()) .OrderByDescending(_ => _.CreatedTime) .FirstOrDefault()?.Id; - conversationService.SetConversationId(latestConversationId, "wechat"); + conversationService.SetConversationId(latestConversationId, new List + { + "channel=wechat" + }); latestConversationId ??= (await conversationService.NewConversation(new Conversation() {