openai-sdk-helpers 0.0.2__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 (40) hide show
  1. openai_sdk_helpers/__init__.py +34 -0
  2. openai_sdk_helpers/agent/__init__.py +23 -0
  3. openai_sdk_helpers/agent/base.py +432 -0
  4. openai_sdk_helpers/agent/config.py +66 -0
  5. openai_sdk_helpers/agent/project_manager.py +416 -0
  6. openai_sdk_helpers/agent/runner.py +117 -0
  7. openai_sdk_helpers/agent/utils.py +47 -0
  8. openai_sdk_helpers/agent/vector_search.py +418 -0
  9. openai_sdk_helpers/agent/web_search.py +404 -0
  10. openai_sdk_helpers/config.py +141 -0
  11. openai_sdk_helpers/enums/__init__.py +7 -0
  12. openai_sdk_helpers/enums/base.py +17 -0
  13. openai_sdk_helpers/environment.py +27 -0
  14. openai_sdk_helpers/prompt/__init__.py +77 -0
  15. openai_sdk_helpers/response/__init__.py +16 -0
  16. openai_sdk_helpers/response/base.py +477 -0
  17. openai_sdk_helpers/response/messages.py +211 -0
  18. openai_sdk_helpers/response/runner.py +42 -0
  19. openai_sdk_helpers/response/tool_call.py +70 -0
  20. openai_sdk_helpers/structure/__init__.py +57 -0
  21. openai_sdk_helpers/structure/base.py +591 -0
  22. openai_sdk_helpers/structure/plan/__init__.py +13 -0
  23. openai_sdk_helpers/structure/plan/enum.py +48 -0
  24. openai_sdk_helpers/structure/plan/plan.py +104 -0
  25. openai_sdk_helpers/structure/plan/task.py +122 -0
  26. openai_sdk_helpers/structure/prompt.py +24 -0
  27. openai_sdk_helpers/structure/responses.py +148 -0
  28. openai_sdk_helpers/structure/summary.py +65 -0
  29. openai_sdk_helpers/structure/vector_search.py +82 -0
  30. openai_sdk_helpers/structure/web_search.py +46 -0
  31. openai_sdk_helpers/utils/__init__.py +13 -0
  32. openai_sdk_helpers/utils/core.py +208 -0
  33. openai_sdk_helpers/vector_storage/__init__.py +15 -0
  34. openai_sdk_helpers/vector_storage/cleanup.py +91 -0
  35. openai_sdk_helpers/vector_storage/storage.py +501 -0
  36. openai_sdk_helpers/vector_storage/types.py +58 -0
  37. openai_sdk_helpers-0.0.2.dist-info/METADATA +137 -0
  38. openai_sdk_helpers-0.0.2.dist-info/RECORD +40 -0
  39. openai_sdk_helpers-0.0.2.dist-info/WHEEL +4 -0
  40. openai_sdk_helpers-0.0.2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,418 @@
