第二章:结构化输出(强制返回 JSON)⭐ 重点!
为什么需要这个?
之前我们让 AI 回答,它返回的是自然语言:
张三今年25岁,住在北京
但是写代码的时候,我们要的是能直接用的数据结构:
{
"name": "张三",
"age": 25,
"city": "北京"
}
知识点 1:with_structured_output(一行搞定)
这是 LangChain 最牛的功能之一! 自动强制大模型输出你要的格式,100% 准确
# ============== 复制就能跑 ==============
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field # 定义数据结构用的
load_dotenv()
llm = ChatOpenAI(model="qwen-plus", temperature=0.0) # 结构化输出建议用 qwen-plus / gpt-4o-mini
# 1. 定义你想要的数据结构(就像定义一张表的字段)
class Person(BaseModel):
"""人物信息"""
name: str = Field(description="姓名")
age: int = Field(description="年龄,整数")
city: str = Field(description="居住城市")
# 2. ✨ 魔法:给模型套上结构化输出
structured_llm = llm.with_structured_output(Person)
# 3. 调用,直接返回Python对象!
result = structured_llm.invoke("张三,25岁,家在北京")
print("=== 结果类型 ===")
print(type(result)) # <class '__main__.Person'>
print("\n=== 直接拿属性 ===")
print(f"姓名:{result.name}")
print(f"年龄:{result.age}")
print(f"城市:{result.city}")
print("\n=== 转成字典 ===")
print(result.model_dump()) # {'name': '张三', 'age': 25, 'city': '北京'}
✅ 运行结果:
=== 结果类型 ===
<class '__main__.Person'>
=== 直接拿属性 ===
姓名:张三
年龄:25
城市:北京
=== 转成字典 ===
{'name': '张三', 'age': 25, 'city': '北京'}
知识点 2:提取复杂信息(实战!)
场景: 从一段自然语言中提取结构化信息
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
from typing import List # 支持数组
load_dotenv()
llm = ChatOpenAI(model="qwen-plus", temperature=0.0)
# 定义:一个订单里有多个商品
class Product(BaseModel):
"""商品信息"""
product_name: str = Field(description="商品名称")
price: float = Field(description="单价")
quantity: int = Field(description="数量")
class Order(BaseModel):
"""订单信息"""
order_id: str = Field(description="订单号")
customer_name: str = Field(description="客户姓名")
products: List[Product] = Field(description="购买的商品列表")
total_amount: float = Field(description="总金额")
# 给模型套上结构化输出
structured_llm = llm.with_structured_output(Order)
# 一段杂乱的自然语言
text = """
王小明在我们店里买了东西,订单号是ORD2024001。
他买了2个苹果,每个5.5元;还买了3瓶牛奶,每瓶8元。
总共花了35元。
"""
result = structured_llm.invoke(text)
print("=== 提取结果 ===")
print(f"订单号:{result.order_id}")
print(f"客户:{result.customer_name}")
print(f"总金额:{result.total_amount}")
print("\n商品明细:")
for p in result.products:
print(f"- {p.product_name}: {p.quantity}个 × {p.price}元")
运行结果:
=== 提取结果 ===
订单号:ORD2024001
客户:王小明
总金额:35.0
商品明细:
- 苹果: 2个 × 5.5元
- 牛奶: 3个 × 8.0元
🎉 太神奇了! AI 自动从一段废话里,把你要的字段全提取出来了,格式丝毫不差!
知识点 3:分类任务(NLP 经典场景)
场景: 自动判断用户意图、给文本打标签
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
from enum import Enum # 枚举,只能选这几个值
load_dotenv()
llm = ChatOpenAI(model="qwen-plus", temperature=0.0)
# 定义:用户意图只能是这4种
class Intent(str, Enum):
CONSULT = "咨询"
COMPLAINT = "投诉"
REFUND = "退款"
OTHER = "其他"
class UserQuery(BaseModel):
"""用户查询分类"""
intent: Intent = Field(description="用户意图")
key_words: str = Field(description="提取关键词")
need_transfer: bool = Field(description="是否需要转人工")
structured_llm = llm.with_structured_output(UserQuery)
# 测试几个用户问题
queries = [
"这个东西怎么用?",
"你们产品太烂了!我要投诉!",
"我买错了,能退钱吗",
"今天天气真好"
]
for q in queries:
result = structured_llm.invoke(q)
print(f"用户说:{q}")
print(f" 意图:{result.intent}")
print(f" 关键词:{result.key_words}")
print(f" 转人工:{result.need_transfer}")
print("-" * 50)
✅ 运行结果:
用户说:这个东西怎么用?
意图:咨询
关键词:怎么用
转人工:False
--------------------------------------------------
用户说:你们产品太烂了!我要投诉!
意图:投诉
关键词:产品烂,投诉
转人工:True
--------------------------------------------------
用户说:我买错了,能退钱吗
意图:退款
关键词:买错,退钱
转人工:False
--------------------------------------------------
用户说:今天天气真好
意图:其他
关键词:天气好
转人工:False
💡 重点总结(这节太重要了)
- 定义结构:用
Pydantic + Field写清楚每个字段和描述 - 套魔法:
llm.with_structured_output(你的类) - 直接用:返回的就是 Python 对象,直接
.字段名
这一个功能就值回票价了! 以前要写一堆正则、NLP 模型,现在一行搞定!
6673

被折叠的 条评论
为什么被折叠?



