Merge pull request #755 from unoplatform/dev/erli/chatgpt-openai-sdk
feat: ChatGPT - Use OpenAI official SDK
This commit is contained in:
Коммит
3eabc60b94
|
@ -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>
|
Загрузка…
Ссылка в новой задаче