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

print reasoning with deepseek model #30067

Open
5 tasks done
laurafbec opened this issue Mar 2, 2025 · 18 comments
Open
5 tasks done

print reasoning with deepseek model #30067

laurafbec opened this issue Mar 2, 2025 · 18 comments
Labels
🤖:bug Related to a bug, vulnerability, unexpected error with an existing feature

Comments

@laurafbec
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

The following code does not return DeepSeek reasoning:
`from langchain_core.prompts import ChatPromptTemplate
from dotenv import load_dotenv

load_dotenv()
import os

from langchain_deepseek import ChatDeepSeek
from langchain_openai import ChatOpenAI

#os.environ["DEEPSEEK_API_KEY"] = os.getenv("DEEPSEEK_API_KEY")

llm = ChatDeepSeek(
model="deepseek-chat",
temperature=0,
max_tokens=None,
timeout=None,
max_retries=2,
# other params...
)

llm = ChatOpenAI(
#model = 'deepseek/deepseek-chat:free',
#model = 'deepseek/deepseek-chat',
model = 'deepseek/deepseek-r1:nitro',
#model='deepseek/deepseek-r1-distill-qwen-32b',
#model='deepseek/deepseek-r1-distill-llama-8b',
base_url="https://openrouter.ai/api/v1",
api_key=os.getenv("OPENROUTER_API_KEY"),
model_kwargs={"extra_body": {"include_reasoning": True}}
)

messages = [
(
"system",
"You are a helpful assistant that translates English to French. Translate the user sentence.",
),
("human", "I love programming."),
]
ai_msg = llm.invoke(messages)
print(ai_msg.content)

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

chain = prompt | llm
result = chain.invoke(
{
"input_language": "English",
"output_language": "German",
"input": "I love programming.",
}
)
print(result.content)
print(result)`

Error Message and Stack Trace (if applicable)

I'm not able to print the reasoning content of deepseek model. Find attached the code I'm using.
Thanks in advance!

Description

`from langchain_core.prompts import ChatPromptTemplate
from dotenv import load_dotenv

load_dotenv()
import os

from langchain_deepseek import ChatDeepSeek
from langchain_openai import ChatOpenAI

#os.environ["DEEPSEEK_API_KEY"] = os.getenv("DEEPSEEK_API_KEY")

llm = ChatDeepSeek(
model="deepseek-chat",
temperature=0,
max_tokens=None,
timeout=None,
max_retries=2,
# other params...
)

llm = ChatOpenAI(
#model = 'deepseek/deepseek-chat:free',
#model = 'deepseek/deepseek-chat',
model = 'deepseek/deepseek-r1:nitro',
#model='deepseek/deepseek-r1-distill-qwen-32b',
#model='deepseek/deepseek-r1-distill-llama-8b',
base_url="https://openrouter.ai/api/v1",
api_key=os.getenv("OPENROUTER_API_KEY"),
model_kwargs={"extra_body": {"include_reasoning": True}}
)

messages = [
(
"system",
"You are a helpful assistant that translates English to French. Translate the user sentence.",
),
("human", "I love programming."),
]
ai_msg = llm.invoke(messages)
print(ai_msg.content)

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

chain = prompt | llm
result = chain.invoke(
{
"input_language": "English",
"output_language": "German",
"input": "I love programming.",
}
)
print(result.content)
print(result)`

System Info

System Information

OS: Windows
OS Version: 10.0.22631
Python Version: 3.10.0 | packaged by conda-forge | (default, Nov 10 2021, 13:20:59) [MSC v.1916 64 bit (AMD64)]

Package Information

langchain_core: 0.3.40
langchain: 0.3.19
langchain_community: 0.3.14
langsmith: 0.2.11
langchain_deepseek: 0.1.0
langchain_google_genai: 2.0.11
langchain_groq: 0.2.4
langchain_huggingface: 0.1.2
langchain_mongodb: 0.4.0
langchain_openai: 0.3.7
langchain_text_splitters: 0.3.6
langchain_together: 0.3.0
langgraph_sdk: 0.1.51

