一个项目带你 入门AI应用开发02 - bamb00
2.1 你的目标用户输入不同的内容,程序自动判断意图并做出对应的回应:You: 帮我查一下快递[意图识别: order_query]AI: 正在查询您的订单...You: 你们的产品太 2026-8-1 11:45:0 Author: www.cnblogs.com(查看原文) 阅读量:9 收藏

2.1 你的目标

用户输入不同的内容,程序自动判断意图并做出对应的回应:

You: 帮我查一下快递
[意图识别: order_query]
AI: 正在查询您的订单...

You: 你们的产品太差了
[意图识别: complaint]
AI: 非常抱歉,我已记录您的问题...

You: 你好
[意图识别: greeting]
AI: 你好!有什么可以帮你的?

2.2 反例:关键词匹配为什么不行?

你可能第一反应是写 if-else:

if "订单" in user_input or "物流" in user_input:
    handle_order()
elif "退货" in user_input or "投诉" in user_input:
    handle_complaint()
elif "产品" in user_input or "价格" in user_input:
    handle_product()

跑一下看看:

用户输入 期望 实际结果
"查一下我的快递到哪了" 查订单 ❌ 走了 else——没有"订单"关键词
"我要退了这个耳机" 投诉/退货 ❌ 走了 else——虽然有"退",但条件匹配不精确
"这个订单我要投诉" 投诉 ⚠️ 同时包含"订单"和"投诉",取决于 if 顺序

为什么不行? 语言是灵活的。"我的快递到哪了"明明是在查订单,但关键词匹配无法理解"快递"="查订单"这种语义关系。人类能理解,代码不行。

这个问题的本质是什么?

关键词匹配是在字符层面工作,而意图识别需要在语义层面工作。LLM 恰好擅长后者。

2.3 正解:让 LLM 做分类器

把分类规则写进 system prompt,让 LLM 来判断:

def classify_intent(user_input):
    prompt = """你是一个电商客服意图分类器。判断用户消息属于以下哪一类:
- order_query: 查询订单、物流、配送状态
- complaint: 投诉、不满、要求售后
- product_inquiry: 询问产品信息、功能、价格
- greeting: 问候、闲聊
- other: 其他

只返回 JSON 格式:{"intent": "<分类>", "reason": "<理由>"}"""
    
    reply = call_llm([
        {"role": "system", "content": prompt},
        {"role": "user", "content": user_input},
    ])
    
    import json
    try:
        parsed = json.loads(reply)
        return parsed.get("intent", "other")
    except json.JSONDecodeError:
        return "other"  # 解析失败时走最安全的路径

为什么 JSON mode 很重要?

你看 prompt 的最后一句:"只返回 JSON 格式"。这是告诉 LLM 输出结构化的数据,而不是自然语言。

如果不加这句话,LLM 可能会回复:

我认为用户的问题是 order_query,因为他在查询订单状态。

加了之后,它会回复:

{"intent": "order_query", "reason": "用户在查询订单状态"}

结构化输出让下游代码可以直接 parsed["intent"],不需要做文本解析。这是 Agent 系统中反复出现的模式——LLM 负责理解,代码负责执行。

为什么需要 try/except?

LLM 的输出没有 100% 的保证。即使你说了"只返回 JSON",它偶尔也会输出别的。所以:

try:
    parsed = json.loads(reply)
    return parsed.get("intent", "other")
except:
    return "other"  # 兜底:走最安全的路径

这不是"偷懒",而是防御性编程——承认 LLM 不可靠,并为不可靠做好准备。

2.4 路由表:替代 if-else

传统的 if-else:

def handle(user_input, intent):
    if intent == "greeting":
        return "你好!"
    elif intent == "complaint":
        return "已记录投诉..."
    elif intent == "order_query":
        return call_llm([...订单客服...])
    ...

改用路由表(dict):

INTENT_ROUTE = {
    "order_query": handle_order,
    "complaint": handle_complaint,
    "product_inquiry": handle_product,
    "greeting": handle_greeting,
}

def handle_by_intent(user_input, intent):
    handler = INTENT_ROUTE.get(intent, handle_other)
    return handler(user_input)

用 dict 代替 if-else 的好处:

  1. 新增意图:在 dict 里加一行,不用改 if-else 结构
  2. 动态路由:dict 可以在运行时修改
  3. 可配置:路由表可以放在配置文件里

更重要的:容错

handler = INTENT_ROUTE.get(intent, handle_other)

如果 LLM 返回了一个 INTENT_ROUTE 里不存在的意图(比如 "return_request"),程序不会崩溃,而是走 handle_other 兜底。

2.5 完整代码的结构

├── Settings              # 配置管理(第1课的内容)
├── call_llm()            # LLM 调用(第1课的内容)
├── classify_intent()     # ★ 本课新增:意图分类
├── handle_order()        # 订单处理
├── handle_product()      # 产品咨询
├── handle_other()        # 兜底处理
├── INTENT_ROUTE          # ★ 本课新增:路由表
├── handle_by_intent()    # ★ 本课新增:按意图路由
└── main()                # 主循环

从第1课到第2课的变化: 代码结构从"问→答"变成了"问→分类→按类回答"。只加了一层抽象,但系统的行为从"统一回复"变成了"按需响应"。

本课知识点

概念 你做了什么 为什么
意图分类 用 LLM 替代关键词匹配 LLM 理解语义,"快递到哪了"也能识别为 order_query
System Prompt 在 system 消息中定义分类规则 规则独立于具体对话,可单独优化
JSON mode 要求 LLM 输出 JSON + try/except 结构化输出方便下游处理;异常时走兜底路径
路由表 dict 替代 if-else 新增意图只需加一行,不会破坏现有逻辑
容错 route.get(intent, default) LLM 输出未定义意图时,程序不会崩溃

课后作业

  1. 在 prompt 里加一个 price_inquiry 意图,并在路由表中注册对应的处理函数
  2. INTENT_ROUTE 改成从 JSON 文件读取,体验"配置驱动"的思路

面试可能会问

"System Prompt 和 User Prompt 的区别是什么?为什么分类规则放在 System 里?"

"如果 LLM 返回了一个未定义的意图名称,你的系统会怎么处理?"


文章来源: https://www.cnblogs.com/goodhacker/p/22137472
如有侵权请联系:admin#unsafe.sh