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.
- openai_sdk_helpers/__init__.py +90 -2
- openai_sdk_helpers/agent/__init__.py +8 -4
- openai_sdk_helpers/agent/base.py +80 -45
- openai_sdk_helpers/agent/config.py +6 -4
- openai_sdk_helpers/agent/{project_manager.py → coordination.py} +29 -45
- openai_sdk_helpers/agent/prompt_utils.py +7 -1
- openai_sdk_helpers/agent/runner.py +67 -141
- openai_sdk_helpers/agent/search/__init__.py +33 -0
- openai_sdk_helpers/agent/search/base.py +297 -0
- openai_sdk_helpers/agent/{vector_search.py → search/vector.py} +89 -157
- openai_sdk_helpers/agent/{web_search.py → search/web.py} +77 -156
- openai_sdk_helpers/agent/summarizer.py +29 -8
- openai_sdk_helpers/agent/translator.py +40 -13
- openai_sdk_helpers/agent/validation.py +32 -8
- openai_sdk_helpers/async_utils.py +132 -0
- openai_sdk_helpers/config.py +101 -65
- openai_sdk_helpers/context_manager.py +241 -0
- openai_sdk_helpers/enums/__init__.py +9 -1
- openai_sdk_helpers/enums/base.py +67 -8
- openai_sdk_helpers/environment.py +33 -6
- openai_sdk_helpers/errors.py +133 -0
- openai_sdk_helpers/logging_config.py +105 -0
- openai_sdk_helpers/prompt/__init__.py +10 -71
- openai_sdk_helpers/prompt/base.py +222 -0
- openai_sdk_helpers/response/__init__.py +38 -3
- openai_sdk_helpers/response/base.py +363 -210
- openai_sdk_helpers/response/config.py +318 -0
- openai_sdk_helpers/response/messages.py +56 -40
- openai_sdk_helpers/response/runner.py +77 -33
- openai_sdk_helpers/response/tool_call.py +62 -27
- openai_sdk_helpers/response/vector_store.py +27 -14
- openai_sdk_helpers/retry.py +175 -0
- openai_sdk_helpers/streamlit_app/__init__.py +19 -2
- openai_sdk_helpers/streamlit_app/app.py +114 -39
- openai_sdk_helpers/streamlit_app/config.py +502 -0
- openai_sdk_helpers/streamlit_app/streamlit_web_search.py +5 -6
- openai_sdk_helpers/structure/__init__.py +72 -3
- openai_sdk_helpers/structure/agent_blueprint.py +82 -19
- openai_sdk_helpers/structure/base.py +208 -93
- openai_sdk_helpers/structure/plan/__init__.py +29 -1
- openai_sdk_helpers/structure/plan/enum.py +41 -5
- openai_sdk_helpers/structure/plan/helpers.py +172 -0
- openai_sdk_helpers/structure/plan/plan.py +109 -49
- openai_sdk_helpers/structure/plan/task.py +38 -6
- openai_sdk_helpers/structure/plan/types.py +15 -0
- openai_sdk_helpers/structure/prompt.py +21 -2
- openai_sdk_helpers/structure/responses.py +52 -11
- openai_sdk_helpers/structure/summary.py +55 -7
- openai_sdk_helpers/structure/validation.py +34 -6
- openai_sdk_helpers/structure/vector_search.py +132 -18
- openai_sdk_helpers/structure/web_search.py +125 -13
- openai_sdk_helpers/tools.py +193 -0
- openai_sdk_helpers/types.py +57 -0
- openai_sdk_helpers/utils/__init__.py +34 -1
- openai_sdk_helpers/utils/core.py +296 -34
- openai_sdk_helpers/validation.py +302 -0
- openai_sdk_helpers/vector_storage/__init__.py +21 -1
- openai_sdk_helpers/vector_storage/cleanup.py +25 -13
- openai_sdk_helpers/vector_storage/storage.py +123 -64
- openai_sdk_helpers/vector_storage/types.py +20 -19
- openai_sdk_helpers-0.1.0.dist-info/METADATA +550 -0
- openai_sdk_helpers-0.1.0.dist-info/RECORD +69 -0
- openai_sdk_helpers/streamlit_app/configuration.py +0 -324
- openai_sdk_helpers-0.0.8.dist-info/METADATA +0 -194
- openai_sdk_helpers-0.0.8.dist-info/RECORD +0 -55
- {openai_sdk_helpers-0.0.8.dist-info → openai_sdk_helpers-0.1.0.dist-info}/WHEEL +0 -0
- {openai_sdk_helpers-0.0.8.dist-info → openai_sdk_helpers-0.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"""Core prompt rendering implementation.
|
|
2
|
+
|
|
3
|
+
This module provides the PromptRenderer class for loading and rendering
|
|
4
|
+
Jinja2 templates with context variables. Templates can be loaded from a
|
|
5
|
+
specified directory or by absolute path. Includes template caching for
|
|
6
|
+
improved performance.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import warnings
|
|
12
|
+
from functools import lru_cache
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from dotenv import load_dotenv
|
|
17
|
+
from jinja2 import Environment, FileSystemLoader, Template
|
|
18
|
+
|
|
19
|
+
load_dotenv()
|
|
20
|
+
warnings.filterwarnings("ignore")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class PromptRenderer:
|
|
24
|
+
"""Jinja2-based template renderer for dynamic prompt generation.
|
|
25
|
+
|
|
26
|
+
Loads and renders Jinja2 templates from a base directory or by absolute
|
|
27
|
+
path. The renderer supports variable substitution, template inheritance,
|
|
28
|
+
and all standard Jinja2 features for creating dynamic prompts. Templates
|
|
29
|
+
are cached using LRU cache for improved performance on repeated renders.
|
|
30
|
+
|
|
31
|
+
Templates are loaded from a base directory (defaulting to the built-in
|
|
32
|
+
prompt package directory) or can be specified with absolute paths.
|
|
33
|
+
Autoescape is disabled by default since prompts are plain text.
|
|
34
|
+
|
|
35
|
+
Attributes
|
|
36
|
+
----------
|
|
37
|
+
base_dir : Path
|
|
38
|
+
Base directory for template loading.
|
|
39
|
+
|
|
40
|
+
Methods
|
|
41
|
+
-------
|
|
42
|
+
render(template_path, context=None)
|
|
43
|
+
Render a Jinja2 template with the given context variables.
|
|
44
|
+
clear_cache()
|
|
45
|
+
Clear the template compilation cache.
|
|
46
|
+
|
|
47
|
+
Examples
|
|
48
|
+
--------
|
|
49
|
+
Basic template rendering with custom base directory:
|
|
50
|
+
|
|
51
|
+
>>> from pathlib import Path
|
|
52
|
+
>>> from openai_sdk_helpers.prompt import PromptRenderer
|
|
53
|
+
>>> renderer = PromptRenderer(base_dir=Path("./templates"))
|
|
54
|
+
>>> prompt = renderer.render(
|
|
55
|
+
... "greeting.jinja",
|
|
56
|
+
... context={"name": "Alice", "language": "English"}
|
|
57
|
+
... )
|
|
58
|
+
>>> print(prompt)
|
|
59
|
+
|
|
60
|
+
Using absolute path (no base_dir required):
|
|
61
|
+
|
|
62
|
+
>>> renderer = PromptRenderer()
|
|
63
|
+
>>> prompt = renderer.render(
|
|
64
|
+
... "/absolute/path/to/template.jinja",
|
|
65
|
+
... context={"name": "Bob"}
|
|
66
|
+
... )
|
|
67
|
+
|
|
68
|
+
Using built-in templates:
|
|
69
|
+
|
|
70
|
+
>>> renderer = PromptRenderer() # Uses built-in templates
|
|
71
|
+
>>> prompt = renderer.render("summarizer.jinja", context={})
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
def __init__(self, base_dir: Path | None = None) -> None:
|
|
75
|
+
"""Initialize the renderer with a Jinja2 environment.
|
|
76
|
+
|
|
77
|
+
Sets up the Jinja2 environment with a FileSystemLoader pointing to
|
|
78
|
+
the specified base directory. If no base directory is provided,
|
|
79
|
+
defaults to the built-in prompt package directory containing
|
|
80
|
+
standard templates.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
base_dir : Path or None, default None
|
|
85
|
+
Base directory containing Jinja2 templates. If None, uses the
|
|
86
|
+
prompt package directory containing built-in templates.
|
|
87
|
+
|
|
88
|
+
Examples
|
|
89
|
+
--------
|
|
90
|
+
>>> from pathlib import Path
|
|
91
|
+
>>> renderer = PromptRenderer(base_dir=Path("./my_templates"))
|
|
92
|
+
>>> renderer.base_dir
|
|
93
|
+
PosixPath('.../my_templates')
|
|
94
|
+
|
|
95
|
+
>>> default_renderer = PromptRenderer()
|
|
96
|
+
>>> default_renderer.base_dir.name
|
|
97
|
+
'prompt'
|
|
98
|
+
"""
|
|
99
|
+
if base_dir is None:
|
|
100
|
+
# Defaults to the directory containing this file, which also
|
|
101
|
+
# contains the builtin prompt templates.
|
|
102
|
+
self.base_dir = Path(__file__).resolve().parent
|
|
103
|
+
else:
|
|
104
|
+
self.base_dir = base_dir
|
|
105
|
+
|
|
106
|
+
self._env = Environment(
|
|
107
|
+
loader=FileSystemLoader(str(self.base_dir)),
|
|
108
|
+
autoescape=False, # Prompts are plain text
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
@lru_cache(maxsize=128)
|
|
112
|
+
def _compile_template(self, template_path_str: str) -> Template:
|
|
113
|
+
"""Compile a template by path with LRU caching.
|
|
114
|
+
|
|
115
|
+
Parameters
|
|
116
|
+
----------
|
|
117
|
+
template_path_str : str
|
|
118
|
+
Absolute path to the template file.
|
|
119
|
+
|
|
120
|
+
Returns
|
|
121
|
+
-------
|
|
122
|
+
Template
|
|
123
|
+
Compiled Jinja2 template ready for rendering.
|
|
124
|
+
"""
|
|
125
|
+
template_text = Path(template_path_str).read_text()
|
|
126
|
+
return Template(template_text)
|
|
127
|
+
|
|
128
|
+
def render(self, template_path: str, context: dict[str, Any] | None = None) -> str:
|
|
129
|
+
"""Render a Jinja2 template with the given context variables.
|
|
130
|
+
|
|
131
|
+
Loads the template from either an absolute path or a path relative
|
|
132
|
+
to the base directory. The template is rendered with the provided
|
|
133
|
+
context dictionary using Jinja2's template engine. Templates are
|
|
134
|
+
cached for improved performance on repeated renders.
|
|
135
|
+
|
|
136
|
+
For security, relative paths are validated to prevent path traversal
|
|
137
|
+
attacks. Absolute paths are allowed but should be used with caution
|
|
138
|
+
as they bypass base directory restrictions.
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
template_path : str
|
|
143
|
+
Path to the template file. Can be an absolute path or relative
|
|
144
|
+
to base_dir.
|
|
145
|
+
context : dict[str, Any] or None, default None
|
|
146
|
+
Context variables to pass to the template. If None, an empty
|
|
147
|
+
dictionary is used.
|
|
148
|
+
|
|
149
|
+
Returns
|
|
150
|
+
-------
|
|
151
|
+
str
|
|
152
|
+
Fully rendered template as a string.
|
|
153
|
+
|
|
154
|
+
Raises
|
|
155
|
+
------
|
|
156
|
+
FileNotFoundError
|
|
157
|
+
If the template file does not exist at the specified path.
|
|
158
|
+
InputValidationError
|
|
159
|
+
If the path contains suspicious patterns or attempts to escape
|
|
160
|
+
the base directory.
|
|
161
|
+
TemplateNotFound
|
|
162
|
+
If the template cannot be loaded by Jinja2.
|
|
163
|
+
|
|
164
|
+
Examples
|
|
165
|
+
--------
|
|
166
|
+
>>> renderer = PromptRenderer()
|
|
167
|
+
>>> context = {"name": "Alice", "age": 30}
|
|
168
|
+
>>> result = renderer.render("greeting.jinja", context)
|
|
169
|
+
>>> "Alice" in result
|
|
170
|
+
True
|
|
171
|
+
|
|
172
|
+
With absolute path:
|
|
173
|
+
|
|
174
|
+
>>> result = renderer.render(
|
|
175
|
+
... "/path/to/template.jinja",
|
|
176
|
+
... context={"key": "value"}
|
|
177
|
+
... )
|
|
178
|
+
"""
|
|
179
|
+
from openai_sdk_helpers.validation import validate_safe_path
|
|
180
|
+
|
|
181
|
+
path = Path(template_path)
|
|
182
|
+
if path.is_absolute():
|
|
183
|
+
# Absolute paths allowed but not validated against base_dir
|
|
184
|
+
template_path_ = path
|
|
185
|
+
else:
|
|
186
|
+
# Relative paths validated to prevent directory traversal
|
|
187
|
+
template_path_ = validate_safe_path(
|
|
188
|
+
self.base_dir / template_path,
|
|
189
|
+
base_dir=self.base_dir,
|
|
190
|
+
field_name="template_path",
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Check if template exists and provide clear error message
|
|
194
|
+
if not template_path_.exists():
|
|
195
|
+
raise FileNotFoundError(
|
|
196
|
+
f"Template not found: {template_path_}. "
|
|
197
|
+
f"Ensure the template exists in {self.base_dir} or provide an absolute path."
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# Cache-compile template by path (not by content)
|
|
201
|
+
template = self._compile_template(str(template_path_))
|
|
202
|
+
return template.render(context or {})
|
|
203
|
+
|
|
204
|
+
def clear_cache(self) -> None:
|
|
205
|
+
"""Clear the template compilation cache.
|
|
206
|
+
|
|
207
|
+
Useful when templates are modified during runtime and need to be
|
|
208
|
+
reloaded. Call this method to force re-compilation of all templates
|
|
209
|
+
on next render.
|
|
210
|
+
|
|
211
|
+
Examples
|
|
212
|
+
--------
|
|
213
|
+
>>> renderer = PromptRenderer()
|
|
214
|
+
>>> renderer.render("template.jinja", {}) # Compiles and caches
|
|
215
|
+
>>> # ... modify template.jinja ...
|
|
216
|
+
>>> renderer.clear_cache() # Clear cache
|
|
217
|
+
>>> renderer.render("template.jinja", {}) # Re-compiles
|
|
218
|
+
"""
|
|
219
|
+
self._compile_template.cache_clear()
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
__all__ = ["PromptRenderer"]
|
|
@@ -1,20 +1,55 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Response handling for OpenAI API interactions.
|
|
2
|
+
|
|
3
|
+
This module provides comprehensive support for managing OpenAI API responses,
|
|
4
|
+
including message handling, tool execution, vector store attachments, and
|
|
5
|
+
structured output parsing. It serves as the foundation for building
|
|
6
|
+
sophisticated AI agents with persistent conversation state.
|
|
7
|
+
|
|
8
|
+
Classes
|
|
9
|
+
-------
|
|
10
|
+
BaseResponse
|
|
11
|
+
Core response manager for OpenAI interactions with structured outputs.
|
|
12
|
+
ResponseConfiguration
|
|
13
|
+
Immutable configuration for defining request/response structures.
|
|
14
|
+
ResponseMessage
|
|
15
|
+
Single message exchanged with the OpenAI client.
|
|
16
|
+
ResponseMessages
|
|
17
|
+
Collection of messages in a response conversation.
|
|
18
|
+
ResponseToolCall
|
|
19
|
+
Container for tool call data and formatting.
|
|
20
|
+
|
|
21
|
+
Functions
|
|
22
|
+
---------
|
|
23
|
+
run_sync
|
|
24
|
+
Execute a response workflow synchronously with resource cleanup.
|
|
25
|
+
run_async
|
|
26
|
+
Execute a response workflow asynchronously with resource cleanup.
|
|
27
|
+
run_streamed
|
|
28
|
+
Execute a response workflow and return the asynchronous result.
|
|
29
|
+
attach_vector_store
|
|
30
|
+
Attach vector stores to a response's file_search tool.
|
|
31
|
+
"""
|
|
2
32
|
|
|
3
33
|
from __future__ import annotations
|
|
4
34
|
|
|
5
35
|
from .base import BaseResponse
|
|
36
|
+
from .config import ResponseConfiguration, ResponseRegistry, get_default_registry
|
|
6
37
|
from .messages import ResponseMessage, ResponseMessages
|
|
7
|
-
from .runner import
|
|
38
|
+
from .runner import run_async, run_streamed, run_sync
|
|
39
|
+
from .tool_call import ResponseToolCall, parse_tool_arguments
|
|
8
40
|
from .vector_store import attach_vector_store
|
|
9
|
-
from .tool_call import ResponseToolCall
|
|
10
41
|
|
|
11
42
|
__all__ = [
|
|
12
43
|
"BaseResponse",
|
|
44
|
+
"ResponseConfiguration",
|
|
45
|
+
"ResponseRegistry",
|
|
46
|
+
"get_default_registry",
|
|
13
47
|
"ResponseMessage",
|
|
14
48
|
"ResponseMessages",
|
|
15
49
|
"run_sync",
|
|
16
50
|
"run_async",
|
|
17
51
|
"run_streamed",
|
|
18
52
|
"ResponseToolCall",
|
|
53
|
+
"parse_tool_arguments",
|
|
19
54
|
"attach_vector_store",
|
|
20
55
|
]
|