Architecture
The parts of TypedLM, how a call flows through them, and where each one lives in the code.
Crates
| Crate | Content |
|---|---|
typedlm |
the library: signatures, programs, providers, validation, evaluation |
typedlm-macros |
#[derive(TypedLm)], used through typedlm |
typedlm-cli |
Evals harness, snapshot store, the typedlm binary for stored reports |
Modules in crates/typedlm/src/:
| Module | Responsibility |
|---|---|
signature.rs |
the Signature trait |
program.rs |
Program: strategy choice, instructions, worked examples, repair loop, tracing |
optimize.rs |
few-shot optimizer on pathwise’s budgeted local search, reflective instruction optimizer (feature optimize) |
tools.rs |
action enums as tools, Action, Policy, ToolProgram |
compiled.rs |
CompiledProgram: configuration as JSON artefact, signature hash, checks on load |
provider.rs |
Provider, DynProvider, Request, Response, Capabilities |
dialect.rs |
schema_for_dialect: schema rewriting per provider |
output.rs |
parse_output: the validation pipeline |
json.rs |
tolerant JSON extraction |
schema.rs |
schema validator, Violation |
error.rs |
Error, repair feedback |
http.rs |
OpenAiCompatible (feature http) |
eval.rs |
datasets, metrics, evaluate, Report (feature eval) |
eval/regression.rs |
Baseline, compare, Report::require_score |
sha256.rs |
dataset and request fingerprints |
testing.rs |
TestProvider, FnProvider, Recorder, Replay |
Signature
Signature is implemented on the input type. It names the output type, which must implement
DeserializeOwned + JsonSchema, and carries a name and a description as constants. The derive
fills them from #[lm(output = …)] and the doc comment; implementing the trait by hand is
supported. An optional validate function holds domain rules.
A call, step by step
Program::executeserialises the input to JSON.- It asks the provider for its
Capabilitiesand chooses the strategy: the one set on the program, otherwise the strongest the provider supports. - It rewrites the output schema into the provider’s dialect and builds the instructions: the description, plus the schema when the strategy or the provider requires it.
- The provider sends the request and returns the raw answer, the model, the finish reason and token usage.
parse_outputturns the answer into the output type or an error (see Validation and repair).- A repairable error adds the answer and its feedback to the next request, until the answer is valid or the attempts are used up.
- The result is an
Execution(output, attempts, usage, model, strategy) or aFailedwith the error, attempts and usage.
All of it runs inside one tracing span.
Providers
Provider uses native async fn in traits, so a program over a concrete provider has no boxing.
DynProvider is the object-safe counterpart, implemented for every provider; Box<dyn DynProvider> is a provider again. Transport retries live in the provider, repairs in the program.
Evaluation
evaluate runs every example through Program::execute with a concurrency limit
(futures-util, no runtime binding) and builds a Report from the outcomes. It reuses the
schema validator to check dataset labels when loading. The report keeps each example’s
score and a SHA-256 of the dataset, so eval/regression.rs can compare two runs pairwise and
refuse runs on different examples.