惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园_首页
量子位
阮一峰的网络日志
阮一峰的网络日志
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
云风的 BLOG
云风的 BLOG
D
DataBreaches.Net
B
Blog
L
LangChain Blog
Apple Machine Learning Research
Apple Machine Learning Research
Vercel News
Vercel News
博客园 - 三生石上(FineUI控件)
爱范儿
爱范儿
Microsoft Azure Blog
Microsoft Azure Blog
IT之家
IT之家
aimingoo的专栏
aimingoo的专栏
B
Blog RSS Feed
H
Help Net Security
The Cloudflare Blog
U
Unit 42

博客园 - bamb00

PDF 解析为什么难:一份面向 RAG 的问题清单与解决路线 一个项目带你入门AI应用开发08 一个项目带你入门AI应用开发08 一个项目带你入门AI应用开发课程介绍 一个项目带你入门AI应用开发07 一个项目带你入门AI应用开发06 一个项目带你入门AI应用开发05 一个项目带你入门AI应用开发05 一个项目带你入门AI应用开发04 一个项目带你入门AI应用开发03 一个项目带你入门AI应用开发01 3・15 曝光 AI 安全暗礁:企业如何筑牢投毒与幻觉防护墙 CodeQL学习——导航调用图 CodeQL学习——java程序抽象语法树 linux进程隐藏手段及对抗方法 OAuth2.0安全设计之Authorization Code CodeQL学习——CodeQl数据流分析 CodeQL学习——CodeQL java库 CodeQL学习——自定义查询 CodeQL学习——CodeQL CLI入门 用户中心 - 博客园 浏览器解析js intent 参数的规范 Fiddler如何自动修改请求和响应包 Burp Suite学习之Intruder的4种攻击模式 对Android系统权限的认识 "INSTALL_FAILED_DUPLICATE_PERMISSION "错误解决 Android hook神器frida(二) 移动广告作弊技术研究 Android如果有一个任意写入的漏洞,如何将写权限转成执行权限
一个项目带你 入门AI应用开发02
bamb00 · 2026-08-01 · via 博客园 - bamb00

第 2 课:让程序理解用户的意图

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 返回了一个未定义的意图名称,你的系统会怎么处理?"