openai-sdk-helpers 0.0.8__py3-none-any.whl → 0.0.9__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 (64) hide show
  1. openai_sdk_helpers/__init__.py +66 -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 +74 -36
  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 +172 -0
  25. openai_sdk_helpers/response/__init__.py +35 -3
  26. openai_sdk_helpers/response/base.py +363 -210
  27. openai_sdk_helpers/response/config.py +176 -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 +49 -25
  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 +69 -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 +15 -1
  41. openai_sdk_helpers/structure/plan/enum.py +41 -5
  42. openai_sdk_helpers/structure/plan/plan.py +101 -45
  43. openai_sdk_helpers/structure/plan/task.py +38 -6
  44. openai_sdk_helpers/structure/prompt.py +21 -2
  45. openai_sdk_helpers/structure/responses.py +52 -11
  46. openai_sdk_helpers/structure/summary.py +55 -7
  47. openai_sdk_helpers/structure/validation.py +34 -6
  48. openai_sdk_helpers/structure/vector_search.py +132 -18
  49. openai_sdk_helpers/structure/web_search.py +125 -13
  50. openai_sdk_helpers/types.py +57 -0
  51. openai_sdk_helpers/utils/__init__.py +30 -1
  52. openai_sdk_helpers/utils/core.py +168 -34
  53. openai_sdk_helpers/validation.py +302 -0
  54. openai_sdk_helpers/vector_storage/__init__.py +21 -1
  55. openai_sdk_helpers/vector_storage/cleanup.py +25 -13
  56. openai_sdk_helpers/vector_storage/storage.py +123 -64
  57. openai_sdk_helpers/vector_storage/types.py +20 -19
  58. openai_sdk_helpers-0.0.9.dist-info/METADATA +550 -0
  59. openai_sdk_helpers-0.0.9.dist-info/RECORD +66 -0
  60. openai_sdk_helpers/streamlit_app/configuration.py +0 -324
  61. openai_sdk_helpers-0.0.8.dist-info/METADATA +0 -194
  62. openai_sdk_helpers-0.0.8.dist-info/RECORD +0 -55
  63. {openai_sdk_helpers-0.0.8.dist-info → openai_sdk_helpers-0.0.9.dist-info}/WHEEL +0 -0
  64. {openai_sdk_helpers-0.0.8.dist-info → openai_sdk_helpers-0.0.9.dist-info}/licenses/LICENSE +0 -0
@@ -2,7 +2,6 @@
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, Dict, List, Optional, Union
8
7
 
@@ -10,21 +9,21 @@ from agents import custom_span, gen_trace_id, trace
10
9
  from agents.model_settings import ModelSettings
11
10
  from agents.tool import WebSearchTool
12
11
 
