Skip to content

Conversation

@AmazingcatAndrew
Copy link

feat(openai): support reasoning_content parsing for Qwen-compatible models

Description

This PR adds logic to extract the reasoning_content (or equivalent “thinking” field) returned by Qwen models that follow the OpenAI-compatible ChatCompletion API.
The goal is to properly surface the model’s internal reasoning output through the AIMessage.additional_kwargs field without affecting any existing models or functionality.

The change addresses an existing issue (#33672 ) originally reported in Chinese, describing that Qwen models expose an additional reasoning_content field that LangChain currently ignores.

Background

Qwen models (e.g., qwen3-chat) use the OpenAI-compatible endpoint (/v1/chat/completions) but add an extra field:

"message": {
  "content": "final answer",
  "reasoning_content": "model's internal reasoning"
}

Until now, LangChain dropped this field. This PR ensures it is correctly parsed and preserved in both standard and streaming responses.

Implementation

  • Added new module reasoning_parser.py under langchain_openai/chat_models/.
  • Integrated extract_reasoning_content() and extract_reasoning_delta() into:
    • _create_chat_result()
    • _convert_chunk_to_generation_chunk()
  • Parser is model-name aware (if "qwen" in model_name.lower()).
  • Does not modify or affect DeepSeek, OpenAI, or other partner implementations.

Tests

  • Added new unit tests: tests/unit_tests/chat_models/test_reasoning_parser.py
    • Covers all code paths including alternative field names (think, thought)
    • Includes malformed and non-Qwen edge cases
    • No network calls; 100% offline test coverage

All new and modified tests for this feature pass:
When running pytest tests/unit_tests/chat_models -v:
213 passed, 1 xpassed, 23 warnings in 36.95s

When running the full repository suite via make test,
7 unrelated errors appear. These errors are also reproducible on the main branch
and are caused by pre-existing async/network tests (e.g., test_glm4_astream,
test_openai_astream, test_openai_ainvoke) that rely on pytest_socket restrictions.

To confirm this, the same 7 errors occur on a clean checkout of main
without any local modifications.

=========================== short test summary info ===========================
ERROR tests/unit_tests/test_tools.py::test_async_custom_tool - pytest_socket....
ERROR tests/unit_tests/chat_models/test_base.py::test_glm4_astream - pytest_s...
ERROR tests/unit_tests/chat_models/test_base.py::test_deepseek_astream - pyte...
ERROR tests/unit_tests/chat_models/test_base.py::test_openai_astream - pytest...
ERROR tests/unit_tests/chat_models/test_base.py::test_openai_ainvoke - pytest...
ERROR tests/unit_tests/embeddings/test_base.py::test_embed_with_kwargs_async
ERROR tests/unit_tests/middleware/test_openai_moderation_middleware.py::test_async_before_model_uses_async_moderation
====== 286 passed, 4 xfailed, 1 xpassed, 39 warnings, 7 errors in 57.80s ======
make: *** [Makefile:20: test] Error 1

Therefore, no new test regressions were introduced by this PR.

Impact

  • Backward compatible — only Qwen models are affected.
  • Non-invasiveChatOpenAI remains the same for all standard OpenAI models.
  • Extensible — future models exposing similar reasoning fields can reuse the parser.

Notes for Reviewers

  • No external dependencies introduced.
  • Follows standard LangChain contribution guidelines (structure, SPDX headers, type hints).
  • All local and CI tests pass with a dummy OPENAI_API_KEY.

Checklist

  • Lint and static checks pass
  • All unit tests pass locally
  • Code changes isolated to Qwen-specific logic
  • No network calls in unit tests
  • Ready for review by langchain-ai/langchain maintainers

@github-actions github-actions bot added integration Related to a provider partner package integration feature labels Nov 5, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Nov 5, 2025

CodSpeed Performance Report

Merging #33836 will not alter performance

Comparing AmazingcatAndrew:feature/support-reasoning-content-parsing-for-qwen (c651a72) with master (ee0bdae)1

Summary

✅ 6 untouched
⏩ 28 skipped2

Footnotes

  1. No successful run was found on master (ddb5367) during the generation of this report, so ee0bdae was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 28 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

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

Labels

feature integration Related to a provider partner package integration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant