Add Azure OpenAi.

This commit is contained in:
Haiping Chen 2023-05-28 11:30:27 -05:00
parent 4d5ac2111d
commit bae5087642
12 changed files with 164 additions and 23 deletions

View file

@ -1,6 +1,12 @@
using BotSharp.Abstraction.Models;
namespace BotSharp.Abstraction;
public interface IChatCompletionHandler
{
Task GetChatCompletionsAsync(string text, Func<string, bool, Task> onChunkReceived);
Task GetChatCompletionsAsync(string text,
Func<string> GetInstruction,
Func<List<RoleDialogModel>> GetChatHistory,
Func<string, Task> onChunkReceived,
Func<Task> onChunkCompleted);
}

View file

@ -1,6 +1,12 @@
using BotSharp.Abstraction.Models;
namespace BotSharp.Abstraction;
public interface IPlatformMidware
{
Task GetChatCompletionsAsync(string text, Func<string, bool, Task> onChunkReceived);
Task GetChatCompletionsAsync(string text,
Func<string> GetInstruction,
Func<List<RoleDialogModel>> GetChatHistory,
Func<string, Task> onChunkReceived,
Func<Task> onChunkCompleted);
}

View file

@ -0,0 +1,7 @@
namespace BotSharp.Abstraction.Models;
public class RoleDialogModel
{
public string Role { get; set; }
public string Content { get; set; }
}

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Models;
using Microsoft.Extensions.DependencyInjection;
namespace BotSharp.Core.Services;
@ -10,13 +11,21 @@ public class PlatformMidware : IPlatformMidware
_services = services;
}
public async Task GetChatCompletionsAsync(string text, Func<string, bool, Task> onChunkReceived)
public async Task GetChatCompletionsAsync(string text,
Func<string> GetInstruction,
Func<List<RoleDialogModel>> GetChatHistory,
Func<string, Task> onChunkReceived,
Func<Task> onChunkCompleted)
{
var handlers = _services.GetServices<IChatCompletionHandler>().ToList();
for (int i = 0; i < handlers.Count(); i++)
{
var handler = handlers[i];
await handler.GetChatCompletionsAsync(text, onChunkReceived);
await handler.GetChatCompletionsAsync(text,
GetInstruction,
GetChatHistory,
onChunkReceived,
onChunkCompleted);
}
}
}

View file

@ -0,0 +1,21 @@
using BotSharp.Abstraction;
using BotSharp.Platform.AzureAi;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace BotSharp.Core;
public static class AzureAiServiceCollectionExtensions
{
public static IServiceCollection AddAzureOpenAi(this IServiceCollection services, IConfiguration config)
{
services.AddSingleton(x =>
{
var settings = new AzureAiSettings();
config.Bind("AzureAi", settings);
return settings;
});
services.AddScoped<IChatCompletionHandler, ChatCompletionHandler>();
return services;
}
}

View file

@ -0,0 +1,9 @@
namespace BotSharp.Platform.AzureAi;
public class AzureAiSettings
{
public string ApiKey { get; set; }
public string Endpoint { get; set; }
public string DeploymentModel { get; set; }
public string InstructionFile { get; set; }
}

View file

@ -0,0 +1,65 @@
using Azure;
using Azure.AI.OpenAI;
using BotSharp.Abstraction;
using BotSharp.Abstraction.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace BotSharp.Platform.AzureAi;
public class ChatCompletionHandler : IChatCompletionHandler
{
private readonly AzureAiSettings _settings;
public ChatCompletionHandler(AzureAiSettings settings)
{
_settings = settings;
}
public async Task GetChatCompletionsAsync(string text,
Func<string> GetInstruction,
Func<List<RoleDialogModel>> GetChatHistory,
Func<string, Task> onChunkReceived,
Func<Task> onChunkCompleted)
{
var client = new OpenAIClient(new Uri(_settings.Endpoint), new AzureKeyCredential(_settings.ApiKey));
var chatCompletionsOptions = PrepareOptions(text, GetInstruction, GetChatHistory);
var response = await client.GetChatCompletionsStreamingAsync(_settings.DeploymentModel, chatCompletionsOptions);
using StreamingChatCompletions streaming = response.Value;
string content = "";
await foreach (var choice in streaming.GetChoicesStreaming())
{
await foreach (var message in choice.GetMessageStreaming())
{
if (message.Content == null)
continue;
Console.Write(message.Content);
content += message.Content;
await onChunkReceived(message.Content);
}
}
Console.WriteLine();
await onChunkCompleted();
}
private ChatCompletionsOptions PrepareOptions(string text,
Func<string> GetInstruction,
Func<List<RoleDialogModel>> GetChatHistory)
{
var prompt = File.ReadAllText(_settings.InstructionFile);
var chatCompletionsOptions = new ChatCompletionsOptions()
{
Messages =
{
new ChatMessage(ChatRole.System, prompt)
}
};
return chatCompletionsOptions;
}
}

