Skip to main content

Module normalize

Module normalize 

Source
Expand description

§normalize

LOC Complexity

Universal local-LLM consistency layer.

This module rewrites model-specific output dialects into the strict OpenAI-shaped crate::domain::agent::LlmStreamEvent sequence that the rest of the codebase expects. Adapters wrap the LLM stream once at the port boundary; every downstream surface (Axum, CLI, Tauri, proxy) consumes the canonical form.

Dialect selection is data-driven: a crate::domain::dialect::DialectSpec — detected from the model’s own chat template at import time and persisted per model — configures the delimited parser, and the same spec generates the decode-time GBNF grammar, so parsing and enforcement cannot drift.

§Module map

§Adding a new dialect

Usually: no code. A dialect whose template renders tool calls as MARKERS{json}MARKERS is derived automatically by the template probe in gglib-gguf and arrives here as a spec — registry::get_parser drives the delimited parser with it.

For a new builtin (a dialect that needs a fallback tag because its templates are often stripped):

  1. Add a pub const FORMAT_* to tags.
  2. Map the tag to a spec in registry::dialect_for_tags.

Only a genuinely new body codec (a non-JSON, non-inner-XML body encoding) needs parser code — a BodyCodec variant plus its decoder in parsers; see CONTRIBUTING.md’s architecture-registry section.

The registry is the only place that knows the full set of parsers, by design — see the module docs there.

Future work: <think> handling still lives outside the spec — stream strips think tags unconditionally and history keeps its own marker constants. Folding reasoning markers into DialectSpec is deliberate follow-up scope, since it changes behaviour for untagged models.

Modules

Re-exports§

pub use registry::get_parser;
pub use residue::ResidueScanner;
pub use residue::scan_complete;

Modules§

coerce 🔒
Deterministic local repair of a tool-call body the parsers rejected.
error 🔒
Non-fatal error reporting from normalization parsers.
history 🔒
Cross-turn “thinking debt” removal for chat history.
oneshot 🔒
One-shot dialect normalization for non-streaming responses.
parser 🔒
The ToolCallParser trait and its companion ParserOutput.
parsers 🔒
parsers
registry
Dialect-spec parser dispatch.
residue
Chunk-safe scanner for dialect markup that reached client-visible text.
stream 🔒
NormalizingStream — the single wrap point that canonicalises an LLM event stream.
tags
Format-tag constants used to select a normalization parser.

Structs§

NormalizationError
A non-fatal normalization issue surfaced from a parser.
NormalizingStream
Stream adapter that runs every event through a ToolCallParser before re-emitting the normalized result. See module docs.
ParserOutput
Result of feeding one chunk of input to a parser.

Enums§

NormalizationErrorKind
Discriminates the kind of malformation a parser detected.

Traits§

ToolCallParser
Stream-stateful parser that normalizes a single LLM dialect into canonical ParserOutput fragments.

Functions§

normalize_chat_completion_body
Normalize a complete (non-streaming) chat.completion response body in place, using the parser for the model’s resolved dialect.
strip_thinking_debt
Strip reasoning artifacts from prior assistant messages in messages.