13
- from ..structure.web_search import (
12
+ from ...structure.web_search import (
14
13
  WebSearchItemStructure,
15
14
  WebSearchItemResultStructure,
16
15
  WebSearchStructure,
17
16
  WebSearchPlanStructure,
18
17
  WebSearchReportStructure,
19
18
  )
20
- from .base import AgentBase
21
- from .config import AgentConfig
22
- from .utils import run_coroutine_agent_sync
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 WebAgentPlanner(AgentBase):
26
+ class WebAgentPlanner(SearchPlanner[WebSearchPlanStructure]):
28
27
  """Plan web searches to satisfy a user query.
29
28
 
30
29
  Methods
@@ -40,46 +39,33 @@ class WebAgentPlanner(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 web 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="web_planner",
54
59
  description="Agent that plans web searches based on a user query.",
55
60
  output_type=WebSearchPlanStructure,
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) -> WebSearchPlanStructure:
62
- """Plan searches for ``query``.
63
63
 
64
- Parameters
65
- ----------
66
- query : str
67
- User search query.
68
-
69
- Returns
70
- -------
71
- WebSearchPlanStructure
72
- Plan describing searches to perform.
73
- """
74
- result: WebSearchPlanStructure = await self.run_async(
75
- input=query,
76
- output_type=self._output_type,
77
- )
78
-
79
- return result
80
-
81
-
82
- class WebSearchToolAgent(AgentBase):
64
+ class WebSearchToolAgent(
65
+ SearchToolAgent[
66
+ WebSearchItemStructure, WebSearchItemResultStructure, WebSearchPlanStructure
67
+ ]
68
+ ):
83
69
  """Execute web searches defined in a plan.
84
70
 
85
71
  Methods
@@ -97,68 +83,32 @@ class WebSearchToolAgent(AgentBase):
97
83
 
98
84
  Parameters
99
85
  ----------
100
- prompt_dir : pathlib.Path or None, default=None
86
+ prompt_dir : Path or None, default=None
101
87
  Directory containing prompt templates.
102
88
  default_model : str or None, default=None
103
89
  Default model identifier to use when not defined in config.
90
+ """
91
+ super().__init__(
92
+ prompt_dir=prompt_dir,
93
+ default_model=default_model,
94
+ max_concurrent_searches=MAX_CONCURRENT_SEARCHES,
95
+ )
96
+
97
+ def _configure_agent(self) -> AgentConfig:
98
+ """Return configuration for the web search tool agent.
104
99
 
105
100
  Returns
106
101
  -------
107
- None
102
+ AgentConfig
103
+ Configuration with name, description, input type, and tools.
108
104
  """
109
- config = AgentConfig(
105
+ return AgentConfig(
110
106
  name="web_search",
111
107
  description="Agent that performs web searches and summarizes results.",
112
108
  input_type=WebSearchPlanStructure,
113
109
  tools=[WebSearchTool()],
114
110
  model_settings=ModelSettings(tool_choice="required"),
115
111
  )
116
- super().__init__(
117
- config=config, prompt_dir=prompt_dir, default_model=default_model
118
- )
119
-
120
- async def run_agent(
121
- self, search_plan: WebSearchPlanStructure
122
- ) -> List[WebSearchItemResultStructure]:
123
- """Execute all searches in the plan with a progress bar.
124
-
125
- Parameters
126
- ----------
127
- search_plan : WebSearchPlanStructure
128
- Plan describing each search to perform.
129
-
130
- Returns
131
- -------
132
- list[WebSearchItemResultStructure]
133
- Completed search results.
134
- """
135
- with custom_span("Search the web"):
136
- semaphore = asyncio.Semaphore(MAX_CONCURRENT_SEARCHES)
137
-
138
- async def _bounded_search(
139
- item: WebSearchItemStructure,
140
- ) -> WebSearchItemResultStructure:
141
- """Execute a single search within the concurrency limit.
142
-
143
- Parameters
144
- ----------
145
- item : WebSearchItemStructure
146
- Search item to process.
147
-
148
- Returns
149
- -------
150
- WebSearchItemResultStructure
151
- Search result for ``item``.
152
- """
153
- async with semaphore:
154
- return await self.run_search(item)
155
-
156
- tasks = [
157
- asyncio.create_task(_bounded_search(item))
158
- for item in search_plan.searches
159
- ]
160
- results = await asyncio.gather(*tasks)
161
- return [result for result in results if result is not None]
162
112
 
163
113
  async def run_search(
164
114
  self, item: WebSearchItemStructure
@@ -173,25 +123,37 @@ class WebSearchToolAgent(AgentBase):
173
123
  Returns
174
124
  -------
175
125
  WebSearchItemResultStructure
176
- Search result summarising the page.
126
+ Search result summarizing the page.
177
127
  """
178
- template_context: Dict[str, Any] = {
179
- "search_term": item.query,
180
- "reason": item.reason,
181
- }
182
-
183
- result = await super().run_async(
184
- input=item.query,
185
- context=template_context,
186
- output_type=str,
187
- )
188
- return self._coerce_item_result(result)
128
+ with custom_span("Search the web"):
129
+ template_context: Dict[str, Any] = {
130
+ "search_term": item.query,
131
+ "reason": item.reason,
132
+ }
133
+
134
+ result = await super(SearchToolAgent, self).run_async(
135
+ input=item.query,
136
+ context=template_context,
137
+ output_type=str,
138
+ )
139
+ return self._coerce_item_result(result)
189
140
 
190
141
  @staticmethod
191
142
  def _coerce_item_result(
192
143
  result: Union[str, WebSearchItemResultStructure, Any],
193
144
  ) -> WebSearchItemResultStructure:
194
- """Return a WebSearchItemResultStructure from varied agent outputs."""
145
+ """Return a WebSearchItemResultStructure from varied agent outputs.
146
+
147
+ Parameters
148
+ ----------
149
+ result : str or WebSearchItemResultStructure or Any
150
+ Agent output that may be of various types.
151
+
152
+ Returns
153
+ -------
154
+ WebSearchItemResultStructure
155
+ Coerced search result structure.
156
+ """
195
157
  if isinstance(result, WebSearchItemResultStructure):
196
158
  return result
197
159
  try:
@@ -200,7 +162,7 @@ class WebSearchToolAgent(AgentBase):
200
162
  return WebSearchItemResultStructure(text="")
201
163
 
202
164
 
203
- class WebAgentWriter(AgentBase):
165
+ class WebAgentWriter(SearchWriter[WebSearchReportStructure]):
204
166
  """Summarize search results into a human-readable report.
205
167
 
206
168
  Methods
@@ -216,64 +178,38 @@ class WebAgentWriter(AgentBase):
216
178
 
217
179
  Parameters
218
180
  ----------
219
- prompt_dir : pathlib.Path or None, default=None
181
+ prompt_dir : Path or None, default=None
220
182
  Directory containing prompt templates.
221
183
  default_model : str or None, default=None
222
184
  Default model identifier to use when not defined in config.
185
+ """
186
+ super().__init__(prompt_dir=prompt_dir, default_model=default_model)
187
+
188
+ def _configure_agent(self) -> AgentConfig:
189
+ """Return configuration for the web writer agent.
223
190
 
224
191
  Returns
225
192
  -------
226
- None
193
+ AgentConfig
194
+ Configuration with name, description, and output type.
227
195
  """
228
- config = AgentConfig(
196
+ return AgentConfig(
229
197
  name="web_writer",
230
198
  description="Agent that writes a report based on web search results.",
231
199
  output_type=WebSearchReportStructure,
232
200
  )
233
- super().__init__(
234
- config=config, prompt_dir=prompt_dir, default_model=default_model
235
- )
236
-
237
- async def run_agent(
238
- self, query: str, search_results: List[WebSearchItemResultStructure]
239
- ) -> WebSearchReportStructure:
240
- """Compile a report from search results.
241
-
242
- Parameters
243
- ----------
244
- query : str
245
- Original search query.
246
- search_results : list[WebSearchItemResultStructure]
247
- Results produced by the search step.
248
-
249
- Returns
250
- -------
251
- WebSearchReportStructure
252
- Generated report for the query.
253
- """
254
- template_context: Dict[str, Any] = {
255
- "original_query": query,
256
- "search_results": search_results,
257
- }
258
- result: WebSearchReportStructure = await self.run_async(
259
- input=query,
260
- context=template_context,
261
- output_type=self._output_type,
262
- )
263
201
 
264
- return result
265
202
 
266
-
267
- class WebAgentSearch(AgentBase):
203
+ class WebAgentSearch:
268
204
  """Manage the complete web search workflow.
269
205
 
270
206
  Methods
271
207
  -------
272
- run_agent(search_query)
208
+ run_agent_async(search_query)
273
209
  Execute the research workflow asynchronously.
274
210
  run_agent_sync(search_query)
275
211
  Execute the research workflow synchronously.
276
- run_web_agent(search_query)
212
+ run_web_agent_async(search_query)
277
213
  Convenience asynchronous entry point for the workflow.
278
214
  run_web_agent_sync(search_query)
279
215
  Convenience synchronous entry point for the workflow.
@@ -281,7 +217,6 @@ class WebAgentSearch(AgentBase):
281
217
 
282
218
  def __init__(
283
219
  self,
284
- config: Optional[AgentConfig] = None,
285
220
  prompt_dir: Optional[Path] = None,
286
221
  default_model: Optional[str] = None,
287
222
  ) -> None:
@@ -289,27 +224,13 @@ class WebAgentSearch(AgentBase):
289
224
 
290
225
  Parameters
291
226
  ----------
292
- config : AgentConfig or None, default=None
293
- Optional configuration for the agent.
294
- prompt_dir : pathlib.Path or None, default=None
227
+ prompt_dir : Path or None, default=None
295
228
  Directory containing prompt templates.
296
229
  default_model : str or None, default=None
297
230
  Default model identifier to use when not defined in config.
298
-
299
- Returns
300
- -------
301
- None
302
231
  """
303
- if config is None:
304
- config = AgentConfig(
305
- name="web_agent",
306
- description="Agent that coordinates web searches and report writing.",
307
- output_type=WebSearchStructure,
308
- )
309
- super().__init__(
310
- config=config, prompt_dir=prompt_dir, default_model=default_model
311
- )
312
232
  self._prompt_dir = prompt_dir
233
+ self._default_model = default_model
313
234
 
314
235
  async def run_agent_async(self, search_query: str) -> WebSearchStructure:
315
236
  """Execute the entire research workflow for ``search_query``.
@@ -327,13 +248,13 @@ class WebAgentSearch(AgentBase):
327
248
  trace_id = gen_trace_id()
328
249
  with trace("WebAgentSearch trace", trace_id=trace_id):
329
250
  planner = WebAgentPlanner(
330
- prompt_dir=self._prompt_dir, default_model=self.model
251
+ prompt_dir=self._prompt_dir, default_model=self._default_model
331
252
  )
332
253
  tool = WebSearchToolAgent(
333
- prompt_dir=self._prompt_dir, default_model=self.model
254
+ prompt_dir=self._prompt_dir, default_model=self._default_model
334
255
  )
335
256
  writer = WebAgentWriter(
336
- prompt_dir=self._prompt_dir, default_model=self.model
257
+ prompt_dir=self._prompt_dir, default_model=self._default_model
337
258
  )
338
259
  search_plan = await planner.run_agent(query=search_query)
339
260
  search_results = await tool.run_agent(search_plan=search_plan)
@@ -346,7 +267,7 @@ class WebAgentSearch(AgentBase):
346
267
  )
347
268
 
348
269
  def run_agent_sync(self, search_query: str) -> WebSearchStructure:
349
- """Run :meth:`run_agent` synchronously for ``search_query``.
270
+ """Run :meth:`run_agent_async` synchronously for ``search_query``.
350
271
 
351
272
  Parameters
352
273
  ----------
@@ -377,7 +298,7 @@ class WebAgentSearch(AgentBase):
377
298
 
378
299
  @staticmethod
379
300
  def run_web_agent_sync(search_query: str) -> WebSearchStructure:
380
- """Run :meth:`run_web_agent` synchronously for ``search_query``.
301
+ """Run :meth:`run_web_agent_async` synchronously for ``search_query``.
381
302
 
382
303
  Parameters
383
304
  ----------
@@ -14,6 +14,31 @@ from .prompt_utils import DEFAULT_PROMPT_DIR
14
14
  class SummarizerAgent(AgentBase):
15
15
  """Generate concise summaries from provided text.
16
16
 
17
+ This agent uses OpenAI models to create structured summaries from longer-form
18
+ content. The output follows the ``SummaryStructure`` format by default but
19
+ can be customized with a different output type.
20
+
21
+ Examples
22
+ --------
23
+ Basic usage with default settings:
24
+
25
+ >>> from openai_sdk_helpers.agent import SummarizerAgent
26
+ >>> summarizer = SummarizerAgent(default_model="gpt-4o-mini")
27
+ >>> summary = summarizer.run_sync("Long text to summarize...")
28
+ >>> print(summary.text)
29
+
30
+ With custom metadata:
31
+
32
+ >>> import asyncio
33
+ >>> async def main():
34
+ ... summarizer = SummarizerAgent(default_model="gpt-4o-mini")
35
+ ... result = await summarizer.run_agent(
36
+ ... text="Article content...",
37
+ ... metadata={"source": "news.txt", "date": "2025-01-01"}
38
+ ... )
39
+ ... return result
40
+ >>> asyncio.run(main())
41
+
17
42
  Methods
18
43
  -------
19
44
  run_agent(text, metadata)
@@ -31,17 +56,13 @@ class SummarizerAgent(AgentBase):
31
56
 
32
57
  Parameters
33
58
  ----------
34
- prompt_dir : pathlib.Path or None, default=None
59
+ prompt_dir : Path or None, default=None
35
60
  Optional directory containing Jinja prompt templates. Defaults to the
36
61
  packaged ``prompt`` directory when not provided.
37
62
  default_model : str or None, default=None
38
63
  Fallback model identifier when not specified elsewhere.
39
64
  output_type : type, default=SummaryStructure
40
65
  Type describing the expected summary output.
41
-
42
- Returns
43
- -------
44
- None
45
66
  """
46
67
  config = AgentConfig(
47
68
  name="summarizer",
@@ -56,14 +77,14 @@ class SummarizerAgent(AgentBase):
56
77
  async def run_agent(
57
78
  self, text: str, metadata: Optional[Dict[str, Any]] = None
58
79
  ) -> Any:
59
- """Return a summary for ``text``.
80
+ """Generate a summary for ``text``.
60
81
 
61
82
  Parameters
62
83
  ----------
63
84
  text : str
64
85
  Source content to summarize.
65
- metadata : dict, optional
66
- Additional metadata to include in the prompt context. Default ``None``.
86
+ metadata : dict or None, default=None
87
+ Additional metadata to include in the prompt context.
67
88
 
68
89
  Returns
69
90
  -------
@@ -13,6 +13,32 @@ from .prompt_utils import DEFAULT_PROMPT_DIR
13
13
  class TranslatorAgent(AgentBase):
14
14
  """Translate text into a target language.
15
15
 
16
+ This agent provides language translation services using OpenAI models,
17
+ supporting both synchronous and asynchronous execution modes.
18
+
19
+ Examples
20
+ --------
21
+ Basic translation:
22
+
23
+ >>> from openai_sdk_helpers.agent import TranslatorAgent
24
+ >>> translator = TranslatorAgent(default_model="gpt-4o-mini")
25
+ >>> result = translator.run_sync("Hello world", target_language="Spanish")
26
+ >>> print(result)
27
+ 'Hola mundo'
28
+
29
+ Async translation with context:
30
+
31
+ >>> import asyncio
32
+ >>> async def main():
33
+ ... translator = TranslatorAgent(default_model="gpt-4o-mini")
34
+ ... result = await translator.run_agent(
35
+ ... text="Good morning",
36
+ ... target_language="French",
37
+ ... context={"formality": "formal"}
38
+ ... )
39
+ ... return result
40
+ >>> asyncio.run(main())
41
+
16
42
  Methods
17
43
  -------
18
44
  run_agent(text, target_language, context)
@@ -31,15 +57,11 @@ class TranslatorAgent(AgentBase):
31
57
 
32
58
  Parameters
33
59
  ----------
34
- prompt_dir : pathlib.Path or None, default=None
60
+ prompt_dir : Path or None, default=None
35
61
  Optional directory containing Jinja prompt templates. Defaults to the
36
62
  packaged ``prompt`` directory when not provided.
37
63
  default_model : str or None, default=None
38
64
  Fallback model identifier when not specified elsewhere.
39
-
40
- Returns
41
- -------
42
- None
43
65
  """
44
66
  config = AgentConfig(
45
67
  name="translator",
@@ -65,8 +87,8 @@ class TranslatorAgent(AgentBase):
65
87
  Source content to translate.
66
88
  target_language : str
67
89
  Language to translate the content into.
68
- context : dict, optional
69
- Additional context values to merge into the prompt. Default ``None``.
90
+ context : dict or None, default=None
91
+ Additional context values to merge into the prompt.
70
92
 
71
93
  Returns
72
94
  -------
@@ -99,21 +121,26 @@ class TranslatorAgent(AgentBase):
99
121
  ----------
100
122
  input : str
101
123
  Source content to translate.
102
- context : dict, optional
103
- Additional context values to merge into the prompt. Default ``None``.
104
- output_type : type or None, optional
105
- Optional output type cast for the response. Default ``None``.
106
- target_language : str, optional
124
+ context : dict or None, default=None
125
+ Additional context values to merge into the prompt.
126
+ output_type : type or None, default=None
127
+ Optional output type cast for the response.
128
+ target_language : str or None, optional
107
129
  Target language to translate the content into. Required unless supplied
108
130
  within ``context`` or ``kwargs``.
109
131
  **kwargs
110
132
  Optional keyword arguments. ``context`` is accepted as an alias for
111
- ``context`` for backward compatibility.
133
+ backward compatibility.
112
134
 
113
135
  Returns
114
136
  -------
115
137
  str
116
138
  Translated text returned by the agent.
139
+
140
+ Raises
141
+ ------
142
+ ValueError
143
+ If ``target_language`` is not provided.
117
144
  """
118
145
  merged_context: Dict[str, Any] = {}
119
146
 
@@ -14,6 +14,34 @@ from .prompt_utils import DEFAULT_PROMPT_DIR
14
14
  class ValidatorAgent(AgentBase):
15
15
  """Check user prompts and agent responses against safety guardrails.
16
16
 
17
+ This agent validates inputs and outputs to ensure they comply with safety
18
+ policies and usage guidelines, returning structured validation results with
19
+ recommended actions.
20
+
21
+ Examples
22
+ --------
23
+ Validate user input:
24
+
25
+ >>> from openai_sdk_helpers.agent import ValidatorAgent
26
+ >>> validator = ValidatorAgent(default_model="gpt-4o-mini")
27
+ >>> result = validator.run_sync("Tell me about Python programming")
28
+ >>> print(result.input_safe) # True
29
+ >>> print(result.violations) # []
30
+
31
+ Validate both input and output:
32
+
33
+ >>> import asyncio
34
+ >>> async def main():
35
+ ... validator = ValidatorAgent(default_model="gpt-4o-mini")
36
+ ... result = await validator.run_agent(
37
+ ... user_input="Summarize this document",
38
+ ... agent_output="Summary containing PII...",
39
+ ... policy_notes="No PII in outputs"
40
+ ... )
41
+ ... if not result.output_safe:
42
+ ... print(result.sanitized_output)
43
+ >>> asyncio.run(main())
44
+
17
45
  Methods
18
46
  -------
19
47
  run_agent(user_input, agent_output, policy_notes, extra_context)
@@ -30,15 +58,11 @@ class ValidatorAgent(AgentBase):
30
58
 
31
59
  Parameters
32
60
  ----------
33
- prompt_dir : pathlib.Path or None, default=None
61
+ prompt_dir : Path or None, default=None
34
62
  Optional directory containing Jinja prompt templates. Defaults to the
35
63
  packaged ``prompt`` directory when not provided.
36
64
  default_model : str or None, default=None
37
65
  Fallback model identifier when not specified elsewhere.
38
-
39
- Returns
40
- -------
41
- None
42
66
  """
43
67
  config = AgentConfig(
44
68
  name="validator",
@@ -64,13 +88,13 @@ class ValidatorAgent(AgentBase):
64
88
  ----------
65
89
  user_input : str
66
90
  Raw input provided by the user for the agent to evaluate.
67
- agent_output : str, optional
91
+ agent_output : str or None, optional
68
92
  Latest agent response to validate against safety guardrails.
69
93
  Default ``None`` when only the input should be assessed.
70
- policy_notes : str, optional
94
+ policy_notes : str or None, optional
71
95
  Additional policy snippets or guardrail expectations to reinforce.
72
96
  Default ``None``.
73
- extra_context : dict, optional
97
+ extra_context : dict or None, optional
74
98
  Additional fields to merge into the validation context. Default ``None``.
75
99
 
76
100
  Returns