View file

@ -1,7 +1,9 @@
using BotSharp.Abstraction;
using BotSharp.Abstraction.Models;
using BotSharp.Platform.LlamaSharp;
using LLama;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
@ -31,16 +33,21 @@ public class ChatCompletionHandler : IChatCompletionHandler
_model.InitChatAntiprompt(new string[] { "User:" });
}
public Task GetChatCompletionsAsync(string text, Func<string, bool, Task> onChunkReceived)
public async Task GetChatCompletionsAsync(string text,
Func<string> GetInstruction,
Func<List<RoleDialogModel>> GetChatHistory,
Func<string, Task> onChunkReceived,
Func<Task> onChunkCompleted)
{
string totalResponse = "";
foreach (var response in _model.Chat(text, "", "UTF-8"))
{
Console.WriteLine(response);
Console.Write(response);
totalResponse += response;
onChunkReceived(response, false);
await onChunkReceived(response);
}
onChunkReceived("", true);
return Task.CompletedTask;
Console.WriteLine();
await onChunkCompleted();
}
}

View file

@ -59,22 +59,23 @@ public class ChatbotUiController : ControllerBase, IBotUiAdapter
Response.Headers.Add(HeaderNames.Connection, "keep-alive");
var outputStream = Response.Body;
await _platform.GetChatCompletionsAsync(input.Messages.Last().Content, async (content, end) =>
{
if (end)
await _platform.GetChatCompletionsAsync(input.Messages.Last().Content,
delegate
{
if (content.Length > 0)
{
await OnChunkReceived(outputStream, content);
}
await OnEventCompleted(outputStream);
}
else
return "";
},
delegate
{
return new List<RoleDialogModel>();
},
async content =>
{
await OnChunkReceived(outputStream, content);
}
});
},
async () =>
{
await OnEventCompleted(outputStream);
});
}
private async Task OnChunkReceived(Stream outputStream, string content)

View file

@ -12,7 +12,8 @@ builder.Services.AddHttpContextAccessor();
// Add BotSharp
builder.Services.AddBotSharp();
builder.Services.AddLlamaSharp(builder.Configuration);
// builder.Services.AddLlamaSharp(builder.Configuration);
builder.Services.AddAzureOpenAi(builder.Configuration);
var app = builder.Build();

View file

@ -23,7 +23,9 @@
<ItemGroup>
<ProjectReference Include="..\Infrastructure\BotSharp.Core\BotSharp.Core.csproj" />
<ProjectReference Include="..\Platforms\BotSharp.Platform.AureAi\BotSharp.Platform.AzureAi.csproj" />
<ProjectReference Include="..\Platforms\BotSharp.Platform.LlamaSharp\BotSharp.Platform.LlamaSharp.csproj" />
<ProjectReference Include="..\Platforms\BotSharp.Platform.OpenAi\BotSharp.Platform.OpenAi.csproj" />
<ProjectReference Include="..\UiAdapters\ChatbotUI\ChatbotUI.csproj" />
</ItemGroup>

View file

@ -16,5 +16,12 @@
"ModelPath": "C:\\Users\\haipi\\Downloads\\ggml-vic13b-q5_1.bin",
"InstructionFile": "Prompts\\chat-with-bob.txt",
"MaxContextLength": 512
},
"AzureAi": {
"ApiKey": "",
"Endpoint": "",
"InstructionFile": "Prompts\\chat-with-bob.txt",
"DeploymentModel": ""
}
}