openai-sdk-helpers 0.4.3__py3-none-any.whl → 0.5.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 +41 -7
- openai_sdk_helpers/agent/__init__.py +1 -2
- openai_sdk_helpers/agent/base.py +89 -173
- openai_sdk_helpers/agent/configuration.py +12 -20
- openai_sdk_helpers/agent/coordinator.py +14 -17
- openai_sdk_helpers/agent/runner.py +3 -45
- openai_sdk_helpers/agent/search/base.py +49 -71
- openai_sdk_helpers/agent/search/vector.py +82 -110
- openai_sdk_helpers/agent/search/web.py +103 -81
- openai_sdk_helpers/agent/summarizer.py +20 -28
- openai_sdk_helpers/agent/translator.py +17 -23
- openai_sdk_helpers/agent/validator.py +17 -23
- openai_sdk_helpers/errors.py +9 -0
- openai_sdk_helpers/extract/__init__.py +23 -0
- openai_sdk_helpers/extract/extractor.py +157 -0
- openai_sdk_helpers/extract/generator.py +476 -0
- openai_sdk_helpers/prompt/extractor_config_agent_instructions.jinja +6 -0
- openai_sdk_helpers/prompt/extractor_config_generator.jinja +37 -0
- openai_sdk_helpers/prompt/extractor_config_generator_instructions.jinja +9 -0
- openai_sdk_helpers/prompt/extractor_prompt_optimizer_agent_instructions.jinja +4 -0
- openai_sdk_helpers/prompt/extractor_prompt_optimizer_request.jinja +11 -0
- openai_sdk_helpers/response/__init__.py +2 -6
- openai_sdk_helpers/response/base.py +85 -94
- openai_sdk_helpers/response/configuration.py +39 -14
- openai_sdk_helpers/response/files.py +2 -0
- openai_sdk_helpers/response/runner.py +1 -48
- openai_sdk_helpers/response/tool_call.py +0 -141
- openai_sdk_helpers/response/vector_store.py +8 -5
- openai_sdk_helpers/streamlit_app/app.py +1 -1
- openai_sdk_helpers/structure/__init__.py +16 -0
- openai_sdk_helpers/structure/base.py +239 -278
- openai_sdk_helpers/structure/extraction.py +1228 -0
- openai_sdk_helpers/structure/plan/plan.py +0 -20
- openai_sdk_helpers/structure/plan/task.py +0 -33
- openai_sdk_helpers/structure/prompt.py +16 -0
- openai_sdk_helpers/structure/responses.py +2 -2
- openai_sdk_helpers/structure/web_search.py +0 -10
- openai_sdk_helpers/tools.py +346 -99
- openai_sdk_helpers/utils/__init__.py +7 -0
- openai_sdk_helpers/utils/json/base_model.py +315 -32
- openai_sdk_helpers/utils/langextract.py +194 -0
- {openai_sdk_helpers-0.4.3.dist-info → openai_sdk_helpers-0.5.0.dist-info}/METADATA +18 -4
- {openai_sdk_helpers-0.4.3.dist-info → openai_sdk_helpers-0.5.0.dist-info}/RECORD +46 -37
- openai_sdk_helpers/streamlit_app/streamlit_web_search.py +0 -75
- {openai_sdk_helpers-0.4.3.dist-info → openai_sdk_helpers-0.5.0.dist-info}/WHEEL +0 -0
- {openai_sdk_helpers-0.4.3.dist-info → openai_sdk_helpers-0.5.0.dist-info}/entry_points.txt +0 -0
- {openai_sdk_helpers-0.4.3.dist-info → openai_sdk_helpers-0.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -7,9 +7,6 @@ and robust argument parsing.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
import ast
|
|
11
|
-
import json
|
|
12
|
-
import re
|
|
13
10
|
from dataclasses import dataclass
|
|
14
11
|
|
|
15
12
|
from openai.types.responses.response_function_tool_call_param import (
|
|
@@ -94,141 +91,3 @@ class ResponseToolCall(DataclassJSONSerializable):
|
|
|
94
91
|
},
|
|
95
92
|
)
|
|
96
93
|
return function_call, function_call_output
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def _to_snake_case(name: str) -> str:
|
|
100
|
-
"""Convert a PascalCase or camelCase string to snake_case.
|
|
101
|
-
|
|
102
|
-
Parameters
|
|
103
|
-
----------
|
|
104
|
-
name : str
|
|
105
|
-
The name to convert.
|
|
106
|
-
|
|
107
|
-
Returns
|
|
108
|
-
-------
|
|
109
|
-
str
|
|
110
|
-
The snake_case version of the name.
|
|
111
|
-
|
|
112
|
-
Examples
|
|
113
|
-
--------
|
|
114
|
-
>>> _to_snake_case("ExampleStructure")
|
|
115
|
-
'example_structure'
|
|
116
|
-
>>> _to_snake_case("MyToolName")
|
|
117
|
-
'my_tool_name'
|
|
118
|
-
"""
|
|
119
|
-
# First regex: Insert underscore before uppercase letters followed by
|
|
120
|
-
# lowercase letters (e.g., "Tool" in "ExampleTool" becomes "_Tool")
|
|
121
|
-
s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
|
|
122
|
-
# Second regex: Insert underscore between lowercase/digit and uppercase
|
|
123
|
-
# (e.g., "e3" followed by "T" becomes "e3_T")
|
|
124
|
-
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower()
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def _unwrap_arguments(parsed: dict, tool_name: str) -> dict:
|
|
128
|
-
"""Unwrap arguments if wrapped in a single-key dict.
|
|
129
|
-
|
|
130
|
-
Some responses wrap arguments under a key matching the structure class
|
|
131
|
-
name (e.g., {"ExampleStructure": {...}}) or snake_case variant
|
|
132
|
-
(e.g., {"example_structure": {...}}). This function detects and unwraps
|
|
133
|
-
such wrappers to normalize the payload.
|
|
134
|
-
|
|
135
|
-
Parameters
|
|
136
|
-
----------
|
|
137
|
-
parsed : dict
|
|
138
|
-
The parsed arguments dictionary.
|
|
139
|
-
tool_name : str
|
|
140
|
-
The tool name, used to match potential wrapper keys.
|
|
141
|
-
|
|
142
|
-
Returns
|
|
143
|
-
-------
|
|
144
|
-
dict
|
|
145
|
-
Unwrapped arguments dictionary, or original if no wrapper detected.
|
|
146
|
-
|
|
147
|
-
Examples
|
|
148
|
-
--------
|
|
149
|
-
>>> _unwrap_arguments({"ExampleTool": {"arg": "value"}}, "ExampleTool")
|
|
150
|
-
{'arg': 'value'}
|
|
151
|
-
>>> _unwrap_arguments({"example_tool": {"arg": "value"}}, "ExampleTool")
|
|
152
|
-
{'arg': 'value'}
|
|
153
|
-
>>> _unwrap_arguments({"arg": "value"}, "ExampleTool")
|
|
154
|
-
{'arg': 'value'}
|
|
155
|
-
"""
|
|
156
|
-
# Only unwrap if dict has exactly one key
|
|
157
|
-
if not isinstance(parsed, dict) or len(parsed) != 1:
|
|
158
|
-
return parsed
|
|
159
|
-
|
|
160
|
-
wrapper_key = next(iter(parsed))
|
|
161
|
-
wrapped_value = parsed[wrapper_key]
|
|
162
|
-
|
|
163
|
-
# Only unwrap if the value is also a dict
|
|
164
|
-
if not isinstance(wrapped_value, dict):
|
|
165
|
-
return parsed
|
|
166
|
-
|
|
167
|
-
# Check if wrapper key matches tool name (case-insensitive or snake_case)
|
|
168
|
-
tool_name_lower = tool_name.lower()
|
|
169
|
-
tool_name_snake = _to_snake_case(tool_name)
|
|
170
|
-
wrapper_key_lower = wrapper_key.lower()
|
|
171
|
-
|
|
172
|
-
if wrapper_key_lower in (tool_name_lower, tool_name_snake):
|
|
173
|
-
return wrapped_value
|
|
174
|
-
|
|
175
|
-
return parsed
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
def parse_tool_arguments(arguments: str, tool_name: str) -> dict:
|
|
179
|
-
"""Parse tool call arguments with fallback for malformed JSON.
|
|
180
|
-
|
|
181
|
-
Attempts to parse arguments as JSON first, then falls back to
|
|
182
|
-
ast.literal_eval for cases where the OpenAI API returns minor
|
|
183
|
-
formatting issues like single quotes instead of double quotes.
|
|
184
|
-
Provides clear error context including tool name and raw payload.
|
|
185
|
-
|
|
186
|
-
Also handles unwrapping of arguments that are wrapped in a single-key
|
|
187
|
-
dictionary matching the tool name (e.g., {"ExampleStructure": {...}}).
|
|
188
|
-
|
|
189
|
-
Parameters
|
|
190
|
-
----------
|
|
191
|
-
arguments : str
|
|
192
|
-
Raw argument string from a tool call, expected to be JSON.
|
|
193
|
-
tool_name : str
|
|
194
|
-
Tool name for improved error context (required).
|
|
195
|
-
|
|
196
|
-
Returns
|
|
197
|
-
-------
|
|
198
|
-
dict
|
|
199
|
-
Parsed dictionary of tool arguments, with wrapper unwrapped if present.
|
|
200
|
-
|
|
201
|
-
Raises
|
|
202
|
-
------
|
|
203
|
-
ValueError
|
|
204
|
-
If the arguments cannot be parsed as valid JSON or Python literal.
|
|
205
|
-
Error message includes tool name and payload excerpt for debugging.
|
|
206
|
-
|
|
207
|
-
Examples
|
|
208
|
-
--------
|
|
209
|
-
>>> parse_tool_arguments('{"key": "value"}', tool_name="search")
|
|
210
|
-
{'key': 'value'}
|
|
211
|
-
|
|
212
|
-
>>> parse_tool_arguments("{'key': 'value'}", tool_name="search")
|
|
213
|
-
{'key': 'value'}
|
|
214
|
-
|
|
215
|
-
>>> parse_tool_arguments('{"ExampleTool": {"arg": "value"}}', "ExampleTool")
|
|
216
|
-
{'arg': 'value'}
|
|
217
|
-
"""
|
|
218
|
-
try:
|
|
219
|
-
parsed = json.loads(arguments)
|
|
220
|
-
except json.JSONDecodeError:
|
|
221
|
-
try:
|
|
222
|
-
parsed = ast.literal_eval(arguments)
|
|
223
|
-
except Exception as exc: # noqa: BLE001
|
|
224
|
-
# Build informative error message with context
|
|
225
|
-
payload_preview = (
|
|
226
|
-
arguments[:100] + "..." if len(arguments) > 100 else arguments
|
|
227
|
-
)
|
|
228
|
-
raise ValueError(
|
|
229
|
-
f"Failed to parse tool arguments for tool '{tool_name}'. "
|
|
230
|
-
f"Raw payload: {payload_preview}"
|
|
231
|
-
) from exc
|
|
232
|
-
|
|
233
|
-
# Unwrap if wrapped in a single-key dict matching tool name
|
|
234
|
-
return _unwrap_arguments(parsed, tool_name)
|
|
@@ -73,13 +73,16 @@ def attach_vector_store(
|
|
|
73
73
|
raise ValueError(f"Vector store '{store}' not found.")
|
|
74
74
|
if match not in resolved_ids:
|
|
75
75
|
resolved_ids.append(match)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
file_search_tool = None
|
|
77
|
+
if response._tools is not None:
|
|
78
|
+
file_search_tool = next(
|
|
79
|
+
(tool for tool in response._tools if tool.get("type") == "file_search"),
|
|
80
|
+
None,
|
|
81
|
+
)
|
|
81
82
|
|
|
82
83
|
if file_search_tool is None:
|
|
84
|
+
if response._tools is None:
|
|
85
|
+
response._tools = []
|
|
83
86
|
response._tools.append(
|
|
84
87
|
{"type": "file_search", "vector_store_ids": resolved_ids}
|
|
85
88
|
)
|
|
@@ -177,7 +177,7 @@ def _render_summary(result: Any, response: ResponseBase[Any]) -> str:
|
|
|
177
177
|
the result cannot be formatted directly.
|
|
178
178
|
"""
|
|
179
179
|
if isinstance(result, StructureBase):
|
|
180
|
-
return result
|
|
180
|
+
return str(result)
|
|
181
181
|
if isinstance(result, str):
|
|
182
182
|
return result
|
|
183
183
|
if isinstance(result, dict):
|
|
@@ -53,6 +53,10 @@ VectorSearchReportStructure
|
|
|
53
53
|
Complete vector search report.
|
|
54
54
|
ValidationResultStructure
|
|
55
55
|
Validation results with pass/fail status.
|
|
56
|
+
ExtractionItem
|
|
57
|
+
Extracted item with source span data.
|
|
58
|
+
ExtractionResult
|
|
59
|
+
Structured extraction results for a document.
|
|
56
60
|
|
|
57
61
|
Functions
|
|
58
62
|
---------
|
|
@@ -72,6 +76,13 @@ from __future__ import annotations
|
|
|
72
76
|
|
|
73
77
|
from .agent_blueprint import AgentBlueprint
|
|
74
78
|
from .base import *
|
|
79
|
+
from .extraction import (
|
|
80
|
+
AnnotatedDocumentStructure,
|
|
81
|
+
AttributeStructure,
|
|
82
|
+
DocumentStructure,
|
|
83
|
+
ExampleDataStructure,
|
|
84
|
+
ExtractionStructure,
|
|
85
|
+
)
|
|
75
86
|
from .plan import *
|
|
76
87
|
from .prompt import PromptStructure
|
|
77
88
|
from .responses import *
|
|
@@ -109,6 +120,11 @@ __all__ = [
|
|
|
109
120
|
"VectorSearchPlanStructure",
|
|
110
121
|
"VectorSearchStructure",
|
|
111
122
|
"ValidationResultStructure",
|
|
123
|
+
"AnnotatedDocumentStructure",
|
|
124
|
+
"AttributeStructure",
|
|
125
|
+
"DocumentStructure",
|
|
126
|
+
"ExampleDataStructure",
|
|
127
|
+
"ExtractionStructure",
|
|
112
128
|
"assistant_tool_definition",
|
|
113
129
|
"assistant_format",
|
|
114
130
|
"response_tool_definition",
|