Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot retrieve reasoning_content while streaming #29513

Open
5 tasks done
yigit353 opened this issue Jan 30, 2025 · 2 comments
Open
5 tasks done

Cannot retrieve reasoning_content while streaming #29513

yigit353 opened this issue Jan 30, 2025 · 2 comments

Comments

@yigit353
Copy link

Checked other resources

  • I added a very descriptive title to this issue.
  • I searched the LangChain documentation with the integrated search.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).

Example Code

When I run the simple code:

from dotenv import load_dotenv
from langchain_core.prompts import ChatPromptTemplate
from langchain_deepseek import ChatDeepSeek

load_dotenv()

llm = ChatDeepSeek(model="deepseek-reasoner", temperature=0, streaming=True)

prompt = ChatPromptTemplate(
    [
        (
            "system",
            "You are a helpful assistant that translates {input_language} to {output_language}.",
        ),
        ("human", "{input}"),
    ]
)

params = {
    "input_language": "English",
    "output_language": "German",
    "input": "I love programming.",
}

messages = prompt.invoke(params)

for chunk in llm.stream(messages):
    print(chunk)

I get empty reasoning_content while streaming. However, I need it to display in UI in real-time.
For that I wrote my own solution:

import asyncio
from typing import Any, Optional, Iterator
from typing import AsyncIterator

from langchain.schema import HumanMessage, AIMessage, SystemMessage
from langchain_core.messages import AIMessageChunk
from langchain_core.outputs import ChatGenerationChunk, LLMResult
from langchain_openai import ChatOpenAI


class DeepseekChatOpenAI(ChatOpenAI):
    async def _astream(
            self,
            messages: Any,
            stop: Optional[Any] = None,
            run_manager: Optional[Any] = None,
            **kwargs: Any,
    ) -> AsyncIterator[AIMessageChunk]:
        openai_messages = []
        for msg in messages:
            if isinstance(msg, HumanMessage):
                openai_messages.append({"role": "user", "content": msg.content})
            elif isinstance(msg, AIMessage):
                openai_messages.append({"role": "assistant", "content": msg.content})
            elif isinstance(msg, SystemMessage):
                openai_messages.append({"role": "system", "content": msg.content})
            else:
                raise ValueError(f"Unsupported message type: {type(msg)}")

        params = {
            "model": self.model_name,
            "messages": openai_messages,
            **self.model_kwargs,
            **kwargs,
            "extra_body": {
                "enable_enhanced_generation": True,
                **(kwargs.get("extra_body", {})),
                **(self.model_kwargs.get("extra_body", {}))
            }
        }
        params = {k: v for k, v in params.items() if v not in (None, {}, [])}

        # Create and process the stream
        async for chunk in await self.async_client.create(
                stream=True,
                **params
        ):
            content = chunk.choices[0].delta.content or ""
            reasoning = chunk.choices[0].delta.model_extra.get("reasoning_content", "") if chunk.choices[
                0].delta.model_extra else ""
            if content:
                yield ChatGenerationChunk(
                    message=AIMessageChunk(content=content),
                    generation_info={"reasoning": reasoning}
                )
            if reasoning:
                yield ChatGenerationChunk(
                    message=AIMessageChunk(
                        content="",
                        additional_kwargs={"reasoning": reasoning}
                    ),
                    generation_info={"reasoning": reasoning}
                )

    def invoke(
            self,
            messages: Any,
            stop: Optional[Any] = None,
            run_manager: Optional[Any] = None,
            **kwargs: Any,
    ) -> AIMessage:
        async def _ainvoke():
            combined_content = []
            combined_reasoning = []
            async for chunk in self._astream(messages, stop, run_manager, **kwargs):
                if chunk.message.content:
                    combined_content.append(chunk.message.content)
                # If reasoning is in additional_kwargs, gather that too
                if "reasoning" in chunk.message.additional_kwargs:
                    combined_reasoning.append(
                        chunk.message.additional_kwargs["reasoning"]
                    )
            return AIMessage(
                content="".join(combined_content),
                additional_kwargs={"reasoning": "".join(combined_reasoning)} if combined_reasoning else {}
            )

        return asyncio.run(_ainvoke())

Now I can get my results as a workaround.

For that I created a project around it: https://github.com/yigit353/DeepSeekRAGChat
You can read the post about it: https://www.linkedin.com/posts/yigitbekir_github-yigit353deepseekragchat-a-streamlit-based-activity-7290487810770309120-J0Ln?utm_source=share&utm_medium=member_desktop

Thank you!

Error Message and Stack Trace (if applicable)

No response

Description

  • I expect to get reasoning_content in additional_kwargs as a key value pair while streaming with llm.stream for llm = ChatDeepSeek(model="deepseek-reasoner", temperature=0, streaming=True)
  • I get empty content until the reasoning finishes and always empty additional_kwargs

System Info

System Information

OS: Windows
OS Version: 10.0.26100
Python Version: 3.11.9 (tags/v3.11.9:de54cf5, Apr 2 2024, 10:12:12) [MSC v.1938 64 bit (AMD64)]

Package Information

langchain_core: 0.3.33
langchain: 0.3.14
langchain_community: 0.3.14
langsmith: 0.2.11
langchain_chroma: 0.2.0
langchain_deepseek: Installed. No version info available.
langchain_groq: 0.2.3
langchain_huggingface: 0.1.2
langchain_ollama: 0.2.2
langchain_openai: 0.3.3
langchain_text_splitters: 0.3.5

Optional packages not installed

langserve

Other Dependencies

aiohttp: 3.11.11
async-timeout: Installed. No version info available.
chromadb: 0.5.23
dataclasses-json: 0.6.7
fastapi: 0.115.6
groq: 0.15.0
httpx: 0.27.2
httpx-sse: 0.4.0
huggingface-hub: 0.27.1
jsonpatch: 1.33
langsmith-pyo3: Installed. No version info available.
numpy: 1.26.4
ollama: 0.4.6
openai: 1.60.2
orjson: 3.10.15
packaging: 24.2
pydantic: 2.10.5
pydantic-settings: 2.7.1
PyYAML: 6.0.2
requests: 2.32.3
requests-toolbelt: 1.0.0
sentence-transformers: 3.4.0
SQLAlchemy: 2.0.37
tenacity: 9.0.0
tiktoken: 0.8.0
tokenizers: 0.21.0
transformers: 4.48.1
typing-extensions: 4.12.2
zstandard: Installed. No version info available.

@codergma
Copy link

codergma commented Feb 2, 2025

Like me, I believe that the method _convert_delta_to_message_chunk() did not retrieve the key reasoning_content.

def _convert_delta_to_message_chunk(

codergma added a commit to codergma/langchain that referenced this issue Feb 2, 2025
…tent while streaming

Extract reasoning_content in the _convert_delta_to_message_chunk function
codergma added a commit to codergma/langchain that referenced this issue Feb 2, 2025
…tent while streaming

Extract reasoning_content in the _convert_delta_to_message_chunk function
@yigit353
Copy link
Author

yigit353 commented Feb 2, 2025

Like me, I believe that the method _convert_delta_to_message_chunk() did not retrieve the key reasoning_content.

langchain/libs/partners/openai/langchain_openai/chat_models/base.py

Line 262 in 0c782ee

def _convert_delta_to_message_chunk(

You proposed a very minimal and excellent solution, however, I guess maintainers didn't want to change the base class for the solution. I believe that a change in the specialized DeepSeekChat class might be better if possible.

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

No branches or pull requests

2 participants