在使用 LangChain 构建复杂的大模型应用时,经常需要将多个组件串联起来,形成一条“链”。然而,会遇到一个棘手的问题:数据类型的兼容性
大模型(LLM)的直接输出通常是封装好的对象(如 LangChain 中的 AIMessage),而链的下一个环节——无论是下一个模型还是提示词模板——往往需要字符串或字典作为输入。为了解决这种“接口不匹配”的问题,LangChain 引入了 Output Parser(输出解析器)
本文将深入探讨三种常用的数据处理方式:StrOutputParserJsonOutputParser 以及自定义函数。

1. StrOutputParser:打破 AIMessage 的壁垒

1.1 背景与原理

在 LangChain 的架构中,当你调用一个聊天模型(如 ChatTongyi 或 ChatOpenAI)时,它的原生返回值并不是简单的字符串,而是一个 AIMessage 对象。这个对象包含了内容、元数据、token 使用情况等丰富信息。
然而,在链式调用中,如果你希望将上一个模型的回复直接传给下一个模型,或者作为中间结果处理,直接传递 AIMessage 对象往往会导致类型错误或不符合下游接口的预期。StrOutputParser 的作用非常纯粹:它将 AIMessage 对象“解包”,提取其中的 content 字段,将其转换为标准的 Python 字符串。

1.2 代码

下面的代码展示了如何使用 StrOutputParser 将模型的输出转换为字符串,从而实现模型到模型的无缝传递。

# 解析器示例,指定输出为字符串
from langchain_core.output_parsers import StrOutputParser
from langchain_community.chat_models.tongyi import ChatTongyi
from langchain_core.prompts import PromptTemplate
parser = StrOutputParser() # 解析器,指定输出为字符串
model = ChatTongyi(model="qwen3-max-preview")
prompt = PromptTemplate.from_template(
    "我邻居姓:{lastname},刚生了{gender},请起名,仅告知我名字无需其它内容。"
)
chain = prompt | model | parser | model
res = chain.invoke({"lastname": "张", "gender": "男"})
print(res.content)

1.3 代码详解

  • parser = StrOutputParser(): 实例化一个字符串解析器。
  • chain = prompt | model | parser | model: 这是 LangChain 的 LCEL(LangChain Expression Language)语法。
    1. prompt 接收输入参数,生成提示词。
    2. model 接收提示词,生成 AIMessage
    3. 关键点 parser:接收 AIMessage,将其转换为纯字符串。
    4. 最后一个 model:接收上一个环节的字符串,将其视为用户输入进行再次处理。
  • 结果输出:由于链的最后一个是 model,所以 res 依然是一个 AIMessage 对象,我们需要通过 res.content 获取最终的字符串内容。

2. JsonOutputParser:结构化数据的高效传递

2.1 为什么需要 JSON 解析?

在实际业务开发中,我们往往希望模型的输出是结构化的数据(如 JSON),以便后续程序进行解析和存储。JsonOutputParser 能够将模型输出的 JSON 格式字符串自动转换为 Python 字典,这使得我们可以直接将模型输出作为下一个 Prompt 模板的变量输入。

2.2 代码

这个例子演示了如何让模型输出 JSON,解析后传递给下一个 Prompt 进行名字解析。

# 将AIMessage转为字典,给模板使用
from langchain_community.chat_models import ChatTongyi
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.prompts import PromptTemplate
# 实例化parser
str_parser = StrOutputParser()
json_parser = JsonOutputParser()
model = ChatTongyi(model="qwen3-max-preview")
# 修改提示词,明确要求使用双引号
first_prompt = PromptTemplate.from_template(
    "邻居姓{lastname},生了{gender},请起名,并封装json格式返回给我"
    "我的要求key是name,value是名字,必须使用标准JSON格式,所有字符串都用双引号,json格式如下:{{\"name\": \"xxx\"}}"
)
second_prompt = PromptTemplate.from_template(
    "姓名{name},请帮我解析含义"
)
chain = first_prompt | model | json_parser | second_prompt | model | str_parser
res: str = chain.invoke({"lastname": "张", "gender": "女儿"})
print(res)

2.3 代码详解

  • Prompt 设计:为了让大模型准确输出 JSON,我们在 first_prompt 中显式规定了格式,并给出了示例。注意 {{\"name\": \"xxx\"}} 中的双层大括号 {{}} 是 LangChain 模板中的转义写法,代表字面量 {}
  • 数据流转
    1. first_prompt -> model:模型生成类似 {"name": "张三"}AIMessage
    2. 关键点 json_parser:将 AIMessage 中的内容解析为 Python 字典 {'name': '张三'}
    3. second_prompt:接收字典作为输入。由于字典中包含键 name,正好匹配模板中的 {name} 占位符,LangChain 会自动完成变量填充。
    4. 最后的 str_parser 将第二个模型的最终回复转换为字符串,方便打印。

3. 自定义函数:灵活处理复杂数据

3.1 突破标准解析器的限制

虽然 StrOutputParserJsonOutputParser 覆盖了大部分场景,但有时我们需要对模型输出进行特殊的中间处理。例如,提取特定的属性、进行数据清洗,或者将 AIMessage 转换为特定的字典结构。
LangChain 提供了 RunnableLambda,允许我们将任意的 Python 函数封装成 Runnable 组件,从而插入到链中。这赋予了开发者极高的自由度。

3.2 代码

下面的代码使用了自定义函数,手动提取 AIMessage 的内容并封装成字典,实现了与 JsonOutputParser 类似但更灵活的效果。

from langchain_community.chat_models import ChatTongyi
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnableLambda
str_parser = StrOutputParser()
my_func = RunnableLambda(lambda ai_msg: {"name": ai_msg.content})  # 自定义函数
model = ChatTongyi(model="qwen3-max-preview")
first_prompt = PromptTemplate.from_template(
    "邻居姓{lastname},生了{gender},请起名,只告诉最终名字即可"
)
second_prompt = PromptTemplate.from_template(
    "姓名{name},请帮我解析含义"
)
chain = first_prompt | model | my_func | second_prompt | model | str_parser
res: str = chain.invoke({"lastname": "张", "gender": "女儿"})
print(res)

3.3 代码详解

  • RunnableLambda:这是核心组件。它接收一个 lambda 函数。
  • lambda ai_msg: {"name": ai_msg.content}
    • 输入:上游 model 传递过来的 AIMessage 对象。
    • 处理:从对象中取出 .content(即名字字符串)。
    • 输出:构造了一个字典 {"name": "名字"}
  • 链的衔接:自定义函数输出的字典,完美匹配了下游 second_prompt 中的 {name} 占位符需求。这种方式让我们可以在数据流转过程中插入任意的业务逻辑,非常强大。

总结

在 LangChain 的链式调用中,输出解析器扮演着“数据适配器”的角色:

  • StrOutputParser:用于将复杂对象“降维”为字符串,常用于模型间的简单对话传递。
  • JsonOutputParser:用于结构化数据提取,实现“模型输出 -> 字典 -> 下一个Prompt”的自动化流转。
  • 自定义函数:提供了良好的灵活性,能更灵活的处理中间数据。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