1
+ """Core workflow management for ``vector search``."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from pathlib import Path
7
+ from typing import Any, Dict, List, Optional
8
+
9
+ from agents import custom_span, gen_trace_id, trace
10
+
11
+ from ..structure.vector_search import (
12
+ VectorSearchItemStructure,
13
+ VectorSearchItemResultStructure,
14
+ VectorSearchItemResultsStructure,
15
+ VectorSearchStructure,
16
+ VectorSearchPlanStructure,
17
+ VectorSearchReportStructure,
18
+ )
19
+ from ..vector_storage import VectorStorage
20
+ from .base import BaseAgent, _run_agent
21
+ from .config import AgentConfig
22
+ from .utils import run_coro_sync
23
+
24
+ MAX_CONCURRENT_SEARCHES = 10
25
+
26
+
27
+ class VectorSearchPlanner(BaseAgent):
28
+ """Plan vector searches to satisfy a user query.
29
+
30
+ Methods
31
+ -------
32
+ run_agent(query)
33
+ Generate a vector search plan for the provided query.
34
+ """
35
+
36
+ def __init__(
37
+ self, prompt_dir: Optional[Path] = None, default_model: Optional[str] = None
38
+ ) -> None:
39
+ """Initialize the planner agent.
40
+
41
+ Parameters
42
+ ----------
43
+ prompt_dir : pathlib.Path or None, default=None
44
+ Directory containing prompt templates.
45
+ default_model : str or None, default=None
46
+ Default model identifier to use when not defined in config.
47
+
48
+ Returns
49
+ -------
50
+ None
51
+ """
52
+ config = AgentConfig(
53
+ name="vector_planner",
54
+ description="Plan vector searches based on a user query.",
55
+ output_type=VectorSearchPlanStructure,
56
+ )
57
+ super().__init__(
58
+ config=config, prompt_dir=prompt_dir, default_model=default_model
59
+ )
60
+
61
+ async def run_agent(self, query: str) -> VectorSearchPlanStructure:
62
+ """Create a search plan for ``query``.
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 _run_agent(
75
+ agent=self.get_agent(),
76
+ agent_input=query,
77
+ output_type=self._output_type,
78
+ )
79
+
80
+ return result
81
+
82
+
83
+ class VectorSearchTool(BaseAgent):
84
+ """Execute vector searches defined in a search plan.
85
+
86
+ Methods
87
+ -------
88
+ run_agent(search_plan)
89
+ Execute searches described by the plan.
90
+ run_search(item)
91
+ Perform a single vector search and summarise the result.
92
+ """
93
+
94
+ def __init__(
95
+ self,
96
+ prompt_dir: Optional[Path] = None,
97
+ default_model: Optional[str] = None,
98
+ store_name: Optional[str] = None,
99
+ ) -> None:
100
+ """Initialize the search tool agent.
101
+
102
+ Parameters
103
+ ----------
104
+ prompt_dir : pathlib.Path or None, default=None
105
+ Directory containing prompt templates.
106
+ default_model : str or None, default=None
107
+ Default model identifier to use when not defined in config.
108
+
109
+ Returns
110
+ -------
111
+ None
112
+ """
113
+ self._vector_storage: Optional[VectorStorage] = None
114
+ self._store_name = store_name or "editorial"
115
+ config = AgentConfig(
116
+ name="vector_search",
117
+ description="Perform vector searches based on a search plan.",
118
+ input_type=VectorSearchPlanStructure,
119
+ output_type=VectorSearchItemResultsStructure,
120
+ )
121
+ super().__init__(
122
+ config=config, prompt_dir=prompt_dir, default_model=default_model
123
+ )
124
+
125
+ def _get_vector_storage(self) -> VectorStorage:
126
+ """Return a cached vector storage instance.
127
+
128
+ Returns
129
+ -------
130
+ VectorStorage
131
+ Vector storage helper for executing searches.
132
+ """
133
+ if self._vector_storage is None:
134
+ self._vector_storage = VectorStorage(store_name=self._store_name)
135
+ return self._vector_storage
136
+
137
+ async def run_agent(
138
+ self, search_plan: VectorSearchPlanStructure
139
+ ) -> VectorSearchItemResultsStructure:
140
+ """Execute all searches in the plan with a progress bar.
141
+
142
+ Parameters
143
+ ----------
144
+ search_plan : VectorSearchPlanStructure
145
+ Plan describing each search to perform.
146
+
147
+ Returns
148
+ -------
149
+ VectorSearchItemResultsStructure
150
+ Collection of results for the completed searches.
151
+ """
152
+ with custom_span("Search vector store"):
153
+ semaphore = asyncio.Semaphore(MAX_CONCURRENT_SEARCHES)
154
+
155
+ async def _bounded_search(
156
+ item: VectorSearchItemStructure,
157
+ ) -> VectorSearchItemResultStructure:
158
+ """Execute a single search within the concurrency limit.
159
+
160
+ Parameters
161
+ ----------
162
+ item : VectorSearchItemStructure
163
+ Search item to process.
164
+
165
+ Returns
166
+ -------
167
+ VectorSearchItemResultStructure
168
+ Result of the search.
169
+ """
170
+ async with semaphore:
171
+ return await self.run_search(item)
172
+
173
+ tasks = [
174
+ asyncio.create_task(_bounded_search(item))
175
+ for item in search_plan.searches
176
+ ]
177
+ results_list = await asyncio.gather(*tasks)
178
+ results = VectorSearchItemResultsStructure()
179
+ for result in results_list:
180
+ if result is not None:
181
+ results.append(result)
182
+ return results
183
+
184
+ async def run_search(
185
+ self, item: VectorSearchItemStructure
186
+ ) -> VectorSearchItemResultStructure:
187
+ """Perform a single vector search using the search tool.
188
+
189
+ Parameters
190
+ ----------
191
+ item : VectorSearchItemStructure
192
+ Search item containing the query and reason.
193
+
194
+ Returns
195
+ -------
196
+ VectorSearchItemResultStructure
197
+ Summarized search result. The ``texts`` attribute is empty when no
198
+ results are found.
199
+ """
200
+ results = self._get_vector_storage().search(item.query)
201
+ if results is None:
202
+ texts: List[str] = []
203
+ else:
204
+ texts = [
205
+ content.text
206
+ for result in results.data
207
+ for content in (result.content or [])
208
+ if getattr(content, "text", None)
209
+ ]
210
+ return VectorSearchItemResultStructure(texts=texts)
211
+
212
+
213
+ class VectorSearchWriter(BaseAgent):
214
+ """Generate reports summarizing vector search results.
215
+
216
+ Methods
217
+ -------
218
+ run_agent(query, search_results)
219
+ Compile a final report from search results.
220
+ """
221
+
222
+ def __init__(
223
+ self, prompt_dir: Optional[Path] = None, default_model: Optional[str] = None
224
+ ) -> None:
225
+ """Initialize the writer agent.
226
+
227
+ Parameters
228
+ ----------
229
+ prompt_dir : pathlib.Path or None, default=None
230
+ Directory containing prompt templates.
231
+ default_model : str or None, default=None
232
+ Default model identifier to use when not defined in config.
233
+
234
+ Returns
235
+ -------
236
+ None
237
+ """
238
+ config = AgentConfig(
239
+ name="vector_writer",
240
+ description="Write a report based on search results.",
241
+ output_type=VectorSearchReportStructure,
242
+ )
243
+ super().__init__(
244
+ config=config, prompt_dir=prompt_dir, default_model=default_model
245
+ )
246
+
247
+ async def run_agent(
248
+ self, query: str, search_results: VectorSearchItemResultsStructure
249
+ ) -> VectorSearchReportStructure:
250
+ """Compile a final report from search results.
251
+
252
+ Parameters
253
+ ----------
254
+ query : str
255
+ Original search query.
256
+ search_results : VectorSearchItemResultsStructure
257
+ Results returned from the search step.
258
+
259
+ Returns
260
+ -------
261
+ VectorSearchReportStructure
262
+ Generated report for the query.
263
+ """
264
+ template_context: Dict[str, Any] = {
265
+ "original_query": query,
266
+ "search_results": search_results,
267
+ }
268
+ result: VectorSearchReportStructure = await _run_agent(
269
+ agent=self.get_agent(),
270
+ agent_input=query,
271
+ agent_context=template_context,
272
+ output_type=self._output_type,
273
+ )
274
+
275
+ return result
276
+
277
+
278
+ class VectorSearch(BaseAgent):
279
+ """Manage the complete vector search workflow.
280
+
281
+ Methods
282
+ -------
283
+ run_agent(search_query)
284
+ Execute the research workflow asynchronously.
285
+ run_agent_sync(search_query)
286
+ Execute the research workflow synchronously.
287
+ run_vector_agent(search_query)
288
+ Convenience asynchronous entry point for the workflow.
289
+ run_vector_agent_sync(search_query)
290
+ Convenience synchronous entry point for the workflow.
291
+ """
292
+
293
+ def __init__(
294
+ self,
295
+ config: Optional[AgentConfig] = None,
296
+ prompt_dir: Optional[Path] = None,
297
+ default_model: Optional[str] = None,
298
+ vector_store_name: Optional[str] = None,
299
+ ) -> None:
300
+ """Create the main VectorSearch agent.
301
+
302
+ Parameters
303
+ ----------
304
+ config : AgentConfig or None, default=None
305
+ Optional configuration for the agent.
306
+ prompt_dir : pathlib.Path or None, default=None
307
+ Directory containing prompt templates.
308
+ default_model : str or None, default=None
309
+ Default model identifier to use when not defined in config.
310
+
311
+ Returns
312
+ -------
313
+ None
314
+ """
315
+ if config is None:
316
+ config = AgentConfig(
317
+ name="vector_agent",
318
+ description="Coordinates the research process, including planning, searching, and report writing.",
319
+ output_type=VectorSearchStructure,
320
+ input_type=VectorSearchReportStructure,
321
+ )
322
+ super().__init__(
323
+ config=config, prompt_dir=prompt_dir, default_model=default_model
324
+ )
325
+ self._prompt_dir = prompt_dir
326
+ self._vector_store_name = vector_store_name
327
+
328
+ async def run_agent(self, search_query: str) -> VectorSearchStructure:
329
+ """Execute the entire research workflow for ``search_query``.
330
+
331
+ Parameters
332
+ ----------
333
+ search_query : str
334
+ User's research query.
335
+
336
+ Returns
337
+ -------
338
+ VectorSearchStructure
339
+ Completed research output.
340
+ """
341
+ trace_id = gen_trace_id()
342
+ with trace("VectorSearch trace", trace_id=trace_id):
343
+ planner = VectorSearchPlanner(
344
+ prompt_dir=self._prompt_dir, default_model=self.model
345
+ )
346
+ tool = VectorSearchTool(
347
+ prompt_dir=self._prompt_dir,
348
+ default_model=self.model,
349
+ store_name=self._vector_store_name,
350
+ )
351
+ writer = VectorSearchWriter(
352
+ prompt_dir=self._prompt_dir, default_model=self.model
353
+ )
354
+ search_plan = await planner.run_agent(query=search_query)
355
+ search_results = await tool.run_agent(search_plan=search_plan)
356
+ search_report = await writer.run_agent(search_query, search_results)
357
+ return VectorSearchStructure(
358
+ query=search_query,
359
+ plan=search_plan,
360
+ results=search_results,
361
+ report=search_report,
362
+ )
363
+
364
+ def run_agent_sync(self, search_query: str) -> VectorSearchStructure:
365
+ """Run :meth:`run_agent` synchronously for ``search_query``.
366
+
367
+ Parameters
368
+ ----------
369
+ search_query : str
370
+ User's research query.
371
+
372
+ Returns
373
+ -------
374
+ VectorSearchStructure
375
+ Completed research output.
376
+ """
377
+ return run_coro_sync(self.run_agent(search_query))
378
+
379
+ @staticmethod
380
+ async def run_vector_agent(search_query: str) -> VectorSearchStructure:
381
+ """Return a research report for the given query using ``VectorSearch``.
382
+
383
+ Parameters
384
+ ----------
385
+ search_query : str
386
+ User's research query.
387
+
388
+ Returns
389
+ -------
390
+ VectorSearchStructure
391
+ Completed research output.
392
+ """
393
+ return await VectorSearch().run_agent(search_query=search_query)
394
+
395
+ @staticmethod
396
+ def run_vector_agent_sync(search_query: str) -> VectorSearchStructure:
397
+ """Run :meth:`run_vector_agent` synchronously for ``search_query``.
398
+
399
+ Parameters
400
+ ----------
401
+ search_query : str
402
+ User's research query.
403
+
404
+ Returns
405
+ -------
406
+ VectorSearchStructure
407
+ Completed research output.
408
+ """
409
+ return run_coro_sync(VectorSearch.run_vector_agent(search_query=search_query))
410
+
411
+
412
+ __all__ = [
413
+ "MAX_CONCURRENT_SEARCHES",
414
+ "VectorSearchPlanner",
415
+ "VectorSearchTool",
416
+ "VectorSearchWriter",
417
+ "VectorSearch",
418
+ ]