An adapter sits between your signature and the LM. It formats typed inputs into prompts and parses LM responses back into typed outputs.Documentation Index
Fetch the complete documentation index at: https://dsrs.herumbshandilya.com/llms.txt
Use this file to discover all available pages before exploring further.
What adapters do
ChatAdapter, which handles both formatting and parsing.
ChatAdapter
Prompt structure
The system message has four parts (in this order):- Field descriptions - Lists input/output fields with types and descriptions
- Field structure - Shows the marker format + type schemas
- Response instructions - “Respond with
[[ ## field ## ]]…” - Task description - Your instruction from the signature docstring (at the end)
Marker protocol
Fields are delimited by markers:Type schemas
For complex types, the adapter renders full schemas using BAML’s schema format:- Module paths stripped:
my_crate::Sentiment→Sentiment class/enumprefixes removed" | "→" or "(more natural)
Robust parsing with jsonish
Response parsing uses BAML’sjsonish parser, which handles:
- Malformed JSON - Missing quotes, trailing commas
- Markdown fences - Extracts JSON from ```json blocks
- Type coercion -
"42"→42,"true"→true - Partial recovery - Returns what it can parse + all errors
Constraint evaluation
After parsing, the adapter runs constraints:#[check]results → stored in metadata#[assert]failures → returnsParseError::AssertFailed
Error handling
Parse errors aggregate - you get all problems, not just the first:Using the adapter directly
Usually you don’t touch the adapter -Predict handles it. But for debugging:
Input formatting options
Input fields support two rendering paths:#[format("json" | "yaml" | "toon")]: serialize a field using that format.#[render(jinja = "...")]: render a field with a MiniJinja template.#[format]and#[render]are mutually exclusive on the same field.
#[render] context in ChatAdapter:
this: current field valueinput: full input object (plus top-level alias overlays)field:{ name, rust_name, type }vars: adapter/surface vars (currently{})
ChatAdapter configures MiniJinja with strict undefined behavior.
Available filters include:
- MiniJinja built-ins
- BAML parity helpers (
regex_match,sum) truncatefor length-limited string rendering
ChatAdapter panics.
Compiled templates are cached process-wide by template string.
Real example: Insurance claim extraction
Here’s what a prompt looks like for a complex nested type (fromexamples/16-insurance-claim-prompt.rs):
Full type definitions (InsuranceClaim and nested types)
Full type definitions (InsuranceClaim and nested types)
- Enums with many variants become “Definitions” at the top
- Doc comments become inline
//comments in the schema Option<T>renders asT or null- Nested objects show their full structure
- The instruction comes from the signature docstring
Design notes
- DSPy inspiration: Marker protocol from DSPy’s ChatAdapter
- BAML inspiration: Schema rendering and jsonish parsing from BAML
- Separation of concerns: Adapter doesn’t know about LMs - just formatting/parsing
