你的词槽提取任务属于典型的**意图识别+槽位填充(Intent Detection & Slot Filling)**问题。这是NLP中的核心任务,目标是从用户对话中识别不同的槽位,对应用户查询的不同参数。对于外卖场景,需要处理复杂的商业逻辑和多轮对话。
展开代码用户输入 → 意图识别 → 词槽提取 → 后处理校验 → 结果返回 ↓ ↓ ↓ ↓ ↓ 预处理 链式提示 结构化 程序逻辑 最终结果 工程 输出 校正
第一层:意图识别层
第二层:词槽提取层
第三层:后处理校验层
步骤1:意图识别提示词
展开代码你是一个外卖订餐助手,需要识别用户意图。 用户可能的意图包括: - 外卖下单:想要点外卖订餐 - 再来一单:重复之前的订单 - 搜索店铺:查找特定店铺 - 其他 请分析以下用户输入的意图: 用户输入:{user_query} 返回JSON格式: { "intent": "外卖下单|再来一单|搜索店铺|其他", "confidence": 0.95 }
步骤2:基于意图的词槽提取提示词
展开代码你是专业的信息提取助手。用户意图是"外卖下单",请从用户输入中提取以下词槽: 必选词槽: - task_entry: 外卖/再来一单 - target_shops: 目标店铺名称列表,只支持1个元素 - target_products: 目标商品列表 可选词槽: - address: 收货地址 - filter_conditions: 筛选条件(如"神券商家","免配送费") - sort_type: 排序方式,归一化为:综合排序/距离优先/起送价优先/配送费优先/人均高到低/人均低到高 [其他词槽定义...] 提取规则: 1. 店铺名称:如果用户说"乡村的小鸡",店铺是"乡村",商品是"小鸡" 2. 不需要完整匹配,只提取用户明确提到的部分 3. 空值用null表示 用户输入:{user_query} 返回JSON格式: { "task_entry": "外卖", "target_shops": ["乡村"], "target_products": ["小鸡"], "address": null, ... }
1. 店铺名与商品名区分策略
通过语法结构和上下文模式识别:
2. 多轮对话处理
python展开代码# 伪代码示例
def extract_slots(user_query, conversation_history=None):
# 意图识别
intent = identify_intent(user_query)
# 选择对应的词槽提取模板
slot_template = get_slot_template(intent)
# 考虑对话历史的词槽提取
if conversation_history:
context_prompt = build_context_prompt(conversation_history)
result = llm_extract(user_query, slot_template, context_prompt)
else:
result = llm_extract(user_query, slot_template)
# 后处理
return post_process(result, intent)
使用结构化的提示词可以显著提高信息提取的准确性。关键技巧:
1. JSON Schema约束
展开代码请严格按照以下JSON schema返回结果: { "type": "object", "properties": { "target_shops": { "type": "array", "items": {"type": "string"}, "maxItems": 1 } } }
2. Few-shot示例
展开代码示例1: 输入:我想吃肯德基的炸鸡 输出:{"target_shops": ["肯德基"], "target_products": ["炸鸡"]} 示例2: 输入:来一份麦当劳的可乐和薯条 输出:{"target_shops": ["麦当劳"], "target_products": ["可乐", "薯条"]} 现在处理:{user_query}
3. 思维链推理
展开代码请按以下步骤分析: 1. 识别句子中的店铺相关词汇 2. 识别句子中的商品相关词汇 3. 根据语法结构判断归属关系 4. 输出最终结果 分析过程: {让模型展示推理过程} 最终结果: {JSON输出}
对于需要归一化的字段,使用映射表+大模型组合:
python展开代码# 地址标签归一化
ADDRESS_LABELS = {
"家里": "家", "家中": "家", "住址": "家",
"公司": "公司", "单位": "公司", "办公室": "公司",
"学校": "学校", "校园": "学校"
}
def normalize_address_label(raw_label):
# 先用映射表快速匹配
if raw_label in ADDRESS_LABELS:
return ADDRESS_LABELS[raw_label]
# 再用大模型处理边缘情况
prompt = f"将'{raw_label}'归一化为:家/学校/公司/父母家 中的一个"
return llm_normalize(prompt)
python展开代码def validate_slots(slots, intent):
errors = []
# 必选字段检查
required_fields = get_required_fields(intent)
for field in required_fields:
if not slots.get(field):
errors.append(f"缺少必选字段: {field}")
# 格式校验
if slots.get("phone_number"):
if not is_valid_phone(slots["phone_number"]):
errors.append("手机号格式错误")
# 业务逻辑校验
if slots.get("target_shops") and len(slots["target_shops"]) > 1:
errors.append("target_shops只支持1个元素")
return errors
python展开代码def post_process_slots(slots, user_query):
# 默认值填充
if not slots.get("sort_type"):
slots["sort_type"] = "综合排序"
if not slots.get("delivery_method"):
slots["delivery_method"] = "外卖配送"
# 智能纠错:如果店铺名可能是商品名
if slots.get("target_shops") and is_likely_product(slots["target_shops"][0]):
# 重新分析或标记需要用户确认
slots["_need_confirmation"] = True
return slots
你的方案核心思路完全正确:意图识别→词槽提取→程序校验的三步走策略是目前主流的解决方案。提示词工程确实是高效使用大语言模型的关键技能,特别适合你这种有明确业务逻辑的场景。
关键成功要素:
这种方案比传统的规则匹配更灵活,比完全依赖大模型更可控,是当前技术条件下的最优选择。
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!