From 0aac7a82f23d49ab60991b2a66878c2f09650d27 Mon Sep 17 00:00:00 2001 From: HuZehua Date: Tue, 5 Sep 2023 14:38:17 +0800 Subject: [PATCH 1/4] Modify the ChatCompletionCreateResponse class --- .../ResponseModels/ChatCompletionCreateResponse.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs index 0615826a..e2dfd4b3 100644 --- a/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs +++ b/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs @@ -6,10 +6,11 @@ namespace OpenAI.ObjectModels.ResponseModels; public record ChatCompletionCreateResponse : BaseResponse, IOpenAiModels.IId, IOpenAiModels.ICreatedAt { [JsonPropertyName("model")] public string Model { get; set; } + [JsonPropertyName("object")] public string Type { get; set; } [JsonPropertyName("choices")] public List Choices { get; set; } - [JsonPropertyName("usage")] public UsageResponse Usage { get; set; } + [JsonPropertyName("usage")] public UsageResponse? Usage { get; set; } [JsonPropertyName("created")] public int CreatedAt { get; set; } From 6a2dca4087718e030fd93c0ee173983e657b8256 Mon Sep 17 00:00:00 2001 From: HuZehua Date: Tue, 5 Sep 2023 15:18:13 +0800 Subject: [PATCH 2/4] Modified some nullability checks in ChatCompletion return objects --- OpenAI.SDK/Managers/OpenAIChatCompletions.cs | 27 +++++++++++++------ .../ObjectModels/RequestModels/ChatMessage.cs | 9 ++++--- .../ChatCompletionCreateResponse.cs | 2 +- .../SharedModels/ChatChoiceResponse.cs | 6 ++--- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/OpenAI.SDK/Managers/OpenAIChatCompletions.cs b/OpenAI.SDK/Managers/OpenAIChatCompletions.cs index 8018c604..f4b86be4 100644 --- a/OpenAI.SDK/Managers/OpenAIChatCompletions.cs +++ b/OpenAI.SDK/Managers/OpenAIChatCompletions.cs @@ -10,14 +10,18 @@ namespace OpenAI.Managers; public partial class OpenAIService : IChatCompletionService { /// - public async Task CreateCompletion(ChatCompletionCreateRequest chatCompletionCreateRequest, string? modelId = null, CancellationToken cancellationToken = default) + public async Task CreateCompletion( + ChatCompletionCreateRequest chatCompletionCreateRequest, string? modelId = null, + CancellationToken cancellationToken = default) { chatCompletionCreateRequest.ProcessModelId(modelId, _defaultModelId); - return await _httpClient.PostAndReadAsAsync(_endpointProvider.ChatCompletionCreate(), chatCompletionCreateRequest, cancellationToken); + return await _httpClient.PostAndReadAsAsync( + _endpointProvider.ChatCompletionCreate(), chatCompletionCreateRequest, cancellationToken); } /// - public async IAsyncEnumerable CreateCompletionAsStream(ChatCompletionCreateRequest chatCompletionCreateRequest, string? modelId = null, + public async IAsyncEnumerable CreateCompletionAsStream( + ChatCompletionCreateRequest chatCompletionCreateRequest, string? modelId = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { // Helper data in case we need to reassemble a multi-packet response @@ -29,7 +33,8 @@ public async IAsyncEnumerable CreateCompletionAsSt // Send the request to the CompletionCreate endpoint chatCompletionCreateRequest.ProcessModelId(modelId, _defaultModelId); - using var response = _httpClient.PostAsStreamAsync(_endpointProvider.ChatCompletionCreate(), chatCompletionCreateRequest, cancellationToken); + using var response = _httpClient.PostAsStreamAsync(_endpointProvider.ChatCompletionCreate(), + chatCompletionCreateRequest, cancellationToken); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken); using var reader = new StreamReader(stream); @@ -117,16 +122,22 @@ public void Process(ChatCompletionCreateResponse block) // We're going to steal the partial message and squirrel it away for the time being. if (!IsFnAssemblyActive && isStreamingFnCall) { - FnCall = firstChoice.Message.FunctionCall; - firstChoice.Message.FunctionCall = null; - justStarted = true; + if (firstChoice.Message != null) + { + FnCall = firstChoice.Message.FunctionCall; + firstChoice.Message.FunctionCall = null; + justStarted = true; + } } // As long as we're assembling, keep on appending those args // (Skip the first one, because it was already processed in the block above) if (IsFnAssemblyActive && !justStarted) { - FnCall.Arguments += ExtractArgsSoFar(); + if (FnCall != null) + { + FnCall.Arguments += ExtractArgsSoFar(); + } } // If we were assembling and it just finished, fill this block with the info we've assembled, and we're done. diff --git a/OpenAI.SDK/ObjectModels/RequestModels/ChatMessage.cs b/OpenAI.SDK/ObjectModels/RequestModels/ChatMessage.cs index 037f3ac1..02b4fb0a 100644 --- a/OpenAI.SDK/ObjectModels/RequestModels/ChatMessage.cs +++ b/OpenAI.SDK/ObjectModels/RequestModels/ChatMessage.cs @@ -18,10 +18,11 @@ public class ChatMessage /// length of 64 characters. /// /// The name and arguments of a function that should be called, as generated by the model. - public ChatMessage(string role, string content, string? name = null, FunctionCall? functionCall = null) + public ChatMessage(string? role = null, string? content = null, string? name = null, + FunctionCall? functionCall = null) { - Role = role; - Content = content; + Role = role ?? string.Empty; + Content = content ?? string.Empty; Name = name; FunctionCall = functionCall; } @@ -30,7 +31,7 @@ public ChatMessage(string role, string content, string? name = null, FunctionCal /// The role of the author of this message. One of system, user, or assistant. /// [JsonPropertyName("role")] - public string Role { get; set; } + public string? Role { get; set; } /// /// The contents of the message. diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs index e2dfd4b3..dfd99504 100644 --- a/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs +++ b/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs @@ -8,7 +8,7 @@ public record ChatCompletionCreateResponse : BaseResponse, IOpenAiModels.IId, IO [JsonPropertyName("model")] public string Model { get; set; } [JsonPropertyName("object")] public string Type { get; set; } - [JsonPropertyName("choices")] public List Choices { get; set; } + [JsonPropertyName("choices")] public List? Choices { get; set; } [JsonPropertyName("usage")] public UsageResponse? Usage { get; set; } diff --git a/OpenAI.SDK/ObjectModels/SharedModels/ChatChoiceResponse.cs b/OpenAI.SDK/ObjectModels/SharedModels/ChatChoiceResponse.cs index 441d51b5..a3a7b312 100644 --- a/OpenAI.SDK/ObjectModels/SharedModels/ChatChoiceResponse.cs +++ b/OpenAI.SDK/ObjectModels/SharedModels/ChatChoiceResponse.cs @@ -6,15 +6,15 @@ namespace OpenAI.ObjectModels.SharedModels; public record ChatChoiceResponse { [JsonPropertyName("delta")] - public ChatMessage Delta + public ChatMessage? Delta { get => Message; set => Message = value; } - [JsonPropertyName("message")] public ChatMessage Message { get; set; } + [JsonPropertyName("message")] public ChatMessage? Message { get; set; } [JsonPropertyName("index")] public int? Index { get; set; } - [JsonPropertyName("finish_reason")] public string FinishReason { get; set; } + [JsonPropertyName("finish_reason")] public string? FinishReason { get; set; } } \ No newline at end of file From ff066ba8bdf130f1de931c01c8a78e65ef9d5f93 Mon Sep 17 00:00:00 2001 From: HuZehua Date: Tue, 5 Sep 2023 16:32:41 +0800 Subject: [PATCH 3/4] remove redundant object fields --- .../ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs b/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs index dfd99504..76ea2b5d 100644 --- a/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs +++ b/OpenAI.SDK/ObjectModels/ResponseModels/ChatCompletionCreateResponse.cs @@ -6,7 +6,6 @@ namespace OpenAI.ObjectModels.ResponseModels; public record ChatCompletionCreateResponse : BaseResponse, IOpenAiModels.IId, IOpenAiModels.ICreatedAt { [JsonPropertyName("model")] public string Model { get; set; } - [JsonPropertyName("object")] public string Type { get; set; } [JsonPropertyName("choices")] public List? Choices { get; set; } From 67edfae5e5048d6bf780845e96d38aafeab23ef1 Mon Sep 17 00:00:00 2001 From: Tolga Kayhan Date: Sat, 6 Apr 2024 23:17:13 +0100 Subject: [PATCH 4/4] Code Cleanup --- OpenAI.SDK/Managers/OpenAIChatCompletions.cs | 13 ++++--------- .../ObjectModels/RequestModels/ChatMessage.cs | 3 +-- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/OpenAI.SDK/Managers/OpenAIChatCompletions.cs b/OpenAI.SDK/Managers/OpenAIChatCompletions.cs index f4b86be4..a837d7f4 100644 --- a/OpenAI.SDK/Managers/OpenAIChatCompletions.cs +++ b/OpenAI.SDK/Managers/OpenAIChatCompletions.cs @@ -10,18 +10,14 @@ namespace OpenAI.Managers; public partial class OpenAIService : IChatCompletionService { /// - public async Task CreateCompletion( - ChatCompletionCreateRequest chatCompletionCreateRequest, string? modelId = null, - CancellationToken cancellationToken = default) + public async Task CreateCompletion(ChatCompletionCreateRequest chatCompletionCreateRequest, string? modelId = null, CancellationToken cancellationToken = default) { chatCompletionCreateRequest.ProcessModelId(modelId, _defaultModelId); - return await _httpClient.PostAndReadAsAsync( - _endpointProvider.ChatCompletionCreate(), chatCompletionCreateRequest, cancellationToken); + return await _httpClient.PostAndReadAsAsync(_endpointProvider.ChatCompletionCreate(), chatCompletionCreateRequest, cancellationToken); } /// - public async IAsyncEnumerable CreateCompletionAsStream( - ChatCompletionCreateRequest chatCompletionCreateRequest, string? modelId = null, + public async IAsyncEnumerable CreateCompletionAsStream(ChatCompletionCreateRequest chatCompletionCreateRequest, string? modelId = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { // Helper data in case we need to reassemble a multi-packet response @@ -33,8 +29,7 @@ public async IAsyncEnumerable CreateCompletionAsSt // Send the request to the CompletionCreate endpoint chatCompletionCreateRequest.ProcessModelId(modelId, _defaultModelId); - using var response = _httpClient.PostAsStreamAsync(_endpointProvider.ChatCompletionCreate(), - chatCompletionCreateRequest, cancellationToken); + using var response = _httpClient.PostAsStreamAsync(_endpointProvider.ChatCompletionCreate(), chatCompletionCreateRequest, cancellationToken); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken); using var reader = new StreamReader(stream); diff --git a/OpenAI.SDK/ObjectModels/RequestModels/ChatMessage.cs b/OpenAI.SDK/ObjectModels/RequestModels/ChatMessage.cs index 02b4fb0a..02177ec6 100644 --- a/OpenAI.SDK/ObjectModels/RequestModels/ChatMessage.cs +++ b/OpenAI.SDK/ObjectModels/RequestModels/ChatMessage.cs @@ -18,8 +18,7 @@ public class ChatMessage /// length of 64 characters. /// /// The name and arguments of a function that should be called, as generated by the model. - public ChatMessage(string? role = null, string? content = null, string? name = null, - FunctionCall? functionCall = null) + public ChatMessage(string? role = null, string? content = null, string? name = null, FunctionCall? functionCall = null) { Role = role ?? string.Empty; Content = content ?? string.Empty;