From 16fc53b5884c18536b9d26f81aae492ca7af94c0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 11 Jul 2025 15:37:09 +0000 Subject: [PATCH 1/5] Initial plan From 7cd5342f84bc5400d5804e4b48be99932a5cc67d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 11 Jul 2025 15:45:37 +0000 Subject: [PATCH 2/5] Implement ChatModelFactory class in OpenAI namespace Co-authored-by: KrzysztofCwalina <9724236+KrzysztofCwalina@users.noreply.github.com> --- src/Custom/ChatModelFactory.cs | 212 ++++++++++++++++++++ tests/Chat/ChatModelFactoryTests.cs | 295 ++++++++++++++++++++++++++++ 2 files changed, 507 insertions(+) create mode 100644 src/Custom/ChatModelFactory.cs create mode 100644 tests/Chat/ChatModelFactoryTests.cs diff --git a/src/Custom/ChatModelFactory.cs b/src/Custom/ChatModelFactory.cs new file mode 100644 index 000000000..3b8cc6add --- /dev/null +++ b/src/Custom/ChatModelFactory.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using OpenAI.Chat; + +namespace OpenAI; + +/// Model factory for Chat models. +public static partial class ChatModelFactory +{ + /// Initializes a new instance of . + /// A new instance for mocking. + public static ChatCompletion ChatCompletion( + string id = null, + ChatFinishReason finishReason = default, + ChatMessageContent content = null, + string refusal = null, + IEnumerable toolCalls = null, + ChatMessageRole role = default, + IEnumerable contentTokenLogProbabilities = null, + IEnumerable refusalTokenLogProbabilities = null, + DateTimeOffset createdAt = default, + string model = null, + string systemFingerprint = null, + ChatTokenUsage usage = default) + { + return OpenAI.Chat.OpenAIChatModelFactory.ChatCompletion( + id: id, + finishReason: finishReason, + content: content, + refusal: refusal, + toolCalls: toolCalls, + role: role, + functionCall: default, + contentTokenLogProbabilities: contentTokenLogProbabilities, + refusalTokenLogProbabilities: refusalTokenLogProbabilities, + createdAt: createdAt, + model: model, + systemFingerprint: systemFingerprint, + usage: usage); + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static StreamingChatCompletionUpdate StreamingChatCompletionUpdate( + string completionId = null, + ChatMessageContent contentUpdate = null, + IEnumerable toolCallUpdates = null, + ChatMessageRole? role = default, + string refusalUpdate = null, + IEnumerable contentTokenLogProbabilities = null, + IEnumerable refusalTokenLogProbabilities = null, + ChatFinishReason? finishReason = default, + DateTimeOffset createdAt = default, + string model = null, + string systemFingerprint = null, + ChatTokenUsage usage = default) + { + return OpenAI.Chat.OpenAIChatModelFactory.StreamingChatCompletionUpdate( + completionId: completionId, + contentUpdate: contentUpdate, + functionCallUpdate: default, + toolCallUpdates: toolCallUpdates, + role: role, + refusalUpdate: refusalUpdate, + contentTokenLogProbabilities: contentTokenLogProbabilities, + refusalTokenLogProbabilities: refusalTokenLogProbabilities, + finishReason: finishReason, + createdAt: createdAt, + model: model, + systemFingerprint: systemFingerprint, + usage: usage); + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static ChatCompletionDeletionResult ChatCompletionDeletionResult( + bool deleted = true, + string chatCompletionId = null) + { + return new ChatCompletionDeletionResult( + deleted: deleted, + @object: "chat.completion.deleted", + chatCompletionId: chatCompletionId, + additionalBinaryDataProperties: null); + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static UserChatMessage UserChatMessage( + string content = null, + string participantName = null) + { + content ??= "User message content"; + var message = new UserChatMessage(content); + if (participantName != null) + { + message.ParticipantName = participantName; + } + return message; + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static AssistantChatMessage AssistantChatMessage( + string content = null, + IEnumerable toolCalls = null, + string participantName = null) + { + AssistantChatMessage message; + if (toolCalls != null) + { + message = new AssistantChatMessage(toolCalls); + } + else + { + content ??= "Assistant message content"; + message = new AssistantChatMessage(content); + } + + if (participantName != null) + { + message.ParticipantName = participantName; + } + return message; + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static SystemChatMessage SystemChatMessage( + string content = null, + string participantName = null) + { + content ??= "System message content"; + var message = new SystemChatMessage(content); + if (participantName != null) + { + message.ParticipantName = participantName; + } + return message; + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static ToolChatMessage ToolChatMessage( + string toolCallId = "tool_call_id", + string content = null) + { + content ??= "Tool message content"; + return new ToolChatMessage(toolCallId, content); + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static ChatTokenUsage ChatTokenUsage( + int outputTokenCount = default, + int inputTokenCount = default, + int totalTokenCount = default) + { + return OpenAI.Chat.OpenAIChatModelFactory.ChatTokenUsage( + outputTokenCount: outputTokenCount, + inputTokenCount: inputTokenCount, + totalTokenCount: totalTokenCount); + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static ChatTokenLogProbabilityDetails ChatTokenLogProbabilityDetails( + string token = null, + float logProbability = default, + ReadOnlyMemory? utf8Bytes = null, + IEnumerable topLogProbabilities = null) + { + return OpenAI.Chat.OpenAIChatModelFactory.ChatTokenLogProbabilityDetails( + token: token, + logProbability: logProbability, + utf8Bytes: utf8Bytes, + topLogProbabilities: topLogProbabilities); + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static ChatTokenTopLogProbabilityDetails ChatTokenTopLogProbabilityDetails( + string token = null, + float logProbability = default, + ReadOnlyMemory? utf8Bytes = null) + { + return OpenAI.Chat.OpenAIChatModelFactory.ChatTokenTopLogProbabilityDetails( + token: token, + logProbability: logProbability, + utf8Bytes: utf8Bytes); + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static StreamingChatToolCallUpdate StreamingChatToolCallUpdate( + int index = default, + string toolCallId = null, + ChatToolCallKind kind = default, + string functionName = null, + BinaryData functionArgumentsUpdate = null) + { + return OpenAI.Chat.OpenAIChatModelFactory.StreamingChatToolCallUpdate( + index: index, + toolCallId: toolCallId, + kind: kind, + functionName: functionName, + functionArgumentsUpdate: functionArgumentsUpdate); + } +} \ No newline at end of file diff --git a/tests/Chat/ChatModelFactoryTests.cs b/tests/Chat/ChatModelFactoryTests.cs new file mode 100644 index 000000000..03ee08481 --- /dev/null +++ b/tests/Chat/ChatModelFactoryTests.cs @@ -0,0 +1,295 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using OpenAI.Chat; + +namespace OpenAI.Tests.Chat; + +[Parallelizable(ParallelScope.All)] +[Category("Chat")] +[Category("Smoke")] +public partial class ChatModelFactoryTests +{ + [Test] + public void ChatCompletionWithNoPropertiesWorks() + { + ChatCompletion chatCompletion = ChatModelFactory.ChatCompletion(); + + Assert.That(chatCompletion.Id, Is.Null); + Assert.That(chatCompletion.FinishReason, Is.EqualTo(default(ChatFinishReason))); + Assert.That(chatCompletion.Content, Is.Not.Null.And.Empty); + Assert.That(chatCompletion.Refusal, Is.Null); + Assert.That(chatCompletion.ToolCalls, Is.Not.Null.And.Empty); + Assert.That(chatCompletion.Role, Is.EqualTo(default(ChatMessageRole))); + Assert.That(chatCompletion.ContentTokenLogProbabilities, Is.Not.Null.And.Empty); + Assert.That(chatCompletion.RefusalTokenLogProbabilities, Is.Not.Null.And.Empty); + Assert.That(chatCompletion.CreatedAt, Is.EqualTo(default(DateTimeOffset))); + Assert.That(chatCompletion.Model, Is.Null); + Assert.That(chatCompletion.SystemFingerprint, Is.Null); + Assert.That(chatCompletion.Usage, Is.Null); + } + + [Test] + public void ChatCompletionWithIdWorks() + { + string id = "chat_completion_id"; + ChatCompletion chatCompletion = ChatModelFactory.ChatCompletion(id: id); + + Assert.That(chatCompletion.Id, Is.EqualTo(id)); + Assert.That(chatCompletion.FinishReason, Is.EqualTo(default(ChatFinishReason))); + Assert.That(chatCompletion.Content, Is.Not.Null.And.Empty); + Assert.That(chatCompletion.Refusal, Is.Null); + Assert.That(chatCompletion.ToolCalls, Is.Not.Null.And.Empty); + Assert.That(chatCompletion.Role, Is.EqualTo(default(ChatMessageRole))); + Assert.That(chatCompletion.ContentTokenLogProbabilities, Is.Not.Null.And.Empty); + Assert.That(chatCompletion.RefusalTokenLogProbabilities, Is.Not.Null.And.Empty); + Assert.That(chatCompletion.CreatedAt, Is.EqualTo(default(DateTimeOffset))); + Assert.That(chatCompletion.Model, Is.Null); + Assert.That(chatCompletion.SystemFingerprint, Is.Null); + Assert.That(chatCompletion.Usage, Is.Null); + } + + [Test] + public void ChatCompletionWithAllPropertiesWorks() + { + string id = "chat_completion_id"; + ChatFinishReason finishReason = ChatFinishReason.Stop; + ChatMessageContent content = [ChatMessageContentPart.CreateTextPart("Hello, world!")]; + string refusal = "I cannot comply"; + IEnumerable toolCalls = [ + ChatToolCall.CreateFunctionToolCall("id1", "get_weather", BinaryData.FromString("{}")) + ]; + ChatMessageRole role = ChatMessageRole.Assistant; + DateTimeOffset createdAt = DateTimeOffset.UtcNow; + string model = "gpt-4"; + string systemFingerprint = "fp_123"; + ChatTokenUsage usage = ChatModelFactory.ChatTokenUsage(inputTokenCount: 10, outputTokenCount: 20); + + ChatCompletion chatCompletion = ChatModelFactory.ChatCompletion( + id: id, + finishReason: finishReason, + content: content, + refusal: refusal, + toolCalls: toolCalls, + role: role, + createdAt: createdAt, + model: model, + systemFingerprint: systemFingerprint, + usage: usage); + + Assert.That(chatCompletion.Id, Is.EqualTo(id)); + Assert.That(chatCompletion.FinishReason, Is.EqualTo(finishReason)); + Assert.That(chatCompletion.Content.SequenceEqual(content), Is.True); + Assert.That(chatCompletion.Refusal, Is.EqualTo(refusal)); + Assert.That(chatCompletion.ToolCalls.SequenceEqual(toolCalls), Is.True); + Assert.That(chatCompletion.Role, Is.EqualTo(role)); + Assert.That(chatCompletion.CreatedAt, Is.EqualTo(createdAt)); + Assert.That(chatCompletion.Model, Is.EqualTo(model)); + Assert.That(chatCompletion.SystemFingerprint, Is.EqualTo(systemFingerprint)); + Assert.That(chatCompletion.Usage, Is.EqualTo(usage)); + } + + [Test] + public void StreamingChatCompletionUpdateWithNoPropertiesWorks() + { + StreamingChatCompletionUpdate update = ChatModelFactory.StreamingChatCompletionUpdate(); + + Assert.That(update.CompletionId, Is.Null); + Assert.That(update.ContentUpdate, Is.Not.Null.And.Empty); + Assert.That(update.ToolCallUpdates, Is.Not.Null.And.Empty); + Assert.That(update.Role, Is.Null); + Assert.That(update.RefusalUpdate, Is.Null); + Assert.That(update.ContentTokenLogProbabilities, Is.Not.Null.And.Empty); + Assert.That(update.RefusalTokenLogProbabilities, Is.Not.Null.And.Empty); + Assert.That(update.FinishReason, Is.Null); + Assert.That(update.CreatedAt, Is.EqualTo(default(DateTimeOffset))); + Assert.That(update.Model, Is.Null); + Assert.That(update.SystemFingerprint, Is.Null); + Assert.That(update.Usage, Is.Null); + } + + [Test] + public void StreamingChatCompletionUpdateWithPropertiesWorks() + { + string completionId = "completion_id"; + ChatMessageContent contentUpdate = [ChatMessageContentPart.CreateTextPart("Hello")]; + ChatMessageRole role = ChatMessageRole.Assistant; + DateTimeOffset createdAt = DateTimeOffset.UtcNow; + string model = "gpt-4"; + + StreamingChatCompletionUpdate update = ChatModelFactory.StreamingChatCompletionUpdate( + completionId: completionId, + contentUpdate: contentUpdate, + role: role, + createdAt: createdAt, + model: model); + + Assert.That(update.CompletionId, Is.EqualTo(completionId)); + Assert.That(update.ContentUpdate.SequenceEqual(contentUpdate), Is.True); + Assert.That(update.Role, Is.EqualTo(role)); + Assert.That(update.CreatedAt, Is.EqualTo(createdAt)); + Assert.That(update.Model, Is.EqualTo(model)); + } + + [Test] + public void ChatCompletionDeletionResultWorks() + { + string chatCompletionId = "completion_id"; + bool deleted = true; + + ChatCompletionDeletionResult result = ChatModelFactory.ChatCompletionDeletionResult( + deleted: deleted, + chatCompletionId: chatCompletionId); + + Assert.That(result.Deleted, Is.EqualTo(deleted)); + Assert.That(result.ChatCompletionId, Is.EqualTo(chatCompletionId)); + } + + [Test] + public void UserChatMessageWorks() + { + string content = "Hello, assistant!"; + string participantName = "user1"; + + UserChatMessage message = ChatModelFactory.UserChatMessage( + content: content, + participantName: participantName); + + Assert.That(message.Content[0].Text, Is.EqualTo(content)); + Assert.That(message.ParticipantName, Is.EqualTo(participantName)); + Assert.That(message.Role, Is.EqualTo(ChatMessageRole.User)); + } + + [Test] + public void AssistantChatMessageWorks() + { + string content = "Hello, user!"; + IEnumerable toolCalls = [ + ChatToolCall.CreateFunctionToolCall("id1", "get_weather", BinaryData.FromString("{}")) + ]; + string participantName = "assistant1"; + + AssistantChatMessage message = ChatModelFactory.AssistantChatMessage( + content: content, + participantName: participantName); + + Assert.That(message.Content[0].Text, Is.EqualTo(content)); + Assert.That(message.ParticipantName, Is.EqualTo(participantName)); + Assert.That(message.Role, Is.EqualTo(ChatMessageRole.Assistant)); + + // Test with tool calls + AssistantChatMessage messageWithToolCalls = ChatModelFactory.AssistantChatMessage( + toolCalls: toolCalls, + participantName: participantName); + + Assert.That(messageWithToolCalls.ToolCalls.SequenceEqual(toolCalls), Is.True); + Assert.That(messageWithToolCalls.ParticipantName, Is.EqualTo(participantName)); + Assert.That(messageWithToolCalls.Role, Is.EqualTo(ChatMessageRole.Assistant)); + } + + [Test] + public void SystemChatMessageWorks() + { + string content = "You are a helpful assistant"; + string participantName = "system"; + + SystemChatMessage message = ChatModelFactory.SystemChatMessage( + content: content, + participantName: participantName); + + Assert.That(message.Content[0].Text, Is.EqualTo(content)); + Assert.That(message.ParticipantName, Is.EqualTo(participantName)); + Assert.That(message.Role, Is.EqualTo(ChatMessageRole.System)); + } + + [Test] + public void ToolChatMessageWorks() + { + string toolCallId = "tool_call_id"; + string content = "Weather is sunny"; + + ToolChatMessage message = ChatModelFactory.ToolChatMessage( + toolCallId: toolCallId, + content: content); + + Assert.That(message.Content[0].Text, Is.EqualTo(content)); + Assert.That(message.ToolCallId, Is.EqualTo(toolCallId)); + Assert.That(message.Role, Is.EqualTo(ChatMessageRole.Tool)); + } + + [Test] + public void ChatTokenUsageWorks() + { + int inputTokenCount = 100; + int outputTokenCount = 50; + int totalTokenCount = 150; + + ChatTokenUsage usage = ChatModelFactory.ChatTokenUsage( + inputTokenCount: inputTokenCount, + outputTokenCount: outputTokenCount, + totalTokenCount: totalTokenCount); + + Assert.That(usage.InputTokenCount, Is.EqualTo(inputTokenCount)); + Assert.That(usage.OutputTokenCount, Is.EqualTo(outputTokenCount)); + Assert.That(usage.TotalTokenCount, Is.EqualTo(totalTokenCount)); + } + + [Test] + public void ChatTokenLogProbabilityDetailsWorks() + { + string token = "hello"; + float logProbability = -0.5f; + ReadOnlyMemory utf8Bytes = "hello"u8.ToArray(); + + ChatTokenLogProbabilityDetails details = ChatModelFactory.ChatTokenLogProbabilityDetails( + token: token, + logProbability: logProbability, + utf8Bytes: utf8Bytes); + + Assert.That(details.Token, Is.EqualTo(token)); + Assert.That(details.LogProbability, Is.EqualTo(logProbability)); + Assert.That(details.Utf8Bytes.Value.ToArray().SequenceEqual(utf8Bytes.ToArray()), Is.True); + Assert.That(details.TopLogProbabilities, Is.Not.Null.And.Empty); + } + + [Test] + public void ChatTokenTopLogProbabilityDetailsWorks() + { + string token = "hello"; + float logProbability = -0.5f; + ReadOnlyMemory utf8Bytes = "hello"u8.ToArray(); + + ChatTokenTopLogProbabilityDetails details = ChatModelFactory.ChatTokenTopLogProbabilityDetails( + token: token, + logProbability: logProbability, + utf8Bytes: utf8Bytes); + + Assert.That(details.Token, Is.EqualTo(token)); + Assert.That(details.LogProbability, Is.EqualTo(logProbability)); + Assert.That(details.Utf8Bytes.Value.ToArray().SequenceEqual(utf8Bytes.ToArray()), Is.True); + } + + [Test] + public void StreamingChatToolCallUpdateWorks() + { + int index = 0; + string toolCallId = "tool_call_id"; + ChatToolCallKind kind = ChatToolCallKind.Function; + string functionName = "get_weather"; + BinaryData functionArgumentsUpdate = BinaryData.FromString("{\"location\":"); + + StreamingChatToolCallUpdate update = ChatModelFactory.StreamingChatToolCallUpdate( + index: index, + toolCallId: toolCallId, + kind: kind, + functionName: functionName, + functionArgumentsUpdate: functionArgumentsUpdate); + + Assert.That(update.Index, Is.EqualTo(index)); + Assert.That(update.ToolCallId, Is.EqualTo(toolCallId)); + Assert.That(update.Kind, Is.EqualTo(kind)); + Assert.That(update.FunctionName, Is.EqualTo(functionName)); + Assert.That(update.FunctionArgumentsUpdate, Is.EqualTo(functionArgumentsUpdate)); + } +} \ No newline at end of file From b2449971b604f23dd9a4b74009ad6777bc2e6d00 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 11 Jul 2025 15:47:36 +0000 Subject: [PATCH 3/5] Add additional factory methods for ChatMessageAnnotation and token usage details Co-authored-by: KrzysztofCwalina <9724236+KrzysztofCwalina@users.noreply.github.com> --- src/Custom/ChatModelFactory.cs | 41 ++++++++++++++++++++++ tests/Chat/ChatModelFactoryTests.cs | 54 +++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/src/Custom/ChatModelFactory.cs b/src/Custom/ChatModelFactory.cs index 3b8cc6add..a72d634ed 100644 --- a/src/Custom/ChatModelFactory.cs +++ b/src/Custom/ChatModelFactory.cs @@ -209,4 +209,45 @@ public static StreamingChatToolCallUpdate StreamingChatToolCallUpdate( functionName: functionName, functionArgumentsUpdate: functionArgumentsUpdate); } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static ChatMessageAnnotation ChatMessageAnnotation( + int startIndex = default, + int endIndex = default, + Uri webResourceUri = default, + string webResourceTitle = default) + { + return OpenAI.Chat.OpenAIChatModelFactory.ChatMessageAnnotation( + startIndex: startIndex, + endIndex: endIndex, + webResourceUri: webResourceUri, + webResourceTitle: webResourceTitle); + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static ChatInputTokenUsageDetails ChatInputTokenUsageDetails( + int audioTokenCount = default, + int cachedTokenCount = default) + { + return OpenAI.Chat.OpenAIChatModelFactory.ChatInputTokenUsageDetails( + audioTokenCount: audioTokenCount, + cachedTokenCount: cachedTokenCount); + } + + /// Initializes a new instance of . + /// A new instance for mocking. + public static ChatOutputTokenUsageDetails ChatOutputTokenUsageDetails( + int reasoningTokenCount = default, + int audioTokenCount = default, + int acceptedPredictionTokenCount = default, + int rejectedPredictionTokenCount = default) + { + return OpenAI.Chat.OpenAIChatModelFactory.ChatOutputTokenUsageDetails( + reasoningTokenCount: reasoningTokenCount, + audioTokenCount: audioTokenCount, + acceptedPredictionTokenCount: acceptedPredictionTokenCount, + rejectedPredictionTokenCount: rejectedPredictionTokenCount); + } } \ No newline at end of file diff --git a/tests/Chat/ChatModelFactoryTests.cs b/tests/Chat/ChatModelFactoryTests.cs index 03ee08481..c222bea71 100644 --- a/tests/Chat/ChatModelFactoryTests.cs +++ b/tests/Chat/ChatModelFactoryTests.cs @@ -292,4 +292,58 @@ public void StreamingChatToolCallUpdateWorks() Assert.That(update.FunctionName, Is.EqualTo(functionName)); Assert.That(update.FunctionArgumentsUpdate, Is.EqualTo(functionArgumentsUpdate)); } + + [Test] + public void ChatMessageAnnotationWorks() + { + int startIndex = 5; + int endIndex = 10; + Uri webResourceUri = new Uri("https://example.com"); + string webResourceTitle = "Example Resource"; + + ChatMessageAnnotation annotation = ChatModelFactory.ChatMessageAnnotation( + startIndex: startIndex, + endIndex: endIndex, + webResourceUri: webResourceUri, + webResourceTitle: webResourceTitle); + + Assert.That(annotation.StartIndex, Is.EqualTo(startIndex)); + Assert.That(annotation.EndIndex, Is.EqualTo(endIndex)); + Assert.That(annotation.WebResourceUri, Is.EqualTo(webResourceUri)); + Assert.That(annotation.WebResourceTitle, Is.EqualTo(webResourceTitle)); + } + + [Test] + public void ChatInputTokenUsageDetailsWorks() + { + int audioTokenCount = 25; + int cachedTokenCount = 75; + + ChatInputTokenUsageDetails details = ChatModelFactory.ChatInputTokenUsageDetails( + audioTokenCount: audioTokenCount, + cachedTokenCount: cachedTokenCount); + + Assert.That(details.AudioTokenCount, Is.EqualTo(audioTokenCount)); + Assert.That(details.CachedTokenCount, Is.EqualTo(cachedTokenCount)); + } + + [Test] + public void ChatOutputTokenUsageDetailsWorks() + { + int reasoningTokenCount = 30; + int audioTokenCount = 15; + int acceptedPredictionTokenCount = 5; + int rejectedPredictionTokenCount = 2; + + ChatOutputTokenUsageDetails details = ChatModelFactory.ChatOutputTokenUsageDetails( + reasoningTokenCount: reasoningTokenCount, + audioTokenCount: audioTokenCount, + acceptedPredictionTokenCount: acceptedPredictionTokenCount, + rejectedPredictionTokenCount: rejectedPredictionTokenCount); + + Assert.That(details.ReasoningTokenCount, Is.EqualTo(reasoningTokenCount)); + Assert.That(details.AudioTokenCount, Is.EqualTo(audioTokenCount)); + Assert.That(details.AcceptedPredictionTokenCount, Is.EqualTo(acceptedPredictionTokenCount)); + Assert.That(details.RejectedPredictionTokenCount, Is.EqualTo(rejectedPredictionTokenCount)); + } } \ No newline at end of file From e75e26002f26d1667a599ab47c207b8369818cd9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 11 Jul 2025 16:00:39 +0000 Subject: [PATCH 4/5] Remove unnecessary factory methods for message types with public constructors Co-authored-by: KrzysztofCwalina <9724236+KrzysztofCwalina@users.noreply.github.com> --- src/Custom/ChatModelFactory.cs | 63 -------------------------- tests/Chat/ChatModelFactoryTests.cs | 70 ----------------------------- 2 files changed, 133 deletions(-) diff --git a/src/Custom/ChatModelFactory.cs b/src/Custom/ChatModelFactory.cs index a72d634ed..16de48aa6 100644 --- a/src/Custom/ChatModelFactory.cs +++ b/src/Custom/ChatModelFactory.cs @@ -87,70 +87,7 @@ public static ChatCompletionDeletionResult ChatCompletionDeletionResult( additionalBinaryDataProperties: null); } - /// Initializes a new instance of . - /// A new instance for mocking. - public static UserChatMessage UserChatMessage( - string content = null, - string participantName = null) - { - content ??= "User message content"; - var message = new UserChatMessage(content); - if (participantName != null) - { - message.ParticipantName = participantName; - } - return message; - } - - /// Initializes a new instance of . - /// A new instance for mocking. - public static AssistantChatMessage AssistantChatMessage( - string content = null, - IEnumerable toolCalls = null, - string participantName = null) - { - AssistantChatMessage message; - if (toolCalls != null) - { - message = new AssistantChatMessage(toolCalls); - } - else - { - content ??= "Assistant message content"; - message = new AssistantChatMessage(content); - } - - if (participantName != null) - { - message.ParticipantName = participantName; - } - return message; - } - /// Initializes a new instance of . - /// A new instance for mocking. - public static SystemChatMessage SystemChatMessage( - string content = null, - string participantName = null) - { - content ??= "System message content"; - var message = new SystemChatMessage(content); - if (participantName != null) - { - message.ParticipantName = participantName; - } - return message; - } - - /// Initializes a new instance of . - /// A new instance for mocking. - public static ToolChatMessage ToolChatMessage( - string toolCallId = "tool_call_id", - string content = null) - { - content ??= "Tool message content"; - return new ToolChatMessage(toolCallId, content); - } /// Initializes a new instance of . /// A new instance for mocking. diff --git a/tests/Chat/ChatModelFactoryTests.cs b/tests/Chat/ChatModelFactoryTests.cs index c222bea71..5b20aec4b 100644 --- a/tests/Chat/ChatModelFactoryTests.cs +++ b/tests/Chat/ChatModelFactoryTests.cs @@ -146,77 +146,7 @@ public void ChatCompletionDeletionResultWorks() Assert.That(result.ChatCompletionId, Is.EqualTo(chatCompletionId)); } - [Test] - public void UserChatMessageWorks() - { - string content = "Hello, assistant!"; - string participantName = "user1"; - - UserChatMessage message = ChatModelFactory.UserChatMessage( - content: content, - participantName: participantName); - - Assert.That(message.Content[0].Text, Is.EqualTo(content)); - Assert.That(message.ParticipantName, Is.EqualTo(participantName)); - Assert.That(message.Role, Is.EqualTo(ChatMessageRole.User)); - } - - [Test] - public void AssistantChatMessageWorks() - { - string content = "Hello, user!"; - IEnumerable toolCalls = [ - ChatToolCall.CreateFunctionToolCall("id1", "get_weather", BinaryData.FromString("{}")) - ]; - string participantName = "assistant1"; - - AssistantChatMessage message = ChatModelFactory.AssistantChatMessage( - content: content, - participantName: participantName); - - Assert.That(message.Content[0].Text, Is.EqualTo(content)); - Assert.That(message.ParticipantName, Is.EqualTo(participantName)); - Assert.That(message.Role, Is.EqualTo(ChatMessageRole.Assistant)); - - // Test with tool calls - AssistantChatMessage messageWithToolCalls = ChatModelFactory.AssistantChatMessage( - toolCalls: toolCalls, - participantName: participantName); - Assert.That(messageWithToolCalls.ToolCalls.SequenceEqual(toolCalls), Is.True); - Assert.That(messageWithToolCalls.ParticipantName, Is.EqualTo(participantName)); - Assert.That(messageWithToolCalls.Role, Is.EqualTo(ChatMessageRole.Assistant)); - } - - [Test] - public void SystemChatMessageWorks() - { - string content = "You are a helpful assistant"; - string participantName = "system"; - - SystemChatMessage message = ChatModelFactory.SystemChatMessage( - content: content, - participantName: participantName); - - Assert.That(message.Content[0].Text, Is.EqualTo(content)); - Assert.That(message.ParticipantName, Is.EqualTo(participantName)); - Assert.That(message.Role, Is.EqualTo(ChatMessageRole.System)); - } - - [Test] - public void ToolChatMessageWorks() - { - string toolCallId = "tool_call_id"; - string content = "Weather is sunny"; - - ToolChatMessage message = ChatModelFactory.ToolChatMessage( - toolCallId: toolCallId, - content: content); - - Assert.That(message.Content[0].Text, Is.EqualTo(content)); - Assert.That(message.ToolCallId, Is.EqualTo(toolCallId)); - Assert.That(message.Role, Is.EqualTo(ChatMessageRole.Tool)); - } [Test] public void ChatTokenUsageWorks() From ea57bbcd04b308ba5feb3423c6bdf082c45edf71 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 11 Jul 2025 17:16:43 +0000 Subject: [PATCH 5/5] Remove redundant ChatModelFactory since OpenAIChatModelFactory already exists Co-authored-by: KrzysztofCwalina <9724236+KrzysztofCwalina@users.noreply.github.com> --- src/Custom/ChatModelFactory.cs | 190 ------------------- tests/Chat/ChatModelFactoryTests.cs | 279 ---------------------------- 2 files changed, 469 deletions(-) delete mode 100644 src/Custom/ChatModelFactory.cs delete mode 100644 tests/Chat/ChatModelFactoryTests.cs diff --git a/src/Custom/ChatModelFactory.cs b/src/Custom/ChatModelFactory.cs deleted file mode 100644 index 16de48aa6..000000000 --- a/src/Custom/ChatModelFactory.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using OpenAI.Chat; - -namespace OpenAI; - -/// Model factory for Chat models. -public static partial class ChatModelFactory -{ - /// Initializes a new instance of . - /// A new instance for mocking. - public static ChatCompletion ChatCompletion( - string id = null, - ChatFinishReason finishReason = default, - ChatMessageContent content = null, - string refusal = null, - IEnumerable toolCalls = null, - ChatMessageRole role = default, - IEnumerable contentTokenLogProbabilities = null, - IEnumerable refusalTokenLogProbabilities = null, - DateTimeOffset createdAt = default, - string model = null, - string systemFingerprint = null, - ChatTokenUsage usage = default) - { - return OpenAI.Chat.OpenAIChatModelFactory.ChatCompletion( - id: id, - finishReason: finishReason, - content: content, - refusal: refusal, - toolCalls: toolCalls, - role: role, - functionCall: default, - contentTokenLogProbabilities: contentTokenLogProbabilities, - refusalTokenLogProbabilities: refusalTokenLogProbabilities, - createdAt: createdAt, - model: model, - systemFingerprint: systemFingerprint, - usage: usage); - } - - /// Initializes a new instance of . - /// A new instance for mocking. - public static StreamingChatCompletionUpdate StreamingChatCompletionUpdate( - string completionId = null, - ChatMessageContent contentUpdate = null, - IEnumerable toolCallUpdates = null, - ChatMessageRole? role = default, - string refusalUpdate = null, - IEnumerable contentTokenLogProbabilities = null, - IEnumerable refusalTokenLogProbabilities = null, - ChatFinishReason? finishReason = default, - DateTimeOffset createdAt = default, - string model = null, - string systemFingerprint = null, - ChatTokenUsage usage = default) - { - return OpenAI.Chat.OpenAIChatModelFactory.StreamingChatCompletionUpdate( - completionId: completionId, - contentUpdate: contentUpdate, - functionCallUpdate: default, - toolCallUpdates: toolCallUpdates, - role: role, - refusalUpdate: refusalUpdate, - contentTokenLogProbabilities: contentTokenLogProbabilities, - refusalTokenLogProbabilities: refusalTokenLogProbabilities, - finishReason: finishReason, - createdAt: createdAt, - model: model, - systemFingerprint: systemFingerprint, - usage: usage); - } - - /// Initializes a new instance of . - /// A new instance for mocking. - public static ChatCompletionDeletionResult ChatCompletionDeletionResult( - bool deleted = true, - string chatCompletionId = null) - { - return new ChatCompletionDeletionResult( - deleted: deleted, - @object: "chat.completion.deleted", - chatCompletionId: chatCompletionId, - additionalBinaryDataProperties: null); - } - - - - /// Initializes a new instance of . - /// A new instance for mocking. - public static ChatTokenUsage ChatTokenUsage( - int outputTokenCount = default, - int inputTokenCount = default, - int totalTokenCount = default) - { - return OpenAI.Chat.OpenAIChatModelFactory.ChatTokenUsage( - outputTokenCount: outputTokenCount, - inputTokenCount: inputTokenCount, - totalTokenCount: totalTokenCount); - } - - /// Initializes a new instance of . - /// A new instance for mocking. - public static ChatTokenLogProbabilityDetails ChatTokenLogProbabilityDetails( - string token = null, - float logProbability = default, - ReadOnlyMemory? utf8Bytes = null, - IEnumerable topLogProbabilities = null) - { - return OpenAI.Chat.OpenAIChatModelFactory.ChatTokenLogProbabilityDetails( - token: token, - logProbability: logProbability, - utf8Bytes: utf8Bytes, - topLogProbabilities: topLogProbabilities); - } - - /// Initializes a new instance of . - /// A new instance for mocking. - public static ChatTokenTopLogProbabilityDetails ChatTokenTopLogProbabilityDetails( - string token = null, - float logProbability = default, - ReadOnlyMemory? utf8Bytes = null) - { - return OpenAI.Chat.OpenAIChatModelFactory.ChatTokenTopLogProbabilityDetails( - token: token, - logProbability: logProbability, - utf8Bytes: utf8Bytes); - } - - /// Initializes a new instance of . - /// A new instance for mocking. - public static StreamingChatToolCallUpdate StreamingChatToolCallUpdate( - int index = default, - string toolCallId = null, - ChatToolCallKind kind = default, - string functionName = null, - BinaryData functionArgumentsUpdate = null) - { - return OpenAI.Chat.OpenAIChatModelFactory.StreamingChatToolCallUpdate( - index: index, - toolCallId: toolCallId, - kind: kind, - functionName: functionName, - functionArgumentsUpdate: functionArgumentsUpdate); - } - - /// Initializes a new instance of . - /// A new instance for mocking. - public static ChatMessageAnnotation ChatMessageAnnotation( - int startIndex = default, - int endIndex = default, - Uri webResourceUri = default, - string webResourceTitle = default) - { - return OpenAI.Chat.OpenAIChatModelFactory.ChatMessageAnnotation( - startIndex: startIndex, - endIndex: endIndex, - webResourceUri: webResourceUri, - webResourceTitle: webResourceTitle); - } - - /// Initializes a new instance of . - /// A new instance for mocking. - public static ChatInputTokenUsageDetails ChatInputTokenUsageDetails( - int audioTokenCount = default, - int cachedTokenCount = default) - { - return OpenAI.Chat.OpenAIChatModelFactory.ChatInputTokenUsageDetails( - audioTokenCount: audioTokenCount, - cachedTokenCount: cachedTokenCount); - } - - /// Initializes a new instance of . - /// A new instance for mocking. - public static ChatOutputTokenUsageDetails ChatOutputTokenUsageDetails( - int reasoningTokenCount = default, - int audioTokenCount = default, - int acceptedPredictionTokenCount = default, - int rejectedPredictionTokenCount = default) - { - return OpenAI.Chat.OpenAIChatModelFactory.ChatOutputTokenUsageDetails( - reasoningTokenCount: reasoningTokenCount, - audioTokenCount: audioTokenCount, - acceptedPredictionTokenCount: acceptedPredictionTokenCount, - rejectedPredictionTokenCount: rejectedPredictionTokenCount); - } -} \ No newline at end of file diff --git a/tests/Chat/ChatModelFactoryTests.cs b/tests/Chat/ChatModelFactoryTests.cs deleted file mode 100644 index 5b20aec4b..000000000 --- a/tests/Chat/ChatModelFactoryTests.cs +++ /dev/null @@ -1,279 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using OpenAI.Chat; - -namespace OpenAI.Tests.Chat; - -[Parallelizable(ParallelScope.All)] -[Category("Chat")] -[Category("Smoke")] -public partial class ChatModelFactoryTests -{ - [Test] - public void ChatCompletionWithNoPropertiesWorks() - { - ChatCompletion chatCompletion = ChatModelFactory.ChatCompletion(); - - Assert.That(chatCompletion.Id, Is.Null); - Assert.That(chatCompletion.FinishReason, Is.EqualTo(default(ChatFinishReason))); - Assert.That(chatCompletion.Content, Is.Not.Null.And.Empty); - Assert.That(chatCompletion.Refusal, Is.Null); - Assert.That(chatCompletion.ToolCalls, Is.Not.Null.And.Empty); - Assert.That(chatCompletion.Role, Is.EqualTo(default(ChatMessageRole))); - Assert.That(chatCompletion.ContentTokenLogProbabilities, Is.Not.Null.And.Empty); - Assert.That(chatCompletion.RefusalTokenLogProbabilities, Is.Not.Null.And.Empty); - Assert.That(chatCompletion.CreatedAt, Is.EqualTo(default(DateTimeOffset))); - Assert.That(chatCompletion.Model, Is.Null); - Assert.That(chatCompletion.SystemFingerprint, Is.Null); - Assert.That(chatCompletion.Usage, Is.Null); - } - - [Test] - public void ChatCompletionWithIdWorks() - { - string id = "chat_completion_id"; - ChatCompletion chatCompletion = ChatModelFactory.ChatCompletion(id: id); - - Assert.That(chatCompletion.Id, Is.EqualTo(id)); - Assert.That(chatCompletion.FinishReason, Is.EqualTo(default(ChatFinishReason))); - Assert.That(chatCompletion.Content, Is.Not.Null.And.Empty); - Assert.That(chatCompletion.Refusal, Is.Null); - Assert.That(chatCompletion.ToolCalls, Is.Not.Null.And.Empty); - Assert.That(chatCompletion.Role, Is.EqualTo(default(ChatMessageRole))); - Assert.That(chatCompletion.ContentTokenLogProbabilities, Is.Not.Null.And.Empty); - Assert.That(chatCompletion.RefusalTokenLogProbabilities, Is.Not.Null.And.Empty); - Assert.That(chatCompletion.CreatedAt, Is.EqualTo(default(DateTimeOffset))); - Assert.That(chatCompletion.Model, Is.Null); - Assert.That(chatCompletion.SystemFingerprint, Is.Null); - Assert.That(chatCompletion.Usage, Is.Null); - } - - [Test] - public void ChatCompletionWithAllPropertiesWorks() - { - string id = "chat_completion_id"; - ChatFinishReason finishReason = ChatFinishReason.Stop; - ChatMessageContent content = [ChatMessageContentPart.CreateTextPart("Hello, world!")]; - string refusal = "I cannot comply"; - IEnumerable toolCalls = [ - ChatToolCall.CreateFunctionToolCall("id1", "get_weather", BinaryData.FromString("{}")) - ]; - ChatMessageRole role = ChatMessageRole.Assistant; - DateTimeOffset createdAt = DateTimeOffset.UtcNow; - string model = "gpt-4"; - string systemFingerprint = "fp_123"; - ChatTokenUsage usage = ChatModelFactory.ChatTokenUsage(inputTokenCount: 10, outputTokenCount: 20); - - ChatCompletion chatCompletion = ChatModelFactory.ChatCompletion( - id: id, - finishReason: finishReason, - content: content, - refusal: refusal, - toolCalls: toolCalls, - role: role, - createdAt: createdAt, - model: model, - systemFingerprint: systemFingerprint, - usage: usage); - - Assert.That(chatCompletion.Id, Is.EqualTo(id)); - Assert.That(chatCompletion.FinishReason, Is.EqualTo(finishReason)); - Assert.That(chatCompletion.Content.SequenceEqual(content), Is.True); - Assert.That(chatCompletion.Refusal, Is.EqualTo(refusal)); - Assert.That(chatCompletion.ToolCalls.SequenceEqual(toolCalls), Is.True); - Assert.That(chatCompletion.Role, Is.EqualTo(role)); - Assert.That(chatCompletion.CreatedAt, Is.EqualTo(createdAt)); - Assert.That(chatCompletion.Model, Is.EqualTo(model)); - Assert.That(chatCompletion.SystemFingerprint, Is.EqualTo(systemFingerprint)); - Assert.That(chatCompletion.Usage, Is.EqualTo(usage)); - } - - [Test] - public void StreamingChatCompletionUpdateWithNoPropertiesWorks() - { - StreamingChatCompletionUpdate update = ChatModelFactory.StreamingChatCompletionUpdate(); - - Assert.That(update.CompletionId, Is.Null); - Assert.That(update.ContentUpdate, Is.Not.Null.And.Empty); - Assert.That(update.ToolCallUpdates, Is.Not.Null.And.Empty); - Assert.That(update.Role, Is.Null); - Assert.That(update.RefusalUpdate, Is.Null); - Assert.That(update.ContentTokenLogProbabilities, Is.Not.Null.And.Empty); - Assert.That(update.RefusalTokenLogProbabilities, Is.Not.Null.And.Empty); - Assert.That(update.FinishReason, Is.Null); - Assert.That(update.CreatedAt, Is.EqualTo(default(DateTimeOffset))); - Assert.That(update.Model, Is.Null); - Assert.That(update.SystemFingerprint, Is.Null); - Assert.That(update.Usage, Is.Null); - } - - [Test] - public void StreamingChatCompletionUpdateWithPropertiesWorks() - { - string completionId = "completion_id"; - ChatMessageContent contentUpdate = [ChatMessageContentPart.CreateTextPart("Hello")]; - ChatMessageRole role = ChatMessageRole.Assistant; - DateTimeOffset createdAt = DateTimeOffset.UtcNow; - string model = "gpt-4"; - - StreamingChatCompletionUpdate update = ChatModelFactory.StreamingChatCompletionUpdate( - completionId: completionId, - contentUpdate: contentUpdate, - role: role, - createdAt: createdAt, - model: model); - - Assert.That(update.CompletionId, Is.EqualTo(completionId)); - Assert.That(update.ContentUpdate.SequenceEqual(contentUpdate), Is.True); - Assert.That(update.Role, Is.EqualTo(role)); - Assert.That(update.CreatedAt, Is.EqualTo(createdAt)); - Assert.That(update.Model, Is.EqualTo(model)); - } - - [Test] - public void ChatCompletionDeletionResultWorks() - { - string chatCompletionId = "completion_id"; - bool deleted = true; - - ChatCompletionDeletionResult result = ChatModelFactory.ChatCompletionDeletionResult( - deleted: deleted, - chatCompletionId: chatCompletionId); - - Assert.That(result.Deleted, Is.EqualTo(deleted)); - Assert.That(result.ChatCompletionId, Is.EqualTo(chatCompletionId)); - } - - - - [Test] - public void ChatTokenUsageWorks() - { - int inputTokenCount = 100; - int outputTokenCount = 50; - int totalTokenCount = 150; - - ChatTokenUsage usage = ChatModelFactory.ChatTokenUsage( - inputTokenCount: inputTokenCount, - outputTokenCount: outputTokenCount, - totalTokenCount: totalTokenCount); - - Assert.That(usage.InputTokenCount, Is.EqualTo(inputTokenCount)); - Assert.That(usage.OutputTokenCount, Is.EqualTo(outputTokenCount)); - Assert.That(usage.TotalTokenCount, Is.EqualTo(totalTokenCount)); - } - - [Test] - public void ChatTokenLogProbabilityDetailsWorks() - { - string token = "hello"; - float logProbability = -0.5f; - ReadOnlyMemory utf8Bytes = "hello"u8.ToArray(); - - ChatTokenLogProbabilityDetails details = ChatModelFactory.ChatTokenLogProbabilityDetails( - token: token, - logProbability: logProbability, - utf8Bytes: utf8Bytes); - - Assert.That(details.Token, Is.EqualTo(token)); - Assert.That(details.LogProbability, Is.EqualTo(logProbability)); - Assert.That(details.Utf8Bytes.Value.ToArray().SequenceEqual(utf8Bytes.ToArray()), Is.True); - Assert.That(details.TopLogProbabilities, Is.Not.Null.And.Empty); - } - - [Test] - public void ChatTokenTopLogProbabilityDetailsWorks() - { - string token = "hello"; - float logProbability = -0.5f; - ReadOnlyMemory utf8Bytes = "hello"u8.ToArray(); - - ChatTokenTopLogProbabilityDetails details = ChatModelFactory.ChatTokenTopLogProbabilityDetails( - token: token, - logProbability: logProbability, - utf8Bytes: utf8Bytes); - - Assert.That(details.Token, Is.EqualTo(token)); - Assert.That(details.LogProbability, Is.EqualTo(logProbability)); - Assert.That(details.Utf8Bytes.Value.ToArray().SequenceEqual(utf8Bytes.ToArray()), Is.True); - } - - [Test] - public void StreamingChatToolCallUpdateWorks() - { - int index = 0; - string toolCallId = "tool_call_id"; - ChatToolCallKind kind = ChatToolCallKind.Function; - string functionName = "get_weather"; - BinaryData functionArgumentsUpdate = BinaryData.FromString("{\"location\":"); - - StreamingChatToolCallUpdate update = ChatModelFactory.StreamingChatToolCallUpdate( - index: index, - toolCallId: toolCallId, - kind: kind, - functionName: functionName, - functionArgumentsUpdate: functionArgumentsUpdate); - - Assert.That(update.Index, Is.EqualTo(index)); - Assert.That(update.ToolCallId, Is.EqualTo(toolCallId)); - Assert.That(update.Kind, Is.EqualTo(kind)); - Assert.That(update.FunctionName, Is.EqualTo(functionName)); - Assert.That(update.FunctionArgumentsUpdate, Is.EqualTo(functionArgumentsUpdate)); - } - - [Test] - public void ChatMessageAnnotationWorks() - { - int startIndex = 5; - int endIndex = 10; - Uri webResourceUri = new Uri("https://example.com"); - string webResourceTitle = "Example Resource"; - - ChatMessageAnnotation annotation = ChatModelFactory.ChatMessageAnnotation( - startIndex: startIndex, - endIndex: endIndex, - webResourceUri: webResourceUri, - webResourceTitle: webResourceTitle); - - Assert.That(annotation.StartIndex, Is.EqualTo(startIndex)); - Assert.That(annotation.EndIndex, Is.EqualTo(endIndex)); - Assert.That(annotation.WebResourceUri, Is.EqualTo(webResourceUri)); - Assert.That(annotation.WebResourceTitle, Is.EqualTo(webResourceTitle)); - } - - [Test] - public void ChatInputTokenUsageDetailsWorks() - { - int audioTokenCount = 25; - int cachedTokenCount = 75; - - ChatInputTokenUsageDetails details = ChatModelFactory.ChatInputTokenUsageDetails( - audioTokenCount: audioTokenCount, - cachedTokenCount: cachedTokenCount); - - Assert.That(details.AudioTokenCount, Is.EqualTo(audioTokenCount)); - Assert.That(details.CachedTokenCount, Is.EqualTo(cachedTokenCount)); - } - - [Test] - public void ChatOutputTokenUsageDetailsWorks() - { - int reasoningTokenCount = 30; - int audioTokenCount = 15; - int acceptedPredictionTokenCount = 5; - int rejectedPredictionTokenCount = 2; - - ChatOutputTokenUsageDetails details = ChatModelFactory.ChatOutputTokenUsageDetails( - reasoningTokenCount: reasoningTokenCount, - audioTokenCount: audioTokenCount, - acceptedPredictionTokenCount: acceptedPredictionTokenCount, - rejectedPredictionTokenCount: rejectedPredictionTokenCount); - - Assert.That(details.ReasoningTokenCount, Is.EqualTo(reasoningTokenCount)); - Assert.That(details.AudioTokenCount, Is.EqualTo(audioTokenCount)); - Assert.That(details.AcceptedPredictionTokenCount, Is.EqualTo(acceptedPredictionTokenCount)); - Assert.That(details.RejectedPredictionTokenCount, Is.EqualTo(rejectedPredictionTokenCount)); - } -} \ No newline at end of file