Set model in conversation state.

This commit is contained in:
Haiping Chen 2023-09-13 20:41:51 -05:00
parent d911b8de3f
commit 17bfcb2518
19 changed files with 59 additions and 101 deletions

View file

@ -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

View file

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

View file

@ -4,7 +4,7 @@ public interface IConversationService
{
IConversationStateService States { get; }
Task<Conversation> NewConversation(Conversation conversation);
void SetConversationId(string conversationId, string channel);
void SetConversationId(string conversationId, List<string> states);
Task<Conversation> GetConversation(string id);
Task<List<Conversation>> GetConversations();
Task DeleteConversation(string id);

View file

@ -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();

View file

@ -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;
/// <summary>
/// Function name if LLM response function call
@ -43,11 +40,6 @@ public class RoleDialogModel
/// </summary>
public bool StopCompletion { get; set; }
/// <summary>
/// Channel name
/// </summary>
public string Channel { get; set; }
public RoleDialogModel(string role, string text)
{
Role = role;

View file

@ -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<RoleDialogModel, Task> onFunctionExecuting,
Func<RoleDialogModel, Task> 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;

View file

@ -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;

View file

@ -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<string> states)
{
_conversationId = conversationId;
_state.Load(_conversationId);
_state.SetState("channel", channel);
states.ForEach(x => _state.SetState(x.Split('=')[0], x.Split('=')[1]));
}
}

View file

@ -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];
}

View file

@ -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<IChatCompletion>();
var settings = services.GetRequiredService<ConversationSetting>();
// var settings = services.GetRequiredService<ConversationSetting>();
// completions.FirstOrDefault(x => x.GetType().FullName.EndsWith(settings.ChatCompletion));
return completions.FirstOrDefault(x => x.ModelName == modelName);
var state = services.GetRequiredService<IConversationStateService>();
var model = state.GetState("model", "gpt-3.5-turbo");
return completions.FirstOrDefault(x => x.ModelName == model);
}
}

View file

@ -71,7 +71,7 @@ public partial class InstructService : IInstructService
Func<RoleDialogModel, Task> onFunctionExecuting,
Func<RoleDialogModel, Task> onFunctionExecuted)
{
var chatCompletion = CompletionProvider.GetChatCompletion(_services, wholeDialogs.Last().ModelName);
var chatCompletion = CompletionProvider.GetChatCompletion(_services);
var result = await chatCompletion.GetChatCompletionsAsync(agent, wholeDialogs, async msg =>
{

View file

@ -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<IAgentService>();
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

View file

@ -43,20 +43,17 @@ public class ConversationController : ControllerBase, IApiAdapter
[FromBody] NewMessageModel input)
{
var conv = _services.GetRequiredService<IConversationService>();
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<RoleDialogModel>();
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);

View file

@ -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);

View file

@ -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; }
}

View file

@ -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<IConversationStateService>();
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<ConversationSetting>();
if (convSetting.ShowVerboseLog)

View file

@ -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<IConversationService>();
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,

View file

@ -98,12 +98,12 @@ public class WebhookController : ControllerBase
// Go to LLM
var conv = _services.GetRequiredService<IConversationService>();
conv.SetConversationId(senderId, "messenger");
var result = await conv.SendMessage(agentId, new RoleDialogModel("user", input)
conv.SetConversationId(senderId, new List<string>
{
Channel = "messenger"
}, async msg =>
"channel=messenger"
});
var result = await conv.SendMessage(agentId, new RoleDialogModel("user", input), async msg =>
{
reply.Text = msg.Content;
}, async functionExecuting =>

View file

@ -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<string>
{
"channel=wechat"
});
latestConversationId ??= (await conversationService.NewConversation(new Conversation()
{