@@ -26,19 +26,19 @@ def register_models(register):
26
26
"o1" : {"reasoning" : True , "vision" : True },
27
27
"o1-pro" : {"reasoning" : True , "vision" : True , "streaming" : False },
28
28
# GPT-4.1 (all have vision: true, streaming: true)
29
- "gpt-4.1" : {"vision" : True },
30
- "gpt-4.1-2025-04-14" : {"vision" : True },
31
- "gpt-4.1-mini" : {"vision" : True },
32
- "gpt-4.1-mini-2025-04-14" : {"vision" : True },
29
+ "gpt-4.1" : {"vision" : True , "search" : True },
30
+ "gpt-4.1-2025-04-14" : {"vision" : True , "search" : True },
31
+ "gpt-4.1-mini" : {"vision" : True , "search" : True },
32
+ "gpt-4.1-mini-2025-04-14" : {"vision" : True , "search" : True },
33
33
"gpt-4.1-nano" : {"vision" : True },
34
34
"gpt-4.1-nano-2025-04-14" : {"vision" : True },
35
35
# April 16th 2025
36
36
"o3" : {"vision" : True , "reasoning" : True , "streaming" : False },
37
37
"o3-2025-04-16" : {"vision" : True , "reasoning" : True , "streaming" : False },
38
38
"o3-streaming" : {"vision" : True , "reasoning" : True },
39
39
"o3-2025-04-16-streaming" : {"vision" : True , "reasoning" : True },
40
- "o4-mini" : {"vision" : True , "reasoning" : True },
41
- "o4-mini-2025-04-16" : {"vision" : True , "reasoning" : True },
40
+ "o4-mini" : {"vision" : True , "reasoning" : True , "search" : True },
41
+ "o4-mini-2025-04-16" : {"vision" : True , "reasoning" : True , "search" : True },
42
42
}
43
43
for model_id , options in models .items ():
44
44
register (
@@ -64,6 +64,18 @@ class ReasoningEffortEnum(str, Enum):
64
64
high = "high"
65
65
66
66
67
+ class ReasoningSummaryEnum (str , Enum ):
68
+ auto = "auto"
69
+ concise = "concise"
70
+ detailed = "detailed"
71
+
72
+
73
+ class SearchContextSizeEnum (str , Enum ):
74
+ low = "low"
75
+ medium = "medium"
76
+ high = "high"
77
+
78
+
67
79
class BaseOptions (Options ):
68
80
max_output_tokens : Optional [int ] = Field (
69
81
description = (
@@ -131,14 +143,44 @@ class ReasoningOptions(Options):
131
143
),
132
144
default = None ,
133
145
)
146
+ reasoning_summary : Optional [ReasoningSummaryEnum ] = Field (
147
+ description = (
148
+ "A summary of the reasoning performed by the model. This can be useful for "
149
+ "debugging and understanding the model's reasoning process."
150
+ ),
151
+ default = None ,
152
+ )
153
+
154
+
155
+ class SearchOptions (Options ):
156
+ web_search_preview : Optional [bool ] = Field (
157
+ description = (
158
+ "Allow models to search the web for the latest information before generating "
159
+ "a response."
160
+ ),
161
+ default = None ,
162
+ )
163
+ search_context_size : Optional [SearchContextSizeEnum ] = Field (
164
+ description = (
165
+ "How much context is retrieved from the web to help the tool formulate "
166
+ 'a response. "low", "medium" or "high". Default is medium.'
167
+ ),
168
+ default = None ,
169
+ )
134
170
135
171
136
172
class _SharedResponses :
137
173
needs_key = "openai"
138
174
key_env_var = "OPENAI_API_KEY"
139
175
140
176
def __init__ (
141
- self , model_name , vision = False , streaming = True , schemas = True , reasoning = False
177
+ self ,
178
+ model_name ,
179
+ vision = False ,
180
+ streaming = True ,
181
+ schemas = True ,
182
+ reasoning = False ,
183
+ search = False ,
142
184
):
143
185
self .model_id = "openai/" + model_name
144
186
streaming_suffix = "-streaming"
@@ -149,6 +191,7 @@ def __init__(
149
191
self .supports_schema = schemas
150
192
options = [BaseOptions ]
151
193
self .vision = vision
194
+ self .search = search
152
195
if vision :
153
196
self .attachment_types = {
154
197
"image/png" ,
@@ -158,6 +201,9 @@ def __init__(
158
201
"application/pdf" ,
159
202
}
160
203
options .append (VisionOptions )
204
+ if search :
205
+ options .append (SearchOptions )
206
+ self .supports_reasoning = reasoning
161
207
if reasoning :
162
208
options .append (ReasoningOptions )
163
209
self .Options = combine_options (* options )
@@ -243,6 +289,24 @@ def _build_kwargs(self, prompt, conversation):
243
289
"schema" : additional_properties_false (prompt .schema ),
244
290
}
245
291
}
292
+ if self .supports_reasoning and (
293
+ prompt .options .reasoning_effort or prompt .options .reasoning_summary
294
+ ):
295
+ kwargs ["reasoning" ] = {}
296
+ if prompt .options .reasoning_effort :
297
+ kwargs ["reasoning" ]["effort" ] = prompt .options .reasoning_effort
298
+ if prompt .options .reasoning_summary :
299
+ kwargs ["reasoning" ]["summary" ] = prompt .options .reasoning_summary
300
+ tools = []
301
+ if self .search and prompt .options .web_search_preview :
302
+ search_tool = {
303
+ "type" : "web_search" ,
304
+ }
305
+ if prompt .options .search_context_size :
306
+ search_tool ["search_context_size" ] = prompt .options .search_context_size
307
+ tools .append (search_tool )
308
+ if tools :
309
+ kwargs ["tools" ] = tools
246
310
return kwargs
247
311
248
312
def _handle_event (self , event , response ):
0 commit comments