Skip to main content

Module reasoning

Module reasoning 

Source
Expand description

Separating a model’s reasoning from its content.

Thinking models (Nemotron with detailed thinking on, DeepSeek-R1, Qwen3, …) emit their chain-of-thought inline in the content stream, wrapped in <think>…</think> tags — distinct from the Ollama/OpenAI separate reasoning field the loop already detects. Left in place, that reasoning leaks into the reply shown to the user and into the content the agentic loop parses (issue #385). This module strips it.

It’s a split, not just a strip: split_reasoning returns (content, reasoning) so the reasoning can be captured (the plan_mode technique, docs/design/thinking-effort-and-plan-mode.md) rather than thrown away — today every caller discards the reasoning half, matching prior behavior.

Two surfaces:

  • split_reasoning — batch, for a fully-assembled reply (the non-streaming completion paths).
  • ThinkFilter — incremental, for the streaming path, where a <think> block spans token boundaries (<thi / nk>…</thi / nk>) and must be suppressed live without ever printing a partial tag.

Structs§

ThinkFilter
An incremental filter that suppresses <think>…</think> spans from a streamed content sequence, emitting only the clean (non-reasoning) text — even when a tag is split across feeds.

Functions§

emits_leading_reasoning
Whether a model streams its chain-of-thought as a lone leading closer (reasoning</think>answer, with no opening <think>) — the shape Nemotron (detailed thinking on), DeepSeek-R1, and Qwen3 emit. Such models need ThinkFilter::with_leading_reasoning so the streamed reasoning (and the bare </think>) is suppressed rather than printed into the reply.
split_reasoning
Split inline <think>…</think> reasoning out of content, returning (clean_content, reasoning).