openai-sdk-helpers 0.3.0__py3-none-any.whl → 0.4.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 +6 -6
- openai_sdk_helpers/agent/__init__.py +2 -2
- openai_sdk_helpers/agent/base.py +231 -110
- openai_sdk_helpers/agent/config.py +83 -29
- openai_sdk_helpers/agent/coordination.py +64 -28
- openai_sdk_helpers/agent/runner.py +16 -15
- openai_sdk_helpers/agent/search/base.py +94 -45
- openai_sdk_helpers/agent/search/vector.py +86 -58
- openai_sdk_helpers/agent/search/web.py +71 -40
- openai_sdk_helpers/agent/summarizer.py +32 -7
- openai_sdk_helpers/agent/translator.py +57 -24
- openai_sdk_helpers/agent/validation.py +34 -4
- openai_sdk_helpers/cli.py +42 -0
- openai_sdk_helpers/config.py +0 -1
- openai_sdk_helpers/environment.py +3 -2
- openai_sdk_helpers/files_api.py +35 -3
- openai_sdk_helpers/prompt/base.py +6 -0
- openai_sdk_helpers/response/__init__.py +3 -3
- openai_sdk_helpers/response/base.py +142 -73
- openai_sdk_helpers/response/config.py +43 -51
- openai_sdk_helpers/response/files.py +5 -5
- openai_sdk_helpers/response/messages.py +3 -3
- openai_sdk_helpers/response/runner.py +7 -7
- openai_sdk_helpers/response/tool_call.py +94 -4
- openai_sdk_helpers/response/vector_store.py +3 -3
- openai_sdk_helpers/streamlit_app/app.py +16 -16
- openai_sdk_helpers/streamlit_app/config.py +38 -37
- openai_sdk_helpers/streamlit_app/streamlit_web_search.py +2 -2
- openai_sdk_helpers/structure/__init__.py +6 -2
- openai_sdk_helpers/structure/agent_blueprint.py +2 -2
- openai_sdk_helpers/structure/base.py +8 -99
- openai_sdk_helpers/structure/plan/plan.py +2 -2
- openai_sdk_helpers/structure/plan/task.py +9 -9
- openai_sdk_helpers/structure/prompt.py +2 -2
- openai_sdk_helpers/structure/responses.py +15 -15
- openai_sdk_helpers/structure/summary.py +3 -3
- openai_sdk_helpers/structure/translation.py +32 -0
- openai_sdk_helpers/structure/validation.py +2 -2
- openai_sdk_helpers/structure/vector_search.py +7 -7
- openai_sdk_helpers/structure/web_search.py +6 -6
- openai_sdk_helpers/tools.py +41 -15
- openai_sdk_helpers/utils/__init__.py +19 -5
- openai_sdk_helpers/utils/json/__init__.py +55 -0
- openai_sdk_helpers/utils/json/base_model.py +181 -0
- openai_sdk_helpers/utils/{json_utils.py → json/data_class.py} +33 -68
- openai_sdk_helpers/utils/json/ref.py +113 -0
- openai_sdk_helpers/utils/json/utils.py +203 -0
- openai_sdk_helpers/utils/output_validation.py +21 -1
- openai_sdk_helpers/utils/path_utils.py +34 -1
- openai_sdk_helpers/utils/registry.py +17 -6
- openai_sdk_helpers/vector_storage/storage.py +10 -0
- {openai_sdk_helpers-0.3.0.dist-info → openai_sdk_helpers-0.4.0.dist-info}/METADATA +7 -7
- openai_sdk_helpers-0.4.0.dist-info/RECORD +86 -0
- openai_sdk_helpers-0.3.0.dist-info/RECORD +0 -81
- {openai_sdk_helpers-0.3.0.dist-info → openai_sdk_helpers-0.4.0.dist-info}/WHEEL +0 -0
- {openai_sdk_helpers-0.3.0.dist-info → openai_sdk_helpers-0.4.0.dist-info}/entry_points.txt +0 -0
- {openai_sdk_helpers-0.3.0.dist-info → openai_sdk_helpers-0.4.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Reference encoding helpers for object reconstruction.
|
|
2
|
+
|
|
3
|
+
This module provides helpers for encoding and decoding object references
|
|
4
|
+
using module and qualname information, enabling serialization of class
|
|
5
|
+
references for later reconstruction.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import importlib
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_module_qualname(obj: Any) -> tuple[str, str] | None:
|
|
15
|
+
"""Retrieve module and qualname for an object.
|
|
16
|
+
|
|
17
|
+
Safe retrieval that returns None if module or qualname cannot be determined.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
obj : Any
|
|
22
|
+
Object to get module and qualname from.
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
tuple[str, str] or None
|
|
27
|
+
Tuple of (module, qualname) or None if cannot be determined.
|
|
28
|
+
|
|
29
|
+
Examples
|
|
30
|
+
--------
|
|
31
|
+
>>> class MyClass:
|
|
32
|
+
... pass
|
|
33
|
+
>>> get_module_qualname(MyClass)
|
|
34
|
+
('__main__', 'MyClass')
|
|
35
|
+
"""
|
|
36
|
+
module = getattr(obj, "__module__", None)
|
|
37
|
+
qualname = getattr(obj, "__qualname__", None)
|
|
38
|
+
if module and qualname:
|
|
39
|
+
return (module, qualname)
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def encode_module_qualname(obj: Any) -> dict[str, Any] | None:
|
|
44
|
+
"""Encode object reference for import reconstruction.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
obj : Any
|
|
49
|
+
Object to encode (typically a class).
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
dict[str, Any] or None
|
|
54
|
+
Dictionary with 'module' and 'qualname' keys, or None if encoding fails.
|
|
55
|
+
|
|
56
|
+
Examples
|
|
57
|
+
--------
|
|
58
|
+
>>> class MyClass:
|
|
59
|
+
... pass
|
|
60
|
+
>>> encode_module_qualname(MyClass)
|
|
61
|
+
{'module': '__main__', 'qualname': 'MyClass'}
|
|
62
|
+
"""
|
|
63
|
+
result = get_module_qualname(obj)
|
|
64
|
+
if result is None:
|
|
65
|
+
return None
|
|
66
|
+
module, qualname = result
|
|
67
|
+
return {"module": module, "qualname": qualname}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def decode_module_qualname(ref: dict[str, Any]) -> Any | None:
|
|
71
|
+
"""Import and retrieve object by encoded reference.
|
|
72
|
+
|
|
73
|
+
Parameters
|
|
74
|
+
----------
|
|
75
|
+
ref : dict[str, Any]
|
|
76
|
+
Dictionary with 'module' and 'qualname' keys.
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
Any or None
|
|
81
|
+
Retrieved object or None if import/retrieval fails.
|
|
82
|
+
|
|
83
|
+
Examples
|
|
84
|
+
--------
|
|
85
|
+
>>> ref = {'module': 'pathlib', 'qualname': 'Path'}
|
|
86
|
+
>>> decode_module_qualname(ref)
|
|
87
|
+
<class 'pathlib.Path'>
|
|
88
|
+
"""
|
|
89
|
+
if not isinstance(ref, dict):
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
module_name = ref.get("module")
|
|
93
|
+
qualname = ref.get("qualname")
|
|
94
|
+
|
|
95
|
+
if not module_name or not qualname:
|
|
96
|
+
return None
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
module = importlib.import_module(module_name)
|
|
100
|
+
# Handle nested qualnames (e.g., "OuterClass.InnerClass")
|
|
101
|
+
obj = module
|
|
102
|
+
for attr in qualname.split("."):
|
|
103
|
+
obj = getattr(obj, attr)
|
|
104
|
+
return obj
|
|
105
|
+
except (ImportError, AttributeError):
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
__all__ = [
|
|
110
|
+
"get_module_qualname",
|
|
111
|
+
"encode_module_qualname",
|
|
112
|
+
"decode_module_qualname",
|
|
113
|
+
]
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""Core JSON serialization utilities.
|
|
2
|
+
|
|
3
|
+
This module provides the core functions for converting common types to
|
|
4
|
+
JSON-serializable forms, including to_jsonable, coerce_jsonable, and
|
|
5
|
+
customJSONEncoder.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
from dataclasses import asdict, is_dataclass
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from .ref import encode_module_qualname
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def to_jsonable(value: Any) -> Any:
|
|
21
|
+
"""Convert common types to JSON-safe forms.
|
|
22
|
+
|
|
23
|
+
Recursively converts containers, dicts, dataclasses, Pydantic models, enums,
|
|
24
|
+
paths, datetimes, and StructureBase instances/classes to JSON-serializable forms.
|
|
25
|
+
Private properties (starting with underscore) are excluded from serialization.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
value : Any
|
|
30
|
+
Value to convert to JSON-serializable form.
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
Any
|
|
35
|
+
JSON-serializable representation of the value.
|
|
36
|
+
|
|
37
|
+
Notes
|
|
38
|
+
-----
|
|
39
|
+
Serialization rules:
|
|
40
|
+
- Enums: use enum.value
|
|
41
|
+
- Paths: serialize to string
|
|
42
|
+
- Datetimes: ISO8601 datetime.isoformat()
|
|
43
|
+
- Dataclasses (instances): asdict followed by recursive conversion
|
|
44
|
+
- Pydantic-like objects: use model_dump() if available
|
|
45
|
+
- Dicts/containers: recursively convert values; dict keys coerced to str
|
|
46
|
+
- Private properties: keys starting with underscore are excluded
|
|
47
|
+
- StructureBase instances: use .model_dump()
|
|
48
|
+
- StructureBase classes: encode with {module, qualname, "__structure_class__": True}
|
|
49
|
+
- Sets: converted to lists
|
|
50
|
+
|
|
51
|
+
Examples
|
|
52
|
+
--------
|
|
53
|
+
>>> from enum import Enum
|
|
54
|
+
>>> class Color(Enum):
|
|
55
|
+
... RED = "red"
|
|
56
|
+
>>> to_jsonable(Color.RED)
|
|
57
|
+
'red'
|
|
58
|
+
>>> to_jsonable(Path("/tmp/test"))
|
|
59
|
+
'/tmp/test'
|
|
60
|
+
>>> to_jsonable({"public": 1, "_private": 2})
|
|
61
|
+
{'public': 1}
|
|
62
|
+
"""
|
|
63
|
+
return _to_jsonable(value)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _to_jsonable(value: Any) -> Any:
|
|
67
|
+
"""Convert common helper types to JSON-serializable forms (internal)."""
|
|
68
|
+
from openai_sdk_helpers.structure.base import StructureBase
|
|
69
|
+
|
|
70
|
+
if value is None:
|
|
71
|
+
return None
|
|
72
|
+
if isinstance(value, Enum):
|
|
73
|
+
return value.value
|
|
74
|
+
if isinstance(value, Path):
|
|
75
|
+
return str(value)
|
|
76
|
+
if isinstance(value, datetime):
|
|
77
|
+
return value.isoformat()
|
|
78
|
+
if is_dataclass(value) and not isinstance(value, type):
|
|
79
|
+
return {
|
|
80
|
+
k: _to_jsonable(v)
|
|
81
|
+
for k, v in asdict(value).items()
|
|
82
|
+
if not str(k).startswith("_")
|
|
83
|
+
}
|
|
84
|
+
# Check for StructureBase class (not instance) before model_dump check
|
|
85
|
+
if isinstance(value, type):
|
|
86
|
+
try:
|
|
87
|
+
if issubclass(value, StructureBase):
|
|
88
|
+
encoded = encode_module_qualname(value)
|
|
89
|
+
if encoded:
|
|
90
|
+
encoded["__structure_class__"] = True
|
|
91
|
+
return encoded
|
|
92
|
+
return str(value)
|
|
93
|
+
except TypeError:
|
|
94
|
+
# Some type-like objects may pass isinstance(value, type) but
|
|
95
|
+
# still not be valid arguments to issubclass; ignore these.
|
|
96
|
+
pass
|
|
97
|
+
if isinstance(value, StructureBase):
|
|
98
|
+
return value.model_dump()
|
|
99
|
+
# Check for model_dump on instances (after class checks)
|
|
100
|
+
if hasattr(value, "model_dump") and not isinstance(value, type):
|
|
101
|
+
model_dump = getattr(value, "model_dump")
|
|
102
|
+
return model_dump()
|
|
103
|
+
if isinstance(value, dict):
|
|
104
|
+
return {
|
|
105
|
+
str(k): _to_jsonable(v)
|
|
106
|
+
for k, v in value.items()
|
|
107
|
+
if not str(k).startswith("_")
|
|
108
|
+
}
|
|
109
|
+
if isinstance(value, (list, tuple, set)):
|
|
110
|
+
return [_to_jsonable(v) for v in value]
|
|
111
|
+
return value
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def coerce_jsonable(value: Any) -> Any:
|
|
115
|
+
"""Ensure json.dumps succeeds.
|
|
116
|
+
|
|
117
|
+
Falls back to str when necessary. Special-cases ResponseBase.
|
|
118
|
+
|
|
119
|
+
Parameters
|
|
120
|
+
----------
|
|
121
|
+
value : Any
|
|
122
|
+
Value to coerce to JSON-serializable form.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
Any
|
|
127
|
+
JSON-serializable representation, or str(value) as fallback.
|
|
128
|
+
|
|
129
|
+
Notes
|
|
130
|
+
-----
|
|
131
|
+
This function first attempts to convert the value using to_jsonable(),
|
|
132
|
+
then validates it can be serialized with json.dumps(). If serialization
|
|
133
|
+
fails, it falls back to str(value).
|
|
134
|
+
|
|
135
|
+
Special handling for ResponseBase: serialized as messages.to_json().
|
|
136
|
+
|
|
137
|
+
Examples
|
|
138
|
+
--------
|
|
139
|
+
>>> coerce_jsonable({"key": "value"})
|
|
140
|
+
{'key': 'value'}
|
|
141
|
+
>>> class CustomObj:
|
|
142
|
+
... def __str__(self):
|
|
143
|
+
... return "custom"
|
|
144
|
+
>>> coerce_jsonable(CustomObj())
|
|
145
|
+
'custom'
|
|
146
|
+
"""
|
|
147
|
+
from openai_sdk_helpers.response.base import ResponseBase
|
|
148
|
+
|
|
149
|
+
if value is None:
|
|
150
|
+
return None
|
|
151
|
+
if isinstance(value, ResponseBase):
|
|
152
|
+
return coerce_jsonable(value.messages.to_json())
|
|
153
|
+
if is_dataclass(value) and not isinstance(value, type):
|
|
154
|
+
return {
|
|
155
|
+
key: coerce_jsonable(item)
|
|
156
|
+
for key, item in asdict(value).items()
|
|
157
|
+
if not (isinstance(key, str) and key.startswith("_"))
|
|
158
|
+
}
|
|
159
|
+
coerced = _to_jsonable(value)
|
|
160
|
+
try:
|
|
161
|
+
json.dumps(coerced)
|
|
162
|
+
return coerced
|
|
163
|
+
except TypeError:
|
|
164
|
+
return str(coerced)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class customJSONEncoder(json.JSONEncoder):
|
|
168
|
+
"""JSON encoder delegating to to_jsonable.
|
|
169
|
+
|
|
170
|
+
This encoder handles common types like Enum, Path, datetime, dataclasses,
|
|
171
|
+
sets, StructureBase instances/classes, and Pydantic-like objects.
|
|
172
|
+
|
|
173
|
+
Examples
|
|
174
|
+
--------
|
|
175
|
+
>>> import json
|
|
176
|
+
>>> from enum import Enum
|
|
177
|
+
>>> class Color(Enum):
|
|
178
|
+
... RED = "red"
|
|
179
|
+
>>> json.dumps({"color": Color.RED}, cls=customJSONEncoder)
|
|
180
|
+
'{"color": "red"}'
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
def default(self, o: Any) -> Any:
|
|
184
|
+
"""Return JSON-serializable representation of object.
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
o : Any
|
|
189
|
+
Object to serialize.
|
|
190
|
+
|
|
191
|
+
Returns
|
|
192
|
+
-------
|
|
193
|
+
Any
|
|
194
|
+
JSON-serializable representation.
|
|
195
|
+
"""
|
|
196
|
+
return _to_jsonable(o)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
__all__ = [
|
|
200
|
+
"to_jsonable",
|
|
201
|
+
"coerce_jsonable",
|
|
202
|
+
"customJSONEncoder",
|
|
203
|
+
]
|
|
@@ -82,7 +82,7 @@ class JSONSchemaValidator(ValidationRule):
|
|
|
82
82
|
Parameters
|
|
83
83
|
----------
|
|
84
84
|
schema : dict
|
|
85
|
-
JSON schema to validate against.
|
|
85
|
+
A dictionary representing the JSON schema to validate against.
|
|
86
86
|
|
|
87
87
|
Examples
|
|
88
88
|
--------
|
|
@@ -100,6 +100,11 @@ class JSONSchemaValidator(ValidationRule):
|
|
|
100
100
|
----------
|
|
101
101
|
schema : dict
|
|
102
102
|
JSON schema dictionary.
|
|
103
|
+
|
|
104
|
+
Raises
|
|
105
|
+
------
|
|
106
|
+
ValueError
|
|
107
|
+
If the schema is not a valid dictionary.
|
|
103
108
|
"""
|
|
104
109
|
self.schema = schema
|
|
105
110
|
|
|
@@ -186,6 +191,11 @@ class SemanticValidator(ValidationRule):
|
|
|
186
191
|
Phrases that must not appear.
|
|
187
192
|
must_reference_sources : bool
|
|
188
193
|
Check for source references.
|
|
194
|
+
|
|
195
|
+
Raises
|
|
196
|
+
------
|
|
197
|
+
ValueError
|
|
198
|
+
If any of the parameters are not of the expected type.
|
|
189
199
|
"""
|
|
190
200
|
self.must_contain = must_contain or []
|
|
191
201
|
self.must_not_contain = must_not_contain or []
|
|
@@ -281,6 +291,11 @@ class LengthValidator(ValidationRule):
|
|
|
281
291
|
Minimum word count.
|
|
282
292
|
max_words : int, optional
|
|
283
293
|
Maximum word count.
|
|
294
|
+
|
|
295
|
+
Raises
|
|
296
|
+
------
|
|
297
|
+
ValueError
|
|
298
|
+
If any of the parameters are not integers.
|
|
284
299
|
"""
|
|
285
300
|
self.min_length = min_length
|
|
286
301
|
self.max_length = max_length
|
|
@@ -354,6 +369,11 @@ class OutputValidator:
|
|
|
354
369
|
----------
|
|
355
370
|
rules : list[ValidationRule], optional
|
|
356
371
|
Initial validation rules.
|
|
372
|
+
|
|
373
|
+
Raises
|
|
374
|
+
------
|
|
375
|
+
ValueError
|
|
376
|
+
If rules is not a list of ValidationRule instances.
|
|
357
377
|
"""
|
|
358
378
|
self.rules = rules or []
|
|
359
379
|
|
|
@@ -24,6 +24,18 @@ def check_filepath(
|
|
|
24
24
|
-------
|
|
25
25
|
Path
|
|
26
26
|
Path object representing the validated file path.
|
|
27
|
+
|
|
28
|
+
Raises
|
|
29
|
+
------
|
|
30
|
+
ValueError
|
|
31
|
+
If both or neither of filepath and fullfilepath are provided.
|
|
32
|
+
IOError
|
|
33
|
+
If the directory cannot be created.
|
|
34
|
+
|
|
35
|
+
Examples
|
|
36
|
+
--------
|
|
37
|
+
>>> check_filepath(fullfilepath="/tmp/my_app/data.json")
|
|
38
|
+
Path('/tmp/my_app/data.json')
|
|
27
39
|
"""
|
|
28
40
|
if filepath is None and fullfilepath is None:
|
|
29
41
|
raise ValueError("filepath or fullfilepath is required.")
|
|
@@ -38,7 +50,28 @@ def check_filepath(
|
|
|
38
50
|
|
|
39
51
|
|
|
40
52
|
def ensure_directory(path: Path) -> Path:
|
|
41
|
-
"""Ensure a directory exists and return it.
|
|
53
|
+
"""Ensure a directory exists and return it.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
path : Path
|
|
58
|
+
The directory path to check and create if necessary.
|
|
59
|
+
|
|
60
|
+
Returns
|
|
61
|
+
-------
|
|
62
|
+
Path
|
|
63
|
+
The validated Path object for the directory.
|
|
64
|
+
|
|
65
|
+
Raises
|
|
66
|
+
------
|
|
67
|
+
IOError
|
|
68
|
+
If the directory cannot be created.
|
|
69
|
+
|
|
70
|
+
Examples
|
|
71
|
+
--------
|
|
72
|
+
>>> ensure_directory(Path("/tmp/my_app"))
|
|
73
|
+
Path('/tmp/my_app')
|
|
74
|
+
"""
|
|
42
75
|
path.mkdir(parents=True, exist_ok=True)
|
|
43
76
|
return path
|
|
44
77
|
|
|
@@ -6,9 +6,10 @@ import warnings
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import Generic, TypeVar
|
|
8
8
|
|
|
9
|
+
from ..utils.json.data_class import DataclassJSONSerializable
|
|
9
10
|
from .path_utils import ensure_directory
|
|
10
11
|
|
|
11
|
-
T = TypeVar("T")
|
|
12
|
+
T = TypeVar("T", bound=DataclassJSONSerializable)
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class BaseRegistry(Generic[T]):
|
|
@@ -43,6 +44,17 @@ class BaseRegistry(Generic[T]):
|
|
|
43
44
|
"""Initialize an empty registry."""
|
|
44
45
|
self._configs: dict[str, T] = {}
|
|
45
46
|
|
|
47
|
+
@property
|
|
48
|
+
def configs(self) -> dict[str, T]:
|
|
49
|
+
"""Return the internal configuration mapping.
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
dict[str, T]
|
|
54
|
+
Mapping of configuration names to instances.
|
|
55
|
+
"""
|
|
56
|
+
return self._configs
|
|
57
|
+
|
|
46
58
|
def register(self, config: T) -> None:
|
|
47
59
|
"""Add a configuration to the registry.
|
|
48
60
|
|
|
@@ -121,7 +133,7 @@ class BaseRegistry(Generic[T]):
|
|
|
121
133
|
If the directory cannot be created or files cannot be written.
|
|
122
134
|
"""
|
|
123
135
|
dir_path = ensure_directory(Path(path))
|
|
124
|
-
config_names = self.
|
|
136
|
+
config_names = self.configs
|
|
125
137
|
|
|
126
138
|
if not config_names:
|
|
127
139
|
return
|
|
@@ -129,9 +141,8 @@ class BaseRegistry(Generic[T]):
|
|
|
129
141
|
for config_name in config_names:
|
|
130
142
|
config = self.get(config_name)
|
|
131
143
|
filename = f"{config_name}.json"
|
|
132
|
-
filepath = dir_path / filename
|
|
133
|
-
|
|
134
|
-
getattr(config, "to_json_file")(filepath)
|
|
144
|
+
filepath = dir_path / config.__class__.__name__ / filename
|
|
145
|
+
config.to_json_file(filepath)
|
|
135
146
|
|
|
136
147
|
def load_from_directory(self, path: Path | str, *, config_class: type[T]) -> int:
|
|
137
148
|
"""Load all configurations from JSON files in a directory.
|
|
@@ -170,7 +181,7 @@ class BaseRegistry(Generic[T]):
|
|
|
170
181
|
count = 0
|
|
171
182
|
for json_file in sorted(dir_path.glob("*.json")):
|
|
172
183
|
try:
|
|
173
|
-
config =
|
|
184
|
+
config = config_class.from_json_file(json_file)
|
|
174
185
|
self.register(config)
|
|
175
186
|
count += 1
|
|
176
187
|
except Exception as exc:
|
|
@@ -56,6 +56,16 @@ class VectorStorage:
|
|
|
56
56
|
including file uploads, deletions, and semantic search operations. It handles
|
|
57
57
|
file caching, concurrent uploads, and automatic store creation.
|
|
58
58
|
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
store_name : str
|
|
62
|
+
Name of the vector store to create or connect to.
|
|
63
|
+
client : OpenAIClient or None, optional
|
|
64
|
+
Preconfigured OpenAI-compatible client, by default None.
|
|
65
|
+
model : str or None, optional
|
|
66
|
+
Embedding model identifier. Reads OPENAI_MODEL env var if None,
|
|
67
|
+
by default None.
|
|
68
|
+
|
|
59
69
|
Examples
|
|
60
70
|
--------
|
|
61
71
|
Basic usage:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openai-sdk-helpers
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Composable helpers for OpenAI SDK agents, prompts, and storage
|
|
5
5
|
Author: openai-sdk-helpers maintainers
|
|
6
6
|
License: MIT
|
|
@@ -277,14 +277,14 @@ when instantiating `OpenAISettings`.
|
|
|
277
277
|
For more fine-grained control over API interactions, use the `response` module built on the standard `openai` SDK. This gives you direct access to message history, tool handlers, and custom response parsing:
|
|
278
278
|
|
|
279
279
|
```python
|
|
280
|
-
from openai_sdk_helpers.response import
|
|
280
|
+
from openai_sdk_helpers.response import ResponseBase
|
|
281
281
|
from openai_sdk_helpers import OpenAISettings
|
|
282
282
|
|
|
283
283
|
# Configure OpenAI settings
|
|
284
284
|
settings = OpenAISettings.from_env()
|
|
285
285
|
|
|
286
286
|
# Create a response handler with custom instructions
|
|
287
|
-
response =
|
|
287
|
+
response = ResponseBase(
|
|
288
288
|
instructions="You are a helpful code review assistant.",
|
|
289
289
|
tools=None, # Or provide custom tool definitions
|
|
290
290
|
output_structure=None, # Or a Pydantic model for structured output
|
|
@@ -311,12 +311,12 @@ response.close()
|
|
|
311
311
|
The `response` module automatically detects file types and handles them appropriately:
|
|
312
312
|
|
|
313
313
|
```python
|
|
314
|
-
from openai_sdk_helpers.response import
|
|
314
|
+
from openai_sdk_helpers.response import ResponseBase
|
|
315
315
|
from openai_sdk_helpers import OpenAISettings
|
|
316
316
|
|
|
317
317
|
settings = OpenAISettings.from_env()
|
|
318
318
|
|
|
319
|
-
with
|
|
319
|
+
with ResponseBase(
|
|
320
320
|
name="analyzer",
|
|
321
321
|
instructions="You are a helpful assistant that can analyze files.",
|
|
322
322
|
tools=None,
|
|
@@ -550,7 +550,7 @@ These modules use the `openai-agents` SDK for high-level agent workflows with au
|
|
|
550
550
|
|
|
551
551
|
These modules use the standard `openai` SDK for direct API interactions with fine-grained control over request/response cycles.
|
|
552
552
|
|
|
553
|
-
- **`openai_sdk_helpers.response.base.
|
|
553
|
+
- **`openai_sdk_helpers.response.base.ResponseBase`**
|
|
554
554
|
Manages complete OpenAI API interaction lifecycle including input construction,
|
|
555
555
|
tool execution, message history, and structured output parsing. Uses the
|
|
556
556
|
`client.responses.create()` API (from the OpenAI Responses API, distinct from
|
|
@@ -566,7 +566,7 @@ These modules use the standard `openai` SDK for direct API interactions with fin
|
|
|
566
566
|
Centralizes OpenAI API configuration with environment variable support.
|
|
567
567
|
Creates configured OpenAI clients with consistent settings.
|
|
568
568
|
|
|
569
|
-
- **`openai_sdk_helpers.structure.
|
|
569
|
+
- **`openai_sdk_helpers.structure.StructureBase`**
|
|
570
570
|
Pydantic-based foundation for all structured outputs. Provides JSON schema
|
|
571
571
|
generation, validation, and serialization helpers.
|
|
572
572
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
openai_sdk_helpers/__init__.py,sha256=ZvcdJWHP7oMRxSGemxgO7CIpF0dc6oBTh4oftZAYv3c,4640
|
|
2
|
+
openai_sdk_helpers/cli.py,sha256=YnQz-IcAqcBdh8eCCxVYa7NHDuHgHaU-PJ4FWPvkz58,8278
|
|
3
|
+
openai_sdk_helpers/config.py,sha256=xK_u0YNKgtPrLrZrVr4F4k0CvSuYbsmkqqw9mCMdyF8,10932
|
|
4
|
+
openai_sdk_helpers/context_manager.py,sha256=QqlrtenwKoz2krY0IzuToKdTX1HptUYtIEylxieybgY,6633
|
|
5
|
+
openai_sdk_helpers/deprecation.py,sha256=VF0VDDegawYhsu5f-vE6dop9ob-jv8egxsm0KsPvP9E,4753
|
|
6
|
+
openai_sdk_helpers/environment.py,sha256=PqH9viiGIgRAiwU8xPPWlE25KbgSBLmE6nj7S8izCV4,1491
|
|
7
|
+
openai_sdk_helpers/errors.py,sha256=0TLrcpRXPBvk2KlrU5I1VAQl-sYy-d15h_SMDkEawvI,2757
|
|
8
|
+
openai_sdk_helpers/files_api.py,sha256=uMKHvGg1Od0J95Izl3AG9ofQYq8EDJXEty7zP0oKjJM,12569
|
|
9
|
+
openai_sdk_helpers/logging_config.py,sha256=JcR0FTWht1tYdwD-bXH835pr0JV0RwHfY3poruiZGHM,795
|
|
10
|
+
openai_sdk_helpers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
openai_sdk_helpers/retry.py,sha256=J10oQYphfzDXm3BnLoXwxk7PAhN93TC2LQOv0VDGOwI,6533
|
|
12
|
+
openai_sdk_helpers/tools.py,sha256=Awj5htt1ImBbNToM1u6qdrIZ-7MiPZAXZ_oKKiWivy8,10547
|
|
13
|
+
openai_sdk_helpers/types.py,sha256=xzldCRfwCZ3rZl18IBmfgA-PVdoZKSWNrlSIhirumSo,1451
|
|
14
|
+
openai_sdk_helpers/agent/__init__.py,sha256=rWJks5wZ-AP1vsZoxROXCeVen_twE269FJLqdpNIKS0,1086
|
|
15
|
+
openai_sdk_helpers/agent/base.py,sha256=5G2ELmdR8wPOLuppzqDzflW2se7pSmfYEf9_drcSN9I,20914
|
|
16
|
+
openai_sdk_helpers/agent/config.py,sha256=SOEX0-G0jDgrCNiHFYCMCk-K-oP4fWapTxtDvgF7FXc,15939
|
|
17
|
+
openai_sdk_helpers/agent/coordination.py,sha256=VTzyl4RV1q4ugiyFW4Fj7pOAVVO0bMRD63PfQRDwfoQ,18030
|
|
18
|
+
openai_sdk_helpers/agent/prompt_utils.py,sha256=-1M66tqQxh9wWCFg6X-K7cCcqauca3yA04ZjvOpN3bA,337
|
|
19
|
+
openai_sdk_helpers/agent/runner.py,sha256=aOVN1OYKK5_u7oFBqRCOOeTgcb-lLl4kZGxuPLmJrMw,4884
|
|
20
|
+
openai_sdk_helpers/agent/summarizer.py,sha256=lg_PLB1DSHox3PNDgiCzvCPM5VoCUbKEMGy1gqUvl8Y,4168
|
|
21
|
+
openai_sdk_helpers/agent/translator.py,sha256=3u7er1GhUGdy7OMa3A_vyqFFZfev3XBCZW_6w5OwYVc,6286
|
|
22
|
+
openai_sdk_helpers/agent/utils.py,sha256=DTD5foCqGYfXf13F2bZMYIQROl7SbDSy5GDPGi0Zl-0,1089
|
|
23
|
+
openai_sdk_helpers/agent/validation.py,sha256=6NHZIFaUOqRZeYqvRBnDc_uApAV3YHJnOhLHKbVUsi0,5094
|
|
24
|
+
openai_sdk_helpers/agent/search/__init__.py,sha256=xqosfzH4HcBs9IFZks9msG_694rS5q6Ea4_qNeRQRmU,798
|
|
25
|
+
openai_sdk_helpers/agent/search/base.py,sha256=VokTw3-V2yxGzm2WzlcvU100h3UaeyGslCFwIgMvJwI,10146
|
|
26
|
+
openai_sdk_helpers/agent/search/vector.py,sha256=i5nWUvEE9eAv41FwbMT52uORZ7OHCEc8d4F6qH-klCc,14282
|
|
27
|
+
openai_sdk_helpers/agent/search/web.py,sha256=7rYvFAZ1S00IaFPcneEOP2yY2vKIvYdnJvAbVTRbESc,10767
|
|
28
|
+
openai_sdk_helpers/enums/__init__.py,sha256=aFf79C4JBeLC3kMlJfSpehyjx5uNCtW6eK5rD6ZFfhM,322
|
|
29
|
+
openai_sdk_helpers/enums/base.py,sha256=cNllDtzcgI0_eZYXxFko14yhxwicX6xbeDfz9gFE3qo,2753
|
|
30
|
+
openai_sdk_helpers/prompt/__init__.py,sha256=MOqgKwG9KLqKudoKRlUfLxiSmdOi2aD6hNrWDFqLHkk,418
|
|
31
|
+
openai_sdk_helpers/prompt/base.py,sha256=6X0zeopEvO0ba8207O8Nnj1QvFZEZier7kNNh4qkcmE,7782
|
|
32
|
+
openai_sdk_helpers/prompt/summarizer.jinja,sha256=jliSetWDISbql1EkWi1RB8-L_BXUg8JMkRRsPRHuzbY,309
|
|
33
|
+
openai_sdk_helpers/prompt/translator.jinja,sha256=SZhW8ipEzM-9IA4wyS_r2wIMTAclWrilmk1s46njoL0,291
|
|
34
|
+
openai_sdk_helpers/prompt/validator.jinja,sha256=6t8q_IdxFd3mVBGX6SFKNOert1Wo3YpTOji2SNEbbtE,547
|
|
35
|
+
openai_sdk_helpers/response/__init__.py,sha256=Rh3tBygneOhS-Er_4dtX4Xa69ukvxYv01brq26VpgwQ,1886
|
|
36
|
+
openai_sdk_helpers/response/base.py,sha256=OA1p9h6EIzwt8VCWFXEalaQHOe0_eZDefqs5jQKu-vU,34844
|
|
37
|
+
openai_sdk_helpers/response/config.py,sha256=KsfLKnh8mPTn15l26JK_BCqPj3CqyArW-L30ceYRNpk,8903
|
|
38
|
+
openai_sdk_helpers/response/files.py,sha256=6iHXeNZg4R08ilQ7D53qIJDQGYPpTLcByAhNJlEwbZ4,13226
|
|
39
|
+
openai_sdk_helpers/response/messages.py,sha256=qX3sW79rLuJEys28zyv5MovZikwGOaLevzdVN0VYMRE,10104
|
|
40
|
+
openai_sdk_helpers/response/runner.py,sha256=Rg8XmxU5UwxJc3MjPlYlXWDimxy_cjxzefGiruNZK6s,4269
|
|
41
|
+
openai_sdk_helpers/response/tool_call.py,sha256=c9Filh4IG5H_RWuJlYl6KUZDaF7mCjkabFRQMNiz7zM,7422
|
|
42
|
+
openai_sdk_helpers/response/vector_store.py,sha256=cG5Mzdhjw5FsX1phgclIGz2MQ8f8uMKBaage1O2EZQU,3074
|
|
43
|
+
openai_sdk_helpers/streamlit_app/__init__.py,sha256=RjJbnBDS5_YmAmxvaa3phB5u9UcXsXDEk_jMlY_pa5Q,793
|
|
44
|
+
openai_sdk_helpers/streamlit_app/app.py,sha256=jNkMQ4zkfojP501qk_vncyLN4TymiDXxA3cXkUvBfsw,17402
|
|
45
|
+
openai_sdk_helpers/streamlit_app/config.py,sha256=Jla8IoKsazHBq71pDFUGEv8W23WE18GSmAKcTI5LCww,16042
|
|
46
|
+
openai_sdk_helpers/streamlit_app/streamlit_web_search.py,sha256=21xhBhdTsqK6ybPcLzSKSLOVeK8a3x9y_rRNvNBOAGM,2812
|
|
47
|
+
openai_sdk_helpers/structure/__init__.py,sha256=jROw0IbXYVRD2Eb3dBMsB6amQZrX8X7XSgGh_zjsZWc,3469
|
|
48
|
+
openai_sdk_helpers/structure/agent_blueprint.py,sha256=VyJWkgPNzAYKRDMeR1M4kE6qqQURnwqtrrEn0TRJf0g,9698
|
|
49
|
+
openai_sdk_helpers/structure/base.py,sha256=7JuHxKkLR5gP0RWGQIjOQlvySfain6LrB4-zHb0oFxo,25298
|
|
50
|
+
openai_sdk_helpers/structure/prompt.py,sha256=Pp3j-fOG0SWQO5Ts9zS86n8cveSB6kWzSGHW6J9MlcY,1075
|
|
51
|
+
openai_sdk_helpers/structure/responses.py,sha256=eqCcW4d8lwhUF5kzHMA4FR9uNkaBHl8CuZk7a8YrenI,4868
|
|
52
|
+
openai_sdk_helpers/structure/summary.py,sha256=iP1uffqve18B9HXceP4rV0Ho5AaDZXMmC66tRKDNx3c,3143
|
|
53
|
+
openai_sdk_helpers/structure/translation.py,sha256=rBSzGBX6hGaETD43340z9MbKGsxWekjRD4xEZz67SnI,712
|
|
54
|
+
openai_sdk_helpers/structure/validation.py,sha256=D03rlyBDn22qNjTGaGsjhsk3g50oPmzYMFqycYF2_CU,2409
|
|
55
|
+
openai_sdk_helpers/structure/vector_search.py,sha256=XNQsG6_-c7X6TpXjqWOdKCmqXatX1gwd0zq-hII3cz4,5782
|
|
56
|
+
openai_sdk_helpers/structure/web_search.py,sha256=8ETWc2G1eO3dWkNQrs5rsxvHHyhyG1puEYUVRNCLUYI,4572
|
|
57
|
+
openai_sdk_helpers/structure/plan/__init__.py,sha256=IGr0Tk4inN_8o7fT2N02_FTi6U6l2T9_npcQHAlBwKA,1076
|
|
58
|
+
openai_sdk_helpers/structure/plan/enum.py,sha256=seESSwH-IeeW-9BqIMUQyk3qjtchfU3TDhF9HPDB1OM,3079
|
|
59
|
+
openai_sdk_helpers/structure/plan/helpers.py,sha256=Vc6dBTMFrNWlsaCTpEImEIKjfFq4BSSxNjB4K8dywOQ,5139
|
|
60
|
+
openai_sdk_helpers/structure/plan/plan.py,sha256=CStfSfCdcv7HfLWV_G09xElJvq_kAKi_6JDkB3I7cSI,9663
|
|
61
|
+
openai_sdk_helpers/structure/plan/task.py,sha256=FSdt2OJ_arC60zMoWIUHMT3U1syWM_7svyTpOIwiRSM,4580
|
|
62
|
+
openai_sdk_helpers/structure/plan/types.py,sha256=7y9QEVdZreQUXV7n-R4RoNZzw5HeOVbJGWx9QkSfuNY,418
|
|
63
|
+
openai_sdk_helpers/utils/__init__.py,sha256=le6bj7RDCM5IQv8lh2mJ1dlnUggwhsNGM_zFYba_4PM,3670
|
|
64
|
+
openai_sdk_helpers/utils/async_utils.py,sha256=9KbPEVfi6IXdbwkTUE0h5DleK8TI7I6P_VPL8UgUv98,3689
|
|
65
|
+
openai_sdk_helpers/utils/coercion.py,sha256=Pq1u7tAbD7kTZ84lK-7Fb9CyYKKKQt4fypG5BlSI6oQ,3774
|
|
66
|
+
openai_sdk_helpers/utils/deprecation.py,sha256=VF0VDDegawYhsu5f-vE6dop9ob-jv8egxsm0KsPvP9E,4753
|
|
67
|
+
openai_sdk_helpers/utils/encoding.py,sha256=oDtlNGZ5p-edXiHW76REs-0-8NXkQNReKJdj6sHLkt8,4615
|
|
68
|
+
openai_sdk_helpers/utils/instructions.py,sha256=trbjxjxv2otQR9VmBsPFk1_CJj8nA85Sgtj_5QmQOKI,942
|
|
69
|
+
openai_sdk_helpers/utils/output_validation.py,sha256=3DC6Hr6vAFx_bQGaLsxkGN_LuKe_MugLpVogMBgG9tc,12621
|
|
70
|
+
openai_sdk_helpers/utils/path_utils.py,sha256=NOSX7553cc8LqxbnvmdYjgDBi5Le2W2LuMINwFsTzyM,1969
|
|
71
|
+
openai_sdk_helpers/utils/registry.py,sha256=qJrhPRbrw3y0gaqvsdUz2IsTRxClWZ4oLqHwhxTJjUc,5873
|
|
72
|
+
openai_sdk_helpers/utils/validation.py,sha256=ZjnZNOy5AoFlszRxarNol6YZwfgw6LnwPtkCekZmwAU,7826
|
|
73
|
+
openai_sdk_helpers/utils/json/__init__.py,sha256=wBm1DBgfy_n1uSUcnCPyqBn_cCq41mijjPigSMZJZqg,2118
|
|
74
|
+
openai_sdk_helpers/utils/json/base_model.py,sha256=8j__oKly46RRekmRjwFZjAxBHhZkIjMADcJReKo-QsQ,5100
|
|
75
|
+
openai_sdk_helpers/utils/json/data_class.py,sha256=hffMQQTNTwybuMTOtmKNzxd6kXrVyQen67F5BE_OGqE,6469
|
|
76
|
+
openai_sdk_helpers/utils/json/ref.py,sha256=jIzv3M96G1b9x2tW8JZBqKBxAsE3bUhVmMADBFH6Jb4,2806
|
|
77
|
+
openai_sdk_helpers/utils/json/utils.py,sha256=iyc25tnObqXQJWPKLZMVts932GArdKer59KuC8aQKsY,5948
|
|
78
|
+
openai_sdk_helpers/vector_storage/__init__.py,sha256=L5LxO09puh9_yBB9IDTvc1CvVkARVkHqYY1KX3inB4c,975
|
|
79
|
+
openai_sdk_helpers/vector_storage/cleanup.py,sha256=ImWIE-9lli-odD8qIARvmeaa0y8ZD4pYYP-kT0O3178,3552
|
|
80
|
+
openai_sdk_helpers/vector_storage/storage.py,sha256=A6zJDicObdSOVSlzhHVxEGq_tKO2_bNcsYi94xsKDNI,23655
|
|
81
|
+
openai_sdk_helpers/vector_storage/types.py,sha256=jTCcOYMeOpZWvcse0z4T3MVs-RBOPC-fqWTBeQrgafU,1639
|
|
82
|
+
openai_sdk_helpers-0.4.0.dist-info/METADATA,sha256=bRSOBilp9Y0zr8r2VNKSMTJHSBWoV2aH_HQw7diindo,23557
|
|
83
|
+
openai_sdk_helpers-0.4.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
84
|
+
openai_sdk_helpers-0.4.0.dist-info/entry_points.txt,sha256=gEOD1ZeXe8d2OP-KzUlG-b_9D9yUZTCt-GFW3EDbIIY,63
|
|
85
|
+
openai_sdk_helpers-0.4.0.dist-info/licenses/LICENSE,sha256=CUhc1NrE50bs45tcXF7OcTQBKEvkUuLqeOHgrWQ5jaA,1067
|
|
86
|
+
openai_sdk_helpers-0.4.0.dist-info/RECORD,,
|