008.LangChain 输出解析器

该教程旨在带大家从 0 起步,掌握用 Python 开发大模型应用的技能。若当前内容让你感到晦涩,可回溯本合集的前期文章,降低学习难度。


1. 为什么要学"输出解析器"?

没有解析器 有了解析器
AI 想回啥就回啥,格式千奇百怪 让 AI 先立规矩再说话
正则/字符串切割写到崩溃 一行代码直接拿到 Python 对象
线上崩了才发现格式变了 解析失败就抛异常,提前暴露问题

2. CommaSeparatedListOutputParser(逗号列表解析器)

2.1. 它到底干啥?

给模型下指令 :请用英文逗号 , 把答案分开

帮你解析 :把 "#ff0000,#00ff00,#0000ff" 直接变成 ['#ff0000','#00ff00','#0000ff']

2.2. 具体实践

2.2.1. 安装

复制代码
pip install langchain langchain-deepseek

2.2.2. 创建解析器

Python 复制代码
from langchain.output_parsers import CommaSeparatedListOutputParser

parser = CommaSeparatedListOutputParser()
# 打印看看解析器生成的"命令"长啥样
print(parser.get_format_instructions())
# 输出:Your response should be a list of items separated by commas...

2.2.3. 把"命令"塞进提示词

Python 复制代码
from langchain.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一名色彩设计师。{format_instructions}"),
    ("human", "请给出 5 个符合{theme}主题的背景色十六进制色号"),
])

2.2.4. 调用模型

Python 复制代码
from langchain_deepseek import ChatDeepSeek

llm = ChatDeepSeek(model="deepseek-chat", temperature=0)

prompt_with_fmt = prompt.format_prompt(
    format_instructions=parser.get_format_instructions(),
    theme="夏季"
)
response = llm.invoke(prompt_with_fmt.to_messages())
colors = parser.parse(response.content)
print(colors)   # ['#87CEEB', '#FFA07A', '#32CD32', '#FFD700', '#FF69B4']

3. PydanticOutputParser(JSON → Python 对象)

3.1. 它到底干啥?

给模型下指令 :请按 JSON Schema 输出

帮你解析 :把 JSON 字符串直接变成 Python 数据类(Pydantic 模型)

3.2. 具体实践

3.2.1. 定义"说明书"

Python 复制代码
from typing import List
from pydantic import BaseModel, Field

class BookInfo(BaseModel):
    book_name: str  = Field(..., description="书名")
    book_author: str = Field(..., description="作者")
    genres: List[str] = Field(..., description="题材列表")

3.2.2. 创建解析器

Python 复制代码
from langchain.output_parsers import PydanticOutputParser

parser = PydanticOutputParser(pydantic_object=BookInfo)
print(parser.get_format_instructions())
# 输出:The JSON should have fields "book_name", "book_author", "genres"...

3.2.3. 塞进提示词

Python 复制代码
prompt = ChatPromptTemplate.from_messages([
    ("system", "从用户提供的原始文本中提取书籍信息。{format_instructions}"),
    ("human", "{raw_text}"),
])

3.2.4. 调用模型

Python 复制代码
raw = "《三体》是刘慈欣写的硬核科幻巨作,涉及文明冲突和宇宙社会学。"
book: BookInfo = (prompt | llm | parser).invoke({"raw_text": raw})
print(book.book_name)   # 三体
print(book.book_author) # 刘慈欣
print(book.genres)      # ['科幻', '文明冲突', '宇宙社会学']

如果 AI 把字段拼错或类型不对,Pydantic 会立即抛出 ValidationError,帮你提前发现。


4. LangChain LCEL 管道写法(| 符号到底啥意思?)

4.1. 一句话理解

提示 → 调用模型 → 解析结果 像乐高一样串成一条链,数据从左到右自动流动。

4.2. 从最熟悉的 "函数组合" 开始

Python 复制代码
# 传统写法
out = func3(func2(func1(data)))

# 管道写法
chain = func1 | func2 | func3
out = chain.invoke(data)

在 LangChain 里:

  • func1 是 PromptTemplate
  • func2 是 LLM
  • func3 是 OutputParser

4.3. 优点一览

场景 传统写法 管道写法
加日志 手动包函数 chain = chain.with_listeners(...)
加缓存 手动写缓存 chain = chain.with_cache()
并行/批处理 手写循环 chain.batch([...])
类型提示 全程保持类型安全

4.4 最小可运行示例

Python 复制代码
from langchain.prompts import ChatPromptTemplate
from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain_deepseek import ChatDeepSeek

