openai-sdk-helpers 0.1.0__py3-none-any.whl → 0.1.2__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 +44 -7
- openai_sdk_helpers/agent/base.py +5 -1
- openai_sdk_helpers/agent/coordination.py +4 -5
- openai_sdk_helpers/agent/runner.py +4 -1
- openai_sdk_helpers/agent/search/base.py +1 -0
- openai_sdk_helpers/agent/search/vector.py +2 -0
- openai_sdk_helpers/cli.py +265 -0
- openai_sdk_helpers/config.py +93 -2
- openai_sdk_helpers/context_manager.py +1 -1
- openai_sdk_helpers/deprecation.py +167 -0
- openai_sdk_helpers/environment.py +3 -2
- openai_sdk_helpers/errors.py +0 -12
- openai_sdk_helpers/files_api.py +373 -0
- openai_sdk_helpers/logging_config.py +24 -95
- openai_sdk_helpers/prompt/base.py +1 -1
- openai_sdk_helpers/response/__init__.py +7 -3
- openai_sdk_helpers/response/base.py +217 -147
- openai_sdk_helpers/response/config.py +16 -1
- openai_sdk_helpers/response/files.py +392 -0
- openai_sdk_helpers/response/messages.py +1 -0
- openai_sdk_helpers/retry.py +1 -1
- openai_sdk_helpers/streamlit_app/app.py +97 -7
- openai_sdk_helpers/streamlit_app/streamlit_web_search.py +15 -8
- openai_sdk_helpers/structure/base.py +6 -6
- openai_sdk_helpers/structure/plan/helpers.py +1 -0
- openai_sdk_helpers/structure/plan/task.py +7 -7
- openai_sdk_helpers/tools.py +116 -13
- openai_sdk_helpers/utils/__init__.py +100 -35
- openai_sdk_helpers/{async_utils.py → utils/async_utils.py} +5 -6
- openai_sdk_helpers/utils/coercion.py +138 -0
- openai_sdk_helpers/utils/deprecation.py +167 -0
- openai_sdk_helpers/utils/encoding.py +189 -0
- openai_sdk_helpers/utils/json_utils.py +98 -0
- openai_sdk_helpers/utils/output_validation.py +448 -0
- openai_sdk_helpers/utils/path_utils.py +46 -0
- openai_sdk_helpers/{validation.py → utils/validation.py} +7 -3
- openai_sdk_helpers/vector_storage/storage.py +59 -28
- {openai_sdk_helpers-0.1.0.dist-info → openai_sdk_helpers-0.1.2.dist-info}/METADATA +152 -3
- openai_sdk_helpers-0.1.2.dist-info/RECORD +79 -0
- openai_sdk_helpers-0.1.2.dist-info/entry_points.txt +2 -0
- openai_sdk_helpers/utils/core.py +0 -596
- openai_sdk_helpers-0.1.0.dist-info/RECORD +0 -69
- {openai_sdk_helpers-0.1.0.dist-info → openai_sdk_helpers-0.1.2.dist-info}/WHEEL +0 -0
- {openai_sdk_helpers-0.1.0.dist-info → openai_sdk_helpers-0.1.2.dist-info}/licenses/LICENSE +0 -0
openai_sdk_helpers/utils/core.py
DELETED
|
@@ -1,596 +0,0 @@
|
|
|
1
|
-
"""Core utility helpers for openai-sdk-helpers.
|
|
2
|
-
|
|
3
|
-
This module provides foundational utility functions for type coercion,
|
|
4
|
-
file path validation, JSON serialization, and logging. These utilities
|
|
5
|
-
support consistent data handling across the package.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
import json
|
|
11
|
-
import logging
|
|
12
|
-
import ast
|
|
13
|
-
from collections.abc import Iterable, Mapping
|
|
14
|
-
from dataclasses import asdict, is_dataclass
|
|
15
|
-
from datetime import datetime
|
|
16
|
-
from enum import Enum
|
|
17
|
-
from pathlib import Path
|
|
18
|
-
from typing import Any, TypeVar
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def coerce_optional_float(value: object) -> float | None:
|
|
22
|
-
"""Return a float when the provided value can be coerced, otherwise None.
|
|
23
|
-
|
|
24
|
-
Handles float, int, and string inputs. Empty strings or None return None.
|
|
25
|
-
|
|
26
|
-
Parameters
|
|
27
|
-
----------
|
|
28
|
-
value : object
|
|
29
|
-
Value to convert into a float. Strings must be parseable as floats.
|
|
30
|
-
|
|
31
|
-
Returns
|
|
32
|
-
-------
|
|
33
|
-
float or None
|
|
34
|
-
Converted float value or None if the input is None.
|
|
35
|
-
|
|
36
|
-
Raises
|
|
37
|
-
------
|
|
38
|
-
ValueError
|
|
39
|
-
If a non-empty string cannot be converted to a float.
|
|
40
|
-
TypeError
|
|
41
|
-
If the value is not a float-compatible type.
|
|
42
|
-
|
|
43
|
-
Examples
|
|
44
|
-
--------
|
|
45
|
-
>>> coerce_optional_float(3.14)
|
|
46
|
-
3.14
|
|
47
|
-
>>> coerce_optional_float("2.5")
|
|
48
|
-
2.5
|
|
49
|
-
>>> coerce_optional_float(None) is None
|
|
50
|
-
True
|
|
51
|
-
"""
|
|
52
|
-
if value is None:
|
|
53
|
-
return None
|
|
54
|
-
if isinstance(value, (float, int)):
|
|
55
|
-
return float(value)
|
|
56
|
-
if isinstance(value, str) and value.strip():
|
|
57
|
-
try:
|
|
58
|
-
return float(value)
|
|
59
|
-
except ValueError as exc:
|
|
60
|
-
raise ValueError("timeout must be a float-compatible value") from exc
|
|
61
|
-
raise TypeError("timeout must be a float, int, str, or None")
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def coerce_optional_int(value: object) -> int | None:
|
|
65
|
-
"""Return an int when the provided value can be coerced, otherwise None.
|
|
66
|
-
|
|
67
|
-
Handles int, float (if whole number), and string inputs. Empty strings
|
|
68
|
-
or None return None. Booleans are not considered valid integers.
|
|
69
|
-
|
|
70
|
-
Parameters
|
|
71
|
-
----------
|
|
72
|
-
value : object
|
|
73
|
-
Value to convert into an int. Strings must be parseable as integers.
|
|
74
|
-
|
|
75
|
-
Returns
|
|
76
|
-
-------
|
|
77
|
-
int or None
|
|
78
|
-
Converted integer value or None if the input is None.
|
|
79
|
-
|
|
80
|
-
Raises
|
|
81
|
-
------
|
|
82
|
-
ValueError
|
|
83
|
-
If a non-empty string cannot be converted to an integer.
|
|
84
|
-
TypeError
|
|
85
|
-
If the value is not an int-compatible type.
|
|
86
|
-
|
|
87
|
-
Examples
|
|
88
|
-
--------
|
|
89
|
-
>>> coerce_optional_int(42)
|
|
90
|
-
42
|
|
91
|
-
>>> coerce_optional_int("100")
|
|
92
|
-
100
|
|
93
|
-
>>> coerce_optional_int(3.0)
|
|
94
|
-
3
|
|
95
|
-
>>> coerce_optional_int(None) is None
|
|
96
|
-
True
|
|
97
|
-
"""
|
|
98
|
-
if value is None:
|
|
99
|
-
return None
|
|
100
|
-
if isinstance(value, int) and not isinstance(value, bool):
|
|
101
|
-
return value
|
|
102
|
-
if isinstance(value, float) and value.is_integer():
|
|
103
|
-
return int(value)
|
|
104
|
-
if isinstance(value, str) and value.strip():
|
|
105
|
-
try:
|
|
106
|
-
return int(value)
|
|
107
|
-
except ValueError as exc:
|
|
108
|
-
raise ValueError("max_retries must be an int-compatible value") from exc
|
|
109
|
-
raise TypeError("max_retries must be an int, str, or None")
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def coerce_dict(value: object) -> dict[str, Any]:
|
|
113
|
-
"""Return a string-keyed dictionary built from value if possible.
|
|
114
|
-
|
|
115
|
-
Converts Mapping objects to dictionaries. None returns an empty dict.
|
|
116
|
-
|
|
117
|
-
Parameters
|
|
118
|
-
----------
|
|
119
|
-
value : object
|
|
120
|
-
Mapping-like value to convert. None yields an empty dictionary.
|
|
121
|
-
|
|
122
|
-
Returns
|
|
123
|
-
-------
|
|
124
|
-
dict[str, Any]
|
|
125
|
-
Dictionary representation of value.
|
|
126
|
-
|
|
127
|
-
Raises
|
|
128
|
-
------
|
|
129
|
-
TypeError
|
|
130
|
-
If the value cannot be treated as a mapping.
|
|
131
|
-
|
|
132
|
-
Examples
|
|
133
|
-
--------
|
|
134
|
-
>>> coerce_dict({"a": 1})
|
|
135
|
-
{'a': 1}
|
|
136
|
-
>>> coerce_dict(None)
|
|
137
|
-
{}
|
|
138
|
-
"""
|
|
139
|
-
if value is None:
|
|
140
|
-
return {}
|
|
141
|
-
if isinstance(value, Mapping):
|
|
142
|
-
return dict(value)
|
|
143
|
-
raise TypeError("extra_client_kwargs must be a mapping or None")
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
def build_openai_settings(
|
|
147
|
-
api_key: str | None = None,
|
|
148
|
-
org_id: str | None = None,
|
|
149
|
-
project_id: str | None = None,
|
|
150
|
-
base_url: str | None = None,
|
|
151
|
-
default_model: str | None = None,
|
|
152
|
-
timeout: float | str | None = None,
|
|
153
|
-
max_retries: int | str | None = None,
|
|
154
|
-
dotenv_path: Path | None = None,
|
|
155
|
-
**extra_kwargs: Any,
|
|
156
|
-
) -> Any: # Returns OpenAISettings but use Any to avoid circular import
|
|
157
|
-
"""Build OpenAI settings from environment with explicit validation.
|
|
158
|
-
|
|
159
|
-
Convenience function for creating OpenAISettings with validation and
|
|
160
|
-
clear error messages. Reads from environment variables and validates
|
|
161
|
-
required fields, with explicit type coercion for timeout and max_retries.
|
|
162
|
-
|
|
163
|
-
Parameters
|
|
164
|
-
----------
|
|
165
|
-
api_key : str or None, default None
|
|
166
|
-
API key for OpenAI authentication. If None, reads from OPENAI_API_KEY.
|
|
167
|
-
org_id : str or None, default None
|
|
168
|
-
Organization ID. If None, reads from OPENAI_ORG_ID.
|
|
169
|
-
project_id : str or None, default None
|
|
170
|
-
Project ID. If None, reads from OPENAI_PROJECT_ID.
|
|
171
|
-
base_url : str or None, default None
|
|
172
|
-
Base URL for API requests. If None, reads from OPENAI_BASE_URL.
|
|
173
|
-
default_model : str or None, default None
|
|
174
|
-
Default model name. If None, reads from OPENAI_MODEL.
|
|
175
|
-
timeout : float, str, or None, default None
|
|
176
|
-
Request timeout in seconds. If None, reads from OPENAI_TIMEOUT.
|
|
177
|
-
Can be string that will be parsed to float.
|
|
178
|
-
max_retries : int, str, or None, default None
|
|
179
|
-
Maximum retry attempts. If None, reads from OPENAI_MAX_RETRIES.
|
|
180
|
-
Can be string that will be parsed to int.
|
|
181
|
-
dotenv_path : Path or None, default None
|
|
182
|
-
Path to .env file. If None, searches for .env in current directory.
|
|
183
|
-
**extra_kwargs : Any
|
|
184
|
-
Additional keyword arguments for extra_client_kwargs.
|
|
185
|
-
|
|
186
|
-
Returns
|
|
187
|
-
-------
|
|
188
|
-
OpenAISettings
|
|
189
|
-
Configured settings instance.
|
|
190
|
-
|
|
191
|
-
Raises
|
|
192
|
-
------
|
|
193
|
-
ValueError
|
|
194
|
-
If OPENAI_API_KEY is not found in environment or parameters.
|
|
195
|
-
If timeout cannot be parsed as float.
|
|
196
|
-
If max_retries cannot be parsed as int.
|
|
197
|
-
TypeError
|
|
198
|
-
If timeout or max_retries have invalid types.
|
|
199
|
-
|
|
200
|
-
Examples
|
|
201
|
-
--------
|
|
202
|
-
Build from explicit parameters:
|
|
203
|
-
|
|
204
|
-
>>> settings = build_openai_settings(
|
|
205
|
-
... api_key="sk-...",
|
|
206
|
-
... default_model="gpt-4o",
|
|
207
|
-
... timeout=30.0
|
|
208
|
-
... )
|
|
209
|
-
|
|
210
|
-
Build from environment:
|
|
211
|
-
|
|
212
|
-
>>> settings = build_openai_settings() # doctest: +SKIP
|
|
213
|
-
|
|
214
|
-
With custom .env location:
|
|
215
|
-
|
|
216
|
-
>>> settings = build_openai_settings(
|
|
217
|
-
... dotenv_path=Path("/path/to/.env")
|
|
218
|
-
... ) # doctest: +SKIP
|
|
219
|
-
"""
|
|
220
|
-
# Import at runtime to avoid circular import
|
|
221
|
-
from openai_sdk_helpers.config import OpenAISettings
|
|
222
|
-
|
|
223
|
-
# Parse timeout with validation
|
|
224
|
-
parsed_timeout: float | None = None
|
|
225
|
-
if timeout is not None:
|
|
226
|
-
try:
|
|
227
|
-
parsed_timeout = coerce_optional_float(timeout)
|
|
228
|
-
except (ValueError, TypeError) as exc:
|
|
229
|
-
raise ValueError(
|
|
230
|
-
f"Invalid timeout value '{timeout}'. Must be a number or numeric string."
|
|
231
|
-
) from exc
|
|
232
|
-
|
|
233
|
-
# Parse max_retries with validation
|
|
234
|
-
parsed_max_retries: int | None = None
|
|
235
|
-
if max_retries is not None:
|
|
236
|
-
try:
|
|
237
|
-
parsed_max_retries = coerce_optional_int(max_retries)
|
|
238
|
-
except (ValueError, TypeError) as exc:
|
|
239
|
-
raise ValueError(
|
|
240
|
-
f"Invalid max_retries value '{max_retries}'. "
|
|
241
|
-
"Must be an integer or numeric string."
|
|
242
|
-
) from exc
|
|
243
|
-
|
|
244
|
-
# Build settings using from_env with overrides
|
|
245
|
-
overrides = {}
|
|
246
|
-
if api_key is not None:
|
|
247
|
-
overrides["api_key"] = api_key
|
|
248
|
-
if org_id is not None:
|
|
249
|
-
overrides["org_id"] = org_id
|
|
250
|
-
if project_id is not None:
|
|
251
|
-
overrides["project_id"] = project_id
|
|
252
|
-
if base_url is not None:
|
|
253
|
-
overrides["base_url"] = base_url
|
|
254
|
-
if default_model is not None:
|
|
255
|
-
overrides["default_model"] = default_model
|
|
256
|
-
if parsed_timeout is not None:
|
|
257
|
-
overrides["timeout"] = parsed_timeout
|
|
258
|
-
if parsed_max_retries is not None:
|
|
259
|
-
overrides["max_retries"] = parsed_max_retries
|
|
260
|
-
if extra_kwargs:
|
|
261
|
-
overrides["extra_client_kwargs"] = extra_kwargs
|
|
262
|
-
|
|
263
|
-
try:
|
|
264
|
-
return OpenAISettings.from_env(dotenv_path=dotenv_path, **overrides)
|
|
265
|
-
except ValueError as exc:
|
|
266
|
-
# Re-raise with more context but preserve original message
|
|
267
|
-
raise ValueError(f"Failed to build OpenAI settings: {exc}") from exc
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
T = TypeVar("T")
|
|
271
|
-
_configured_logging = False
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
def ensure_list(value: Iterable[T] | T | None) -> list[T]:
|
|
275
|
-
"""Normalize a single item or iterable into a list.
|
|
276
|
-
|
|
277
|
-
Converts None to empty list, tuples to lists, and wraps single
|
|
278
|
-
items in a list.
|
|
279
|
-
|
|
280
|
-
Parameters
|
|
281
|
-
----------
|
|
282
|
-
value : Iterable[T] | T | None
|
|
283
|
-
Item or iterable to wrap. None yields an empty list.
|
|
284
|
-
|
|
285
|
-
Returns
|
|
286
|
-
-------
|
|
287
|
-
list[T]
|
|
288
|
-
Normalized list representation of value.
|
|
289
|
-
|
|
290
|
-
Examples
|
|
291
|
-
--------
|
|
292
|
-
>>> ensure_list(None)
|
|
293
|
-
[]
|
|
294
|
-
>>> ensure_list(5)
|
|
295
|
-
[5]
|
|
296
|
-
>>> ensure_list([1, 2, 3])
|
|
297
|
-
[1, 2, 3]
|
|
298
|
-
>>> ensure_list(("a", "b"))
|
|
299
|
-
['a', 'b']
|
|
300
|
-
"""
|
|
301
|
-
if value is None:
|
|
302
|
-
return []
|
|
303
|
-
if isinstance(value, list):
|
|
304
|
-
return value
|
|
305
|
-
if isinstance(value, tuple):
|
|
306
|
-
return list(value)
|
|
307
|
-
return [value] # type: ignore[list-item]
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
def check_filepath(
|
|
311
|
-
filepath: Path | None = None, *, fullfilepath: str | None = None
|
|
312
|
-
) -> Path:
|
|
313
|
-
"""Ensure the parent directory for a file path exists.
|
|
314
|
-
|
|
315
|
-
Creates parent directories as needed. Exactly one of filepath or
|
|
316
|
-
fullfilepath must be provided.
|
|
317
|
-
|
|
318
|
-
Parameters
|
|
319
|
-
----------
|
|
320
|
-
filepath : Path or None, optional
|
|
321
|
-
Path object to validate. Mutually exclusive with fullfilepath.
|
|
322
|
-
fullfilepath : str or None, optional
|
|
323
|
-
String path to validate. Mutually exclusive with filepath.
|
|
324
|
-
|
|
325
|
-
Returns
|
|
326
|
-
-------
|
|
327
|
-
Path
|
|
328
|
-
Path object representing the validated file path.
|
|
329
|
-
|
|
330
|
-
Raises
|
|
331
|
-
------
|
|
332
|
-
ValueError
|
|
333
|
-
If neither filepath nor fullfilepath is provided.
|
|
334
|
-
|
|
335
|
-
Examples
|
|
336
|
-
--------
|
|
337
|
-
>>> from pathlib import Path
|
|
338
|
-
>>> path = check_filepath(filepath=Path("/tmp/test.txt"))
|
|
339
|
-
>>> isinstance(path, Path)
|
|
340
|
-
True
|
|
341
|
-
"""
|
|
342
|
-
if filepath is None and fullfilepath is None:
|
|
343
|
-
raise ValueError("filepath or fullfilepath is required.")
|
|
344
|
-
if fullfilepath is not None:
|
|
345
|
-
target = Path(fullfilepath)
|
|
346
|
-
elif filepath is not None:
|
|
347
|
-
target = Path(filepath)
|
|
348
|
-
else:
|
|
349
|
-
raise ValueError("filepath or fullfilepath is required.")
|
|
350
|
-
target.parent.mkdir(parents=True, exist_ok=True)
|
|
351
|
-
return target
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
def _to_jsonable(value: Any) -> Any:
|
|
355
|
-
"""Convert common helper types to JSON-serializable forms.
|
|
356
|
-
|
|
357
|
-
Handles Enum, Path, datetime, dataclasses, Pydantic models, dicts,
|
|
358
|
-
lists, tuples, and sets.
|
|
359
|
-
|
|
360
|
-
Parameters
|
|
361
|
-
----------
|
|
362
|
-
value : Any
|
|
363
|
-
Value to convert.
|
|
364
|
-
|
|
365
|
-
Returns
|
|
366
|
-
-------
|
|
367
|
-
Any
|
|
368
|
-
A JSON-safe representation of value.
|
|
369
|
-
|
|
370
|
-
Notes
|
|
371
|
-
-----
|
|
372
|
-
This is an internal helper function. Use coerce_jsonable for public API.
|
|
373
|
-
"""
|
|
374
|
-
if value is None:
|
|
375
|
-
return None
|
|
376
|
-
if isinstance(value, Enum):
|
|
377
|
-
return value.value
|
|
378
|
-
if isinstance(value, Path):
|
|
379
|
-
return str(value)
|
|
380
|
-
if isinstance(value, datetime):
|
|
381
|
-
return value.isoformat()
|
|
382
|
-
if is_dataclass(value) and not isinstance(value, type):
|
|
383
|
-
return {k: _to_jsonable(v) for k, v in asdict(value).items()}
|
|
384
|
-
if hasattr(value, "model_dump"):
|
|
385
|
-
model_dump = getattr(value, "model_dump")
|
|
386
|
-
return model_dump()
|
|
387
|
-
if isinstance(value, dict):
|
|
388
|
-
return {str(k): _to_jsonable(v) for k, v in value.items()}
|
|
389
|
-
if isinstance(value, (list, tuple, set)):
|
|
390
|
-
return [_to_jsonable(v) for v in value]
|
|
391
|
-
return value
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
def coerce_jsonable(value: Any) -> Any:
|
|
395
|
-
"""Convert value into a JSON-serializable representation.
|
|
396
|
-
|
|
397
|
-
Handles BaseStructure, BaseResponse, dataclasses, and other complex
|
|
398
|
-
types by recursively converting them to JSON-compatible forms.
|
|
399
|
-
|
|
400
|
-
Parameters
|
|
401
|
-
----------
|
|
402
|
-
value : Any
|
|
403
|
-
Object to convert into a JSON-friendly structure.
|
|
404
|
-
|
|
405
|
-
Returns
|
|
406
|
-
-------
|
|
407
|
-
Any
|
|
408
|
-
JSON-serializable representation of value.
|
|
409
|
-
|
|
410
|
-
Examples
|
|
411
|
-
--------
|
|
412
|
-
>>> from datetime import datetime
|
|
413
|
-
>>> result = coerce_jsonable({"date": datetime(2024, 1, 1)})
|
|
414
|
-
>>> isinstance(result, dict)
|
|
415
|
-
True
|
|
416
|
-
"""
|
|
417
|
-
from openai_sdk_helpers.response.base import BaseResponse
|
|
418
|
-
from openai_sdk_helpers.structure.base import BaseStructure
|
|
419
|
-
|
|
420
|
-
if value is None:
|
|
421
|
-
return None
|
|
422
|
-
if isinstance(value, BaseStructure):
|
|
423
|
-
return value.model_dump()
|
|
424
|
-
if isinstance(value, BaseResponse):
|
|
425
|
-
return coerce_jsonable(value.messages.to_json())
|
|
426
|
-
if is_dataclass(value) and not isinstance(value, type):
|
|
427
|
-
return {key: coerce_jsonable(item) for key, item in asdict(value).items()}
|
|
428
|
-
coerced = _to_jsonable(value)
|
|
429
|
-
try:
|
|
430
|
-
json.dumps(coerced)
|
|
431
|
-
return coerced
|
|
432
|
-
except TypeError:
|
|
433
|
-
return str(coerced)
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
class customJSONEncoder(json.JSONEncoder):
|
|
437
|
-
"""JSON encoder for common helper types like enums and paths.
|
|
438
|
-
|
|
439
|
-
Extends json.JSONEncoder to handle Enum, Path, datetime, dataclasses,
|
|
440
|
-
and Pydantic models automatically.
|
|
441
|
-
|
|
442
|
-
Methods
|
|
443
|
-
-------
|
|
444
|
-
default(o)
|
|
445
|
-
Return a JSON-serializable representation of o.
|
|
446
|
-
|
|
447
|
-
Examples
|
|
448
|
-
--------
|
|
449
|
-
>>> import json
|
|
450
|
-
>>> from pathlib import Path
|
|
451
|
-
>>> json.dumps({"path": Path("/tmp")}, cls=customJSONEncoder)
|
|
452
|
-
'{"path": "/tmp"}'
|
|
453
|
-
"""
|
|
454
|
-
|
|
455
|
-
def default(self, o: Any) -> Any:
|
|
456
|
-
"""Return a JSON-serializable representation of o.
|
|
457
|
-
|
|
458
|
-
Called by the json module when the default serialization fails.
|
|
459
|
-
Delegates to _to_jsonable for type-specific conversions.
|
|
460
|
-
|
|
461
|
-
Parameters
|
|
462
|
-
----------
|
|
463
|
-
o : Any
|
|
464
|
-
Object to serialize.
|
|
465
|
-
|
|
466
|
-
Returns
|
|
467
|
-
-------
|
|
468
|
-
Any
|
|
469
|
-
JSON-safe representation of o.
|
|
470
|
-
"""
|
|
471
|
-
return _to_jsonable(o)
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
class JSONSerializable:
|
|
475
|
-
"""Mixin for classes that can be serialized to JSON.
|
|
476
|
-
|
|
477
|
-
Provides to_json() and to_json_file() methods for any class. Works
|
|
478
|
-
with dataclasses, Pydantic models, and regular classes with __dict__.
|
|
479
|
-
|
|
480
|
-
Methods
|
|
481
|
-
-------
|
|
482
|
-
to_json()
|
|
483
|
-
Return a JSON-compatible dict representation of the instance.
|
|
484
|
-
to_json_file(filepath)
|
|
485
|
-
Write serialized JSON data to a file path.
|
|
486
|
-
|
|
487
|
-
Examples
|
|
488
|
-
--------
|
|
489
|
-
>>> from dataclasses import dataclass
|
|
490
|
-
>>> @dataclass
|
|
491
|
-
... class MyClass(JSONSerializable):
|
|
492
|
-
... value: int
|
|
493
|
-
>>> obj = MyClass(value=42)
|
|
494
|
-
>>> obj.to_json()
|
|
495
|
-
{'value': 42}
|
|
496
|
-
"""
|
|
497
|
-
|
|
498
|
-
def to_json(self) -> dict[str, Any]:
|
|
499
|
-
"""Return a JSON-compatible dict representation.
|
|
500
|
-
|
|
501
|
-
Automatically handles dataclasses, Pydantic models, and objects
|
|
502
|
-
with __dict__ attributes.
|
|
503
|
-
|
|
504
|
-
Returns
|
|
505
|
-
-------
|
|
506
|
-
dict[str, Any]
|
|
507
|
-
Mapping with only JSON-serializable values.
|
|
508
|
-
|
|
509
|
-
Examples
|
|
510
|
-
--------
|
|
511
|
-
>>> obj = JSONSerializable()
|
|
512
|
-
>>> result = obj.to_json()
|
|
513
|
-
>>> isinstance(result, dict)
|
|
514
|
-
True
|
|
515
|
-
"""
|
|
516
|
-
if is_dataclass(self) and not isinstance(self, type):
|
|
517
|
-
return {k: _to_jsonable(v) for k, v in asdict(self).items()}
|
|
518
|
-
if hasattr(self, "model_dump"):
|
|
519
|
-
model_dump = getattr(self, "model_dump")
|
|
520
|
-
return _to_jsonable(model_dump())
|
|
521
|
-
return _to_jsonable(self.__dict__)
|
|
522
|
-
|
|
523
|
-
def to_json_file(self, filepath: str | Path) -> str:
|
|
524
|
-
"""Write serialized JSON data to a file path.
|
|
525
|
-
|
|
526
|
-
Creates parent directories as needed. Uses customJSONEncoder for
|
|
527
|
-
handling special types.
|
|
528
|
-
|
|
529
|
-
Parameters
|
|
530
|
-
----------
|
|
531
|
-
filepath : str | Path
|
|
532
|
-
Destination file path. Parent directories are created as needed.
|
|
533
|
-
|
|
534
|
-
Returns
|
|
535
|
-
-------
|
|
536
|
-
str
|
|
537
|
-
String representation of the file path written.
|
|
538
|
-
|
|
539
|
-
Examples
|
|
540
|
-
--------
|
|
541
|
-
>>> obj = JSONSerializable()
|
|
542
|
-
>>> path = obj.to_json_file("/tmp/output.json") # doctest: +SKIP
|
|
543
|
-
"""
|
|
544
|
-
target = Path(filepath)
|
|
545
|
-
check_filepath(fullfilepath=str(target))
|
|
546
|
-
with open(target, "w", encoding="utf-8") as handle:
|
|
547
|
-
json.dump(
|
|
548
|
-
self.to_json(),
|
|
549
|
-
handle,
|
|
550
|
-
indent=2,
|
|
551
|
-
ensure_ascii=False,
|
|
552
|
-
cls=customJSONEncoder,
|
|
553
|
-
)
|
|
554
|
-
return str(target)
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
def log(message: str, level: int = logging.INFO) -> None:
|
|
558
|
-
"""Log a message with a basic configuration.
|
|
559
|
-
|
|
560
|
-
Configures logging on first use with a simple timestamp format.
|
|
561
|
-
Subsequent calls use the existing configuration.
|
|
562
|
-
|
|
563
|
-
Parameters
|
|
564
|
-
----------
|
|
565
|
-
message : str
|
|
566
|
-
Message to emit.
|
|
567
|
-
level : int, optional
|
|
568
|
-
Logging level (e.g., logging.INFO, logging.WARNING), by default
|
|
569
|
-
logging.INFO.
|
|
570
|
-
|
|
571
|
-
Examples
|
|
572
|
-
--------
|
|
573
|
-
>>> import logging
|
|
574
|
-
>>> log("Test message", level=logging.INFO) # doctest: +SKIP
|
|
575
|
-
"""
|
|
576
|
-
global _configured_logging
|
|
577
|
-
if not _configured_logging:
|
|
578
|
-
logging.basicConfig(
|
|
579
|
-
level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s"
|
|
580
|
-
)
|
|
581
|
-
_configured_logging = True
|
|
582
|
-
logging.log(level, message)
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
__all__ = [
|
|
586
|
-
"ensure_list",
|
|
587
|
-
"check_filepath",
|
|
588
|
-
"coerce_jsonable",
|
|
589
|
-
"JSONSerializable",
|
|
590
|
-
"customJSONEncoder",
|
|
591
|
-
"log",
|
|
592
|
-
"coerce_optional_float",
|
|
593
|
-
"coerce_optional_int",
|
|
594
|
-
"coerce_dict",
|
|
595
|
-
"build_openai_settings",
|
|
596
|
-
]
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
openai_sdk_helpers/__init__.py,sha256=yFWF1rBF8-mCVPK-_PfiCaBMIVl_NGvJb4wySXWenhg,3765
|
|
2
|
-
openai_sdk_helpers/async_utils.py,sha256=_GPiSDQhWehiZu2S_jB_Xgl0p2qGc5MNu1NN92zz3bg,3726
|
|
3
|
-
openai_sdk_helpers/config.py,sha256=841YGiUu7hvFrB2Bdr6ck4YKCtb2HRI0Uhk6HKpIqAc,7640
|
|
4
|
-
openai_sdk_helpers/context_manager.py,sha256=9z54rjcJ-nAFdEoZHjFdk1YYpeD9bet13MOgn23FzM8,6629
|
|
5
|
-
openai_sdk_helpers/environment.py,sha256=HSPI1h1JUuMxzcTSvr28ktHBvyEJLRzL4bZhNfy59lI,1372
|
|
6
|
-
openai_sdk_helpers/errors.py,sha256=oytqn-6Jg6nPMQOP956ftfkLS0R5c1XBDX-lNstrb3Y,3135
|
|
7
|
-
openai_sdk_helpers/logging_config.py,sha256=fOKBgisOkM0VYDt68pmUSxVWzTeO25_u-El0HOxqEYM,2928
|
|
8
|
-
openai_sdk_helpers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
openai_sdk_helpers/retry.py,sha256=3I5cZOq5X6d7kno3fk1SVDYJ7U2VDHqBS7ZsaXWbU6A,6529
|
|
10
|
-
openai_sdk_helpers/tools.py,sha256=MW6bdJH9Ij16LKNCNNvSthq206T-orTOQTLFzLWxQTo,6043
|
|
11
|
-
openai_sdk_helpers/types.py,sha256=xzldCRfwCZ3rZl18IBmfgA-PVdoZKSWNrlSIhirumSo,1451
|
|
12
|
-
openai_sdk_helpers/validation.py,sha256=fr3zVZ7uEokJJqF3LSIcQm4wV3MvWXcep2ZRpseXZBk,7789
|
|
13
|
-
openai_sdk_helpers/agent/__init__.py,sha256=giowU8jke0z0h7FFUG9V6Vssja8AYwvJMQbiMb3s64k,960
|
|
14
|
-
openai_sdk_helpers/agent/base.py,sha256=CKHfcUsBc8Hd5UAKehHw6E3GVEs7VasZZ0M8WrWJPv4,11737
|
|
15
|
-
openai_sdk_helpers/agent/config.py,sha256=htqy5bcrJeMf3rIpRdL9CKlYwyQI4po420rcgR3i8XI,1971
|
|
16
|
-
openai_sdk_helpers/agent/coordination.py,sha256=00iJPHZvpLEDRDeon_HRQPEHdyQnEk4NTjAj9VgkqVI,16204
|
|
17
|
-
openai_sdk_helpers/agent/prompt_utils.py,sha256=-1M66tqQxh9wWCFg6X-K7cCcqauca3yA04ZjvOpN3bA,337
|
|
18
|
-
openai_sdk_helpers/agent/runner.py,sha256=XRa17OV8f0G8--6qyUFw6BwJSHBNe_Yx8DFajxVYFxA,4137
|
|
19
|
-
openai_sdk_helpers/agent/summarizer.py,sha256=fH8AnYK_68ERf2U7mv0nwXL8KyhrluE-TDY_M5TCdD0,3266
|
|
20
|
-
openai_sdk_helpers/agent/translator.py,sha256=GhUuwFTBecgOO9pMQ41VPvK9mTub5DXJ_7BIS9Xp7bs,5082
|
|
21
|
-
openai_sdk_helpers/agent/utils.py,sha256=DTD5foCqGYfXf13F2bZMYIQROl7SbDSy5GDPGi0Zl-0,1089
|
|
22
|
-
openai_sdk_helpers/agent/validation.py,sha256=JIYVhBTTs0tTxYyzYgY3BHC-9psyzE3LLQDZDqpg13M,4191
|
|
23
|
-
openai_sdk_helpers/agent/search/__init__.py,sha256=xqosfzH4HcBs9IFZks9msG_694rS5q6Ea4_qNeRQRmU,798
|
|
24
|
-
openai_sdk_helpers/agent/search/base.py,sha256=05ERHgNqUrG7bs0zrtFgDps_m_dq1b_Hr1W1aSWm5BM,8602
|
|
25
|
-
openai_sdk_helpers/agent/search/vector.py,sha256=ebIRPFusLJa5SfwV4Ush_8eoLVMlH0OsOFi_dCFXF0M,13600
|
|
26
|
-
openai_sdk_helpers/agent/search/web.py,sha256=8le4xnZ3nllySqWb7rZaOq44ZR8q67c_WiE57ncmL90,10014
|
|
27
|
-
openai_sdk_helpers/enums/__init__.py,sha256=aFf79C4JBeLC3kMlJfSpehyjx5uNCtW6eK5rD6ZFfhM,322
|
|
28
|
-
openai_sdk_helpers/enums/base.py,sha256=cNllDtzcgI0_eZYXxFko14yhxwicX6xbeDfz9gFE3qo,2753
|
|
29
|
-
openai_sdk_helpers/prompt/__init__.py,sha256=MOqgKwG9KLqKudoKRlUfLxiSmdOi2aD6hNrWDFqLHkk,418
|
|
30
|
-
openai_sdk_helpers/prompt/base.py,sha256=FvQNEjIdYDLvGEiR9_dbEn6G47TPMsWm4r26jcLjgus,7569
|
|
31
|
-
openai_sdk_helpers/prompt/summarizer.jinja,sha256=jliSetWDISbql1EkWi1RB8-L_BXUg8JMkRRsPRHuzbY,309
|
|
32
|
-
openai_sdk_helpers/prompt/translator.jinja,sha256=SZhW8ipEzM-9IA4wyS_r2wIMTAclWrilmk1s46njoL0,291
|
|
33
|
-
openai_sdk_helpers/prompt/validator.jinja,sha256=6t8q_IdxFd3mVBGX6SFKNOert1Wo3YpTOji2SNEbbtE,547
|
|
34
|
-
openai_sdk_helpers/response/__init__.py,sha256=eoQF086o3OZYmVfJWXhSpYlPhQBb-VLDA5hvw7guLEc,1741
|
|
35
|
-
openai_sdk_helpers/response/base.py,sha256=-d-vvY4OId_MU6EAN55bBPEftnskw9Ry8TVQ705f9Xw,27965
|
|
36
|
-
openai_sdk_helpers/response/config.py,sha256=WheEWkTxNFHL54_yvFY3M0LclNmajwTiMftSFeAH2eI,10300
|
|
37
|
-
openai_sdk_helpers/response/messages.py,sha256=oVSHpSV_iQxHreCXm--a6MlHg_kkElQi3R2Y8Y7VphA,9134
|
|
38
|
-
openai_sdk_helpers/response/runner.py,sha256=Rf13cQGsR7sN9gA81Y5th1tfH2DCCAwQ6RMs3bVgjnk,4269
|
|
39
|
-
openai_sdk_helpers/response/tool_call.py,sha256=VYPvKUR-Ren0Y_nYS4jUSinhTyXKzFwQLxu-d3r_YuM,4506
|
|
40
|
-
openai_sdk_helpers/response/vector_store.py,sha256=MyHUu6P9ueNsd9erbBkyVqq3stLK6qVuehdvmFAHq9E,3074
|
|
41
|
-
openai_sdk_helpers/streamlit_app/__init__.py,sha256=RjJbnBDS5_YmAmxvaa3phB5u9UcXsXDEk_jMlY_pa5Q,793
|
|
42
|
-
openai_sdk_helpers/streamlit_app/app.py,sha256=ID3B4fUQHvv1Cwuuvrlm4nK4d0nWL6uBE40O_T6r7yY,10808
|
|
43
|
-
openai_sdk_helpers/streamlit_app/config.py,sha256=EK6LWACo7YIkDko1oesvupOx56cTuWWnwnXRiu8EYbs,15986
|
|
44
|
-
openai_sdk_helpers/streamlit_app/streamlit_web_search.py,sha256=OrX-kgW_yaHgIsK6wY9gBVLbvDaMFXgkgdhKQDsA8kQ,2506
|
|
45
|
-
openai_sdk_helpers/structure/__init__.py,sha256=QUvRdJMbKsumjwJdWq9ihfcOED4ZbJMBQbmA1nmYJVw,3339
|
|
46
|
-
openai_sdk_helpers/structure/agent_blueprint.py,sha256=2W-RBM5G3ZefMcYHqqoV6Y1witcSbMlUpdU1CA9n3tg,9698
|
|
47
|
-
openai_sdk_helpers/structure/base.py,sha256=7RMsCMjQR7u3mksirqd0E6AgCgWEMVRQtgNefwHWPGo,28278
|
|
48
|
-
openai_sdk_helpers/structure/prompt.py,sha256=7DBdLu6WDvXy2RkEBayDiX2Jn8T4-hJuohsOaKEoqJs,1075
|
|
49
|
-
openai_sdk_helpers/structure/responses.py,sha256=iYJBT_4VFifzQqPnTpRWTcB0o7xkhPIQ2ugedivrpto,4868
|
|
50
|
-
openai_sdk_helpers/structure/summary.py,sha256=MyZzMuqHP9F8B4rYYxCGJwojy5RavWUkMiRZ6yMQzvU,3143
|
|
51
|
-
openai_sdk_helpers/structure/validation.py,sha256=vsilA3Qs3fjWLeYlnZnMEGj9i_bOJtXc2J3mSIEHncg,2409
|
|
52
|
-
openai_sdk_helpers/structure/vector_search.py,sha256=A0w2AR0r6aIFoYbNkscUAGT7VzTe6WuvxrqUsWT2PMQ,5782
|
|
53
|
-
openai_sdk_helpers/structure/web_search.py,sha256=S8OdllBWqEGXaKf6Alocl89ZuG7BlvXK5ra1Lm7lfjE,4572
|
|
54
|
-
openai_sdk_helpers/structure/plan/__init__.py,sha256=IGr0Tk4inN_8o7fT2N02_FTi6U6l2T9_npcQHAlBwKA,1076
|
|
55
|
-
openai_sdk_helpers/structure/plan/enum.py,sha256=seESSwH-IeeW-9BqIMUQyk3qjtchfU3TDhF9HPDB1OM,3079
|
|
56
|
-
openai_sdk_helpers/structure/plan/helpers.py,sha256=25qXUMPY73y3E6EsE88n9VBwNj2JZkzXy1AaWGsoSLw,5132
|
|
57
|
-
openai_sdk_helpers/structure/plan/plan.py,sha256=LtfwWwZiHGe06nFCXSbT8p3x3w9hhI0wXS7hTeeWXvY,9663
|
|
58
|
-
openai_sdk_helpers/structure/plan/task.py,sha256=2dH8iaLhjC7MKZEW1T_HICaggi1RPyKSPOl9ORmmYdg,4538
|
|
59
|
-
openai_sdk_helpers/structure/plan/types.py,sha256=7y9QEVdZreQUXV7n-R4RoNZzw5HeOVbJGWx9QkSfuNY,418
|
|
60
|
-
openai_sdk_helpers/utils/__init__.py,sha256=oNMc8xyOGmXLNIOjwC5EhN8Jjy_S74Vgwzzg41RNb4g,1566
|
|
61
|
-
openai_sdk_helpers/utils/core.py,sha256=Ehm9WePZTl9ypbbKlHNiyRkhI4a5ZhbDwKiSJTNTgz8,17262
|
|
62
|
-
openai_sdk_helpers/vector_storage/__init__.py,sha256=L5LxO09puh9_yBB9IDTvc1CvVkARVkHqYY1KX3inB4c,975
|
|
63
|
-
openai_sdk_helpers/vector_storage/cleanup.py,sha256=ImWIE-9lli-odD8qIARvmeaa0y8ZD4pYYP-kT0O3178,3552
|
|
64
|
-
openai_sdk_helpers/vector_storage/storage.py,sha256=ZiTZnvCY28R-WUQjHdnjQo1xIRbXAM6JL0VhqW9MM9I,21725
|
|
65
|
-
openai_sdk_helpers/vector_storage/types.py,sha256=jTCcOYMeOpZWvcse0z4T3MVs-RBOPC-fqWTBeQrgafU,1639
|
|
66
|
-
openai_sdk_helpers-0.1.0.dist-info/METADATA,sha256=R-Lc44fSOhAohVtwOAVW_pg3_GMHfYW5ve3bwZlIETE,18492
|
|
67
|
-
openai_sdk_helpers-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
68
|
-
openai_sdk_helpers-0.1.0.dist-info/licenses/LICENSE,sha256=CUhc1NrE50bs45tcXF7OcTQBKEvkUuLqeOHgrWQ5jaA,1067
|
|
69
|
-
openai_sdk_helpers-0.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|