Optional packages not installed

langserve

Other Dependencies

aiohttp: 3.11.11
aiohttp<4.0.0,>=3.8.3: Installed. No version info available.
async-timeout<5.0.0,>=4.0.0;: Installed. No version info available.
dataclasses-json: 0.6.7
filetype: 1.2.0
google-ai-generativelanguage: 0.6.16
groq: 0.18.0
httpx: 0.28.1
httpx-sse: 0.4.0
huggingface-hub: 0.28.1
jsonpatch<2.0,>=1.33: Installed. No version info available.
langchain-anthropic;: Installed. No version info available.
langchain-aws;: Installed. No version info available.
langchain-cohere;: Installed. No version info available.
langchain-community;: Installed. No version info available.
langchain-core<1.0.0,>=0.3.34: Installed. No version info available.
langchain-core<1.0.0,>=0.3.35: Installed. No version info available.
langchain-core<1.0.0,>=0.3.39: Installed. No version info available.
langchain-core>=0.3: Installed. No version info available.
langchain-deepseek;: Installed. No version info available.
langchain-fireworks;: Installed. No version info available.
langchain-google-genai;: Installed. No version info available.
langchain-google-vertexai;: Installed. No version info available.
langchain-groq;: Installed. No version info available.
langchain-huggingface;: Installed. No version info available.
langchain-mistralai;: Installed. No version info available.
langchain-ollama;: Installed. No version info available.
langchain-openai;: Installed. No version info available.
langchain-text-splitters<1.0.0,>=0.3.6: Installed. No version info available.
langchain-text-splitters>=0.3: Installed. No version info available.
langchain-together;: Installed. No version info available.
langchain-xai;: Installed. No version info available.
langchain>=0.3: Installed. No version info available.
langsmith-pyo3: Installed. No version info available.
langsmith<0.4,>=0.1.125: Installed. No version info available.
langsmith<0.4,>=0.1.17: Installed. No version info available.
numpy: 1.26.4
numpy<2,>=1.26.4;: Installed. No version info available.
numpy<3,>=1.26.2;: Installed. No version info available.
numpy>=1.26: Installed. No version info available.
openai<2.0.0,>=1.58.1: Installed. No version info available.
orjson: 3.10.15
packaging<25,>=23.2: Installed. No version info available.
pydantic: 2.9.2
pydantic-settings: 2.7.1
pydantic<3.0.0,>=2.5.2;: Installed. No version info available.
pydantic<3.0.0,>=2.7.4: Installed. No version info available.
pydantic<3.0.0,>=2.7.4;: Installed. No version info available.
pymongo>=4.6.1: Installed. No version info available.
PyYAML: 6.0.2
PyYAML>=5.3: Installed. No version info available.
requests: 2.32.3
requests-toolbelt: 1.0.0
requests<3,>=2: Installed. No version info available.
sentence-transformers: 3.4.1
SQLAlchemy: 2.0.37
SQLAlchemy<3,>=1.4: Installed. No version info available.
tenacity: 9.0.0
tenacity!=8.4.0,<10,>=8.1.0: Installed. No version info available.
tenacity!=8.4.0,<10.0.0,>=8.1.0: Installed. No version info available.
tiktoken<1,>=0.7: Installed. No version info available.
tokenizers: 0.21.0
transformers: 4.48.2
typing-extensions>=4.7: Installed. No version info available.
zstandard: Installed. No version info available.

@dosubot dosubot bot added the 🤖:bug Related to a bug, vulnerability, unexpected error with an existing feature label Mar 2, 2025
@YassinNouh21
Copy link

YassinNouh21 commented Mar 2, 2025

It is already mentioned here #29513 as an example
To assist with the issue on how to use the provided code in LangChain for reasoning output, you should follow these steps:

Use the invoke method to get the reasoning output.

