langchain系列第二章

第二章:结构化输出(强制返回 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

💡 重点总结(这节太重要了)

  1. 定义结构:用 Pydantic + Field 写清楚每个字段和描述
  2. 套魔法llm.with_structured_output(你的类)
  3. 直接用:返回的就是 Python 对象,直接 .字段名

这一个功能就值回票价了! 以前要写一堆正则、NLP 模型,现在一行搞定!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值