OutputParser输出解析器

为什么需要输出解析器

我们在使用大语言模型的时候,无论是使用 LangChain,还是直接使用模型的 API,都会遇到大语言模型的输出解析问题,以 OpenAI 的模型为例:

python 复制代码
from langchain_openai import ChatOpenAI

llm = ChatOpenAI()

from langchain_openai import ChatOpenAI

llm = ChatOpenAI()

# 示例1
llm.invoke("告诉我1+1等于几?")  # 输出: 1 + 1 等于 2。

# 示例2
llm.invoke("告诉我3个动物的名字。")  # 输出: 好的,这里有三种动物的名字:
                                     # 1. 狮子
                                     # 2. 大熊猫
                                     # 3. 斑马

# 示例3
llm.invoke("给我一个json数据,键为a和b,值为任意的整型。")  # 输出: {
                                                         #    "a": 10,
                                                         #    "b": 20
                                                         # }

虽然整体的问题已经回答了,但是返回的内容都是一个字符串,并不是结构化的数据,某些场合下我们需要的仅仅是对应的返回值,而不是多余的内容,就需要对返回的内容进行结构化、格式化或者解析。

例如下方为修改后的提示,尽可能先让大语言模型按照特定的规则输出内容,然后再进行解析

python 复制代码
from langchain_openai import ChatOpenAI

llm = ChatOpenAI()

# 示例1,输出:2
llm.invoke("告诉我1+1等于几?除了答案其他内容均不要返回。")

# 示例2,输出:1.老虎\n2.狮子\n3.斑马
llm.invoke("告诉我3个动物的名字。返回示例:1.狮子\n2.大熊猫")

# 示例3,输出:{"a": 10, "b": 20}
llm.invoke("给我一个json数据,键为a和b,值为任意的整型。除了json数据,其他内容均不要返回。")

因此,如果需要 LLM 理解你想要的格式,需要向 LLM 告知要输出的结构信息,当 LLM 进行推理并输出之后,我们需要对 LLM 约定的格式进行解析,于是就诞生了 输出解析器 的概念。

简单拆解:输出解析器 = 预设提示 + 解析功能

输出解析器的解析场景:

  1. 将非结构化的文本转换为结构化的数据:将文本解析为一个 JSON 或者是 Python 里的字典等。
  2. 截取部分文本:只要结果中的某一部分即可。
  3. 自定义处理:在提示中注入其他的指令,告诉语言模型如何去给我返回一个格式的答案,然后解析器可以根据返回提示文本对应的内容做对应的解析。

OutputParser输出解析器

在 LangChain 中预设了大量的输出解析器,输出解析器通常包含两个抽象函数的实现,这也是自定义输出解析器需要实现的两个函数:

  1. get_format_instructions:用来约定输出的格式,并转换为描述文本。
  2. parse:用来解析 LLM 的输出为约定的格式。

但在实际的使用中,输出解析器大部分场景都是解析大语言模型的输出内容,所以可以直接使用 invoke 函数进行调用,在 invoke 函数的底层,还是调用了 parse 函数进行解析。

在 LangChain 中 OutputParser 的基类及子类划分如下:

StrOutputParser

StrOutputParser 是 LangChain 中使用频率最高的输出解析器,使用也非常简单,它会将传入的文本原样返回,常用于解析得到 AIMessage 中的输出文本。

python 复制代码
from langchain_core.output_parsers import StrOutputParser

StrOutputParser().parse("程序员的梦工厂")

输出内容

python 复制代码
程序员的梦工厂

源码实现

python 复制代码
def parse(self, text: str) -> str:
    """Returns the input text with no changes."""
    return text

JsonOutputParser

JsonOutputParser 用于将对应的 LLM 输出转换为特定格式的 json 或 Python 字典,在使用前必须定义 BaseModel 规范解析的数据结构,并将解析器提供的描述文本嵌入到提示中,使用示例如下:

python 复制代码
import dotenv
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI

dotenv.load_dotenv()

# 1. 创建一个json数据结构,用于告诉大语言模型这个json长什么样子
class Joke(BaseModel):
    # 冷笑话
    joke: str = Field(description="回答用户的冷笑话")
    # 冷笑话的笑点
    punchline: str = Field(description="这个冷笑话的笑点")

parser = JsonOutputParser(pydantic_object=Joke)

# 2 构建一个提示函数
prompt = ChatPromptTemplate.from_template("请根据用户的提问进行回答。\n{format_instructions}\n{query}").partial(format_instructions=parser.get_format_instructions())

# 3构建一个大语言模型
llm = ChatOpenAI(model="gpt-3.5-turbo-16k")

# 4 传递提示并进行解析
joke = parser.invoke(llm.invoke(prompt.invoke({"query": "请讲一个关于程序员的冷笑话"})))

print(joke)

其他思路参考

如果使用的模型支持 Function Calling 或者 Tool Calling,可以不使用解析器,而是直接定义一个函数,规定它的函数参数为对应要解析的格式,并强制模型调用这个函数,模型就可以精准无误地按照特定的约束输出。

思考 & 问题:

  1. 如果 outputParser 输出解析失败了,该如何解决?有几种解决方案?
  2. 针对小参数的模型,并且没有函数 / 工具回调,哪一类输出解析器会更稳定?
相关推荐
Highcharts.js1 小时前
缺失数据可视化图表开发实战|Highcharts创建人员出生统计面积图表示例
开发语言·前端·javascript·信息可视化·highcharts·图表开发
测试19985 小时前
软件测试 - 单元测试总结
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
小辰记事本7 小时前
从零读懂RoCEv2数据包构造:从WQE到线缆上的完整旅程
服务器·网络·网络协议·rdma
LaughingZhu8 小时前
Product Hunt 每日热榜 | 2026-05-21
前端·人工智能·经验分享·chatgpt·html
怕浪猫8 小时前
Electron 开发实战(一):从零入门核心基础与环境搭建
前端·electron·ai编程
曲幽8 小时前
我用了FastApiAdmin后,连夜把踩过的坑都整理出来了
redis·python·postgresql·vue3·fastapi·web·sqlalchemy·admin·fastapiadmin
小鹏linux8 小时前
Ubuntu 22.04 部署开源免费具有精美现代web页面的Casdoor账号管理系统
linux·前端·ubuntu·开源·堡垒机
在角落发呆9 小时前
Linux转发配置:解锁网络互联的核心密码
linux·运维·网络
前端若水9 小时前
会话管理:创建、切换、删除对话历史
前端·人工智能·python·react.js
齐潇宇9 小时前
Zabbix 7 概述与配置
linux·zabbix·监控告警