[控场AI]
· 10 分钟阅读· 5,430 字

超越提示词工程:构建意图感知的AI智能体

超越提示词工程:构建意图感知的AI智能体

把意图分类放在LLM调用之前、按意图分层检索上下文并显式管理状态,才是智能体成功的关键。

文章指出,大多数已部署的AI智能体在静默失败,根源不在提示词质量,而在意图识别与上下文管理。作者主张将意图分类作为轻量级中间件放在昂贵LLM调用之前,用正则或量化小模型降低成本和延迟;再按检测到的意图路由到不同的分层上下文检索管线,并为主、次、兜底数据源设定超时与降级策略。同时用结构化状态对象替代全量对话历史传递,只保留实体、检索记录与决策历史。最后强调置信度阈值与显式降级机制,宁可澄清也不猜测。作者建议从单一的意图分类层起步,逐步搭建真正的上下文感知架构。

Building Context-Aware AI Agents That Understand User Intent: Beyond Simple Prompt Engineering

大多数已部署的AI智能体在静默中失败。用户提出一个需求,智能体检索到无关上下文,然后返回一个听起来合理但实际错误的答案。一个真正能交付价值的智能体与单纯包装LLM的壳之间的差异,在于意图识别与上下文管理,而非提示词质量。Anthropic、OpenAI以及数十家初创公司正在专门招聘"AI智能体工程师",正是因为基础的提示词工程无法规模化。你需要系统性的方法来理解用户真正想要什么、检索正确的上下文并果断行动。

意图分类必须在LLM调用之前完成

意图识别不应该在每次调用时都交给LLM处理。每一次LLM调用都消耗token、增加延迟并产生费用。更合理的做法是构建一个轻量级分类器,让它位于上游。

以一个客服智能体为例。用户写道:"我的订单还没到,我周五之前需要它。"表面请求是查询物流信息,但真实意图其实是紧迫性解决。一个幼稚的智能体会检索订单历史然后就停下了。而一个上下文感知的智能体会识别出意图是截止日期驱动的,进而展示加急配送选项或退款资格。

from enum import Enum

class SupportIntent(Enum):
    ORDER_STATUS = "order_status"
    URGENT_DELIVERY = "urgent_delivery"
    REFUND_REQUEST = "refund_request"
    PRODUCT_INQUIRY = "product_inquiry"

def classify_intent(user_message: str) -> tuple[SupportIntent, float]:
    # 使用小型微调模型或基于规则分类器
    # 在本地快速运行,而非调用GPT-4
    keywords = {
        "urgent|asap|deadline|friday|today": SupportIntent.URGENT_DELIVERY,
        "where|tracking|arrived|status": SupportIntent.ORDER_STATUS,
        "refund|return|money back": SupportIntent.REFUND_REQUEST,
    }
    for pattern, intent in keywords.items():
        if re.search(pattern, user_message.lower()):
            return intent, 0.85
    return SupportIntent.PRODUCT_INQUIRY, 0.6

这个分类器可以使用正则模式、轻量级sklearn模型,甚至一个较小的量化LLM。关键是:在昂贵的LLM调用之前运行它,然后将用户消息与检测到的意图路由到上下文检索模块。

可操作要点: 将意图分类步骤添加为中间件。记录意图预测与实际用户结果以衡量准确率。当精确率低于85%时,重新训练。

**量化模型(Quantized Model)**是指将深度学习模型原本的 FP32/FP16 浮点权重压缩为 INT8 甚至 INT4 等低比特表示,从而把模型体积缩小数倍、推理延迟降低数倍的技术。文中提到的"50MB 量化模型"指的正是这类可本地运行的小模型,典型代表有 Qwen、Phi、Gemma 的 INT4 版本。量化通常带来 1%–3% 的精度损失,但对意图分类这种标签空间有限的判别任务几乎无感。相比调用 GPT-4 这类云端大模型,量化小模型可完全离线、单次推理在毫秒级、无需按 token 付费,非常适合放在上游做"守门人"。要注意量化分为训练后量化(PTQ)和量化感知训练(QAT),生产环境一般优先 PTQ 以求快速落地,当精度不达标时再回退到 QAT。

基于意图的分层上下文检索

一旦明确了意图,就可以有针对性地检索上下文。不同意图需要不同数据源、不同时间窗口和不同访问模式。

一个财务顾问智能体面对"我该怎么处理这5万美元?"需要投资组合历史、市场状况和风险画像。而另一个查询"我的存款到账了吗?"需要过去48小时的交易日志。两者访问不同数据库,采用不同查询模式和延迟要求。

将上下文检索结构化为意图专属管线:

Intent: urgent_delivery
├─ Primary: Order status (DynamoDB, <100ms)
├─ Secondary: Shipping partner API (network call, <500ms)
├─ Tertiary: Customer tier/VIP status (cache, <50ms)
└─ Fallback: Previous support tickets (search index)

Intent: refund_request
├─ Primary: Transaction record (database)
├─ Secondary: Refund policy version (config store)
├─ Tertiary: Similar refund decisions (vector search on previous cases)
└─ Fallback: Manager escalation template

