从零讲透 LangChain 输出格式化:让模型真的“能用”

一、我一开始踩的最大坑

刚开始用 LangChain 时,我以为最难的是:

Prompt 怎么写?

结果真正卡住我的,是另一件事:

模型返回的东西,我不知道怎么用。

举个例子。

我让模型判断一条评论是"好评"还是"差评",它会这样回我:

"这条评论整体偏正面,因为用户提到性价比高,但也提到了物流慢。"

我能看懂这句话,但我的代码看不懂。

我想做的是:

  • 根据情感结果走不同逻辑

  • 把结果存进数据库

  • 或者直接交给下一个接口

但面对这一大段话,我只能陷入沉默:

总不能写正则去猜它是不是好评吧?

后来我才明白一个很重要的事:

模型"会说",不等于模型"能用"。


二、输出格式化到底在解决什么问题?

一句话版本:

输出格式化,是把"人能看懂的话",变成"程序能用的数据"。

以前我写 Prompt 只关心:

  • 让它"好好回答"

现在我会多想一步:

  • 让它的回答长得像 JSON

  • 字段名固定

  • 格式稳定

  • 能被代码直接解析

在 LangChain 里,这件事由 **Output Parser(输出解析器)**​ 负责。

它做的事情很简单,但很重要:

  1. 告诉模型:你该怎么输出

  2. 把模型返回的字符串,转成 Python 对象

    Prompt → 模型 → 输出解析器 → 真正可用的结果


三、我最常用的几种输出解析方式

下面这些,是我实际项目中真正用过、踩过坑的。


✅ 1. StrOutputParser:最基础,但不容忽视

很多场景下,我其实只需要一段文字,比如:

  • 写摘要

  • 生成文案

  • 直接展示给用户

    from langchain_core.output_parsers import StrOutputParser

    parser = StrOutputParser()

它做的事情只有一个:

把模型返回的消息,安全地变成字符串。

📌 我当时学到的一点是:

哪怕不用结构化输出,也最好显式加一个 parser,而不是裸用模型。


✅ 2. JsonOutputParser:第一次让我觉得"终于能用了"

当我需要:

  • 接口返回

  • 前端渲染

  • Agent 工具参数

我基本都会选它。

复制代码
from langchain_core.output_parsers import JsonOutputParser

parser = JsonOutputParser()

prompt = ChatPromptTemplate.from_template(
    "请分析评论情感:\n{comment}\n\n{format_instructions}"
).partial(format_instructions=parser.get_format_instructions())

模型看到 format_instructions后,会明显更听话,输出类似

复制代码
{
  "sentiment": "positive",
  "confidence": 0.92
}

📌 对我这种写后端的人来说,这种结果才是真正可用的


✅ 3. PydanticOutputParser:我现在的主力方案

后来我发现一个问题:

JSON 虽然能用,但不够稳

  • 字段可能缺

  • 类型可能不对

  • IDE 也没法补全

所以我现在的首选是 PydanticOutputParser

复制代码
from pydantic import BaseModel, Field
from langchain_core.output_parsers import PydanticOutputParser

class SentimentResult(BaseModel):
    sentiment: str = Field(description="positive / neutral / negative")
    confidence: float = Field(description="0~1 的置信度")

好处非常直接:

  • 自动校验字段

  • 类型不对直接报错

  • 像在用普通 Python 对象

📌 如果你在做稍微正式一点的项目,我真心建议直接上这个。


✅ 4. 枚举值输出:越"死板"越好

有一次我做工单分类,模型老是发挥"创造力":

  • 一会儿叫 bug

  • 一会儿叫 缺陷

  • 一会儿还写一句解释

后来我学乖了,直接在 Prompt 里写死:

只能回答:BUG、FEATURE、QUESTION

配合最简单的 StrOutputParser,反而成了最稳的方案

📌 我现在的原则是:

能枚举的,绝不开放生成。


四、我踩过的几个坑(很重要)

这里每一个坑,都是我真实踩过的:

❌ 忘了注入 format_instructions

模型根本不知道我要什么格式,全靠"猜"。

✅ 解法:

prompt.partial(format_instructions=parser.get_format_instructions())


❌ 模型"多嘴"

它经常在 JSON 前后加一句:

"好的,这是分析结果:"

✅ 解法:

在 Prompt 里明确写:

只输出 JSON,不要有任何解释文字。


❌ 输出被截断,JSON 不完整

✅ 解法:

  • 控制字段数量

  • 控制最大 token

  • 必要时用更简单的结构


五、什么时候用什么解析器?

这是我给自己总结的一张"经验表":

场景 我选的解析器
聊天、文案 StrOutputParser
接口 / Agent 参数 JsonOutputParser
后端 / 数据库 PydanticOutputParser
分类 / 状态判断 枚举值 + StrOutputParser

六、一句话总结

**Prompt 决定模型"怎么想",

Output Parser 决定你"能不能用"。**

没有输出格式化,模型只是一个会说话的黑盒;

有了输出格式化,它才算真正接入你的系统。

相关推荐
薇茗1 小时前
【C++】 类与对象 基础篇
开发语言·c++·基础语法·类与对象
奋斗的小方1 小时前
Java进阶篇1-1:异常
java·开发语言·python
码语智行1 小时前
行政区划 ZIP 导入(importZip)
java
颜酱1 小时前
LangChain 调大模型:模板拼接 + invoke / stream / batch
python·langchain
sycmancia1 小时前
Qt——多页面切换组件
开发语言·qt
何中应1 小时前
Nexus如何设置端口号
java·服务器·maven·nexus
思麟呀1 小时前
C++11并发编程:条件变量
java·linux·jvm·c++·windows
Full Stack Developme1 小时前
Hutool CollUtil 教程
java·开发语言·windows·python
我是一颗柠檬1 小时前
【Java项目技术亮点】Kafka异步写+写聚合:吞吐量提升10倍的消息队列优化秘籍
java·分布式·kafka·linq