openai-sdk-helpers 0.2.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 +4 -2
- openai_sdk_helpers/agent/base.py +391 -106
- openai_sdk_helpers/agent/config.py +405 -44
- openai_sdk_helpers/agent/coordination.py +68 -31
- openai_sdk_helpers/agent/runner.py +29 -19
- openai_sdk_helpers/agent/search/base.py +103 -54
- openai_sdk_helpers/agent/search/vector.py +99 -68
- openai_sdk_helpers/agent/search/web.py +84 -50
- openai_sdk_helpers/agent/summarizer.py +33 -7
- openai_sdk_helpers/agent/translator.py +58 -24
- openai_sdk_helpers/agent/validation.py +35 -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 +161 -22
- openai_sdk_helpers/response/config.py +50 -200
- 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/instructions.py +35 -0
- 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} +43 -70
- 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 +194 -0
- openai_sdk_helpers/vector_storage/storage.py +10 -0
- {openai_sdk_helpers-0.2.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.2.0.dist-info/RECORD +0 -79
- {openai_sdk_helpers-0.2.0.dist-info → openai_sdk_helpers-0.4.0.dist-info}/WHEEL +0 -0
- {openai_sdk_helpers-0.2.0.dist-info → openai_sdk_helpers-0.4.0.dist-info}/entry_points.txt +0 -0
- {openai_sdk_helpers-0.2.0.dist-info → openai_sdk_helpers-0.4.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""OpenAI response and tool helpers for structured outputs.
|
|
2
2
|
|
|
3
3
|
This module provides helper functions for creating OpenAI API response formats
|
|
4
|
-
and tool definitions from
|
|
4
|
+
and tool definitions from StructureBase classes. These helpers simplify the
|
|
5
5
|
process of configuring structured outputs for both Assistant and chat
|
|
6
6
|
completion APIs.
|
|
7
7
|
"""
|
|
@@ -13,12 +13,12 @@ from openai.types.responses.response_format_text_json_schema_config_param import
|
|
|
13
13
|
)
|
|
14
14
|
from openai.types.responses.response_text_config_param import ResponseTextConfigParam
|
|
15
15
|
|
|
16
|
-
from .base import
|
|
16
|
+
from .base import StructureBase
|
|
17
17
|
from ..utils import log
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def assistant_tool_definition(
|
|
21
|
-
structure: type[
|
|
21
|
+
structure: type[StructureBase], name: str, description: str
|
|
22
22
|
) -> dict:
|
|
23
23
|
"""Build a function tool definition for OpenAI Assistants.
|
|
24
24
|
|
|
@@ -27,7 +27,7 @@ def assistant_tool_definition(
|
|
|
27
27
|
|
|
28
28
|
Parameters
|
|
29
29
|
----------
|
|
30
|
-
structure : type[
|
|
30
|
+
structure : type[StructureBase]
|
|
31
31
|
Structure class that defines the tool schema.
|
|
32
32
|
name : str
|
|
33
33
|
Name of the function tool.
|
|
@@ -41,9 +41,9 @@ def assistant_tool_definition(
|
|
|
41
41
|
|
|
42
42
|
Examples
|
|
43
43
|
--------
|
|
44
|
-
>>> from openai_sdk_helpers.structure import
|
|
44
|
+
>>> from openai_sdk_helpers.structure import StructureBase
|
|
45
45
|
>>> tool = assistant_tool_definition(
|
|
46
|
-
...
|
|
46
|
+
... StructureBase,
|
|
47
47
|
... "process_data",
|
|
48
48
|
... "Process input data"
|
|
49
49
|
... )
|
|
@@ -59,7 +59,7 @@ def assistant_tool_definition(
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
def assistant_format(structure: type[
|
|
62
|
+
def assistant_format(structure: type[StructureBase]) -> dict:
|
|
63
63
|
"""Build a response format definition for OpenAI Assistants.
|
|
64
64
|
|
|
65
65
|
Creates a response format specification that instructs the Assistant API
|
|
@@ -67,7 +67,7 @@ def assistant_format(structure: type[BaseStructure]) -> dict:
|
|
|
67
67
|
|
|
68
68
|
Parameters
|
|
69
69
|
----------
|
|
70
|
-
structure : type[
|
|
70
|
+
structure : type[StructureBase]
|
|
71
71
|
Structure class that defines the response schema.
|
|
72
72
|
|
|
73
73
|
Returns
|
|
@@ -77,7 +77,7 @@ def assistant_format(structure: type[BaseStructure]) -> dict:
|
|
|
77
77
|
|
|
78
78
|
Examples
|
|
79
79
|
--------
|
|
80
|
-
>>> format_def = assistant_format(
|
|
80
|
+
>>> format_def = assistant_format(StructureBase)
|
|
81
81
|
"""
|
|
82
82
|
log(f"{structure.__name__}::assistant_format")
|
|
83
83
|
return {
|
|
@@ -90,7 +90,7 @@ def assistant_format(structure: type[BaseStructure]) -> dict:
|
|
|
90
90
|
|
|
91
91
|
|
|
92
92
|
def response_tool_definition(
|
|
93
|
-
structure: type[
|
|
93
|
+
structure: type[StructureBase],
|
|
94
94
|
tool_name: str,
|
|
95
95
|
tool_description: str,
|
|
96
96
|
) -> dict:
|
|
@@ -101,7 +101,7 @@ def response_tool_definition(
|
|
|
101
101
|
|
|
102
102
|
Parameters
|
|
103
103
|
----------
|
|
104
|
-
structure : type[
|
|
104
|
+
structure : type[StructureBase]
|
|
105
105
|
Structure class that defines the tool schema.
|
|
106
106
|
tool_name : str
|
|
107
107
|
Name of the function tool.
|
|
@@ -116,7 +116,7 @@ def response_tool_definition(
|
|
|
116
116
|
Examples
|
|
117
117
|
--------
|
|
118
118
|
>>> tool = response_tool_definition(
|
|
119
|
-
...
|
|
119
|
+
... StructureBase,
|
|
120
120
|
... "analyze",
|
|
121
121
|
... "Analyze data"
|
|
122
122
|
... )
|
|
@@ -132,7 +132,7 @@ def response_tool_definition(
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
|
|
135
|
-
def response_format(structure: type[
|
|
135
|
+
def response_format(structure: type[StructureBase]) -> ResponseTextConfigParam:
|
|
136
136
|
"""Build a response format for OpenAI chat completions.
|
|
137
137
|
|
|
138
138
|
Creates a response format specification that instructs the chat
|
|
@@ -140,7 +140,7 @@ def response_format(structure: type[BaseStructure]) -> ResponseTextConfigParam:
|
|
|
140
140
|
|
|
141
141
|
Parameters
|
|
142
142
|
----------
|
|
143
|
-
structure : type[
|
|
143
|
+
structure : type[StructureBase]
|
|
144
144
|
Structure class that defines the response schema.
|
|
145
145
|
|
|
146
146
|
Returns
|
|
@@ -150,7 +150,7 @@ def response_format(structure: type[BaseStructure]) -> ResponseTextConfigParam:
|
|
|
150
150
|
|
|
151
151
|
Examples
|
|
152
152
|
--------
|
|
153
|
-
>>> format_spec = response_format(
|
|
153
|
+
>>> format_spec = response_format(StructureBase)
|
|
154
154
|
"""
|
|
155
155
|
log(f"{structure.__name__}::response_format")
|
|
156
156
|
response_format_text_JSONSchema_config_param = (
|
|
@@ -6,10 +6,10 @@ including topic-level summaries with citations and consolidated text summaries.
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
-
from .base import
|
|
9
|
+
from .base import StructureBase, spec_field
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class SummaryTopic(
|
|
12
|
+
class SummaryTopic(StructureBase):
|
|
13
13
|
"""Capture a topic-level summary with supporting citations.
|
|
14
14
|
|
|
15
15
|
Represents a single topic or micro-trend identified in source excerpts,
|
|
@@ -55,7 +55,7 @@ class SummaryTopic(BaseStructure):
|
|
|
55
55
|
)
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
class SummaryStructure(
|
|
58
|
+
class SummaryStructure(StructureBase):
|
|
59
59
|
"""Consolidated summary returned by the summarizer agent.
|
|
60
60
|
|
|
61
61
|
Represents a synthesized summary text derived from multiple source excerpts.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Structured output model for translations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .base import StructureBase, spec_field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TranslationStructure(StructureBase):
|
|
9
|
+
"""Structured representation of translated text.
|
|
10
|
+
|
|
11
|
+
Attributes
|
|
12
|
+
----------
|
|
13
|
+
text : str
|
|
14
|
+
Translated text output from the agent.
|
|
15
|
+
|
|
16
|
+
Methods
|
|
17
|
+
-------
|
|
18
|
+
print()
|
|
19
|
+
Return the formatted model fields.
|
|
20
|
+
|
|
21
|
+
Examples
|
|
22
|
+
--------
|
|
23
|
+
>>> translation = TranslationStructure(text="Hola mundo")
|
|
24
|
+
>>> print(translation.text)
|
|
25
|
+
'Hola mundo'
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
text: str = spec_field(
|
|
29
|
+
"text",
|
|
30
|
+
description="Translated text output from the agent.",
|
|
31
|
+
examples=["Hola mundo", "Bonjour le monde"],
|
|
32
|
+
)
|
|
@@ -6,10 +6,10 @@ validation checks on user inputs and agent outputs.
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
-
from .base import
|
|
9
|
+
from .base import StructureBase, spec_field
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class ValidationResultStructure(
|
|
12
|
+
class ValidationResultStructure(StructureBase):
|
|
13
13
|
"""Capture guardrail validation findings for user and agent messages.
|
|
14
14
|
|
|
15
15
|
Represents the results of safety and policy validation checks performed
|
|
@@ -7,10 +7,10 @@ workflows with error tracking and result aggregation.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
from .base import
|
|
10
|
+
from .base import StructureBase, spec_field
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class VectorSearchItemStructure(
|
|
13
|
+
class VectorSearchItemStructure(StructureBase):
|
|
14
14
|
"""A single vector search to perform.
|
|
15
15
|
|
|
16
16
|
Represents one vector search query with rationale for its inclusion
|
|
@@ -35,7 +35,7 @@ class VectorSearchItemStructure(BaseStructure):
|
|
|
35
35
|
query: str = spec_field("query")
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
class VectorSearchPlanStructure(
|
|
38
|
+
class VectorSearchPlanStructure(StructureBase):
|
|
39
39
|
"""Collection of vector searches required to satisfy the query.
|
|
40
40
|
|
|
41
41
|
Represents a plan containing multiple vector searches that together
|
|
@@ -56,7 +56,7 @@ class VectorSearchPlanStructure(BaseStructure):
|
|
|
56
56
|
searches: list[VectorSearchItemStructure] = spec_field("searches")
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
class VectorSearchItemResultStructure(
|
|
59
|
+
class VectorSearchItemResultStructure(StructureBase):
|
|
60
60
|
"""Result of a single vector search.
|
|
61
61
|
|
|
62
62
|
Contains the text results retrieved from executing one vector search query.
|
|
@@ -74,7 +74,7 @@ class VectorSearchItemResultStructure(BaseStructure):
|
|
|
74
74
|
texts: list[str] = spec_field("texts")
|
|
75
75
|
|
|
76
76
|
|
|
77
|
-
class VectorSearchItemResultsStructure(
|
|
77
|
+
class VectorSearchItemResultsStructure(StructureBase):
|
|
78
78
|
"""Collection of search results from multiple queries.
|
|
79
79
|
|
|
80
80
|
Aggregates results from multiple vector searches while tracking any
|
|
@@ -119,7 +119,7 @@ class VectorSearchItemResultsStructure(BaseStructure):
|
|
|
119
119
|
self.item_results.append(item)
|
|
120
120
|
|
|
121
121
|
|
|
122
|
-
class VectorSearchReportStructure(
|
|
122
|
+
class VectorSearchReportStructure(StructureBase):
|
|
123
123
|
"""Structured output from the vector search writer agent.
|
|
124
124
|
|
|
125
125
|
Contains the final synthesized report from vector search results,
|
|
@@ -152,7 +152,7 @@ class VectorSearchReportStructure(BaseStructure):
|
|
|
152
152
|
sources: list[str] = spec_field("sources")
|
|
153
153
|
|
|
154
154
|
|
|
155
|
-
class VectorSearchStructure(
|
|
155
|
+
class VectorSearchStructure(StructureBase):
|
|
156
156
|
"""Complete output of a vector search workflow.
|
|
157
157
|
|
|
158
158
|
Represents the full lifecycle of a vector search operation, from the
|
|
@@ -7,10 +7,10 @@ workflows with comprehensive reporting.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
from .base import
|
|
10
|
+
from .base import StructureBase, spec_field
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class WebSearchReportStructure(
|
|
13
|
+
class WebSearchReportStructure(StructureBase):
|
|
14
14
|
"""Structured output from the web search writer agent.
|
|
15
15
|
|
|
16
16
|
Contains the final synthesized report from web search results,
|
|
@@ -43,7 +43,7 @@ class WebSearchReportStructure(BaseStructure):
|
|
|
43
43
|
sources: list[str] = spec_field("sources")
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
class WebSearchItemStructure(
|
|
46
|
+
class WebSearchItemStructure(StructureBase):
|
|
47
47
|
"""A single web search to perform.
|
|
48
48
|
|
|
49
49
|
Represents one web search query with rationale for its inclusion
|
|
@@ -68,7 +68,7 @@ class WebSearchItemStructure(BaseStructure):
|
|
|
68
68
|
query: str = spec_field("query")
|
|
69
69
|
|
|
70
70
|
|
|
71
|
-
class WebSearchItemResultStructure(
|
|
71
|
+
class WebSearchItemResultStructure(StructureBase):
|
|
72
72
|
"""Result of a single web search.
|
|
73
73
|
|
|
74
74
|
Contains the text content retrieved from executing one web search query.
|
|
@@ -86,7 +86,7 @@ class WebSearchItemResultStructure(BaseStructure):
|
|
|
86
86
|
text: str = spec_field("text")
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
class WebSearchPlanStructure(
|
|
89
|
+
class WebSearchPlanStructure(StructureBase):
|
|
90
90
|
"""Collection of web searches required to satisfy the query.
|
|
91
91
|
|
|
92
92
|
Represents a plan containing multiple web searches that together
|
|
@@ -107,7 +107,7 @@ class WebSearchPlanStructure(BaseStructure):
|
|
|
107
107
|
searches: list[WebSearchItemStructure] = spec_field("searches")
|
|
108
108
|
|
|
109
109
|
|
|
110
|
-
class WebSearchStructure(
|
|
110
|
+
class WebSearchStructure(StructureBase):
|
|
111
111
|
"""Complete output of a web search workflow.
|
|
112
112
|
|
|
113
113
|
Represents the full lifecycle of a web search operation, from the
|
openai_sdk_helpers/tools.py
CHANGED
|
@@ -10,19 +10,21 @@ definitions from named metadata structures.
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
+
import asyncio
|
|
13
14
|
import inspect
|
|
15
|
+
import threading
|
|
14
16
|
from dataclasses import dataclass
|
|
15
17
|
from typing import Any, Callable, TypeAlias, TypeVar
|
|
16
18
|
|
|
17
19
|
from pydantic import BaseModel, ValidationError
|
|
18
20
|
|
|
19
21
|
from openai_sdk_helpers.response.tool_call import parse_tool_arguments
|
|
20
|
-
from openai_sdk_helpers.structure.base import
|
|
22
|
+
from openai_sdk_helpers.structure.base import StructureBase
|
|
21
23
|
from openai_sdk_helpers.utils import coerce_jsonable, customJSONEncoder
|
|
22
24
|
import json
|
|
23
25
|
|
|
24
26
|
T = TypeVar("T", bound=BaseModel)
|
|
25
|
-
StructureType: TypeAlias = type[
|
|
27
|
+
StructureType: TypeAlias = type[StructureBase]
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
def serialize_tool_result(result: Any) -> str:
|
|
@@ -81,7 +83,7 @@ def tool_handler_factory(
|
|
|
81
83
|
The returned handler:
|
|
82
84
|
1. Parses tool_call.arguments using parse_tool_arguments
|
|
83
85
|
2. Validates arguments with input_model if provided
|
|
84
|
-
3. Calls func with validated/parsed arguments
|
|
86
|
+
3. Calls func with validated/parsed arguments (handles both sync and async)
|
|
85
87
|
4. Serializes the result using serialize_tool_result
|
|
86
88
|
|
|
87
89
|
Parameters
|
|
@@ -124,7 +126,13 @@ def tool_handler_factory(
|
|
|
124
126
|
... limit: int = 10
|
|
125
127
|
>>> def search_tool(query: str, limit: int = 10):
|
|
126
128
|
... return {"results": [f"Result for {query}"]}
|
|
127
|
-
>>> handler = tool_handler_factory(search_tool, SearchInput)
|
|
129
|
+
>>> handler = tool_handler_factory(search_tool, input_model=SearchInput)
|
|
130
|
+
|
|
131
|
+
With async function:
|
|
132
|
+
|
|
133
|
+
>>> async def async_search_tool(query: str, limit: int = 10):
|
|
134
|
+
... return {"results": [f"Result for {query}"]}
|
|
135
|
+
>>> handler = tool_handler_factory(async_search_tool)
|
|
128
136
|
|
|
129
137
|
The handler can then be used with OpenAI tool calls:
|
|
130
138
|
|
|
@@ -135,6 +143,7 @@ def tool_handler_factory(
|
|
|
135
143
|
>>> tool_call = ToolCall()
|
|
136
144
|
>>> result = handler(tool_call) # doctest: +SKIP
|
|
137
145
|
"""
|
|
146
|
+
is_async = inspect.iscoroutinefunction(func)
|
|
138
147
|
|
|
139
148
|
def handler(tool_call: Any) -> str:
|
|
140
149
|
"""Handle tool execution with parsing, validation, and serialization.
|
|
@@ -170,15 +179,32 @@ def tool_handler_factory(
|
|
|
170
179
|
else:
|
|
171
180
|
call_kwargs = parsed_args
|
|
172
181
|
|
|
173
|
-
# Execute function (sync
|
|
174
|
-
if
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
+
# Execute function (sync or async with event loop detection)
|
|
183
|
+
if is_async:
|
|
184
|
+
# Handle async function with proper event loop detection
|
|
185
|
+
try:
|
|
186
|
+
loop = asyncio.get_running_loop()
|
|
187
|
+
# We're inside an event loop, need to run in thread
|
|
188
|
+
result_holder: dict[str, Any] = {"value": None, "exception": None}
|
|
189
|
+
|
|
190
|
+
def _thread_func() -> None:
|
|
191
|
+
try:
|
|
192
|
+
result_holder["value"] = asyncio.run(func(**call_kwargs))
|
|
193
|
+
except Exception as exc:
|
|
194
|
+
result_holder["exception"] = exc
|
|
195
|
+
|
|
196
|
+
thread = threading.Thread(target=_thread_func)
|
|
197
|
+
thread.start()
|
|
198
|
+
thread.join()
|
|
199
|
+
|
|
200
|
+
if result_holder["exception"]:
|
|
201
|
+
raise result_holder["exception"]
|
|
202
|
+
result = result_holder["value"]
|
|
203
|
+
except RuntimeError:
|
|
204
|
+
# No event loop running, can use asyncio.run directly
|
|
205
|
+
result = asyncio.run(func(**call_kwargs))
|
|
206
|
+
else:
|
|
207
|
+
result = func(**call_kwargs)
|
|
182
208
|
|
|
183
209
|
# Serialize result
|
|
184
210
|
return serialize_tool_result(result)
|
|
@@ -200,14 +226,14 @@ class ToolSpec:
|
|
|
200
226
|
Attributes
|
|
201
227
|
----------
|
|
202
228
|
structure : StructureType
|
|
203
|
-
The
|
|
229
|
+
The StructureBase class that defines the tool's input parameter schema.
|
|
204
230
|
Used to generate the OpenAI tool definition.
|
|
205
231
|
tool_name : str
|
|
206
232
|
Name identifier for the tool.
|
|
207
233
|
tool_description : str
|
|
208
234
|
Human-readable description of what the tool does.
|
|
209
235
|
output_structure : StructureType or None, default=None
|
|
210
|
-
Optional
|
|
236
|
+
Optional StructureBase class that defines the tool's output schema.
|
|
211
237
|
This is for documentation/reference only and is not sent to OpenAI.
|
|
212
238
|
Useful when a tool accepts one type of input but returns a different
|
|
213
239
|
structured output.
|
|
@@ -21,8 +21,8 @@ coercion
|
|
|
21
21
|
Numeric coercion helpers and list normalization.
|
|
22
22
|
path_utils
|
|
23
23
|
File and path helpers.
|
|
24
|
-
|
|
25
|
-
JSON encoding helpers and mixins.
|
|
24
|
+
json
|
|
25
|
+
JSON encoding helpers and mixins for dataclasses and Pydantic models.
|
|
26
26
|
logging_config
|
|
27
27
|
Centralized logger factory and convenience log helper.
|
|
28
28
|
validation
|
|
@@ -45,11 +45,18 @@ from .coercion import (
|
|
|
45
45
|
coerce_optional_int,
|
|
46
46
|
ensure_list,
|
|
47
47
|
)
|
|
48
|
-
from .
|
|
49
|
-
|
|
48
|
+
from .json import (
|
|
49
|
+
BaseModelJSONSerializable,
|
|
50
|
+
DataclassJSONSerializable,
|
|
50
51
|
coerce_jsonable,
|
|
51
52
|
customJSONEncoder,
|
|
53
|
+
decode_module_qualname,
|
|
54
|
+
encode_module_qualname,
|
|
55
|
+
get_module_qualname,
|
|
56
|
+
to_jsonable,
|
|
52
57
|
)
|
|
58
|
+
from .registry import BaseRegistry
|
|
59
|
+
|
|
53
60
|
from .path_utils import check_filepath, ensure_directory
|
|
54
61
|
from openai_sdk_helpers.logging_config import log
|
|
55
62
|
from .validation import (
|
|
@@ -88,9 +95,14 @@ __all__ = [
|
|
|
88
95
|
"coerce_optional_float",
|
|
89
96
|
"coerce_optional_int",
|
|
90
97
|
"coerce_dict",
|
|
98
|
+
"to_jsonable",
|
|
91
99
|
"coerce_jsonable",
|
|
92
|
-
"
|
|
100
|
+
"DataclassJSONSerializable",
|
|
101
|
+
"BaseModelJSONSerializable",
|
|
93
102
|
"customJSONEncoder",
|
|
103
|
+
"get_module_qualname",
|
|
104
|
+
"encode_module_qualname",
|
|
105
|
+
"decode_module_qualname",
|
|
94
106
|
"log",
|
|
95
107
|
# Validation helpers
|
|
96
108
|
"validate_non_empty_string",
|
|
@@ -122,4 +134,6 @@ __all__ = [
|
|
|
122
134
|
"create_image_data_url",
|
|
123
135
|
"create_file_data_url",
|
|
124
136
|
"is_image_file",
|
|
137
|
+
# Registry
|
|
138
|
+
"BaseRegistry",
|
|
125
139
|
]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Utilities for resolving instructions from strings or file paths."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def resolve_instructions_from_path(instructions: str | Path) -> str:
|
|
9
|
+
"""Resolve instructions from a string or file path.
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
instructions : str or Path
|
|
14
|
+
Either plain-text instructions or a path to a file containing
|
|
15
|
+
instructions.
|
|
16
|
+
|
|
17
|
+
Returns
|
|
18
|
+
-------
|
|
19
|
+
str
|
|
20
|
+
The resolved instruction text.
|
|
21
|
+
|
|
22
|
+
Raises
|
|
23
|
+
------
|
|
24
|
+
ValueError
|
|
25
|
+
If instructions is a Path that cannot be read.
|
|
26
|
+
"""
|
|
27
|
+
if isinstance(instructions, Path):
|
|
28
|
+
instruction_path = instructions.expanduser()
|
|
29
|
+
try:
|
|
30
|
+
return instruction_path.read_text(encoding="utf-8")
|
|
31
|
+
except OSError as exc:
|
|
32
|
+
raise ValueError(
|
|
33
|
+
f"Unable to read instructions at '{instruction_path}': {exc}"
|
|
34
|
+
) from exc
|
|
35
|
+
return instructions
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""JSON serialization helpers for dataclasses, Pydantic models, and reference encoding.
|
|
2
|
+
|
|
3
|
+
This package provides consistent to_json/from_json flows and a JSONEncoder that
|
|
4
|
+
handles common types including dataclasses, Pydantic models, and reference encoding.
|
|
5
|
+
|
|
6
|
+
Package Layout
|
|
7
|
+
--------------
|
|
8
|
+
utils.py
|
|
9
|
+
to_jsonable(), coerce_jsonable(), customJSONEncoder.
|
|
10
|
+
data_class.py
|
|
11
|
+
DataclassJSONSerializable mixin with to_json, to_json_file, from_json, from_json_file.
|
|
12
|
+
base_model.py
|
|
13
|
+
BaseModelJSONSerializable for Pydantic, with _serialize_fields/_deserialize_fields hooks.
|
|
14
|
+
ref.py
|
|
15
|
+
Reference helpers get_module_qualname, encode_module_qualname, decode_module_qualname.
|
|
16
|
+
|
|
17
|
+
Public API
|
|
18
|
+
----------
|
|
19
|
+
to_jsonable(value)
|
|
20
|
+
Convert common types to JSON-safe forms; recursive for containers/dicts.
|
|
21
|
+
coerce_jsonable(value)
|
|
22
|
+
Ensures json.dumps succeeds; falls back to str when necessary. Special-cases ResponseBase.
|
|
23
|
+
customJSONEncoder
|
|
24
|
+
json.JSONEncoder subclass delegating to to_jsonable.
|
|
25
|
+
DataclassJSONSerializable
|
|
26
|
+
Mixin adding to_json(), to_json_file(path) -> str, from_json(data) -> T, from_json_file(path) -> T.
|
|
27
|
+
BaseModelJSONSerializable
|
|
28
|
+
Pydantic BaseModel subclass adding to_json() -> dict, to_json_file(path) -> str,
|
|
29
|
+
from_json(data) -> T, from_json_file(path) -> T, plus overridable _serialize_fields(data)
|
|
30
|
+
and _deserialize_fields(data).
|
|
31
|
+
get_module_qualname(obj) -> (module, qualname)
|
|
32
|
+
Safe retrieval.
|
|
33
|
+
encode_module_qualname(obj) -> dict|None
|
|
34
|
+
{module, qualname} for import reconstruction.
|
|
35
|
+
decode_module_qualname(ref) -> object|None
|
|
36
|
+
Import and getattr by encoded reference.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
from __future__ import annotations
|
|
40
|
+
|
|
41
|
+
from .base_model import BaseModelJSONSerializable
|
|
42
|
+
from .data_class import DataclassJSONSerializable
|
|
43
|
+
from .ref import decode_module_qualname, encode_module_qualname, get_module_qualname
|
|
44
|
+
from .utils import coerce_jsonable, customJSONEncoder, to_jsonable
|
|
45
|
+
|
|
46
|
+
__all__ = [
|
|
47
|
+
"to_jsonable",
|
|
48
|
+
"coerce_jsonable",
|
|
49
|
+
"customJSONEncoder",
|
|
50
|
+
"DataclassJSONSerializable",
|
|
51
|
+
"BaseModelJSONSerializable",
|
|
52
|
+
"get_module_qualname",
|
|
53
|
+
"encode_module_qualname",
|
|
54
|
+
"decode_module_qualname",
|
|
55
|
+
]
|