6.输出解析器

输出解析器

一、什么是输出解析器 OutputParser

1. 核心作用

大模型原生返回是统一的 AIMessage 对象,里面只有一段自由文本 content
实际开发中需要结构化、可直接业务使用的数据(字符串、字典、强类型对象),输出解析器就是专门做「模型输出格式化转换」的工具。
两大核心方法:

  1. invoke(result):接收模型返回对象,转换成目标格式;
  2. get_format_instructions():生成标准化格式提示词,告诉大模型必须按照指定结构输出。

2. 主流分类(文档全部示例覆盖)

  1. StrOutputParser:最简单,只提取纯文本字符串;
  2. JsonOutputParser:输出标准字典dict,支持简单自定义JSON结构;
  3. PydanticOutputParser:强校验结构化输出,基于Pydantic BaseModel,支持字段长度、数值范围等校验;
  4. with_structured_output(TypedDict):LangChain新版快捷结构化输出,基于Python原生TypedDict,轻量无运行时校验。

3. 两个关键类型区分(TypedDict / Pydantic BaseModel)

  • TypedDict + Annotated:仅静态类型提示,运行时不会自动校验数据合法性,仅用于IDE提示、给大模型看字段说明;
  • Pydantic BaseModel + Field运行时强制校验,数值范围、字符串长度、类型错误都会直接抛异常,适合严谨业务场景。

二、解析器代码

1. StrOutputParser 纯字符串解析器(StrOutputParserDemo.py)

核心特点

LangChain最简单解析器,逻辑只有一步:提取模型返回 AIMessage.content 转为普通字符串,无任何结构化处理。

完整代码流程拆解

# 1. 导入依赖
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
import os
from langchain.chat_models import init_chat_model
from loguru import logger

# 2. 构建提示模板,支持变量插值
chat_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一个{role},请简短回答我提出的问题"),
        ("human", "请回答:{question}")
    ]
)
# 填充变量生成完整prompt
prompt = chat_prompt.invoke({"role": "AI助手", "question": "什么是LangChain,简洁回答100字以内"})

# 3. 初始化通义千问兼容接口模型
model = init_chat_model(
    model="qwen-plus",
    model_provider="openai",
    api_key=os.getenv("aliQwen-api"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

# 4. 调用大模型,返回AIMessage对象
result = model.invoke(prompt)
logger.info(f"模型原始输出:\n{result}") # 原始对象包含id、content等字段

# 5. 字符串解析器转换
parser = StrOutputParser()
response = parser.invoke(result)
logger.info(f"解析后结果:\n{response}")
logger.info(f"结果类型: {type(response)}") # <class 'str'>

使用场景

只需要纯文本回答,不需要解析JSON、结构化数据,日常简单问答场景首选。


2. JsonOutputParser JSON字典解析器(两种用法)

用法1:简易JSON(JsonOutputParserDemo.py)

直接在提示词约束模型返回JSON,无需定义数据模型,解析后直接得到dict

# 系统提示强制要求返回json,q存问题,a存答案
chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个{role},请简短回答,结果返回json格式,q字段表示问题,a字段表示答案。"),
    ("human", "请回答:{question}")
])
# 模型调用省略,和上文一致
parser = JsonOutputParser()
response = parser.invoke(result)
print(type(response)) # <class 'dict'>

优点:代码极简;缺点:无法约束JSON字段、字段类型,大模型容易漏字段。

用法2:带格式指令自定义JSON(JsonOutputParser_GetFormatInstructions.py)

基于Pydantic模型定义JSON结构,通过get_format_instructions()自动生成格式规则注入提示词,强制模型输出指定字段。

  1. 先定义数据模板:
from pydantic import BaseModel, Field
class Person(BaseModel):
    time: str = Field(description="新闻时间")
    person: str = Field(description="新闻人物")
    event: str = Field(description="新闻事件")
  1. 生成格式指令并注入prompt:
parser = JsonOutputParser(pydantic_object=Person)
format_instructions = parser.get_format_instructions() # 自动生成JSON规范文本
# 提示词拼接规范指令
chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是AI助手,只能输出结构化JSON。"),
    ("human", "生成{topic}新闻。{format_instructions}")
])
prompt = chat_prompt.format_messages(topic="小米su7跑车", format_instructions=format_instructions)
  1. 模型返回后解析为字典,自带基础字段校验。

