openai-sdk-helpers 0.0.2__py3-none-any.whl → 0.0.3__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/prompt/summarizer.jinja +7 -0
- openai_sdk_helpers/prompt/translator.jinja +7 -0
- openai_sdk_helpers/prompt/validator.jinja +7 -0
- openai_sdk_helpers/py.typed +0 -0
- {openai_sdk_helpers-0.0.2.dist-info → openai_sdk_helpers-0.0.3.dist-info}/METADATA +57 -4
- openai_sdk_helpers-0.0.3.dist-info/RECORD +8 -0
- openai_sdk_helpers/__init__.py +0 -34
- openai_sdk_helpers/agent/__init__.py +0 -23
- openai_sdk_helpers/agent/base.py +0 -432
- openai_sdk_helpers/agent/config.py +0 -66
- openai_sdk_helpers/agent/project_manager.py +0 -416
- openai_sdk_helpers/agent/runner.py +0 -117
- openai_sdk_helpers/agent/utils.py +0 -47
- openai_sdk_helpers/agent/vector_search.py +0 -418
- openai_sdk_helpers/agent/web_search.py +0 -404
- openai_sdk_helpers/config.py +0 -141
- openai_sdk_helpers/enums/__init__.py +0 -7
- openai_sdk_helpers/enums/base.py +0 -17
- openai_sdk_helpers/environment.py +0 -27
- openai_sdk_helpers/prompt/__init__.py +0 -77
- openai_sdk_helpers/response/__init__.py +0 -16
- openai_sdk_helpers/response/base.py +0 -477
- openai_sdk_helpers/response/messages.py +0 -211
- openai_sdk_helpers/response/runner.py +0 -42
- openai_sdk_helpers/response/tool_call.py +0 -70
- openai_sdk_helpers/structure/__init__.py +0 -57
- openai_sdk_helpers/structure/base.py +0 -591
- openai_sdk_helpers/structure/plan/__init__.py +0 -13
- openai_sdk_helpers/structure/plan/enum.py +0 -48
- openai_sdk_helpers/structure/plan/plan.py +0 -104
- openai_sdk_helpers/structure/plan/task.py +0 -122
- openai_sdk_helpers/structure/prompt.py +0 -24
- openai_sdk_helpers/structure/responses.py +0 -148
- openai_sdk_helpers/structure/summary.py +0 -65
- openai_sdk_helpers/structure/vector_search.py +0 -82
- openai_sdk_helpers/structure/web_search.py +0 -46
- openai_sdk_helpers/utils/__init__.py +0 -13
- openai_sdk_helpers/utils/core.py +0 -208
- openai_sdk_helpers/vector_storage/__init__.py +0 -15
- openai_sdk_helpers/vector_storage/cleanup.py +0 -91
- openai_sdk_helpers/vector_storage/storage.py +0 -501
- openai_sdk_helpers/vector_storage/types.py +0 -58
- openai_sdk_helpers-0.0.2.dist-info/RECORD +0 -40
- {openai_sdk_helpers-0.0.2.dist-info → openai_sdk_helpers-0.0.3.dist-info}/WHEEL +0 -0
- {openai_sdk_helpers-0.0.2.dist-info → openai_sdk_helpers-0.0.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,404 +0,0 @@
|
|
|
1
|
-
"""Core workflow management for ``web search``."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import asyncio
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from typing import Any, Dict, List, Optional, Union
|
|
8
|
-
|
|
9
|
-
from agents import custom_span, gen_trace_id, trace
|
|
10
|
-
from agents.model_settings import ModelSettings
|
|
11
|
-
from agents.tool import WebSearchTool
|
|
12
|
-
|
|
13
|
-
from ..structure.web_search import (
|
|
14
|
-
WebSearchItemStructure,
|
|
15
|
-
WebSearchItemResultStructure,
|
|
16
|
-
WebSearchStructure,
|
|
17
|
-
WebSearchPlanStructure,
|
|
18
|
-
WebSearchReportStructure,
|
|
19
|
-
)
|
|
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 WebAgentPlanner(BaseAgent):
|
|
28
|
-
"""Plan web searches to satisfy a user query.
|
|
29
|
-
|
|
30
|
-
Methods
|
|
31
|
-
-------
|
|
32
|
-
run_agent(query)
|
|
33
|
-
Generate a 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="web_planner",
|
|
54
|
-
description="Agent that plans web searches based on a user query.",
|
|
55
|
-
output_type=WebSearchPlanStructure,
|
|
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) -> WebSearchPlanStructure:
|
|
62
|
-
"""Plan searches for ``query``.
|
|
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 _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 WebSearchToolAgent(BaseAgent):
|
|
84
|
-
"""Execute web searches defined in a 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 web search and summarise the result.
|
|
92
|
-
"""
|
|
93
|
-
|
|
94
|
-
def __init__(
|
|
95
|
-
self, prompt_dir: Optional[Path] = None, default_model: Optional[str] = None
|
|
96
|
-
) -> None:
|
|
97
|
-
"""Initialize the search tool agent.
|
|
98
|
-
|
|
99
|
-
Parameters
|
|
100
|
-
----------
|
|
101
|
-
prompt_dir : pathlib.Path or None, default=None
|
|
102
|
-
Directory containing prompt templates.
|
|
103
|
-
default_model : str or None, default=None
|
|
104
|
-
Default model identifier to use when not defined in config.
|
|
105
|
-
|
|
106
|
-
Returns
|
|
107
|
-
-------
|
|
108
|
-
None
|
|
109
|
-
"""
|
|
110
|
-
config = AgentConfig(
|
|
111
|
-
name="web_search",
|
|
112
|
-
description="Agent that performs web searches and summarizes results.",
|
|
113
|
-
input_type=WebSearchPlanStructure,
|
|
114
|
-
tools=[WebSearchTool()],
|
|
115
|
-
model_settings=ModelSettings(tool_choice="required"),
|
|
116
|
-
)
|
|
117
|
-
super().__init__(
|
|
118
|
-
config=config, prompt_dir=prompt_dir, default_model=default_model
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
async def run_agent(
|
|
122
|
-
self, search_plan: WebSearchPlanStructure
|
|
123
|
-
) -> List[WebSearchItemResultStructure]:
|
|
124
|
-
"""Execute all searches in the plan with a progress bar.
|
|
125
|
-
|
|
126
|
-
Parameters
|
|
127
|
-
----------
|
|
128
|
-
search_plan : WebSearchPlanStructure
|
|
129
|
-
Plan describing each search to perform.
|
|
130
|
-
|
|
131
|
-
Returns
|
|
132
|
-
-------
|
|
133
|
-
list[WebSearchItemResultStructure]
|
|
134
|
-
Completed search results.
|
|
135
|
-
"""
|
|
136
|
-
with custom_span("Search the web"):
|
|
137
|
-
semaphore = asyncio.Semaphore(MAX_CONCURRENT_SEARCHES)
|
|
138
|
-
|
|
139
|
-
async def _bounded_search(
|
|
140
|
-
item: WebSearchItemStructure,
|
|
141
|
-
) -> WebSearchItemResultStructure:
|
|
142
|
-
"""Execute a single search within the concurrency limit.
|
|
143
|
-
|
|
144
|
-
Parameters
|
|
145
|
-
----------
|
|
146
|
-
item : WebSearchItemStructure
|
|
147
|
-
Search item to process.
|
|
148
|
-
|
|
149
|
-
Returns
|
|
150
|
-
-------
|
|
151
|
-
WebSearchItemResultStructure
|
|
152
|
-
Search result for ``item``.
|
|
153
|
-
"""
|
|
154
|
-
async with semaphore:
|
|
155
|
-
return await self.run_search(item)
|
|
156
|
-
|
|
157
|
-
tasks = [
|
|
158
|
-
asyncio.create_task(_bounded_search(item))
|
|
159
|
-
for item in search_plan.searches
|
|
160
|
-
]
|
|
161
|
-
results = await asyncio.gather(*tasks)
|
|
162
|
-
return [result for result in results if result is not None]
|
|
163
|
-
|
|
164
|
-
async def run_search(
|
|
165
|
-
self, item: WebSearchItemStructure
|
|
166
|
-
) -> WebSearchItemResultStructure:
|
|
167
|
-
"""Perform a single web search using the search agent.
|
|
168
|
-
|
|
169
|
-
Parameters
|
|
170
|
-
----------
|
|
171
|
-
item : WebSearchItemStructure
|
|
172
|
-
Search item containing the query and reason.
|
|
173
|
-
|
|
174
|
-
Returns
|
|
175
|
-
-------
|
|
176
|
-
WebSearchItemResultStructure
|
|
177
|
-
Search result summarising the page.
|
|
178
|
-
"""
|
|
179
|
-
template_context: Dict[str, Any] = {
|
|
180
|
-
"search_term": item.query,
|
|
181
|
-
"reason": item.reason,
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
result = await super().run(
|
|
185
|
-
agent_input=item.query,
|
|
186
|
-
agent_context=template_context,
|
|
187
|
-
output_type=str,
|
|
188
|
-
)
|
|
189
|
-
return self._coerce_item_result(result)
|
|
190
|
-
|
|
191
|
-
@staticmethod
|
|
192
|
-
def _coerce_item_result(
|
|
193
|
-
result: Union[str, WebSearchItemResultStructure, Any],
|
|
194
|
-
) -> WebSearchItemResultStructure:
|
|
195
|
-
"""Return a WebSearchItemResultStructure from varied agent outputs."""
|
|
196
|
-
if isinstance(result, WebSearchItemResultStructure):
|
|
197
|
-
return result
|
|
198
|
-
try:
|
|
199
|
-
return WebSearchItemResultStructure(text=str(result))
|
|
200
|
-
except Exception:
|
|
201
|
-
return WebSearchItemResultStructure(text="")
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
class WebAgentWriter(BaseAgent):
|
|
205
|
-
"""Summarize search results into a human-readable report.
|
|
206
|
-
|
|
207
|
-
Methods
|
|
208
|
-
-------
|
|
209
|
-
run_agent(query, search_results)
|
|
210
|
-
Compile a report from search results.
|
|
211
|
-
"""
|
|
212
|
-
|
|
213
|
-
def __init__(
|
|
214
|
-
self, prompt_dir: Optional[Path] = None, default_model: Optional[str] = None
|
|
215
|
-
) -> None:
|
|
216
|
-
"""Initialize the writer agent.
|
|
217
|
-
|
|
218
|
-
Parameters
|
|
219
|
-
----------
|
|
220
|
-
prompt_dir : pathlib.Path or None, default=None
|
|
221
|
-
Directory containing prompt templates.
|
|
222
|
-
default_model : str or None, default=None
|
|
223
|
-
Default model identifier to use when not defined in config.
|
|
224
|
-
|
|
225
|
-
Returns
|
|
226
|
-
-------
|
|
227
|
-
None
|
|
228
|
-
"""
|
|
229
|
-
config = AgentConfig(
|
|
230
|
-
name="web_writer",
|
|
231
|
-
description="Agent that writes a report based on web search results.",
|
|
232
|
-
output_type=WebSearchReportStructure,
|
|
233
|
-
)
|
|
234
|
-
super().__init__(
|
|
235
|
-
config=config, prompt_dir=prompt_dir, default_model=default_model
|
|
236
|
-
)
|
|
237
|
-
|
|
238
|
-
async def run_agent(
|
|
239
|
-
self, query: str, search_results: List[WebSearchItemResultStructure]
|
|
240
|
-
) -> WebSearchReportStructure:
|
|
241
|
-
"""Compile a report from search results.
|
|
242
|
-
|
|
243
|
-
Parameters
|
|
244
|
-
----------
|
|
245
|
-
query : str
|
|
246
|
-
Original search query.
|
|
247
|
-
search_results : list[WebSearchItemResultStructure]
|
|
248
|
-
Results produced by the search step.
|
|
249
|
-
|
|
250
|
-
Returns
|
|
251
|
-
-------
|
|
252
|
-
WebSearchReportStructure
|
|
253
|
-
Generated report for the query.
|
|
254
|
-
"""
|
|
255
|
-
template_context: Dict[str, Any] = {
|
|
256
|
-
"original_query": query,
|
|
257
|
-
"search_results": search_results,
|
|
258
|
-
}
|
|
259
|
-
result: WebSearchReportStructure = await _run_agent(
|
|
260
|
-
agent=self.get_agent(),
|
|
261
|
-
agent_input=query,
|
|
262
|
-
agent_context=template_context,
|
|
263
|
-
output_type=self._output_type,
|
|
264
|
-
)
|
|
265
|
-
|
|
266
|
-
return result
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
class WebAgentSearch(BaseAgent):
|
|
270
|
-
"""Manage the complete web search workflow.
|
|
271
|
-
|
|
272
|
-
Methods
|
|
273
|
-
-------
|
|
274
|
-
run_agent(search_query)
|
|
275
|
-
Execute the research workflow asynchronously.
|
|
276
|
-
run_agent_sync(search_query)
|
|
277
|
-
Execute the research workflow synchronously.
|
|
278
|
-
run_web_agent(search_query)
|
|
279
|
-
Convenience asynchronous entry point for the workflow.
|
|
280
|
-
run_web_agent_sync(search_query)
|
|
281
|
-
Convenience synchronous entry point for the workflow.
|
|
282
|
-
"""
|
|
283
|
-
|
|
284
|
-
def __init__(
|
|
285
|
-
self,
|
|
286
|
-
config: Optional[AgentConfig] = None,
|
|
287
|
-
prompt_dir: Optional[Path] = None,
|
|
288
|
-
default_model: Optional[str] = None,
|
|
289
|
-
) -> None:
|
|
290
|
-
"""Create the main web search agent.
|
|
291
|
-
|
|
292
|
-
Parameters
|
|
293
|
-
----------
|
|
294
|
-
config : AgentConfig or None, default=None
|
|
295
|
-
Optional configuration for the agent.
|
|
296
|
-
prompt_dir : pathlib.Path or None, default=None
|
|
297
|
-
Directory containing prompt templates.
|
|
298
|
-
default_model : str or None, default=None
|
|
299
|
-
Default model identifier to use when not defined in config.
|
|
300
|
-
|
|
301
|
-
Returns
|
|
302
|
-
-------
|
|
303
|
-
None
|
|
304
|
-
"""
|
|
305
|
-
if config is None:
|
|
306
|
-
config = AgentConfig(
|
|
307
|
-
name="web_agent",
|
|
308
|
-
description="Agent that coordinates web searches and report writing.",
|
|
309
|
-
output_type=WebSearchStructure,
|
|
310
|
-
)
|
|
311
|
-
super().__init__(
|
|
312
|
-
config=config, prompt_dir=prompt_dir, default_model=default_model
|
|
313
|
-
)
|
|
314
|
-
self._prompt_dir = prompt_dir
|
|
315
|
-
|
|
316
|
-
async def run_agent(self, search_query: str) -> WebSearchStructure:
|
|
317
|
-
"""Execute the entire research workflow for ``search_query``.
|
|
318
|
-
|
|
319
|
-
Parameters
|
|
320
|
-
----------
|
|
321
|
-
search_query : str
|
|
322
|
-
User's research query.
|
|
323
|
-
|
|
324
|
-
Returns
|
|
325
|
-
-------
|
|
326
|
-
WebSearchStructure
|
|
327
|
-
Completed research output.
|
|
328
|
-
"""
|
|
329
|
-
trace_id = gen_trace_id()
|
|
330
|
-
with trace("WebAgentSearch trace", trace_id=trace_id):
|
|
331
|
-
planner = WebAgentPlanner(
|
|
332
|
-
prompt_dir=self._prompt_dir, default_model=self.model
|
|
333
|
-
)
|
|
334
|
-
tool = WebSearchToolAgent(
|
|
335
|
-
prompt_dir=self._prompt_dir, default_model=self.model
|
|
336
|
-
)
|
|
337
|
-
writer = WebAgentWriter(
|
|
338
|
-
prompt_dir=self._prompt_dir, default_model=self.model
|
|
339
|
-
)
|
|
340
|
-
search_plan = await planner.run_agent(query=search_query)
|
|
341
|
-
search_results = await tool.run_agent(search_plan=search_plan)
|
|
342
|
-
search_report = await writer.run_agent(search_query, search_results)
|
|
343
|
-
return WebSearchStructure(
|
|
344
|
-
query=search_query,
|
|
345
|
-
web_search_plan=search_plan,
|
|
346
|
-
web_search_results=search_results,
|
|
347
|
-
web_search_report=search_report,
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
def run_agent_sync(self, search_query: str) -> WebSearchStructure:
|
|
351
|
-
"""Run :meth:`run_agent` synchronously for ``search_query``.
|
|
352
|
-
|
|
353
|
-
Parameters
|
|
354
|
-
----------
|
|
355
|
-
search_query : str
|
|
356
|
-
User's research query.
|
|
357
|
-
|
|
358
|
-
Returns
|
|
359
|
-
-------
|
|
360
|
-
WebSearchStructure
|
|
361
|
-
Completed research output.
|
|
362
|
-
"""
|
|
363
|
-
return run_coro_sync(self.run_agent(search_query))
|
|
364
|
-
|
|
365
|
-
@staticmethod
|
|
366
|
-
async def run_web_agent(search_query: str) -> WebSearchStructure:
|
|
367
|
-
"""Return a research report for the given query using ``WebAgentSearch``.
|
|
368
|
-
|
|
369
|
-
Parameters
|
|
370
|
-
----------
|
|
371
|
-
search_query : str
|
|
372
|
-
User's research query.
|
|
373
|
-
|
|
374
|
-
Returns
|
|
375
|
-
-------
|
|
376
|
-
WebSearchStructure
|
|
377
|
-
Completed research output.
|
|
378
|
-
"""
|
|
379
|
-
return await WebAgentSearch().run_agent(search_query=search_query)
|
|
380
|
-
|
|
381
|
-
@staticmethod
|
|
382
|
-
def run_web_agent_sync(search_query: str) -> WebSearchStructure:
|
|
383
|
-
"""Run :meth:`run_web_agent` synchronously for ``search_query``.
|
|
384
|
-
|
|
385
|
-
Parameters
|
|
386
|
-
----------
|
|
387
|
-
search_query : str
|
|
388
|
-
User's research query.
|
|
389
|
-
|
|
390
|
-
Returns
|
|
391
|
-
-------
|
|
392
|
-
WebSearchStructure
|
|
393
|
-
Completed research output.
|
|
394
|
-
"""
|
|
395
|
-
return run_coro_sync(WebAgentSearch.run_web_agent(search_query=search_query))
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
__all__ = [
|
|
399
|
-
"MAX_CONCURRENT_SEARCHES",
|
|
400
|
-
"WebAgentPlanner",
|
|
401
|
-
"WebSearchToolAgent",
|
|
402
|
-
"WebAgentWriter",
|
|
403
|
-
"WebAgentSearch",
|
|
404
|
-
]
|
openai_sdk_helpers/config.py
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
"""Shared configuration for OpenAI SDK usage."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import os
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from typing import Any, Dict, Mapping, Optional
|
|
8
|
-
|
|
9
|
-
from dotenv import dotenv_values
|
|
10
|
-
from openai import OpenAI
|
|
11
|
-
from pydantic import BaseModel, ConfigDict, Field
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class OpenAISettings(BaseModel):
|
|
15
|
-
"""Configuration helpers for constructing OpenAI clients.
|
|
16
|
-
|
|
17
|
-
Methods
|
|
18
|
-
-------
|
|
19
|
-
from_env(dotenv_path, **overrides)
|
|
20
|
-
Build settings from environment variables and optional overrides.
|
|
21
|
-
client_kwargs()
|
|
22
|
-
Return keyword arguments for ``OpenAI`` initialization.
|
|
23
|
-
create_client()
|
|
24
|
-
Instantiate an ``OpenAI`` client using the stored configuration.
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
model_config = ConfigDict(extra="ignore")
|
|
28
|
-
|
|
29
|
-
api_key: Optional[str] = Field(
|
|
30
|
-
default=None,
|
|
31
|
-
description=(
|
|
32
|
-
"API key used to authenticate requests. Defaults to ``OPENAI_API_KEY``"
|
|
33
|
-
" from the environment."
|
|
34
|
-
),
|
|
35
|
-
)
|
|
36
|
-
org_id: Optional[str] = Field(
|
|
37
|
-
default=None,
|
|
38
|
-
description=(
|
|
39
|
-
"Organization identifier applied to outgoing requests. Defaults to"
|
|
40
|
-
" ``OPENAI_ORG_ID``."
|
|
41
|
-
),
|
|
42
|
-
)
|
|
43
|
-
project_id: Optional[str] = Field(
|
|
44
|
-
default=None,
|
|
45
|
-
description=(
|
|
46
|
-
"Project identifier used for billing and resource scoping. Defaults to"
|
|
47
|
-
" ``OPENAI_PROJECT_ID``."
|
|
48
|
-
),
|
|
49
|
-
)
|
|
50
|
-
base_url: Optional[str] = Field(
|
|
51
|
-
default=None,
|
|
52
|
-
description=(
|
|
53
|
-
"Custom base URL for self-hosted or proxied deployments. Defaults to"
|
|
54
|
-
" ``OPENAI_BASE_URL``."
|
|
55
|
-
),
|
|
56
|
-
)
|
|
57
|
-
default_model: Optional[str] = Field(
|
|
58
|
-
default=None,
|
|
59
|
-
description=(
|
|
60
|
-
"Model name used when constructing agents if no model is explicitly"
|
|
61
|
-
" provided. Defaults to ``OPENAI_MODEL``."
|
|
62
|
-
),
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
@classmethod
|
|
66
|
-
def from_env(
|
|
67
|
-
cls, dotenv_path: Optional[Path] = None, **overrides: Any
|
|
68
|
-
) -> "OpenAISettings":
|
|
69
|
-
"""Load settings from the environment and optional overrides.
|
|
70
|
-
|
|
71
|
-
Parameters
|
|
72
|
-
----------
|
|
73
|
-
dotenv_path : Path | None
|
|
74
|
-
Path to a ``.env`` file to load before reading environment
|
|
75
|
-
variables. Default ``None``.
|
|
76
|
-
overrides : Any
|
|
77
|
-
Keyword overrides applied on top of environment values.
|
|
78
|
-
|
|
79
|
-
Returns
|
|
80
|
-
-------
|
|
81
|
-
OpenAISettings
|
|
82
|
-
Settings instance populated from environment variables and overrides.
|
|
83
|
-
"""
|
|
84
|
-
env_file_values: Mapping[str, Optional[str]]
|
|
85
|
-
if dotenv_path is not None:
|
|
86
|
-
env_file_values = dotenv_values(dotenv_path)
|
|
87
|
-
else:
|
|
88
|
-
env_file_values = dotenv_values()
|
|
89
|
-
|
|
90
|
-
values: Dict[str, Optional[str]] = {
|
|
91
|
-
"api_key": overrides.get("api_key")
|
|
92
|
-
or env_file_values.get("OPENAI_API_KEY")
|
|
93
|
-
or os.getenv("OPENAI_API_KEY"),
|
|
94
|
-
"org_id": overrides.get("org_id")
|
|
95
|
-
or env_file_values.get("OPENAI_ORG_ID")
|
|
96
|
-
or os.getenv("OPENAI_ORG_ID"),
|
|
97
|
-
"project_id": overrides.get("project_id")
|
|
98
|
-
or env_file_values.get("OPENAI_PROJECT_ID")
|
|
99
|
-
or os.getenv("OPENAI_PROJECT_ID"),
|
|
100
|
-
"base_url": overrides.get("base_url")
|
|
101
|
-
or env_file_values.get("OPENAI_BASE_URL")
|
|
102
|
-
or os.getenv("OPENAI_BASE_URL"),
|
|
103
|
-
"default_model": overrides.get("default_model")
|
|
104
|
-
or env_file_values.get("OPENAI_MODEL")
|
|
105
|
-
or os.getenv("OPENAI_MODEL"),
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return cls(**values)
|
|
109
|
-
|
|
110
|
-
def client_kwargs(self) -> Dict[str, Any]:
|
|
111
|
-
"""Return keyword arguments for constructing an ``OpenAI`` client.
|
|
112
|
-
|
|
113
|
-
Returns
|
|
114
|
-
-------
|
|
115
|
-
dict
|
|
116
|
-
Keyword arguments populated with available authentication and routing
|
|
117
|
-
values.
|
|
118
|
-
"""
|
|
119
|
-
kwargs: Dict[str, Any] = {}
|
|
120
|
-
if self.api_key:
|
|
121
|
-
kwargs["api_key"] = self.api_key
|
|
122
|
-
if self.org_id:
|
|
123
|
-
kwargs["organization"] = self.org_id
|
|
124
|
-
if self.project_id:
|
|
125
|
-
kwargs["project"] = self.project_id
|
|
126
|
-
if self.base_url:
|
|
127
|
-
kwargs["base_url"] = self.base_url
|
|
128
|
-
return kwargs
|
|
129
|
-
|
|
130
|
-
def create_client(self) -> OpenAI:
|
|
131
|
-
"""Instantiate an ``OpenAI`` client using the stored configuration.
|
|
132
|
-
|
|
133
|
-
Returns
|
|
134
|
-
-------
|
|
135
|
-
OpenAI
|
|
136
|
-
Client initialized with ``client_kwargs``.
|
|
137
|
-
"""
|
|
138
|
-
return OpenAI(**self.client_kwargs())
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
__all__ = ["OpenAISettings"]
|
openai_sdk_helpers/enums/base.py
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"""Base enum helpers."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from enum import Enum
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class CrosswalkJSONEnum(str, Enum):
|
|
9
|
-
"""Enum base class with crosswalk metadata hooks."""
|
|
10
|
-
|
|
11
|
-
@classmethod
|
|
12
|
-
def CROSSWALK(cls) -> dict[str, dict[str, object]]:
|
|
13
|
-
"""Return metadata describing enum values."""
|
|
14
|
-
raise NotImplementedError("CROSSWALK must be implemented by subclasses.")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
__all__ = ["CrosswalkJSONEnum"]
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"""Environment helpers for openai-sdk-helpers."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
|
|
7
|
-
DATETIME_FMT = "%Y%m%d_%H%M%S"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def get_data_path(module_name: str) -> Path:
|
|
11
|
-
"""Return a writable data directory for the given module name.
|
|
12
|
-
|
|
13
|
-
Parameters
|
|
14
|
-
----------
|
|
15
|
-
module_name : str
|
|
16
|
-
Name of the module requesting a data directory.
|
|
17
|
-
|
|
18
|
-
Returns
|
|
19
|
-
-------
|
|
20
|
-
Path
|
|
21
|
-
Directory path under ``~/.openai-sdk-helpers`` specific to ``module_name``. The
|
|
22
|
-
directory is created if it does not already exist.
|
|
23
|
-
"""
|
|
24
|
-
base = Path.home() / ".openai-sdk-helpers"
|
|
25
|
-
path = base / module_name
|
|
26
|
-
path.mkdir(parents=True, exist_ok=True)
|
|
27
|
-
return path
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
"""Core prompt rendering utilities."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import warnings
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from typing import Any, Mapping, Optional
|
|
8
|
-
|
|
9
|
-
from dotenv import load_dotenv
|
|
10
|
-
from jinja2 import Environment, FileSystemLoader, Template
|
|
11
|
-
|
|
12
|
-
load_dotenv()
|
|
13
|
-
warnings.filterwarnings("ignore")
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class PromptRenderer:
|
|
17
|
-
"""Render prompts using Jinja2 templates.
|
|
18
|
-
|
|
19
|
-
The renderer loads templates from a base directory (defaulting to the
|
|
20
|
-
``prompt`` package directory) and exposes a rendering helper for
|
|
21
|
-
injecting context values.
|
|
22
|
-
|
|
23
|
-
Methods
|
|
24
|
-
-------
|
|
25
|
-
render(template_path, context)
|
|
26
|
-
Render the template at ``template_path`` with the supplied context.
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
def __init__(self, base_dir: Optional[Path] = None) -> None:
|
|
30
|
-
"""Initialize the renderer with a Jinja2 environment.
|
|
31
|
-
|
|
32
|
-
Parameters
|
|
33
|
-
----------
|
|
34
|
-
base_dir : Path or None, default=None
|
|
35
|
-
Base directory containing Jinja2 templates. Defaults to the
|
|
36
|
-
``prompt`` directory adjacent to this file when ``None``.
|
|
37
|
-
|
|
38
|
-
Returns
|
|
39
|
-
-------
|
|
40
|
-
None
|
|
41
|
-
"""
|
|
42
|
-
if base_dir is None:
|
|
43
|
-
# Defaults to the directory containing this file, which also
|
|
44
|
-
# contains the builtin prompt templates.
|
|
45
|
-
self.base_dir = Path(__file__).resolve().parent
|
|
46
|
-
else:
|
|
47
|
-
self.base_dir = base_dir
|
|
48
|
-
|
|
49
|
-
self._env = Environment(
|
|
50
|
-
loader=FileSystemLoader(str(self.base_dir)),
|
|
51
|
-
autoescape=False, # Prompts are plain text
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
def render(
|
|
55
|
-
self, template_path: str, context: Optional[Mapping[str, Any]] = None
|
|
56
|
-
) -> str:
|
|
57
|
-
"""Render a Jinja2 template with the given context.
|
|
58
|
-
|
|
59
|
-
Parameters
|
|
60
|
-
----------
|
|
61
|
-
template_path : str
|
|
62
|
-
Path to the template file, relative to ``base_dir``.
|
|
63
|
-
context : Mapping[str, Any] or None, default=None
|
|
64
|
-
Context variables passed to the template.
|
|
65
|
-
|
|
66
|
-
Returns
|
|
67
|
-
-------
|
|
68
|
-
str
|
|
69
|
-
Rendered prompt as a string.
|
|
70
|
-
"""
|
|
71
|
-
template_path_ = Path(self.base_dir, template_path)
|
|
72
|
-
template_path_text = template_path_.read_text()
|
|
73
|
-
template = Template(template_path_text)
|
|
74
|
-
return template.render(context or {})
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
__all__ = ["PromptRenderer"]
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"""Shared response helpers for OpenAI interactions."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from .base import ResponseBase
|
|
6
|
-
from .messages import ResponseMessage, ResponseMessages
|
|
7
|
-
from .runner import run
|
|
8
|
-
from .tool_call import ResponseToolCall
|
|
9
|
-
|
|
10
|
-
__all__ = [
|
|
11
|
-
"ResponseBase",
|
|
12
|
-
"ResponseMessage",
|
|
13
|
-
"ResponseMessages",
|
|
14
|
-
"run",
|
|
15
|
-
"ResponseToolCall",
|
|
16
|
-
]
|