openai-sdk-helpers 0.0.5__py3-none-any.whl → 0.0.6__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 (48) hide show
  1. openai_sdk_helpers/__init__.py +62 -0
  2. openai_sdk_helpers/agent/__init__.py +31 -0
  3. openai_sdk_helpers/agent/base.py +330 -0
  4. openai_sdk_helpers/agent/config.py +66 -0
  5. openai_sdk_helpers/agent/project_manager.py +511 -0
  6. openai_sdk_helpers/agent/prompt_utils.py +9 -0
  7. openai_sdk_helpers/agent/runner.py +215 -0
  8. openai_sdk_helpers/agent/summarizer.py +85 -0
  9. openai_sdk_helpers/agent/translator.py +139 -0
  10. openai_sdk_helpers/agent/utils.py +47 -0
  11. openai_sdk_helpers/agent/validation.py +97 -0
  12. openai_sdk_helpers/agent/vector_search.py +462 -0
  13. openai_sdk_helpers/agent/web_search.py +404 -0
  14. openai_sdk_helpers/config.py +153 -0
  15. openai_sdk_helpers/enums/__init__.py +7 -0
  16. openai_sdk_helpers/enums/base.py +29 -0
  17. openai_sdk_helpers/environment.py +27 -0
  18. openai_sdk_helpers/prompt/__init__.py +77 -0
  19. openai_sdk_helpers/py.typed +0 -0
  20. openai_sdk_helpers/response/__init__.py +18 -0
  21. openai_sdk_helpers/response/base.py +501 -0
  22. openai_sdk_helpers/response/messages.py +211 -0
  23. openai_sdk_helpers/response/runner.py +104 -0
  24. openai_sdk_helpers/response/tool_call.py +70 -0
  25. openai_sdk_helpers/structure/__init__.py +43 -0
  26. openai_sdk_helpers/structure/agent_blueprint.py +224 -0
  27. openai_sdk_helpers/structure/base.py +713 -0
  28. openai_sdk_helpers/structure/plan/__init__.py +13 -0
  29. openai_sdk_helpers/structure/plan/enum.py +64 -0
  30. openai_sdk_helpers/structure/plan/plan.py +253 -0
  31. openai_sdk_helpers/structure/plan/task.py +122 -0
  32. openai_sdk_helpers/structure/prompt.py +24 -0
  33. openai_sdk_helpers/structure/responses.py +132 -0
  34. openai_sdk_helpers/structure/summary.py +65 -0
  35. openai_sdk_helpers/structure/validation.py +47 -0
  36. openai_sdk_helpers/structure/vector_search.py +86 -0
  37. openai_sdk_helpers/structure/web_search.py +46 -0
  38. openai_sdk_helpers/utils/__init__.py +13 -0
  39. openai_sdk_helpers/utils/core.py +208 -0
  40. openai_sdk_helpers/vector_storage/__init__.py +15 -0
  41. openai_sdk_helpers/vector_storage/cleanup.py +91 -0
  42. openai_sdk_helpers/vector_storage/storage.py +501 -0
  43. openai_sdk_helpers/vector_storage/types.py +58 -0
  44. {openai_sdk_helpers-0.0.5.dist-info → openai_sdk_helpers-0.0.6.dist-info}/METADATA +1 -1
  45. openai_sdk_helpers-0.0.6.dist-info/RECORD +50 -0
  46. openai_sdk_helpers-0.0.5.dist-info/RECORD +0 -7
  47. {openai_sdk_helpers-0.0.5.dist-info → openai_sdk_helpers-0.0.6.dist-info}/WHEEL +0 -0
  48. {openai_sdk_helpers-0.0.5.dist-info → openai_sdk_helpers-0.0.6.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,215 @@
1
+ """Convenience wrappers for running OpenAI agents.
2
+
3
+ These helpers provide a narrow surface around the lower-level functions in
4
+ ``openai-sdk-helpers.agent.base`` so that callers can execute agents with consistent
5
+ signatures whether they need asynchronous, synchronous, or streamed results.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Any, Dict, Optional
11
+ import asyncio
12
+ import threading
13
+ from agents import Agent, Runner, RunResult, RunResultStreaming
14
+
15
+
16
+ async def _run_async(
17
+ agent: Agent,
18
+ input: str,
19
+ context: Optional[Dict[str, Any]] = None,
20
+ output_type: Optional[Any] = None,
21
+ ) -> Any:
22
+ """Run an ``Agent`` asynchronously.
23
+
24
+ Parameters
25
+ ----------
26
+ agent
27
+ Configured agent instance to execute.
28
+ input
29
+ Prompt or query string for the agent.
30
+ context
31
+ Optional context dictionary passed to the agent. Default ``None``.
32
+ output_type
33
+ Optional type used to cast the final output. Default ``None``.
34
+
35
+ Returns
36
+ -------
37
+ Any
38
+ Agent response, optionally converted to ``output_type``.
39
+ """
40
+ result = await Runner.run(agent, input, context=context)
41
+ if output_type is not None:
42
+ result = result.final_output_as(output_type)
43
+ return result
44
+
45
+
46
+ def _run_sync(
47
+ agent: Agent,
48
+ input: str,
49
+ context: Optional[Dict[str, Any]] = None,
50
+ ) -> RunResult:
51
+ """Run an ``Agent`` synchronously.
52
+
53
+ Parameters
54
+ ----------
55
+ agent
56
+ Configured agent instance to execute.
57
+ input
58
+ Prompt or query string for the agent.
59
+ context
60
+ Optional context dictionary passed to the agent. Default ``None``.
61
+
62
+ Returns
63
+ -------
64
+ RunResult
65
+ Result from the agent execution.
66
+ """
67
+ coro = Runner.run(agent, input, context=context)
68
+ try:
69
+ loop = asyncio.get_running_loop()
70
+ except RuntimeError:
71
+ return asyncio.run(coro)
72
+
73
+ if loop.is_running():
74
+ result: RunResult | None = None
75
+
76
+ def _thread_runner() -> None:
77
+ nonlocal result
78
+ result = asyncio.run(coro)
79
+
80
+ thread = threading.Thread(target=_thread_runner, daemon=True)
81
+ thread.start()
82
+ thread.join()
83
+ if result is None:
84
+ raise RuntimeError("Agent execution did not return a result.")
85
+ return result
86
+
87
+ return loop.run_until_complete(coro)
88
+
89
+
90
+ def _run_streamed(
91
+ agent: Agent,
92
+ input: str,
93
+ context: Optional[Dict[str, Any]] = None,
94
+ ) -> RunResultStreaming:
95
+ """Run an ``Agent`` synchronously and return a streaming result.
96
+
97
+ Parameters
98
+ ----------
99
+ agent
100
+ Configured agent to execute.
101
+ input
102
+ Prompt or query string for the agent.
103
+ context
104
+ Optional context dictionary passed to the agent. Default ``None``.
105
+
106
+ Returns
107
+ -------
108
+ RunResultStreaming
109
+ Instance for streaming outputs.
110
+ """
111
+ result = Runner.run_streamed(agent, input, context=context)
112
+ return result
113
+
114
+
115
+ async def run_async(
116
+ agent: Agent,
117
+ input: str,
118
+ context: Optional[Dict[str, Any]] = None,
119
+ output_type: Optional[Any] = None,
120
+ ) -> Any:
121
+ """Run an ``Agent`` asynchronously.
122
+
123
+ Parameters
124
+ ----------
125
+ agent
126
+ Configured agent instance to execute.
127
+ input
128
+ Prompt or query string for the agent.
129
+ context
130
+ Optional context dictionary passed to the agent. Default ``None``.
131
+ output_type
132
+ Optional type used to cast the final output. Default ``None``.
133
+
134
+ Returns
135
+ -------
136
+ Any
137
+ Agent response, optionally converted to ``output_type``.
138
+ """
139
+ return await _run_async(
140
+ agent=agent,
141
+ input=input,
142
+ context=context,
143
+ output_type=output_type,
144
+ )
145
+
146
+
147
+ def run_sync(
148
+ agent: Agent,
149
+ input: str,
150
+ context: Optional[Dict[str, Any]] = None,
151
+ output_type: Optional[Any] = None,
152
+ ) -> Any:
153
+ """Run an ``Agent`` synchronously.
154
+
155
+ Parameters
156
+ ----------
157
+ agent
158
+ Configured agent instance to execute.
159
+ input
160
+ Prompt or query string for the agent.
161
+ context
162
+ Optional context dictionary passed to the agent. Default ``None``.
163
+ output_type
164
+ Optional type used to cast the final output. Default ``None``.
165
+
166
+ Returns
167
+ -------
168
+ Any
169
+ Agent response, optionally converted to ``output_type``.
170
+ """
171
+ result: RunResult = _run_sync(
172
+ agent=agent,
173
+ input=input,
174
+ context=context,
175
+ )
176
+ if output_type:
177
+ return result.final_output_as(output_type)
178
+ return result
179
+
180
+
181
+ def run_streamed(
182
+ agent: Agent,
183
+ input: str,
184
+ context: Optional[Dict[str, Any]] = None,
185
+ output_type: Optional[Any] = None,
186
+ ) -> RunResultStreaming:
187
+ """Run an ``Agent`` and return a streaming result.
188
+
189
+ Parameters
190
+ ----------
191
+ agent
192
+ Configured agent instance to execute.
193
+ input
194
+ Prompt or query string for the agent.
195
+ context
196
+ Optional context dictionary passed to the agent. Default ``None``.
197
+ output_type
198
+ Optional type used to cast the final output. Default ``None``.
199
+
200
+ Returns
201
+ -------
202
+ RunResultStreaming
203
+ Streaming output wrapper from the agent execution.
204
+ """
205
+ result = _run_streamed(
206
+ agent=agent,
207
+ input=input,
208
+ context=context,
209
+ )
210
+ if output_type:
211
+ return result.final_output_as(output_type)
212
+ return result
213
+
214
+
215
+ __all__ = ["run_sync", "run_async", "run_streamed"]
@@ -0,0 +1,85 @@
1
+ """Lightweight agent for summarizing text."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Any, Dict, Optional
7
+
8
+ from ..structure import SummaryStructure
9
+ from .base import AgentBase
10
+ from .config import AgentConfig
11
+ from .prompt_utils import DEFAULT_PROMPT_DIR
12
+
13
+
14
+ class SummarizerAgent(AgentBase):
15
+ """Generate concise summaries from provided text.
16
+
17
+ Methods
18
+ -------
19
+ run_agent(text, metadata)
20
+ Summarize the supplied text with optional metadata context.
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ *,
26
+ prompt_dir: Optional[Path] = None,
27
+ default_model: Optional[str] = None,
28
+ output_type: type[Any] = SummaryStructure,
29
+ ) -> None:
30
+ """Initialize the summarizer agent configuration.
31
+
32
+ Parameters
33
+ ----------
34
+ prompt_dir : pathlib.Path or None, default=None
35
+ Optional directory containing Jinja prompt templates. Defaults to the
36
+ packaged ``prompt`` directory when not provided.
37
+ default_model : str or None, default=None
38
+ Fallback model identifier when not specified elsewhere.
39
+ output_type : type, default=SummaryStructure
40
+ Type describing the expected summary output.
41
+
42
+ Returns
43
+ -------
44
+ None
45
+ """
46
+ config = AgentConfig(
47
+ name="summarizer",
48
+ description="Summarize passages into concise findings.",
49
+ output_type=output_type,
50
+ )
51
+ prompt_directory = prompt_dir or DEFAULT_PROMPT_DIR
52
+ super().__init__(
53
+ config=config, prompt_dir=prompt_directory, default_model=default_model
54
+ )
55
+
56
+ async def run_agent(
57
+ self, text: str, metadata: Optional[Dict[str, Any]] = None
58
+ ) -> Any:
59
+ """Return a summary for ``text``.
60
+
61
+ Parameters
62
+ ----------
63
+ text : str
64
+ Source content to summarize.
65
+ metadata : dict, optional
66
+ Additional metadata to include in the prompt context. Default ``None``.
67
+
68
+ Returns
69
+ -------
70
+ Any
71
+ Structured summary produced by the agent.
72
+ """
73
+ context: Optional[Dict[str, Any]] = None
74
+ if metadata:
75
+ context = {"metadata": metadata}
76
+
77
+ result = await self.run_async(
78
+ input=text,
79
+ context=context,
80
+ output_type=self._output_type,
81
+ )
82
+ return result
83
+
84
+
85
+ __all__ = ["SummarizerAgent"]
@@ -0,0 +1,139 @@
1
+ """Lightweight agent for translating text into a target language."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Any, Dict, Optional
7
+
8
+ from .base import AgentBase
9
+ from .config import AgentConfig
10
+ from .prompt_utils import DEFAULT_PROMPT_DIR
11
+
12
+
13
+ class TranslatorAgent(AgentBase):
14
+ """Translate text into a target language.
15
+
16
+ Methods
17
+ -------
18
+ run_agent(text, target_language, context)
19
+ Translate the supplied text into the target language.
20
+ run_sync(text, target_language, context)
21
+ Translate the supplied text synchronously.
22
+ """
23
+
24
+ def __init__(
25
+ self,
26
+ *,
27
+ prompt_dir: Optional[Path] = None,
28
+ default_model: Optional[str] = None,
29
+ ) -> None:
30
+ """Initialize the translation agent configuration.
31
+
32
+ Parameters
33
+ ----------
34
+ prompt_dir : pathlib.Path or None, default=None
35
+ Optional directory containing Jinja prompt templates. Defaults to the
36
+ packaged ``prompt`` directory when not provided.
37
+ default_model : str or None, default=None
38
+ Fallback model identifier when not specified elsewhere.
39
+
40
+ Returns
41
+ -------
42
+ None
43
+ """
44
+ config = AgentConfig(
45
+ name="translator",
46
+ description="Translate text into the requested language.",
47
+ output_type=str,
48
+ )
49
+ prompt_directory = prompt_dir or DEFAULT_PROMPT_DIR
50
+ super().__init__(
51
+ config=config, prompt_dir=prompt_directory, default_model=default_model
52
+ )
53
+
54
+ async def run_agent(
55
+ self,
56
+ text: str,
57
+ target_language: str,
58
+ context: Optional[Dict[str, Any]] = None,
59
+ ) -> str:
60
+ """Translate ``text`` to ``target_language``.
61
+
62
+ Parameters
63
+ ----------
64
+ text : str
65
+ Source content to translate.
66
+ target_language : str
67
+ Language to translate the content into.
68
+ context : dict, optional
69
+ Additional context values to merge into the prompt. Default ``None``.
70
+
71
+ Returns
72
+ -------
73
+ str
74
+ Translated text returned by the agent.
75
+ """
76
+ template_context: Dict[str, Any] = {"target_language": target_language}
77
+ if context:
78
+ template_context.update(context)
79
+
80
+ result: str = await self.run_async(
81
+ input=text,
82
+ context=template_context,
83
+ output_type=str,
84
+ )
85
+ return result
86
+
87
+ def run_sync(
88
+ self,
89
+ input: str,
90
+ context: Optional[Dict[str, Any]] = None,
91
+ output_type: Optional[Any] = None,
92
+ *,
93
+ target_language: Optional[str] = None,
94
+ **kwargs: Any,
95
+ ) -> str:
96
+ """Translate ``input`` to ``target_language`` synchronously.
97
+
98
+ Parameters
99
+ ----------
100
+ input : str
101
+ 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
107
+ Target language to translate the content into. Required unless supplied
108
+ within ``context`` or ``kwargs``.
109
+ **kwargs
110
+ Optional keyword arguments. ``context`` is accepted as an alias for
111
+ ``context`` for backward compatibility.
112
+
113
+ Returns
114
+ -------
115
+ str
116
+ Translated text returned by the agent.
117
+ """
118
+ merged_context: Dict[str, Any] = {}
119
+
120
+ if context:
121
+ merged_context.update(context)
122
+ if "context" in kwargs and kwargs["context"]:
123
+ merged_context.update(kwargs["context"])
124
+ if target_language:
125
+ merged_context["target_language"] = target_language
126
+
127
+ if "target_language" not in merged_context:
128
+ msg = "target_language is required for translation"
129
+ raise ValueError(msg)
130
+
131
+ result: str = super().run_sync(
132
+ input=input,
133
+ context=merged_context,
134
+ output_type=output_type or str,
135
+ )
136
+ return result
137
+
138
+
139
+ __all__ = ["TranslatorAgent"]
@@ -0,0 +1,47 @@
1
+ """Utility helpers for synchronous interaction with async agents."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import threading
7
+ from typing import Any, Coroutine, TypeVar
8
+
9
+ T = TypeVar("T")
10
+
11
+
12
+ def run_coroutine_agent_sync(coro: Coroutine[Any, Any, T]) -> T:
13
+ """Run a coroutine from synchronous code.
14
+
15
+ Parameters
16
+ ----------
17
+ coro : Coroutine[Any, Any, T]
18
+ Coroutine to execute.
19
+
20
+ Returns
21
+ -------
22
+ T
23
+ Result returned by the coroutine.
24
+ """
25
+ try:
26
+ loop = asyncio.get_running_loop()
27
+ except RuntimeError:
28
+ return asyncio.run(coro)
29
+
30
+ if loop.is_running():
31
+ result: T | None = None
32
+
33
+ def _thread_runner() -> None:
34
+ nonlocal result
35
+ result = asyncio.run(coro)
36
+
37
+ thread = threading.Thread(target=_thread_runner, daemon=True)
38
+ thread.start()
39
+ thread.join()
40
+ if result is None:
41
+ raise RuntimeError("Coroutine execution did not return a result.")
42
+ return result
43
+
44
+ return loop.run_until_complete(coro)
45
+
46
+
47
+ __all__ = ["run_coroutine_agent_sync"]
@@ -0,0 +1,97 @@
1
+ """Agent helper for validating inputs and outputs against guardrails."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Any, Dict, Optional
7
+
8
+ from ..structure.validation import ValidationResultStructure
9
+ from .base import AgentBase
10
+ from .config import AgentConfig
11
+ from .prompt_utils import DEFAULT_PROMPT_DIR
12
+
13
+
14
+ class ValidatorAgent(AgentBase):
15
+ """Check user prompts and agent responses against safety guardrails.
16
+
17
+ Methods
18
+ -------
19
+ run_agent(user_input, agent_output, policy_notes, extra_context)
20
+ Validate user and agent messages and return a structured report.
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ *,
26
+ prompt_dir: Optional[Path] = None,
27
+ default_model: Optional[str] = None,
28
+ ) -> None:
29
+ """Initialize the validator agent configuration.
30
+
31
+ Parameters
32
+ ----------
33
+ prompt_dir : pathlib.Path or None, default=None
34
+ Optional directory containing Jinja prompt templates. Defaults to the
35
+ packaged ``prompt`` directory when not provided.
36
+ default_model : str or None, default=None
37
+ Fallback model identifier when not specified elsewhere.
38
+
39
+ Returns
40
+ -------
41
+ None
42
+ """
43
+ config = AgentConfig(
44
+ name="validator",
45
+ description="Validate user input and agent output against guardrails.",
46
+ output_type=ValidationResultStructure,
47
+ )
48
+ prompt_directory = prompt_dir or DEFAULT_PROMPT_DIR
49
+ super().__init__(
50
+ config=config, prompt_dir=prompt_directory, default_model=default_model
51
+ )
52
+
53
+ async def run_agent(
54
+ self,
55
+ user_input: str,
56
+ *,
57
+ agent_output: Optional[str] = None,
58
+ policy_notes: Optional[str] = None,
59
+ extra_context: Optional[Dict[str, Any]] = None,
60
+ ) -> ValidationResultStructure:
61
+ """Validate user and agent messages.
62
+
63
+ Parameters
64
+ ----------
65
+ user_input : str
66
+ Raw input provided by the user for the agent to evaluate.
67
+ agent_output : str, optional
68
+ Latest agent response to validate against safety guardrails.
69
+ Default ``None`` when only the input should be assessed.
70
+ policy_notes : str, optional
71
+ Additional policy snippets or guardrail expectations to reinforce.
72
+ Default ``None``.
73
+ extra_context : dict, optional
74
+ Additional fields to merge into the validation context. Default ``None``.
75
+
76
+ Returns
77
+ -------
78
+ ValidationResultStructure
79
+ Structured validation result describing any violations and actions.
80
+ """
81
+ context: Dict[str, Any] = {"user_input": user_input}
82
+ if agent_output is not None:
83
+ context["agent_output"] = agent_output
84
+ if policy_notes is not None:
85
+ context["policy_notes"] = policy_notes
86
+ if extra_context:
87
+ context.update(extra_context)
88
+
89
+ result: ValidationResultStructure = await self.run_async(
90
+ input=user_input,
91
+ context=context,
92
+ output_type=ValidationResultStructure,
93
+ )
94
+ return result
95
+
96
+
97
+ __all__ = ["ValidatorAgent"]