【LangChain指南】输出解析器(Output parsers)
今天我们来深入讲解 LangChain 框架中一个非常核心且实用的组件——Output Parsers(输出解析器)。
大家都知道,大型语言模型(LLM)的原始输出是自由格式的文本。但在实际的项目开发中,我们往往需要将这些文本转换为结构化的数据(如 Python 对象、字典、列表)或进行特定的格式处理,以便后续的程序逻辑能够方便地使用。Output Parsers 就是专门用来解决这个问题的工具。
简单来说,Output Parser 就是一个“翻译官”和“质检员”。它告诉模型:“请按照这个格式回答我”,然后在模型回答后,它负责把模型的自然语言回复“翻译”成我们需要的、干净的、结构化的数据。
一、Output Parser 的核心接口
在深入具体类型之前,我们必须理解所有 Output Parser 都遵循的基本契约。一个标准的 Output Parser 通常需要实现以下方法:
get_format_instructions()
: 这个方法会返回一段字符串,里面包含了给 LLM 的、非常具体的格式化指令。我们会把这个指令注入到提示词(Prompt)中,引导模型生成符合要求的输出。parse(text: str) -> Any
: 这是核心方法。它接收 LLM 生成的原始字符串,尝试将其解析成目标结构(如 Pydantic 模型、字典、布尔值等)。如果解析失败,通常会抛出OutputParserException
异常。parse_with_prompt(text: str, prompt: PromptValue) -> Any
(可选): 当parse
方法失败时,有些高级的解析器(如RetryOutputParser
)会用到这个方法。它会把原始的提示词也传进来,以便 LLM 能根据上下文更好地修正错误。
此外,所有的 Output Parser 都是 Runnable 对象,这意味着它们可以无缝地集成到 LangChain Expression Language (LCEL) 的链式调用中,使用 |
操作符进行组合,并天然支持 invoke
, stream
, batch
等异步和流式操作。
二、常用内置 Output Parser 详解
接下来,我们逐一讲解官方文档中提到的几种常用解析器,并配上代码示例。
1. StrOutputParser
: 最基础的文本提取器
适用场景: 当你只需要从 LLM 的回复中提取纯文本时,尤其是在使用支持工具调用(Tool Calling)的聊天模型时。因为工具调用的返回结果是一个复杂的列表,StrOutputParser
能自动帮你提取出其中的文本部分。
代码示例:
from langchain_core.output_parsers import StrOutputParser
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool# 定义一个工具
@tool
def get_weather(location: str) -> str:"""Get the weather from a location."""return "Sunny in " + location# 创建一个绑定了工具的模型
llm = ChatAnthropic(model="claude-3-5-sonnet-20240620")
llm_with_tools = llm.bind_tools([get_weather])# 直接调用模型,返回的是包含工具调用信息的复杂结构
raw_response = llm_with_tools.invoke("What's the weather like in New York?")
print("Raw Response Type:", type(raw_response.content))
print("Raw Response Content:", raw_response.content)
# 输出可能是: [{'type': 'text', 'text': 'I will check...'}, {'type': 'tool_use', 'id': '...', 'name': 'get_weather', ...}]# 使用 StrOutputParser 提取纯文本
chain = llm_with_tools | StrOutputParser()
clean_text = chain.invoke("What's the weather like in New York?")
print("\nClean Text:", clean_text)
# 输出: "I will check the weather for New York right away."# 它也完美支持流式传输
print("\nStreaming Output:")
for chunk in chain.stream("What's the weather like in New York?"):print(chunk, end="", flush=True)
2. PydanticOutputParser
: 结构化数据的王者
适用场景: 这是最强大、最常用的解析器。当你需要将 LLM 的输出解析为一个具有明确字段和数据类型的 Python 对象时,PydanticOutputParser
是首选。它利用 Pydantic 库的强大功能,不仅能解析,还能进行数据验证。
代码示例:
from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI # 注意:这里使用ChatOpenAI更常见
from pydantic import BaseModel, Field, model_validator# 1. 定义你想要的数据结构
class Joke(BaseModel):setup: str = Field(description="The setup of the joke, must be a question.")punchline: str = Field(description="The punchline of the joke.")# 可选:添加自定义验证器@model_validator(mode="before")@classmethoddef validate_setup_ends_with_question_mark(cls, values):setup = values.get("setup", "")if setup and not setup.strip().endswith("?"):raise ValueError("The setup must end with a question mark.")return values# 2. 创建解析器
parser