Skip to content

Record what constrains a natural-language layer, and the design it forces - #45

Open
skearnes wants to merge 3 commits into
mainfrom
agent/nl-layer-constraints
Open

Record what constrains a natural-language layer, and the design it forces#45
skearnes wants to merge 3 commits into
mainfrom
agent/nl-layer-constraints

Conversation

@skearnes

@skearnes skearnes commented Aug 18, 2026

Copy link
Copy Markdown
Member

Summary

An entry recording why the NL layer cannot use constrained decoding, and a design doc beside it for the layer that follows. The measurements are live API calls, not inference from docs — the probes are in the entry's assets.

Changes

  • entries/2026-08-17-what-constrains-a-natural-language-layer/README.md — seven findings: the four walls constrained decoding hits, what a flattened depth-2 grammar with all 431 scalar paths enumerated does fit, the JSON-string shape both models return, model accuracy and cost, and a gap in the grammar itself.

  • assets/nl-search-design.md — the design for review: scope, module layout, the translate/repair/answer flow, error taxonomy, testing, and three open questions.

  • assets/*.py — twelve probes, including two reusable schema transforms (stratify.py, require_all.py).

  • assets/nl-search-plan.md — seven tasks, TDD throughout, each ending in a commit.

Testing

Every table in the entry is a live call against the Messages API using the interface deployment's key. probe_repair.py <model> reproduces the accuracy and cost figures; probe_recursion.py needs no key at all, since it uses a mock transport to capture what the SDK puts on the wire.

Notes

The plan is now beside the design. Task 1 is the grammar change, not NL code; tasks 2-7 build the layer and its eval harness.

The design is draft, for review — please read assets/nl-search-design.md before I turn it into an implementation plan. The part most worth your eye is "The gap this depends on": aggregates and ordering keys cannot reach a value under a repeated level, so the ten highest-yielding reactions is unwritable today. I propose closing that in the grammar first, since an NL layer built over it would answer the question wrongly rather than refuse.

Two numbers that looked inconsistent are reconciled in the entry: the probe walks to 431 scalar paths, while the schema rendering counts 442 leaves, because the rendering carries the key side of a map too.

🤖 Generated with Claude Code

skearnes and others added 2 commits August 17, 2026 21:40
…rces

Constrained decoding cannot carry the search grammar: circular refs are
refused, the compiled grammar has a size budget, oneOf is unsupported,
and union-typed parameters are capped. Stratifying into acyclic levels,
requiring every property, and flattening the predicate union each moved
a wall, and the best that fits is a depth-2 tree -- which cannot express
the correlation the pivots exist to serve.

So translation is unconstrained generation checked afterwards, which the
measurements say is fine: Opus 5 compiles 9/10 first try, Haiku 4.5 gets
7/10 with one repair turn at 5.6x less. The design beside the entry
builds on that, and starts by closing a gap the probing exposed -- an
aggregate cannot reach a value under a repeated level, so "the ten
highest-yielding reactions" is unwritable and both models tried anyway.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Seven tasks: the reduction that closes the grammar gap first, then the
module and its extra, translation with the coercing parse, the repair
turn pinned to one attempt, the summary and prose answer, the round
trip, and an eval harness that scores on the reactions a query returns
rather than on how the query is spelled.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three things the design got wrong, each found by building it: a resolved
compound compared in PubChem's spelling rather than the corpus's, which
answered a question about 24,930 reactions with zero; a forced tool call
that left the model no way to decline, so both models built a plausible
query for a question the grammar cannot express; and an eval case whose
counterexamples were sampled rather than derived, which failed both
models on a translation they had got right.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant