Merge pull request #755 from unoplatform/dev/erli/chatgpt-openai-sdk

feat: ChatGPT - Use OpenAI official SDK
This commit is contained in:
Agnès ZITTE 2024-06-27 14:14:03 -04:00 коммит произвёл GitHub
Родитель 38338ca152 c648b69b55
Коммит 3eabc60b94
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
10 изменённых файлов: 54 добавлений и 87 удалений

Просмотреть файл

@ -42,17 +42,15 @@ public partial class App : Application
{
var section = context.Configuration.GetSection(nameof(AppConfig));
var apiKey = section[nameof(AppConfig.ApiKey)];
var useMockService = apiKey is null or { Length: 0 };
if (useMockService)
if (apiKey is null or { Length: 0 })
{
services.AddSingleton<IChatService, MockChatService>();
}
else
{
services
.AddSingleton<OpenAiOptions, ChatAiOptions>()
.AddSingleton<IChatCompletionService, OpenAIService>()
.AddSingleton(new ChatClient("gpt-3.5-turbo", apiKey))
.AddSingleton<IChatService, ChatService>();
}

Просмотреть файл

@ -1,11 +0,0 @@
using OpenAI;
namespace ChatGPT.Business.Models;
public class ChatAiOptions : OpenAiOptions
{
public ChatAiOptions(IOptions<AppConfig> appConfig)
{
this.ApiKey = appConfig.Value.ApiKey ?? throw new InvalidOperationException("You must define an OpenAI API key in appsettings.json file.");
}
}

Просмотреть файл

@ -29,8 +29,7 @@
Configuration;
</UnoFeatures>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Betalgo.OpenAI" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="OpenAI" />
</ItemGroup>
</Project>

Просмотреть файл

@ -6,8 +6,7 @@ global using Microsoft.Extensions.Options;
global using ChatGPT.Business.Models;
global using ChatGPT.Presentation;
global using ChatGPT.Services;
global using ChatGPT.Business;
global using OpenAI.Chat;
global using ApplicationExecutionState = Windows.ApplicationModel.Activation.ApplicationExecutionState;
global using Color = Windows.UI.Color;
global using OpenAI;
global using OpenAI.Interfaces;
global using OpenAI.Managers;
global using Color = Windows.UI.Color;

Просмотреть файл

@ -1,7 +1,4 @@
using ChatGPT.Business;
using ChatGPT.Services;
namespace ChatGPT.Presentation;
namespace ChatGPT.Presentation;
public partial record MainModel
{

Просмотреть файл

@ -1,6 +1,4 @@
using ChatGPT.Business;
namespace ChatGPT.Presentation;
namespace ChatGPT.Presentation;
public partial record Message(Guid Id, Source Source, Status Status, string? Content)
{

Просмотреть файл

@ -1,39 +1,37 @@
using ChatGPT.Business;
using OpenAI.Interfaces;
using OpenAI.ObjectModels;
using OpenAI.ObjectModels.RequestModels;
using OpenAI.ObjectModels.ResponseModels;
using System.ClientModel;
using System.Runtime.CompilerServices;
using System.Text;
namespace ChatGPT.Services;
public class ChatService(IChatCompletionService client) : IChatService
public class ChatService : IChatService
{
private readonly IChatCompletionService _client = client;
private const string systemPrompt = "You are Uno ChatGPT Sample, a helpful assistant helping users to learn more about how to develop using Uno Platform.";
private readonly ChatClient _client;
public ChatService(ChatClient client)
{
_client = client;
}
public async ValueTask<ChatResponse> AskAsync(ChatRequest chatRequest, CancellationToken ct = default)
{
try
{
var request = ToCompletionRequest(chatRequest);
var result = await _client.CreateCompletion(request, cancellationToken: ct);
ChatCompletion result = await _client.CompleteChatAsync(request);
if (result.Successful)
return result.FinishReason switch
{
var response = result.Choices.Select(choice => choice.Message.Content);
return new ChatResponse(string.Join("", response));
}
else
{
return new ChatResponse(result.Error?.Message, IsError: true);
}
ChatFinishReason.Stop => new ChatResponse(result.ToString()),
ChatFinishReason.Length => new ChatResponse("Incomplete model output due to MaxTokens parameter or token limit exceeded.", IsError: true),
ChatFinishReason.ContentFilter => new ChatResponse("Omitted content due to a content filter flag.", IsError: true),
_ => new ChatResponse(result.FinishReason.ToString())
};
}
catch (Exception)
catch (Exception ex)
{
return new ChatResponse(IsError: true);
return new ChatResponse($"Something went wrong: {ex.Message}", IsError: true);
}
}
@ -43,56 +41,46 @@ public class ChatService(IChatCompletionService client) : IChatService
var response = new ChatResponse();
var content = new StringBuilder();
IAsyncEnumerator<ChatCompletionCreateResponse>? responseStream = default;
IAsyncEnumerator<StreamingChatCompletionUpdate>? responseStream = default;
while (!response.IsError)
{
try
{
responseStream ??= _client.CreateCompletionAsStream(request).GetAsyncEnumerator(ct);
responseStream ??= _client.CompleteChatStreamingAsync(request).GetAsyncEnumerator(ct);
if (await responseStream.MoveNextAsync())
{
if (responseStream.Current.Successful)
foreach (var updatePart in responseStream.Current.ContentUpdate)
{
foreach (var choice in responseStream.Current.Choices)
{
content.Append(choice.Message.Content);
}
response = response with { Message = content.ToString() };
}
else
{
response = response with { Message = responseStream.Current.Error?.Message, IsError = true };
content.Append(updatePart.Text);
}
response = response with { Message = content.ToString() };
}
else
{
yield break;
}
}
catch (Exception)
catch (Exception ex)
{
response = response with { IsError = true };
response = response with { Message = $"Something went wrong: {ex.Message}", IsError = true };
}
yield return response;
}
}
private ChatCompletionCreateRequest ToCompletionRequest(ChatRequest request)
{
var history = request.History;
var requestMessages = new List<ChatMessage>(history.Count + 1)
{
ChatMessage.FromSystem(systemPrompt)
};
requestMessages.AddRange(history.Select(entry => entry.IsUser
? ChatMessage.FromUser(entry.Message)
: ChatMessage.FromAssistant(entry.Message)));
private ChatMessage[] ToCompletionRequest(ChatRequest request)
=> request.History
.Select(ConvertMessage)
.Prepend(ChatMessage.CreateSystemMessage(systemPrompt))
.ToArray();
return new ChatCompletionCreateRequest()
{
Messages = requestMessages,
Model = Models.Gpt_3_5_Turbo
};
}
private ChatMessage ConvertMessage(ChatEntry entry)
=> entry.IsUser
? ChatMessage.CreateUserMessage(entry.Message)
: ChatMessage.CreateAssistantMessage(entry.Message);
}

Просмотреть файл

@ -1,6 +1,4 @@
using ChatGPT.Business;
namespace ChatGPT.Services;
namespace ChatGPT.Services;
public interface IChatService
{
ValueTask<ChatResponse> AskAsync(ChatRequest request, CancellationToken ct = default);

Просмотреть файл

@ -1,5 +1,4 @@
using ChatGPT.Business;
using System.Runtime.CompilerServices;
using System.Runtime.CompilerServices;
using System.Text;
namespace ChatGPT.Services;

Просмотреть файл

@ -5,6 +5,8 @@
See https://aka.platform.uno/using-uno-sdk for more information.
-->
<ItemGroup>
<PackageVersion Include="Betalgo.OpenAI" Version="7.4.3" />
</ItemGroup>
</Project>
<ItemGroup>
<PackageVersion Include="OpenAI" Version="2.0.0-beta.7" />
</ItemGroup>
</Project>