使用场景

需要结构化数据,但不需要复杂字段校验(长度、数值范围等),大部分业务场景通用。


3. PydanticOutputParser 强校验结构化解析器(StructuredOutput_Pydantic.py)

核心优势

基于BaseModel,支持:

  1. 字段描述 Field(description="xxx")
  2. 自定义校验器 @field_validator
  3. 运行时自动校验,不满足规则直接抛异常;
  4. 自动生成格式化指令约束大模型输出。

代码关键片段讲解

from pydantic import BaseModel, Field, field_validator
# 1. 定义强约束数据模型
class Product(BaseModel):
    name: str = Field(description="产品名称")
    category: str = Field(description="产品类别")
    description: str = Field(description="产品简介")

    # 自定义字段校验:简介长度≥10
    @field_validator("description")
    def validate_description(cls, value):
        if len(value) < 10:
            raise ValueError('产品简介长度必须大于等于10')
        return value

# 2. 初始化解析器,自动生成格式指令
parser = PydanticOutputParser(pydantic_object=Product)
format_instructions = parser.get_format_instructions()

# 3. 提示词注入规则,调用模型后解析
response = parser.invoke(result)
print(type(response)) # Product对象,可直接response.name取属性

使用场景

对输出数据规范要求极高:表单、商品信息、报表、需要严格字段校验的业务。


4. TypedDict 轻量结构化输出(StructuredOutput_TypedDict.py)

核心特点

Python3.8+原生类型注解,配合llm.with_structured_output()快捷调用,无运行时校验,仅用于给大模型定义输出结构。

from typing import TypedDict, Annotated
# 定义嵌套结构
class Animal(TypedDict):
    animal: Annotated[str, "动物名称"]
    emoji: Annotated[str, "对应表情"]

class AnimalList(TypedDict):
    animals: Annotated[list[Animal], "动物表情列表"]

# 模型直接绑定结构化输出,无需手动拼接format_instructions
llm_with_structured_output = llm.with_structured_output(AnimalList)
resp = llm_with_structured_output.invoke("生成三种动物和对应emoji")
# resp 是原生dict,无校验,即使类型错误也不会报错

Annotated补充说明(AnnotatedTypedDict.py / AnnotatedPydantic.py)

  1. Annotated[基础类型, 元数据]:给字段附加说明文本;
  2. 搭配TypedDict:仅静态提示,运行时无效;
  3. 搭配Pydantic Field:元数据+运行时校验双重生效。

例:年龄约束

# TypedDict:只注释,188不会报错
Age = Annotated[int, "年龄0-150"]
# Pydantic:搭配Field,超出范围直接抛异常
Age = Annotated[int, Field(ge=0, le=150, description="年龄0-150")]

三、四大解析器对比总结

解析器 输出类型 运行时校验 适用场景 优缺点
StrOutputParser str 纯文本问答 极简,无结构化能力
JsonOutputParser dict 弱校验(字段存在) 简单结构化数据 上手快,不支持复杂校验
PydanticOutputParser Pydantic对象 强自定义校验 严谨业务、表单、报表 功能最全,代码量稍多
with_structured_output(TypedDict) dict 快速原型、简单嵌套结构 调用简洁,无数据校验

四、开发选型建议

  1. 简单问答、只需要文字:StrOutputParser
  2. 需要JSON字典,无严格校验:JsonOutputParser / TypedDict + with_structured_output
  3. 输出有格式、长度、数值范围强制要求:PydanticOutputParser
  4. 快速开发、不想手动拼接format_instructions:优先 llm.with_structured_output()

五、核心避坑点

  1. TypedDict 只有类型提示,运行时不会拦截非法数据,严谨业务不要用;
  2. Pydantic校验会直接抛出ValidationError,生产环境需要try-except捕获异常;
  3. 使用get_format_instructions()时,必须把变量注入提示词,否则大模型不会遵守格式;
  4. 所有解析器入参必须是模型返回的AIMessage对象,不能直接传入字符串。
posted @ 2026-08-17 20:45  _丑小鸭  阅读(0)  评论(0)    收藏  举报