fix(oaistream): replay ReasoningContent when converting messages - #4485
Open
MysticalMount wants to merge 1 commit into
Open
MysticalMount wants to merge 1 commit into
MysticalMount wants to merge 1 commit into
Conversation
OpenAI-compatible custom providers (e.g. Qwen served via llama.cpp, vLLM, or other endpoints using the DeepSeek-style reasoning_content convention) have their streamed reasoning captured into msg.ReasoningContent, but convertMessagesWithCaps built the outgoing assistant param from Content, FunctionCall, and ToolCalls only -- the stored reasoning was silently dropped when the conversation history was replayed on the next request. openai-go's typed ChatCompletionAssistantMessageParam has no field for reasoning_content (non-standard extension -- see openai/openai-go#558), so it is attached via SetExtraFields when present; nothing is added when the history contains no reasoning. The assistant-turn skip predicate is also taught to keep reasoning-only messages (e.g. a model that exhausted its output budget mid-reasoning) instead of dropping them as empty. Fixes docker#4363 Signed-off-by: Jay <12496124+MysticalMount@users.noreply.github.com>
MysticalMount
force-pushed
the
fix/reasoning-content-oaistream-v2
branch
from
September 30, 2026 08:10
ab8d68a to
15d5b95
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4363
Supersedes #4365 (re-based onto current
mainwith signed commits, extended so reasoning-only assistant messages are no longer dropped as empty).Root cause
convertMessagesWithCapsinpkg/model/provider/oaistream/messages.gobuilt the outgoing assistant message param fromContent,FunctionCall, andToolCallsonly.msg.ReasoningContentwas never read, so reasoning captured from OpenAI-compatible custom providers (e.g. Qwen via llama.cpp, vLLM) was silently dropped when the conversation history was replayed on the next request.The same assistant-turn skip predicate also dropped messages that contain only reasoning (no text, no tool calls — e.g. a model that exhausted its output budget mid-reasoning) before conversion ever saw them.
Fix
SetExtraFields—openai-go's typedChatCompletionAssistantMessageParamhas no field forreasoning_content(non-standard, provider-specific extension; see can @chatcompletion.go support reasoning_content? openai/openai-go#558). Nothing is added when the stored history contains no reasoning.Compatibility note
reasoning_contentis only serialized when a stored message actually carries reasoning. Since this path serves many OpenAI-compatible endpoints (xAI, Mistral, Groq, OpenRouter, DeepSeek, ...), a session that accumulates reasoning on one endpoint will send the field when later routed to any other endpoint through this provider. If a specific endpoint is known to reject unknown fields, preservation could be made per-model opt-out via the existing capability-override mechanism (as the issue itself suggested) — happy to add that as a follow-up if maintainers prefer.Testing
Added
repro_issue4363_test.gocovering: reasoning is carried onto the replayed message, no field is added when reasoning is absent, reasoning survives alongside tool calls, and a reasoning-only assistant message survives conversion.