weakincentives 0.2.0__py3-none-any.whl → 0.3.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.
Potentially problematic release.
This version of weakincentives might be problematic. Click here for more details.
- weakincentives/__init__.py +26 -2
- weakincentives/adapters/__init__.py +6 -5
- weakincentives/adapters/core.py +7 -17
- weakincentives/adapters/litellm.py +594 -0
- weakincentives/adapters/openai.py +286 -57
- weakincentives/events.py +103 -0
- weakincentives/examples/__init__.py +67 -0
- weakincentives/examples/code_review_prompt.py +118 -0
- weakincentives/examples/code_review_session.py +171 -0
- weakincentives/examples/code_review_tools.py +376 -0
- weakincentives/{prompts → prompt}/__init__.py +6 -8
- weakincentives/{prompts → prompt}/_types.py +1 -1
- weakincentives/{prompts/text.py → prompt/markdown.py} +19 -9
- weakincentives/{prompts → prompt}/prompt.py +216 -66
- weakincentives/{prompts → prompt}/response_format.py +9 -6
- weakincentives/{prompts → prompt}/section.py +25 -4
- weakincentives/{prompts/structured.py → prompt/structured_output.py} +16 -5
- weakincentives/{prompts → prompt}/tool.py +6 -6
- weakincentives/prompt/versioning.py +144 -0
- weakincentives/serde/__init__.py +0 -14
- weakincentives/serde/dataclass_serde.py +3 -17
- weakincentives/session/__init__.py +31 -0
- weakincentives/session/reducers.py +60 -0
- weakincentives/session/selectors.py +45 -0
- weakincentives/session/session.py +168 -0
- weakincentives/tools/__init__.py +69 -0
- weakincentives/tools/errors.py +22 -0
- weakincentives/tools/planning.py +538 -0
- weakincentives/tools/vfs.py +590 -0
- weakincentives-0.3.0.dist-info/METADATA +231 -0
- weakincentives-0.3.0.dist-info/RECORD +35 -0
- weakincentives-0.2.0.dist-info/METADATA +0 -173
- weakincentives-0.2.0.dist-info/RECORD +0 -20
- /weakincentives/{prompts → prompt}/errors.py +0 -0
- {weakincentives-0.2.0.dist-info → weakincentives-0.3.0.dist-info}/WHEEL +0 -0
- {weakincentives-0.2.0.dist-info → weakincentives-0.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: weakincentives
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Tools for developing and optimizing side effect free background agents
|
|
5
|
+
Project-URL: Homepage, https://weakincentives.com/
|
|
6
|
+
Project-URL: Documentation, https://github.com/weakincentives/weakincentives#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/weakincentives/weakincentives
|
|
8
|
+
Project-URL: Issue Tracker, https://github.com/weakincentives/weakincentives/issues
|
|
9
|
+
Author-email: Andrei Savu <andrei@weakincentives.com>
|
|
10
|
+
License: Apache-2.0
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: agents,ai,background-agents,optimization,side-effect-free,weak-incentives
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.12
|
|
26
|
+
Provides-Extra: litellm
|
|
27
|
+
Requires-Dist: litellm>=1.79.0; extra == 'litellm'
|
|
28
|
+
Provides-Extra: openai
|
|
29
|
+
Requires-Dist: openai>=2.6.1; extra == 'openai'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# Weak Incentives
|
|
33
|
+
|
|
34
|
+
**Lean, typed building blocks for side-effect-free background agents.**
|
|
35
|
+
Compose deterministic prompts, run typed tools, and parse strict JSON replies without
|
|
36
|
+
heavy dependencies. Optional adapters snap in when you need a model provider.
|
|
37
|
+
|
|
38
|
+
## Highlights
|
|
39
|
+
|
|
40
|
+
- Namespaced prompt trees with deterministic Markdown renders, placeholder
|
|
41
|
+
verification, and tool-aware versioning metadata.
|
|
42
|
+
- Stdlib-only dataclass serde (`parse`, `dump`, `clone`, `schema`) keeps request and
|
|
43
|
+
response types honest end-to-end.
|
|
44
|
+
- Session state container and event bus collect prompt and tool telemetry for
|
|
45
|
+
downstream automation.
|
|
46
|
+
- Built-in planning and virtual filesystem tool suites give agents durable plans and
|
|
47
|
+
sandboxed edits backed by reducers and selectors.
|
|
48
|
+
- Optional OpenAI and LiteLLM adapters integrate structured output parsing, tool
|
|
49
|
+
orchestration, and telemetry hooks.
|
|
50
|
+
|
|
51
|
+
## Requirements
|
|
52
|
+
|
|
53
|
+
- Python 3.12+ (the repository pins 3.14 in `.python-version` for development)
|
|
54
|
+
- [`uv`](https://github.com/astral-sh/uv) CLI
|
|
55
|
+
|
|
56
|
+
## Install
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uv add weakincentives
|
|
60
|
+
# optional provider adapters
|
|
61
|
+
uv add "weakincentives[openai]"
|
|
62
|
+
uv add "weakincentives[litellm]"
|
|
63
|
+
# cloning the repo? use: uv sync --extra openai --extra litellm
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Quickstart
|
|
67
|
+
|
|
68
|
+
````python
|
|
69
|
+
from dataclasses import dataclass
|
|
70
|
+
from weakincentives import (
|
|
71
|
+
MarkdownSection,
|
|
72
|
+
Prompt,
|
|
73
|
+
Tool,
|
|
74
|
+
ToolResult,
|
|
75
|
+
parse_structured_output,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
@dataclass
|
|
79
|
+
class ResearchGuidance:
|
|
80
|
+
topic: str
|
|
81
|
+
|
|
82
|
+
@dataclass
|
|
83
|
+
class SourceLookup:
|
|
84
|
+
source_id: str
|
|
85
|
+
|
|
86
|
+
@dataclass
|
|
87
|
+
class SourceDetails:
|
|
88
|
+
source_id: str
|
|
89
|
+
title: str
|
|
90
|
+
|
|
91
|
+
@dataclass
|
|
92
|
+
class ResearchSummary:
|
|
93
|
+
summary: str
|
|
94
|
+
citations: list[str]
|
|
95
|
+
|
|
96
|
+
def lookup_source(params: SourceLookup) -> ToolResult[SourceDetails]:
|
|
97
|
+
details = SourceDetails(source_id=params.source_id, title="Ada Lovelace Archive")
|
|
98
|
+
return ToolResult(message=f"Loaded {details.title}", value=details)
|
|
99
|
+
|
|
100
|
+
catalog_tool = Tool[SourceLookup, SourceDetails](
|
|
101
|
+
name="catalog_lookup",
|
|
102
|
+
description="Look up a primary source identifier and return details.",
|
|
103
|
+
handler=lookup_source,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
task_section = MarkdownSection[ResearchGuidance](
|
|
107
|
+
title="Task",
|
|
108
|
+
template=(
|
|
109
|
+
"Research ${topic}. Use `catalog_lookup` for citations and reply with a "
|
|
110
|
+
"JSON summary."
|
|
111
|
+
),
|
|
112
|
+
key="research.task",
|
|
113
|
+
tools=[catalog_tool],
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
prompt = Prompt[ResearchSummary](
|
|
117
|
+
ns="examples/research",
|
|
118
|
+
key="research.run",
|
|
119
|
+
name="research_prompt",
|
|
120
|
+
sections=[task_section],
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
rendered = prompt.render(ResearchGuidance(topic="Ada Lovelace"))
|
|
124
|
+
print(rendered.text)
|
|
125
|
+
print([tool.name for tool in rendered.tools])
|
|
126
|
+
|
|
127
|
+
reply = """```json
|
|
128
|
+
{
|
|
129
|
+
"summary": "Ada Lovelace pioneered computing...",
|
|
130
|
+
"citations": ["catalog_lookup:ada-archive"]
|
|
131
|
+
}
|
|
132
|
+
```"""
|
|
133
|
+
result = parse_structured_output(reply, rendered)
|
|
134
|
+
print(result.summary)
|
|
135
|
+
print(result.citations)
|
|
136
|
+
````
|
|
137
|
+
|
|
138
|
+
The rendered prompt text stays deterministic, tool metadata travels with the prompt,
|
|
139
|
+
and `parse_structured_output` enforces your dataclass contract.
|
|
140
|
+
|
|
141
|
+
## Sessions and Built-in Tools
|
|
142
|
+
|
|
143
|
+
Session state turns prompt output and tool calls into durable data. Built-in planning
|
|
144
|
+
and virtual filesystem sections register reducers on the provided session.
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from weakincentives.session import Session, select_latest
|
|
148
|
+
from weakincentives.tools import (
|
|
149
|
+
PlanningToolsSection,
|
|
150
|
+
Plan,
|
|
151
|
+
VfsToolsSection,
|
|
152
|
+
VirtualFileSystem,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
session = Session()
|
|
156
|
+
planning_section = PlanningToolsSection(session=session)
|
|
157
|
+
vfs_section = VfsToolsSection(session=session)
|
|
158
|
+
|
|
159
|
+
prompt = Prompt[ResearchSummary](
|
|
160
|
+
ns="examples/research",
|
|
161
|
+
key="research.session",
|
|
162
|
+
sections=[task_section, planning_section, vfs_section],
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
active_plan = select_latest(session, Plan)
|
|
166
|
+
vfs_snapshot = select_latest(session, VirtualFileSystem)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Use `session.select_all(...)` or the helpers in `weakincentives.session` to drive UI
|
|
170
|
+
state, persistence, or audits after each adapter run.
|
|
171
|
+
|
|
172
|
+
## Adapter Integrations
|
|
173
|
+
|
|
174
|
+
Adapters stay optional and only load their dependencies when you import them.
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
from weakincentives.adapters.openai import OpenAIAdapter
|
|
178
|
+
from weakincentives.events import InProcessEventBus
|
|
179
|
+
from weakincentives.session import Session
|
|
180
|
+
from weakincentives.tools import Plan
|
|
181
|
+
|
|
182
|
+
bus = InProcessEventBus()
|
|
183
|
+
session = Session(bus=bus)
|
|
184
|
+
|
|
185
|
+
adapter = OpenAIAdapter(
|
|
186
|
+
model="gpt-4o-mini",
|
|
187
|
+
client_kwargs={"api_key": "sk-..."},
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
response = adapter.evaluate(
|
|
191
|
+
prompt,
|
|
192
|
+
ResearchGuidance(topic="Ada Lovelace"),
|
|
193
|
+
bus=bus,
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
plan_history = session.select_all(Plan)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
`InProcessEventBus` publishes `ToolInvoked` and `PromptExecuted` events for the
|
|
200
|
+
session (or any other subscriber) to consume.
|
|
201
|
+
|
|
202
|
+
## Development Setup
|
|
203
|
+
|
|
204
|
+
1. Install Python 3.14 (for example with `pyenv install 3.14.0`).
|
|
205
|
+
|
|
206
|
+
1. Install `uv`, then bootstrap the environment and hooks:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
uv sync
|
|
210
|
+
./install-hooks.sh
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
1. Run checks with `uv run` so everything shares the managed virtualenv:
|
|
214
|
+
|
|
215
|
+
- `make format` / `make format-check`
|
|
216
|
+
- `make lint` / `make lint-fix`
|
|
217
|
+
- `make typecheck` (Ty + Pyright, warnings fail the build)
|
|
218
|
+
- `make test` (pytest via `build/run_pytest.py`, 100% coverage enforced)
|
|
219
|
+
- `make check` (aggregates the quiet checks above plus Bandit, Deptry, pip-audit,
|
|
220
|
+
and markdown linting)
|
|
221
|
+
|
|
222
|
+
## Documentation
|
|
223
|
+
|
|
224
|
+
- `AGENTS.md` — operational handbook and contributor workflow.
|
|
225
|
+
- `specs/` — design docs for prompts, planning tools, and adapters.
|
|
226
|
+
- `ROADMAP.md` — upcoming feature sketches.
|
|
227
|
+
- `docs/api/` — API reference material.
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
Apache 2.0 • Status: Alpha (APIs may change between releases)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
weakincentives/__init__.py,sha256=MOVuBbGbGA2O_QS69wH8E17bkRc_fHQ2Z0MGD-79ngE,1092
|
|
2
|
+
weakincentives/events.py,sha256=s1ddTuCOgKNcRZvL9T7vX7PUOXbifD8Gr1QJiuenA6c,3048
|
|
3
|
+
weakincentives/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
weakincentives/adapters/__init__.py,sha256=loPj9FVLCSm2zZu8-8GV9h_Usc3lPISzojPOlS2Us8k,948
|
|
5
|
+
weakincentives/adapters/core.py,sha256=Eo1309SsjZPPET_xCIjbSoeSQmakwwLdVXDlv2ZlulI,2101
|
|
6
|
+
weakincentives/adapters/litellm.py,sha256=ZO8B05zZ8JkHirxciCQPZjxNILFWCop3LjvcKU4SBmA,21261
|
|
7
|
+
weakincentives/adapters/openai.py,sha256=LEYih4EcQ7So-b_sTItgRt-6JVRITsfO0aG847TpHNs,20871
|
|
8
|
+
weakincentives/examples/__init__.py,sha256=SNyUBOjzdKl4UkaEk99uSenVnqDvK7m1UnAe27Rhry8,1724
|
|
9
|
+
weakincentives/examples/code_review_prompt.py,sha256=VkLS3ZNcyxWQLX6VxH8MmTWbKCjDxNFnjye2nbhMcK8,4316
|
|
10
|
+
weakincentives/examples/code_review_session.py,sha256=ArCrBiakJb3DlcNjVw2s420zdVOsdT8Pq_fQaTItGyE,5236
|
|
11
|
+
weakincentives/examples/code_review_tools.py,sha256=rOTZBxgMZfuy8b_oNCJu31BskeExSa4jWB3GPOSJ88g,11193
|
|
12
|
+
weakincentives/prompt/__init__.py,sha256=gPGFeVN6puN-P1ztqFrobE5zRb3CJ4_JZJSmPatIjUo,1274
|
|
13
|
+
weakincentives/prompt/_types.py,sha256=zvb4KrJyqFGhilmvzvgZzIxpZhm1LRIzc8vwugnZ2jY,925
|
|
14
|
+
weakincentives/prompt/errors.py,sha256=DR3GN54oTnNARkto3mVbIuT6BwhijTP3onLpcB6jdq0,1664
|
|
15
|
+
weakincentives/prompt/markdown.py,sha256=KUqxKfRWvASNzAyLno7M0Z0d7TWx8jc6qiWaWImBiHY,3460
|
|
16
|
+
weakincentives/prompt/prompt.py,sha256=tO-u9ZdjlzdTSjc6obvhniV3564ry7yilHZhmJVUf00,22962
|
|
17
|
+
weakincentives/prompt/response_format.py,sha256=uYGg2mD6KIXuBDGgx65szV7er804ychb0zuZj9Irtuo,1805
|
|
18
|
+
weakincentives/prompt/section.py,sha256=LdqoZADjsvvSpTvPzG0Unan_N-q1AgPWw-0F2LrWn5Y,4962
|
|
19
|
+
weakincentives/prompt/structured_output.py,sha256=v3Ton3DpJbXYOf-itpUrUJtIad9j58oHmZ1UeMCRviY,5286
|
|
20
|
+
weakincentives/prompt/tool.py,sha256=_a5vKUfH6mBYtHWbf1KFk4RlXr6O9endzB4yjh9tTiE,9156
|
|
21
|
+
weakincentives/prompt/versioning.py,sha256=Ur0rLYvVvMuoGxOB-SzYIALMlK6IKbOvxJWf2HsE9lQ,4034
|
|
22
|
+
weakincentives/serde/__init__.py,sha256=jkYZa12RWgXlDzfPVHA6x3Jh0x52SnkVbVD2SpRUOtU,690
|
|
23
|
+
weakincentives/serde/dataclass_serde.py,sha256=9ZYYGyl0PCRLweYx9XQk8vKKLiSiY_3mf_P7BmsCxOE,37327
|
|
24
|
+
weakincentives/session/__init__.py,sha256=f-JN93x4VXzGJd1oontyZuaRJ1wSN80MQ6qduNG-3ss,1000
|
|
25
|
+
weakincentives/session/reducers.py,sha256=_Wi8brUaGhT9jxfCychu59T_6jo3tvYp5JkhWpSb5ts,1944
|
|
26
|
+
weakincentives/session/selectors.py,sha256=uLYfhVF8ot8W03BQtmj7AzLltrdZ_VAsRsn31gQfWUk,1427
|
|
27
|
+
weakincentives/session/session.py,sha256=RnLG9KRXdpj3PRVlXwTa501qNdUzeTaXc5s2G4hLlL8,5782
|
|
28
|
+
weakincentives/tools/__init__.py,sha256=B5U8Ujh4--3CwssNSUApkC5KCn5z_NqbHR2w_jdgcyc,1524
|
|
29
|
+
weakincentives/tools/errors.py,sha256=cHD_78WEpwzVjtuiSGtEyMy8u-n-1k0I95fEBoMngbI,765
|
|
30
|
+
weakincentives/tools/planning.py,sha256=qlxulLZgLlt_7eFI4Psb8IGNaea4N6uR_ijch1f7Jc4,17023
|
|
31
|
+
weakincentives/tools/vfs.py,sha256=3u9v3CDkqcKmuNFId8Bov00Mb5IxcJvH9mb5yTE2zo4,20582
|
|
32
|
+
weakincentives-0.3.0.dist-info/METADATA,sha256=jfUtPG9WpJcyXTwU3jeJ51uzC37C4dfpuVx3TGha9rs,6965
|
|
33
|
+
weakincentives-0.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
34
|
+
weakincentives-0.3.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
35
|
+
weakincentives-0.3.0.dist-info/RECORD,,
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: weakincentives
|
|
3
|
-
Version: 0.2.0
|
|
4
|
-
Summary: Tools for developing and optimizing side effect free background agents
|
|
5
|
-
Project-URL: Homepage, https://weakincentives.com/
|
|
6
|
-
Project-URL: Documentation, https://github.com/weakincentives/weakincentives#readme
|
|
7
|
-
Project-URL: Repository, https://github.com/weakincentives/weakincentives
|
|
8
|
-
Project-URL: Issue Tracker, https://github.com/weakincentives/weakincentives/issues
|
|
9
|
-
Author-email: Andrei Savu <andrei@weakincentives.com>
|
|
10
|
-
License: Apache-2.0
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
Keywords: agents,ai,background-agents,optimization,side-effect-free,weak-incentives
|
|
13
|
-
Classifier: Development Status :: 3 - Alpha
|
|
14
|
-
Classifier: Intended Audience :: Developers
|
|
15
|
-
Classifier: Intended Audience :: Science/Research
|
|
16
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
-
Classifier: Operating System :: OS Independent
|
|
18
|
-
Classifier: Programming Language :: Python :: 3
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
-
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
-
Classifier: Typing :: Typed
|
|
23
|
-
Requires-Python: >=3.14
|
|
24
|
-
Provides-Extra: openai
|
|
25
|
-
Requires-Dist: openai>=2.6.1; extra == 'openai'
|
|
26
|
-
Description-Content-Type: text/markdown
|
|
27
|
-
|
|
28
|
-
# Weak Incentives
|
|
29
|
-
|
|
30
|
-
Tools for developing and optimizing side effect free background agents. The library ships prompt composition primitives, structured tool metadata, and optional provider adapters so you can scaffold deterministic automation flows quickly. All commands below assume Astral's `uv` CLI.
|
|
31
|
-
|
|
32
|
-
## For Library Users
|
|
33
|
-
|
|
34
|
-
### Installation
|
|
35
|
-
|
|
36
|
-
- `uv add weakincentives`
|
|
37
|
-
- Add `uv add "weakincentives[openai]"` (or `uv sync --extra openai` when cloning the repo) to enable the OpenAI adapter helpers.
|
|
38
|
-
|
|
39
|
-
### Key Features
|
|
40
|
-
|
|
41
|
-
- Fully typed prompt composition primitives (`Prompt`, `Section`, `TextSection`, `Tool`, `ToolResult`) for assembling deterministic Markdown prompts with attached tool metadata.
|
|
42
|
-
- Stdlib-only dataclass serde utilities (`parse`, `dump`, `clone`, `schema`) for Pydantic-like ergonomics without third-party dependencies.
|
|
43
|
-
- Optional OpenAI adapter that gates imports behind a friendly error and returns the SDK client when the extra is present.
|
|
44
|
-
- Quiet-by-default package with minimal runtime dependencies so background agents stay lean and predictable.
|
|
45
|
-
|
|
46
|
-
### Quickstart
|
|
47
|
-
|
|
48
|
-
````python
|
|
49
|
-
from dataclasses import dataclass
|
|
50
|
-
|
|
51
|
-
from weakincentives.prompts import (
|
|
52
|
-
Prompt,
|
|
53
|
-
TextSection,
|
|
54
|
-
Tool,
|
|
55
|
-
ToolResult,
|
|
56
|
-
parse_output,
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
@dataclass
|
|
61
|
-
class ResearchGuidance:
|
|
62
|
-
topic: str
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
@dataclass
|
|
66
|
-
class SourceLookup:
|
|
67
|
-
source_id: str
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
@dataclass
|
|
71
|
-
class SourceDetails:
|
|
72
|
-
source_id: str
|
|
73
|
-
title: str
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
@dataclass
|
|
77
|
-
class ResearchSummary:
|
|
78
|
-
summary: str
|
|
79
|
-
citations: list[str]
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def lookup_source(params: SourceLookup) -> ToolResult[SourceDetails]:
|
|
83
|
-
details = SourceDetails(source_id=params.source_id, title="Ada Lovelace Archive")
|
|
84
|
-
return ToolResult(message=f"Loaded {details.title}", payload=details)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
catalog_tool = Tool[SourceLookup, SourceDetails](
|
|
88
|
-
name="catalog_lookup",
|
|
89
|
-
description="Look up a primary source identifier and return structured details.",
|
|
90
|
-
handler=lookup_source,
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
research_section = TextSection[ResearchGuidance](
|
|
94
|
-
title="Task",
|
|
95
|
-
body=(
|
|
96
|
-
"Research ${topic}. Use the `catalog_lookup` tool for citations and return"
|
|
97
|
-
" a JSON summary with citations."
|
|
98
|
-
),
|
|
99
|
-
tools=[catalog_tool],
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
prompt = Prompt[ResearchSummary](
|
|
103
|
-
name="research_run",
|
|
104
|
-
sections=[research_section],
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
rendered = prompt.render(ResearchGuidance(topic="Ada Lovelace"))
|
|
108
|
-
print(rendered.text)
|
|
109
|
-
print([tool.name for tool in rendered.tools])
|
|
110
|
-
|
|
111
|
-
reply = """```json
|
|
112
|
-
{
|
|
113
|
-
"summary": "Ada Lovelace pioneered computing...",
|
|
114
|
-
"citations": ["catalog_lookup:ada-archive"]
|
|
115
|
-
}
|
|
116
|
-
```"""
|
|
117
|
-
|
|
118
|
-
parsed = parse_output(reply, rendered)
|
|
119
|
-
print(parsed.summary)
|
|
120
|
-
print(parsed.citations)
|
|
121
|
-
````
|
|
122
|
-
|
|
123
|
-
### Optional Extras
|
|
124
|
-
|
|
125
|
-
Use the OpenAI helpers once the extra is installed:
|
|
126
|
-
|
|
127
|
-
```python
|
|
128
|
-
from weakincentives.adapters import OpenAIAdapter
|
|
129
|
-
|
|
130
|
-
adapter = OpenAIAdapter(model="gpt-4o-mini", client_kwargs={"api_key": "sk-..."})
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
If the dependency is missing, the adapter raises a runtime error with installation guidance.
|
|
134
|
-
|
|
135
|
-
## For Library Developers
|
|
136
|
-
|
|
137
|
-
### Environment Setup
|
|
138
|
-
|
|
139
|
-
1. Install Python 3.14 (pyenv users can run `pyenv install 3.14.0`).
|
|
140
|
-
1. Install [`uv`](https://github.com/astral-sh/uv).
|
|
141
|
-
1. Sync the virtualenv and optional git hooks:
|
|
142
|
-
```bash
|
|
143
|
-
uv sync
|
|
144
|
-
./install-hooks.sh # optional – wires git hooks that call make check
|
|
145
|
-
```
|
|
146
|
-
1. Use `uv run ...` when invoking ad-hoc scripts so everything stays inside the managed environment.
|
|
147
|
-
|
|
148
|
-
### Development Workflow
|
|
149
|
-
|
|
150
|
-
- `make format` / `make format-check` — run Ruff formatters.
|
|
151
|
-
- `make lint` / `make lint-fix` — lint with Ruff.
|
|
152
|
-
- `make typecheck` — execute Ty with warnings promoted to errors.
|
|
153
|
-
- `make test` — run pytest via `build/run_pytest.py` with `--cov-fail-under=100`.
|
|
154
|
-
- `make bandit`, `make deptry`, `make pip-audit` — security, dependency, and vulnerability audits.
|
|
155
|
-
- `make check` — aggregate the quiet quality gate; run this before every commit (git hooks enforce it).
|
|
156
|
-
|
|
157
|
-
### Project Layout
|
|
158
|
-
|
|
159
|
-
- `src/weakincentives/` — package root for the Python module.
|
|
160
|
-
- `src/weakincentives/prompts/` — prompt, section, and tool primitives.
|
|
161
|
-
- `src/weakincentives/adapters/` — optional provider integrations.
|
|
162
|
-
- `tests/` — pytest suites covering prompts, tools, and adapters.
|
|
163
|
-
- `specs/` — design docs; see `specs/PROMPTS.md` for prompt requirements.
|
|
164
|
-
- `build/` — thin wrappers that keep CLI tools quiet inside `uv`.
|
|
165
|
-
- `hooks/` — symlink-friendly git hooks (install via `./install-hooks.sh`).
|
|
166
|
-
|
|
167
|
-
### Release Notes
|
|
168
|
-
|
|
169
|
-
Version numbers come from git tags named `vX.Y.Z`. Tag the repository manually before pushing a release.
|
|
170
|
-
|
|
171
|
-
### More Documentation
|
|
172
|
-
|
|
173
|
-
`AGENTS.md` captures the full agent handbook, workflows, and TDD expectations. `ROADMAP.md` and `specs/` document upcoming work and prompt requirements.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
weakincentives/__init__.py,sha256=2hDTwJS-d3T6LPBd2dNcZvv-OLLjb8RV5UzuqUg3S7c,615
|
|
2
|
-
weakincentives/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
weakincentives/adapters/__init__.py,sha256=i4zRQQvL21f1up1NFSe9kk3U6E4Nxj3hYMkGHSc4xbE,923
|
|
4
|
-
weakincentives/adapters/core.py,sha256=UDo-Em289TiBwj6dau0tbssoSecyDEaYWyI5POPECiM,2345
|
|
5
|
-
weakincentives/adapters/openai.py,sha256=fDmh-V1_FO3tvvw68VJh9ggh-OW5Vl9HycwB7oSC6_w,12240
|
|
6
|
-
weakincentives/prompts/__init__.py,sha256=SQWvYq1je_dH_H55Yo8SaOawKPoOtODkuAsbMwvrZOo,1273
|
|
7
|
-
weakincentives/prompts/_types.py,sha256=y9-bB9Pt_bG-C0258UJ93oGq1zt-ktoutjAKkEsjSSk,904
|
|
8
|
-
weakincentives/prompts/errors.py,sha256=DR3GN54oTnNARkto3mVbIuT6BwhijTP3onLpcB6jdq0,1664
|
|
9
|
-
weakincentives/prompts/prompt.py,sha256=k9D3O00vJb1YN-jKKB7vtKUPrOtj3ux6JpbHgjcNnX4,17152
|
|
10
|
-
weakincentives/prompts/response_format.py,sha256=1LyhgEy9pWrx0n0oiYDqPb69qPLeZY7W165C6DkjYrY,1723
|
|
11
|
-
weakincentives/prompts/section.py,sha256=kvbtsk7cWr3cSh9GxoPpsPItwI1cwV0ZgLzxUulbefw,4240
|
|
12
|
-
weakincentives/prompts/structured.py,sha256=sUyfMwYI7oHqbvISTf7OABUs4VFKKGBkl_7LD7qvcHo,4842
|
|
13
|
-
weakincentives/prompts/text.py,sha256=KRliScmPigC45zHV-SotD9UZ2RdIspkwPTiVCCp8kd4,3118
|
|
14
|
-
weakincentives/prompts/tool.py,sha256=uGOFW8F2cMs_RRODqsXl6BpVXXTI3rlfKeTG-AHW3YE,9051
|
|
15
|
-
weakincentives/serde/__init__.py,sha256=oGOvoKTF2txToLZJ2sRAH9SC5myO_-GFKi1X9YHdQ6w,1270
|
|
16
|
-
weakincentives/serde/dataclass_serde.py,sha256=g5fEq3ACq6xphB0yGxIB_gJAD2u4nUxhDEC9mOtOk1c,37886
|
|
17
|
-
weakincentives-0.2.0.dist-info/METADATA,sha256=w1xpKkylT9qfaMjR5YxE00ux1yEX4bdQMzicO_kvyJc,5936
|
|
18
|
-
weakincentives-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
19
|
-
weakincentives-0.2.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
20
|
-
weakincentives-0.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|