TextCompletion of google-ai
This commit is contained in:
parent
caf60693a4
commit
c9822dd7ee
|
|
@ -2,7 +2,7 @@
|
|||
<PropertyGroup>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<OutputPath>..\..\..\packages</OutputPath>
|
||||
<BotSharpVersion>0.15.1</BotSharpVersion>
|
||||
<BotSharpVersion>0.16.0</BotSharpVersion>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -12,6 +12,7 @@ public class RoutingSettings
|
|||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
public bool EnableReasoning { get; set; } = false;
|
||||
public bool UseTextCompletion { get; set; } = false;
|
||||
|
||||
public string Provider { get; set; } = string.Empty;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,21 +18,6 @@ public static class StringExtensions
|
|||
return str;
|
||||
}
|
||||
|
||||
public static string CleanPhoneNumber(this string phoneNumber)
|
||||
{
|
||||
if (phoneNumber != null && !phoneNumber.All(char.IsDigit))
|
||||
{
|
||||
phoneNumber = Regex.Replace(phoneNumber, @"[^\d]", "");
|
||||
}
|
||||
|
||||
if (phoneNumber != null && phoneNumber.Length > 10)
|
||||
{
|
||||
phoneNumber = phoneNumber.Substring(1);
|
||||
}
|
||||
|
||||
return phoneNumber;
|
||||
}
|
||||
|
||||
public static string[] SplitByNewLine(this string input)
|
||||
{
|
||||
return input.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
|
|
|||
|
|
@ -31,4 +31,32 @@ public class CompletionProvider
|
|||
|
||||
return completer;
|
||||
}
|
||||
|
||||
public static ITextCompletion GetTextCompletion(IServiceProvider services, string? provider = null, string? model = null)
|
||||
{
|
||||
var completions = services.GetServices<ITextCompletion>();
|
||||
|
||||
var state = services.GetRequiredService<IConversationStateService>();
|
||||
|
||||
if (string.IsNullOrEmpty(provider))
|
||||
{
|
||||
provider = state.GetState("provider", "azure-openai");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(model))
|
||||
{
|
||||
model = state.GetState("model", "gpt-3.5-turbo");
|
||||
}
|
||||
|
||||
var completer = completions.FirstOrDefault(x => x.Provider == provider);
|
||||
if (completer == null)
|
||||
{
|
||||
var logger = services.GetRequiredService<ILogger<CompletionProvider>>();
|
||||
logger.LogError($"Can't resolve completion provider by {provider}");
|
||||
}
|
||||
|
||||
completer.SetModelName(model);
|
||||
|
||||
return completer;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Routing;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using System.Drawing;
|
||||
using System.Text.RegularExpressions;
|
||||
|
|
@ -19,16 +18,30 @@ public partial class RoutingService
|
|||
var content = $"{prompt} Response must be in JSON format {responseFormat}";
|
||||
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
var provider = state.GetState("provider", _settings.Provider);
|
||||
var model = state.GetState("model", _settings.Model);
|
||||
var chatCompletion = CompletionProvider.GetChatCompletion(_services,
|
||||
provider: provider,
|
||||
model: model);
|
||||
|
||||
|
||||
var response = chatCompletion.GetChatCompletions(_routerInstance.Router, new List<RoleDialogModel>
|
||||
RoleDialogModel response = default;
|
||||
if (_settings.UseTextCompletion)
|
||||
{
|
||||
var completion = CompletionProvider.GetTextCompletion(_services,
|
||||
provider: _settings.Provider,
|
||||
model: _settings.Model);
|
||||
|
||||
content = _routerInstance.Router.Instruction + "\r\n\r\n" + content + "\r\nResponse: ";
|
||||
var text = await completion.GetCompletion(content);
|
||||
response = new RoleDialogModel(AgentRole.Assistant, text);
|
||||
}
|
||||
else
|
||||
{
|
||||
var completion = CompletionProvider.GetChatCompletion(_services,
|
||||
provider: _settings.Provider,
|
||||
model: _settings.Model);
|
||||
|
||||
response = completion.GetChatCompletions(_routerInstance.Router, new List<RoleDialogModel>
|
||||
{
|
||||
new RoleDialogModel(AgentRole.User, content)
|
||||
});
|
||||
}
|
||||
|
||||
var args = new FunctionCallFromLlm();
|
||||
try
|
||||
|
|
|
|||
|
|
@ -37,59 +37,15 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
_tokenStatistics = tokenStatistics;
|
||||
}
|
||||
|
||||
protected virtual (OpenAIClient, string) GetClient()
|
||||
{
|
||||
if (_model == "gpt-4")
|
||||
{
|
||||
var client = new OpenAIClient(new Uri(_settings.GPT4.Endpoint), new AzureKeyCredential(_settings.GPT4.ApiKey));
|
||||
return (client, _settings.GPT4.DeploymentModel);
|
||||
}
|
||||
else
|
||||
{
|
||||
var client = new OpenAIClient(new Uri(_settings.Endpoint), new AzureKeyCredential(_settings.ApiKey));
|
||||
return (client, _settings.DeploymentModel.ChatCompletionModel);
|
||||
}
|
||||
}
|
||||
|
||||
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 RoleDialogModel GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
|
||||
{
|
||||
var (client, deploymentModel) = GetClient();
|
||||
var (client, deploymentModel) = ProviderHelper.GetClient(_model, _settings);
|
||||
var chatCompletionsOptions = PrepareOptions(agent, conversations);
|
||||
|
||||
_tokenStatistics.StartTimer();
|
||||
var response = client.GetChatCompletions(deploymentModel, chatCompletionsOptions);
|
||||
_tokenStatistics.StopTimer();
|
||||
|
||||
var choice = response.Value.Choices[0];
|
||||
var message = choice.Message;
|
||||
|
||||
|
|
@ -104,7 +60,7 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
|
||||
if (choice.FinishReason == CompletionsFinishReason.FunctionCall)
|
||||
{
|
||||
_logger.LogInformation($"[{agent.Name}]: {message.FunctionCall.Name} => {message.FunctionCall.Arguments}");
|
||||
_logger.LogInformation($"[{agent.Name}]: {message.FunctionCall.Name}({message.FunctionCall.Arguments})");
|
||||
|
||||
var funcContextIn = new RoleDialogModel(AgentRole.Function, message.Content)
|
||||
{
|
||||
|
|
@ -137,7 +93,7 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
Func<RoleDialogModel, Task> onMessageReceived,
|
||||
Func<RoleDialogModel, Task> onFunctionExecuting)
|
||||
{
|
||||
var (client, deploymentModel) = GetClient();
|
||||
var (client, deploymentModel) = ProviderHelper.GetClient(_model, _settings);
|
||||
var chatCompletionsOptions = PrepareOptions(agent, conversations);
|
||||
|
||||
var response = await client.GetChatCompletionsAsync(deploymentModel, chatCompletionsOptions);
|
||||
|
|
@ -155,7 +111,7 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
|
||||
if (choice.FinishReason == CompletionsFinishReason.FunctionCall)
|
||||
{
|
||||
_logger.LogInformation($"[{agent.Name}]: {message.FunctionCall.Name} => {message.FunctionCall.Arguments}");
|
||||
_logger.LogInformation($"[{agent.Name}]: {message.FunctionCall.Name}({message.FunctionCall.Arguments})");
|
||||
|
||||
var funcContextIn = new RoleDialogModel(AgentRole.Function, message.Content)
|
||||
{
|
||||
|
|
@ -246,7 +202,7 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
chatCompletionsOptions.Messages.Add(new ChatMessage(ChatRole.System, agent.Knowledges));
|
||||
}
|
||||
|
||||
var samples = GetChatSamples(agent.Samples);
|
||||
var samples = ProviderHelper.GetChatSamples(agent.Samples);
|
||||
foreach (var message in samples)
|
||||
{
|
||||
chatCompletionsOptions.Messages.Add(new ChatMessage(message.Role, message.Content));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
using Azure.AI.OpenAI;
|
||||
using Azure;
|
||||
using System;
|
||||
using BotSharp.Plugin.AzureOpenAI.Settings;
|
||||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BotSharp.Plugin.AzureOpenAI.Providers;
|
||||
|
||||
public class ProviderHelper
|
||||
{
|
||||
public static (OpenAIClient, string) GetClient(string model, AzureOpenAiSettings settings)
|
||||
{
|
||||
if (model == "gpt-4")
|
||||
{
|
||||
var client = new OpenAIClient(new Uri(settings.GPT4.Endpoint), new AzureKeyCredential(settings.GPT4.ApiKey));
|
||||
return (client, settings.GPT4.DeploymentModel);
|
||||
}
|
||||
else
|
||||
{
|
||||
var client = new OpenAIClient(new Uri(settings.Endpoint), new AzureKeyCredential(settings.ApiKey));
|
||||
return (client, settings.DeploymentModel.ChatCompletionModel);
|
||||
}
|
||||
}
|
||||
|
||||
public static 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +1,68 @@
|
|||
using Azure.AI.OpenAI;
|
||||
using Azure;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using BotSharp.Plugin.AzureOpenAI.Settings;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using BotSharp.Abstraction.Conversations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using BotSharp.Abstraction.Conversations.Models;
|
||||
|
||||
namespace BotSharp.Plugin.AzureOpenAI.Providers;
|
||||
|
||||
public class TextCompletionProvider : ITextCompletion
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly AzureOpenAiSettings _settings;
|
||||
private readonly ILogger _logger;
|
||||
bool _useAzureOpenAI = true;
|
||||
private readonly ITokenStatistics _tokenStatistics;
|
||||
private string _model;
|
||||
public string Provider => "azure-openai";
|
||||
|
||||
public TextCompletionProvider(AzureOpenAiSettings settings, ILogger<TextCompletionProvider> logger)
|
||||
public TextCompletionProvider(IServiceProvider services,
|
||||
AzureOpenAiSettings settings,
|
||||
ILogger<TextCompletionProvider> logger,
|
||||
ITokenStatistics tokenStatistics)
|
||||
{
|
||||
_services = services;
|
||||
_settings = settings;
|
||||
_logger = logger;
|
||||
_tokenStatistics = tokenStatistics;
|
||||
}
|
||||
|
||||
public async Task<string> GetCompletion(string text)
|
||||
{
|
||||
var client = GetOpenAIClient();
|
||||
var (client, _) = ProviderHelper.GetClient(_model, _settings);
|
||||
|
||||
var completionsOptions = new CompletionsOptions()
|
||||
{
|
||||
Prompts =
|
||||
{
|
||||
text
|
||||
},
|
||||
Temperature = 0.7f,
|
||||
MaxTokens = 256
|
||||
};
|
||||
|
||||
var state = _services.GetRequiredService<IConversationStateService>();
|
||||
var temperature = float.Parse(state.GetState("temperature", "0.5"));
|
||||
var samplingFactor = float.Parse(state.GetState("sampling_factor", "0.5"));
|
||||
completionsOptions.Temperature = temperature;
|
||||
completionsOptions.NucleusSamplingFactor = samplingFactor;
|
||||
|
||||
_tokenStatistics.StartTimer();
|
||||
var response = await client.GetCompletionsAsync(
|
||||
deploymentOrModelName: _settings.DeploymentModel.TextCompletionModel,
|
||||
completionsOptions);
|
||||
_tokenStatistics.StopTimer();
|
||||
|
||||
_tokenStatistics.AddToken(new TokenStatsModel
|
||||
{
|
||||
Model = _model,
|
||||
PromptCount = response.Value.Usage.PromptTokens,
|
||||
CompletionCount = response.Value.Usage.CompletionTokens,
|
||||
PromptCost = 0.0015f,
|
||||
CompletionCost = 0.002f
|
||||
});
|
||||
|
||||
// OpenAI
|
||||
var completion = "";
|
||||
|
|
@ -46,7 +71,7 @@ public class TextCompletionProvider : ITextCompletion
|
|||
completion += t.Text;
|
||||
};
|
||||
|
||||
_logger.LogInformation(text + completion);
|
||||
_logger.LogInformation(text);
|
||||
|
||||
return completion.Trim();
|
||||
}
|
||||
|
|
@ -55,14 +80,4 @@ public class TextCompletionProvider : ITextCompletion
|
|||
{
|
||||
_model = model;
|
||||
}
|
||||
|
||||
private OpenAIClient GetOpenAIClient()
|
||||
{
|
||||
OpenAIClient client = _useAzureOpenAI
|
||||
? new OpenAIClient(
|
||||
new Uri(_settings.Endpoint),
|
||||
new AzureKeyCredential(_settings.ApiKey))
|
||||
: new OpenAIClient("your-api-key-from-platform.openai.com");
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,10 +29,9 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
public RoleDialogModel GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
|
||||
{
|
||||
var client = new GooglePalmClient(apiKey: _settings.PaLM.ApiKey);
|
||||
List<PalmChatMessage> messages = new()
|
||||
{
|
||||
new(conversations.Last().Content, "user"),
|
||||
};
|
||||
var messages = conversations.Select(c => new PalmChatMessage(c.Content, c.Role == AgentRole.User ? "user" : "AI"))
|
||||
.ToList();
|
||||
|
||||
_tokenStatistics.StartTimer();
|
||||
var response = client.ChatAsync(messages, agent.Instruction, null).Result;
|
||||
_tokenStatistics.StopTimer();
|
||||
|
|
|
|||
|
|
@ -1,13 +1,42 @@
|
|||
using BotSharp.Abstraction.Conversations;
|
||||
using BotSharp.Plugin.GoogleAI.Settings;
|
||||
using LLMSharp.Google.Palm;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BotSharp.Plugin.GoogleAI.Providers;
|
||||
|
||||
public class TextCompletionProvider : ITextCompletion
|
||||
{
|
||||
public string Provider => "google-ai";
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly GoogleAiSettings _settings;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ITokenStatistics _tokenStatistics;
|
||||
private string _model;
|
||||
|
||||
public Task<string> GetCompletion(string text)
|
||||
public TextCompletionProvider(IServiceProvider services,
|
||||
GoogleAiSettings settings,
|
||||
ILogger<TextCompletionProvider> logger,
|
||||
ITokenStatistics tokenStatistics)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_services = services;
|
||||
_settings = settings;
|
||||
_logger = logger;
|
||||
_tokenStatistics = tokenStatistics;
|
||||
}
|
||||
|
||||
public async Task<string> GetCompletion(string text)
|
||||
{
|
||||
var client = new GooglePalmClient(apiKey: _settings.PaLM.ApiKey);
|
||||
_tokenStatistics.StartTimer();
|
||||
var response = await client.GenerateTextAsync(text, null);
|
||||
_tokenStatistics.StopTimer();
|
||||
|
||||
var message = response.Candidates.First();
|
||||
|
||||
_logger.LogInformation(text);
|
||||
|
||||
return message.Output.Trim();
|
||||
}
|
||||
|
||||
public void SetModelName(string model)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
"RouterId": "01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a",
|
||||
"RouterName": "PizzaBot",
|
||||
"Description": "Pizza restaurant AI Bot",
|
||||
"UseTextCompletion": false,
|
||||
"EnableReasoning": false,
|
||||
"Provider": "azure-openai",
|
||||
"Model": "gpt-3.5-turbo"
|
||||
|
|
|
|||
Loading…
Reference in a new issue