15
15
using OpenAI . Responses ;
16
16
using static Microsoft . Extensions . AI . OpenAIChatClient ;
17
17
18
+ #pragma warning disable S907 // "goto" statement should not be used
18
19
#pragma warning disable S1067 // Expressions should not be too complex
19
20
#pragma warning disable S3011 // Reflection should not be used to increase accessibility of classes, methods, or fields
20
21
#pragma warning disable S3604 // Member initializer values should not be redundant
@@ -87,12 +88,13 @@ public async Task<ChatResponse> GetResponseAsync(
87
88
// Convert and return the results.
88
89
ChatResponse response = new ( )
89
90
{
90
- ResponseId = openAIResponse . Id ,
91
91
ConversationId = openAIResponse . Id ,
92
92
CreatedAt = openAIResponse . CreatedAt ,
93
93
FinishReason = ToFinishReason ( openAIResponse . IncompleteStatusDetails ? . Reason ) ,
94
94
Messages = [ new ( ChatRole . Assistant , [ ] ) ] ,
95
95
ModelId = openAIResponse . Model ,
96
+ RawRepresentation = openAIResponse ,
97
+ ResponseId = openAIResponse . Id ,
96
98
Usage = ToUsageDetails ( openAIResponse ) ,
97
99
} ;
98
100
@@ -125,12 +127,20 @@ public async Task<ChatResponse> GetResponseAsync(
125
127
126
128
case FunctionCallResponseItem functionCall :
127
129
response . FinishReason ??= ChatFinishReason . ToolCalls ;
128
- message . Contents . Add (
129
- FunctionCallContent . CreateFromParsedArguments (
130
- functionCall . FunctionArguments . ToMemory ( ) ,
131
- functionCall . CallId ,
132
- functionCall . FunctionName ,
133
- static json => JsonSerializer . Deserialize ( json . Span , ResponseClientJsonContext . Default . IDictionaryStringObject ) ! ) ) ;
130
+ var fcc = FunctionCallContent . CreateFromParsedArguments (
131
+ functionCall . FunctionArguments . ToMemory ( ) ,
132
+ functionCall . CallId ,
133
+ functionCall . FunctionName ,
134
+ static json => JsonSerializer . Deserialize ( json . Span , ResponseClientJsonContext . Default . IDictionaryStringObject ) ! ) ;
135
+ fcc . RawRepresentation = outputItem ;
136
+ message . Contents . Add ( fcc ) ;
137
+ break ;
138
+
139
+ default :
140
+ message . Contents . Add ( new ( )
141
+ {
142
+ RawRepresentation = outputItem ,
143
+ } ) ;
134
144
break ;
135
145
}
136
146
}
@@ -170,20 +180,21 @@ public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
170
180
createdAt = createdUpdate . Response . CreatedAt ;
171
181
responseId = createdUpdate . Response . Id ;
172
182
modelId = createdUpdate . Response . Model ;
173
- break ;
183
+ goto default ;
174
184
175
185
case StreamingResponseCompletedUpdate completedUpdate :
176
186
yield return new ( )
177
187
{
178
- Contents = ToUsageDetails ( completedUpdate . Response ) is { } usage ? [ new UsageContent ( usage ) ] : [ ] ,
179
- CreatedAt = createdAt ,
180
- ResponseId = responseId ,
181
- ConversationId = responseId ,
182
188
FinishReason =
183
189
ToFinishReason ( completedUpdate . Response ? . IncompleteStatusDetails ? . Reason ) ??
184
190
( functionCallInfos is not null ? ChatFinishReason . ToolCalls : ChatFinishReason . Stop ) ,
191
+ Contents = ToUsageDetails ( completedUpdate . Response ) is { } usage ? [ new UsageContent ( usage ) ] : [ ] ,
192
+ ConversationId = responseId ,
193
+ CreatedAt = createdAt ,
185
194
MessageId = lastMessageId ,
186
195
ModelId = modelId ,
196
+ RawRepresentation = streamingUpdate ,
197
+ ResponseId = responseId ,
187
198
Role = lastRole ,
188
199
} ;
189
200
break ;
@@ -200,23 +211,24 @@ public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
200
211
break ;
201
212
}
202
213
203
- break ;
214
+ goto default ;
204
215
205
216
case StreamingResponseOutputItemDoneUpdate outputItemDoneUpdate :
206
217
_ = outputIndexToMessages . Remove ( outputItemDoneUpdate . OutputIndex ) ;
207
- break ;
218
+ goto default ;
208
219
209
220
case StreamingResponseOutputTextDeltaUpdate outputTextDeltaUpdate :
210
221
_ = outputIndexToMessages . TryGetValue ( outputTextDeltaUpdate . OutputIndex , out MessageResponseItem ? messageItem ) ;
211
222
lastMessageId = messageItem ? . Id ;
212
223
lastRole = ToChatRole ( messageItem ? . Role ) ;
213
224
yield return new ChatResponseUpdate ( lastRole , outputTextDeltaUpdate . Delta )
214
225
{
226
+ ConversationId = responseId ,
215
227
CreatedAt = createdAt ,
216
228
MessageId = lastMessageId ,
217
229
ModelId = modelId ,
230
+ RawRepresentation = streamingUpdate ,
218
231
ResponseId = responseId ,
219
- ConversationId = responseId ,
220
232
} ;
221
233
break ;
222
234
@@ -227,7 +239,7 @@ public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
227
239
_ = ( callInfo . Arguments ??= new ( ) ) . Append ( functionCallArgumentsDeltaUpdate . Delta ) ;
228
240
}
229
241
230
- break ;
242
+ goto default ;
231
243
}
232
244
233
245
case StreamingResponseFunctionCallArgumentsDoneUpdate functionCallOutputDoneUpdate :
@@ -246,25 +258,23 @@ public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
246
258
lastRole = ChatRole . Assistant ;
247
259
yield return new ChatResponseUpdate ( lastRole , [ fci ] )
248
260
{
261
+ ConversationId = responseId ,
249
262
CreatedAt = createdAt ,
250
263
MessageId = lastMessageId ,
251
264
ModelId = modelId ,
265
+ RawRepresentation = streamingUpdate ,
252
266
ResponseId = responseId ,
253
- ConversationId = responseId ,
254
267
} ;
268
+
269
+ break ;
255
270
}
256
271
257
- break ;
272
+ goto default ;
258
273
}
259
274
260
275
case StreamingResponseErrorUpdate errorUpdate :
261
276
yield return new ChatResponseUpdate
262
277
{
263
- CreatedAt = createdAt ,
264
- MessageId = lastMessageId ,
265
- ModelId = modelId ,
266
- ResponseId = responseId ,
267
- Role = lastRole ,
268
278
ConversationId = responseId ,
269
279
Contents =
270
280
[
@@ -274,6 +284,12 @@ public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
274
284
Details = errorUpdate . Param ,
275
285
}
276
286
] ,
287
+ CreatedAt = createdAt ,
288
+ MessageId = lastMessageId ,
289
+ ModelId = modelId ,
290
+ RawRepresentation = streamingUpdate ,
291
+ ResponseId = responseId ,
292
+ Role = lastRole ,
277
293
} ;
278
294
break ;
279
295
@@ -283,12 +299,26 @@ public async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
283
299
CreatedAt = createdAt ,
284
300
MessageId = lastMessageId ,
285
301
ModelId = modelId ,
302
+ RawRepresentation = streamingUpdate ,
286
303
ResponseId = responseId ,
287
304
Role = lastRole ,
288
305
ConversationId = responseId ,
289
306
Contents = [ new ErrorContent ( refusalDone . Refusal ) { ErrorCode = nameof ( ResponseContentPart . Refusal ) } ] ,
290
307
} ;
291
308
break ;
309
+
310
+ default :
311
+ yield return new ChatResponseUpdate
312
+ {
313
+ ConversationId = responseId ,
314
+ CreatedAt = createdAt ,
315
+ MessageId = lastMessageId ,
316
+ ModelId = modelId ,
317
+ RawRepresentation = streamingUpdate ,
318
+ ResponseId = responseId ,
319
+ Role = lastRole ,
320
+ } ;
321
+ break ;
292
322
}
293
323
}
294
324
}
@@ -487,6 +517,10 @@ private static IEnumerable<ResponseItem> ToOpenAIResponseItems(
487
517
callContent . Arguments ,
488
518
AIJsonUtilities . DefaultOptions . GetTypeInfo ( typeof ( IDictionary < string , object ? > ) ) ) ) ) ;
489
519
break ;
520
+
521
+ case AIContent when item . RawRepresentation is ResponseItem rawRep :
522
+ yield return rawRep ;
523
+ break ;
490
524
}
491
525
}
492
526
@@ -530,11 +564,25 @@ private static List<AIContent> ToAIContents(IEnumerable<ResponseContentPart> con
530
564
switch ( part . Kind )
531
565
{
532
566
case ResponseContentPartKind . OutputText :
533
- results . Add ( new TextContent ( part . Text ) ) ;
567
+ results . Add ( new TextContent ( part . Text )
568
+ {
569
+ RawRepresentation = part ,
570
+ } ) ;
534
571
break ;
535
572
536
573
case ResponseContentPartKind . Refusal :
537
- results . Add ( new ErrorContent ( part . Refusal ) { ErrorCode = nameof ( ResponseContentPartKind . Refusal ) } ) ;
574
+ results . Add ( new ErrorContent ( part . Refusal )
575
+ {
576
+ ErrorCode = nameof ( ResponseContentPartKind . Refusal ) ,
577
+ RawRepresentation = part ,
578
+ } ) ;
579
+ break ;
580
+
581
+ default :
582
+ results . Add ( new ( )
583
+ {
584
+ RawRepresentation = part ,
585
+ } ) ;
538
586
break ;
539
587
}
540
588
}
@@ -570,6 +618,10 @@ private static List<ResponseContentPart> ToOpenAIResponsesContent(IList<AIConten
570
618
case ErrorContent errorContent when errorContent . ErrorCode == nameof ( ResponseContentPartKind . Refusal ) :
571
619
parts . Add ( ResponseContentPart . CreateRefusalPart ( errorContent . Message ) ) ;
572
620
break ;
621
+
622
+ case AIContent when content . RawRepresentation is ResponseContentPart rawRep :
623
+ parts . Add ( rawRep ) ;
624
+ break ;
573
625
}
574
626
}
575
627
0 commit comments