LangChain进阶篇(二):文本分类——利用结构化输出构建智能标注系统

在传统的自然语言处理(NLP)中,文本分类通常需要训练专门的模型(如BERT)并进行繁琐的数据标注。而在大模型时代,利用 LangChain 结合 LLM(大语言模型),我们可以通过几行代码实现一个具备多维度分析能力的通用分类器。

本文将深入探讨如何使用 LangChain 的 with_structured_output 功能,构建一个能同时识别情感攻击性语言类型的智能标注系统。


一、核心概念与架构设计

在开始写代码之前,我们需要理解基于 LLM 的文本分类与传统方法的区别。LLM 分类本质上是一个 “理解 + 格式化” 的过程。

1.1 任务维度分析

我们的目标是输入一段文本,让 AI 输出三个维度的标签。这可以通过以下思维导图概括:

文本分类任务

输入

一段自然语言文本

分析维度

情感 Sentiment

Happy

Neutral

Sad

攻击性 Aggressiveness

整数

数值越高越强

语言 Language

Spanish

English

French

German

Italian

输出

严格的 JSON 格式

Pydantic 对象

1.2 处理流程

LangChain 通过 Chain(链) 的概念将提示词(Prompt)与模型(Model)串联。为了保证输出的稳定性,我们引入 Pydantic 进行数据验证。

渲染后的Prompt

结构化生成

验证通过

验证失败

用户输入 Text

Prompt Template
提示词模板

LLM
GPT-4o-mini

Pydantic Schema
数据验证

Classification 对象

Error / Retry


二、实战代码:构建分类器

下面是完整的实现代码。我们将使用 OpenAI 的 gpt-4o-mini 模型,因为它在保持低成本的同时,具备优秀的指令遵循能力。

2.1 环境准备

确保已安装核心依赖:

pip install langchain langchain-openai pydantic

2.2 代码实现

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field
import os

# ----------------------------
# 1. 定义结构化数据模型 (Schema)
# ----------------------------
class Classification(BaseModel):
    """
    定义输出的数据结构。
    Pydantic 不仅用于验证,其文档字符串(docstring)也会作为提示词的一部分传给 LLM。
    """
    sentiment: str = Field(
        description="The sentiment of the text", 
        enum=["happy", "neutral", "sad"]
    )
    aggressiveness: int = Field(
        description="describes how aggressive the statement is, the higher the number the more aggressive",
        enum=[1, 2, 3, 4, 5]
    )
    language: str = Field(
        description="The language the text is written in", 
        enum=["spanish", "english", "french", "german", "italian"]
    )

# ----------------------------
# 2. 定义提示词模板 (Prompt)
# ----------------------------
# 我们使用 Few-shot 思想和明确的约束指令来构建 Prompt
tagging_prompt = ChatPromptTemplate.from_template(
    """
    YOUR TASK: Analyze the passage and return ONLY a JSON object with these EXACT fields:
    - sentiment: MUST be one of ["happy", "neutral", "sad"] (no other values)
    - aggressiveness: MUST be an integer from 1-5
    - language: MUST be one of ["spanish", "english", "french", "german", "italian"]

    Passage:
    {input}

    JSON FORMAT REQUIREMENTS:
    - NO extra fields or keys
    - NO comments or explanations
    - NO markdown or formatting
    - ONLY valid JSON object

    EXAMPLE OUTPUT:
    {{"sentiment": "happy", "aggressiveness": 1, "language": "spanish"}}
    """
)

# ----------------------------
# 3. 初始化 LLM 并绑定结构化输出
# ----------------------------
llm = ChatOpenAI(
    model_name="gpt-4o-mini",
    temperature=0.7, # 稍微增加一点随机性以处理语义,但不要太高
    max_tokens=2000,
    api_key=os.environ["OPENAI_API_KEY_4O_MINI"],
    base_url="https://oneapi.xty.app/v1/"
).with_structured_output(
    Classification  # 关键步骤:绑定 Pydantic 模型
)

