Draft of Reasoning

This commit is contained in:
hchen2020 2023-08-27 22:50:10 -05:00
parent e4d8524376
commit 6f5cf2fcae
25 changed files with 560 additions and 77 deletions

View file

@ -1,8 +1,11 @@
using BotSharp.Abstraction.Routing.Models;
namespace BotSharp.Abstraction.Agents;
public interface IAgentRouting
{
string AgentId { get; }
Task<Agent> LoadRouter();
Task<Agent> LoadCurrentAgent();
RoutingRecord[] GetRoutingRecords();
RoutingRecord GetRecordByName(string name);
}

View file

@ -6,7 +6,12 @@ public class AgentSettings
/// Router Agent Id
/// </summary>
public string RouterId { get; set; }
/// <summary>
/// Reasoner Agent Id
/// </summary>
public string ReasonerId { get; set; }
public string DataDir { get; set; }
public string TemplateFormat { get; set; }
public int MaxRecursiveDepth { get; set; } = 3;
}

View file

@ -45,7 +45,7 @@ public class RoleDialogModel
{
if (Role == AgentRole.Function)
{
return $"{Role}: {FunctionName}";
return $"{Role}: {FunctionName} => {ExecutionResult}";
}
else
{

View file

@ -6,4 +6,6 @@ public class ConversationSetting
public string ChatCompletion { get; set; }
public bool EnableKnowledgeBase { get; set; }
public bool ShowVerboseLog { get; set; }
public int MaxRecursiveDepth { get; set; } = 3;
public bool EnableReasoning { get; set; }
}

View file

@ -0,0 +1,14 @@
using BotSharp.Abstraction.Routing.Models;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace BotSharp.Abstraction.Functions.Models;
public class FunctionCallFromLlm
{
[JsonPropertyName("function")]
public string Function { get; set; }
[JsonPropertyName("parameters")]
public RetrievalArgs Parameters { get; set; }
}

View file

@ -0,0 +1,16 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace BotSharp.Abstraction.Routing.Models;
public class RetrievalArgs : RoutingArgs
{
[JsonPropertyName("question")]
public string Question { get; set; }
[JsonPropertyName("reason")]
public string Reason { get; set; }
[JsonPropertyName("args")]
public JsonDocument Arguments { get; set; }
}

View file

@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
namespace BotSharp.Abstraction.Agents.Models;
namespace BotSharp.Abstraction.Routing.Models;
public class RoutingArgs
{

View file

@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
namespace BotSharp.Abstraction.Agents.Models;
namespace BotSharp.Abstraction.Routing.Models;
public class RoutingRecord
{

View file

@ -0,0 +1,8 @@
namespace BotSharp.Abstraction.Routing.Settings;
public class GPT4Settings
{
public string ApiKey { get; set; }
public string Endpoint { get; set; }
public string DeploymentModel { get; set; }
}

View file

@ -1,53 +0,0 @@
using BotSharp.Abstraction.Agents.Models;
using System.IO;
namespace BotSharp.Core.Agents.Services;
public class AgentRouter : IAgentRouting
{
private readonly IServiceProvider _services;
private readonly ILogger _logger;
private readonly AgentSettings _settings;
public AgentRouter(IServiceProvider services,
ILogger<AgentRouter> logger,
AgentSettings settings)
{
_services = services;
_logger = logger;
_settings = settings;
}
public async Task<Agent> LoadRouter()
{
var agentService = _services.GetRequiredService<IAgentService>();
var agent = await agentService.LoadAgent(_settings.RouterId);
return agent;
}
public async Task<Agent> LoadCurrentAgent()
{
// Load current agent from state
var state = _services.GetRequiredService<IConversationStateService>();
var currentAgentId = state.GetState("agent_id");
if (string.IsNullOrEmpty(currentAgentId))
{
currentAgentId = _settings.RouterId;
}
var agentService = _services.GetRequiredService<IAgentService>();
var agent = await agentService.LoadAgent(currentAgentId);
// Set agent and trigger state changed
state.SetState("agent_id", currentAgentId);
return agent;
}
public RoutingRecord[] GetRoutingRecords()
{
var agentSettings = _services.GetRequiredService<AgentSettings>();
var dbSettings = _services.GetRequiredService<MyDatabaseSettings>();
var filePath = Path.Combine(dbSettings.FileRepository, agentSettings.DataDir, agentSettings.RouterId, "route.json");
return JsonSerializer.Deserialize<RoutingRecord[]>(File.ReadAllText(filePath));
}
}

View file

@ -82,8 +82,4 @@
<ProjectReference Include="..\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Reasoning\" />
</ItemGroup>
</Project>

View file

@ -1,6 +1,8 @@
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Functions;
using BotSharp.Core.Functions;
using BotSharp.Core.Hooks;
using BotSharp.Core.Routing;
using BotSharp.Core.Templating;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
@ -41,13 +43,21 @@ public static class BotSharpServiceCollectionExtensions
services.AddSingleton<TemplateRender>();
// Register router
services.AddScoped<IAgentRouting, AgentRouter>();
services.AddScoped<Router>();
services.AddScoped<Reasoner>();
services.AddScoped<IAgentRouting>(p =>
{
var setting = p.GetRequiredService<ConversationSetting>();
return setting.EnableReasoning ? p.GetRequiredService<Reasoner>() : p.GetRequiredService<Router>();
});
// Register function callback
services.AddScoped<IFunctionCallback, RouteToAgentFn>();
// Register Hooks
services.AddScoped<IAgentHook, AgentHook>();
services.AddScoped<IAgentHook, RoutingHook>();
services.AddScoped<Simulator>();
return services;
}

View file

@ -13,13 +13,12 @@ public partial class ConversationService
string conversationId,
Agent agent,
List<RoleDialogModel> wholeDialogs,
int maxRecursiveDepth,
Func<RoleDialogModel, Task> onMessageReceived,
Func<RoleDialogModel, Task> onFunctionExecuting,
Func<RoleDialogModel, Task> onFunctionExecuted)
{
currentRecursiveDepth++;
if (currentRecursiveDepth > maxRecursiveDepth)
if (currentRecursiveDepth > _settings.MaxRecursiveDepth)
{
_logger.LogWarning($"Exceeded max recursive depth.");
@ -65,7 +64,6 @@ public partial class ConversationService
fn.Content = fn.FunctionArgs.Replace("\r", " ").Replace("\n", " ").Trim() + " => " + fn.ExecutionResult;
// Agent has been transferred
var agentSettings = _services.GetRequiredService<AgentSettings>();
if (fn.CurrentAgentId != preAgentId)
{
var agentService = _services.GetRequiredService<IAgentService>();
@ -83,7 +81,6 @@ public partial class ConversationService
conversationId,
agent,
wholeDialogs,
maxRecursiveDepth,
onMessageReceived,
onFunctionExecuting,
onFunctionExecuted);

View file

@ -1,5 +1,8 @@
using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.MLTasks;
using BotSharp.Core.Routing;
namespace BotSharp.Core.Conversations.Services;
@ -31,7 +34,7 @@ public partial class ConversationService
stateService.SetState("channel", lastDialog.Channel);
var router = _services.GetRequiredService<IAgentRouting>();
var agent = await router.LoadRouter();
Agent agent = await router.LoadRouter();
_logger.LogInformation($"[{agent.Name}] {lastDialog.Role}: {lastDialog.Content}");
@ -65,14 +68,42 @@ public partial class ConversationService
await hook.BeforeCompletion();
}
var agentSettings = _services.GetRequiredService<AgentSettings>();
// reasoning
if (_settings.EnableReasoning)
{
var simulator = _services.GetRequiredService<Simulator>();
var reasonedContext = await simulator.Enter(agent, wholeDialogs);
if (reasonedContext.FunctionName == "interrupt_task_execution")
{
await HandleAssistantMessage(new RoleDialogModel(AgentRole.Assistant, reasonedContext.Content)
{
CurrentAgentId = agent.Id,
Channel = lastDialog.Channel
}, onMessageReceived);
return true;
}
else if (reasonedContext.FunctionName == "continue_execute_task")
{
if (reasonedContext.CurrentAgentId != agent.Id)
{
var agentService = _services.GetRequiredService<IAgentService>();
agent = await agentService.LoadAgent(reasonedContext.CurrentAgentId);
}
}
simulator.Dialogs.ForEach(x =>
{
wholeDialogs.Add(x);
_storage.Append(conversationId, agent.Id, x);
});
}
var chatCompletion = GetChatCompletion();
var result = await GetChatCompletionsAsyncRecursively(chatCompletion,
conversationId,
agent,
wholeDialogs,
agentSettings.MaxRecursiveDepth,
onMessageReceived,
onFunctionExecuting,
onFunctionExecuted);
@ -101,4 +132,10 @@ public partial class ConversationService
var completions = _services.GetServices<IChatCompletion>();
return completions.FirstOrDefault(x => x.GetType().FullName.EndsWith(_settings.ChatCompletion));
}
public IChatCompletion GetGpt4ChatCompletion()
{
var completions = _services.GetServices<IChatCompletion>();
return completions.FirstOrDefault(x => x.GetType().FullName.EndsWith("GPT4CompletionProvider"));
}
}