messages = [
    {"role": "system", "content": "You are an assistant."},
    {"role": "user", "content": "Explain the reasoning behind this decision."}
]
response = llm.invoke(messages)
print(response.content)
print(response.additional_kwargs.get("reasoning", ""))

This setup will allow you to capture both the content and reasoning from DeepSeek's responses.

@laurafbec
Copy link
Author

Thanks @YassinNouh21! but it does not work for me with ChatOpenAI class. This is the code I'm using

`

from langchain_openai import ChatOpenAI
from dotenv import load_dotenv

import os
load_dotenv()

llm = ChatOpenAI(
    model = 'deepseek/deepseek-r1:nitro',
    base_url="https://openrouter.ai/api/v1",
    api_key=os.getenv("OPENROUTER_API_KEY"),
    extra_body={"include_reasoning": True}
)

messages = [
    {"role": "system", "content": "You are an assistant."},
    {"role": "user", "content": "9.11 and 9.8, which is greater? Explain the reasoning behind this decision."}
]
response = llm.invoke(messages)
print(response.content)
print(response.additional_kwargs.get("reasoning", ""))
print(response)

@andrasfe
Copy link

andrasfe commented Mar 5, 2025

the same code works fine for me:

`To determine whether 9.11 or 9.8 is greater, follow these steps:

  1. Align the decimal places:
    Write both numbers with the same number of decimal places:

    • ( 9.11 ) remains ( 9.11 ).
    • ( 9.8 ) becomes ( 9.80 ) (adding a trailing zero for clarity).
  2. Compare digit by digit (left to right):

    • Units place: Both have ( 9 ), so they are equal here.
    • Tenths place: Compare ( 1 ) (from ( 9.11 )) vs. ( 8 ) (from ( 9.80 )). Since ( 8 > 1 ), ( 9.80 ) is already larger at this stage.
    • Note: The hundredths place (( 1 ) vs. ( 0 )) is irrelevant once the tenths place determines the result.
  3. Conclusion:
    ( 9.8 ) (or ( 9.80 )) is greater than ( 9.11 ).

Final Answer:
( 9.8 ) is greater than ( 9.11 ). The key factor is the tenths place: ( 8 > 1 ), which outweighs any smaller digits in subsequent places.

content='To determine whether 9.11 or 9.8 is greater, follow these steps:\n\n1. Align the decimal places: \n Write both numbers with the same number of decimal places: \n - \( 9.11 \) remains \( 9.11 \). \n - \( 9.8 \) becomes \( 9.80 \) (adding a trailing zero for clarity).\n\n2. Compare digit by digit (left to right): \n - Units place: Both have \( 9 \), so they are equal here. \n - Tenths place: Compare \( 1 \) (from \( 9.11 \)) vs. \( 8 \) (from \( 9.80 \)). Since \( 8 > 1 \), \( 9.80 \) is already larger at this stage. \n - Note: The hundredths place (\( 1 \) vs. \( 0 \)) is irrelevant once the tenths place determines the result.\n\n3. Conclusion: \n \( 9.8 \) (or \( 9.80 \)) is greater than \( 9.11 \).\n\nFinal Answer: \n\( 9.8 \) is greater than \( 9.11 \). The key factor is the tenths place: \( 8 > 1 \), which outweighs any smaller digits in subsequent places.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 1067, 'prompt_tokens': 30, 'total_tokens': 1097, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'deepseek/deepseek-r1', 'system_fingerprint': 'fastcoe', 'finish_reason': 'stop', 'logprobs': None} id='run-d10b4520-d61b-4460-8f54-360c1fb92799-0' usage_metadata={'input_tokens': 30, 'output_tokens': 1067, 'total_tokens': 1097, 'input_token_details': {}, 'output_token_details': {}}`

@laurafbec
Copy link
Author

Thanks @andrasfe ! Yes, the code works, but I'm not able to access to the reasoning that should be something like this:

