Skip to content

Conversation

@Harrrryz
Copy link

@Harrrryz Harrrryz commented Dec 5, 2025

Propagate reasoning_content onto assistant tool-call messages when using DeepSeek/thinking mode via LiteLLM. Extend the chat completion converter to optionally include reasoning content and enable it for DeepSeek. Added regression test covering reasoning content attachment.

@seratch seratch changed the title Fix DeepSeek reasoning content handling for LiteLLM Fix #2155 DeepSeek reasoning content handling for LiteLLM Dec 5, 2025
@seratch
Copy link
Member

seratch commented Dec 5, 2025

Thanks for sending this PR! One thing I want to check is that if this customization could be done on the LiteLLM side, that'd be the most appropriate situation for us. Have you considered contributing to the LiteLLM project?

@seratch seratch marked this pull request as draft December 5, 2025 23:41
@ihower
Copy link
Contributor

ihower commented Dec 7, 2025

This PR doesn’t cover the case where DeepSeek is accessed directly through its OpenAI-compatible endpoint.

For example:

custom_client = AsyncOpenAI(
    base_url="https://api.deepseek.com",
    api_key=os.getenv("DEEPSEEK_API_KEY")
)

model = OpenAIChatCompletionsModel(
        model="deepseek-reasoner",
        openai_client=custom_client,
    )

agent = Agent(
    name="Assistant",
    model= model,
    ...
)

Since the SDK’s internal conversion flow here through litellm -> chatcmpl -> raw item, they actually share part of the same code path. It would be ideal to fix both cases together for consistency.

Also, I’m currently updating Gemini 3 Pro support in PR 2158, so there might be some overlapping changes or conflicts to be aware of.

@Harrrryz
Copy link
Author

Harrrryz commented Dec 8, 2025

Thanks for sending this PR! One thing I want to check is that if this customization could be done on the LiteLLM side, that'd be the most appropriate situation for us. Have you considered contributing to the LiteLLM project?

Yes—looked into it. LiteLLM already returns reasoning_content on DeepSeek responses, but it doesn’t (and can’t, without keeping state) auto-inject that into subsequent assistant tool-call messages. To make it automatic upstream, they’d need an opt-in flag like “auto_include_reasoning_content” that replays the last reasoning text, or at least a warning/helper for DeepSeek + thinking + tools. I’ve drafted a LiteLLM docs update showing how to echo reasoning_content and linking to DeepSeek’s official guide; and already turned that into a PR.

@Harrrryz
Copy link
Author

Harrrryz commented Dec 8, 2025

This PR doesn’t cover the case where DeepSeek is accessed directly through its OpenAI-compatible endpoint.

For example:

custom_client = AsyncOpenAI(
    base_url="https://api.deepseek.com",
    api_key=os.getenv("DEEPSEEK_API_KEY")
)

model = OpenAIChatCompletionsModel(
        model="deepseek-reasoner",
        openai_client=custom_client,
    )

agent = Agent(
    name="Assistant",
    model= model,
    ...
)

Since the SDK’s internal conversion flow here through litellm -> chatcmpl -> raw item, they actually share part of the same code path. It would be ideal to fix both cases together for consistency.

Also, I’m currently updating Gemini 3 Pro support in PR 2158, so there might be some overlapping changes or conflicts to be aware of.

I picked this up and extended the fix to cover DeepSeek when it’s accessed via an OpenAI-compatible client (not just LiteLLM). Changes:

Add reasoning_content forwarding for DeepSeek in OpenAIChatCompletionsModel so tool-call messages include reasoning_content when model name/base_url indicates DeepSeek or thinking is enabled.
Regression tests to ensure reasoning_content is included for DeepSeek and not for non-DeepSeek models (tests/test_reasoning_content.py).

This should cover both LiteLLM and direct DeepSeek/OpenAI-compatible paths.

)
return response, ret

def _should_include_reasoning_content(self, model_settings: ModelSettings) -> bool:
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the logic here should be strictly restricted to DeepSeek models only to avoid potential regressions for other providers.

According to the DeepSeek Thinking Mode docs, we should only return True in these two cases:

  1. The model_name contains deepseek-reasoner.
    or
  2. The model_name contains deepseek and the thinking parameter is explicitly set.

Right now your logic will enable this whenever a thinking parameter is passed for non-DeepSeek models, and also for deepseek-chat even when thinking is not set.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LiteLLM DeepSeek thinking mode fails with missing reasoning_conten on tool calls

3 participants