我叫老王,在一家中型电商公司做后端开发。去年双十一,我们上线了一套基于 AI 的智能客服系统,上线第一天就崩了——不是并发扛不住,而是 AI 返回的数据格式完全不可控。客服问"帮我查一下订单20231111的状态",AI 返回了一段自然语言描述,但我们的订单系统需要的是 JSON 结构:{"order_id": "20231111", "status": "shipped", "timestamp": "..."}

这正是 LangChain 输出解析(Output Parsing)的核心价值所在。在我们的场景中,AI 不只是生成文本,而是要与下游系统对接,必须返回机器可读的、严格结构化的数据。本文将完整记录我从踩坑到解决问题的全过程,包含可复制的代码和真实价格对比。

为什么需要 Output Parsing

在传统 AI 应用中,调用大模型后我们得到的是一段字符串。如果下游是另一个 AI 系统,这没问题;但如果下游是数据库、API、前端组件,你就需要做大量字符串解析工作。更要命的是,AI 的输出不稳定——今天返回"已发货",明天返回"快递已发出",你永远不知道它会说什么。

Output Parsing 的本质是给 AI 一个"输出契约":无论输入什么,模型必须按照你定义的格式返回数据。这在以下场景尤为关键:

环境准备:连接 HolySheheep API

在开始之前,我们需要配置 LangChain 连接 HolySheep 的大模型服务。选择 HolySheep 的原因很实际:汇率 ¥1=$1,比官方节省超过 85%,而且国内直连延迟在 50ms 以内,对高并发的客服场景非常友好。

# 安装必要依赖
pip install langchain langchain-core langchain-community langchain-holysheep

配置 HolySheep API

import os os.environ["HOLYSHEEP_API_KEY"] = "YOUR_HOLYSHEEP_API_KEY" os.environ["HOLYSHEEP_API_BASE"] = "https://api.holysheep.ai/v1"
# 初始化 HolySheep LLM
from langchain_holysheep import ChatHolySheep

llm = ChatHolySheep(
    model="gpt-4.1",  # 或 claude-sonnet-4.5, deepseek-v3.2 等
    temperature=0.3,
    api_key="YOUR_HOLYSHEEP_API_KEY"
)

测试连接

response = llm.invoke("你好,请回复'连接成功'") print(response.content) # 应该输出:连接成功

这里有个实战经验:HolySheep 支持 GPT-4.1($8/MTok)和 Claude Sonnet 4.5($15/MTok),对于结构化输出场景,我建议用 GPT-4.1——它对 JSON 格式的遵循度更高,而且价格便宜近一半。如果你的项目成本敏感,也可以用 DeepSeek V3.2,价格只要 $0.42/MTok,性价比极高。

实战场景:电商订单状态查询系统

我们回到最初的场景:用户问"订单20231111现在到哪了",AI 需要返回结构化的订单信息。

方案一:PydanticOutputParser(推荐)

这是最强大的方案,通过 Pydantic 模型定义输出结构,LangChain 会自动引导模型生成符合 schema 的 JSON。

from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate
from pydantic import BaseModel, Field
from typing import Optional
from datetime import datetime

定义订单数据结构

class OrderInfo(BaseModel): order_id: str = Field(description="订单号") status: str = Field(description="订单状态:pending/shipped/delivered/cancelled") current_location: Optional[str] = Field(description="当前物流位置", default=None) estimated_delivery: Optional[str] = Field(description="预计送达时间", default=None) carrier: Optional[str] = Field(description="快递公司", default=None) last_update: str = Field(description="最后更新时间")

创建解析器

parser = PydanticOutputParser(pydantic_object=OrderInfo)

构建提示词模板

prompt = PromptTemplate( template="""你是一个电商订单查询助手。用户会询问订单状态。 {format_instructions} 用户问题:{query} 请根据订单数据库返回结构化信息。如果订单不存在,返回所有字段为 null(除了 status 设为 "not_found")。""", input_variables=["query"], partial_variables={"format_instructions": parser.get_format_instructions()} )

创建链

chain = prompt | llm | parser

执行查询

result = chain.invoke({"query": "帮我查一下订单 20231111 的状态"}) print(f"订单号: {result.order_id}") print(f"状态: {result.status}") print(f"物流位置: {result.current_location}") print(f"快递公司: {result.carrier}") print(f"最后更新: {result.last_update}")

这段代码的输出会类似:

订单号: 20231111
状态: shipped
物流位置: 上海分拨中心
快递公司: 顺丰速运
最后更新: 2023-11-11 14:32:00

关键是 parser.get_format_instructions() 会自动生成一段提示词告诉模型如何输出。LangChain 内部会在 prompt 末尾追加类似这样的指令:

The output should be formatted as a JSON instance that conforms to the JSON schema below.

Here is the output schema:
{"properties": {"order_id": {"description": "订单号", "type": "string"}, "status": {...}}, "required": ["order_id", "status", "last_update"]}

方案二:JsonOutputParser

如果你的数据结构比较简单,不需要复杂的验证逻辑,可以用 JsonOutputParser。

from langchain.output_parsers import JsonOutputParser

定义简单的 JSON schema

json_schema = { "type": "object", "properties": { "answer": {"type": "string", "description": "回复用户的自然语言答案"}, "confidence": {"type": "number", "description": "答案置信度 0-1"}, "requires_escalation": {"type": "boolean", "description": "是否需要转人工"} }, "required": ["answer", "confidence", "requires_escalation"] } parser = JsonOutputParser(schema=json_schema) prompt = PromptTemplate( template="""作为客服助手,回答用户问题并评估是否需要转人工。 {format_instructions} 用户问题:{question}""", input_variables=["question"], partial_variables={"format_instructions": parser.getFormatInstructions()} ) chain = prompt | llm | parser result = chain.invoke({"question": "这个商品能便宜点吗?我是老客户"}) print(result)

输出: {"answer": "