View file

@ -72,6 +72,7 @@ public class ConversationStorage : IConversationStorage
CurrentAgentId = currentAgentId,
FunctionName = funcName,
FunctionArgs = funcArgs,
ExecutionResult = text,
CreatedAt = createdAt
});
}

View file

@ -1,6 +1,6 @@
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.Functions;
using BotSharp.Abstraction.Routing.Models;
using System.IO;
namespace BotSharp.Core.Functions;
@ -51,8 +51,7 @@ public class RouteToAgentFn : IFunctionCallback
{
var args = JsonSerializer.Deserialize<RoutingArgs>(message.FunctionArgs);
var router = _services.GetRequiredService<IAgentRouting>();
var records = router.GetRoutingRecords();
var routingRule = records.FirstOrDefault(x => x.Name.ToLower() == args.AgentName.ToLower());
var routingRule = router.GetRecordByName(args.AgentName);
if (routingRule == null)
{

View file

@ -0,0 +1,14 @@
namespace BotSharp.Core.Hooks;
public class ReasoningHook : AgentHookBase
{
public ReasoningHook(IServiceProvider services, AgentSettings settings)
: base(services, settings)
{
}
public override bool OnInstructionLoaded(string template, Dictionary<string, object> dict)
{
return true;
}
}

View file

@ -1,8 +1,8 @@
namespace BotSharp.Core.Hooks;
public class AgentHook : AgentHookBase
public class RoutingHook : AgentHookBase
{
public AgentHook(IServiceProvider services, AgentSettings settings)
public RoutingHook(IServiceProvider services, AgentSettings settings)
: base(services, settings)
{
}

View file

@ -0,0 +1,12 @@
namespace BotSharp.Core.Routing;
public class Reasoner : Router
{
public override string AgentId => _settings.ReasonerId;
public Reasoner(IServiceProvider services,
ILogger<Reasoner> logger,
AgentSettings settings) : base(services, logger, settings)
{
}
}

View file

@ -0,0 +1,43 @@
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Routing.Models;
using System.IO;
using static Tensorflow.ApiDef.Types;
namespace BotSharp.Core.Routing;
public class Router : IAgentRouting
{
protected readonly IServiceProvider _services;
protected readonly ILogger _logger;
protected readonly AgentSettings _settings;
public virtual string AgentId => _settings.RouterId;
public Router(IServiceProvider services,
ILogger<Router> logger,
AgentSettings settings)
{
_services = services;
_logger = logger;
_settings = settings;
}
public virtual async Task<Agent> LoadRouter()
{
var agentService = _services.GetRequiredService<IAgentService>();
return await agentService.LoadAgent(AgentId);
}
public RoutingRecord[] GetRoutingRecords()
{
var agentSettings = _services.GetRequiredService<AgentSettings>();
var dbSettings = _services.GetRequiredService<MyDatabaseSettings>();
var filePath = Path.Combine(dbSettings.FileRepository, agentSettings.DataDir, agentSettings.RouterId, "route.json");
return JsonSerializer.Deserialize<RoutingRecord[]>(File.ReadAllText(filePath));
}
public RoutingRecord GetRecordByName(string name)
{
return GetRoutingRecords().First(x => x.Name.ToLower() == name.ToLower());
}
}

View file

@ -0,0 +1,133 @@
using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.MLTasks;
namespace BotSharp.Core.Routing;
/// <summary>
/// Simulate the dialogue between different agents.
/// </summary>
public class Simulator
{
private readonly IServiceProvider _services;
private readonly ILogger _logger;
private List<RoleDialogModel> _dialogs;
public List<RoleDialogModel> Dialogs => _dialogs;
public Simulator(IServiceProvider services, ILogger<Simulator> logger)
{
_services = services;
_logger = logger;
}
public async Task<RoleDialogModel> Enter(Agent agent, List<RoleDialogModel> whileDialogs)
{
_dialogs = new List<RoleDialogModel>();
foreach (var dialog in whileDialogs.TakeLast(10))
{
agent.Instruction += $"\r\n{dialog.Role}: {dialog.Content}";
}
var response = await SendMessageToReasoner(agent);
var args = JsonSerializer.Deserialize<FunctionCallFromLlm>(response.Content);
response.FunctionName = args.Function;
response.Content = args.Parameters.Reason;
if (args.Function == "continue_execute_task")
{
response.FunctionArgs = JsonSerializer.Serialize(args.Parameters.Arguments);
var router = _services.GetRequiredService<IAgentRouting>();
var record = router.GetRecordByName(args.Parameters.AgentName);
response.CurrentAgentId = record.AgentId;
}
return response;
}
private async Task<RoleDialogModel> SendMessageToReasoner(Agent reasoner)
{
var wholeDialogs = new List<RoleDialogModel>
{
new RoleDialogModel(AgentRole.User, @"What's the next step, your response must be in JSON format with ""function"" and ""parameters"". ")
};
var chatCompletion = GetGpt4ChatCompletion();
RoleDialogModel response = null;
await chatCompletion.GetChatCompletionsAsync(reasoner, wholeDialogs, async msg
=> response = msg, fn
=> Task.CompletedTask);
var args = JsonSerializer.Deserialize<FunctionCallFromLlm>(response.Content);
SaveStateByArgs(args.Parameters.Arguments);
// Retrieve information from specific agent
var router = _services.GetRequiredService<IAgentRouting>();
var record = router.GetRecordByName(args.Parameters.AgentName);
response = await SendMessageToAgent(record.AgentId, new List<RoleDialogModel>
{
new RoleDialogModel(AgentRole.User, args.Parameters.Question)
});
_dialogs.Add(new RoleDialogModel(AgentRole.Function, $"{record.Name}: {response.Content}")
{
FunctionName = args.Function,
FunctionArgs = JsonSerializer.Serialize(args.Parameters.Arguments),
ExecutionResult = response.Content
});
reasoner.Instruction += $"\r\n{record.Name}: {response.Content}";
// Got the response from agent, then send to reasoner again to make the decision
await chatCompletion.GetChatCompletionsAsync(reasoner, wholeDialogs, async msg
=> response = msg, fn
=> Task.CompletedTask);
return response;
}
private async Task<RoleDialogModel> SendMessageToAgent(string agentId, List<RoleDialogModel> wholeDialogs)
{
var agentService = _services.GetRequiredService<IAgentService>();
var agent = await agentService.LoadAgent(agentId);
var chatCompletion = GetChatCompletion();
RoleDialogModel response = null;
await chatCompletion.GetChatCompletionsAsync(agent, wholeDialogs, async msg
=> response = msg, fn
=> Task.CompletedTask);
return response;
}
public IChatCompletion GetChatCompletion()
{
var completions = _services.GetServices<IChatCompletion>();
var settings = _services.GetRequiredService<ConversationSetting>();
return completions.FirstOrDefault(x => x.GetType().FullName.EndsWith(settings.ChatCompletion));
}
public IChatCompletion GetGpt4ChatCompletion()
{
var completions = _services.GetServices<IChatCompletion>();
return completions.FirstOrDefault(x => x.GetType().FullName.EndsWith("GPT4CompletionProvider"));
}
private void SaveStateByArgs(JsonDocument args)
{
var stateService = _services.GetRequiredService<IConversationStateService>();
if (args.RootElement is JsonElement root)
{
foreach (JsonProperty property in root.EnumerateObject())
{
if (!string.IsNullOrEmpty(property.Value.ToString()))
{
stateService.SetState(property.Name, property.Value.ToString());
}
}
}
}
}

View file

@ -1,4 +1,5 @@
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Routing.Models;
using BotSharp.Abstraction.Templating;
using Fluid;
using Microsoft.Extensions.Options;
@ -17,7 +18,7 @@ public class TemplateRender : ITemplateRender
_services = services;
_logger = logger;
_options = new TemplateOptions();
_options.MemberAccessStrategy.MemberNameStrategy = MemberNameStrategies.CamelCase;
_options.MemberAccessStrategy.MemberNameStrategy = MemberNameStrategies.SnakeCase;
_options.MemberAccessStrategy.Register<RoutingRecord>();
}

View file

@ -23,5 +23,6 @@ public class AzureOpenAiPlugin : IBotSharpPlugin
services.AddScoped<ITextCompletion, TextCompletionProvider>();
services.AddScoped<IChatCompletion, ChatCompletionProvider>();
services.AddScoped<IChatCompletion, GPT4CompletionProvider>();
}
}

