@@ -13,9 +13,6 @@ namespace Devlooped.Extensions.AI.OpenAI;
1313[ EditorBrowsable ( EditorBrowsableState . Never ) ]
1414public static class OpenAIExtensions
1515{
16- // Key used to mark that our factory has been installed
17- const string FactoryInstalledKey = "__OpenAIResponsesFactory" ;
18-
1916 /// <summary>
2017 /// Gets or sets the effort level for a reasoning AI model when generating responses.
2118 /// </summary>
@@ -38,7 +35,7 @@ public ReasoningEffort? ReasoningEffort
3835 {
3936 options . AdditionalProperties ??= [ ] ;
4037 options . AdditionalProperties [ "reasoning_effort" ] = value ;
41- EnsureFactoryInstalled ( options ) ;
38+ EnsureFactory ( options ) ;
4239 }
4340 else
4441 {
@@ -67,7 +64,7 @@ public Verbosity? Verbosity
6764 {
6865 options . AdditionalProperties ??= [ ] ;
6966 options . AdditionalProperties [ "verbosity" ] = value ;
70- EnsureFactoryInstalled ( options ) ;
67+ EnsureFactory ( options ) ;
7168 }
7269 else
7370 {
@@ -77,93 +74,17 @@ public Verbosity? Verbosity
7774 }
7875 }
7976
80- static void EnsureFactoryInstalled ( ChatOptions options )
77+ static void EnsureFactory ( ChatOptions options )
8178 {
82- options . AdditionalProperties ??= [ ] ;
83-
84- // Check if our factory is already installed
85- if ( options . AdditionalProperties . TryGetValue ( FactoryInstalledKey , out var _ ) )
86- return ;
87-
88- // Check if a different factory has been set
89- if ( options . RawRepresentationFactory is not null )
79+ if ( options . RawRepresentationFactory is not null &&
80+ options . RawRepresentationFactory . Target is not ResponseOptionsFactory )
9081 {
9182 throw new InvalidOperationException (
9283 "Cannot use OpenAI Responses API extension properties (ReasoningEffort, Verbosity) when " +
9384 "RawRepresentationFactory has already been set to a custom factory. These extension " +
9485 "properties automatically configure the factory for the OpenAI Responses API." ) ;
9586 }
9687
97- // Install our factory
98- options . RawRepresentationFactory = _ => CreateResponseCreationOptions ( options ) ;
99- options . AdditionalProperties [ FactoryInstalledKey ] = true ;
100- }
101-
102- static ResponseCreationOptions CreateResponseCreationOptions ( ChatOptions options )
103- {
104- var creation = new ResponseCreationOptions ( ) ;
105-
106- if ( options . ReasoningEffort is { } effort )
107- creation . ReasoningOptions = new ReasoningEffortOptions ( effort ) ;
108-
109- if ( options . Verbosity is { } verbosity )
110- creation . TextOptions = new VerbosityOptions ( verbosity ) ;
111-
112- return creation ;
113- }
114-
115- class ReasoningEffortOptions ( ReasoningEffort effort ) : ResponseReasoningOptions
116- {
117- protected override void JsonModelWriteCore ( Utf8JsonWriter writer , ModelReaderWriterOptions options )
118- {
119- writer . WritePropertyName ( "effort"u8 ) ;
120- writer . WriteStringValue ( effort . ToString ( ) . ToLowerInvariant ( ) ) ;
121- base . JsonModelWriteCore ( writer , options ) ;
122- }
123- }
124-
125- class VerbosityOptions ( Verbosity verbosity ) : ResponseTextOptions
126- {
127- protected override void JsonModelWriteCore ( Utf8JsonWriter writer , ModelReaderWriterOptions options )
128- {
129- writer . WritePropertyName ( "verbosity"u8 ) ;
130- writer . WriteStringValue ( verbosity . ToString ( ) . ToLowerInvariant ( ) ) ;
131- base . JsonModelWriteCore ( writer , options ) ;
132- }
133- }
134- }
135-
136- /// <summary>
137- /// Extended <see cref="ChatOptions"/> that includes OpenAI Responses API specific properties.
138- /// </summary>
139- /// <remarks>
140- /// This class is provided for configuration binding scenarios. The <see cref="ReasoningEffort"/>
141- /// and <see cref="Verbosity"/> properties are specific to the OpenAI Responses API.
142- /// </remarks>
143- [ EditorBrowsable ( EditorBrowsableState . Never ) ]
144- public class OpenAIChatOptions : ChatOptions
145- {
146- /// <summary>
147- /// Gets or sets the effort level for a reasoning AI model when generating responses.
148- /// </summary>
149- /// <remarks>
150- /// This property is specific to the OpenAI Responses API.
151- /// </remarks>
152- public ReasoningEffort ? ReasoningEffort
153- {
154- get => ( ( ChatOptions ) this ) . ReasoningEffort ;
155- set => ( ( ChatOptions ) this ) . ReasoningEffort = value ;
156- }
157-
158- /// <summary>
159- /// Gets or sets the verbosity level for a GPT-5+ model when generating responses.
160- /// </summary>
161- /// <remarks>
162- /// This property is specific to the OpenAI Responses API and only supported by GPT-5+ models.
163- /// </remarks>
164- public Verbosity ? Verbosity
165- {
166- get => ( ( ChatOptions ) this ) . Verbosity ;
167- set => ( ( ChatOptions ) this ) . Verbosity = value ;
88+ options . RawRepresentationFactory ??= new ResponseOptionsFactory ( options ) . CreateResponseCreationOptions ;
16889 }
169- }
90+ }
0 commit comments