-
Notifications
You must be signed in to change notification settings - Fork 0
docs: search plumbing for agent autoresearch loops #279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,48 @@ | ||||||||||||||||||||||||
| # Autoresearch / agent loops | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Alkahest is useful inside unsupervised or lightly-supervised math search loops | ||||||||||||||||||||||||
| because it is designed to be called **many times under a budget**, with results | ||||||||||||||||||||||||
| that stay auditable. The pieces below are the *search plumbing* that sits next | ||||||||||||||||||||||||
| to the mathematics: | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| | Need | API | Guide | | ||||||||||||||||||||||||
| |---|---|---| | ||||||||||||||||||||||||
| | Bound one candidate so a hard instance cannot stall the sweep | `Budget`, `context(budget=…)`, `request_cancel` | [Budgets](./budgets.md) | | ||||||||||||||||||||||||
| | Fan out many candidates without one failure aborting the batch | `batch_map`, `integrate_many`, … | [Batch](./batch.md) | | ||||||||||||||||||||||||
| | Cheap, versioned payloads for logs / LLM context | `DerivedResult.to_dict(mode="compact")` | [Derivation logs](./derivations.md#machine-parseable-output-to_dict--to_json) | | ||||||||||||||||||||||||
| | Accumulate claims across iterations | `alkahest.research` claim graph | [Claim graphs](./claim-graphs.md) | | ||||||||||||||||||||||||
| | Ask “will this call certify?” before spending compute | `certifiable`, `require_certificate` | [Certificate coverage](./certificate-coverage.md) | | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| A minimal loop shape: | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ```python | ||||||||||||||||||||||||
| import alkahest as ak | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| pool = ak.ExprPool() | ||||||||||||||||||||||||
| x = pool.symbol("x") | ||||||||||||||||||||||||
| candidates = [x**2, ak.sin(x), ak.log(ak.log(x))] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| with ak.research.session(title="Sweep", pool=pool, capture=True) as s: | ||||||||||||||||||||||||
| with ak.context(pool=pool, budget=ak.Budget(wall_ms=200, max_steps=50_000, seed=7)): | ||||||||||||||||||||||||
| for item in ak.integrate_many(candidates, x, parallel=True): | ||||||||||||||||||||||||
| if not item.ok: | ||||||||||||||||||||||||
| # E-BUDGET-* → deprioritize; E-INT-* → record and move on | ||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||
| # Token-cheap record for the next iteration / a human referee | ||||||||||||||||||||||||
| _ = item.value.to_dict(mode="compact") | ||||||||||||||||||||||||
|
Comment on lines
+31
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Keep the compact envelope instead of discarding it.
Proposed fix+records = []
with ak.research.session(title="Sweep", pool=pool, capture=True) as s:
with ak.context(pool=pool, budget=ak.Budget(wall_ms=200, max_steps=50_000, seed=7)):
for item in ak.integrate_many(candidates, x, parallel=True):
if not item.ok:
continue
- _ = item.value.to_dict(mode="compact")
+ records.append(item.value.to_dict(mode="compact"))🤖 Prompt for AI Agents |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| print(s.graph.to_markdown()) | ||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Honesty rules that matter in a loop: | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - A **budget trip is a fine answer**, not a crash — catch `BudgetExceededError` | ||||||||||||||||||||||||
| (`E-BUDGET-*`) and deprioritize that candidate. | ||||||||||||||||||||||||
| - A **batch never drops a slot** — failures become `BatchItem(ok=False, error=…)`. | ||||||||||||||||||||||||
| - **Compact mode never hides verification status** — `verification["status"]` | ||||||||||||||||||||||||
| stays readable; Lean source is omitted on purpose. | ||||||||||||||||||||||||
|
Comment on lines
+39
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Align the failure-handling rules with
Proposed wording- A budget trip is a fine answer, not a crash — catch `BudgetExceededError`
- (`E-BUDGET-*`) and deprioritize that candidate.
- A batch never drops a slot — failures become `BatchItem(ok=False, error=…)`.
+ For direct calls, catch `BudgetExceededError` (`E-BUDGET-*`). For batch
+ calls, inspect `BatchItem.error` and deprioritize failed candidates.
+ Batch calls preserve a slot for ordinary `Exception` failures, but
+ `KeyboardInterrupt` and `SystemExit` still stop the batch.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| - **Certificates are withheld rather than lied about** — see | ||||||||||||||||||||||||
| [certificate coverage](./certificate-coverage.md). | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| See also the runnable experimental-mathematics demo | ||||||||||||||||||||||||
| [`examples/pslq_research_loop.py`](https://github.com/alkahest-cas/alkahest/blob/main/examples/pslq_research_loop.py). | ||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -169,6 +169,32 @@ Exception subclasses | |
| ak.diff(ak.sin(x), x) # fine — certifies | ||
| ak.integrate(ak.log(x), x) # raises E-CERT-001 | ||
|
|
||
| .. exception:: BudgetExceededError | ||
|
|
||
| Code prefix ``E-BUDGET-*``. A cooperative budget or cancellation trip — | ||
| not a mathematical failure. Raised when an active | ||
| :class:`~alkahest.Budget` is exceeded (or :func:`~alkahest.request_cancel` | ||
| was called) at a checkpoint inside an engine that honors budgets | ||
| (notably :func:`~alkahest.integrate`). See the | ||
|
Comment on lines
+172
to
+178
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Document the Python wall-clock fallback path.
🤖 Prompt for AI Agents |
||
| `budgets guide <../budgets.html>`_ and the | ||
| `workload API <workload.html>`_. | ||
|
|
||
| - ``E-BUDGET-001`` — wall-clock limit elapsed | ||
| - ``E-BUDGET-002`` — step limit exceeded | ||
| - ``E-BUDGET-003`` — cancellation requested | ||
|
|
||
| Example:: | ||
|
|
||
| import alkahest as ak | ||
|
|
||
| pool = ak.ExprPool() | ||
| x = pool.symbol("x") | ||
| try: | ||
| with ak.context(pool=pool, budget=ak.Budget(max_steps=0)): | ||
| ak.integrate(x**2, x) | ||
| except ak.BudgetExceededError as e: | ||
| print(e.code) # E-BUDGET-002 | ||
|
|
||
| Catching errors by subsystem | ||
| ---------------------------- | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Qualify the determinism claim for wall-clock budgets.
wall_msdepends on machine load and parallel scheduling. A seed does not make wall-clock cutoffs deterministic. State that explicit context improves reproducibility, while step and seed controls can be deterministic and wall-clock limits are best effort.🤖 Prompt for AI Agents