Zurück zur Startseite

Wie speichert man Reasoning-Inhalt in LangChain für CoT-Modelle

Der Artikel erklärt, warum LangChain Reasoning-Inhalt in CoT-Modellen ignoriert, und bietet einen funktionierenden Patch, um diesen Block in additional_kwargs zu speichern. Geeignet für Entwickler, die Anbieter wie polza.ai oder StepFun über OpenAI-kompatible API nutzen.

Verlieren Sie Reasoning-Inhalt in LangChain? So beheben Sie es
Advertisement 728x90

# Reasoning-Inhalte in LangChain speichern: Patch für CoT-Modelle

Beim Arbeiten mit CoT-Modellen über LangChain stoßen Entwickler auf den Verlust des Reasoning-Inhalts – des zentralen Blocks des Denkvorgangs, den das Modell vor der finalen Antwort erzeugt. Das ist kein Bug, sondern eine Folge einer architektonischen Entscheidung: Klassen wie ChatOpenAI halten sich strikt an die offizielle OpenAI API und ignorieren nicht-standardisierte Felder wie reasoning, reasoning_content oder reasoning_details. Das Ergebnis sind langsamere Reaktionszeiten und eine schlechtere UX, da Nutzer die Zwischenschritte des Denkens der KI nicht sehen. Hier ist, wie man das auf Code-Ebene behebt, ohne auf ein offizielles Update zu warten.

Warum LangChain Reasoning-Inhalte ignoriert

LangChain positioniert sich als universelles Framework, das mit einer breiten Palette von LLM-Anbietern kompatibel ist. Um Fragmentierung zu vermeiden, implementieren seine Kernklassen (wie ChatOpenAI) nur die offizielle OpenAI Chat Completion API-Spezifikation. Felder wie reasoning_content, reasoning und Ähnliche sind Erweiterungen, die von DeepSeek, xAI, vLLM und anderen eingeführt wurden. Jeder Anbieter verwendet eigene Namen und Formate, was Chaos erzeugt:

  • DeepSeek → reasoning_content
  • vLLM → switched from reasoning_content to reasoning
  • xAI / OpenRouter → may use reasoning_details

Die Unterstützung aller Varianten in ChatOpenAI würde erfordern:

Google AdInline article slot
  • Ständige Überwachung von API-Änderungen bei Drittanbietern.
  • Pflege einer wachsenden Liste von Feldzuordnungen.
  • ChatOpenAI in einen universellen Adapter zu verwandeln – was seinem Zweck widerspricht.

Deshalb empfehlen die LangChain-Entwickler, spezialisierte Klassen wie ChatDeepSeek zu verwenden. Aber die meisten Anbieter (einschließlich polza.ai, StepFun und anderer) bieten immer noch APIs im OpenAI-Format an – und genau da besteht das Problem.

Wie man den Patch in base.py anwendet

Die Lösung besteht darin, zwei Funktionen im Quellcode von LangChain zu modifizieren: _convert_dict_to_message und _convert_delta_to_message_chunk. Diese kümmern sich um die Umwandlung roher LLM-Antworten in Message-Objekte, die im Framework verwendet werden. Man muss die Extraktion des reasoning-Felds hinzufügen und es in additional_kwargs speichern.

Hier der minimale Patch:

Google AdInline article slot
def _convert_dict_to_message(_dict):
    ...
    content = _dict.get("content", "") or ""
    reasoning = _dict.get("reasoning", "") or ""  # added
    additional_kwargs: dict = {}
    if reasoning:  # added
        additional_kwargs['reasoning_content'] = reasoning  # added
    if function_call := _dict.get("function_call"):
        additional_kwargs["function_call"] = dict(function_call)
    tool_calls = []
    ...

Ähnlich für den Streaming-Modus:

def _convert_delta_to_message_chunk(_dict):
    ...
    id_ = _dict.get("id")
    role = cast(str, _dict.get("role"))
    content = cast(str, _dict.get("content") or "")
    reasoning = cast(str, _dict.get("reasoning", "") or "")  # added
    additional_kwargs: dict = {}
    if reasoning:  # added
        additional_kwargs['reasoning_content'] = reasoning  # added
    ...

Dieser Patch:

  • Bricht die bestehende Architektur nicht.
  • Erhält die Kompatibilität mit der offiziellen API.
  • Fügt Unterstützung für reasoning_content von jedem Anbieter hinzu, der ein reasoning-Feld zurückgibt.

Beispielnutzung mit Streaming-Output

Nach Anwendung des Patches ist der Reasoning-Inhalt in additional_kwargs für jeden Chunk verfügbar. Hier ist, wie man den Output einrichtet:

Google AdInline article slot
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model="stepfun/step-3.5-flash",
    openai_api_base="https://api.polza.ai/v1",
    openai_api_key="your_api_key",
)

for chunk in model.stream('Hello!'):
    if "reasoning_content" in chunk.additional_kwargs:
        print(chunk.additional_kwargs['reasoning_content'], end="", flush=True)
    else:
        print(chunk.content, end="", flush=True)

Jetzt können Nutzer den Denkvorgang des Modells in Echtzeit sehen – das ist besonders wertvoll in CoT-Apps, wo Zwischenschritte wie Datenanalyse, Hypothesenvergleich und Logikprüfungen entscheidend sind.

Alternative Ansätze und Einschränkungen

Der Patch ist zwar effektiv, hat aber Einschränkungen:

  • Lokale Modifikation: Änderungen wirken nur auf Ihre Kopie von LangChain. Sie gehen bei Paket-Updates verloren.
  • Inkompatibilität der Feldnamen: Wenn ein Anbieter reasoning_details statt reasoning verwendet, müssen Sie den Code anpassen.
  • Fehlende Standardisierung: Ohne einheitliche Absprache unter den Anbietern ist für jeden Fall manuelle Anpassung nötig.

Saubere Alternativen:

  • Eigener MessageConverter – erstellen Sie eine eigene Klasse, die von BaseMessageConverter erbt, und überschreiben Sie die Parsing-Logik.
  • Middleware-Schicht – abfangen Sie HTTP-Antworten vom Anbieter, bevor sie LangChain erreichen, und normalisieren Sie die Felder.
  • LangChain Expression Language (LCEL) – umschließen Sie den Model-Aufruf mit einem RunnableLambda, das den Reasoning-Inhalt extrahiert, bevor er an die Kette weitergeleitet wird.

Diese Methoden sind jedoch komplexer und erfordern ein tiefes Verständnis der Framework-Interna. Für ein MVP oder eine schnelle Lösung ist das Patchen von base.py die optimale Option.

Wichtige Erkenntnisse

  • Reasoning-Inhalte gehen nicht durch einen Bug verloren, sondern weil LangChain der OpenAI API strikt folgt.
  • Der Patch fügt Unterstützung für das reasoning-Feld in additional_kwargs hinzu, ohne die Abwärtskompatibilität zu brechen.
  • Er funktioniert für normale und Streaming-Aufrufe.
  • Er muss nach jedem LangChain-Update manuell erneut angewendet werden.
  • Er verbessert die UX in CoT-Apps, indem der Denkvorgang des Modells für Nutzer transparent wird.

— Editorial Team

Advertisement 728x90

Weiterlesen