Unify the LLM Provider Settings #234
This commit is contained in:
parent
ab913b0b8e
commit
538753571a
|
|
@ -16,14 +16,19 @@ Suppose we need to write a Pizza restaurant order AI Bot. First, specify a name
|
||||||
BotSharp uses the latest large language model in natural language understanding, can interact with OpenAI's ChatGPT, and also supports the most widely used open source large language model [LLaMA](https://ai.meta.com/blog/large-language-model-llama-meta-ai/) and its fine-tuning model. In this example, we use [Azure OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service) as the LLM engine.
|
BotSharp uses the latest large language model in natural language understanding, can interact with OpenAI's ChatGPT, and also supports the most widely used open source large language model [LLaMA](https://ai.meta.com/blog/large-language-model-llama-meta-ai/) and its fine-tuning model. In this example, we use [Azure OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service) as the LLM engine.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"AzureOpenAi": {
|
"LlmProviders": [
|
||||||
"ApiKey": "",
|
{
|
||||||
"Endpoint": "",
|
"Provider": "azure-openai",
|
||||||
"DeploymentModel": {
|
"Models": [{
|
||||||
"ChatCompletionModel": "",
|
"Name": "gpt-35-turbo",
|
||||||
"TextCompletionModel": ""
|
"ApiKey": "",
|
||||||
|
"Endpoint": "https://gpt-35-turbo.openai.azure.com/",
|
||||||
|
"Type": "chat",
|
||||||
|
"PromptCost": 0.0015,
|
||||||
|
"CompletionCost": 0.002
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
If you use the installation package to run, please ensure that the [BotSharp.Plugin.AzureOpenAI](https://www.nuget.org/packages/BotSharp.Plugin.AzureOpenAI) plugin package is installed.
|
If you use the installation package to run, please ensure that the [BotSharp.Plugin.AzureOpenAI](https://www.nuget.org/packages/BotSharp.Plugin.AzureOpenAI) plugin package is installed.
|
||||||
|
|
|
||||||
|
|
@ -64,9 +64,9 @@ author = 'Haiping Chen'
|
||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '0.20'
|
version = '0.21'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '0.20.0'
|
release = '0.21.0'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,29 @@ PS D:\> dotnet build
|
||||||
`BotSharp` can work with serveral LLM providers. Update `appsettings.json` in your project. Below config is tasking Azure OpenAI as the LLM backend
|
`BotSharp` can work with serveral LLM providers. Update `appsettings.json` in your project. Below config is tasking Azure OpenAI as the LLM backend
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"AzureOpenAi": {
|
"LlmProviders": [
|
||||||
"ApiKey": "",
|
{
|
||||||
"Endpoint": "https://xxx.openai.azure.com/",
|
"Provider": "azure-openai",
|
||||||
"DeploymentModel": {
|
"Models": [
|
||||||
"ChatCompletionModel": "",
|
{
|
||||||
"TextCompletionModel": ""
|
"Name": "gpt-35-turbo",
|
||||||
}
|
"ApiKey": "",
|
||||||
}
|
"Endpoint": "https://gpt-35-turbo.openai.azure.com/",
|
||||||
|
"Type": "chat",
|
||||||
|
"PromptCost": 0.0015,
|
||||||
|
"CompletionCost": 0.002
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "gpt-35-turbo-instruct",
|
||||||
|
"ApiKey": "",
|
||||||
|
"Endpoint": "https://gpt-35-turbo-instruct.openai.azure.com/",
|
||||||
|
"Type": "text",
|
||||||
|
"PromptCost": 0.0015,
|
||||||
|
"CompletionCost": 0.002
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Run backend web project
|
### Run backend web project
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,3 @@ Even with this simple question, you can see conversational experience are hard t
|
||||||
Your code would have to handle all these different types of requests ro carry out the same logic: looking up some forecast information for a feature. For this reason, a traditional computer interface would tend to force users to input a well-known, standard request at the detriment of the user experience, because it's just easier.
|
Your code would have to handle all these different types of requests ro carry out the same logic: looking up some forecast information for a feature. For this reason, a traditional computer interface would tend to force users to input a well-known, standard request at the detriment of the user experience, because it's just easier.
|
||||||
|
|
||||||
However, BotSharp lets you easily achieve a conversational user experience by handling the natural language understanding (NLU) for you. When you use BotSharp, you can create agents that can understand the meaning of natural language and the nuances and trainslate that to structured meaning your software can understand.
|
However, BotSharp lets you easily achieve a conversational user experience by handling the natural language understanding (NLU) for you. When you use BotSharp, you can create agents that can understand the meaning of natural language and the nuances and trainslate that to structured meaning your software can understand.
|
||||||
|
|
||||||
Features
|
|
||||||
-------------
|
|
||||||
|
|
||||||
* Built-in multi-Agents management, easy to build Bot as a Service platform.
|
|
||||||
* Integrate with multiple LLMs like ChatGPT and LLaMA.
|
|
||||||
* Using plug-in design, it is easy to expand functions.
|
|
||||||
* Working with multiple Vector Stores for senmatic search.
|
|
||||||
* Supporting different UI providers like [Chatbot UI](https://github.com/SciSharp/chatbot-ui) and [HuggingChat UI](https://github.com/huggingface/chat-ui).
|
|
||||||
* Integrated with popular social platforms like Facebook Messenger, Slack and Telegram.
|
|
||||||
* Providing REST APIs to work with your own UI.
|
|
||||||
|
|
@ -11,6 +11,11 @@ public class Agent
|
||||||
public DateTime CreatedDateTime { get; set; }
|
public DateTime CreatedDateTime { get; set; }
|
||||||
public DateTime UpdatedDateTime { get; set; }
|
public DateTime UpdatedDateTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default LLM settings
|
||||||
|
/// </summary>
|
||||||
|
public AgentLlmConfig? LlmConfig { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instruction
|
/// Instruction
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
namespace BotSharp.Abstraction.Agents.Models;
|
||||||
|
|
||||||
|
public class AgentLlmConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Completion Provider
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("provider")]
|
||||||
|
public string? Provider { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Model name
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("model")]
|
||||||
|
public string? Model { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -2,18 +2,10 @@ namespace BotSharp.Abstraction.Conversations.Models;
|
||||||
|
|
||||||
public class TokenStatsModel
|
public class TokenStatsModel
|
||||||
{
|
{
|
||||||
|
public string Provider { get; set; }
|
||||||
public string Model { get; set; }
|
public string Model { get; set; }
|
||||||
public string Prompt { get; set; }
|
public string Prompt { get; set; }
|
||||||
public int PromptCount { get; set; }
|
public int PromptCount { get; set; }
|
||||||
public int CompletionCount { get; set; }
|
public int CompletionCount { get; set; }
|
||||||
|
public AgentLlmConfig LlmConfig { get; set; }
|
||||||
/// <summary>
|
|
||||||
/// Prompt cost per 1K token
|
|
||||||
/// </summary>
|
|
||||||
public float PromptCost { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Completion cost per 1K token
|
|
||||||
/// </summary>
|
|
||||||
public float CompletionCost { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,5 @@ namespace BotSharp.Abstraction.Evaluations.Settings;
|
||||||
|
|
||||||
public class EvaluatorSetting
|
public class EvaluatorSetting
|
||||||
{
|
{
|
||||||
public string EvaluatorId { get; set; }
|
public string AgentId { get; set; }
|
||||||
public string Provider { get; set; }
|
|
||||||
public string Model { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
using BotSharp.Abstraction.MLTasks.Settings;
|
||||||
|
|
||||||
|
namespace BotSharp.Abstraction.MLTasks;
|
||||||
|
|
||||||
|
public interface ILlmProviderSettingService
|
||||||
|
{
|
||||||
|
LlmModelSetting GetSetting(string provider, string model);
|
||||||
|
}
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
namespace BotSharp.Abstraction.MLTasks.Settings;
|
|
||||||
|
|
||||||
public class ChatCompletionSetting
|
|
||||||
{
|
|
||||||
public string Provider { get; set; }
|
|
||||||
public string Model { get; set; }
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
namespace BotSharp.Abstraction.MLTasks.Settings;
|
||||||
|
|
||||||
|
public class LlmModelSetting
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string ApiKey { get; set; }
|
||||||
|
public string Endpoint { get; set; }
|
||||||
|
public LlmModelType Type { get; set; } = LlmModelType.Chat;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prompt cost per 1K token
|
||||||
|
/// </summary>
|
||||||
|
public float PromptCost { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Completion cost per 1K token
|
||||||
|
/// </summary>
|
||||||
|
public float CompletionCost { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"[{Type}] {Name} {Endpoint}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum LlmModelType
|
||||||
|
{
|
||||||
|
Text = 1,
|
||||||
|
Chat = 2
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace BotSharp.Abstraction.MLTasks.Settings;
|
||||||
|
|
||||||
|
public class LlmProviderSetting
|
||||||
|
{
|
||||||
|
public string Provider { get; set; }
|
||||||
|
= "azure-openai";
|
||||||
|
|
||||||
|
public List<LlmModelSetting> Models { get; set; }
|
||||||
|
= new List<LlmModelSetting>();
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Provider} with {Models.Count} models";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
namespace BotSharp.Abstraction.MLTasks.Settings;
|
|
||||||
|
|
||||||
public class TextCompletionSetting
|
|
||||||
{
|
|
||||||
public string Provider { get; set; }
|
|
||||||
public string Model { get; set; }
|
|
||||||
}
|
|
||||||
|
|
@ -22,14 +22,14 @@ public class RoutingContext
|
||||||
/// Agent that can handl user original goal.
|
/// Agent that can handl user original goal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OriginAgentId
|
public string OriginAgentId
|
||||||
=> _stack.Where(x => x != _setting.RouterId).Last();
|
=> _stack.Where(x => x != _setting.AgentId).Last();
|
||||||
|
|
||||||
public bool IsEmpty => !_stack.Any();
|
public bool IsEmpty => !_stack.Any();
|
||||||
public string GetCurrentAgentId()
|
public string GetCurrentAgentId()
|
||||||
{
|
{
|
||||||
if (_stack.Count == 0)
|
if (_stack.Count == 0)
|
||||||
{
|
{
|
||||||
_stack.Push(_setting.RouterId);
|
_stack.Push(_setting.AgentId);
|
||||||
}
|
}
|
||||||
return _stack.Peek();
|
return _stack.Peek();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,7 @@ public class RoutingSettings
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Router Agent Id
|
/// Router Agent Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string RouterId { get; set; } = string.Empty;
|
public string AgentId { get; set; } = string.Empty;
|
||||||
|
|
||||||
public string Planner { get; set; } = string.Empty;
|
public string Planner { get; set; } = string.Empty;
|
||||||
public string Provider { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public string Model { get; set; } = string.Empty;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ using BotSharp.Core.Evaluations;
|
||||||
using BotSharp.Abstraction.MLTasks.Settings;
|
using BotSharp.Abstraction.MLTasks.Settings;
|
||||||
using BotSharp.Abstraction.Planning;
|
using BotSharp.Abstraction.Planning;
|
||||||
using BotSharp.Core.Planning;
|
using BotSharp.Core.Planning;
|
||||||
|
using BotSharp.Abstraction.MLTasks;
|
||||||
|
using static Dapper.SqlMapper;
|
||||||
|
|
||||||
namespace BotSharp.Core;
|
namespace BotSharp.Core;
|
||||||
|
|
||||||
|
|
@ -27,7 +29,7 @@ public static class BotSharpCoreExtensions
|
||||||
public static IServiceCollection AddBotSharpCore(this IServiceCollection services, IConfiguration config)
|
public static IServiceCollection AddBotSharpCore(this IServiceCollection services, IConfiguration config)
|
||||||
{
|
{
|
||||||
services.AddScoped<IUserService, UserService>();
|
services.AddScoped<IUserService, UserService>();
|
||||||
|
services.AddScoped<ILlmProviderSettingService, LlmProviderSettingService>();
|
||||||
services.AddScoped<IAgentService, AgentService>();
|
services.AddScoped<IAgentService, AgentService>();
|
||||||
|
|
||||||
var agentSettings = new AgentSettings();
|
var agentSettings = new AgentSettings();
|
||||||
|
|
@ -51,13 +53,16 @@ public static class BotSharpCoreExtensions
|
||||||
config.Bind("Database", myDatabaseSettings);
|
config.Bind("Database", myDatabaseSettings);
|
||||||
services.AddSingleton((IServiceProvider x) => myDatabaseSettings);
|
services.AddSingleton((IServiceProvider x) => myDatabaseSettings);
|
||||||
|
|
||||||
var textCompletionSettings = new TextCompletionSetting();
|
var llmProviders = new List<LlmProviderSetting>();
|
||||||
config.Bind("TextCompletion", textCompletionSettings);
|
config.Bind("LlmProviders", llmProviders);
|
||||||
services.AddSingleton((IServiceProvider x) => textCompletionSettings);
|
services.AddSingleton((IServiceProvider x) =>
|
||||||
|
{
|
||||||
var chatCompletionSettings = new ChatCompletionSetting();
|
foreach (var llmProvider in llmProviders)
|
||||||
config.Bind("ChatCompletion", chatCompletionSettings);
|
{
|
||||||
services.AddSingleton((IServiceProvider x) => chatCompletionSettings);
|
Console.WriteLine($"Loaded LlmProvider {llmProvider.Provider} settings with {llmProvider.Models.Count} models.");
|
||||||
|
}
|
||||||
|
return llmProviders;
|
||||||
|
});
|
||||||
|
|
||||||
RegisterPlugins(services, config);
|
RegisterPlugins(services, config);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ public partial class ConversationService
|
||||||
var routing = _services.GetRequiredService<IRoutingService>();
|
var routing = _services.GetRequiredService<IRoutingService>();
|
||||||
var settings = _services.GetRequiredService<RoutingSettings>();
|
var settings = _services.GetRequiredService<RoutingSettings>();
|
||||||
|
|
||||||
response = agentId == settings.RouterId ?
|
response = agentId == settings.AgentId ?
|
||||||
await routing.InstructLoop(message) :
|
await routing.InstructLoop(message) :
|
||||||
await routing.ExecuteDirectly(agent, message);
|
await routing.ExecuteDirectly(agent, message);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using BotSharp.Abstraction.MLTasks;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
|
||||||
|
|
@ -36,19 +37,24 @@ public class TokenStatistics : ITokenStatistics
|
||||||
_model = stats.Model;
|
_model = stats.Model;
|
||||||
_promptTokenCount += stats.PromptCount;
|
_promptTokenCount += stats.PromptCount;
|
||||||
_completionTokenCount += stats.CompletionCount;
|
_completionTokenCount += stats.CompletionCount;
|
||||||
_promptCost += stats.PromptCount / 1000f * stats.PromptCost;
|
|
||||||
_completionCost += stats.CompletionCount / 1000f * stats.CompletionCost;
|
var settingsService = _services.GetRequiredService<ILlmProviderSettingService>();
|
||||||
|
var settings = settingsService.GetSetting(stats.Provider, _model);
|
||||||
|
|
||||||
|
_promptCost += stats.PromptCount / 1000f * settings.PromptCost;
|
||||||
|
_completionCost += stats.CompletionCount / 1000f * settings.CompletionCost;
|
||||||
|
|
||||||
// Accumulated Token
|
// Accumulated Token
|
||||||
var stat = _services.GetRequiredService<IConversationStateService>();
|
var stat = _services.GetRequiredService<IConversationStateService>();
|
||||||
var count1 = int.Parse(stat.GetState("prompt_total", "0"));
|
var inputCount = int.Parse(stat.GetState("prompt_total", "0"));
|
||||||
stat.SetState("prompt_total", stats.PromptCount + count1);
|
stat.SetState("prompt_total", stats.PromptCount + inputCount);
|
||||||
var count2 = int.Parse(stat.GetState("completion_total", "0"));
|
var outputCount = int.Parse(stat.GetState("completion_total", "0"));
|
||||||
stat.SetState("completion_total", stats.CompletionCount + count2);
|
stat.SetState("completion_total", stats.CompletionCount + outputCount);
|
||||||
|
|
||||||
// Total cost
|
// Total cost
|
||||||
var count3 = float.Parse(stat.GetState("llm_total_cost", "0"));
|
var total_cost = float.Parse(stat.GetState("llm_total_cost", "0"));
|
||||||
stat.SetState("llm_total_cost", stats.PromptCount / 1000f * stats.PromptCost + stats.CompletionCount / 1000f * stats.CompletionCost + count3);
|
total_cost += Cost;
|
||||||
|
stat.SetState("llm_total_cost", total_cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrintStatistics()
|
public void PrintStatistics()
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ public class EvaluatingService : IEvaluatingService
|
||||||
public async Task<Conversation> Execute(string task, EvaluationRequest request)
|
public async Task<Conversation> Execute(string task, EvaluationRequest request)
|
||||||
{
|
{
|
||||||
var agentService = _services.GetRequiredService<IAgentService>();
|
var agentService = _services.GetRequiredService<IAgentService>();
|
||||||
var evaluator = await agentService.GetAgent(_settings.EvaluatorId);
|
var evaluator = await agentService.GetAgent(_settings.AgentId);
|
||||||
// Task execution mode
|
// Task execution mode
|
||||||
evaluator.Instruction = evaluator.Templates.First(x => x.Name == "instruction.executor").Content;
|
evaluator.Instruction = evaluator.Templates.First(x => x.Name == "instruction.executor").Content;
|
||||||
var taskPrompt = evaluator.Templates.First(x => x.Name == $"task.{task}").Content;
|
var taskPrompt = evaluator.Templates.First(x => x.Name == $"task.{task}").Content;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using BotSharp.Abstraction.MLTasks;
|
using BotSharp.Abstraction.MLTasks;
|
||||||
using BotSharp.Abstraction.MLTasks.Settings;
|
|
||||||
|
|
||||||
namespace BotSharp.Core.Infrastructures;
|
namespace BotSharp.Core.Infrastructures;
|
||||||
|
|
||||||
|
|
@ -7,19 +6,18 @@ public class CompletionProvider
|
||||||
{
|
{
|
||||||
public static IChatCompletion GetChatCompletion(IServiceProvider services, string? provider = null, string? model = null)
|
public static IChatCompletion GetChatCompletion(IServiceProvider services, string? provider = null, string? model = null)
|
||||||
{
|
{
|
||||||
var settings = services.GetRequiredService<ChatCompletionSetting>();
|
|
||||||
var completions = services.GetServices<IChatCompletion>();
|
var completions = services.GetServices<IChatCompletion>();
|
||||||
|
|
||||||
var state = services.GetRequiredService<IConversationStateService>();
|
var state = services.GetRequiredService<IConversationStateService>();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(provider))
|
if (string.IsNullOrEmpty(provider))
|
||||||
{
|
{
|
||||||
provider = state.GetState("provider", settings.Provider ?? "azure-openai");
|
provider = state.GetState("provider", "azure-openai");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(model))
|
if (string.IsNullOrEmpty(model))
|
||||||
{
|
{
|
||||||
model = state.GetState("model", settings.Model ?? "gpt-3.5-turbo");
|
model = state.GetState("model", "gpt-35-turbo-4k");
|
||||||
}
|
}
|
||||||
|
|
||||||
var completer = completions.FirstOrDefault(x => x.Provider == provider);
|
var completer = completions.FirstOrDefault(x => x.Provider == provider);
|
||||||
|
|
@ -36,19 +34,18 @@ public class CompletionProvider
|
||||||
|
|
||||||
public static ITextCompletion GetTextCompletion(IServiceProvider services, string? provider = null, string? model = null)
|
public static ITextCompletion GetTextCompletion(IServiceProvider services, string? provider = null, string? model = null)
|
||||||
{
|
{
|
||||||
var settings = services.GetRequiredService<TextCompletionSetting>();
|
|
||||||
var completions = services.GetServices<ITextCompletion>();
|
var completions = services.GetServices<ITextCompletion>();
|
||||||
|
|
||||||
var state = services.GetRequiredService<IConversationStateService>();
|
var state = services.GetRequiredService<IConversationStateService>();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(provider))
|
if (string.IsNullOrEmpty(provider))
|
||||||
{
|
{
|
||||||
provider = state.GetState("provider", settings.Provider ?? "azure-openai");
|
provider = state.GetState("provider", "azure-openai");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(model))
|
if (string.IsNullOrEmpty(model))
|
||||||
{
|
{
|
||||||
model = state.GetState("model", settings.Model ?? "gpt-3.5-turbo");
|
model = state.GetState("model", "gpt-35-turbo-instruct");
|
||||||
}
|
}
|
||||||
|
|
||||||
var completer = completions.FirstOrDefault(x => x.Provider == provider);
|
var completer = completions.FirstOrDefault(x => x.Provider == provider);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
using BotSharp.Abstraction.MLTasks;
|
||||||
|
using BotSharp.Abstraction.MLTasks.Settings;
|
||||||
|
|
||||||
|
namespace BotSharp.Core.Infrastructures;
|
||||||
|
|
||||||
|
public class LlmProviderSettingService : ILlmProviderSettingService
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _services;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public LlmProviderSettingService(IServiceProvider services, ILogger<LlmProviderSettingService> logger)
|
||||||
|
{
|
||||||
|
_services = services;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LlmModelSetting? GetSetting(string provider, string model)
|
||||||
|
{
|
||||||
|
var settings = _services.GetRequiredService<List<LlmProviderSetting>>();
|
||||||
|
var providerSetting = settings.FirstOrDefault(p => p.Provider.Equals(provider, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
if (providerSetting == null)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Can't find provider settings for {provider}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var modelSetting = providerSetting.Models.FirstOrDefault(m => m.Name.Equals(model, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
if (modelSetting == null)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Can't find model settings for {provider}.{model}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modelSetting;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,10 +30,9 @@ public class HFPlanner : IPlaner
|
||||||
RoleDialogModel response = default;
|
RoleDialogModel response = default;
|
||||||
var inst = new FunctionCallFromLlm();
|
var inst = new FunctionCallFromLlm();
|
||||||
|
|
||||||
var routerSetting = _services.GetRequiredService<RoutingSettings>();
|
|
||||||
var completion = CompletionProvider.GetChatCompletion(_services,
|
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||||
provider: routerSetting.Provider,
|
provider: router?.LlmConfig?.Provider,
|
||||||
model: routerSetting.Model);
|
model: router?.LlmConfig?.Model);
|
||||||
|
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
while (retryCount < 3)
|
while (retryCount < 3)
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,9 @@ public class NaivePlanner : IPlaner
|
||||||
var completion = CompletionProvider.GetTextCompletion(_services);*/
|
var completion = CompletionProvider.GetTextCompletion(_services);*/
|
||||||
|
|
||||||
// chat completion
|
// chat completion
|
||||||
var routerSetting = _services.GetRequiredService<RoutingSettings>();
|
|
||||||
var completion = CompletionProvider.GetChatCompletion(_services,
|
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||||
provider: routerSetting.Provider,
|
provider: router?.LlmConfig?.Provider,
|
||||||
model: routerSetting.Model);
|
model: router?.LlmConfig?.Model);
|
||||||
|
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
while (retryCount < 3)
|
while (retryCount < 3)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ namespace BotSharp.Core.Routing.Hooks;
|
||||||
public class RoutingAgentHook : AgentHookBase
|
public class RoutingAgentHook : AgentHookBase
|
||||||
{
|
{
|
||||||
private readonly RoutingSettings _routingSetting;
|
private readonly RoutingSettings _routingSetting;
|
||||||
public override string SelfId => _routingSetting.RouterId;
|
public override string SelfId => _routingSetting.AgentId;
|
||||||
|
|
||||||
public RoutingAgentHook(IServiceProvider services, AgentSettings settings, RoutingSettings routingSetting)
|
public RoutingAgentHook(IServiceProvider services, AgentSettings settings, RoutingSettings routingSetting)
|
||||||
: base(services, settings)
|
: base(services, settings)
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,9 @@ public partial class RoutingService
|
||||||
var agentService = _services.GetRequiredService<IAgentService>();
|
var agentService = _services.GetRequiredService<IAgentService>();
|
||||||
var agent = await agentService.LoadAgent(agentId);
|
var agent = await agentService.LoadAgent(agentId);
|
||||||
|
|
||||||
var chatCompletion = CompletionProvider.GetChatCompletion(_services);
|
var chatCompletion = CompletionProvider.GetChatCompletion(_services,
|
||||||
|
provider: agent?.LlmConfig?.Provider,
|
||||||
|
model: agent.LlmConfig?.Model);
|
||||||
|
|
||||||
var message = dialogs.Last();
|
var message = dialogs.Last();
|
||||||
var response = chatCompletion.GetChatCompletions(agent, dialogs);
|
var response = chatCompletion.GetChatCompletions(agent, dialogs);
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ public partial class RoutingService : IRoutingService
|
||||||
public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message)
|
public async Task<RoleDialogModel> InstructLoop(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
var agentService = _services.GetRequiredService<IAgentService>();
|
var agentService = _services.GetRequiredService<IAgentService>();
|
||||||
_router = await agentService.LoadAgent(_settings.RouterId);
|
_router = await agentService.LoadAgent(_settings.AgentId);
|
||||||
|
|
||||||
RoleDialogModel response = default;
|
RoleDialogModel response = default;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@ public class TokenStatsConversationHook : IContentGeneratingHook
|
||||||
public async Task AfterGenerated(RoleDialogModel message, TokenStatsModel tokenStats)
|
public async Task AfterGenerated(RoleDialogModel message, TokenStatsModel tokenStats)
|
||||||
{
|
{
|
||||||
_tokenStatistics.StopTimer();
|
_tokenStatistics.StopTimer();
|
||||||
tokenStats.PromptCost = 0.0015f;
|
|
||||||
tokenStats.CompletionCost = 0.002f;
|
|
||||||
_tokenStatistics.AddToken(tokenStats);
|
_tokenStatistics.AddToken(tokenStats);
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
using BotSharp.Abstraction.Conversations.Enums;
|
|
||||||
using BotSharp.Abstraction.Conversations.Models;
|
|
||||||
|
|
||||||
namespace BotSharp.OpenAPI.ViewModels.Conversations;
|
namespace BotSharp.OpenAPI.ViewModels.Conversations;
|
||||||
|
|
||||||
public class NewMessageModel : IncomingMessageModel
|
public class NewMessageModel : IncomingMessageModel
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ public class AzureOpenAiPlugin : IBotSharpPlugin
|
||||||
config.Bind("AzureOpenAi", settings);
|
config.Bind("AzureOpenAi", settings);
|
||||||
services.AddSingleton(x =>
|
services.AddSingleton(x =>
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Loaded AzureOpenAi settings: ({settings.Endpoint}) {settings.ApiKey.SubstringMax(4)}");
|
Console.WriteLine($"Loaded AzureOpenAi settings");
|
||||||
return settings;
|
return settings;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ public class ChatCompletionProvider : IChatCompletion
|
||||||
hook.BeforeGenerating(agent, conversations).Wait();
|
hook.BeforeGenerating(agent, conversations).Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
var client = ProviderHelper.GetClient(_model, _settings);
|
var client = ProviderHelper.GetClient(_model, _services);
|
||||||
var (prompt, chatCompletionsOptions) = PrepareOptions(agent, conversations);
|
var (prompt, chatCompletionsOptions) = PrepareOptions(agent, conversations);
|
||||||
chatCompletionsOptions.DeploymentName = _model;
|
chatCompletionsOptions.DeploymentName = _model;
|
||||||
var response = client.GetChatCompletions(chatCompletionsOptions);
|
var response = client.GetChatCompletions(chatCompletionsOptions);
|
||||||
|
|
@ -81,6 +81,7 @@ public class ChatCompletionProvider : IChatCompletion
|
||||||
hook.AfterGenerated(responseMessage, new TokenStatsModel
|
hook.AfterGenerated(responseMessage, new TokenStatsModel
|
||||||
{
|
{
|
||||||
Prompt = prompt,
|
Prompt = prompt,
|
||||||
|
Provider = Provider,
|
||||||
Model = _model,
|
Model = _model,
|
||||||
PromptCount = response.Value.Usage.PromptTokens,
|
PromptCount = response.Value.Usage.PromptTokens,
|
||||||
CompletionCount = response.Value.Usage.CompletionTokens
|
CompletionCount = response.Value.Usage.CompletionTokens
|
||||||
|
|
@ -103,7 +104,7 @@ public class ChatCompletionProvider : IChatCompletion
|
||||||
await hook.BeforeGenerating(agent, conversations);
|
await hook.BeforeGenerating(agent, conversations);
|
||||||
}
|
}
|
||||||
|
|
||||||
var client = ProviderHelper.GetClient(_model, _settings);
|
var client = ProviderHelper.GetClient(_model, _services);
|
||||||
var (prompt, chatCompletionsOptions) = PrepareOptions(agent, conversations);
|
var (prompt, chatCompletionsOptions) = PrepareOptions(agent, conversations);
|
||||||
|
|
||||||
chatCompletionsOptions.DeploymentName = _model;
|
chatCompletionsOptions.DeploymentName = _model;
|
||||||
|
|
@ -122,6 +123,7 @@ public class ChatCompletionProvider : IChatCompletion
|
||||||
await hook.AfterGenerated(msg, new TokenStatsModel
|
await hook.AfterGenerated(msg, new TokenStatsModel
|
||||||
{
|
{
|
||||||
Prompt = prompt,
|
Prompt = prompt,
|
||||||
|
Provider = Provider,
|
||||||
Model = _model,
|
Model = _model,
|
||||||
PromptCount = response.Value.Usage.PromptTokens,
|
PromptCount = response.Value.Usage.PromptTokens,
|
||||||
CompletionCount = response.Value.Usage.CompletionTokens
|
CompletionCount = response.Value.Usage.CompletionTokens
|
||||||
|
|
@ -159,7 +161,7 @@ public class ChatCompletionProvider : IChatCompletion
|
||||||
|
|
||||||
public async Task<bool> GetChatCompletionsStreamingAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived)
|
public async Task<bool> GetChatCompletionsStreamingAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived)
|
||||||
{
|
{
|
||||||
var client = ProviderHelper.GetClient(_model, _settings);
|
var client = ProviderHelper.GetClient(_model, _services);
|
||||||
var (prompt, chatCompletionsOptions) = PrepareOptions(agent, conversations);
|
var (prompt, chatCompletionsOptions) = PrepareOptions(agent, conversations);
|
||||||
chatCompletionsOptions.DeploymentName = _model;
|
chatCompletionsOptions.DeploymentName = _model;
|
||||||
var response = await client.GetChatCompletionsStreamingAsync(chatCompletionsOptions);
|
var response = await client.GetChatCompletionsStreamingAsync(chatCompletionsOptions);
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,21 @@
|
||||||
using Azure.AI.OpenAI;
|
using Azure.AI.OpenAI;
|
||||||
using Azure;
|
using Azure;
|
||||||
using System;
|
using System;
|
||||||
using BotSharp.Plugin.AzureOpenAI.Settings;
|
|
||||||
using BotSharp.Abstraction.Conversations.Models;
|
using BotSharp.Abstraction.Conversations.Models;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using BotSharp.Abstraction.MLTasks;
|
||||||
|
|
||||||
namespace BotSharp.Plugin.AzureOpenAI.Providers;
|
namespace BotSharp.Plugin.AzureOpenAI.Providers;
|
||||||
|
|
||||||
public class ProviderHelper
|
public class ProviderHelper
|
||||||
{
|
{
|
||||||
public static OpenAIClient GetClient(string model, AzureOpenAiSettings settings)
|
public static OpenAIClient GetClient(string model, IServiceProvider services)
|
||||||
{
|
{
|
||||||
if (model.Contains("gpt-4") || model.Contains("gpt4"))
|
var settingsService = services.GetRequiredService<ILlmProviderSettingService>();
|
||||||
{
|
var settings = settingsService.GetSetting("azure-openai", model);
|
||||||
var client = new OpenAIClient(new Uri(settings.GPT4.Endpoint), new AzureKeyCredential(settings.GPT4.ApiKey));
|
var client = new OpenAIClient(new Uri(settings.Endpoint), new AzureKeyCredential(settings.ApiKey));
|
||||||
return client;
|
return client;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var client = new OpenAIClient(new Uri(settings.Endpoint), new AzureKeyCredential(settings.ApiKey));
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<RoleDialogModel> GetChatSamples(List<string> lines)
|
public static List<RoleDialogModel> GetChatSamples(List<string> lines)
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public class TextCompletionProvider : ITextCompletion
|
||||||
message
|
message
|
||||||
})).ToArray());
|
})).ToArray());
|
||||||
|
|
||||||
var client = ProviderHelper.GetClient(_model, _settings);
|
var client = ProviderHelper.GetClient(_model, _services);
|
||||||
|
|
||||||
var completionsOptions = new CompletionsOptions()
|
var completionsOptions = new CompletionsOptions()
|
||||||
{
|
{
|
||||||
|
|
@ -87,6 +87,7 @@ public class TextCompletionProvider : ITextCompletion
|
||||||
hook.AfterGenerated(responseMessage, new TokenStatsModel
|
hook.AfterGenerated(responseMessage, new TokenStatsModel
|
||||||
{
|
{
|
||||||
Prompt = text,
|
Prompt = text,
|
||||||
|
Provider = Provider,
|
||||||
Model = _model,
|
Model = _model,
|
||||||
PromptCount = response.Value.Usage.PromptTokens,
|
PromptCount = response.Value.Usage.PromptTokens,
|
||||||
CompletionCount = response.Value.Usage.CompletionTokens
|
CompletionCount = response.Value.Usage.CompletionTokens
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,5 @@ namespace BotSharp.Plugin.AzureOpenAI.Settings;
|
||||||
|
|
||||||
public class AzureOpenAiSettings
|
public class AzureOpenAiSettings
|
||||||
{
|
{
|
||||||
public string ApiKey { get; set; } = string.Empty;
|
|
||||||
public string Endpoint { get; set; } = string.Empty;
|
|
||||||
public GPT4Settings GPT4 { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
namespace BotSharp.Plugin.AzureOpenAI.Settings;
|
|
||||||
|
|
||||||
public class GPT4Settings
|
|
||||||
{
|
|
||||||
public string ApiKey { get; set; }
|
|
||||||
public string Endpoint { get; set; }
|
|
||||||
public string DeploymentModel { get; set; }
|
|
||||||
}
|
|
||||||
|
|
@ -53,7 +53,7 @@ public class RoutingConversationHook: ConversationHookBase
|
||||||
public override async Task OnResponseGenerated(RoleDialogModel message)
|
public override async Task OnResponseGenerated(RoleDialogModel message)
|
||||||
{
|
{
|
||||||
var routerSettings = _services.GetRequiredService<RoutingSettings>();
|
var routerSettings = _services.GetRequiredService<RoutingSettings>();
|
||||||
bool saveFlag = message.CurrentAgentId != routerSettings.RouterId;
|
bool saveFlag = message.CurrentAgentId != routerSettings.AgentId;
|
||||||
|
|
||||||
if (saveFlag)
|
if (saveFlag)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ public class TwilioService
|
||||||
{
|
{
|
||||||
Gather.InputEnum.Speech
|
Gather.InputEnum.Speech
|
||||||
},
|
},
|
||||||
Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{routingSetting.RouterId}")
|
Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{routingSetting.AgentId}")
|
||||||
};
|
};
|
||||||
gather.Say(message);
|
gather.Say(message);
|
||||||
response.Append(gather);
|
response.Append(gather);
|
||||||
|
|
@ -82,7 +82,7 @@ public class TwilioService
|
||||||
var gather = new Gather()
|
var gather = new Gather()
|
||||||
{
|
{
|
||||||
Input = new List<Gather.InputEnum>() { Gather.InputEnum.Speech },
|
Input = new List<Gather.InputEnum>() { Gather.InputEnum.Speech },
|
||||||
Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{routingSetting.RouterId}"),
|
Action = new Uri($"{_settings.CallbackHost}/twilio/voice/{routingSetting.AgentId}"),
|
||||||
ActionOnEmptyResult = true
|
ActionOnEmptyResult = true
|
||||||
};
|
};
|
||||||
if (!string.IsNullOrEmpty(message))
|
if (!string.IsNullOrEmpty(message))
|
||||||
|
|
|
||||||
|
|
@ -13,17 +13,37 @@
|
||||||
"Key": "31ba6052aa6f4569901facc3a41fcb4a"
|
"Key": "31ba6052aa6f4569901facc3a41fcb4a"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"LlmProviders": [
|
||||||
|
{
|
||||||
|
"Provider": "azure-openai",
|
||||||
|
"Models": [
|
||||||
|
{
|
||||||
|
"Name": "gpt-35-turbo",
|
||||||
|
"ApiKey": "",
|
||||||
|
"Endpoint": "https://gpt-35-turbo.openai.azure.com/",
|
||||||
|
"Type": "chat",
|
||||||
|
"PromptCost": 0.0015,
|
||||||
|
"CompletionCost": 0.002
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "gpt-35-turbo-instruct",
|
||||||
|
"ApiKey": "",
|
||||||
|
"Endpoint": "https://gpt-35-turbo-instruct.openai.azure.com/",
|
||||||
|
"Type": "text",
|
||||||
|
"PromptCost": 0.0015,
|
||||||
|
"CompletionCost": 0.002
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
"Router": {
|
"Router": {
|
||||||
"RouterId": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a",
|
"AgentId": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a",
|
||||||
"Planner": "NaivePlanner",
|
"Planner": "NaivePlanner"
|
||||||
"Provider": "azure-openai",
|
|
||||||
"Model": "gpt-3.5-turbo"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"Evaluator": {
|
"Evaluator": {
|
||||||
"EvaluatorId": "dfd9b46d-d00c-40af-8a75-3fbdc2b89869",
|
"AgentId": "dfd9b46d-d00c-40af-8a75-3fbdc2b89869"
|
||||||
"Provider": "azure-openai",
|
|
||||||
"Model": "gpt-3.5-turbo"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"Agent": {
|
"Agent": {
|
||||||
|
|
@ -47,19 +67,7 @@
|
||||||
"NumberOfGpuLayer": 10
|
"NumberOfGpuLayer": 10
|
||||||
},
|
},
|
||||||
|
|
||||||
"ChatCompletion": {
|
|
||||||
"Provider": "azure-openai",
|
|
||||||
"Model": "gpt-3.5-turbo"
|
|
||||||
},
|
|
||||||
|
|
||||||
"TextCompletion": {
|
|
||||||
"Provider": "azure-openai",
|
|
||||||
"Model": "gpt-3.5-turbo"
|
|
||||||
},
|
|
||||||
|
|
||||||
"AzureOpenAi": {
|
"AzureOpenAi": {
|
||||||
"ApiKey": "",
|
|
||||||
"Endpoint": ""
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"GoogleAi": {
|
"GoogleAi": {
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,9 @@
|
||||||
"createdDateTime": "2023-08-18T14:39:32.2349685Z",
|
"createdDateTime": "2023-08-18T14:39:32.2349685Z",
|
||||||
"updatedDateTime": "2023-08-18T14:39:32.2349686Z",
|
"updatedDateTime": "2023-08-18T14:39:32.2349686Z",
|
||||||
"id": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a",
|
"id": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a",
|
||||||
"isPublic": true
|
"isPublic": true,
|
||||||
|
"llmConfig": {
|
||||||
|
"provider": "azure-openai",
|
||||||
|
"model": "gpt-35-turbo"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,5 +3,8 @@
|
||||||
"description": "Evaluate the performance of the LLM agents",
|
"description": "Evaluate the performance of the LLM agents",
|
||||||
"createdDateTime": "2023-08-18T00:00:00Z",
|
"createdDateTime": "2023-08-18T00:00:00Z",
|
||||||
"updatedDateTime": "2023-08-18T00:00:00Z",
|
"updatedDateTime": "2023-08-18T00:00:00Z",
|
||||||
"id": "dfd9b46d-d00c-40af-8a75-3fbdc2b89869"
|
"id": "dfd9b46d-d00c-40af-8a75-3fbdc2b89869",
|
||||||
|
"llmConfig": {
|
||||||
|
"model": "gpt-35-turbo-instruct"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue