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.
Files changed (47) hide show
  1. openai_sdk_helpers/__init__.py +41 -7
  2. openai_sdk_helpers/agent/__init__.py +1 -2
  3. openai_sdk_helpers/agent/base.py +89 -173
  4. openai_sdk_helpers/agent/configuration.py +12 -20
  5. openai_sdk_helpers/agent/coordinator.py +14 -17
  6. openai_sdk_helpers/agent/runner.py +3 -45
  7. openai_sdk_helpers/agent/search/base.py +49 -71
  8. openai_sdk_helpers/agent/search/vector.py +82 -110
  9. openai_sdk_helpers/agent/search/web.py +103 -81
  10. openai_sdk_helpers/agent/summarizer.py +20 -28
  11. openai_sdk_helpers/agent/translator.py +17 -23
  12. openai_sdk_helpers/agent/validator.py +17 -23
  13. openai_sdk_helpers/errors.py +9 -0
  14. openai_sdk_helpers/extract/__init__.py +23 -0
  15. openai_sdk_helpers/extract/extractor.py +157 -0
  16. openai_sdk_helpers/extract/generator.py +476 -0
  17. openai_sdk_helpers/prompt/extractor_config_agent_instructions.jinja +6 -0
  18. openai_sdk_helpers/prompt/extractor_config_generator.jinja +37 -0
  19. openai_sdk_helpers/prompt/extractor_config_generator_instructions.jinja +9 -0
  20. openai_sdk_helpers/prompt/extractor_prompt_optimizer_agent_instructions.jinja +4 -0
  21. openai_sdk_helpers/prompt/extractor_prompt_optimizer_request.jinja +11 -0
  22. openai_sdk_helpers/response/__init__.py +2 -6
  23. openai_sdk_helpers/response/base.py +85 -94
  24. openai_sdk_helpers/response/configuration.py +39 -14
  25. openai_sdk_helpers/response/files.py +2 -0
  26. openai_sdk_helpers/response/runner.py +1 -48
  27. openai_sdk_helpers/response/tool_call.py +0 -141
  28. openai_sdk_helpers/response/vector_store.py +8 -5
  29. openai_sdk_helpers/streamlit_app/app.py +1 -1
  30. openai_sdk_helpers/structure/__init__.py +16 -0
  31. openai_sdk_helpers/structure/base.py +239 -278
  32. openai_sdk_helpers/structure/extraction.py +1228 -0
  33. openai_sdk_helpers/structure/plan/plan.py +0 -20
  34. openai_sdk_helpers/structure/plan/task.py +0 -33
  35. openai_sdk_helpers/structure/prompt.py +16 -0
  36. openai_sdk_helpers/structure/responses.py +2 -2
  37. openai_sdk_helpers/structure/web_search.py +0 -10
  38. openai_sdk_helpers/tools.py +346 -99
  39. openai_sdk_helpers/utils/__init__.py +7 -0
  40. openai_sdk_helpers/utils/json/base_model.py +315 -32
  41. openai_sdk_helpers/utils/langextract.py +194 -0
  42. {openai_sdk_helpers-0.4.3.dist-info → openai_sdk_helpers-0.5.0.dist-info}/METADATA +18 -4
  43. {openai_sdk_helpers-0.4.3.dist-info → openai_sdk_helpers-0.5.0.dist-info}/RECORD +46 -37
  44. openai_sdk_helpers/streamlit_app/streamlit_web_search.py +0 -75
  45. {openai_sdk_helpers-0.4.3.dist-info → openai_sdk_helpers-0.5.0.dist-info}/WHEEL +0 -0
  46. {openai_sdk_helpers-0.4.3.dist-info → openai_sdk_helpers-0.5.0.dist-info}/entry_points.txt +0 -0
  47. {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
- file_search_tool = next(
78
- (tool for tool in response._tools if tool.get("type") == "file_search"),
79
- None,
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.print()
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",