如何激活Langchain LCEL链的中间步骤输出实现调试?

来源:站长工具作者:广州网站建设头衔:草根站长
导读:本期聚焦于小伙伴创作的《如何激活Langchain LCEL链的中间步骤输出实现调试?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何激活Langchain LCEL链的中间步骤输出实现调试?》有用,将其分享出去将是对创作者最好的鼓励。

Langchain的LCEL(LangChain Expression Language)提供了简洁的链式语法,让开发者可以快速组合提示模板、模型、输出解析器等组件构建处理流程,但在实际开发过程中,我们常常需要查看链中每个中间步骤的处理结果来排查问题,默认情况下LCEL链不会输出中间步骤的内容,需要手动配置激活相关功能。

如何激活Langchain LCEL链的中间步骤输出实现调试?

LCEL链的基本运行逻辑

LCEL链通过管道操作符|将不同的可运行组件串联起来,上一个组件的输出会作为下一个组件的输入,整个链作为一个整体接收输入并返回最终结果。比如下面这个简单的LCEL链示例,实现了输入问题后先调用提示模板生成提示,再调用大模型生成回答,最后解析输出:

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

# 构建提示模板
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个 helpful 的助手"),
    ("user", "{question}")
])
# 初始化大模型
model = ChatOpenAI(model="gpt-3.5-turbo")
# 初始化输出解析器
parser = StrOutputParser()
# 构建LCEL链
chain = prompt | model | parser

# 运行链
result = chain.invoke({"question": "什么是LCEL"})
print(result)

这个链运行后只会返回最终的解析结果,我们无法看到prompt生成的提示内容,也无法看到model返回的原始响应,调试时很难定位问题出在哪个环节。

激活中间步骤输出的方法

方法一:使用with_config配置回调

LCEL链支持通过with_config方法配置回调参数,我们可以自定义回调类来捕获每个组件的运行输入和输出,从而实现中间步骤的输出。首先需要定义一个继承自BaseCallbackHandler的回调类,重写对应的方法记录中间数据:

from langchain_core.callbacks import BaseCallbackHandler

class StepOutputHandler(BaseCallbackHandler):
    def on_chain_start(self, serialized, inputs, **kwargs):
        # 链开始运行时触发,记录输入
        print(f"链开始运行,输入参数:{inputs}")

    def on_chain_end(self, outputs, **kwargs):
        # 链结束运行时触发,记录输出
        print(f"链结束运行,输出结果:{outputs}")

    def on_llm_start(self, serialized, prompts, **kwargs):
        # 大模型开始运行时触发,记录提示内容
        print(f"大模型开始运行,提示内容:{prompts}")

    def on_llm_end(self, response, **kwargs):
        # 大模型结束运行时触发,记录原始响应
        print(f"大模型结束运行,原始响应:{response}")

    def on_prompt_end(self, formatted_prompt, **kwargs):
        # 提示模板生成结束触发,记录生成的提示
        print(f"提示模板生成结束,格式化提示:{formatted_prompt}")

然后将这个回调处理器配置到链中,运行链时就会自动输出每个中间步骤的内容:

# 初始化回调处理器
handler = StepOutputHandler()
# 为链配置回调
chain_with_callback = chain.with_config({"callbacks": [handler]})

# 运行带回调的链
chain_with_callback.invoke({"question": "什么是LCEL"})

运行后可以看到每个环节的输入输出信息,方便我们排查每个组件的运行是否符合预期。

方法二:使用RunnablePassthrough传递中间结果

如果我们不需要全局的回调配置,只是临时需要查看某个步骤的输出,可以使用RunnablePassthrough组件将中间结果传递到后续步骤,同时保留原始输入。比如我们需要查看提示模板生成的提示内容,可以这样修改链:

from langchain_core.runnables import RunnablePassthrough

# 构建新的链,在提示模板之后插入RunnablePassthrough
# assign方法可以将中间结果赋值到字典的新键中,同时保留原始输入
chain_with_step = (
    prompt 
    | RunnablePassthrough.assign(middle_output=lambda x: print(f"提示模板输出:{x}") or x) 
    | model 
    | parser
)

# 运行链
chain_with_step.invoke({"question": "什么是LCEL"})

这种方式适合临时调试单个环节的输出,不需要额外定义回调类,使用起来更加灵活,但是如果需要查看多个环节的输出,就需要多次插入RunnablePassthrough,代码会相对繁琐。

两种方法的适用场景对比

我们可以通过下面的表格对比两种方法的适用场景,根据实际需求选择合适的方式:

对比维度回调配置方法RunnablePassthrough方法
适用场景需要全局查看所有中间步骤输出,长期调试使用临时查看单个或少数几个步骤输出,快速验证使用
代码复杂度需要定义回调类,初始配置稍复杂不需要额外定义类,直接修改链结构即可
灵活性可以捕获所有组件的运行事件,信息更全面只能查看插入位置的步骤输出,范围有限

调试注意事项

在激活中间步骤输出调试时,需要注意以下几点:

  • 回调配置方法中的回调类方法会在链运行的每个对应事件触发时执行,如果链运行频率很高,可能会影响运行性能,调试完成后建议移除回调配置。
  • 使用RunnablePassthrough时,assign方法中的lambda表达式如果包含打印逻辑,要确保打印操作不影响原始数据的传递,比如示例中用or x保证打印后返回原始输入。
  • 如果链中包含了自定义的可运行组件,回调类需要重写对应的自定义事件方法才能捕获中间输出,具体可以参考Langchain官方回调文档的自定义组件部分。

通过上述两种方法,我们可以轻松激活LCEL链的中间步骤输出,快速定位链运行过程中的问题,提升LCEL相关功能的开发效率。

LangchainLCEL链调试中间步骤输出修改时间:2026-07-11 16:54:35

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。