# ----------------------------
# 4. 构建与执行链 (Chain)
# ----------------------------
tagging_chain = tagging_prompt | llm

# 测试输入(西班牙语:很高兴认识你!我觉得我们会成为好朋友!)
inp = "Estoy increiblemente contento de haberte conocido! Creo que seremos muy buenos amigos!"

# 调用
res = tagging_chain.invoke({"input": inp})

print(f"原始输入: {inp}")
print("-" * 30)
print(f"分类结果: {res}")
print(f"情感倾向: {res.sentiment}")
print(f"对象类型: {type(res)}")

2.3 执行结果

运行上述代码,控制台将输出:

原始输入: Estoy increiblemente contento de haberte conocido! Creo que seremos muy buenos amigos!
------------------------------
分类结果: sentiment='happy' aggressiveness=1 language='spanish'
情感倾向: happy
对象类型: <class '__main__.Classification'>

可以看到,LLM 不仅正确识别了西班牙语(Spanish)和开心的情绪(Happy),还给出了攻击性评级为 1(最低)。最重要的是,返回的 res 是一个标准的 Python 对象,可以直接通过属性访问。


三、底层原理深度解析

为什么 tagging_prompt | llm 这样简单的组合就能实现复杂的分类?这里涉及 LangChain 对 LLM 能力的封装。

3.1 提示词工程 (Prompt Engineering)

在代码中,tagging_prompt 充当了“指令官”的角色。它利用了以下技巧:

  • Role Prompting(角色设定):明确任务是 YOUR TASK: Analyze...
  • Constraints(约束条件):使用 MUST be...NO extra fields 强制模型遵守规则。
  • One-shot Learning(单样本学习):提供了一个 EXAMPLE OUTPUT,让模型模仿输出格式。

3.2 结构化输出机制 (Structured Output)

这是本教程的核心。llm.with_structured_output(Classification) 并非简单的后处理,其底层交互时序如下:

OpenAI API (LLM) LangChain 应用程序 OpenAI API (LLM) LangChain 应用程序 转换 Pydantic 为 Tool/Function 定义 自动解析与验证 invoke({"input": "..."}) 渲染 Prompt 模板 发送请求 (Prompt + Tools Schema) 推理分析 返回 Tool Call (JSON 参数) 将 JSON 映射为 Classification 对象 返回 Classification 实例

关键点解析

  1. Schema 转换:LangChain 会自动读取 Classification 类的 Pydantic 定义(包括 descriptionenum),将其转换为 OpenAI API 支持的 Function Calling (Tools) 格式。
  2. 强制性:对于支持 Tool Calling 的模型(如 GPT-3.5/4),这种方式比单纯用 Prompt 让模型生成 JSON 更稳定,因为模型经过了专门的微调来输出这种结构。
  3. 自动验证:如果 LLM 返回的 JSON 缺少字段或类型错误(例如 aggressiveness 返回了 6),Pydantic 会在 LangChain 内部抛出验证错误,甚至可以配置自动重试机制。

四、进阶应用场景

掌握了这种文本分类方法,你可以轻松扩展到更多业务场景:

场景输入示例输出 Schema 设计
客服工单路由“我的卡被吞了”department: [“技术部”, “财务部”, “客服部”]
urgency: [1-5]
垃圾评论过滤“加微信号 xxxx 领奖”is_spam: boolean
reason: [“广告”, “色情”, “正常”]
用户意图识别“帮我定明天去北京的票”intent: [“booking”, “query”, “cancel”]
entities: {“destination”: “北京”, “time”: “明天”}

通过 LangChain 实现文本分类,我们将复杂的 NLP 任务简化为了两个步骤:定义数据结构编写提示词

  • Pydantic 负责“立规矩”,确保输出是计算机可读的。
  • Prompt 负责“教做事”,引导模型理解语义。
  • LangChain 负责“跑腿”,处理 API 通信和数据转换。

这种模式极大地降低了 AI 应用落地的门槛,让开发者能专注于业务逻辑的设计。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TracyCoder123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值