Skip to content

Commit fbb96e6

Browse files
authored
Add ContentParts to ChatCompletionMessageListDatum (#648)
1 parent d8e67d6 commit fbb96e6

12 files changed

+8494
-8347
lines changed

api/OpenAI.net8.0.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,6 +1638,7 @@ public class ChatCompletionMessageCollectionOptions : IJsonModel<ChatCompletionM
16381638
public class ChatCompletionMessageListDatum : IJsonModel<ChatCompletionMessageListDatum>, IPersistableModel<ChatCompletionMessageListDatum> {
16391639
public IReadOnlyList<ChatMessageAnnotation> Annotations { get; }
16401640
public string Content { get; }
1641+
public IList<ChatMessageContentPart> ContentParts { get; }
16411642
public string Id { get; }
16421643
public ChatOutputAudio OutputAudio { get; }
16431644
[EditorBrowsable(EditorBrowsableState.Never)]
@@ -2232,6 +2233,7 @@ public static class OpenAIChatModelFactory {
22322233
public static ChatCompletion ChatCompletion(string id = null, ChatFinishReason finishReason = ChatFinishReason.Stop, ChatMessageContent content = null, string refusal = null, IEnumerable<ChatToolCall> toolCalls = null, ChatMessageRole role = ChatMessageRole.System, ChatFunctionCall functionCall = null, IEnumerable<ChatTokenLogProbabilityDetails> contentTokenLogProbabilities = null, IEnumerable<ChatTokenLogProbabilityDetails> refusalTokenLogProbabilities = null, DateTimeOffset createdAt = default, string model = null, ChatServiceTier? serviceTier = null, string systemFingerprint = null, ChatTokenUsage usage = null, ChatOutputAudio outputAudio = null, IEnumerable<ChatMessageAnnotation> messageAnnotations = null);
22332234
[EditorBrowsable(EditorBrowsableState.Never)]
22342235
public static ChatCompletion ChatCompletion(string id, ChatFinishReason finishReason, ChatMessageContent content, string refusal, IEnumerable<ChatToolCall> toolCalls, ChatMessageRole role, ChatFunctionCall functionCall, IEnumerable<ChatTokenLogProbabilityDetails> contentTokenLogProbabilities, IEnumerable<ChatTokenLogProbabilityDetails> refusalTokenLogProbabilities, DateTimeOffset createdAt, string model, string systemFingerprint, ChatTokenUsage usage);
2236+
public static ChatCompletionMessageListDatum ChatCompletionMessageListDatum(string id, string content, string refusal, ChatMessageRole role, IList<ChatMessageContentPart> contentParts = null, IList<ChatToolCall> toolCalls = null, IList<ChatMessageAnnotation> annotations = null, string functionName = null, string functionArguments = null, ChatOutputAudio outputAudio = null);
22352237
public static ChatInputTokenUsageDetails ChatInputTokenUsageDetails(int audioTokenCount = 0, int cachedTokenCount = 0);
22362238
[Experimental("OPENAI001")]
22372239
public static ChatMessageAnnotation ChatMessageAnnotation(int startIndex = 0, int endIndex = 0, Uri webResourceUri = null, string webResourceTitle = null);

api/OpenAI.netstandard2.0.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,6 +1447,7 @@ public class ChatCompletionMessageCollectionOptions : IJsonModel<ChatCompletionM
14471447
public class ChatCompletionMessageListDatum : IJsonModel<ChatCompletionMessageListDatum>, IPersistableModel<ChatCompletionMessageListDatum> {
14481448
public IReadOnlyList<ChatMessageAnnotation> Annotations { get; }
14491449
public string Content { get; }
1450+
public IList<ChatMessageContentPart> ContentParts { get; }
14501451
public string Id { get; }
14511452
public ChatOutputAudio OutputAudio { get; }
14521453
[EditorBrowsable(EditorBrowsableState.Never)]
@@ -1921,6 +1922,7 @@ public static class OpenAIChatModelFactory {
19211922
public static ChatCompletion ChatCompletion(string id = null, ChatFinishReason finishReason = ChatFinishReason.Stop, ChatMessageContent content = null, string refusal = null, IEnumerable<ChatToolCall> toolCalls = null, ChatMessageRole role = ChatMessageRole.System, ChatFunctionCall functionCall = null, IEnumerable<ChatTokenLogProbabilityDetails> contentTokenLogProbabilities = null, IEnumerable<ChatTokenLogProbabilityDetails> refusalTokenLogProbabilities = null, DateTimeOffset createdAt = default, string model = null, ChatServiceTier? serviceTier = null, string systemFingerprint = null, ChatTokenUsage usage = null, ChatOutputAudio outputAudio = null, IEnumerable<ChatMessageAnnotation> messageAnnotations = null);
19221923
[EditorBrowsable(EditorBrowsableState.Never)]
19231924
public static ChatCompletion ChatCompletion(string id, ChatFinishReason finishReason, ChatMessageContent content, string refusal, IEnumerable<ChatToolCall> toolCalls, ChatMessageRole role, ChatFunctionCall functionCall, IEnumerable<ChatTokenLogProbabilityDetails> contentTokenLogProbabilities, IEnumerable<ChatTokenLogProbabilityDetails> refusalTokenLogProbabilities, DateTimeOffset createdAt, string model, string systemFingerprint, ChatTokenUsage usage);
1925+
public static ChatCompletionMessageListDatum ChatCompletionMessageListDatum(string id, string content, string refusal, ChatMessageRole role, IList<ChatMessageContentPart> contentParts = null, IList<ChatToolCall> toolCalls = null, IList<ChatMessageAnnotation> annotations = null, string functionName = null, string functionArguments = null, ChatOutputAudio outputAudio = null);
19241926
public static ChatInputTokenUsageDetails ChatInputTokenUsageDetails(int audioTokenCount = 0, int cachedTokenCount = 0);
19251927
public static ChatMessageAnnotation ChatMessageAnnotation(int startIndex = 0, int endIndex = 0, Uri webResourceUri = null, string webResourceTitle = null);
19261928
public static ChatOutputAudio ChatOutputAudio(BinaryData audioBytes, string id = null, string transcript = null, DateTimeOffset expiresAt = default);

specification/base/typespec/chat/models.tsp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ alias CreateChatCompletionStreamResponseChoice = {
124124
alias ChatCompletionMessageListData = {
125125
...ChatCompletionResponseMessage;
126126

127+
content_parts?: ChatCompletionRequestMessageContentPart[] | null;
128+
127129
/** The identifier of the chat message. */
128130
id: string;
129131
};

src/Custom/Chat/OpenAIChatModelFactory.cs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.ComponentModel;
44
using System.Diagnostics.CodeAnalysis;
55
using System.Linq;
6+
using OpenAI.Responses;
67

78
namespace OpenAI.Chat;
89

@@ -29,7 +30,7 @@ public static ChatCompletion ChatCompletion(
2930
ChatCompletion(
3031
id: id,
3132
finishReason: finishReason,
32-
content:content,
33+
content: content,
3334
refusal: refusal,
3435
toolCalls: toolCalls,
3536
role: role,
@@ -70,13 +71,13 @@ public static ChatCompletion ChatCompletion(
7071
messageAnnotations ??= new List<ChatMessageAnnotation>();
7172

7273
InternalChatCompletionResponseMessage message = new(
74+
content: content,
7375
refusal: refusal,
7476
toolCalls: toolCalls.ToList(),
7577
annotations: messageAnnotations.ToList(),
76-
audio: outputAudio,
7778
role: role,
78-
content: content,
7979
functionCall: functionCall,
80+
audio: outputAudio,
8081
patch: default);
8182

8283
InternalCreateChatCompletionResponseChoiceLogprobs logprobs = new InternalCreateChatCompletionResponseChoiceLogprobs(
@@ -372,4 +373,40 @@ public static StreamingChatToolCallUpdate StreamingChatToolCallUpdate(int index
372373
toolCallId: toolCallId,
373374
patch: default);
374375
}
376+
377+
/// <summary> Initializes a new instance of <see cref="OpenAI.Chat.ChatCompletionMessageListDatum"/>. </summary>
378+
/// <returns> A new <see cref="OpenAI.Chat.ChatCompletionMessageListDatum"/> instance for mocking.</returns>
379+
public static ChatCompletionMessageListDatum ChatCompletionMessageListDatum(
380+
string id,
381+
string content,
382+
string refusal,
383+
ChatMessageRole role,
384+
IList<ChatMessageContentPart> contentParts = null,
385+
IList<ChatToolCall> toolCalls = null,
386+
IList<ChatMessageAnnotation> annotations = null,
387+
string functionName = null,
388+
string functionArguments = null,
389+
ChatOutputAudio outputAudio = null)
390+
{
391+
InternalChatCompletionResponseMessageFunctionCall functionCall = null;
392+
if (functionName != null && functionArguments != null)
393+
{
394+
functionCall = new(
395+
name: functionName,
396+
arguments: functionArguments,
397+
patch: default);
398+
}
399+
400+
return new ChatCompletionMessageListDatum(
401+
content: content,
402+
contentParts: contentParts,
403+
refusal: refusal,
404+
toolCalls: toolCalls.ToList().AsReadOnly(),
405+
annotations: annotations.ToList().AsReadOnly(),
406+
role: role,
407+
functionCall: functionCall,
408+
outputAudio: outputAudio,
409+
id: id,
410+
patch: default);
411+
}
375412
}

src/Generated/Models/Chat/ChatCompletionMessageListDatum.Serialization.cs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace OpenAI.Chat
1313
{
1414
public partial class ChatCompletionMessageListDatum : IJsonModel<ChatCompletionMessageListDatum>
1515
{
16-
internal ChatCompletionMessageListDatum() : this(null, null, null, null, default, null, null, null, default)
16+
internal ChatCompletionMessageListDatum() : this(null, null, null, null, default, null, null, null, null, default)
1717
{
1818
}
1919

@@ -119,6 +119,29 @@ protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWrit
119119
writer.WritePropertyName("audio"u8);
120120
writer.WriteObjectValue(OutputAudio, options);
121121
}
122+
if (Patch.Contains("$.content_parts"u8))
123+
{
124+
if (!Patch.IsRemoved("$.content_parts"u8))
125+
{
126+
writer.WritePropertyName("content_parts"u8);
127+
writer.WriteRawValue(Patch.GetJson("$.content_parts"u8));
128+
}
129+
}
130+
else if (Optional.IsCollectionDefined(ContentParts))
131+
{
132+
writer.WritePropertyName("content_parts"u8);
133+
writer.WriteStartArray();
134+
for (int i = 0; i < ContentParts.Count; i++)
135+
{
136+
if (ContentParts[i].Patch.IsRemoved("$"u8))
137+
{
138+
continue;
139+
}
140+
writer.WriteObjectValue(ContentParts[i], options);
141+
}
142+
Patch.WriteTo(writer, "$.content_parts"u8);
143+
writer.WriteEndArray();
144+
}
122145
if (!Patch.Contains("$.id"u8))
123146
{
124147
writer.WritePropertyName("id"u8);
@@ -155,6 +178,7 @@ internal static ChatCompletionMessageListDatum DeserializeChatCompletionMessageL
155178
ChatMessageRole role = default;
156179
InternalChatCompletionResponseMessageFunctionCall functionCall = default;
157180
ChatOutputAudio outputAudio = default;
181+
IList<ChatMessageContentPart> contentParts = default;
158182
string id = default;
159183
#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
160184
JsonPatch patch = new JsonPatch(data is null ? ReadOnlyMemory<byte>.Empty : data.ToMemory());
@@ -233,6 +257,20 @@ internal static ChatCompletionMessageListDatum DeserializeChatCompletionMessageL
233257
outputAudio = ChatOutputAudio.DeserializeChatOutputAudio(prop.Value, prop.Value.GetUtf8Bytes(), options);
234258
continue;
235259
}
260+
if (prop.NameEquals("content_parts"u8))
261+
{
262+
if (prop.Value.ValueKind == JsonValueKind.Null)
263+
{
264+
continue;
265+
}
266+
List<ChatMessageContentPart> array = new List<ChatMessageContentPart>();
267+
foreach (var item in prop.Value.EnumerateArray())
268+
{
269+
array.Add(ChatMessageContentPart.DeserializeChatMessageContentPart(item, item.GetUtf8Bytes(), options));
270+
}
271+
contentParts = array;
272+
continue;
273+
}
236274
if (prop.NameEquals("id"u8))
237275
{
238276
id = prop.Value.GetString();
@@ -248,6 +286,7 @@ internal static ChatCompletionMessageListDatum DeserializeChatCompletionMessageL
248286
role,
249287
functionCall,
250288
outputAudio,
289+
contentParts ?? new ChangeTrackingList<ChatMessageContentPart>(),
251290
id,
252291
patch);
253292
}
@@ -315,6 +354,16 @@ private bool PropagateGet(ReadOnlySpan<byte> jsonPath, out JsonPatch.EncodedValu
315354
}
316355
return Annotations[index].Patch.TryGetEncodedValue([.. "$"u8, .. currentSlice.Slice(bytesConsumed)], out value);
317356
}
357+
if (local.StartsWith("content_parts"u8))
358+
{
359+
int propertyLength = "content_parts"u8.Length;
360+
ReadOnlySpan<byte> currentSlice = local.Slice(propertyLength);
361+
if (!currentSlice.TryGetIndex(out int index, out int bytesConsumed))
362+
{
363+
return false;
364+
}
365+
return ContentParts[index].Patch.TryGetEncodedValue([.. "$"u8, .. currentSlice.Slice(bytesConsumed)], out value);
366+
}
318367
return false;
319368
}
320369
#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
@@ -351,6 +400,17 @@ private bool PropagateSet(ReadOnlySpan<byte> jsonPath, JsonPatch.EncodedValue va
351400
Annotations[index].Patch.Set([.. "$"u8, .. currentSlice.Slice(bytesConsumed)], value);
352401
return true;
353402
}
403+
if (local.StartsWith("content_parts"u8))
404+
{
405+
int propertyLength = "content_parts"u8.Length;
406+
ReadOnlySpan<byte> currentSlice = local.Slice(propertyLength);
407+
if (!currentSlice.TryGetIndex(out int index, out int bytesConsumed))
408+
{
409+
return false;
410+
}
411+
ContentParts[index].Patch.Set([.. "$"u8, .. currentSlice.Slice(bytesConsumed)], value);
412+
return true;
413+
}
354414
return false;
355415
}
356416
#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.

src/Generated/Models/Chat/ChatCompletionMessageListDatum.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@ internal ChatCompletionMessageListDatum(string content, string refusal, string i
2222
Refusal = refusal;
2323
ToolCalls = new ChangeTrackingList<ChatToolCall>();
2424
Annotations = new ChangeTrackingList<ChatMessageAnnotation>();
25+
ContentParts = new ChangeTrackingList<ChatMessageContentPart>();
2526
Id = id;
2627
}
2728

2829
#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
29-
internal ChatCompletionMessageListDatum(string content, string refusal, IReadOnlyList<ChatToolCall> toolCalls, IReadOnlyList<ChatMessageAnnotation> annotations, ChatMessageRole role, InternalChatCompletionResponseMessageFunctionCall functionCall, ChatOutputAudio outputAudio, string id, in JsonPatch patch)
30+
internal ChatCompletionMessageListDatum(string content, string refusal, IReadOnlyList<ChatToolCall> toolCalls, IReadOnlyList<ChatMessageAnnotation> annotations, ChatMessageRole role, InternalChatCompletionResponseMessageFunctionCall functionCall, ChatOutputAudio outputAudio, IList<ChatMessageContentPart> contentParts, string id, in JsonPatch patch)
3031
{
3132
// Plugin customization: ensure initialization of collections
3233
Content = content;
@@ -36,6 +37,7 @@ internal ChatCompletionMessageListDatum(string content, string refusal, IReadOnl
3637
Role = role;
3738
FunctionCall = functionCall;
3839
OutputAudio = outputAudio;
40+
ContentParts = contentParts ?? new ChangeTrackingList<ChatMessageContentPart>();
3941
Id = id;
4042
_patch = patch;
4143
_patch.SetPropagators(PropagateSet, PropagateGet);
@@ -56,6 +58,8 @@ internal ChatCompletionMessageListDatum(string content, string refusal, IReadOnl
5658

5759
internal InternalChatCompletionResponseMessageFunctionCall FunctionCall { get; }
5860

61+
public IList<ChatMessageContentPart> ContentParts { get; }
62+
5963
public string Id { get; }
6064
}
6165
}

src/Generated/Models/Chat/InternalChatCompletionRequestMessageContentPartAudio.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ internal InternalChatCompletionRequestMessageContentPartAudio(in JsonPatch patch
2323
}
2424
#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
2525

26-
internal InternalChatCompletionRequestMessageContentPartAudioInputAudio InputAudio { get; }
26+
internal InternalChatCompletionRequestMessageContentPartAudioInputAudio InputAudio { get; set; }
2727
}
2828
}

src/Generated/Models/Chat/InternalChatCompletionRequestMessageContentPartAudioInputAudio.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ internal InternalChatCompletionRequestMessageContentPartAudioInputAudio(BinaryDa
3636
[Experimental("SCME0001")]
3737
public ref JsonPatch Patch => ref _patch;
3838

39-
public BinaryData Data { get; }
39+
public BinaryData Data { get; set; }
4040

41-
public ChatInputAudioFormat Format { get; }
41+
public ChatInputAudioFormat Format { get; set; }
4242
}
4343
}

src/Generated/Models/Chat/InternalChatCompletionRequestMessageContentPartFile.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ internal InternalChatCompletionRequestMessageContentPartFile(in JsonPatch patch,
2323
}
2424
#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
2525

26-
internal InternalChatCompletionRequestMessageContentPartFileFile File { get; }
26+
internal InternalChatCompletionRequestMessageContentPartFileFile File { get; set; }
2727
}
2828
}

src/Generated/Models/Chat/InternalChatCompletionRequestMessageContentPartImage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ internal InternalChatCompletionRequestMessageContentPartImage(in JsonPatch patch
2323
}
2424
#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
2525

26-
internal InternalChatCompletionRequestMessageContentPartImageImageUrl ImageUrl { get; }
26+
internal InternalChatCompletionRequestMessageContentPartImageImageUrl ImageUrl { get; set; }
2727
}
2828
}

0 commit comments

Comments
 (0)