Problem
OLLAMA_THINK (added in #983 / merged via #990, answering #931, shipped in v0.26.0) is parsed in main.go and passed via ollama.WithThink(...) — but it never reaches the Ollama server, in either direction:
- langchaingo v0.1.14 (pinned in go.mod) declares
Think bool with json:"think,omitempty" inside its runner-options struct, so OLLAMA_THINK=true is serialized as options.think — a key the Ollama server ignores. The API expects think as a top-level field of /api/chat (docs/api.md).
- Because of
omitempty on a plain bool, OLLAMA_THINK=false is dropped from the payload entirely.
langchaingo's own test fixture shows the wire format (llms/ollama/testdata/TestWithThink.httprr):
{"model":"gemma3:1b","messages":[...],"format":"","options":{"temperature":0,"think":true}}
So for thinking models (qwen3, deepseek-r1, …) the server default wins either way: the model always thinks, and the env var documented in the README is a silent no-op.
Impact (measured)
With qwen3:14b our metadata pipeline runs at ~3 min/document with thinking vs ~8 s/document without — measured by injecting think: false top-level via a local proxy in front of Ollama (our current production workaround). Quality for the strict-JSON tasks was equal or better without thinking in a paired n=23 run (87.0 % vs 82.6 % correspondent accuracy). This is exactly the use case #931 requested the env var for.
Upstream
Root cause filed as tmc/langchaingo#1514 (with a suggested fix: top-level Think *bool).
Possible fix in paperless-gpt until upstream lands
The Ollama path already supports a custom HTTP client (ocr.OllamaHTTPClient(), used for OLLAMA_HEADERS). A small RoundTripper there could rewrite the request body for /api/chat — move/inject the configured think value at the top level. That keeps OLLAMA_THINK working with the pinned langchaingo and can be dropped once upstream fixes the serialization.
Environment
paperless-gpt v0.26.0+ (current main unchanged, go.mod: langchaingo v0.1.14) · Ollama 0.32.3 · qwen3:14b
Problem
OLLAMA_THINK(added in #983 / merged via #990, answering #931, shipped in v0.26.0) is parsed inmain.goand passed viaollama.WithThink(...)— but it never reaches the Ollama server, in either direction:Think boolwithjson:"think,omitempty"inside its runner-options struct, soOLLAMA_THINK=trueis serialized asoptions.think— a key the Ollama server ignores. The API expectsthinkas a top-level field of/api/chat(docs/api.md).omitemptyon a plain bool,OLLAMA_THINK=falseis dropped from the payload entirely.langchaingo's own test fixture shows the wire format (
llms/ollama/testdata/TestWithThink.httprr):So for thinking models (qwen3, deepseek-r1, …) the server default wins either way: the model always thinks, and the env var documented in the README is a silent no-op.
Impact (measured)
With qwen3:14b our metadata pipeline runs at ~3 min/document with thinking vs ~8 s/document without — measured by injecting
think: falsetop-level via a local proxy in front of Ollama (our current production workaround). Quality for the strict-JSON tasks was equal or better without thinking in a paired n=23 run (87.0 % vs 82.6 % correspondent accuracy). This is exactly the use case #931 requested the env var for.Upstream
Root cause filed as tmc/langchaingo#1514 (with a suggested fix: top-level
Think *bool).Possible fix in paperless-gpt until upstream lands
The Ollama path already supports a custom HTTP client (
ocr.OllamaHTTPClient(), used forOLLAMA_HEADERS). A smallRoundTripperthere could rewrite the request body for/api/chat— move/inject the configuredthinkvalue at the top level. That keepsOLLAMA_THINKworking with the pinned langchaingo and can be dropped once upstream fixes the serialization.Environment
paperless-gpt v0.26.0+ (current main unchanged, go.mod: langchaingo v0.1.14) · Ollama 0.32.3 · qwen3:14b