parser = CommaSeparatedListOutputParser()
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一名色彩设计师。{format_instructions}"),
    ("human", "请给出 3 个符合{theme}主题的背景色")
]).partial(format_instructions=parser.get_format_instructions())

llm = ChatDeepSeek(model="deepseek-chat", temperature=0)

# 一行完成 prompt → llm → parser
chain = prompt | llm | parser
colors = chain.invoke({"theme": "夏日清凉"})
print(colors)   # ['#87CEEB', '#32CD32', '#FFD700']

5. 完整示例代码

5.1. 输出颜色列表

Python 复制代码
from langchain.prompts import ChatPromptTemplate
from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain_deepseek import ChatDeepSeek

def get_theme_colors_common(theme): 
    # 1. 创建解析器
    parser = CommaSeparatedListOutputParser()

    # 2. 构建提示词模版
    prompt = ChatPromptTemplate.from_messages([
        ("system", "你是一名色彩设计师。{format_instructions}"),
        ("human", "请给出 5 个符合{theme}主题的背景色十六进制色号"),
    ])

    # 3. 把解析器塞进模版
    prompt_with_fmt = prompt.format_prompt(format_instructions=parser.get_format_instructions(), theme=theme)

    llm = ChatDeepSeek(model="deepseek-chat", temperature=0)

    # 4. 调用模型
    response = llm.invoke(prompt_with_fmt.to_messages())

    return parser.parse(response.content)

def get_theme_colors_pipeline(theme):
    # 1. 创建解析器
    parser = CommaSeparatedListOutputParser()

    # 2. 构建提示词模版
    prompt = ChatPromptTemplate.from_messages([
        ("system", "你是一名色彩设计师。{format_instructions}"),
        ("human", "请给出 5 个符合{theme}主题的背景色十六进制色号"),
    ])

    # 3. 把解析器塞进模版
    prompt_with_fmt = prompt.partial(format_instructions=parser.get_format_instructions())

    llm = ChatDeepSeek(model="deepseek-chat", temperature=0)

    # 4. 调用模型
    chain = prompt_with_fmt | llm | parser

    return chain.invoke({"theme": theme})

if __name__ == "__main__":
    common_colors = get_theme_colors_common("夏季")
    pipeline_colors = get_theme_colors_pipeline("夏季")

    print(common_colors)
    print(pipeline_colors)

5.2. 解析书籍信息

Python 复制代码
from typing import List
from pydantic import BaseModel, Field
from langchain.output_parsers import PydanticOutputParser
from langchain_deepseek import ChatDeepSeek
from langchain.prompts import ChatPromptTemplate

class BookInfo(BaseModel):
    book_name: str = Field(..., description="书名")
    book_author: str = Field(..., description="作者")
    genres: List[str] = Field(..., description="题材列表")

parser = PydanticOutputParser(pydantic_object=BookInfo)

prompt = ChatPromptTemplate.from_messages([
    ("system", "从用户提供的原始文本中提取书籍信息。{format_instructions}"),
    ("human", "{raw_text}"),
])

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

llm = ChatDeepSeek(model="deepseek-chat", temperature=0)

raw = "《三体》是刘慈欣写的硬核科幻巨作,涉及文明冲突和宇宙社会学。"

book: BookInfo = (prompt_with_fmt | llm | parser).invoke({"raw_text": raw})

print(book.book_name)
print(book.book_author)
print(book.genres)
相关推荐
AI绘画哇哒哒5 小时前
【建议收藏!】35岁后端血泪忠告,这3类人别硬转Agent(过来人亲述)
java·人工智能·后端·ai·程序员·大模型·agent
唐青枫6 小时前
一个值多种形态:Zig union、Tagged Union 与内存布局实战
后端
卷无止境6 小时前
Windows 上丝滑开发 Python,并稳定构建 Docker 镜像
后端·python·docker
Nturmoils6 小时前
备份完不算完,先还原到临时库验一遍
后端
Csvn7 小时前
📊 SQL 入门 Day 22:视图与物化视图
后端·sql
Csvn7 小时前
🐍 Day 4: Python 控制流 — 条件、循环与推导式的艺术
后端·python
2601_953720828 小时前
【计算机毕业设计】基于Vue与Spring Boot的高校兼职信息服务平台设计与实现
spring boot·后端·课程设计
再吃一根胡萝卜9 小时前
用 Rust 写一个桌面悬浮图标:为什么它比 Python 更适合 AI 桌面工具?
后端
IT_陈寒9 小时前
Vue的computed属性把我坑惨了,原来我一直用错姿势
前端·人工智能·后端
evans在进步10 小时前
Spring Boot 核心机制详解:可执行 JAR、CORS、静态资源与配置绑定
spring boot·后端·jar