Okay, so I need to figure out what 1 plus 1 is. Hmm, let's start by recalling basic addition. I remember that when you add two numbers together, you're combining their values. So if I have one apple and someone gives me another apple, how many apples do I have in total? That should be two apples. 
Wait, but maybe I should double-check to make sure I'm not missing something. Let's use my fingers to count. Hold up one finger on my left hand and one finger on my right hand. Now, if I put them together, how many fingers are there? One, two. Yeah, that seems right. 
But what if there's a trick here? Sometimes problems seem simple but have a catch. Is this question straightforward, or is there a different context? Like, in binary, 1 + 1 equals 10, but the question doesn't specify a base. However, since it's a general question, I think it's safe to assume base 10. 
Another way to look at it is using the number line. Starting at 1, then moving one unit to the right. That would land me on 2. So that confirms it again. 
Maybe I can think of it in terms of sets. If I have a set with one element and another set with one element, and they're disjoint, the union of those sets has two elements. So that's another way to visualize it. 
I could also use basic arithmetic properties. The sum of 1 and 1 is defined as the next number after 1, which is 2. So 1 + 1 = 2. 
Wait, but I've heard some people joke that 1 + 1 can equal 11 if you concatenate the numbers. But in mathematics, addition is an operation that combines values, not concatenates digits. So unless specified otherwise, it's addition, not concatenation. 
Is there any other possible answer? In modular arithmetic, like mod 2, 1 + 1 would be 0, but again, the question doesn't mention any modulus. So sticking with standard arithmetic. 
Let me verify with a calculator. If I input 1 + 1, the result is 2. Yep, that's consistent. 
So all these methods point to the same answer. I think I'm confident now that 1 plus 1 equals 2.
```

`

@andrasfe
Copy link

andrasfe commented Mar 7, 2025

@laurafbec , you are right. I validated that the reasoning tokens are correctly returned by the openai module in response.choices[0].message.model_extra["reasoning"]. My huntch is that we should add them in response.model_extra. I will look into it later this week.

@laurafbec
Copy link
Author

Thanks a lot @andrasfe !

@JasonHonKL
Copy link

@andrasfe I think the problem is currently Langchain doesn't save the reasoning content when using Deeseek. Here's a capture output when I put out the LLMResult object inside the chat_models.py