View file

@ -0,0 +1,240 @@
using Azure;
using Azure.AI.OpenAI;
using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.Conversations.Models;
using BotSharp.Abstraction.Conversations.Settings;
using BotSharp.Abstraction.Functions.Models;
using BotSharp.Abstraction.MLTasks;
using BotSharp.Plugin.AzureOpenAI.Settings;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
namespace BotSharp.Plugin.AzureOpenAI.Providers;
public class GPT4CompletionProvider : IChatCompletion
{
private readonly AzureOpenAiSettings _settings;
private readonly IServiceProvider _services;
private readonly ILogger _logger;
public GPT4CompletionProvider(AzureOpenAiSettings settings,
ILogger<GPT4CompletionProvider> logger,
IServiceProvider services)
{
_settings = settings;
_logger = logger;
_services = services;
}
private OpenAIClient GetClient()
{
var client = new OpenAIClient(new Uri(_settings.GPT4.Endpoint), new AzureKeyCredential(_settings.GPT4.ApiKey));
return client;
}
public List<RoleDialogModel> GetChatSamples(string sampleText)
{
var samples = new List<RoleDialogModel>();
if (string.IsNullOrEmpty(sampleText))
{
return samples;
}
var lines = sampleText.Split('\n');
for (int i = 0; i < lines.Length; i++)
{
var line = lines[i];
if (string.IsNullOrEmpty(line.Trim()))
{
continue;
}
var role = line.Substring(0, line.IndexOf(' ') - 1).Trim();
var content = line.Substring(line.IndexOf(' ') + 1).Trim();
// comments
if (role == "##")
{
continue;
}
samples.Add(new RoleDialogModel(role, content));
}
return samples;
}
public List<FunctionDef> GetFunctions(string functionsJson)
{
var functions = new List<FunctionDef>();
if (!string.IsNullOrEmpty(functionsJson))
{
functions = JsonSerializer.Deserialize<List<FunctionDef>>(functionsJson, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
AllowTrailingCommas = true
});
}
return functions;
}
public async Task<bool> GetChatCompletionsAsync(Agent agent,
List<RoleDialogModel> conversations,
Func<RoleDialogModel, Task> onMessageReceived,
Func<RoleDialogModel, Task> onFunctionExecuting)
{
var client = GetClient();
var chatCompletionsOptions = PrepareOptions(agent, conversations);
var response = await client.GetChatCompletionsAsync(_settings.GPT4.DeploymentModel, chatCompletionsOptions);
var choice = response.Value.Choices[0];
var message = choice.Message;
if (choice.FinishReason == CompletionsFinishReason.FunctionCall)
{
_logger.LogInformation($"[{agent.Name}]: {message.FunctionCall.Name} => {message.FunctionCall.Arguments}");
var funcContextIn = new RoleDialogModel(AgentRole.Function, message.Content)
{
CurrentAgentId = agent.Id,
FunctionName = message.FunctionCall.Name,
FunctionArgs = message.FunctionCall.Arguments,
Channel = conversations.Last().Channel
};
// Execute functions
await onFunctionExecuting(funcContextIn);
}
else
{
_logger.LogInformation($"[{agent.Name}] {message.Role}: {message.Content}");
var msg = new RoleDialogModel(AgentRole.Assistant, message.Content)
{
CurrentAgentId= agent.Id,
Channel = conversations.Last().Channel
};
// Text response received
await onMessageReceived(msg);
}
return true;
}
public async Task<bool> GetChatCompletionsStreamingAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived)
{
var client = new OpenAIClient(new Uri(_settings.Endpoint), new AzureKeyCredential(_settings.ApiKey));
var chatCompletionsOptions = PrepareOptions(agent, conversations);
var response = await client.GetChatCompletionsStreamingAsync(_settings.DeploymentModel.ChatCompletionModel, chatCompletionsOptions);
using StreamingChatCompletions streaming = response.Value;
string output = "";
await foreach (var choice in streaming.GetChoicesStreaming())
{
if (choice.FinishReason == CompletionsFinishReason.FunctionCall)
{
var args = "";
await foreach (var message in choice.GetMessageStreaming())
{
if (message.FunctionCall == null || message.FunctionCall.Arguments == null)
continue;
Console.Write(message.FunctionCall.Arguments);
args += message.FunctionCall.Arguments;
}
await onMessageReceived(new RoleDialogModel(ChatRole.Assistant.ToString(), args));
continue;
}
await foreach (var message in choice.GetMessageStreaming())
{
if (message.Content == null)
continue;
Console.Write(message.Content);
output += message.Content;
_logger.LogInformation(message.Content);
await onMessageReceived(new RoleDialogModel(message.Role.ToString(), message.Content));
}
output = "";
}
return true;
}
private ChatCompletionsOptions PrepareOptions(Agent agent, List<RoleDialogModel> conversations)
{
var chatCompletionsOptions = new ChatCompletionsOptions();
if (!string.IsNullOrEmpty(agent.Instruction))
{
chatCompletionsOptions.Messages.Add(new ChatMessage(ChatRole.System, agent.Instruction));
}
if (!string.IsNullOrEmpty(agent.Knowledges))
{
chatCompletionsOptions.Messages.Add(new ChatMessage(ChatRole.System, agent.Knowledges));
}
var samples = GetChatSamples(agent.Samples);
foreach (var message in samples)
{
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Content));
}
var functions = GetFunctions(agent.Functions);
foreach (var function in functions)
{
chatCompletionsOptions.Functions.Add(new FunctionDefinition
{
Name = function.Name,
Description = function.Description,
Parameters = BinaryData.FromObjectAsJson(function.Parameters)
});
}
foreach (var message in conversations)
{
if (message.Role == ChatRole.Function)
{
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Content)
{
Name = message.FunctionName
});
}
else
{
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Content));
}
}
// 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 = 0.5f;
chatCompletionsOptions.NucleusSamplingFactor = 0.5f;
var convSetting = _services.GetRequiredService<ConversationSetting>();
if (convSetting.ShowVerboseLog)
{
var verbose = string.Join("\n", chatCompletionsOptions.Messages.Select(x =>
{
return x.Role == ChatRole.Function ?
$"{x.Role}: {x.Name} {x.Content}" :
$"{x.Role}: {x.Content}";
}));
_logger.LogInformation(verbose);
}
return chatCompletionsOptions;
}
}

View file

@ -1,3 +1,5 @@
using BotSharp.Abstraction.Routing.Settings;
namespace BotSharp.Plugin.AzureOpenAI.Settings;
public class AzureOpenAiSettings
@ -6,4 +8,6 @@ public class AzureOpenAiSettings
public string Endpoint { get; set; } = string.Empty;
public DeploymentModelSetting DeploymentModel { get; set; }
= new DeploymentModelSetting();
public GPT4Settings GPT4 { get; set; }
}