diff --git a/.dotnet.azure/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Vision.cs b/.dotnet.azure/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Vision.cs index 85399aac4..cd7afbe53 100644 --- a/.dotnet.azure/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Vision.cs +++ b/.dotnet.azure/sdk/openai/Azure.AI.OpenAI/tests/ChatTests.Vision.cs @@ -24,22 +24,22 @@ public async Task ChatWithImages(bool useUri) ChatMessageContentPart imagePart; if (useUri) { - imagePart = ChatMessageContentPart.CreateImageMessageContentPart( - imageAsset.Url, ImageChatMessageContentPartDetail.Low); + imagePart = ChatMessageContentPart.CreateImagePart( + imageAsset.Url, ChatImageDetailLevel.Low); } else { using var stream = File.OpenRead(imageAsset.RelativePath); var imageData = BinaryData.FromStream(stream); - imagePart = ChatMessageContentPart.CreateImageMessageContentPart( - imageData, imageAsset.MimeType, ImageChatMessageContentPartDetail.Low); + imagePart = ChatMessageContentPart.CreateImagePart( + imageData, imageAsset.MimeType, ChatImageDetailLevel.Low); } ChatMessage[] messages = [ new SystemChatMessage("You are a helpful assistant that helps describe images."), - new UserChatMessage(imagePart, ChatMessageContentPart.CreateTextMessageContentPart("describe this image")) + new UserChatMessage(imagePart, ChatMessageContentPart.CreateTextPart("describe this image")) ]; ChatCompletionOptions options = new() @@ -94,22 +94,22 @@ public async Task ChatWithImagesStreaming(bool useUri) var imageAsset = Assets.DogAndCat; if (useUri) { - imagePart = ChatMessageContentPart.CreateImageMessageContentPart( - imageAsset.Url, ImageChatMessageContentPartDetail.Low); + imagePart = ChatMessageContentPart.CreateImagePart( + imageAsset.Url, ChatImageDetailLevel.Low); } else { using var stream = File.OpenRead(imageAsset.RelativePath); var imageData = BinaryData.FromStream(stream); - imagePart = ChatMessageContentPart.CreateImageMessageContentPart( - imageData, imageAsset.MimeType, ImageChatMessageContentPartDetail.Low); + imagePart = ChatMessageContentPart.CreateImagePart( + imageData, imageAsset.MimeType, ChatImageDetailLevel.Low); } ChatMessage[] messages = [ new SystemChatMessage("You are a helpful assistant that helps describe images."), - new UserChatMessage(imagePart, ChatMessageContentPart.CreateTextMessageContentPart("describe this image")) + new UserChatMessage(imagePart, ChatMessageContentPart.CreateTextPart("describe this image")) ]; ChatCompletionOptions options = new() diff --git a/.dotnet/CHANGELOG.md b/.dotnet/CHANGELOG.md index 9bf22052a..8e2a926f9 100644 --- a/.dotnet/CHANGELOG.md +++ b/.dotnet/CHANGELOG.md @@ -2,10 +2,22 @@ ## 2.0.0-beta.12 (Unreleased) +### Features Added + +### Breaking Changes + +- Renamed `ChatMessageContentPart`'s `CreateTextMessageContentPart` factory method to `CreateTextPart`. +- Renamed `ChatMessageContentPart`'s `CreateImageMessageContentPart` factory method to `CreateImagePart`. +- Renamed `ChatMessageContentPart`'s `CreateRefusalMessageContentPart` factory method to `CreateRefusalPart`. +- Renamed `ImageChatMessageContentPartDetail` to `ChatImageDetailLevel`. +- Removed `ChatMessageContentPart`'s `ToString` overload. + ### Bugs Fixed - Addressed an issue that caused multi-page queries of fine-tuning jobs, checkpoints, and events to fail. (commit_hash) +### Other Changes + ## 2.0.0-beta.11 (2024-09-03) ### Features Added diff --git a/.dotnet/api/OpenAI.netstandard2.0.cs b/.dotnet/api/OpenAI.netstandard2.0.cs index 26140d4b9..76ba98294 100644 --- a/.dotnet/api/OpenAI.netstandard2.0.cs +++ b/.dotnet/api/OpenAI.netstandard2.0.cs @@ -1320,6 +1320,23 @@ public class ChatFunctionChoice : IJsonModel, IPersistableMo string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options); BinaryData IPersistableModel.Write(ModelReaderWriterOptions options); } + public readonly partial struct ChatImageDetailLevel : IEquatable { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public ChatImageDetailLevel(string value); + public static ChatImageDetailLevel Auto { get; } + public static ChatImageDetailLevel High { get; } + public static ChatImageDetailLevel Low { get; } + public readonly bool Equals(ChatImageDetailLevel other); + [EditorBrowsable(EditorBrowsableState.Never)] + public override readonly bool Equals(object obj); + [EditorBrowsable(EditorBrowsableState.Never)] + public override readonly int GetHashCode(); + public static bool operator ==(ChatImageDetailLevel left, ChatImageDetailLevel right); + public static implicit operator ChatImageDetailLevel(string value); + public static bool operator !=(ChatImageDetailLevel left, ChatImageDetailLevel right); + public override readonly string ToString(); + } public abstract class ChatMessage : IJsonModel, IPersistableModel { protected ChatMessage(); protected internal ChatMessage(ChatMessageRole role, IEnumerable contentParts); @@ -1352,22 +1369,21 @@ public abstract class ChatMessage : IJsonModel, IPersistableModel, IPersistableModel { public BinaryData ImageBytes { get; } public string ImageBytesMediaType { get; } - public ImageChatMessageContentPartDetail? ImageDetail { get; } + public ChatImageDetailLevel? ImageDetailLevel { get; } public Uri ImageUri { get; } public ChatMessageContentPartKind Kind { get; } public string Refusal { get; } public string Text { get; } - public static ChatMessageContentPart CreateImageMessageContentPart(BinaryData imageBytes, string imageBytesMediaType, ImageChatMessageContentPartDetail? imageDetail = null); - public static ChatMessageContentPart CreateImageMessageContentPart(Uri imageUri, ImageChatMessageContentPartDetail? imageDetail = null); - public static ChatMessageContentPart CreateRefusalMessageContentPart(string refusal); - public static ChatMessageContentPart CreateTextMessageContentPart(string text); - public static implicit operator ChatMessageContentPart(string content); + public static ChatMessageContentPart CreateImagePart(BinaryData imageBytes, string imageBytesMediaType, ChatImageDetailLevel? imageDetailLevel = null); + public static ChatMessageContentPart CreateImagePart(Uri imageUri, ChatImageDetailLevel? imageDetailLevel = null); + public static ChatMessageContentPart CreateRefusalPart(string refusal); + public static ChatMessageContentPart CreateTextPart(string text); + public static implicit operator ChatMessageContentPart(string text); ChatMessageContentPart IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options); void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options); ChatMessageContentPart IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options); string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options); BinaryData IPersistableModel.Write(ModelReaderWriterOptions options); - public override string ToString(); } public readonly partial struct ChatMessageContentPartKind : IEquatable { private readonly object _dummy; @@ -1525,23 +1541,6 @@ public class FunctionChatMessage : ChatMessage, IJsonModel, BinaryData IPersistableModel.Write(ModelReaderWriterOptions options); protected internal override void WriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options); } - public readonly partial struct ImageChatMessageContentPartDetail : IEquatable { - private readonly object _dummy; - private readonly int _dummyPrimitive; - public ImageChatMessageContentPartDetail(string value); - public static ImageChatMessageContentPartDetail Auto { get; } - public static ImageChatMessageContentPartDetail High { get; } - public static ImageChatMessageContentPartDetail Low { get; } - public readonly bool Equals(ImageChatMessageContentPartDetail other); - [EditorBrowsable(EditorBrowsableState.Never)] - public override readonly bool Equals(object obj); - [EditorBrowsable(EditorBrowsableState.Never)] - public override readonly int GetHashCode(); - public static bool operator ==(ImageChatMessageContentPartDetail left, ImageChatMessageContentPartDetail right); - public static implicit operator ImageChatMessageContentPartDetail(string value); - public static bool operator !=(ImageChatMessageContentPartDetail left, ImageChatMessageContentPartDetail right); - public override readonly string ToString(); - } public static class OpenAIChatModelFactory { public static ChatCompletion ChatCompletion(string id = null, ChatFinishReason finishReason = ChatFinishReason.Stop, IEnumerable content = null, string refusal = null, IEnumerable toolCalls = null, ChatMessageRole role = ChatMessageRole.System, ChatFunctionCall functionCall = null, IEnumerable contentTokenLogProbabilities = null, IEnumerable refusalTokenLogProbabilities = null, DateTimeOffset createdAt = default, string model = null, string systemFingerprint = null, ChatTokenUsage usage = null); public static ChatTokenLogProbabilityInfo ChatTokenLogProbabilityInfo(string token = null, float logProbability = 0, IEnumerable utf8ByteValues = null, IEnumerable topLogProbabilities = null); diff --git a/.dotnet/examples/Chat/Example01_SimpleChat_Cancellations.cs b/.dotnet/examples/Chat/Example01_SimpleChat_Cancellations.cs deleted file mode 100644 index dbeb05e67..000000000 --- a/.dotnet/examples/Chat/Example01_SimpleChat_Cancellations.cs +++ /dev/null @@ -1,41 +0,0 @@ -using NUnit.Framework; -using OpenAI.Chat; -using System; -using System.ClientModel; -using System.ClientModel.Primitives; -using System.Threading; - -namespace OpenAI.Examples; - -public partial class ChatExamples -{ - [Test] - public void Example01_SimpleChat_Cancellations() - { - ChatClient client = new(model: "gpt-4o", Environment.GetEnvironmentVariable("OPENAI_API_KEY")); - - CancellationTokenSource ct = new CancellationTokenSource(); - RequestOptions options = new() { CancellationToken = ct.Token }; - - ChatMessage message = ChatMessage.CreateUserMessage("Say 'this is a test.'"); - var body = new - { - model = "gpt-4o", - messages = new[] { - new - { - role = "user", - content = "Say \u0027this is a test.\u0027" - } - } - }; - - BinaryData json = BinaryData.FromObjectAsJson(body); - ClientResult result = client.CompleteChat(BinaryContent.Create(json), options); - - // The following code will be simplified in the future. - var wireFormat = new ModelReaderWriterOptions("W"); - ChatCompletion completion = ModelReaderWriter.Read(result.GetRawResponse().Content, wireFormat); - Console.WriteLine($"[ASSISTANT]: {completion}"); - } -} diff --git a/.dotnet/examples/Chat/Example05_ChatWithVision.cs b/.dotnet/examples/Chat/Example05_ChatWithVision.cs index dbe8543ea..dd5724548 100644 --- a/.dotnet/examples/Chat/Example05_ChatWithVision.cs +++ b/.dotnet/examples/Chat/Example05_ChatWithVision.cs @@ -19,8 +19,8 @@ public void Example05_ChatWithVision() List messages = [ new UserChatMessage( - ChatMessageContentPart.CreateTextMessageContentPart("Please describe the following image."), - ChatMessageContentPart.CreateImageMessageContentPart(imageBytes, "image/png")) + ChatMessageContentPart.CreateTextPart("Please describe the following image."), + ChatMessageContentPart.CreateImagePart(imageBytes, "image/png")) ]; ChatCompletion chatCompletion = client.CompleteChat(messages); diff --git a/.dotnet/examples/Chat/Example05_ChatWithVisionAsync.cs b/.dotnet/examples/Chat/Example05_ChatWithVisionAsync.cs index c8f4c05c0..d18cc7b74 100644 --- a/.dotnet/examples/Chat/Example05_ChatWithVisionAsync.cs +++ b/.dotnet/examples/Chat/Example05_ChatWithVisionAsync.cs @@ -20,8 +20,8 @@ public async Task Example05_ChatWithVisionAsync() List messages = [ new UserChatMessage( - ChatMessageContentPart.CreateTextMessageContentPart("Please describe the following image."), - ChatMessageContentPart.CreateImageMessageContentPart(imageBytes, "image/png")) + ChatMessageContentPart.CreateTextPart("Please describe the following image."), + ChatMessageContentPart.CreateImagePart(imageBytes, "image/png")) ]; ChatCompletion chatCompletion = await client.CompleteChatAsync(messages); diff --git a/.dotnet/examples/Chat/Example07_StructuredOutputs.cs b/.dotnet/examples/Chat/Example07_StructuredOutputs.cs index 4e4335226..557e90e93 100644 --- a/.dotnet/examples/Chat/Example07_StructuredOutputs.cs +++ b/.dotnet/examples/Chat/Example07_StructuredOutputs.cs @@ -42,7 +42,7 @@ public void Example07_StructuredOutputs() }; ChatCompletion chatCompletion = client.CompleteChat( - ["How can I solve 8x + 7 = -23?"], + [ new UserChatMessage("How can I solve 8x + 7 = -23?") ], options); using JsonDocument structuredJson = JsonDocument.Parse(chatCompletion.ToString()); diff --git a/.dotnet/examples/Chat/Example07_StructuredOutputsAsync.cs b/.dotnet/examples/Chat/Example07_StructuredOutputsAsync.cs index 5f2732d80..5ef40715e 100644 --- a/.dotnet/examples/Chat/Example07_StructuredOutputsAsync.cs +++ b/.dotnet/examples/Chat/Example07_StructuredOutputsAsync.cs @@ -43,7 +43,7 @@ public async Task Example07_StructuredOutputsAsync() }; ChatCompletion chatCompletion = await client.CompleteChatAsync( - ["How can I solve 8x + 7 = -23?"], + [ new UserChatMessage("How can I solve 8x + 7 = -23?") ], options); using JsonDocument structuredJson = JsonDocument.Parse(chatCompletion.ToString()); diff --git a/.dotnet/examples/CombinationExamples.cs b/.dotnet/examples/CombinationExamples.cs index ffa800c34..633b4294c 100644 --- a/.dotnet/examples/CombinationExamples.cs +++ b/.dotnet/examples/CombinationExamples.cs @@ -34,8 +34,8 @@ public void AlpacaArtAssessor() new SystemChatMessage("Assume the role of a cranky art critic. When asked to describe or " + "evaluate imagery, focus on criticizing elements of subject, composition, and other details."), new UserChatMessage( - ChatMessageContentPart.CreateTextMessageContentPart("describe the following image in a few sentences"), - ChatMessageContentPart.CreateImageMessageContentPart(imageGeneration.ImageUri)), + ChatMessageContentPart.CreateTextPart("describe the following image in a few sentences"), + ChatMessageContentPart.CreateImagePart(imageGeneration.ImageUri)), ], new ChatCompletionOptions() { @@ -120,8 +120,8 @@ public async Task CuriousCreatureCreator() [ new SystemChatMessage("Assume the role of an art critic. Although usually cranky and occasionally even referred to as a 'curmudgeon', you're somehow entirely smitten with the subject presented to you and, despite your best efforts, can't help but lavish praise when you're asked to appraise a provided image."), new UserChatMessage( - ChatMessageContentPart.CreateTextMessageContentPart("Evaluate this image for me. What is it, and what do you think of it?"), - ChatMessageContentPart.CreateImageMessageContentPart(imageLocation)), + ChatMessageContentPart.CreateTextPart("Evaluate this image for me. What is it, and what do you think of it?"), + ChatMessageContentPart.CreateImagePart(imageLocation)), ], new ChatCompletionOptions() { diff --git a/.dotnet/src/Custom/Chat/ChatClient.cs b/.dotnet/src/Custom/Chat/ChatClient.cs index 1eb1c0e1a..164441aa9 100644 --- a/.dotnet/src/Custom/Chat/ChatClient.cs +++ b/.dotnet/src/Custom/Chat/ChatClient.cs @@ -181,7 +181,7 @@ public virtual AsyncCollectionResult CompleteChat async Task getResultAsync() => await CompleteChatAsync(content, cancellationToken.ToRequestOptions(streaming: true)).ConfigureAwait(false); - return new AsyncStreamingChatCompletionUpdateCollection(getResultAsync); + return new InternalAsyncStreamingChatCompletionUpdateCollection(getResultAsync); } /// @@ -206,7 +206,7 @@ public virtual CollectionResult CompleteChatStrea using BinaryContent content = options.ToBinaryContent(); ClientResult getResult() => CompleteChat(content, cancellationToken.ToRequestOptions(streaming: true)); - return new StreamingChatCompletionUpdateCollection(getResult); + return new InternalStreamingChatCompletionUpdateCollection(getResult); } /// diff --git a/.dotnet/src/Custom/Chat/ChatImageDetailLevel.cs b/.dotnet/src/Custom/Chat/ChatImageDetailLevel.cs new file mode 100644 index 000000000..5676bc43a --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatImageDetailLevel.cs @@ -0,0 +1,10 @@ +namespace OpenAI.Chat; + +/// +/// The level of detail with which the model should process the image and generate its textual understanding of +/// it. Learn more in the vision guide. +/// +[CodeGenModel("ChatCompletionRequestMessageContentPartImageImageUrlDetail")] +public readonly partial struct ChatImageDetailLevel +{ +} diff --git a/.dotnet/src/Custom/Chat/ChatMessage.Serialization.cs b/.dotnet/src/Custom/Chat/ChatMessage.Serialization.cs index 39ea1f59d..a0e6558c4 100644 --- a/.dotnet/src/Custom/Chat/ChatMessage.Serialization.cs +++ b/.dotnet/src/Custom/Chat/ChatMessage.Serialization.cs @@ -26,7 +26,7 @@ internal static void DeserializeContentValue(JsonProperty property, ref IList /// The content associated with the message. The interpretation of this content will vary depending on the message type. diff --git a/.dotnet/src/Custom/Chat/ChatMessageContentPart.Serialization.cs b/.dotnet/src/Custom/Chat/ChatMessageContentPart.Serialization.cs index 42d75589c..506cddcfb 100644 --- a/.dotnet/src/Custom/Chat/ChatMessageContentPart.Serialization.cs +++ b/.dotnet/src/Custom/Chat/ChatMessageContentPart.Serialization.cs @@ -30,7 +30,7 @@ internal static void WriteCoreContentPart(ChatMessageContentPart instance, Utf8J else if (instance._kind == ChatMessageContentPartKind.Image) { writer.WritePropertyName("image_url"u8); - writer.WriteObjectValue(instance._imageUrl, options); + writer.WriteObjectValue(instance._imageUri, options); } writer.WriteSerializedAdditionalRawData(instance.SerializedAdditionalRawData, options); writer.WriteEndObject(); @@ -71,7 +71,7 @@ internal static ChatMessageContentPart DeserializeChatMessageContentPart(JsonEle string kind = default; string text = default; string refusal = default; - InternalChatCompletionRequestMessageContentPartImageImageUrl imageUrl = default; + InternalChatCompletionRequestMessageContentPartImageImageUrl imageUri = default; IDictionary serializedAdditionalRawData = default; Dictionary rawDataDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -88,7 +88,7 @@ internal static ChatMessageContentPart DeserializeChatMessageContentPart(JsonEle } if (property.NameEquals("image_url"u8)) { - imageUrl = InternalChatCompletionRequestMessageContentPartImageImageUrl.DeserializeInternalChatCompletionRequestMessageContentPartImageImageUrl(property.Value, options); + imageUri = InternalChatCompletionRequestMessageContentPartImageImageUrl.DeserializeInternalChatCompletionRequestMessageContentPartImageImageUrl(property.Value, options); continue; } if (property.NameEquals("refusal"u8)) @@ -102,6 +102,6 @@ internal static ChatMessageContentPart DeserializeChatMessageContentPart(JsonEle } } serializedAdditionalRawData = rawDataDictionary; - return new ChatMessageContentPart(kind, text, refusal, imageUrl, serializedAdditionalRawData); + return new ChatMessageContentPart(kind, text, imageUri, refusal, serializedAdditionalRawData); } } diff --git a/.dotnet/src/Custom/Chat/ChatMessageContentPart.cs b/.dotnet/src/Custom/Chat/ChatMessageContentPart.cs index 2267b7877..109cc9a2e 100644 --- a/.dotnet/src/Custom/Chat/ChatMessageContentPart.cs +++ b/.dotnet/src/Custom/Chat/ChatMessageContentPart.cs @@ -4,7 +4,22 @@ namespace OpenAI.Chat; /// -/// Represents the common base type for a piece of message content used for chat completions. +/// A part of the chat message content. +/// +/// +/// Call to create a that +/// encapsulates text. +/// +/// +/// Call or +/// to create a +/// that encapsulates an image. +/// +/// +/// Call to create a that +/// encapsulates a refusal coming from the model. +/// +/// /// [CodeGenModel("ChatMessageContentPart")] [CodeGenSuppress("ChatMessageContentPart", typeof(IDictionary))] @@ -12,162 +27,125 @@ public partial class ChatMessageContentPart { private readonly ChatMessageContentPartKind _kind; private readonly string _text; + private readonly InternalChatCompletionRequestMessageContentPartImageImageUrl _imageUri; private readonly string _refusal; - private readonly InternalChatCompletionRequestMessageContentPartImageImageUrl _imageUrl; - private readonly string _dataUri; - - internal ChatMessageContentPart(string text) - { - Argument.AssertNotNull(text, nameof(text)); - - _text = text; - _kind = ChatMessageContentPartKind.Text; - } // CUSTOM: Made internal. internal ChatMessageContentPart() { } - - internal ChatMessageContentPart(Uri imageUri, ImageChatMessageContentPartDetail? imageDetail = null) - { - Argument.AssertNotNull(imageUri, nameof(imageUri)); - - _imageUrl = new(imageUri) { Detail = imageDetail }; - _kind = ChatMessageContentPartKind.Image; - } - - internal ChatMessageContentPart(BinaryData imageBytes, string imageBytesMediaType, ImageChatMessageContentPartDetail? imageDetail = null) - { - Argument.AssertNotNull(imageBytes, nameof(imageBytes)); - Argument.AssertNotNull(imageBytesMediaType, nameof(imageBytesMediaType)); - - _imageUrl = new(imageBytes, imageBytesMediaType) { Detail = imageDetail }; - _kind = ChatMessageContentPartKind.Image; - } - - /// Initializes a new instance of . - /// The kind. - /// The text. - /// The image URI. - /// Keeps track of any properties unknown to the library. - internal ChatMessageContentPart(string kind, string text, string refusal, InternalChatCompletionRequestMessageContentPartImageImageUrl imageUrl, IDictionary serializedAdditionalRawData) + // CUSTOM: Added to support deserialization. + internal ChatMessageContentPart(string kind, string text, InternalChatCompletionRequestMessageContentPartImageImageUrl imageUri, string refusal, IDictionary serializedAdditionalRawData) { _kind = new ChatMessageContentPartKind(kind); _text = text; + _imageUri = imageUri; _refusal = refusal; - _imageUrl = imageUrl; SerializedAdditionalRawData = serializedAdditionalRawData; } - /// - /// The content part kind. - /// + /// The content part kind. public ChatMessageContentPartKind Kind => _kind; - /// - /// The text content. - /// + /// The text. + /// Present when is . public string Text => _text; - /// - /// The refusal message from the assistant. - /// - public string Refusal => _refusal; + /// The public internet URI where the image is located. + /// Present when is . + public Uri ImageUri => _imageUri?.ImageUri; - /// - /// The image URI content. - /// - public Uri ImageUri => _imageUrl?.ImageUri; + /// The image bytes. + /// Present when is . + public BinaryData ImageBytes => _imageUri?.ImageBytes; - /// - /// The image URI content. - /// - public BinaryData ImageBytes => _imageUrl?.ImageBytes; + /// The MIME type of the image, e.g., image/png. + /// Present when is . + public string ImageBytesMediaType => _imageUri?.ImageBytesMediaType; /// - /// The image URI content. + /// The level of detail with which the model should process the image and generate its textual understanding of + /// it. Learn more in the vision guide. /// - public string ImageBytesMediaType => _imageUrl?.ImageBytesMediaType; + /// Present when is . + public ChatImageDetailLevel? ImageDetailLevel => _imageUri?.Detail; - /// - /// The image URI detail. - /// - public ImageChatMessageContentPartDetail? ImageDetail => _imageUrl?.Detail; + /// The refusal message generated by the model. + /// Present when is . + public string Refusal => _refusal; - /// - /// Creates a new instance of that encapsulates text content. - /// - /// The content for the new instance. - /// A new instance of . - public static ChatMessageContentPart CreateTextMessageContentPart(string text) + /// Creates a new that encapsulates text. + /// The text. + public static ChatMessageContentPart CreateTextPart(string text) { Argument.AssertNotNull(text, nameof(text)); - return new(text); + return new ChatMessageContentPart( + kind: ChatMessageContentPartKind.Text.ToString(), + text: text, + imageUri: null, + refusal: null, + serializedAdditionalRawData: null); } - /// - /// Creates a new instance of that encapsulates an assistant refusal message. - /// - /// The refusal message from the assistant. - /// A new instance of . - public static ChatMessageContentPart CreateRefusalMessageContentPart(string refusal) + /// Creates a new that encapsulates an image. + /// The public internet URI where the image is located. + /// + /// The level of detail with which the model should process the image and generate its textual understanding of + /// it. Learn more in the vision guide. + /// + public static ChatMessageContentPart CreateImagePart(Uri imageUri, ChatImageDetailLevel? imageDetailLevel = null) { - Argument.AssertNotNull(refusal, nameof(refusal)); + Argument.AssertNotNull(imageUri, nameof(imageUri)); return new ChatMessageContentPart( - ChatMessageContentPartKind.Refusal.ToString(), + kind: ChatMessageContentPartKind.Image.ToString(), text: null, - refusal: refusal, - imageUrl: null, + imageUri: new(imageUri) { Detail = imageDetailLevel }, + refusal: null, serializedAdditionalRawData: null); } - /// - /// Creates a new instance of that encapsulates image content obtained from - /// an internet location that will be accessible to the model when evaluating a message with this content. - /// - /// An internet location pointing to an image. This must be accessible to the model. - /// The detail level of the image. - /// A new instance of . - public static ChatMessageContentPart CreateImageMessageContentPart(Uri imageUri, ImageChatMessageContentPartDetail? imageDetail = null) + /// Creates a new that encapsulates an image. + /// The image bytes. + /// The MIME type of the image, e.g., image/png. + /// + /// The level of detail with which the model should process the image and generate its textual understanding of + /// it. Learn more in the vision guide. + /// + public static ChatMessageContentPart CreateImagePart(BinaryData imageBytes, string imageBytesMediaType, ChatImageDetailLevel? imageDetailLevel = null) { - Argument.AssertNotNull(imageUri, nameof(imageUri)); + Argument.AssertNotNull(imageBytes, nameof(imageBytes)); + Argument.AssertNotNull(imageBytesMediaType, nameof(imageBytesMediaType)); - return new(imageUri, imageDetail); + return new ChatMessageContentPart( + kind: ChatMessageContentPartKind.Image.ToString(), + text: null, + imageUri: new(imageBytes, imageBytesMediaType) { Detail = imageDetailLevel }, + refusal: null, + serializedAdditionalRawData: null); } - /// - /// Creates a new instance of that encapsulates image content obtained from - /// an internet location that will be accessible to the model when evaluating a message with this content. - /// - /// The readable stream containing the image data to use as content. - /// The MIME descriptor, like image/png, corresponding to the image data format of the provided data. - /// The detail level of the image. - /// A new instance of . - public static ChatMessageContentPart CreateImageMessageContentPart(BinaryData imageBytes, string imageBytesMediaType, ImageChatMessageContentPartDetail? imageDetail = null) + /// Creates a new that encapsulates a refusal coming from the model. + /// The refusal message generated by the model. + public static ChatMessageContentPart CreateRefusalPart(string refusal) { - Argument.AssertNotNull(imageBytes, nameof(imageBytes)); - Argument.AssertNotNull(imageBytesMediaType, nameof(imageBytesMediaType)); + Argument.AssertNotNull(refusal, nameof(refusal)); - return new(imageBytes, imageBytesMediaType, imageDetail); + return new ChatMessageContentPart( + kind: ChatMessageContentPartKind.Refusal.ToString(), + text: null, + imageUri: null, + refusal: refusal, + serializedAdditionalRawData: null); } /// - /// Returns text representation of this part. - /// - /// - public override string ToString() => Text; - - /// - /// Implicitly creates a new instance from an item of plain text. + /// Implicitly intantiates a new from a . As such, + /// using a in place of a is equivalent to calling the + /// method. /// - /// - /// Using a in the position of a is equivalent to - /// calling the method. - /// - /// The text content to use as this content part. - public static implicit operator ChatMessageContentPart(string content) => new(content); + /// The text encapsulated by this . + public static implicit operator ChatMessageContentPart(string text) => CreateTextPart(text); } diff --git a/.dotnet/src/Custom/Chat/ChatMessageContentPartKind.cs b/.dotnet/src/Custom/Chat/ChatMessageContentPartKind.cs index 73ba771ad..0962a4bc5 100644 --- a/.dotnet/src/Custom/Chat/ChatMessageContentPartKind.cs +++ b/.dotnet/src/Custom/Chat/ChatMessageContentPartKind.cs @@ -24,7 +24,7 @@ public ChatMessageContentPartKind(string value) /// Text. public static ChatMessageContentPartKind Text { get; } = new ChatMessageContentPartKind(TextValue); /// Refusal. - public static ChatMessageContentPartKind Refusal { get; } = new(RefusalValue); + public static ChatMessageContentPartKind Refusal { get; } = new ChatMessageContentPartKind(RefusalValue); /// Image. public static ChatMessageContentPartKind Image { get; } = new ChatMessageContentPartKind(ImageValue); @@ -43,7 +43,7 @@ public ChatMessageContentPartKind(string value) /// [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; + public override int GetHashCode() => _value != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(_value) : 0; /// public override string ToString() => _value; } \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ImageChatMessageContentPartDetail.cs b/.dotnet/src/Custom/Chat/ImageChatMessageContentPartDetail.cs deleted file mode 100644 index 943400a8e..000000000 --- a/.dotnet/src/Custom/Chat/ImageChatMessageContentPartDetail.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace OpenAI.Chat; - -[CodeGenModel("ChatCompletionRequestMessageContentPartImageImageUrlDetail")] -public readonly partial struct ImageChatMessageContentPartDetail -{ -} diff --git a/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionRequestMessageContentPartImageImageUrl.cs b/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionRequestMessageContentPartImageImageUrl.cs index c47eebaec..5e308a3cc 100644 --- a/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionRequestMessageContentPartImageImageUrl.cs +++ b/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionRequestMessageContentPartImageImageUrl.cs @@ -53,7 +53,7 @@ public InternalChatCompletionRequestMessageContentPartImageImageUrl(BinaryData i /// Either a URL of the image or the base64 encoded image data. /// Specifies the detail level of the image. Learn more in the [Vision guide](/docs/guides/vision/low-or-high-fidelity-image-understanding). /// Keeps track of any properties unknown to the library. - internal InternalChatCompletionRequestMessageContentPartImageImageUrl(string url, ImageChatMessageContentPartDetail? detail, IDictionary serializedAdditionalRawData) + internal InternalChatCompletionRequestMessageContentPartImageImageUrl(string url, ChatImageDetailLevel? detail, IDictionary serializedAdditionalRawData) { Match parsedDataUri = ParseDataUriRegex().Match(url); diff --git a/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionResponseMessage.Serialization.cs b/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionResponseMessage.Serialization.cs index 4ed0cadda..153e86e70 100644 --- a/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionResponseMessage.Serialization.cs +++ b/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionResponseMessage.Serialization.cs @@ -84,7 +84,7 @@ internal static InternalChatCompletionResponseMessage DeserializeInternalChatCom continue; } List array = new List(); - array.Add(ChatMessageContentPart.CreateTextMessageContentPart(property.Value.GetString())); + array.Add(ChatMessageContentPart.CreateTextPart(property.Value.GetString())); content = array; continue; } diff --git a/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionStreamResponseDelta.Serialization.cs b/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionStreamResponseDelta.Serialization.cs index 0239d2571..1c4f8ab1b 100644 --- a/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionStreamResponseDelta.Serialization.cs +++ b/.dotnet/src/Custom/Chat/Internal/InternalChatCompletionStreamResponseDelta.Serialization.cs @@ -87,7 +87,7 @@ internal static InternalChatCompletionStreamResponseDelta DeserializeInternalCha continue; } List array = new List(); - array.Add(ChatMessageContentPart.CreateTextMessageContentPart(property.Value.GetString())); + array.Add(ChatMessageContentPart.CreateTextPart(property.Value.GetString())); content = array; continue; } diff --git a/.dotnet/src/Custom/Chat/Internal/Streaming/AsyncStreamingChatCompletionUpdateCollection.cs b/.dotnet/src/Custom/Chat/Streaming/InternalAsyncStreamingChatCompletionUpdateCollection.cs similarity index 92% rename from .dotnet/src/Custom/Chat/Internal/Streaming/AsyncStreamingChatCompletionUpdateCollection.cs rename to .dotnet/src/Custom/Chat/Streaming/InternalAsyncStreamingChatCompletionUpdateCollection.cs index d3bc8ae90..55e304d31 100644 --- a/.dotnet/src/Custom/Chat/Internal/Streaming/AsyncStreamingChatCompletionUpdateCollection.cs +++ b/.dotnet/src/Custom/Chat/Streaming/InternalAsyncStreamingChatCompletionUpdateCollection.cs @@ -15,11 +15,11 @@ namespace OpenAI.Chat; /// /// Implementation of collection abstraction over streaming chat updates. /// -internal class AsyncStreamingChatCompletionUpdateCollection : AsyncCollectionResult +internal class InternalAsyncStreamingChatCompletionUpdateCollection : AsyncCollectionResult { private readonly Func> _getResultAsync; - public AsyncStreamingChatCompletionUpdateCollection(Func> getResultAsync) : base() + public InternalAsyncStreamingChatCompletionUpdateCollection(Func> getResultAsync) : base() { Argument.AssertNotNull(getResultAsync, nameof(getResultAsync)); @@ -36,7 +36,7 @@ private sealed class AsyncStreamingChatUpdateEnumerator : IAsyncEnumerator TerminalData => "[DONE]"u8; private readonly Func> _getResultAsync; - private readonly AsyncStreamingChatCompletionUpdateCollection _enumerable; + private readonly InternalAsyncStreamingChatCompletionUpdateCollection _enumerable; private readonly CancellationToken _cancellationToken; // These enumerators represent what is effectively a doubly-nested @@ -53,7 +53,7 @@ private sealed class AsyncStreamingChatUpdateEnumerator : IAsyncEnumerator> getResultAsync, - AsyncStreamingChatCompletionUpdateCollection enumerable, + InternalAsyncStreamingChatCompletionUpdateCollection enumerable, CancellationToken cancellationToken) { Debug.Assert(getResultAsync is not null); diff --git a/.dotnet/src/Custom/Chat/Internal/Streaming/StreamingChatCompletionUpdateCollection.cs b/.dotnet/src/Custom/Chat/Streaming/InternalStreamingChatCompletionUpdateCollection.cs similarity index 92% rename from .dotnet/src/Custom/Chat/Internal/Streaming/StreamingChatCompletionUpdateCollection.cs rename to .dotnet/src/Custom/Chat/Streaming/InternalStreamingChatCompletionUpdateCollection.cs index bc5d360d7..055d6d844 100644 --- a/.dotnet/src/Custom/Chat/Internal/Streaming/StreamingChatCompletionUpdateCollection.cs +++ b/.dotnet/src/Custom/Chat/Streaming/InternalStreamingChatCompletionUpdateCollection.cs @@ -14,11 +14,11 @@ namespace OpenAI.Chat; /// /// Implementation of collection abstraction over streaming chat updates. /// -internal class StreamingChatCompletionUpdateCollection : CollectionResult +internal class InternalStreamingChatCompletionUpdateCollection : CollectionResult { private readonly Func _getResult; - public StreamingChatCompletionUpdateCollection(Func getResult) : base() + public InternalStreamingChatCompletionUpdateCollection(Func getResult) : base() { Argument.AssertNotNull(getResult, nameof(getResult)); @@ -35,7 +35,7 @@ private sealed class StreamingChatUpdateEnumerator : IEnumerator TerminalData => "[DONE]"u8; private readonly Func _getResult; - private readonly StreamingChatCompletionUpdateCollection _enumerable; + private readonly InternalStreamingChatCompletionUpdateCollection _enumerable; // These enumerators represent what is effectively a doubly-nested // loop over the outer event collection and the inner update collection, @@ -51,7 +51,7 @@ private sealed class StreamingChatUpdateEnumerator : IEnumerator getResult, - StreamingChatCompletionUpdateCollection enumerable) + InternalStreamingChatCompletionUpdateCollection enumerable) { Debug.Assert(getResult is not null); Debug.Assert(enumerable is not null); diff --git a/.dotnet/src/Custom/Chat/StreamingChatCompletionUpdate.cs b/.dotnet/src/Custom/Chat/Streaming/StreamingChatCompletionUpdate.cs similarity index 100% rename from .dotnet/src/Custom/Chat/StreamingChatCompletionUpdate.cs rename to .dotnet/src/Custom/Chat/Streaming/StreamingChatCompletionUpdate.cs diff --git a/.dotnet/src/Custom/Chat/StreamingChatFunctionCallUpdate.cs b/.dotnet/src/Custom/Chat/Streaming/StreamingChatFunctionCallUpdate.cs similarity index 100% rename from .dotnet/src/Custom/Chat/StreamingChatFunctionCallUpdate.cs rename to .dotnet/src/Custom/Chat/Streaming/StreamingChatFunctionCallUpdate.cs diff --git a/.dotnet/src/Custom/Chat/StreamingChatToolCallUpdate.cs b/.dotnet/src/Custom/Chat/Streaming/StreamingChatToolCallUpdate.cs similarity index 100% rename from .dotnet/src/Custom/Chat/StreamingChatToolCallUpdate.cs rename to .dotnet/src/Custom/Chat/Streaming/StreamingChatToolCallUpdate.cs diff --git a/.dotnet/src/Generated/Models/ChatImageDetailLevel.cs b/.dotnet/src/Generated/Models/ChatImageDetailLevel.cs new file mode 100644 index 000000000..28d44ae56 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatImageDetailLevel.cs @@ -0,0 +1,38 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Chat +{ + public readonly partial struct ChatImageDetailLevel : IEquatable + { + private readonly string _value; + + public ChatImageDetailLevel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string AutoValue = "auto"; + private const string LowValue = "low"; + private const string HighValue = "high"; + + public static ChatImageDetailLevel Auto { get; } = new ChatImageDetailLevel(AutoValue); + public static ChatImageDetailLevel Low { get; } = new ChatImageDetailLevel(LowValue); + public static ChatImageDetailLevel High { get; } = new ChatImageDetailLevel(HighValue); + public static bool operator ==(ChatImageDetailLevel left, ChatImageDetailLevel right) => left.Equals(right); + public static bool operator !=(ChatImageDetailLevel left, ChatImageDetailLevel right) => !left.Equals(right); + public static implicit operator ChatImageDetailLevel(string value) => new ChatImageDetailLevel(value); + + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ChatImageDetailLevel other && Equals(other); + public bool Equals(ChatImageDetailLevel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(_value) : 0; + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ImageChatMessageContentPartDetail.cs b/.dotnet/src/Generated/Models/ImageChatMessageContentPartDetail.cs deleted file mode 100644 index 137c9a819..000000000 --- a/.dotnet/src/Generated/Models/ImageChatMessageContentPartDetail.cs +++ /dev/null @@ -1,38 +0,0 @@ -// - -#nullable disable - -using System; -using System.ComponentModel; - -namespace OpenAI.Chat -{ - public readonly partial struct ImageChatMessageContentPartDetail : IEquatable - { - private readonly string _value; - - public ImageChatMessageContentPartDetail(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - private const string AutoValue = "auto"; - private const string LowValue = "low"; - private const string HighValue = "high"; - - public static ImageChatMessageContentPartDetail Auto { get; } = new ImageChatMessageContentPartDetail(AutoValue); - public static ImageChatMessageContentPartDetail Low { get; } = new ImageChatMessageContentPartDetail(LowValue); - public static ImageChatMessageContentPartDetail High { get; } = new ImageChatMessageContentPartDetail(HighValue); - public static bool operator ==(ImageChatMessageContentPartDetail left, ImageChatMessageContentPartDetail right) => left.Equals(right); - public static bool operator !=(ImageChatMessageContentPartDetail left, ImageChatMessageContentPartDetail right) => !left.Equals(right); - public static implicit operator ImageChatMessageContentPartDetail(string value) => new ImageChatMessageContentPartDetail(value); - - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => obj is ImageChatMessageContentPartDetail other && Equals(other); - public bool Equals(ImageChatMessageContentPartDetail other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(_value) : 0; - public override string ToString() => _value; - } -} diff --git a/.dotnet/src/Generated/Models/InternalChatCompletionRequestMessageContentPartImageImageUrl.Serialization.cs b/.dotnet/src/Generated/Models/InternalChatCompletionRequestMessageContentPartImageImageUrl.Serialization.cs index f094173d0..e84cdd271 100644 --- a/.dotnet/src/Generated/Models/InternalChatCompletionRequestMessageContentPartImageImageUrl.Serialization.cs +++ b/.dotnet/src/Generated/Models/InternalChatCompletionRequestMessageContentPartImageImageUrl.Serialization.cs @@ -74,7 +74,7 @@ internal static InternalChatCompletionRequestMessageContentPartImageImageUrl Des return null; } string url = default; - ImageChatMessageContentPartDetail? detail = default; + ChatImageDetailLevel? detail = default; IDictionary serializedAdditionalRawData = default; Dictionary rawDataDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -90,7 +90,7 @@ internal static InternalChatCompletionRequestMessageContentPartImageImageUrl Des { continue; } - detail = new ImageChatMessageContentPartDetail(property.Value.GetString()); + detail = new ChatImageDetailLevel(property.Value.GetString()); continue; } if (true) diff --git a/.dotnet/src/Generated/Models/InternalChatCompletionRequestMessageContentPartImageImageUrl.cs b/.dotnet/src/Generated/Models/InternalChatCompletionRequestMessageContentPartImageImageUrl.cs index 1ff5dc332..e0e87271f 100644 --- a/.dotnet/src/Generated/Models/InternalChatCompletionRequestMessageContentPartImageImageUrl.cs +++ b/.dotnet/src/Generated/Models/InternalChatCompletionRequestMessageContentPartImageImageUrl.cs @@ -14,6 +14,6 @@ internal partial class InternalChatCompletionRequestMessageContentPartImageImage internal InternalChatCompletionRequestMessageContentPartImageImageUrl() { } - public ImageChatMessageContentPartDetail? Detail { get; set; } + public ChatImageDetailLevel? Detail { get; set; } } } diff --git a/.dotnet/tests/Chat/ChatSmokeTests.cs b/.dotnet/tests/Chat/ChatSmokeTests.cs index f06d97a98..1e01b8529 100644 --- a/.dotnet/tests/Chat/ChatSmokeTests.cs +++ b/.dotnet/tests/Chat/ChatSmokeTests.cs @@ -66,8 +66,8 @@ public async Task SmokeTest() ChatClient client = new("model_name_replaced", new ApiKeyCredential("sk-not-a-real-key"), options); ClientResult completionResult = IsAsync - ? await client.CompleteChatAsync(["Mock me!"]) - : client.CompleteChat(["Mock me!"]); + ? await client.CompleteChatAsync([ new UserChatMessage("Mock me!") ]) + : client.CompleteChat([ new UserChatMessage("Mock me!") ]); Assert.That(completionResult?.GetRawResponse(), Is.Not.Null); Assert.That(completionResult.GetRawResponse().Content?.ToString(), Does.Contain("additional world")); @@ -325,7 +325,7 @@ public void SerializeChatMessageContentPartAsText(bool fromRawJson) else { // We construct a new instance. Later, we serialize it and confirm it was constructed correctly. - part = ChatMessageContentPart.CreateTextMessageContentPart(text); + part = ChatMessageContentPart.CreateTextPart(text); } BinaryData serializedPart = ModelReaderWriter.Write(part); @@ -379,7 +379,7 @@ public void SerializeChatMessageContentPartAsImageUri(bool fromRawJson) else { // We construct a new instance. Later, we serialize it and confirm it was constructed correctly. - part = ChatMessageContentPart.CreateImageMessageContentPart(new Uri(uri), ImageChatMessageContentPartDetail.High); + part = ChatMessageContentPart.CreateImagePart(new Uri(uri), ChatImageDetailLevel.High); } BinaryData serializedPart = ModelReaderWriter.Write(part); @@ -454,7 +454,7 @@ public void SerializeChatMessageContentPartAsImageBytes(bool fromRawJson) else { // We construct a new instance. Later, we serialize it and confirm it was constructed correctly. - part = ChatMessageContentPart.CreateImageMessageContentPart(imageData, imageMediaType, ImageChatMessageContentPartDetail.Auto); + part = ChatMessageContentPart.CreateImagePart(imageData, imageMediaType, ChatImageDetailLevel.Auto); } BinaryData serializedPart = ModelReaderWriter.Write(part); @@ -494,8 +494,8 @@ public void SerializeChatMessageContentPartAsImageBytes(bool fromRawJson) public void SerializeCompoundContent() { UserChatMessage message = new( - ChatMessageContentPart.CreateTextMessageContentPart("Describe this image for me:"), - ChatMessageContentPart.CreateImageMessageContentPart(new Uri("https://api.openai.com/test"))); + ChatMessageContentPart.CreateTextPart("Describe this image for me:"), + ChatMessageContentPart.CreateImagePart(new Uri("https://api.openai.com/test"))); string serializedMessage = ModelReaderWriter.Write(message).ToString(); Assert.That(serializedMessage, Does.Contain("this image")); Assert.That(serializedMessage, Does.Contain("openai.com/test")); @@ -605,7 +605,7 @@ public void TopLevelClientOptionsPersistence() OpenAIClient topLevelClient = new(new("mock-credential"), options); ChatClient firstClient = topLevelClient.GetChatClient("mock-model"); - ClientResult first = firstClient.CompleteChat("Hello, world"); + ClientResult first = firstClient.CompleteChat(new UserChatMessage("Hello, world")); Assert.That(observedEndpoint, Is.Not.Null); Assert.That(observedEndpoint.AbsoluteUri, Does.Contain("my.custom.com/expected/test/endpoint")); diff --git a/.dotnet/tests/Chat/ChatTests.cs b/.dotnet/tests/Chat/ChatTests.cs index 62d842874..792948239 100644 --- a/.dotnet/tests/Chat/ChatTests.cs +++ b/.dotnet/tests/Chat/ChatTests.cs @@ -170,8 +170,8 @@ public async Task ChatWithVision() ChatClient client = GetTestClient(TestScenario.Chat); IEnumerable messages = [ new UserChatMessage( - ChatMessageContentPart.CreateTextMessageContentPart("Describe this image for me."), - ChatMessageContentPart.CreateImageMessageContentPart(imageData, mediaType)), + ChatMessageContentPart.CreateTextPart("Describe this image for me."), + ChatMessageContentPart.CreateImagePart(imageData, mediaType)), ]; ChatCompletionOptions options = new() { MaxTokens = 2048 }; @@ -334,8 +334,8 @@ public async Task NonStrictJsonSchemaWorks() strictSchemaEnabled: false) }; ChatCompletion completion = IsAsync - ? await client.CompleteChatAsync(["What are the hex values for red, green, and blue?"], options) - : client.CompleteChat(["What are the hex values for red, green, and blue?"], options); + ? await client.CompleteChatAsync([ new UserChatMessage("What are the hex values for red, green, and blue?") ], options) + : client.CompleteChat([ new UserChatMessage("What are the hex values for red, green, and blue?") ], options); Console.WriteLine(completion); } @@ -485,7 +485,7 @@ public async Task StructuredRefusalWorks() Assert.That(contextMessage.Refusal, Has.Length.GreaterThan(0)); messages.Add(contextMessage); - messages.Add("Why can't you help me?"); + messages.Add(new UserChatMessage("Why can't you help me?")); completion = IsAsync ? await client.CompleteChatAsync(messages) diff --git a/.dotnet/tests/Chat/OpenAIChatModelFactoryTests.cs b/.dotnet/tests/Chat/OpenAIChatModelFactoryTests.cs index 2255c8d55..78f540e1b 100644 --- a/.dotnet/tests/Chat/OpenAIChatModelFactoryTests.cs +++ b/.dotnet/tests/Chat/OpenAIChatModelFactoryTests.cs @@ -76,8 +76,8 @@ public void ChatCompletionWithFinishReasonWorks() public void ChatCompletionWithContentWorks() { IEnumerable content = [ - ChatMessageContentPart.CreateTextMessageContentPart("first part"), - ChatMessageContentPart.CreateTextMessageContentPart("second part") + ChatMessageContentPart.CreateTextPart("first part"), + ChatMessageContentPart.CreateTextPart("second part") ]; ChatCompletion chatCompletion = OpenAIChatModelFactory.ChatCompletion(content: content); @@ -508,8 +508,8 @@ public void StreamingChatCompletionUpdateWithIdWorks() public void StreamingChatCompletionUpdateWithContentUpdateWorks() { IEnumerable contentUpdate = [ - ChatMessageContentPart.CreateTextMessageContentPart("first part"), - ChatMessageContentPart.CreateTextMessageContentPart("second part") + ChatMessageContentPart.CreateTextPart("first part"), + ChatMessageContentPart.CreateTextPart("second part") ]; StreamingChatCompletionUpdate streamingChatCompletionUpdate = OpenAIChatModelFactory.StreamingChatCompletionUpdate(contentUpdate: contentUpdate); diff --git a/.dotnet/tests/Images/ImageGenerationTests.cs b/.dotnet/tests/Images/ImageGenerationTests.cs index efc95c544..1816d5853 100644 --- a/.dotnet/tests/Images/ImageGenerationTests.cs +++ b/.dotnet/tests/Images/ImageGenerationTests.cs @@ -181,8 +181,8 @@ private void ValidateGeneratedImage(Uri imageUri, string expectedSubstring, stri ChatClient chatClient = GetTestClient(TestScenario.Chat); IEnumerable messages = [ new UserChatMessage( - ChatMessageContentPart.CreateTextMessageContentPart($"Describe this image for me. {descriptionHint}"), - ChatMessageContentPart.CreateImageMessageContentPart(imageUri)), + ChatMessageContentPart.CreateTextPart($"Describe this image for me. {descriptionHint}"), + ChatMessageContentPart.CreateImagePart(imageUri)), ]; ChatCompletionOptions chatOptions = new() { MaxTokens = 2048 }; ClientResult result = chatClient.CompleteChat(messages, chatOptions); @@ -195,8 +195,8 @@ private void ValidateGeneratedImage(BinaryData imageBytes, string expectedSubstr ChatClient chatClient = GetTestClient(TestScenario.Chat); IEnumerable messages = [ new UserChatMessage( - ChatMessageContentPart.CreateTextMessageContentPart($"Describe this image for me. {descriptionHint}"), - ChatMessageContentPart.CreateImageMessageContentPart(imageBytes, "image/png")), + ChatMessageContentPart.CreateTextPart($"Describe this image for me. {descriptionHint}"), + ChatMessageContentPart.CreateImagePart(imageBytes, "image/png")), ]; ChatCompletionOptions chatOptions = new() { MaxTokens = 2048 }; ClientResult result = chatClient.CompleteChat(messages, chatOptions);