You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Other LLM functionality (reasoning, grounding, prompt caching, etc.)
New models / model parameter fixes
Version
Bumped top-level version in manifest.yaml (not the one under meta)
dify_plugin>=0.3.0,<0.11.0 is declared in pyproject.toml and locked in uv.lock (or kept in requirements.txt for legacy plugins without uv.lock) — SDK docs
Testing
Local deployment — Dify version: dify-ee 3.9.14 LTS
Hi @shirumesu, thanks for fixing the prefilled think handling in openai_api_compatible!
Heads-up about models/openai_api_compatible/manifest.yaml: the consolidated dependency refresh (#4106–#4111) bumped it to 0.0.69 on main, and several PRs are currently open for this plugin from different authors (#3795, #3869, #4066, #4068, #4079). Please rebase on latest main and bump the version to the next unused one so the releases don't collide. If there's a related issue for this fix, linking it in the description would help too.
Enabling thinking locally does not guarantee visible reasoning, especially in strict compatibility mode, which does not send the thinking switch to the server. A content-only stream such as {"class":"x"} becomes <think>\n{"class":"x"} without a closing tag, incorrectly marking the answer as unfinished reasoning. Require an explicit prefilled-template capability or confirm an unmatched closing delimiter before inserting the opening tag, and add a content-only streaming regression case with enable_thinking=True.
Thanks @crazywoola! Rebased onto the latest main and bumped the version to 0.0.72.
Related issue: None. This came up in real-world usage; happy to open an issue with full details if that would help.
Summary of changes since the last review:
Literal in normal answers: non-streaming restoration is now skipped when the whole response is valid JSON, so {"tag":"</think>"} is preserved in every configuration. I didn't gate it on enable_thinking, because in strict mode (the default) the flag is never sent, yet Qwen3.5 still prefills <think>, so gating would leave the all-defaults case broken.
Streaming with the flag unset: streaming has to decide on the first chunk, before any </think> is visible. With the flag unset, the server default depends on the model (Qwen3.5 thinks by default, hybrid models like DeepSeek-V3.1 don't), so always restoring would wrap the latter's entire answer in an unclosed <think>. Streaming therefore restores only when thinking is explicitly enabled, which matches vLLM's Qwen3ReasoningParser.
Tests: added the requested reasoning</think>\n{"class":"x"} case, plus all-defaults stripping, preserving a literal </think> across 3 configs, streaming restoration (including a tag split across chunks), and no false restoration in streaming. All 104 tests pass.
Known limitation: streaming with the flag unset (or when the server thinks but the plugin assumes it doesn't) is not covered, since fixing it would require buffering the full output and losing streaming for every default-config model. The recommended setup is still enabling a server-side reasoning parser
Chat templates such as Qwen3.5's prefill `<think>` in the prompt, so the
generated content only contains the closing tag and Dify cannot strip the
reasoning before parsing JSON.
- Non-streaming: restore the opening tag when `</think>` comes first,
unless the whole content is already valid JSON, then apply the existing
thinking filter.
- Streaming: prepend the opening tag to the first content chunk only when
thinking is explicitly enabled, since the stream cannot wait for the
closing tag and hybrid models may default to non-thinking.
Related to langgenius/dify#26992.
Only treat a closing think tag that ends its line as the end of prefilled
reasoning, so a literal `</think>` in prose or fenced JSON is preserved.
In streams, hold the first few characters until a split `<think>` or
`</think>` can be recognized, so empty reasoning that starts with the
closing tag also gets its opening tag restored.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The thinking-tag heuristics can misclassify normal content as reasoning, deleting valid replies or marking content-only streams as unfinished reasoning.
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
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.
Summary
Qwen3.5 can prefill the opening
<think>tag in its prompt, so generated content may contain reasoning followed by</think>without an opening tag.References:
Restore the missing opening tag so Question Classifier can remove the complete reasoning block before parsing JSON.
Release Notes
Change Type
Screenshots / Videos
LLM Plugin Checklist
Areas affected by this change (check all that apply)
Version
versioninmanifest.yaml(not the one undermeta)dify_plugin>=0.3.0,<0.11.0is declared inpyproject.tomland locked inuv.lock(or kept inrequirements.txtfor legacy plugins withoutuv.lock) — SDK docsTesting