generations=[[ChatGeneration(text='The translation of "I love programming." into German is:\n\n**"Ich liebe das Programmieren."**\n\nThis translation uses the nominalized verb "Programmieren" with the article "das" to accurately reflect the gerund form in English. Alternatively, if using the infinitive construction, it can also be:\n\n**"Ich liebe es, zu programmieren."**\n\nBoth are correct, but the first option is more direct for the given sentence.', generation_info={'finish_reason': 'stop', 'logprobs': None}, message=AIMessage(content='The translation of "I love programming." into German is:\n\n**"Ich liebe das Programmieren."**\n\nThis translation uses the nominalized verb "Programmieren" with the article "das" to accurately reflect the gerund form in English. Alternatively, if using the infinitive construction, it can also be:\n\n**"Ich liebe es, zu programmieren."**\n\nBoth are correct, but the first option is more direct for the given sentence.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 1229, 'prompt_tokens': 20, 'total_tokens': 1249, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 1134, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 20}, 'model_name': 'deepseek-reasoner', 'system_fingerprint': 'fp_5417b77867_prod0225', 'finish_reason': 'stop', 'logprobs': None}, id='run-69543cf6-8c13-4f78-8a36-d87024b90f74-0', usage_metadata={'input_tokens': 20, 'output_tokens': 1229, 'total_tokens': 1249, 'input_token_details': {'cache_read': 0}, 'output_token_details': {'reasoning': 1134}}))]] llm_output={'token_usage': {'completion_tokens': 1229, 'prompt_tokens': 20, 'total_tokens': 1249, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 1134, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 20}, 'model_name': 'deepseek-reasoner', 'system_fingerprint': 'fp_5417b77867_prod0225'} run=None type='LLMResult'

Noticing there is no reasoning content. Here's how Dee-seek api use Openai to get the reasoning content

messages = [{"role": "user", "content": "9.11 and 9.8, which is greater?"}]
response = client.chat.completions.create(
    model="deepseek-reasoner",
    messages=messages
)

reasoning_content = response.choices[0].message.reasoning_content
content = response.choices[0].message.content

I guess some API has to be update
@laurafbec For your reference I think using langchain Dee-seek is better than using langchain openai as the supporting services are sometime quite difference I face similar problem when develop text embedding with the langchain openai while using Dee-seek API. I will try to modify the code and push a pull request later this week when time allows.

Hope this helps you a bit.

@JasonHonKL
Copy link

@laurafbec I have tried to solve the issue. Please check if it can solve your case. Have a nice day.

@ccurme
Copy link
Collaborator

ccurme commented Mar 9, 2025

What is the motivation to use ChatOpenAI instead of ChatDeepSeek? ChatDeepSeek extends BaseChatOpenAI, its intent is to support Deepseek.

ChatOpenAI is intended to support the OpenAI API. It's not tenable to modify this class to support all usage of the openai SDK; it will become a mess. That's why we implement BaseChatOpenAI and extend it with specific providers.

@andrasfe
Copy link

andrasfe commented Mar 9, 2025

@JasonHonKL , I got the fix working but have not yer initiated a PR. It's a very simple enhancement (4 lines of code) to ChatBaseOpenAI to add the reasoning key to response.additional_kwargs if not already there.This is in line with @YassinNouh21 's suggestion. But I see how adding this to the community module is a better choice.

@YassinNouh21
Copy link

@JasonHonKL , I got the fix working but have not yer initiated a PR. It's a very simple enhancement (4 lines of code) to ChatBaseOpenAI to add the reasoning key to response.additional_kwargs if not already there.This is in line with @YassinNouh21 's suggestion. But I see how adding this to the community module is a better choice.

Glad it works with u can u mark it as solved

@laurafbec
Copy link
Author

Thanks @andrasfe and @YassinNouh21 !! shoudl I update langchain to test it?
@ccurme The motivation is to use Openrouter API or other providers as DeepSeek API is quite unreliable regarding latency.
Thanks again!

@JasonHonKL
Copy link

@laurafbec I guess they won't update it cause they intend you to use the Deepseek chat. You can check my pull request #30186 actually just modify a few lines of code see if it is useful for you.

@ccurme
Copy link
Collaborator

ccurme commented Mar 9, 2025

@laurafbec can you use Openrouter with ChatDeepSeek? You can set the base_url in api_base.

@andrasfe
Copy link

andrasfe commented Mar 9, 2025

This works for me, indeed. The key is not to use base_url.

llm = ChatDeepSeek( model = 'deepseek/deepseek-r1:nitro', api_base="https://openrouter.ai/api/v1", api_key=os.getenv("OPENROUTER_API_KEY"), )

@JasonHonKL
Copy link

@andrasfe Same it works for me.

@laurafbec
Copy link
Author

But I'm not able to print the reasoning...are you?

llm = ChatDeepSeek( model = 'deepseek/deepseek-r1:nitro', api_base="https://openrouter.ai/api/v1", api_key=os.getenv("OPENROUTER_API_KEY")) 
messages = [
    {"role": "system", "content": "You are an assistant."},
    {"role": "user", "content": "9.11 and 9.8, which is greater? Explain the reasoning behind this decision."}
]
response = llm.invoke(messages, extra_body={"include_reasoning": True})
print(response.content)
print(f"REASONING: {response.additional_kwargs.get('reasoning', '')}")
print(response)

@JasonHonKL
Copy link

@laurafbec I think you fill in wrong kwargs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤖:bug Related to a bug, vulnerability, unexpected error with an existing feature
Projects
None yet
Development

No branches or pull requests

5 participants