NeMo-Guardrails icon indicating copy to clipboard operation
NeMo-Guardrails copied to clipboard

feat(llm): add LangChain 1.x content blocks support for reasoning and tool calls

Open Pouyanpi opened this issue 4 weeks ago • 1 comments

Description

Added support for extracting reasoning traces and tool calls from LangChain 1.x content blocks format, with automatic fallback to the legacy format for backward compatibility.

The implementation:

  • extracts reasoning from content_blocks with type: "reasoning"
  • extracts tool calls from content_blocks with type: "tool_call"
  • falls back to additional_kwargs and tool_calls attribute for providers using the legacy format

references:

  • https://docs.langchain.com/oss/python/migrate/langchain-v1#standard-content
  • https://docs.langchain.com/oss/python/langchain/messages#standard-content-blocks

requires:

#1472

Pouyanpi avatar Nov 06 '25 14:11 Pouyanpi

Codecov Report

:white_check_mark: All modified and coverable lines are covered by tests.

:loudspeaker: Thoughts on this report? Let us know!

codecov[bot] avatar Nov 06 '25 14:11 codecov[bot]

Greptile Overview

Greptile Summary

This PR adds LangChain 1.x content_blocks support for extracting reasoning traces and tool calls, enabling compatibility with the new standard format while maintaining backward compatibility.

Key Changes:

  • Implements extraction from content_blocks with type="reasoning" and type="tool_call" (LangChain v1 standard)
  • Maintains fallback chain: content_blocks → additional_kwargs → legacy formats
  • Refactors extraction logic into separate functions for better modularity
  • Adds 20+ comprehensive tests covering all extraction methods and edge cases
  • Includes pytest fixture to properly reset context variables between tests

Implementation Quality:

  • Clean separation of concerns with dedicated extraction functions
  • Proper prioritization of extraction methods (v1 standard first, legacy fallback)
  • Comprehensive test coverage including MockResponse and real AIMessage tests
  • All edge cases handled: missing attributes, empty blocks, mixed content types

Confidence Score: 5/5

  • This PR is safe to merge with no identified risks
  • The implementation is clean, well-tested, and maintains full backward compatibility. The fallback chain ensures existing functionality continues to work while adding new LangChain v1 support. Test coverage is comprehensive with 20+ tests covering all code paths and edge cases. The previous review concern about KeyError was addressed through the developer discussion confirming the downstream interface guarantees.
  • No files require special attention

Important Files Changed

File Analysis

Filename Score Overview
nemoguardrails/actions/llm/utils.py 5/5 Adds LangChain v1 content_blocks extraction with clean fallback chain for reasoning and tool calls
tests/test_actions_llm_utils.py 5/5 Comprehensive test coverage with 20+ new tests covering all extraction methods and edge cases

Sequence Diagram

sequenceDiagram
    participant LLM as LLM Provider
    participant llm_call
    participant store_reasoning as _store_reasoning_traces
    participant store_tools as _store_tool_calls
    participant context as Context Variables

    LLM->>llm_call: Return response
    llm_call->>store_reasoning: Extract reasoning
    
    alt Has content_blocks
        store_reasoning->>store_reasoning: _extract_reasoning_from_content_blocks()
        store_reasoning->>store_reasoning: Check for type="reasoning"
        alt Found reasoning in content_blocks
            store_reasoning->>context: Set reasoning_trace_var
        else No reasoning in content_blocks
            store_reasoning->>store_reasoning: _extract_reasoning_from_additional_kwargs()
            alt Found in additional_kwargs
                store_reasoning->>context: Set reasoning_trace_var
            else Still no reasoning
                store_reasoning->>store_reasoning: _extract_and_remove_think_tags()
                alt Found <think> tags
                    store_reasoning->>context: Set reasoning_trace_var
                end
            end
        end
    end

    llm_call->>store_tools: Extract tool calls
    
    alt Has content_blocks
        store_tools->>store_tools: _extract_tool_calls_from_content_blocks()
        store_tools->>store_tools: Check for type="tool_call"
        alt Found tool calls in content_blocks
            store_tools->>context: Set tool_calls_var
        else No tool calls in content_blocks
            store_tools->>store_tools: _extract_tool_calls_from_attribute()
            alt Found tool_calls attribute
                store_tools->>context: Set tool_calls_var
            end
        end
    end

greptile-apps[bot] avatar Nov 24 '25 14:11 greptile-apps[bot]