11// Copyright (c) Microsoft Corporation. All rights reserved.
22// Licensed under the MIT License.
33
4- using Azure . AI . OpenAI . Internal ;
4+ using System . ClientModel ;
5+ using System . ClientModel . Primitives ;
56using System . Diagnostics . CodeAnalysis ;
7+ using System . Text ;
8+ using System . Text . Json ;
9+ using System . Text . Json . Nodes ;
610
711#pragma warning disable AZC0112
812
@@ -14,26 +18,40 @@ public static partial class AzureChatExtensions
1418 [ Experimental ( "AOAI001" ) ]
1519 public static void AddDataSource ( this ChatCompletionOptions options , ChatDataSource dataSource )
1620 {
17- options . SerializedAdditionalRawData ??= new Dictionary < string , BinaryData > ( ) ;
18-
19- IList < ChatDataSource > existingSources =
20- AdditionalPropertyHelpers . GetAdditionalPropertyAsListOfChatDataSource (
21- options . SerializedAdditionalRawData ,
22- "data_sources" )
23- ?? new ChangeTrackingList < ChatDataSource > ( ) ;
24- existingSources . Add ( dataSource ) ;
25- AdditionalPropertyHelpers . SetAdditionalProperty (
26- options . SerializedAdditionalRawData ,
27- "data_sources" ,
28- existingSources ) ;
21+ JsonArray doc ;
22+ if ( options . Patch . TryGetJson ( "$.data_sources"u8 , out ReadOnlyMemory < byte > jsonBytes ) )
23+ {
24+ using var stream = new MemoryStream ( ) ;
25+ stream . Write ( jsonBytes . ToArray ( ) , 0 , jsonBytes . Length ) ;
26+ string json = Encoding . UTF8 . GetString ( stream . ToArray ( ) ) ;
27+ doc = JsonObject . Parse ( json ) . AsObject ( ) . AsArray ( ) ;
28+ }
29+ else
30+ {
31+ doc = new ( ) ;
32+ }
33+ using var objectStream = new MemoryStream ( ) ;
34+ using BinaryContent contentBytes = BinaryContent . Create ( dataSource , ModelSerializationExtensions . WireOptions ) ;
35+ contentBytes . WriteTo ( objectStream ) ;
36+ string newJson = Encoding . UTF8 . GetString ( objectStream . ToArray ( ) ) ;
37+ doc . Append ( JsonObject . Parse ( newJson ) ) ;
38+ options . Patch . Set ( "$.data_sources"u8 , BinaryData . FromString ( doc . ToJsonString ( ) ) ) ;
2939 }
3040
3141 [ Experimental ( "AOAI001" ) ]
3242 public static IReadOnlyList < ChatDataSource > GetDataSources ( this ChatCompletionOptions options )
3343 {
34- return AdditionalPropertyHelpers . GetAdditionalPropertyAsListOfChatDataSource (
35- options . SerializedAdditionalRawData ,
36- "data_sources" ) as IReadOnlyList < ChatDataSource > ;
44+ if ( options . Patch . TryGetJson ( "$.data_sources"u8 , out ReadOnlyMemory < byte > mem ) )
45+ {
46+ using JsonDocument doc = JsonDocument . Parse ( mem ) ;
47+ List < ChatDataSource > chats = [ ] ;
48+ foreach ( JsonElement dataSource in doc . RootElement . EnumerateArray ( ) )
49+ {
50+ chats . Add ( ChatDataSource . DeserializeChatDataSource ( dataSource , ModelSerializationExtensions . WireOptions ) ) ;
51+ }
52+ return chats ;
53+ }
54+ return null ;
3755 }
3856
3957 [ Experimental ( "AOAI001" ) ]
@@ -42,99 +60,110 @@ public static void SetNewMaxCompletionTokensPropertyEnabled(this ChatCompletionO
4260 if ( newPropertyEnabled )
4361 {
4462 // Blocking serialization of max_tokens via dictionary acts as a signal to skip pre-serialization fixup
45- options . SerializedAdditionalRawData ??= new Dictionary < string , BinaryData > ( ) ;
46- AdditionalPropertyHelpers . SetEmptySentinelValue ( options . SerializedAdditionalRawData , "max_tokens" ) ;
63+ options . Patch . Remove ( "$.max_tokens"u8 ) ;
4764 }
4865 else
4966 {
5067 // In the absence of a dictionary serialization block to max_tokens, the newer property name will
5168 // automatically be blocked and the older property name will be used via dictionary override
52- if ( options ? . SerializedAdditionalRawData ? . ContainsKey ( " max_tokens") == true )
69+ if ( options . Patch . Contains ( "$. max_tokens"u8 ) )
5370 {
54- options ? . SerializedAdditionalRawData ? . Remove ( "max_tokens" ) ;
71+ options . Patch . Remove ( "$. max_tokens"u8 ) ;
5572 }
5673 }
5774 }
5875
5976 [ Experimental ( "AOAI001" ) ]
6077 public static RequestContentFilterResult GetRequestContentFilterResult ( this ChatCompletion chatCompletion )
6178 {
62- return AdditionalPropertyHelpers . GetAdditionalPropertyAsListOfRequestContentFilterResult (
63- chatCompletion . SerializedAdditionalRawData ,
64- "prompt_filter_results" ) ? [ 0 ] ;
79+ if ( chatCompletion . Patch . TryGetJson ( "$.prompt_filter_results"u8 , out ReadOnlyMemory < byte > mem ) )
80+ {
81+ using JsonDocument doc = JsonDocument . Parse ( mem ) ;
82+ return RequestContentFilterResult . DeserializeRequestContentFilterResult ( doc . RootElement , ModelSerializationExtensions . WireOptions ) ;
83+ }
84+ return null ;
6585 }
6686
6787 [ Experimental ( "AOAI001" ) ]
6888 public static ResponseContentFilterResult GetResponseContentFilterResult ( this ChatCompletion chatCompletion )
6989 {
70- return AdditionalPropertyHelpers . GetAdditionalPropertyAsResponseContentFilterResult (
71- chatCompletion . Choices ? [ 0 ] ? . SerializedAdditionalRawData ,
72- "content_filter_results" ) ;
90+ if ( chatCompletion . Choices ? [ 0 ] ? . Patch . TryGetJson ( "$.content_filter_results"u8 , out ReadOnlyMemory < byte > mem ) ?? false )
91+ {
92+ using JsonDocument doc = JsonDocument . Parse ( mem ) ;
93+ return ResponseContentFilterResult . DeserializeResponseContentFilterResult ( doc . RootElement , ModelSerializationExtensions . WireOptions ) ;
94+ }
95+ return null ;
7396 }
7497
7598 [ Experimental ( "AOAI001" ) ]
7699 public static ChatMessageContext GetMessageContext ( this ChatCompletion chatCompletion )
77100 {
78- return AdditionalPropertyHelpers . GetAdditionalPropertyAsChatMessageContext (
79- chatCompletion . Choices ? [ 0 ] ? . Message ? . SerializedAdditionalRawData ,
80- "context" ) ;
101+ if ( chatCompletion . Choices ? [ 0 ] ? . Message ? . Patch . TryGetJson ( "$.context"u8 , out ReadOnlyMemory < byte > mem ) ?? false )
102+ {
103+ using JsonDocument doc = JsonDocument . Parse ( mem ) ;
104+ return ChatMessageContext . DeserializeChatMessageContext ( doc . RootElement , ModelSerializationExtensions . WireOptions ) ;
105+ }
106+ return null ;
81107 }
82108
83109 [ Experimental ( "AOAI001" ) ]
84110 public static ChatMessageContext GetMessageContext ( this StreamingChatCompletionUpdate chatUpdate )
85111 {
86- if ( chatUpdate . Choices ? . Count > 0 )
112+ if ( chatUpdate . Choices ? . Count > 0 && chatUpdate . Choices [ 0 ] . Delta . Patch . TryGetJson ( "$.content_filter_results"u8 , out ReadOnlyMemory < byte > mem ) )
87113 {
88- return AdditionalPropertyHelpers . GetAdditionalPropertyAsChatMessageContext (
89- chatUpdate . Choices [ 0 ] . Delta ? . SerializedAdditionalRawData ,
90- "context" ) ;
114+ using JsonDocument doc = JsonDocument . Parse ( mem ) ;
115+ return ChatMessageContext . DeserializeChatMessageContext ( doc . RootElement , ModelSerializationExtensions . WireOptions ) ;
91116 }
92117 return null ;
93118 }
94119
95120 [ Experimental ( "AOAI001" ) ]
96121 public static RequestContentFilterResult GetRequestContentFilterResult ( this StreamingChatCompletionUpdate chatUpdate )
97122 {
98- return AdditionalPropertyHelpers . GetAdditionalPropertyAsListOfRequestContentFilterResult (
99- chatUpdate . SerializedAdditionalRawData ,
100- "prompt_filter_results" ) ? [ 0 ] ;
123+ if ( chatUpdate . Patch . TryGetJson ( "$.prompt_filter_results"u8 , out ReadOnlyMemory < byte > mem ) )
124+ {
125+ using JsonDocument doc = JsonDocument . Parse ( mem ) ;
126+ return RequestContentFilterResult . DeserializeRequestContentFilterResult ( doc . RootElement , ModelSerializationExtensions . WireOptions ) ;
127+ }
128+ return null ;
101129 }
102130
103131 [ Experimental ( "AOAI001" ) ]
104132 public static ResponseContentFilterResult GetResponseContentFilterResult ( this StreamingChatCompletionUpdate chatUpdate )
105133 {
106- return AdditionalPropertyHelpers . GetAdditionalPropertyAsResponseContentFilterResult (
107- chatUpdate ? . Choices ? . ElementAtOrDefault ( 0 ) ? . SerializedAdditionalRawData ,
108- "content_filter_results" ) ;
134+ if ( chatUpdate ? . Choices ? . ElementAtOrDefault ( 0 ) ? . Patch . TryGetJson ( "$.content_filter_results"u8 , out ReadOnlyMemory < byte > mem ) ?? false )
135+ {
136+ using JsonDocument doc = JsonDocument . Parse ( mem ) ;
137+ return ResponseContentFilterResult . DeserializeResponseContentFilterResult ( doc . RootElement , ModelSerializationExtensions . WireOptions ) ;
138+ }
139+ return null ;
109140 }
110141
111142 [ Experimental ( "AOAI001" ) ]
112143 public static void SetUserSecurityContext ( this ChatCompletionOptions options , UserSecurityContext userSecurityContext )
113144 {
114- options . SerializedAdditionalRawData ??= new Dictionary < string , BinaryData > ( ) ;
115-
116- AdditionalPropertyHelpers . SetAdditionalProperty (
117- options . SerializedAdditionalRawData ,
118- "user_security_context" ,
119- userSecurityContext ) ;
145+ BinaryData bin = ModelReaderWriter . Write ( userSecurityContext , ModelSerializationExtensions . WireOptions ) ;
146+ options . Patch . Set ( "$.user_security_context"u8 , bin ) ;
120147 }
121148
122149 [ Experimental ( "AOAI001" ) ]
123150 public static UserSecurityContext GetUserSecurityContext ( this ChatCompletionOptions options )
124151 {
125- return AdditionalPropertyHelpers . GetAdditionalPropertyAsUserSecurityContext (
126- options . SerializedAdditionalRawData ,
127- "user_security_context" ) ;
152+ if ( options . Patch . TryGetJson ( "$.user_security_context"u8 , out ReadOnlyMemory < byte > mem ) )
153+ {
154+ using JsonDocument doc = JsonDocument . Parse ( mem ) ;
155+ return UserSecurityContext . DeserializeUserSecurityContext ( doc . RootElement , ModelSerializationExtensions . WireOptions ) ;
156+ }
157+ return null ;
128158 }
129159
130160 [ Experimental ( "AOAI001" ) ]
131161 public static string GetMessageReasoningContent ( this ChatCompletion chatCompletion )
132162 {
133- if ( chatCompletion ? . Choices ? . FirstOrDefault ( ) ? . Message ? . SerializedAdditionalRawData ? . TryGetValue ( "reasoning_content" , out BinaryData reasoningContentData ) == true
134- && reasoningContentData ? . ToString ( ) is string retrievedReasoningContent )
163+ if ( chatCompletion ? . Choices ? . FirstOrDefault ( ) ? . Message ? . Patch . TryGetValue ( "$.reasoning_content"u8 , out string retrievedReasoningContent ) ?? false )
135164 {
136165 return retrievedReasoningContent ;
137166 }
138167 return null ;
139168 }
140- }
169+ }
0 commit comments