openai-sdk-helpers 0.0.8__py3-none-any.whl → 0.1.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 (67) hide show
  1. openai_sdk_helpers/__init__.py +90 -2
  2. openai_sdk_helpers/agent/__init__.py +8 -4
  3. openai_sdk_helpers/agent/base.py +80 -45
  4. openai_sdk_helpers/agent/config.py +6 -4
  5. openai_sdk_helpers/agent/{project_manager.py → coordination.py} +29 -45
  6. openai_sdk_helpers/agent/prompt_utils.py +7 -1
  7. openai_sdk_helpers/agent/runner.py +67 -141
  8. openai_sdk_helpers/agent/search/__init__.py +33 -0
  9. openai_sdk_helpers/agent/search/base.py +297 -0
  10. openai_sdk_helpers/agent/{vector_search.py → search/vector.py} +89 -157
  11. openai_sdk_helpers/agent/{web_search.py → search/web.py} +77 -156
  12. openai_sdk_helpers/agent/summarizer.py +29 -8
  13. openai_sdk_helpers/agent/translator.py +40 -13
  14. openai_sdk_helpers/agent/validation.py +32 -8
  15. openai_sdk_helpers/async_utils.py +132 -0
  16. openai_sdk_helpers/config.py +101 -65
  17. openai_sdk_helpers/context_manager.py +241 -0
  18. openai_sdk_helpers/enums/__init__.py +9 -1
  19. openai_sdk_helpers/enums/base.py +67 -8
  20. openai_sdk_helpers/environment.py +33 -6
  21. openai_sdk_helpers/errors.py +133 -0
  22. openai_sdk_helpers/logging_config.py +105 -0
  23. openai_sdk_helpers/prompt/__init__.py +10 -71
  24. openai_sdk_helpers/prompt/base.py +222 -0
  25. openai_sdk_helpers/response/__init__.py +38 -3
  26. openai_sdk_helpers/response/base.py +363 -210
  27. openai_sdk_helpers/response/config.py +318 -0
  28. openai_sdk_helpers/response/messages.py +56 -40
  29. openai_sdk_helpers/response/runner.py +77 -33
  30. openai_sdk_helpers/response/tool_call.py +62 -27
  31. openai_sdk_helpers/response/vector_store.py +27 -14
  32. openai_sdk_helpers/retry.py +175 -0
  33. openai_sdk_helpers/streamlit_app/__init__.py +19 -2
  34. openai_sdk_helpers/streamlit_app/app.py +114 -39
  35. openai_sdk_helpers/streamlit_app/config.py +502 -0
  36. openai_sdk_helpers/streamlit_app/streamlit_web_search.py +5 -6
  37. openai_sdk_helpers/structure/__init__.py +72 -3
  38. openai_sdk_helpers/structure/agent_blueprint.py +82 -19
  39. openai_sdk_helpers/structure/base.py +208 -93
  40. openai_sdk_helpers/structure/plan/__init__.py +29 -1
  41. openai_sdk_helpers/structure/plan/enum.py +41 -5
  42. openai_sdk_helpers/structure/plan/helpers.py +172 -0
  43. openai_sdk_helpers/structure/plan/plan.py +109 -49
  44. openai_sdk_helpers/structure/plan/task.py +38 -6
  45. openai_sdk_helpers/structure/plan/types.py +15 -0
  46. openai_sdk_helpers/structure/prompt.py +21 -2
  47. openai_sdk_helpers/structure/responses.py +52 -11
  48. openai_sdk_helpers/structure/summary.py +55 -7
  49. openai_sdk_helpers/structure/validation.py +34 -6
  50. openai_sdk_helpers/structure/vector_search.py +132 -18
  51. openai_sdk_helpers/structure/web_search.py +125 -13
  52. openai_sdk_helpers/tools.py +193 -0
  53. openai_sdk_helpers/types.py +57 -0
  54. openai_sdk_helpers/utils/__init__.py +34 -1
  55. openai_sdk_helpers/utils/core.py +296 -34
  56. openai_sdk_helpers/validation.py +302 -0
  57. openai_sdk_helpers/vector_storage/__init__.py +21 -1
  58. openai_sdk_helpers/vector_storage/cleanup.py +25 -13
  59. openai_sdk_helpers/vector_storage/storage.py +123 -64
  60. openai_sdk_helpers/vector_storage/types.py +20 -19
  61. openai_sdk_helpers-0.1.0.dist-info/METADATA +550 -0
  62. openai_sdk_helpers-0.1.0.dist-info/RECORD +69 -0
  63. openai_sdk_helpers/streamlit_app/configuration.py +0 -324
  64. openai_sdk_helpers-0.0.8.dist-info/METADATA +0 -194
  65. openai_sdk_helpers-0.0.8.dist-info/RECORD +0 -55
  66. {openai_sdk_helpers-0.0.8.dist-info → openai_sdk_helpers-0.1.0.dist-info}/WHEEL +0 -0
  67. {openai_sdk_helpers-0.0.8.dist-info → openai_sdk_helpers-0.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -2,13 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import asyncio
6
5
  from pathlib import Path
7
6
  from typing import Any, Callable, Dict, List, Optional
8
7
 
9
8
  from agents import custom_span, gen_trace_id, trace
10
9
 
11
- from ..structure.vector_search import (
10
+ from ...structure.vector_search import (
12
11
  VectorSearchItemStructure,
13
12
  VectorSearchItemResultStructure,
14
13
  VectorSearchItemResultsStructure,
@@ -16,15 +15,15 @@ from ..structure.vector_search import (
16
15
  VectorSearchPlanStructure,
17
16
  VectorSearchReportStructure,
18
17
  )
19
- from ..vector_storage import VectorStorage
20
- from .base import AgentBase
21
- from .config import AgentConfig
22
- from .utils import run_coroutine_agent_sync
18
+ from ...vector_storage import VectorStorage
19
+ from ..config import AgentConfig
20
+ from ..utils import run_coroutine_agent_sync
21
+ from .base import SearchPlanner, SearchToolAgent, SearchWriter
23
22
 
24
23
  MAX_CONCURRENT_SEARCHES = 10
25
24
 
26
25
 
27
- class VectorSearchPlanner(AgentBase):
26
+ class VectorSearchPlanner(SearchPlanner[VectorSearchPlanStructure]):
28
27
  """Plan vector searches to satisfy a user query.
29
28
 
30
29
  Methods
@@ -40,46 +39,35 @@ class VectorSearchPlanner(AgentBase):
40
39
 
41
40
  Parameters
42
41
  ----------
43
- prompt_dir : pathlib.Path or None, default=None
42
+ prompt_dir : Path or None, default=None
44
43
  Directory containing prompt templates.
45
44
  default_model : str or None, default=None
46
45
  Default model identifier to use when not defined in config.
46
+ """
47
+ super().__init__(prompt_dir=prompt_dir, default_model=default_model)
48
+
49
+ def _configure_agent(self) -> AgentConfig:
50
+ """Return configuration for the vector planner agent.
47
51
 
48
52
  Returns
49
53
  -------
50
- None
54
+ AgentConfig
55
+ Configuration with name, description, and output type.
51
56
  """
52
- config = AgentConfig(
57
+ return AgentConfig(
53
58
  name="vector_planner",
54
59
  description="Plan vector searches based on a user query.",
55
60
  output_type=VectorSearchPlanStructure,
56
61
  )
57
- super().__init__(
58
- config=config, prompt_dir=prompt_dir, default_model=default_model
59
- )
60
62
 
61
- async def run_agent(self, query: str) -> VectorSearchPlanStructure:
62
- """Create a search plan for ``query``.
63
63
 
64
- Parameters
65
- ----------
66
- query : str
67
- User search query.
68
-
69
- Returns
70
- -------
71
- VectorSearchPlanStructure
72
- Generated search plan.
73
- """
74
- result: VectorSearchPlanStructure = await self.run_async(
75
- input=query,
76
- output_type=self._output_type,
77
- )
78
-
79
- return result
80
-
81
-
82
- class VectorSearchTool(AgentBase):
64
+ class VectorSearchTool(
65
+ SearchToolAgent[
66
+ VectorSearchItemStructure,
67
+ VectorSearchItemResultStructure,
68
+ VectorSearchPlanStructure,
69
+ ]
70
+ ):
83
71
  """Execute vector searches defined in a search plan.
84
72
 
85
73
  Methods
@@ -103,7 +91,7 @@ class VectorSearchTool(AgentBase):
103
91
 
104
92
  Parameters
105
93
  ----------
106
- prompt_dir : pathlib.Path or None, default=None
94
+ prompt_dir : Path or None, default=None
107
95
  Directory containing prompt templates.
108
96
  default_model : str or None, default=None
109
97
  Default model identifier to use when not defined in config.
@@ -113,29 +101,35 @@ class VectorSearchTool(AgentBase):
113
101
  Maximum number of concurrent vector search tasks to run.
114
102
  vector_storage : VectorStorage or None, default=None
115
103
  Optional preconfigured vector storage instance to reuse.
116
- vector_storage_factory : callable, default=None
117
- Factory for constructing a :class:`VectorStorage` when one is not
118
- provided. Receives ``store_name`` as an argument.
119
-
120
- Returns
121
- -------
122
- None
104
+ vector_storage_factory : Callable or None, default=None
105
+ Factory for constructing a VectorStorage when one is not provided.
106
+ Receives ``store_name`` as an argument.
123
107
  """
124
108
  self._vector_storage: Optional[VectorStorage] = None
125
109
  self._store_name = store_name or "editorial"
126
110
  self._vector_storage_factory = vector_storage_factory
127
111
  if vector_storage is not None:
128
112
  self._vector_storage = vector_storage
129
- self._max_concurrent_searches = max_concurrent_searches
130
- config = AgentConfig(
113
+ super().__init__(
114
+ prompt_dir=prompt_dir,
115
+ default_model=default_model,
116
+ max_concurrent_searches=max_concurrent_searches,
117
+ )
118
+
119
+ def _configure_agent(self) -> AgentConfig:
120
+ """Return configuration for the vector search tool agent.
121
+
122
+ Returns
123
+ -------
124
+ AgentConfig
125
+ Configuration with name, description, and input type.
126
+ """
127
+ return AgentConfig(
131
128
  name="vector_search",
132
129
  description="Perform vector searches based on a search plan.",
133
130
  input_type=VectorSearchPlanStructure,
134
131
  output_type=VectorSearchItemResultsStructure,
135
132
  )
136
- super().__init__(
137
- config=config, prompt_dir=prompt_dir, default_model=default_model
138
- )
139
133
 
140
134
  def _get_vector_storage(self) -> VectorStorage:
141
135
  """Return a cached vector storage instance.
@@ -152,57 +146,6 @@ class VectorSearchTool(AgentBase):
152
146
  self._vector_storage = VectorStorage(store_name=self._store_name)
153
147
  return self._vector_storage
154
148
 
155
- async def run_agent(
156
- self, search_plan: VectorSearchPlanStructure
157
- ) -> VectorSearchItemResultsStructure:
158
- """Execute all searches in the plan with a progress bar.
159
-
160
- Parameters
161
- ----------
162
- search_plan : VectorSearchPlanStructure
163
- Plan describing each search to perform.
164
-
165
- Returns
166
- -------
167
- VectorSearchItemResultsStructure
168
- Collection of results for the completed searches.
169
- """
170
- with custom_span("Search vector store"):
171
- semaphore = asyncio.Semaphore(self._max_concurrent_searches)
172
-
173
- async def _bounded_search(
174
- item: VectorSearchItemStructure,
175
- ) -> VectorSearchItemResultStructure:
176
- """Execute a single search within the concurrency limit.
177
-
178
- Parameters
179
- ----------
180
- item : VectorSearchItemStructure
181
- Search item to process.
182
-
183
- Returns
184
- -------
185
- VectorSearchItemResultStructure
186
- Result of the search.
187
- """
188
- async with semaphore:
189
- return await self.run_search(item)
190
-
191
- tasks = [
192
- asyncio.create_task(_bounded_search(item))
193
- for item in search_plan.searches
194
- ]
195
- results_list = await asyncio.gather(*tasks, return_exceptions=True)
196
- results = VectorSearchItemResultsStructure()
197
- for item, result in zip(search_plan.searches, results_list):
198
- if isinstance(result, BaseException):
199
- results.errors.append(f"Search for '{item.query}' failed: {result}")
200
- continue
201
- if result is not None:
202
- results.append(result)
203
-
204
- return results
205
-
206
149
  async def run_search(
207
150
  self, item: VectorSearchItemStructure
208
151
  ) -> VectorSearchItemResultStructure:
@@ -232,7 +175,7 @@ class VectorSearchTool(AgentBase):
232
175
  return VectorSearchItemResultStructure(texts=texts)
233
176
 
234
177
 
235
- class VectorSearchWriter(AgentBase):
178
+ class VectorSearchWriter(SearchWriter[VectorSearchReportStructure]):
236
179
  """Generate reports summarizing vector search results.
237
180
 
238
181
  Methods
@@ -248,56 +191,56 @@ class VectorSearchWriter(AgentBase):
248
191
 
249
192
  Parameters
250
193
  ----------
251
- prompt_dir : pathlib.Path or None, default=None
194
+ prompt_dir : Path or None, default=None
252
195
  Directory containing prompt templates.
253
196
  default_model : str or None, default=None
254
197
  Default model identifier to use when not defined in config.
198
+ """
199
+ super().__init__(prompt_dir=prompt_dir, default_model=default_model)
200
+
201
+ def _configure_agent(self) -> AgentConfig:
202
+ """Return configuration for the vector writer agent.
255
203
 
256
204
  Returns
257
205
  -------
258
- None
206
+ AgentConfig
207
+ Configuration with name, description, and output type.
259
208
  """
260
- config = AgentConfig(
209
+ return AgentConfig(
261
210
  name="vector_writer",
262
211
  description="Write a report based on search results.",
263
212
  output_type=VectorSearchReportStructure,
264
213
  )
265
- super().__init__(
266
- config=config, prompt_dir=prompt_dir, default_model=default_model
267
- )
268
214
 
269
- async def run_agent(
270
- self, query: str, search_results: VectorSearchItemResultsStructure
271
- ) -> VectorSearchReportStructure:
272
- """Compile a final report from search results.
273
215
 
274
- Parameters
275
- ----------
276
- query : str
277
- Original search query.
278
- search_results : VectorSearchItemResultsStructure
279
- Results returned from the search step.
216
+ class VectorSearch:
217
+ """Manage the complete vector search workflow.
280
218
 
281
- Returns
282
- -------
283
- VectorSearchReportStructure
284
- Generated report for the query.
285
- """
286
- template_context: Dict[str, Any] = {
287
- "original_query": query,
288
- "search_results": search_results,
289
- }
290
- result: VectorSearchReportStructure = await self.run_async(
291
- input=query,
292
- context=template_context,
293
- output_type=self._output_type,
294
- )
219
+ This high-level agent orchestrates a multi-step research process that plans
220
+ searches, executes them concurrently against a vector store, and generates
221
+ comprehensive reports. It combines ``VectorSearchPlanner``,
222
+ ``VectorSearchTool``, and ``VectorSearchWriter`` into a single workflow.
295
223
 
296
- return result
224
+ Examples
225
+ --------
226
+ Basic vector search:
297
227
 
228
+ >>> from pathlib import Path
229
+ >>> from openai_sdk_helpers.agent.search.vector import VectorSearch
230
+ >>> prompts = Path("./prompts")
231
+ >>> search = VectorSearch(prompt_dir=prompts, default_model="gpt-4o-mini")
232
+ >>> result = search.run_agent_sync("What are the key findings in recent AI research?")
233
+ >>> print(result.report.report)
298
234
 
299
- class VectorSearch(AgentBase):
300
- """Manage the complete vector search workflow.
235
+ Custom vector store:
236
+
237
+ >>> from openai_sdk_helpers.vector_storage import VectorStorage
238
+ >>> storage = VectorStorage(store_name="research_papers")
239
+ >>> search = VectorSearch(
240
+ ... default_model="gpt-4o-mini",
241
+ ... vector_storage=storage,
242
+ ... max_concurrent_searches=5
243
+ ... )
301
244
 
302
245
  Methods
303
246
  -------
@@ -313,7 +256,6 @@ class VectorSearch(AgentBase):
313
256
 
314
257
  def __init__(
315
258
  self,
316
- config: Optional[AgentConfig] = None,
317
259
  prompt_dir: Optional[Path] = None,
318
260
  default_model: Optional[str] = None,
319
261
  vector_store_name: Optional[str] = None,
@@ -325,9 +267,7 @@ class VectorSearch(AgentBase):
325
267
 
326
268
  Parameters
327
269
  ----------
328
- config : AgentConfig or None, default=None
329
- Optional configuration for the agent.
330
- prompt_dir : pathlib.Path or None, default=None
270
+ prompt_dir : Path or None, default=None
331
271
  Directory containing prompt templates.
332
272
  default_model : str or None, default=None
333
273
  Default model identifier to use when not defined in config.
@@ -338,24 +278,11 @@ class VectorSearch(AgentBase):
338
278
  vector_storage : VectorStorage or None, default=None
339
279
  Optional preconfigured vector storage instance to reuse.
340
280
  vector_storage_factory : callable, default=None
341
- Factory used to construct a :class:`VectorStorage` when one is not
342
- provided. Receives ``vector_store_name`` as an argument.
343
-
344
- Returns
345
- -------
346
- None
281
+ Factory used to construct a VectorStorage when one is not provided.
282
+ Receives ``vector_store_name`` as an argument.
347
283
  """
348
- if config is None:
349
- config = AgentConfig(
350
- name="vector_agent",
351
- description="Coordinates the research process, including planning, searching, and report writing.",
352
- output_type=VectorSearchStructure,
353
- input_type=VectorSearchReportStructure,
354
- )
355
- super().__init__(
356
- config=config, prompt_dir=prompt_dir, default_model=default_model
357
- )
358
284
  self._prompt_dir = prompt_dir
285
+ self._default_model = default_model
359
286
  self._vector_store_name = vector_store_name
360
287
  self._max_concurrent_searches = max_concurrent_searches
361
288
  self._vector_storage = vector_storage
@@ -377,25 +304,30 @@ class VectorSearch(AgentBase):
377
304
  trace_id = gen_trace_id()
378
305
  with trace("VectorSearch trace", trace_id=trace_id):
379
306
  planner = VectorSearchPlanner(
380
- prompt_dir=self._prompt_dir, default_model=self.model
307
+ prompt_dir=self._prompt_dir, default_model=self._default_model
381
308
  )
382
309
  tool = VectorSearchTool(
383
310
  prompt_dir=self._prompt_dir,
384
- default_model=self.model,
311
+ default_model=self._default_model,
385
312
  store_name=self._vector_store_name,
386
313
  max_concurrent_searches=self._max_concurrent_searches,
387
314
  vector_storage=self._vector_storage,
388
315
  vector_storage_factory=self._vector_storage_factory,
389
316
  )
390
317
  writer = VectorSearchWriter(
391
- prompt_dir=self._prompt_dir, default_model=self.model
318
+ prompt_dir=self._prompt_dir, default_model=self._default_model
392
319
  )
393
320
  with custom_span("vector_search.plan"):
394
321
  search_plan = await planner.run_agent(query=search_query)
395
322
  with custom_span("vector_search.search"):
396
- search_results = await tool.run_agent(search_plan=search_plan)
323
+ search_results_list = await tool.run_agent(search_plan=search_plan)
397
324
  with custom_span("vector_search.write"):
398
- search_report = await writer.run_agent(search_query, search_results)
325
+ search_report = await writer.run_agent(
326
+ search_query, search_results_list
327
+ )
328
+ search_results = VectorSearchItemResultsStructure(
329
+ item_results=search_results_list
330
+ )
399
331
  return VectorSearchStructure(
400
332
  query=search_query,
401
333
  plan=search_plan,