openai-sdk-helpers 0.0.8__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openai_sdk_helpers/__init__.py +90 -2
- openai_sdk_helpers/agent/__init__.py +8 -4
- openai_sdk_helpers/agent/base.py +80 -45
- openai_sdk_helpers/agent/config.py +6 -4
- openai_sdk_helpers/agent/{project_manager.py → coordination.py} +29 -45
- openai_sdk_helpers/agent/prompt_utils.py +7 -1
- openai_sdk_helpers/agent/runner.py +67 -141
- openai_sdk_helpers/agent/search/__init__.py +33 -0
- openai_sdk_helpers/agent/search/base.py +297 -0
- openai_sdk_helpers/agent/{vector_search.py → search/vector.py} +89 -157
- openai_sdk_helpers/agent/{web_search.py → search/web.py} +77 -156
- openai_sdk_helpers/agent/summarizer.py +29 -8
- openai_sdk_helpers/agent/translator.py +40 -13
- openai_sdk_helpers/agent/validation.py +32 -8
- openai_sdk_helpers/async_utils.py +132 -0
- openai_sdk_helpers/config.py +101 -65
- openai_sdk_helpers/context_manager.py +241 -0
- openai_sdk_helpers/enums/__init__.py +9 -1
- openai_sdk_helpers/enums/base.py +67 -8
- openai_sdk_helpers/environment.py +33 -6
- openai_sdk_helpers/errors.py +133 -0
- openai_sdk_helpers/logging_config.py +105 -0
- openai_sdk_helpers/prompt/__init__.py +10 -71
- openai_sdk_helpers/prompt/base.py +222 -0
- openai_sdk_helpers/response/__init__.py +38 -3
- openai_sdk_helpers/response/base.py +363 -210
- openai_sdk_helpers/response/config.py +318 -0
- openai_sdk_helpers/response/messages.py +56 -40
- openai_sdk_helpers/response/runner.py +77 -33
- openai_sdk_helpers/response/tool_call.py +62 -27
- openai_sdk_helpers/response/vector_store.py +27 -14
- openai_sdk_helpers/retry.py +175 -0
- openai_sdk_helpers/streamlit_app/__init__.py +19 -2
- openai_sdk_helpers/streamlit_app/app.py +114 -39
- openai_sdk_helpers/streamlit_app/config.py +502 -0
- openai_sdk_helpers/streamlit_app/streamlit_web_search.py +5 -6
- openai_sdk_helpers/structure/__init__.py +72 -3
- openai_sdk_helpers/structure/agent_blueprint.py +82 -19
- openai_sdk_helpers/structure/base.py +208 -93
- openai_sdk_helpers/structure/plan/__init__.py +29 -1
- openai_sdk_helpers/structure/plan/enum.py +41 -5
- openai_sdk_helpers/structure/plan/helpers.py +172 -0
- openai_sdk_helpers/structure/plan/plan.py +109 -49
- openai_sdk_helpers/structure/plan/task.py +38 -6
- openai_sdk_helpers/structure/plan/types.py +15 -0
- openai_sdk_helpers/structure/prompt.py +21 -2
- openai_sdk_helpers/structure/responses.py +52 -11
- openai_sdk_helpers/structure/summary.py +55 -7
- openai_sdk_helpers/structure/validation.py +34 -6
- openai_sdk_helpers/structure/vector_search.py +132 -18
- openai_sdk_helpers/structure/web_search.py +125 -13
- openai_sdk_helpers/tools.py +193 -0
- openai_sdk_helpers/types.py +57 -0
- openai_sdk_helpers/utils/__init__.py +34 -1
- openai_sdk_helpers/utils/core.py +296 -34
- openai_sdk_helpers/validation.py +302 -0
- openai_sdk_helpers/vector_storage/__init__.py +21 -1
- openai_sdk_helpers/vector_storage/cleanup.py +25 -13
- openai_sdk_helpers/vector_storage/storage.py +123 -64
- openai_sdk_helpers/vector_storage/types.py +20 -19
- openai_sdk_helpers-0.1.0.dist-info/METADATA +550 -0
- openai_sdk_helpers-0.1.0.dist-info/RECORD +69 -0
- openai_sdk_helpers/streamlit_app/configuration.py +0 -324
- openai_sdk_helpers-0.0.8.dist-info/METADATA +0 -194
- openai_sdk_helpers-0.0.8.dist-info/RECORD +0 -55
- {openai_sdk_helpers-0.0.8.dist-info → openai_sdk_helpers-0.1.0.dist-info}/WHEEL +0 -0
- {openai_sdk_helpers-0.0.8.dist-info → openai_sdk_helpers-0.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
"""Configuration management for Streamlit chat applications.
|
|
2
|
+
|
|
3
|
+
This module provides Pydantic-based configuration validation and loading for
|
|
4
|
+
Streamlit chat applications. It handles response instantiation, vector store
|
|
5
|
+
attachment, and validation of application settings.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import importlib.util
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from types import ModuleType
|
|
13
|
+
from typing import Callable, Sequence, cast
|
|
14
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
15
|
+
|
|
16
|
+
from openai_sdk_helpers.response.base import BaseResponse
|
|
17
|
+
from openai_sdk_helpers.structure.base import BaseStructure
|
|
18
|
+
from openai_sdk_helpers.utils import ensure_list
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class StreamlitAppConfig(BaseModel):
|
|
22
|
+
"""Validated configuration for Streamlit chat applications.
|
|
23
|
+
|
|
24
|
+
Manages all settings required to run a configuration-driven Streamlit
|
|
25
|
+
chat interface, including response handlers, vector stores, display
|
|
26
|
+
settings, and validation rules. Uses Pydantic for comprehensive
|
|
27
|
+
validation and type safety.
|
|
28
|
+
|
|
29
|
+
Attributes
|
|
30
|
+
----------
|
|
31
|
+
response : BaseResponse, type[BaseResponse], Callable, or None
|
|
32
|
+
Response handler as an instance, class, or callable factory.
|
|
33
|
+
display_title : str
|
|
34
|
+
Title displayed at the top of the Streamlit page.
|
|
35
|
+
description : str or None
|
|
36
|
+
Optional description shown beneath the title.
|
|
37
|
+
system_vector_store : list[str] or None
|
|
38
|
+
Optional vector store names to attach for file search.
|
|
39
|
+
preserve_vector_stores : bool
|
|
40
|
+
When True, skip automatic cleanup of vector stores on session close.
|
|
41
|
+
model : str or None
|
|
42
|
+
Optional model identifier displayed in the chat interface.
|
|
43
|
+
|
|
44
|
+
Methods
|
|
45
|
+
-------
|
|
46
|
+
normalized_vector_stores()
|
|
47
|
+
Return configured system vector stores as a list.
|
|
48
|
+
create_response()
|
|
49
|
+
Instantiate and return the configured BaseResponse.
|
|
50
|
+
load_app_config(config_path)
|
|
51
|
+
Load, validate, and return configuration from a Python module.
|
|
52
|
+
|
|
53
|
+
Examples
|
|
54
|
+
--------
|
|
55
|
+
>>> from openai_sdk_helpers.streamlit_app import StreamlitAppConfig
|
|
56
|
+
>>> config = StreamlitAppConfig(
|
|
57
|
+
... response=MyResponse,
|
|
58
|
+
... display_title="My Assistant",
|
|
59
|
+
... description="A helpful AI assistant"
|
|
60
|
+
... )
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
|
|
64
|
+
|
|
65
|
+
response: BaseResponse[BaseStructure] | type[BaseResponse] | Callable | None = (
|
|
66
|
+
Field(
|
|
67
|
+
default=None,
|
|
68
|
+
description=(
|
|
69
|
+
"Configured ``BaseResponse`` subclass, instance, or callable that returns"
|
|
70
|
+
" a response instance."
|
|
71
|
+
),
|
|
72
|
+
)
|
|
73
|
+
)
|
|
74
|
+
display_title: str = Field(
|
|
75
|
+
default="Example copilot",
|
|
76
|
+
description="Title displayed at the top of the Streamlit page.",
|
|
77
|
+
)
|
|
78
|
+
description: str | None = Field(
|
|
79
|
+
default=None,
|
|
80
|
+
description="Optional short description shown beneath the title.",
|
|
81
|
+
)
|
|
82
|
+
system_vector_store: list[str] | None = Field(
|
|
83
|
+
default=None,
|
|
84
|
+
description=(
|
|
85
|
+
"Optional vector store names to attach as system context for "
|
|
86
|
+
"file search tools."
|
|
87
|
+
),
|
|
88
|
+
)
|
|
89
|
+
preserve_vector_stores: bool = Field(
|
|
90
|
+
default=False,
|
|
91
|
+
description="When ``True``, skip automatic vector store cleanup on close.",
|
|
92
|
+
)
|
|
93
|
+
model: str | None = Field(
|
|
94
|
+
default=None,
|
|
95
|
+
description="Optional model hint for display alongside the chat interface.",
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
@field_validator("system_vector_store", mode="before")
|
|
99
|
+
@classmethod
|
|
100
|
+
def validate_vector_store(
|
|
101
|
+
cls, value: Sequence[str] | str | None
|
|
102
|
+
) -> list[str] | None:
|
|
103
|
+
"""Normalize configured vector stores to a list of strings.
|
|
104
|
+
|
|
105
|
+
Ensures that vector store configurations are always represented as
|
|
106
|
+
a list, whether provided as a single string or sequence.
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
value : Sequence[str], str, or None
|
|
111
|
+
Raw value from configuration (single name, list, or None).
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
list[str] or None
|
|
116
|
+
Normalized list of vector store names, or None if not configured.
|
|
117
|
+
|
|
118
|
+
Raises
|
|
119
|
+
------
|
|
120
|
+
ValueError
|
|
121
|
+
If any entry cannot be converted to a string.
|
|
122
|
+
"""
|
|
123
|
+
if value is None:
|
|
124
|
+
return None
|
|
125
|
+
stores = ensure_list(value)
|
|
126
|
+
if not all(isinstance(store, str) for store in stores):
|
|
127
|
+
raise ValueError("system_vector_store values must be strings.")
|
|
128
|
+
return list(stores)
|
|
129
|
+
|
|
130
|
+
@field_validator("response")
|
|
131
|
+
@classmethod
|
|
132
|
+
def validate_response(
|
|
133
|
+
cls, value: BaseResponse[BaseStructure] | type[BaseResponse] | Callable | None
|
|
134
|
+
) -> BaseResponse[BaseStructure] | type[BaseResponse] | Callable | None:
|
|
135
|
+
"""Validate that the response field is a valid handler source.
|
|
136
|
+
|
|
137
|
+
Ensures the provided response can be used to create a BaseResponse
|
|
138
|
+
instance for handling chat interactions.
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
value : BaseResponse, type[BaseResponse], Callable, or None
|
|
143
|
+
Response handler as instance, class, or factory function.
|
|
144
|
+
|
|
145
|
+
Returns
|
|
146
|
+
-------
|
|
147
|
+
BaseResponse, type[BaseResponse], Callable, or None
|
|
148
|
+
Validated response handler.
|
|
149
|
+
|
|
150
|
+
Raises
|
|
151
|
+
------
|
|
152
|
+
TypeError
|
|
153
|
+
If value is not a BaseResponse, subclass, or callable.
|
|
154
|
+
"""
|
|
155
|
+
if value is None:
|
|
156
|
+
return None
|
|
157
|
+
if isinstance(value, BaseResponse):
|
|
158
|
+
return value
|
|
159
|
+
if isinstance(value, type) and issubclass(value, BaseResponse):
|
|
160
|
+
return value
|
|
161
|
+
if callable(value):
|
|
162
|
+
return value
|
|
163
|
+
raise TypeError("response must be a BaseResponse, subclass, or callable")
|
|
164
|
+
|
|
165
|
+
def normalized_vector_stores(self) -> list[str]:
|
|
166
|
+
"""Return configured system vector stores as a list.
|
|
167
|
+
|
|
168
|
+
Provides a consistent interface for accessing vector store names,
|
|
169
|
+
returning an empty list when none are configured.
|
|
170
|
+
|
|
171
|
+
Returns
|
|
172
|
+
-------
|
|
173
|
+
list[str]
|
|
174
|
+
Vector store names, or empty list if not configured.
|
|
175
|
+
|
|
176
|
+
Examples
|
|
177
|
+
--------
|
|
178
|
+
>>> config.normalized_vector_stores()
|
|
179
|
+
['docs', 'knowledge_base']
|
|
180
|
+
"""
|
|
181
|
+
return list(self.system_vector_store or [])
|
|
182
|
+
|
|
183
|
+
@model_validator(mode="after")
|
|
184
|
+
def ensure_response(self) -> StreamlitAppConfig:
|
|
185
|
+
"""Validate that a response source is provided.
|
|
186
|
+
|
|
187
|
+
Ensures the configuration includes a valid response handler, which
|
|
188
|
+
is required for the chat application to function.
|
|
189
|
+
|
|
190
|
+
Returns
|
|
191
|
+
-------
|
|
192
|
+
StreamlitAppConfig
|
|
193
|
+
Self reference after validation.
|
|
194
|
+
|
|
195
|
+
Raises
|
|
196
|
+
------
|
|
197
|
+
ValueError
|
|
198
|
+
If no response source is configured.
|
|
199
|
+
"""
|
|
200
|
+
if self.response is None:
|
|
201
|
+
raise ValueError("response must be provided.")
|
|
202
|
+
return self
|
|
203
|
+
|
|
204
|
+
def create_response(self) -> BaseResponse[BaseStructure]:
|
|
205
|
+
"""Instantiate and return the configured response handler.
|
|
206
|
+
|
|
207
|
+
Converts the response field (whether class, instance, or callable)
|
|
208
|
+
into an active BaseResponse instance ready for chat interactions.
|
|
209
|
+
|
|
210
|
+
Returns
|
|
211
|
+
-------
|
|
212
|
+
BaseResponse[BaseStructure]
|
|
213
|
+
Active response instance for handling chat messages.
|
|
214
|
+
|
|
215
|
+
Raises
|
|
216
|
+
------
|
|
217
|
+
TypeError
|
|
218
|
+
If the configured response cannot produce a BaseResponse.
|
|
219
|
+
|
|
220
|
+
Examples
|
|
221
|
+
--------
|
|
222
|
+
>>> response = config.create_response()
|
|
223
|
+
>>> result = response.run_sync("Hello")
|
|
224
|
+
"""
|
|
225
|
+
return _instantiate_response(self.response)
|
|
226
|
+
|
|
227
|
+
@staticmethod
|
|
228
|
+
def load_app_config(
|
|
229
|
+
config_path: Path,
|
|
230
|
+
) -> StreamlitAppConfig:
|
|
231
|
+
"""Load, validate, and return configuration from a Python module.
|
|
232
|
+
|
|
233
|
+
Imports the specified Python module and extracts its APP_CONFIG
|
|
234
|
+
variable to create a validated StreamlitAppConfig instance.
|
|
235
|
+
|
|
236
|
+
Parameters
|
|
237
|
+
----------
|
|
238
|
+
config_path : Path
|
|
239
|
+
Filesystem path to the Python configuration module.
|
|
240
|
+
|
|
241
|
+
Returns
|
|
242
|
+
-------
|
|
243
|
+
StreamlitAppConfig
|
|
244
|
+
Validated configuration extracted from the module.
|
|
245
|
+
|
|
246
|
+
Raises
|
|
247
|
+
------
|
|
248
|
+
FileNotFoundError
|
|
249
|
+
If config_path does not exist.
|
|
250
|
+
ImportError
|
|
251
|
+
If the module cannot be imported.
|
|
252
|
+
ValueError
|
|
253
|
+
If APP_CONFIG is missing from the module.
|
|
254
|
+
TypeError
|
|
255
|
+
If APP_CONFIG has an invalid type.
|
|
256
|
+
|
|
257
|
+
Examples
|
|
258
|
+
--------
|
|
259
|
+
>>> from pathlib import Path
|
|
260
|
+
>>> config = StreamlitAppConfig.load_app_config(
|
|
261
|
+
... Path("./my_config.py")
|
|
262
|
+
... )
|
|
263
|
+
"""
|
|
264
|
+
module = _import_config_module(config_path)
|
|
265
|
+
return _extract_config(module)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def _import_config_module(config_path: Path) -> ModuleType:
|
|
269
|
+
"""Import a Python module from the specified filesystem path.
|
|
270
|
+
|
|
271
|
+
Uses importlib to dynamically load a configuration module, enabling
|
|
272
|
+
runtime configuration discovery.
|
|
273
|
+
|
|
274
|
+
Parameters
|
|
275
|
+
----------
|
|
276
|
+
config_path : Path
|
|
277
|
+
Filesystem path pointing to the configuration Python file.
|
|
278
|
+
|
|
279
|
+
Returns
|
|
280
|
+
-------
|
|
281
|
+
ModuleType
|
|
282
|
+
Loaded Python module containing application configuration.
|
|
283
|
+
|
|
284
|
+
Raises
|
|
285
|
+
------
|
|
286
|
+
FileNotFoundError
|
|
287
|
+
If config_path does not exist on the filesystem.
|
|
288
|
+
ImportError
|
|
289
|
+
If the module cannot be imported or executed.
|
|
290
|
+
|
|
291
|
+
Examples
|
|
292
|
+
--------
|
|
293
|
+
>>> module = _import_config_module(Path("./config.py"))
|
|
294
|
+
>>> hasattr(module, 'APP_CONFIG')
|
|
295
|
+
True
|
|
296
|
+
"""
|
|
297
|
+
if not config_path.exists():
|
|
298
|
+
raise FileNotFoundError(f"Configuration file not found at '{config_path}'.")
|
|
299
|
+
|
|
300
|
+
spec = importlib.util.spec_from_file_location(config_path.stem, config_path)
|
|
301
|
+
if spec is None or spec.loader is None:
|
|
302
|
+
raise ImportError(f"Unable to load configuration module at '{config_path}'.")
|
|
303
|
+
|
|
304
|
+
module = importlib.util.module_from_spec(spec)
|
|
305
|
+
spec.loader.exec_module(module)
|
|
306
|
+
return module
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def _extract_config(module: ModuleType) -> StreamlitAppConfig:
|
|
310
|
+
"""Extract and validate StreamlitAppConfig from a loaded module.
|
|
311
|
+
|
|
312
|
+
Looks for APP_CONFIG in the module and converts it to a validated
|
|
313
|
+
StreamlitAppConfig instance. Supports multiple input formats including
|
|
314
|
+
dictionaries, BaseResponse instances, and existing config objects.
|
|
315
|
+
|
|
316
|
+
Parameters
|
|
317
|
+
----------
|
|
318
|
+
module : ModuleType
|
|
319
|
+
Python module loaded from the configuration path.
|
|
320
|
+
|
|
321
|
+
Returns
|
|
322
|
+
-------
|
|
323
|
+
StreamlitAppConfig
|
|
324
|
+
Parsed and validated configuration instance.
|
|
325
|
+
|
|
326
|
+
Raises
|
|
327
|
+
------
|
|
328
|
+
ValueError
|
|
329
|
+
If APP_CONFIG is missing from the module.
|
|
330
|
+
TypeError
|
|
331
|
+
If APP_CONFIG is not a valid type (dict, BaseResponse, callable,
|
|
332
|
+
or StreamlitAppConfig).
|
|
333
|
+
|
|
334
|
+
Examples
|
|
335
|
+
--------
|
|
336
|
+
>>> config = _extract_config(module)
|
|
337
|
+
>>> isinstance(config, StreamlitAppConfig)
|
|
338
|
+
True
|
|
339
|
+
"""
|
|
340
|
+
if not hasattr(module, "APP_CONFIG"):
|
|
341
|
+
raise ValueError("APP_CONFIG must be defined in the configuration module.")
|
|
342
|
+
|
|
343
|
+
raw_config = getattr(module, "APP_CONFIG")
|
|
344
|
+
if isinstance(raw_config, StreamlitAppConfig):
|
|
345
|
+
return raw_config
|
|
346
|
+
if isinstance(raw_config, dict):
|
|
347
|
+
return _config_from_mapping(raw_config)
|
|
348
|
+
if isinstance(raw_config, BaseResponse):
|
|
349
|
+
return StreamlitAppConfig(response=raw_config)
|
|
350
|
+
if isinstance(raw_config, type) and issubclass(raw_config, BaseResponse):
|
|
351
|
+
return StreamlitAppConfig(response=raw_config)
|
|
352
|
+
if callable(raw_config):
|
|
353
|
+
return StreamlitAppConfig(response=raw_config)
|
|
354
|
+
|
|
355
|
+
raise TypeError(
|
|
356
|
+
"APP_CONFIG must be a dict, callable, BaseResponse, or StreamlitAppConfig."
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
def _instantiate_response(candidate: object) -> BaseResponse[BaseStructure]:
|
|
361
|
+
"""Convert a response candidate into a BaseResponse instance.
|
|
362
|
+
|
|
363
|
+
Handles multiple candidate types: existing instances (returned as-is),
|
|
364
|
+
classes (instantiated with no arguments), and callables (invoked to
|
|
365
|
+
produce an instance).
|
|
366
|
+
|
|
367
|
+
Parameters
|
|
368
|
+
----------
|
|
369
|
+
candidate : object
|
|
370
|
+
Response source as instance, class, or callable factory.
|
|
371
|
+
|
|
372
|
+
Returns
|
|
373
|
+
-------
|
|
374
|
+
BaseResponse[BaseStructure]
|
|
375
|
+
Active response instance ready for use.
|
|
376
|
+
|
|
377
|
+
Raises
|
|
378
|
+
------
|
|
379
|
+
TypeError
|
|
380
|
+
If candidate cannot produce a BaseResponse instance.
|
|
381
|
+
|
|
382
|
+
Examples
|
|
383
|
+
--------
|
|
384
|
+
>>> response = _instantiate_response(MyResponse)
|
|
385
|
+
>>> isinstance(response, BaseResponse)
|
|
386
|
+
True
|
|
387
|
+
"""
|
|
388
|
+
if isinstance(candidate, BaseResponse):
|
|
389
|
+
return candidate
|
|
390
|
+
if isinstance(candidate, type) and issubclass(candidate, BaseResponse):
|
|
391
|
+
response_cls = cast(type[BaseResponse[BaseStructure]], candidate)
|
|
392
|
+
return response_cls() # type: ignore[call-arg]
|
|
393
|
+
if callable(candidate):
|
|
394
|
+
response_callable = cast(Callable[[], BaseResponse[BaseStructure]], candidate)
|
|
395
|
+
response = response_callable()
|
|
396
|
+
if isinstance(response, BaseResponse):
|
|
397
|
+
return response
|
|
398
|
+
raise TypeError("response must be a BaseResponse, subclass, or callable")
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def _config_from_mapping(raw_config: dict) -> StreamlitAppConfig:
|
|
402
|
+
"""Build StreamlitAppConfig from a dictionary with field aliases.
|
|
403
|
+
|
|
404
|
+
Supports both 'response' and 'build_response' keys for backward
|
|
405
|
+
compatibility. Extracts configuration fields and constructs a
|
|
406
|
+
validated StreamlitAppConfig instance.
|
|
407
|
+
|
|
408
|
+
Parameters
|
|
409
|
+
----------
|
|
410
|
+
raw_config : dict
|
|
411
|
+
Developer-supplied dictionary from the configuration module.
|
|
412
|
+
|
|
413
|
+
Returns
|
|
414
|
+
-------
|
|
415
|
+
StreamlitAppConfig
|
|
416
|
+
Validated configuration constructed from the dictionary.
|
|
417
|
+
|
|
418
|
+
Examples
|
|
419
|
+
--------
|
|
420
|
+
>>> config = _config_from_mapping({
|
|
421
|
+
... 'response': MyResponse,
|
|
422
|
+
... 'display_title': 'My App'
|
|
423
|
+
... })
|
|
424
|
+
"""
|
|
425
|
+
config_kwargs = dict(raw_config)
|
|
426
|
+
response_candidate = config_kwargs.pop("response", None)
|
|
427
|
+
if response_candidate is None:
|
|
428
|
+
response_candidate = config_kwargs.pop("build_response", None)
|
|
429
|
+
if response_candidate is not None:
|
|
430
|
+
config_kwargs["response"] = response_candidate
|
|
431
|
+
|
|
432
|
+
return StreamlitAppConfig(**config_kwargs)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def load_app_config(
|
|
436
|
+
config_path: Path,
|
|
437
|
+
) -> StreamlitAppConfig:
|
|
438
|
+
"""Load and validate Streamlit configuration from a Python module.
|
|
439
|
+
|
|
440
|
+
Convenience function that proxies to StreamlitAppConfig.load_app_config
|
|
441
|
+
for backward compatibility.
|
|
442
|
+
|
|
443
|
+
Parameters
|
|
444
|
+
----------
|
|
445
|
+
config_path : Path
|
|
446
|
+
Filesystem path to the configuration module.
|
|
447
|
+
|
|
448
|
+
Returns
|
|
449
|
+
-------
|
|
450
|
+
StreamlitAppConfig
|
|
451
|
+
Validated configuration loaded from the module.
|
|
452
|
+
|
|
453
|
+
Examples
|
|
454
|
+
--------
|
|
455
|
+
>>> from pathlib import Path
|
|
456
|
+
>>> config = load_app_config(Path("./my_config.py"))
|
|
457
|
+
"""
|
|
458
|
+
return StreamlitAppConfig.load_app_config(config_path=config_path)
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def _load_configuration(config_path: Path) -> StreamlitAppConfig:
|
|
462
|
+
"""Load configuration with user-friendly error handling for Streamlit.
|
|
463
|
+
|
|
464
|
+
Wraps StreamlitAppConfig.load_app_config with exception handling that
|
|
465
|
+
displays errors in the Streamlit UI and halts execution gracefully.
|
|
466
|
+
|
|
467
|
+
Parameters
|
|
468
|
+
----------
|
|
469
|
+
config_path : Path
|
|
470
|
+
Filesystem location of the configuration module.
|
|
471
|
+
|
|
472
|
+
Returns
|
|
473
|
+
-------
|
|
474
|
+
StreamlitAppConfig
|
|
475
|
+
Validated configuration object.
|
|
476
|
+
|
|
477
|
+
Raises
|
|
478
|
+
------
|
|
479
|
+
RuntimeError
|
|
480
|
+
If configuration loading fails (after displaying error in UI).
|
|
481
|
+
|
|
482
|
+
Notes
|
|
483
|
+
-----
|
|
484
|
+
This function is designed specifically for use within Streamlit
|
|
485
|
+
applications where errors should be displayed in the UI rather
|
|
486
|
+
than raising exceptions that crash the app.
|
|
487
|
+
"""
|
|
488
|
+
try:
|
|
489
|
+
return StreamlitAppConfig.load_app_config(config_path=config_path)
|
|
490
|
+
except Exception as exc: # pragma: no cover - surfaced in UI
|
|
491
|
+
import streamlit as st # type: ignore[import-not-found]
|
|
492
|
+
|
|
493
|
+
st.error(f"Configuration error: {exc}")
|
|
494
|
+
st.stop()
|
|
495
|
+
raise RuntimeError("Configuration loading halted.") from exc
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
__all__ = [
|
|
499
|
+
"StreamlitAppConfig",
|
|
500
|
+
"load_app_config",
|
|
501
|
+
"_load_configuration",
|
|
502
|
+
]
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"""Developer configuration for the example Streamlit chat app."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
from openai_sdk_helpers.agent.
|
|
4
|
+
from openai_sdk_helpers.agent.search.web import WebAgentSearch
|
|
5
5
|
from openai_sdk_helpers.config import OpenAISettings
|
|
6
6
|
from openai_sdk_helpers.response.base import BaseResponse
|
|
7
7
|
from openai_sdk_helpers.structure.web_search import WebSearchStructure
|
|
8
8
|
from openai_sdk_helpers.structure.prompt import PromptStructure
|
|
9
9
|
from openai_sdk_helpers.utils.core import customJSONEncoder
|
|
10
|
-
|
|
11
|
-
DEFAULT_MODEL = "gpt-4o-mini"
|
|
10
|
+
from openai_sdk_helpers.environment import DEFAULT_MODEL
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
class StreamlitWebSearch(BaseResponse[WebSearchStructure]):
|
|
@@ -22,6 +21,8 @@ class StreamlitWebSearch(BaseResponse[WebSearchStructure]):
|
|
|
22
21
|
|
|
23
22
|
def __init__(self) -> None:
|
|
24
23
|
settings = OpenAISettings.from_env()
|
|
24
|
+
if not settings.default_model:
|
|
25
|
+
settings = settings.model_copy(update={"default_model": DEFAULT_MODEL})
|
|
25
26
|
super().__init__(
|
|
26
27
|
instructions="Perform web searches and generate reports.",
|
|
27
28
|
tools=[
|
|
@@ -30,11 +31,9 @@ class StreamlitWebSearch(BaseResponse[WebSearchStructure]):
|
|
|
30
31
|
tool_description="Tool to perform web searches and generate reports.",
|
|
31
32
|
)
|
|
32
33
|
],
|
|
33
|
-
schema=WebSearchStructure.response_format(),
|
|
34
34
|
output_structure=WebSearchStructure,
|
|
35
35
|
tool_handlers={"perform_search": perform_search},
|
|
36
|
-
|
|
37
|
-
model=settings.default_model or DEFAULT_MODEL,
|
|
36
|
+
openai_settings=settings,
|
|
38
37
|
)
|
|
39
38
|
|
|
40
39
|
|
|
@@ -1,15 +1,81 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Structured output models for OpenAI API interactions.
|
|
2
|
+
|
|
3
|
+
This module provides Pydantic-based structured output models for defining
|
|
4
|
+
schemas, validation, and serialization of AI agent outputs. It includes base
|
|
5
|
+
classes, specialized structures for various agent types, and utilities for
|
|
6
|
+
generating OpenAI-compatible schema definitions.
|
|
7
|
+
|
|
8
|
+
Classes
|
|
9
|
+
-------
|
|
10
|
+
BaseStructure
|
|
11
|
+
Base class for all structured output models with schema generation.
|
|
12
|
+
SchemaOptions
|
|
13
|
+
Configuration options for schema generation behavior.
|
|
14
|
+
AgentBlueprint
|
|
15
|
+
Structure for designing and planning new agents.
|
|
16
|
+
AgentEnum
|
|
17
|
+
Enumeration of available agent types.
|
|
18
|
+
TaskStructure
|
|
19
|
+
Representation of a single task in an execution plan.
|
|
20
|
+
PlanStructure
|
|
21
|
+
Ordered sequence of tasks for multi-step agent workflows.
|
|
22
|
+
PromptStructure
|
|
23
|
+
Structure for prompt design and validation.
|
|
24
|
+
SummaryTopic
|
|
25
|
+
Individual topic within a summary.
|
|
26
|
+
SummaryStructure
|
|
27
|
+
Basic summary with topic breakdown.
|
|
28
|
+
ExtendedSummaryStructure
|
|
29
|
+
Enhanced summary with additional metadata.
|
|
30
|
+
WebSearchStructure
|
|
31
|
+
Web search results structure.
|
|
32
|
+
WebSearchPlanStructure
|
|
33
|
+
Planned web search queries and strategy.
|
|
34
|
+
WebSearchItemStructure
|
|
35
|
+
Individual web search item.
|
|
36
|
+
WebSearchItemResultStructure
|
|
37
|
+
Result from executing a web search item.
|
|
38
|
+
WebSearchReportStructure
|
|
39
|
+
Complete web search report with findings.
|
|
40
|
+
VectorSearchStructure
|
|
41
|
+
Vector database search results.
|
|
42
|
+
VectorSearchPlanStructure
|
|
43
|
+
Planned vector search queries.
|
|
44
|
+
VectorSearchItemStructure
|
|
45
|
+
Individual vector search query.
|
|
46
|
+
VectorSearchItemResultStructure
|
|
47
|
+
Result from executing a vector search query.
|
|
48
|
+
VectorSearchItemResultsStructure
|
|
49
|
+
Collection of vector search results.
|
|
50
|
+
VectorSearchReportStructure
|
|
51
|
+
Complete vector search report.
|
|
52
|
+
ValidationResultStructure
|
|
53
|
+
Validation results with pass/fail status.
|
|
54
|
+
|
|
55
|
+
Functions
|
|
56
|
+
---------
|
|
57
|
+
spec_field
|
|
58
|
+
Create a Pydantic Field with standard documentation formatting.
|
|
59
|
+
assistant_tool_definition
|
|
60
|
+
Build function tool definition for Assistant APIs.
|
|
61
|
+
assistant_format
|
|
62
|
+
Build response format for Assistant APIs.
|
|
63
|
+
response_tool_definition
|
|
64
|
+
Build function tool definition for chat completions.
|
|
65
|
+
response_format
|
|
66
|
+
Build response format for chat completions.
|
|
67
|
+
"""
|
|
2
68
|
|
|
3
69
|
from __future__ import annotations
|
|
4
70
|
|
|
5
71
|
from .agent_blueprint import AgentBlueprint
|
|
6
|
-
from .plan import *
|
|
7
72
|
from .base import *
|
|
73
|
+
from .plan import *
|
|
8
74
|
from .prompt import PromptStructure
|
|
9
75
|
from .responses import *
|
|
10
76
|
from .summary import *
|
|
11
|
-
from .vector_search import *
|
|
12
77
|
from .validation import ValidationResultStructure
|
|
78
|
+
from .vector_search import *
|
|
13
79
|
from .web_search import *
|
|
14
80
|
|
|
15
81
|
__all__ = [
|
|
@@ -20,6 +86,9 @@ __all__ = [
|
|
|
20
86
|
"AgentEnum",
|
|
21
87
|
"TaskStructure",
|
|
22
88
|
"PlanStructure",
|
|
89
|
+
"create_plan",
|
|
90
|
+
"execute_task",
|
|
91
|
+
"execute_plan",
|
|
23
92
|
"PromptStructure",
|
|
24
93
|
"SummaryTopic",
|
|
25
94
|
"SummaryStructure",
|