电商问答助手
项目背景目标用户问商品/订单/售后问题助手自动回答答不了转人工。典型问题这个手机支持无线充电吗我的订单什么时候到七天无理由退货怎么操作这件衣服有没有 XL 码核心挑战问题类型杂商品咨询、订单查询、售后政策、闲聊需要实时数据库存、物流、订单不能瞎编幻觉客诉赔钱要高并发、低延迟一、整体架构text┌──────────────────────────────────────────────────────────┐ │ 用户端APP/网页 │ └────────────────────────┬─────────────────────────────────┘ ↓ ┌──────────────────────────────────────────────────────────┐ │ API 网关鉴权/限流 │ └────────────────────────┬─────────────────────────────────┘ ↓ ┌──────────────────────────────────────────────────────────┐ │ 对话管理服务Session │ │ 多轮上下文 / 用户画像 / 历史记录 │ └────────────────────────┬─────────────────────────────────┘ ↓ ┌──────────────────────────────────────────────────────────┐ │ 意图识别 路由核心大脑 │ │ 商品咨询 → RAG 订单查询 → API 售后 → 知识库 │ └───┬──────────┬──────────┬──────────┬────────────────────┘ ↓ ↓ ↓ ↓ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ RAG │ │ 业务API │ │ 知识库 │ │ 兜底 │ │ 向量库 │ │ 订单/物流│ │ FAQ │ │ 转人工 │ └────────┘ └────────┘ └────────┘ └────────┘ ↓ ↓ ↓ ↓ ┌──────────────────────────────────────────────────────────┐ │ LLM 生成Qwen/GLM vLLM 部署 │ └────────────────────────┬─────────────────────────────────┘ ↓ ┌──────────────────────────────────────────────────────────┐ │ 后处理合规过滤 / 格式化 / 引用 │ └────────────────────────┬─────────────────────────────────┘ ↓ 返回用户二、全链路 12 个环节环节 1需求拆解与场景定义做什么明确助手要解决哪些问题边界在哪。输出场景清单场景示例数据来源处理方式商品咨询支持快充吗商品详情RAG库存查询有货吗库存系统API订单查询到哪了订单系统API售后政策怎么退货政策文档RAG优惠咨询有什么券营销系统API闲聊你好—LLM 直接答投诉我要投诉—转人工关键决策✅ 哪些必须查实时数据不能靠模型编✅ 哪些可以模型直接答✅ 哪些必须转人工投诉、复杂售后坑场景没列全上线后被各种奇葩问题打穿边界不清模型乱答导致客诉环节 2数据准备电商问答助手需要四类数据2.1 商品知识库结构化json{ product_id: P10086, title: 小米14 Pro, attributes: { 屏幕: 6.73英寸 2K, 电池: 4880mAh, 充电: 120W有线 50W无线, 防水: IP68 }, description: ..., faq: [ {q: 支持无线充电吗, a: 支持50W 无线快充}, {q: 防水等级, a: IP68 级防水} ] }2.2 政策文档非结构化退换货政策运费规则保修条款发票说明2.3 历史对话用于微调json{messages: [ {role: user, content: 这个手机能无线充电吗}, {role: assistant, content: 小米14 Pro 支持 50W 无线快充需要搭配小米官方无线充电器使用。} ]}2.4 意图标注数据用于训练分类器json{text: 我的订单怎么还没发货, intent: order_status, slots: {order_id: null}} {text: 这个手机多少钱, intent: product_price, slots: {product: 手机}}数据工程要点商品数据要分块chunk每块 200-500 字政策文档按章节切保留标题层级历史对话要脱敏去掉手机号、地址意图标注要覆盖长尾别只标高频环节 3意图识别与路由这是整个系统的大脑决定问题走哪条路。方案 A小模型分类推荐用BERT或Qwen2.5-0.5B微调一个分类器pythonINTENTS [ product_query, # 商品咨询 stock_query, # 库存查询 order_status, # 订单状态 logistics, # 物流 return_refund, # 退换货 coupon, # 优惠券 complaint, # 投诉 chitchat, # 闲聊 other, # 其他 ]训练数据格式参考前面微调章节json{messages: [ {role: system, content: 你是意图分类器输出JSON。}, {role: user, content: 我的订单到哪了}, {role: assistant, content: {\intent\: \logistics\, \slots\: {\order_id\: null}}} ]}输出json{intent: logistics, confidence: 0.95, slots: {order_id: null}}方案 BLLM 直接判断用大模型 prompttext判断用户问题的意图从以下选项中选择 [商品咨询, 库存, 订单, 物流, 退换货, 优惠, 投诉, 闲聊, 其他] 用户我的订单到哪了 输出 JSON{intent: ..., confidence: 0-1}对比方案速度成本准确率适合小模型快10ms低高95%生产LLM慢500ms高高冷启动/复杂意图推荐小模型做一级路由LLM 做兜底和复杂意图。路由表pythonROUTING { product_query: rag, stock_query: api_stock, order_status: api_order, logistics: api_logistics, return_refund: rag_policy, coupon: api_coupon, complaint: human, chitchat: llm_direct, other: rag_general, }坑意图边界模糊退货和换货混多意图这个手机有货吗多少钱—— 需要拆解置信度低时要兜底环节 4检索增强生成RAG为什么需要模型不知道你家的商品和政策必须外挂知识。4.1 知识库构建流程text原始文档 ↓ 加载PDF/Word/数据库 ↓ 清洗去噪、去格式 ↓ 分块chunk ↓ Embedding向量化 ↓ 存入向量库4.2 分块策略策略说明适用固定长度512 字符切通用按段落按 \n\n 切政策文档按标题按章节切手册语义分块用模型判断边界高质量要求重叠切相邻块重叠 10-20%防止截断商品数据分块示例pythondef chunk_product(product): chunks [] # 属性单独一块 chunks.append({ text: f商品{product[title]}\n参数{format_attrs(product[attributes])}, metadata: {product_id: product[id], type: spec} }) # FAQ 每条一块 for faq in product[faq]: chunks.append({ text: f问{faq[q]}\n答{faq[a]}, metadata: {product_id: product[id], type: faq} }) return chunks4.3 向量化pythonfrom sentence_transformers import SentenceTransformer model SentenceTransformer(BAAI/bge-large-zh-v1.5) def embed(texts): return model.encode(texts, normalize_embeddingsTrue)推荐中文 Embedding模型维度特点BAAI/bge-large-zh-v1.51024中文强BAAI/bge-m31024多语言moka-ai/m3e-base768轻量阿里 text-embedding-v31024商用4.4 向量库选型库特点适合FAISS本地快小规模Milvus分布式生产Qdrant云原生生产Chroma轻量原型pgvector集成 PG已有 PG4.5 检索流程pythondef retrieve(query, top_k5, product_idNone): # 1. 查询向量化 q_vec embed([query])[0] # 2. 向量检索 filter_expr {product_id: product_id} if product_id else None results vector_store.search(q_vec, top_ktop_k, filterfilter_expr) # 3. 重排序可选 if reranker: pairs [(query, r[text]) for r in results] scores reranker.predict(pairs) results sorted(zip(results, scores), keylambda x: -x[1]) results [r for r, _ in results] return results4.6 混合检索推荐向量检索 BM25 关键词检索取长补短pythondef hybrid_retrieve(query, top_k5): vec_results vector_search(query, top_k) bm25_results bm25_search(query, top_k) # RRF 融合 merged reciprocal_rank_fusion(vec_results, bm25_results) return merged[:top_k]4.7 重排序Rerank向量检索召回 top-20用 Reranker 精排到 top-5pythonfrom FlagEmbedding import FlagReranker reranker FlagReranker(BAAI/bge-reranker-large, use_fp16True) def rerank(query, docs, top_k5): pairs [[query, d[text]] for d in docs] scores reranker.compute_score(pairs) ranked sorted(zip(docs, scores), keylambda x: -x[1]) return [d for d, _ in ranked[:top_k]]4.8 RAG 生成提示词text你是电商客服助手。根据以下资料回答用户问题。 【资料】 {retrieved_context} 【规则】 1. 只根据资料回答资料没有的信息说这个问题我需要帮您转人工 2. 不要编造商品参数、价格、政策 3. 回答简洁不超过 3 句话 4. 涉及具体订单/物流引导用户提供订单号 【用户问题】 {query} 【回答】坑检索不到相关内容 → 必须兜底不能让模型瞎编检索到错误内容 → 加 Reranker上下文太长 → 控制 top_k多商品混检索 → 加 product_id 过滤环节 5业务 API 对接为什么要 API库存、订单、物流是实时变化的不能靠 RAG。5.1 工具定义Function Callingpythontools [ { type: function, function: { name: query_stock, description: 查询商品库存, parameters: { type: object, properties: { product_id: {type: string, description: 商品ID}, sku: {type: string, description: 规格如颜色尺码} }, required: [product_id] } } }, { type: function, function: { name: query_order, description: 查询订单状态, parameters: { type: object, properties: { order_id: {type: string} }, required: [order_id] } } }, { type: function, function: { name: query_logistics, description: 查询物流轨迹, parameters: { type: object, properties: { order_id: {type: string} }, required: [order_id] } } } ]5.2 调用流程pythondef handle_with_tools(query, user_id, history): messages [{role: system, content: SYSTEM_PROMPT}] messages history messages.append({role: user, content: query}) # 1. LLM 决定调用哪个工具 response llm.chat(messages, toolstools, tool_choiceauto) # 2. 如果有工具调用 if response.tool_calls: tool_results [] for call in response.tool_calls: fn_name call.function.name args json.loads(call.function.arguments) # 3. 执行真实 API result execute_tool(fn_name, args, user_id) tool_results.append({ tool_call_id: call.id, role: tool, content: json.dumps(result, ensure_asciiFalse) }) # 4. 把结果喂回 LLM messages.append(response.message) messages.extend(tool_results) final llm.chat(messages) return final.content return response.content def execute_tool(name, args, user_id): if name query_order: # 权限校验只能查自己的订单 order order_service.get(args[order_id]) if order.user_id ! user_id: return {error: 无权访问该订单} return order.to_dict() elif name query_logistics: return logistics_service.track(args[order_id]) elif name query_stock: return stock_service.check(args[product_id], args.get(sku))5.3 安全要点✅权限校验只能查当前用户的订单✅参数校验order_id 格式、SQL 注入防护✅超时控制API 超时 3s失败降级✅敏感信息脱敏手机号、地址部分打码❌ 不要让 LLM 直接生成 SQL/URL环节 6多轮对话管理6.1 上下文管理pythonclass DialogueManager: def __init__(self, max_turns10): self.sessions {} # user_id - history self.max_turns max_turns def add(self, user_id, role, content): if user_id not in self.sessions: self.sessions[user_id] [] self.sessions[user_id].append({role: role, content: content}) # 保留最近 N 轮 if len(self.sessions[user_id]) self.max_turns * 2: self.sessions[user_id] self.sessions[user_id][-self.max_turns*2:] def get(self, user_id): return self.sessions.get(user_id, [])6.2 指代消解用户这个多少钱 → 这个指什么pythondef resolve_reference(query, history, current_productNone): # 如果 query 含指代词且上下文有商品 if any(w in query for w in [这个, 那个, 它]) and current_product: query query.replace(这个, current_product[title]) query query.replace(它, current_product[title]) return query6.3 槽位填充多轮补全信息text用户我要退货 助手请提供订单号 用户12345 助手[查询订单] → 处理退货pythonclass SlotFiller: def __init__(self): self.required { return_refund: [order_id], logistics: [order_id], stock_query: [product_id] } def check(self, intent, slots, history): missing [s for s in self.required.get(intent, []) if not slots.get(s)] if missing: return f请提供{missing[0]} return None环节 7LLM 生成7.1 模型选型场景推荐理由意图识别Qwen2.5-0.5B 微调快、省简单问答Qwen2.5-7B平衡复杂推理Qwen2.5-14B/72B质量成本敏感GLM-4-Flash免费7.2 部署参考前面的 vLLM 部署章节bashpython -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct \ --port 8000 \ --gpu-memory-utilization 0.9 \ --max-model-len 8192 \ --enable-prefix-caching7.3 生成参数pythongeneration_config { temperature: 0.3, # 客服要稳 top_p: 0.9, max_tokens: 512, repetition_penalty: 1.05, stop: [\n\n用户, \n\n【] }7.4 提示词模板text# 角色 你是{shop_name}的智能客服专业、友好、简洁。 # 当前用户 - 会员等级{vip_level} - 当前咨询商品{current_product} # 知识 {retrieved_context} # 工具结果 {tool_results} # 对话历史 {history} # 规则 1. 只根据知识回答不确定就转人工 2. 不承诺政策外的补偿 3. 涉及金额必须准确 4. 语气亲切用您 5. 回答不超过 3 句话 # 用户问题 {query} # 回答环节 8后处理与合规8.1 敏感词过滤pythonSENSITIVE [投诉, 举报, 12315, 曝光, 媒体] def check_sensitive(text): for w in SENSITIVE: if w in text: return True return False if check_sensitive(user_query): return 非常抱歉给您带来不好的体验正在为您转接人工客服...8.2 幻觉检测pythondef check_hallucination(answer, context): # 简单方案答案中的数字/价格是否在 context 中出现 numbers re.findall(r\d, answer) for n in numbers: if n not in context: return True # 可能有幻觉 return False8.3 格式规范化价格加 ¥时间统一格式去掉模型多余的自称8.4 引用来源pythonanswer f{llm_answer}\n\n参考{source_title}环节 9兜底与转人工9.1 兜底策略情况处理意图置信度 0.6转人工RAG 检索相似度 阈值转人工涉及投诉/退款转人工连续 3 轮没解决转人工LLM 拒答转人工pythondef should_transfer(intent_conf, rag_score, query, turn_count): if intent_conf 0.6: return True, 意图不明确 if rag_score 0.5: return True, 知识库无匹配 if any(w in query for w in [投诉, 退款, 举报]): return True, 敏感问题 if turn_count 3: return True, 多轮未解决 return False, None9.2 转人工流程pythondef transfer_to_human(user_id, reason, history): ticket create_ticket( user_iduser_id, reasonreason, historyhistory, priorityhigh if reason 敏感问题 else normal ) return f正在为您转接人工客服工单号{ticket.id}请稍候...环节 10评测体系10.1 离线评测意图识别准确率、F1、混淆矩阵RAG召回率KMRR、NDCG生成BLEU/ROUGE参考LLM-as-Judge推荐人工评估10.2 LLM-as-JudgepythonJUDGE_PROMPT 请评估以下客服回答的质量。 用户问题{query} 参考知识{context} 模型回答{answer} 评分维度1-5分 1. 准确性是否基于知识有无幻觉 2. 完整性是否解决用户问题 3. 友好度语气是否得体 输出 JSON{accuracy: 4, completeness: 5, friendliness: 4, reason: ...} def judge(query, context, answer): result judge_llm.chat(JUDGE_PROMPT.format( queryquery, contextcontext, answeranswer)) return json.loads(result)10.3 在线指标指标含义目标解决率未转人工且用户满意 70%转人工率转人工占比 30%首响时间TTFT 1s用户满意度点赞/点踩 85%平均对话轮数越少越好 310.4 A/B 测试pythondef ab_test(user_id): if hash(user_id) % 2 0: return v1 # 旧版 return v2 # 新版环节 11上线与监控11.1 灰度发布text5% 流量 → 观察 1 天 → 20% → 50% → 100%11.2 监控指标pythonmetrics { qps: ..., # 请求量 latency_p99: ..., # P99 延迟 error_rate: ..., # 错误率 intent_distribution: ..., # 意图分布 transfer_rate: ..., # 转人工率 rag_hit_rate: ..., # RAG 命中率 llm_token_usage: ..., # token 消耗 }11.3 日志pythonlog { user_id: user_id, query: query, intent: intent, confidence: conf, rag_docs: [d[id] for d in docs], answer: answer, latency_ms: latency, model: model_name, transfer: transferred, timestamp: time.time() }11.4 持续优化每周分析 badcase补充知识库补充训练数据调整提示词环节 12成本优化优化点方案效果模型小模型做意图大模型只做生成降 50%缓存相同问题缓存答案降 20%前缀缓存vLLM prefix caching降 30%量化AWQ/INT8 部署降 40%批处理Continuous Batching吞吐 5x限流按用户等级限流防滥用三、完整调用链路示例pythondef chat(user_id, query, session): t0 time.time() # 1. 获取上下文 history session.get(user_id) current_product session.get_current_product(user_id) # 2. 指代消解 query resolve_reference(query, history, current_product) # 3. 意图识别 intent_result intent_classifier.predict(query) intent, conf intent_result[intent], intent_result[confidence] # 4. 置信度低 → 兜底 if conf 0.6: return transfer_to_human(user_id, 意图不明确, history) # 5. 敏感词检查 if check_sensitive(query): return transfer_to_human(user_id, 敏感问题, history) # 6. 路由 route ROUTING[intent] if route rag or route rag_policy or route rag_general: # RAG 流程 docs hybrid_retrieve(query, product_idcurrent_product[id] if current_product else None) docs rerank(query, docs, top_k3) if not docs or docs[0][score] 0.5: return transfer_to_human(user_id, 知识库无匹配, history) context \n\n.join(d[text] for d in docs) answer llm_generate(query, context, history, current_product) elif route.startswith(api_): # 工具调用流程 answer handle_with_tools(query, user_id, history) elif route llm_direct: # 闲聊直接答 answer llm_chat(query, history) elif route human: return transfer_to_human(user_id, 用户要求, history) else: answer 抱歉我没理解您的问题请换个说法或转人工。 # 7. 后处理 answer post_process(answer) # 8. 保存历史 session.add(user_id, user, query) session.add(user_id, assistant, answer) # 9. 日志 log_request(user_id, query, intent, conf, answer, time.time() - t0) return answer四、踩坑清单坑后果解决没做意图识别直接 RAG订单问题也去查知识库先分类再路由RAG 检索不设阈值检索到无关内容模型瞎答设相似度阈值低了转人工不做幻觉检测编造价格/政策客诉数字校验 引用来源不脱敏泄露用户隐私手机号/地址打码不做权限校验用户 A 查用户 B 订单每次 API 调用校验 user_id上下文无限增长token 爆炸、成本高只保留最近 N 轮不设超时API 卡死整个对话所有外部调用设超时没监控出问题不知道全链路埋点不做灰度上线即事故5% → 100%提示词写太长小模型跟不动精简 Few-shot五、技术选型总结模块推荐方案备选意图识别Qwen2.5-0.5B 微调BERT、LLMEmbeddingBAAI/bge-large-zh-v1.5m3e、text-embedding-v3向量库Milvus / QdrantFAISS、pgvectorRerankerBAAI/bge-reranker-largeCohere RerankLLMQwen2.5-7B-InstructGLM-4、DeepSeek推理框架vLLMSGLang、TensorRT-LLM量化AWQGPTQ、INT8对话管理Redis 自研LangChain Memory监控Prometheus Grafana阿里云 ARMS六、一句话总结全链路text用户提问 → 意图识别小模型 → 路由分发 ├─ 商品/政策 → RAG向量BM25重排 ├─ 订单/物流 → 工具调用API ├─ 闲聊 → LLM 直答 └─ 敏感/不懂 → 转人工 → LLM 生成vLLM 部署 → 后处理合规/幻觉检测 → 返回用户 → 埋点监控 → 持续优化
上一篇/下一篇内容由系统自动关联
返回资讯列表 →