LangChain 输出解析器与 LCEL 链构建详解
本文详细介绍 LangChain 框架中的核心组件:输出解析器(OutputParser)的使用,以及如何基于 LangChain 表达式语言(LCEL)构建高效的链(Chain)。通过掌握这些技术,开发者可以更灵活地控制大模型(LLM)的输出格式,并简化应用开发流程。
本文详细介绍了 LangChain 框架中的输出解析器(OutputParser)和 LangChain 表达式语言(LCEL)。内容涵盖为何需要输出解析器以实现结构化数据输出,如何使用内置解析器及自定义 Pydantic 模型解析器。重点阐述了 LCEL 的概念,通过 Runnable 接口和管道符 | 实现组件的高效组合,对比了传统调用方式与 LCEL 的差异。此外,还补充了 LCEL 的异步支持、流式输出、错误处理及性能优化等高级特性,旨在帮助开发者构建更稳健的大模型应用。

本文详细介绍 LangChain 框架中的核心组件:输出解析器(OutputParser)的使用,以及如何基于 LangChain 表达式语言(LCEL)构建高效的链(Chain)。通过掌握这些技术,开发者可以更灵活地控制大模型(LLM)的输出格式,并简化应用开发流程。
在常规使用 LangChain 构建 LLM 应用的流程中,通常遵循 Prompt 输入 -> 调用 LLM -> LLM 输出 的模式。然而,在实际业务场景中,我们往往期望 LLM 返回的数据是结构化的,以便后续程序进行精确处理(如存入数据库、触发 API 调用等)。
如果仅依赖自然语言回复,后续解析将变得困难且不稳定。此时,我们需要在 Prompt 中预设格式要求,并利用输出解析器将 LLM 的原始文本转换为预期的数据结构。输出解析器充当了 LLM 输出与应用程序之间的桥梁。
LangChain 提供了一些内置的解析器,例如 CommaSeparatedListOutputParser,用于将结果解析为逗号分隔的列表。
示例:获取城市景点列表
from langchain_openai import ChatOpenAI
from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.prompts import ChatPromptTemplate
# 定义提示模板
prompt = ChatPromptTemplate.from_messages([
("system", "{parser_instructions}"),
("human", "列出{cityName}的{viewPointNum}个著名景点。")
])
# 初始化解析器
output_parser = CommaSeparatedListOutputParser()
parser_instructions = output_parser.get_format_instructions()
print("解析器指令:", parser_instructions)
# 生成最终 Prompt
final_prompt = prompt.invoke({
"cityName": "南京",
"viewPointNum": 3,
"parser_instructions": parser_instructions
})
# 调用模型
model = ChatOpenAI(
model="gpt-3.5-turbo",
openai_api_key="YOUR_API_KEY",
openai_api_base="https://api.openai.com/v1"
)
response = model.invoke(final_prompt)
print("模型原始输出:", response.content)
# 解析结果
ret = output_parser.invoke(response)
print("解析后结果:", ret)
对于更复杂的结构化数据需求,可以使用 Pydantic 模型配合 PydanticOutputParser 来定义自定义格式。
步骤:
pydantic.BaseModel。PydanticOutputParser 实例化解析器。示例:提取书籍信息
from typing import List
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import ChatPromptTemplate
from langchain.schema import HumanMessage
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI
# 1. 定义数据结构
class BookInfo(BaseModel):
book_name: str = Field(description="书籍的名字")
author_name: str = Field(description="书籍的作者")
genres: List[str] = Field(description="书籍的体裁")
# 2. 初始化解析器
output_parser = PydanticOutputParser(pydantic_object=BookInfo)
print("格式指令:", output_parser.get_format_instructions())
# 3. 构建 Prompt
prompt = ChatPromptTemplate.from_messages([
("system", "{parser_instructions} 你输出的结果请使用中文。"),
("human", "请你帮我从书籍的概述中,提取书名、作者,以及书籍的体裁。书籍概述会被三个#符号包围。\n###{book_introduction}###")
])
book_introduction = """
《朝花夕拾》原名《旧事重提》,是现代文学家鲁迅的散文集,收录鲁迅于 1926 年创作的 10 篇回忆性散文。
此文集作为'回忆的记事',多侧面地反映了作者鲁迅青少年时期的生活。
"""
# 4. 执行链
model = ChatOpenAI(model="gpt-3.5-turbo", openai_api_key="YOUR_API_KEY")
final_prompt = prompt.invoke({
"book_introduction": book_introduction,
"parser_instructions": output_parser.get_format_instructions()
})
response = model.invoke(final_prompt)
result = output_parser.invoke(response)
print(result)
# 输出类型为 BookInfo 对象
LCEL(LangChain Expression Language)是 LangChain 表达式语言的简称。它提供了一种声明式的方式来组合各种组件,使得构建复杂的应用逻辑更加直观和高效。
在 LangChain 中,只要实现了 Runnable 接口并且拥有 invoke 方法的对象,都可以被视为一个可运行的单元(Runnable)。这意味着它们可以接收上一个单元的输出作为自己的输入,从而形成链条。
常见的组件如 ChatPromptTemplate、ChatOpenAI、PydanticOutputParser 等都实现了 Runnable 接口。
LCEL 提供了管道符 | 来连接这些组件,这种方式不仅书写简洁,而且支持异步(Async)、流式(Streaming)等多种执行模式。
在传统模式下,代码需要显式地调用每个组件的 invoke 方法,变量传递繁琐,难以维护。
# 传统写法
final_prompt = prompt.invoke({"book_introduction": book_introduction, "parser_instructions": output_parser.get_format_instructions()})
response = model.invoke(final_prompt)
result = output_parser.invoke(response)
使用 LCEL 可以将多个步骤串联成一个 Chain 对象,代码可读性大幅提升。
# LCEL 写法
chain = prompt | model | output_parser
ret = chain.invoke({
"book_introduction": book_introduction,
"parser_instructions": output_parser.get_format_instructions()
})
LCEL 原生支持异步操作,适合高并发场景。
import asyncio
async def main():
# 使用 ainvoke 替代 invoke
result = await chain.ainvoke({
"book_introduction": book_introduction,
"parser_instructions": output_parser.get_format_instructions()
})
print(result)
asyncio.run(main())
对于长文本生成,流式输出能显著提升用户体验。
for chunk in chain.stream({
"book_introduction": book_introduction,
"parser_instructions": output_parser.get_format_instructions()
}):
print(chunk, end="", flush=True)
在使用 LCEL 时,建议捕获可能出现的异常,特别是当 LLM 未能按照预期格式输出时。可以通过添加 try-except 块或使用 RetryOutputParser 来处理解析失败的情况。
batch 或 astream_events 方法。trace 工具追踪链的执行路径。本文详细讲解了 LangChain 的输出解析器原理及使用方法,包括内置解析器和基于 Pydantic 的自定义解析器。同时,深入介绍了 LCEL 表达式语言如何简化链的构建过程,并展示了其异步和流式能力。掌握这些核心技术,能够帮助开发者更高效地构建稳定、可控的大模型应用。
在实际项目中,建议根据具体需求选择合适的解析器类型,并充分利用 LCEL 的组合能力来管理复杂的业务逻辑。随着 LangChain 生态的不断发展,新的组件和模式会不断涌现,保持对文档的关注和学习是持续进步的关键。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online