每条管线都设置有超时和降级行为。如果DynamoDB响应缓慢,就转向次级数据源。如果所有数据源都失败,智能体应明确告知,而不是产生幻觉。Stripe的API错误处理就遵循这一模式:主端点、备用区域、超时截断、优雅降级。将同样的严谨性应用于智能体的上下文检索。

可操作要点: 将你的前5个意图映射到各自所需的上下文源。为每条管线设定SLA目标(p99延迟、缓存命中率)。每周进行监控和测量。

**向量搜索(Vector Search)**是把文本、图像等非结构化数据编码为高维向量(embedding),再用近似最近邻(ANN)算法检索语义相似项的技术,常用实现有 FAISS、Milvus、Pinecone、pgvector。文中"Similar refund decisions (vector search on previous cases)"的场景下,原始工单被 embedding 模型(如 text-embedding-3、bge-m3)转成向量后写入索引,新的退款请求到来时用相同模型编码,取 Top-K 最相似的历史案例及其审批结论作为参考。相比关键词倒排索引,向量搜索能捕捉"鼠标坏了"与"光标无法移动"这类字面不同但语义相同的表达。代价是它需要额外的 embedding 服务和索引维护成本,因此文中把它放在 Tertiary 层级——只有主路径数据源不足时才回退使用,以控制延迟与费用。

状态管理与记忆窗口

上下文感知智能体需要记忆。不是幻觉记忆,而是跨轮次持久化的实际结构化状态。当用户说"为那个创建一张发票"时,"那个"指的是三轮之前提到的内容。

大多数基于提示词的智能体通过将完整对话历史倾倒入上下文来处理这个问题。这既浪费又引入噪音。更好的做法是维护显式状态:

class AgentState:
    user_id: str
    current_intent: SupportIntent
    conversation_id: str
    extracted_entities: dict  # {"amount": 50000, "product": "laptop"}
    context_retrieved: dict   # 获取了什么以及何时获取
    decision_history: list    # 先前的操作与结果
    timestamp: float

def update_state(state: AgentState, llm_response: str, user_input: str):
    # 从响应中提取实体(结构化输出,而非自由文本)
    entities = extract_entities(llm_response)
    state.extracted_entities.update(entities)
    
    # 记录决策以供审计
    state.decision_history.append({
        "action": llm_response,
        "timestamp": time.time(),
        "confidence": get_confidence_score(llm_response)
    })

当下一个轮次需要上下文时,查询这个状态对象,而非完整对话。只传递相关的先前决策,不传递聊天噪音。GitHub Copilot的代码生成就是这样工作的:它不分析代码库的每一行,而是分析编辑器中打开的特定文件以及这些文件的git变更历史。

可操作要点: 将智能体状态存储为带时间戳、可查询的格式(键值存储中的JSON即可)。除非显式刷新,状态在24小时后过期。对状态模式进行版本管理。

**实体抽取(Entity Extraction)**是从非结构化文本中识别出结构化字段(人名、金额、订单号、产品名等)的任务,属于信息抽取的核心子问题。文中 extract_entities 之所以强调"结构化输出,而非自由文本",是因为直接解析 LLM 自然语言回复来更新状态非常脆弱——模型措辞稍有变化、多写一个逗号就可能让下游解析失败。工程上通常采用三种方式获取稳定结构:一是让 LLM 以 JSON Schema 或函数调用(tool call)格式返回;二是用专门的抽取模型(如 spaCy NER、GLiNER);三是对高频字段做正则兜底。抽取结果写入 state.extracted_entities 后,后续轮次可直接读取 amount、order_id 等字段,无需再把整段对话塞回上下文,从而显著降低 token 消耗并提升可审计性。

错误恢复与显式降级

上下文感知智能体要么优雅失败,要么大声失败。它们不会静默失败。

当智能体无法检索所需上下文时,应该明确说明。当置信度低于阈值时,应该升级处理。当存在歧义时,应该提出澄清问题而非猜测。

def should_proceed_with_action(state: AgentState, confidence: float) -> bool:
    MIN_CONFIDENCE = 0.75
    REQUIRED_CONTEXT = ["customer_id", "order_id"]
    
    if confidence < MIN_CONFIDENCE:
        return False  # 请求澄清
    missing = [key for key in REQUIRED_CONTEXT if key not in state.extracted_entities]
    if missing:
        return False  # 获取缺失上下文或询问用户
    return True

# 在智能体循环中:
if should_proceed_with_action(state, confidence):
    execute_action(state)
else:
    agent_response = generate_clarification_prompt(state, missing_context)

这防止了误判。它比总是执行要慢,但对信任度而言好上100倍。

可操作要点: 为每种意图类型定义最低置信度阈值。记录每一次降级决策。设定目标:用户交互中需要澄清的比例应低于5%。

从意图分类开始本周行动

你不需要重建整个智能体架构。从添加一个层开始:在LLM调用之前进行意图分类。选择你的前3个用例,为每个定义5-7个意图,然后使用正则或50MB量化模型构建分类器。测量它的准确率。当它表现稳定后,用意图路由到不同的上下文源。

这一个改变——按意图路由上下文而非将所有查询一视同仁——就是用户勉强容忍的智能体与真正有效工作的智能体之间的分水岭。

#AI智能体#意图识别#上下文感知#提示词工程#意图分类#上下文检索#LLM应用#状态管理
分享:

相关推荐