Profile-driven post-processing of inference responses.
The adapter translates the wire format faithfully. This module applies model-specific normalization based on the profile:
- Content fallback from thinking (reasoning models with empty content)
- Think tag stripping (DeepSeek, GLM embed reasoning in
<think>tags) - Malformed tool-call filtering (models that emit incomplete tool calls)
- XML text tool-call extraction (models that emit tool calls as text)
- JSON code-block tool-call extraction (last-resort fallback)
- Streaming delta normalization
All model-specific behavior lives here — not in the adapter.
Content is always [content_block()] — text extraction/injection uses
Intent.to_text/1 and Intent.text/1.
Summary
Functions
Normalizes a complete (non-streaming) response based on the model profile.
Normalizes a streaming delta based on the model profile.
Functions
@spec normalize(Arcanum.Response.t(), Arcanum.ModelProfile.t()) :: Arcanum.Response.t()
Normalizes a complete (non-streaming) response based on the model profile.
Applied in order: content fallback → think tag strip → malformed filter → XML extraction → JSON extraction.
@spec normalize_delta(Arcanum.Response.t(), Arcanum.ModelProfile.t()) :: Arcanum.Response.t()
Normalizes a streaming delta based on the model profile.
Only applies content fallback — tool calls are extracted from the final merged response.