Skip to content

Conversation

@ultramancode
Copy link

@ultramancode ultramancode commented Oct 27, 2025

Summary

Add optional reasoning_content field to LLMResultChunkDelta for structured streaming of LLM reasoning/thinking processes.

Relates to #227 (issue)
Follow-up to langgenius/dify#23313

Changes

class LLMResultChunkDelta(BaseModel):
    index: int
    message: AssistantPromptMessage
    reasoning_content: str | None = None  # ← NEW
    usage: LLMUsage | None = None
    finish_reason: str | None = None

Why

Currently, plugins merge reasoning into message.content with <think> tags, requiring Main to parse them back out. This adds:

  • A dedicated field for reasoning content
  • Enables cleaner separation between reasoning and final response
  • Eliminates fragile tag-based parsing

Compatibility

  • Backward-compatible: Optional field (default None), no breaking changes for existing plugins.

Next Steps

This is Phase 1(SDK) of a multi-repo rollout:

  • Phase 2 (Plugins): Add defensive pop("_dify_supports_reasoning_content", False) in all LLM plugins to prevent vendor API errors when Main sends capability flags

  • Phase 3 (Main): Read reasoning_content from plugins and use delta.reasoning_content directly if present (with fallback to _split_reasoning()), then send capability flag via model_parameters for plugin optimization.

  • Phase 4 (Plugins): Provider-by-provider opt-in to emit reasoning_content deltas

See #227 for full plan.

  • Add optional reasoning_content field to support direct streaming of LLM reasoning/thinking content, separate from the main message content.

Pull Request Checklist

Thank you for your contribution! Before submitting your PR, please make sure you have completed the following checks:

Compatibility Check

  • I have checked whether this change affects the backward compatibility of the plugin declared in README.md
  • I have checked whether this change affects the forward compatibility of the plugin declared in README.md
  • If this change introduces a breaking change, I have discussed it with the project maintainer and specified the release version in the README.md
  • I have described the compatibility impact and the corresponding version number in the PR description
  • I have checked whether the plugin version is updated in the README.md

Available Checks

  • Code has passed local tests
  • Relevant documentation has been updated (if necessary)

- Add optional reasoning_content field to support direct streaming of
  LLM reasoning/thinking content, separate from the main message content.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ultramancode, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant enhancement to the LLMResultChunkDelta model by adding an optional reasoning_content field. This new field facilitates the structured and direct streaming of an LLM's internal thought processes, distinct from its primary message output. The core purpose is to improve the clarity and maintainability of LLM responses by eliminating the need for heuristic parsing of reasoning embedded within message content. This is the foundational SDK change in a broader, multi-phase initiative to refine how LLM reasoning is handled and communicated.

Highlights

  • New Field: reasoning_content: An optional reasoning_content field has been added to the LLMResultChunkDelta class. This field is designed to stream the LLM's internal reasoning or thinking processes separately from the main message content.
  • Improved Separation of Concerns: This change aims to eliminate the current practice of embedding reasoning within message.content using <think> tags, providing a cleaner separation between the LLM's reasoning and its final response, and removing fragile tag-based parsing.
  • Backward Compatibility: The new field is optional (str | None = None), ensuring full backward compatibility with existing plugins and systems without requiring immediate changes.
  • Phased Rollout: This pull request represents Phase 1 (SDK) of a multi-repository rollout, with subsequent phases planned for plugin adaptation and Main system integration to fully leverage this new capability.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new optional field reasoning_content to the LLMResultChunkDelta model. This is a well-described, backward-compatible change that paves the way for separating LLM reasoning from the final response content, which is a good architectural improvement. My review includes a suggestion to add a description to the new field for better code clarity and maintainability.


index: int
message: AssistantPromptMessage
reasoning_content: str | None = None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve code clarity and maintainability, it's good practice to add a description for new model fields. This is especially helpful when the field's purpose, like with reasoning_content, is part of a larger architectural change. Using pydantic.Field to add a description will make the model's intent clearer for future developers and will be included in any generated schemas.

Suggested change
reasoning_content: str | None = None
reasoning_content: str | None = Field(default=None, description="The reasoning/thinking content from the LLM, separate from the main message content.")

@ultramancode
Copy link
Author

@laipz8200 @QuantumGhost
When you have a moment, could you please take a look at this?

@Mairuis Mairuis closed this Nov 24, 2025
@ultramancode
Copy link
Author

ultramancode commented Dec 5, 2025

Hi @Mairuis,

I noticed this PR was closed

Just to make sure I’m aligned with the long-term direction for reasoning support in plugins/SDKs:

  • Do you already have a different architecture in mind for exposing reasoning_content from plugins to Dify main?

My intention with #227 + this PR was:

  • to stop relying on fragile <think> tag parsing in plugins/main, and
  • to prepare SDK/plugins so they can help resolve issues like #27796 / #27819 in a clean way.

If this approach doesn’t fit the roadmap, I’d really appreciate any hints or pointers about the preferred direction and I’d be happy to rework the proposal to match that.

Thanks as always for your time and for maintaining the project!

@Mairuis
Copy link
Collaborator

Mairuis commented Dec 8, 2025

Please accept my sincere apologies for the incorrect closure of your pull request due to a technical issue in the trigger test. This was an operational mistake on our side, and I deeply regret any inconvenience this may have caused. Your PR has been reopened accordingly. Thank you for your understanding.

@Mairuis Mairuis reopened this Dec 8, 2025
@ultramancode
Copy link
Author

@Mairuis Thanks for reopening the PR and for the explanation, really appreciate it!

If there’s someone you’d recommend I coordinate with on this PR or the related issue (#227), I’d be happy to discuss the design with them and adjust the proposal to match the project’s long-term direction.

@leslie2046
Copy link
Contributor

Need to add reasoning_content field to AssistantPromptMessage as well,since some models(e.g deepseek-reasoner) requires write back last turn reasoning_content to assistant message.
https://api-docs.deepseek.com/zh-cn/guides/thinking_mode

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants