摘要

大语言模型在电商智能客服场景中,因训练数据的知识时滞、注意力机制失控等问题,频繁出现商品属性混淆、政策解读错误等“幻觉”现象,严重威胁业务合规性与用户体验。本文提出“RAG检索增强+人工兜底”的双层治理方案,从知识增强检索、动态上下文管理、幻觉检测与人工兜底三个维度构建防御体系。配套提供基于LangGraph的多Agent客服系统完整代码,涵盖意图分类、RAG知识库检索、Function Calling工具调用、工单升级与人工兜底等核心流程,为企业构建可信赖的AI客服系统提供可落地的技术方案。

关键词:大模型幻觉;RAG检索增强;智能客服;人工兜底;LangGraph;Function Calling

一、引言:智能客服的“幻觉危机”

1.1 从技术缺陷到业务事故

大语言模型在电商智能客服场景中的幻觉问题,已从技术层面的“小瑕疵”演变为真实的业务风险。据Gartner调查显示,68%的企业曾遭遇智能客服因幻觉导致的业务事故,平均每次造成客户流失率上升19%。

在某电商平台“618”大促期间,某品牌智能客服因将“7天无理由退货”政策错误解读为“仅支持质量问题退货”,导致327笔订单产生纠纷,直接经济损失超过45万元。这并非个案——类似的政策混淆、商品属性错误、价格信息偏差等问题,正频繁出现在各类AI客服系统的生产日志中。

1.2 幻觉的三大典型表现

事实性错误:生成与客观事实相悖的内容。例如将“iPhone 14 Pro支持240Hz刷新率”这类明显错误信息呈现给用户,或混淆“美白”和“亮白”两种化妆品功效。

逻辑矛盾:在多轮对话中出现前后不一致的推理。例如先建议“上午游览故宫”,后推荐“故宫闭馆前1小时参观”,两者存在根本性冲突。

知识断层与政策混淆:将过时或错误的知识应用于当前场景。某金融客服系统的监控数据显示,在处理复杂查询时,传统LLM模型的幻觉发生率高达27%。

1.3 幻觉的技术根源

大语言模型的幻觉本质是注意力机制的失控。Transformer架构的解码过程存在两个致命缺陷:

  • 知识时滞:训练数据截止后,模型无法获取最新产品信息、促销政策等动态知识。
  • 概率性推理偏差:模型基于统计规律生成内容,可能因训练数据中的高共现概率而忽略用户实际描述的关键特征,生成错误解决方案。

此外,在客服场景中,LLM直接基于对话记录学习面临噪声干扰大、不同客服人员风格不一致等障碍,而显式标注人工推理过程又成本高昂且难以泛化。

二、治理方案总览:三层防御架构

针对上述问题,本文提出“RAG检索增强+动态知识管理+人工兜底”三层防御架构:

层级 核心机制 目标
第一层:知识增强检索 RAG + 企业知识库 动态注入最新知识,从源头抑制幻觉
第二层:动态上下文与工具调用 Function Calling + 结构化数据查询 以确定性数据替代模型“猜测”
第三层:幻觉检测与人工兜底 置信度评估 + 工单升级 阻断幻觉输出,转交人工处理

核心设计理念是:将LLM从“知识源”降级为“理解与生成引擎”,所有事实性信息从可验证的知识库和业务系统中获取。 这一思路与字节跳动OlaMind框架“学习思考、学习回应”的两阶段方法论以及其构建的幻觉裁判系统方向一致——通过人机协作完成幻觉检测,疑似幻觉样本由人工评判,确认无误的困难样本再重新注入系统提升检测准确率。

三、RAG检索增强:第一道防线

3.1 RAG如何抑制幻觉

RAG(Retrieval-Augmented Generation)通过“检索+生成”双阶段架构实现动态知识注入:检索模块从企业私有知识库获取精准信息,生成模块结合检索结果与大模型能力输出回答。这种架构使系统具备三大优势:

  • 知识时效性:实时更新企业文档即可同步至客服系统,无需重新训练模型
  • 回答准确性:通过检索约束生成空间,大幅降低幻觉风险
  • 成本可控性:无需全量微调,仅需优化检索策略

某金融客户案例显示,采用RAG架构后,知识库更新效率提升80%,复杂问题解决率从62%提升至89%。

3.2 RAG知识库构建实战

# rag_knowledge_base.py RAG知识库构建与检索模块
import json
import hashlib
from pathlib import Path
from typing import List, Dict, Optional
import numpy as np
from sentence_transformers import SentenceTransformer
import chromadb
from chromadb.config import Settings

class KnowledgeBase:
    """企业知识库RAG检索模块"""
    
    def __init__(self, persist_dir: str = "./chroma_db"):
        # 使用本地Embedding模型,零成本、全隐私
        self.embedder = SentenceTransformer('all-MiniLM-L6-v2')
        
        # 初始化ChromaDB持久化客户端
        self.client = chromadb.PersistentClient(
            path=persist_dir,
            settings=Settings(allow_reset=True)
        )
        self.collection = self.client.get_or_create_collection("knowledge_base")
        self.doc_metadata = {}  # 存储文档元信息
        
    def chunk_document(self, text: str, chunk_size: int = 512, overlap: int = 100) -> List[str]:
        """文档分块策略,防止信息截断"""
        sentences = text.replace('\n', '。').split('。')
        chunks = []
        current_chunk = []
        current_len = 0
        
        for sent in sentences:
            sent_len = len(sent)
            if current_len + sent_len > chunk_size and current_chunk:
                chunks.append('。'.join(current_chunk) + '。')
                # 保留重叠部分
                overlap_text = '。'.join(current_chunk[-2:]) if len(current_chunk) >= 2 else current_chunk[0]
                current_chunk = [overlap_text] if overlap_text else []
                current_len = len(overlap_text)
            current_chunk.append(sent)
            current_len += sent_len
            
        if current_chunk:
            chunks.append('。'.join(current_chunk) + '。')
        return chunks
    
    def index_documents(self, docs: List[Dict], source_name: str):
        """
        索引知识文档
        docs格式: [{"id": "P001", "content": "...", "category": "退货政策"}, ...]
        """
        for doc in docs:
            chunks = self.chunk_document(doc["content"])
            for i, chunk in enumerate(chunks):
                chunk_id = f"{source_name}_{doc['id']}_{i}"
                embedding = self.embedder.encode(chunk).tolist()
                
                self.collection.upsert(
                    ids=[chunk_id],
                    embeddings=[embedding],
                    metadatas=[{
                        "source": source_name,
                        "doc_id": doc["id"],
                        "category": doc.get("category", ""),
                        "chunk_index": i
                    }],
                    documents=[chunk]
                )
                self.doc_metadata[chunk_id] = {
                    "source": source_name,
                    "doc_id": doc["id"],
                    "category": doc.get("category", "")
                }
        print(f"已索引{len(docs)}个文档,共{len(self.doc_metadata)}个分块")
    
    def retrieve(self, query: str, top_k: int = 5, category_filter: Optional[str] = None) -> List[Dict]:
        """检索最相关的知识片段"""
        query_embedding = self.embedder.encode(query).tolist()
        
        # 构建过滤条件
        where_filter = {"category": category_filter} if category_filter else None
        
        results = self.collection.query(
            query_embeddings=[query_embedding],
            n_results=top_k,
            where=where_filter
        )
        
        retrieved = []
        if results['documents'] and results['documents'][0]:
            for i, doc in enumerate(results['documents'][0]):
                retrieved.append({
                    "content": doc,
                    "score": results['distances'][0][i] if results.get('distances') else None,
                    "metadata": self.doc_metadata.get(results['ids'][0][i], {})
                })
        return retrieved
    
    def load_policy_documents(self, policy_dir: str):
        """加载政策文档(退货政策、配送说明、会员规则等)"""
        policy_dir = Path(policy_dir)
        docs = []
        for file_path in policy_dir.glob("*.md"):
            content = file_path.read_text(encoding="utf-8")
            docs.append({
                "id": file_path.stem,
                "content": content,
                "category": "policy"
            })
        self.index_documents(docs, "policy")
        print(f"已加载{len(docs)}个政策文档")
    
    def load_product_documents(self, product_file: str):
        """加载产品知识文档"""
        with open(product_file, 'r', encoding='utf-8') as f:
            products = json.load(f)
        docs = []
        for product in products:
            # 构建产品描述文本
            content = f"""
            产品名称:{product.get('name', '')}
            产品类型:{product.get('category', '')}
            价格:{product.get('price', '')}
            库存:{product.get('stock', '')}
            描述:{product.get('description', '')}
            适用场景:{product.get('usage', '')}
            """
            docs.append({
                "id": product.get('id', ''),
                "content": content,
                "category": "product"
            })
        self.index_documents(docs, "product")
        print(f"已加载{len(docs)}个产品文档")


# 使用示例
if __name__ == "__main__":
    kb = KnowledgeBase()
    
    # 加载政策文档
    kb.load_policy_documents("./data/policies/")
    
    # 加载产品文档
    kb.load_product_documents("./data/products.json")
    
    # 检索测试
    results = kb.retrieve("退货政策是什么?", top_k=3)
    for r in results:
        print(f"[分数:{r['score']:.3f}] {r['content'][:100]}...")

四、Function Calling与确定性数据:第二道防线

4.1 用确定性数据取代模型猜测

RAG解决了文档知识的检索问题,但对于订单查询、物流追踪、库存查询等结构化数据场景,仍需通过Function Calling对接业务系统,以确定性数据取代LLM的“猜测”。

核心原则是:LLM只负责理解用户意图、提取参数,具体数据查询由确定性函数完成,函数返回结果直接用于回答生成,不留幻觉空间

4.2 工具函数定义与实现

# tool_functions.py 客服工具函数定义
from datetime import datetime, timedelta
from typing import Optional, List, Dict
import json

# ============ 模拟业务数据 ============
# 实际生产环境对接CRM、订单系统、ERP等

MOCK_ORDERS = {
    "ORD-001": {"status": "已发货", "物流": "顺丰SF123456", "商品": "iPhone 15", "下单时间": "2026-07-10"},
    "ORD-002": {"status": "待发货", "物流": None, "商品": "MacBook Pro", "下单时间": "2026-07-15"},
}

MOCK_CUSTOMERS = {
    "C1001": {"name": "张三", "return_count": 2, "max_returns": 5},
}

# ============ 工具函数定义(供LLM调用) ============

def get_customer_info(customer_id: str) -> Dict:
    """查询客户信息,包括姓名、订单数、退货次数等"""
    if customer_id in MOCK_CUSTOMERS:
        return {"success": True, "data": MOCK_CUSTOMERS[customer_id]}
    return {"success": False, "error": "客户不存在"}

def get_order_info(order_id: str) -> Dict:
    """查询订单状态和物流信息"""
    if order_id in MOCK_ORDERS:
        return {"success": True, "data": MOCK_ORDERS[order_id]}
    return {"success": False, "error": "订单不存在"}

def check_refund_eligibility(order_id: str, days_ago: int, item_condition: str) -> Dict:
    """
    检查退货资格
    规则:30天内 + 未使用/全新
    """
    if order_id not in MOCK_ORDERS:
        return {"success": False, "error": "订单不存在", "eligible": False}
    
    # 检查退货窗口(模拟:假设30天内可退)
    if days_ago > 30:
        return {"eligible": False, "reason": f"已超出30天退货窗口(已{days_ago}天)"}
    
    # 检查商品状态
    if item_condition.lower() not in ["unused", "全新", "未使用"]:
        return {"eligible": False, "reason": "商品已使用,不符合退货条件"}
    
    return {"eligible": True, "reason": "符合退货条件"}

def get_product_info(product_name: str) -> Dict:
    """查询产品详情"""
    # 实际从产品数据库查询,此处使用RAG知识库
    # 返回结构化产品信息供LLM引用
    MOCK_PRODUCTS = {
        "iphone 15": {"id": "P001", "price": 5999, "stock": 100, "description": "支持灵动岛、A16芯片"},
        "macbook pro": {"id": "P002", "price": 14999, "stock": 50, "description": "M3 Pro芯片、16GB内存"},
    }
    for key, info in MOCK_PRODUCTS.items():
        if product_name.lower() in key:
            return {"success": True, "data": info}
    return {"success": False, "error": "产品不存在"}


# ============ Function Call Schema定义 ============
# 用于向LLM注册可用工具

TOOL_SCHEMAS = [
    {
        "type": "function",
        "function": {
            "name": "get_customer_info",
            "description": "通过客户ID查询客户基本信息(姓名、退货次数等)",
            "parameters": {
                "type": "object",
                "properties": {
                    "customer_id": {"type": "string", "description": "客户唯一标识ID"}
                },
                "required": ["customer_id"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_order_info",
            "description": "通过订单号查询订单状态和物流信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {"type": "string", "description": "订单号"}
                },
                "required": ["order_id"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "check_refund_eligibility",
            "description": "检查订单是否符合退货条件,需提供订单号、购买天数和商品状态",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {"type": "string", "description": "订单号"},
                    "days_ago": {"type": "integer", "description": "购买距今天数"},
                    "item_condition": {"type": "string", "description": "商品状态:unused/used/opened"}
                },
                "required": ["order_id", "days_ago", "item_condition"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_product_info",
            "description": "通过产品名称查询产品详细信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "product_name": {"type": "string", "description": "产品名称"}
                },
                "required": ["product_name"]
            }
        }
    }
]

# 函数名到实际函数的映射
FUNCTION_MAP = {
    "get_customer_info": get_customer_info,
    "get_order_info": get_order_info,
    "check_refund_eligibility": check_refund_eligibility,
    "get_product_info": get_product_info,
}

4.3 确定性决策 vs LLM猜测

在合规敏感的场景(如退货审批、退款金额计算)中,应采用确定性规则而非依赖LLM的推理能力。开源项目RefundGuard的设计原则值得借鉴:LLM负责处理用户输入的语义理解(提取订单号、购买天数、商品状态等),而审批决策由确定性规则执行——这种分工保证了对合规敏感场景的零幻觉保障。

五、幻觉检测与人工兜底:第三道防线

5.1 置信度评估与疑似幻觉检测

# hallucination_detector.py 幻觉检测与兜底机制
from typing import Dict, List, Optional
import re

class HallucinationDetector:
    """幻觉检测与兜底控制器"""
    
    def __init__(self, confidence_threshold: float = 0.85):
        self.threshold = confidence_threshold
        
        # 幻觉特征正则
        self.uncertainty_patterns = [
            r"(可能|也许|大概|好像|似乎是)",  # 不确定性表达
            r"(我不确定|我不清楚|我不知道)",  # 知识不足
            r"(没有找到|无法查询|暂无信息)",  # 检索失败
        ]
    
    def detect_uncertainty(self, response: str) -> float:
        """检测回答中的不确定性表达"""
        score = 0.0
        for pattern in self.uncertainty_patterns:
            if re.search(pattern, response):
                score += 0.2
        return min(score, 1.0)
    
    def check_factual_consistency(self, response: str, retrieved_docs: List[Dict]) -> float:
        """
        检测回答与检索知识的一致性
        若回答包含知识库中没有的信息,可能为幻觉
        """
        if not retrieved_docs:
            return 0.5  # 无检索结果,风险中等
        
        # 提取回答中的关键事实(简化:检查是否在检索文档中出现)
        # 实际可用更复杂的NLI模型或嵌入相似度
        combined_knowledge = " ".join([d["content"] for d in retrieved_docs])
        
        # 检查回答中的关键句是否能在知识库中找到支撑
        sentences = [s.strip() for s in response.split('。') if len(s) > 10]
        matched = 0
        for sent in sentences[:5]:
            if any(kw in combined_knowledge for kw in sent.split(',')[:3]):
                matched += 1
        
        return matched / max(len(sentences[:5]), 1)
    
    def evaluate(self, response: str, retrieved_docs: List[Dict], 
                 tool_results: Optional[List[Dict]] = None) -> Dict:
        """
        综合评估回答质量,判断是否需要人工兜底
        """
        uncertainty_score = self.detect_uncertainty(response)
        consistency_score = self.check_factual_consistency(response, retrieved_docs)
        
        # 如果有工具调用结果,优先信任结构化数据
        has_tool_result = tool_results and any(r.get("success", False) for r in tool_results)
        
        # 综合评分
        if has_tool_result:
            # 工具返回确定性数据,风险低
            confidence = 0.95
        else:
            confidence = 0.5 * (1 - uncertainty_score) + 0.5 * consistency_score
        
        needs_escalation = confidence < self.threshold
        
        return {
            "confidence": round(confidence, 3),
            "needs_escalation": needs_escalation,
            "uncertainty_score": uncertainty_score,
            "consistency_score": consistency_score,
            "reason": "置信度低于阈值" if needs_escalation else "回答可信"
        }

5.2 工单升级与人工兜底

# escalation.py 工单升级与兜底逻辑
from datetime import datetime
import json
from typing import Dict, List

class EscalationManager:
    """人工兜底与工单管理"""
    
    def __init__(self):
        self.tickets = []
        self.ticket_counter = 0
    
    def create_escalation_ticket(self, user_query: str, agent_response: str, 
                                  evaluation: Dict, chat_history: List[Dict]) -> Dict:
        """
        创建人工升级工单
        用于高置信度场景自动转人工
        """
        self.ticket_counter += 1
        ticket = {
            "ticket_id": f"TKT-{self.ticket_counter:04d}",
            "created_at": datetime.now().isoformat(),
            "user_query": user_query,
            "agent_response": agent_response,
            "evaluation": evaluation,
            "chat_history": chat_history[-5:],  # 最近5轮对话
            "status": "pending",
            "priority": "high" if evaluation.get("confidence", 0) < 0.6 else "medium"
        }
        self.tickets.append(ticket)
        return ticket
    
    def get_human_fallback_response(self, ticket: Dict) -> str:
        """生成人工转接话术"""
        return f"""
        非常抱歉,您的问题较为复杂,需要人工客服为您处理。
        
        已为您生成工单:{ticket['ticket_id']}
        工单内容摘要:{ticket['user_query'][:50]}...
        
        我们的客服人员将在30分钟内与您联系。
        您也可以主动拨打客服热线 400-XXX-XXXX 咨询。
        
        感谢您的理解与耐心!
        """
    
    def auto_escalate(self, user_query: str, agent_response: str, 
                      evaluation: Dict, chat_history: List[Dict]) -> Dict:
        """自动升级入口"""
        if evaluation.get("needs_escalation", False):
            ticket = self.create_escalation_ticket(
                user_query, agent_response, evaluation, chat_history
            )
            return {
                "escalated": True,
                "ticket": ticket,
                "response": self.get_human_fallback_response(ticket)
            }
        return {
            "escalated": False,
            "response": agent_response
        }

六、完整系统集成:基于LangGraph的多Agent客服

6.1 系统架构总览

基于LangGraph的多Agent智能客服系统,将意图分类、RAG检索、工具调用、工单升级整合为统一工作流:

用户 → Router Agent(意图分类) → 条件路由
    ├── 知识类 → Knowledge Agent(RAG检索) → Summary Agent
    ├── 业务类 → Tool Agent(Function Calling) → Summary Agent  
    └── 投诉类 → Escalation Agent(工单生成) → Summary Agent
                                         ↓
                              Hallucination Detector(置信度评估)
                                         ↓
                              高置信度 → 直接回复
                              低置信度 → 人工兜底

6.2 核心工作流实现

# customer_service_agent.py 基于LangGraph的多Agent客服系统
from typing import TypedDict, List, Dict, Literal
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage
import json

# ============ 状态定义 ============
class AgentState(TypedDict):
    messages: List[Dict]
    user_query: str
    intent: str  # order_query / product_inquiry / complaint / general
    retrieved_docs: List[Dict]
    tool_results: List[Dict]
    agent_response: str
    confidence: float
    needs_escalation: bool

# ============ 初始化LLM ============
llm = ChatOpenAI(
    model="deepseek-chat",  # 或其他兼容OpenAI接口的模型
    temperature=0.3,
    api_key="your-api-key"
)

# ============ Agent定义 ============

def router_agent(state: AgentState) -> AgentState:
    """意图分类Agent"""
    prompt = """
    你是一个客服意图分类器。根据用户的问题,判断意图类型:
    - order_query: 订单查询、物流追踪、退换货
    - product_inquiry: 产品咨询、功能询问
    - complaint: 投诉、意见反馈
    - general: 问候、闲聊或其他
    
    用户问题:{query}
    输出仅保留意图类别。
    """
    response = llm.invoke(prompt.format(query=state["user_query"]))
    state["intent"] = response.content.strip().lower()
    return state

def knowledge_agent(state: AgentState) -> AgentState:
    """RAG知识检索Agent"""
    kb = KnowledgeBase()
    docs = kb.retrieve(state["user_query"], top_k=5)
    state["retrieved_docs"] = docs
    return state

def tool_agent(state: AgentState) -> AgentState:
    """工具调用Agent - 对接业务系统"""
    from tool_functions import TOOL_SCHEMAS, FUNCTION_MAP
    
    # 构造包含工具定义的LLM调用
    messages = [
        SystemMessage(content="你是电商客服助手,根据需要调用工具获取信息。"),
        HumanMessage(content=state["user_query"])
    ]
    
    # 请求LLM决定是否调用工具
    response = llm.invoke(
        messages,
        tools=TOOL_SCHEMAS,
        tool_choice="auto"
    )
    
    results = []
    if hasattr(response, 'tool_calls') and response.tool_calls:
        for tool_call in response.tool_calls:
            func_name = tool_call['name']
            func_args = json.loads(tool_call['arguments'])
            if func_name in FUNCTION_MAP:
                result = FUNCTION_MAP[func_name](**func_args)
                results.append({"tool": func_name, "result": result})
    
    state["tool_results"] = results
    return state

def escalation_agent(state: AgentState) -> AgentState:
    """工单升级Agent - 处理投诉和复杂问题"""
    from escalation import EscalationManager
    mgr = EscalationManager()
    
    # 生成工单摘要
    ticket = mgr.create_escalation_ticket(
        state["user_query"],
        "待人工处理",
        {"confidence": 0.0, "needs_escalation": True},
        state.get("messages", [])
    )
    state["needs_escalation"] = True
    state["agent_response"] = mgr.get_human_fallback_response(ticket)
    return state

def summary_agent(state: AgentState) -> AgentState:
    """汇总生成最终回复"""
    if state["needs_escalation"]:
        return state  # 已生成兜底话术
    
    # 收集上下文
    context = ""
    if state.get("retrieved_docs"):
        context += "参考知识:\n" + "\n".join([
            f"- {d['content'][:200]}" for d in state["retrieved_docs"][:3]
        ])
    
    if state.get("tool_results"):
        context += "\n业务数据:\n" + json.dumps(state["tool_results"], ensure_ascii=False)
    
    if not context:
        context = "无额外信息"
    
    prompt = f"""
    你是电商AI客服,请基于以下信息回答用户问题。
    回答要求:
    1. 仅使用提供的信息,不要编造任何内容
    2. 保持专业、友善的语气
    3. 如果信息不足,请坦诚告知并建议人工咨询
    
    {context}
    
    用户问题:{state["user_query"]}
    回答:
    """
    
    response = llm.invoke(prompt)
    state["agent_response"] = response.content
    return state

# ============ 路由逻辑 ============

def route_after_intent(state: AgentState) -> Literal["knowledge", "tool", "escalation", "summary"]:
    """根据意图路由到不同Agent"""
    intent = state.get("intent", "general")
    if intent == "order_query":
        return "tool"
    elif intent == "product_inquiry":
        return "knowledge"
    elif intent == "complaint":
        return "escalation"
    else:
        return "summary"

def should_escalate(state: AgentState) -> Literal["escalation", "summary"]:
    """判断是否需要人工兜底"""
    from hallucination_detector import HallucinationDetector
    detector = HallucinationDetector()
    
    eval_result = detector.evaluate(
        state.get("agent_response", ""),
        state.get("retrieved_docs", []),
        state.get("tool_results", [])
    )
    
    state["confidence"] = eval_result["confidence"]
    state["needs_escalation"] = eval_result["needs_escalation"]
    
    return "escalation" if eval_result["needs_escalation"] else "summary"

# ============ 构建工作流图 ============

def build_agent_graph():
    workflow = StateGraph(AgentState)
    
    # 添加节点
    workflow.add_node("router", router_agent)
    workflow.add_node("knowledge", knowledge_agent)
    workflow.add_node("tool", tool_agent)
    workflow.add_node("escalation", escalation_agent)
    workflow.add_node("summary", summary_agent)
    workflow.add_node("final_escalation", escalation_agent)  # 兜底节点
    
    # 设置入口
    workflow.set_entry_point("router")
    
    # 添加条件边:意图分流
    workflow.add_conditional_edges(
        "router",
        route_after_intent,
        {
            "knowledge": "knowledge",
            "tool": "tool",
            "escalation": "escalation",
            "summary": "summary"
        }
    )
    
    # 知识/工具节点后进入汇总
    workflow.add_edge("knowledge", "summary")
    workflow.add_edge("tool", "summary")
    
    # 汇总后检测是否需要兜底
    workflow.add_conditional_edges(
        "summary",
        should_escalate,
        {
            "escalation": "final_escalation",
            "summary": END
        }
    )
    
    # 兜底节点直接结束
    workflow.add_edge("escalation", END)
    workflow.add_edge("final_escalation", END)
    
    return workflow.compile()


# ============ 运行示例 ============
if __name__ == "__main__":
    agent = build_agent_graph()
    
    # 测试各类场景
    test_queries = [
        "怎么退货?",  # 知识类 → RAG检索
        "查询订单 ORD-001",  # 业务类 → Function Calling
        "我要投诉!",  # 投诉类 → 工单升级
        "今天天气怎么样?"  # 闲聊 → 无检索 → 可能触发兜底
    ]
    
    for query in test_queries:
        print(f"\n{'='*50}")
        print(f"用户:{query}")
        
        result = agent.invoke({
            "messages": [],
            "user_query": query,
            "retrieved_docs": [],
            "tool_results": [],
            "agent_response": "",
            "confidence": 1.0,
            "needs_escalation": False
        })
        
        print(f"意图:{result.get('intent')}")
        print(f"回复:{result.get('agent_response')[:200]}...")
        if result.get('needs_escalation'):
            print("⚠️ 已触发人工兜底")

6.3 落地效果参考

据相关企业实践数据,采用RAG+人工兜底架构的智能客服系统可实现显著改善:

指标 纯LLM方案 RAG+兜底方案 改善
幻觉发生率 27% <5% 降低81%
智能解决率 基准 +28.9% 显著提升
人工接管率 基准 -6.1% 显著降低
首次解决率 62% 89% +43%

七、总结与实施建议

本文从RAG检索增强、Function Calling确定性数据、幻觉检测与人工兜底三个层面,系统阐述了大模型在电商客服场景中幻觉治理的完整技术方案。核心实施建议如下:

渐进式落地:先在特定业务线(如退换货政策咨询)试点RAG方案,验证效果后再推广至全场景。

监控优先:建立包含幻觉指数、解决率、人工接管率等核心指标的监控体系,设置异常告警。

人机协同闭环:将人工审核中发现的错误回答归入拒绝采样数据集,定期用于模型迭代;将确认无误的困难样本重新注入系统提升幻觉检测准确率。

确定性优先原则:凡涉及订单、金额、库存等业务数据查询,优先通过Function Calling获取确定性结果,而非依赖LLM推理。

大模型幻觉的治理不是一次性工程,而是需要“检测-修正-迭代”持续闭环的系统性工作。只有将知识检索、工具调用、人工兜底有机结合,才能真正让AI客服从“回答客户”升级为“解决客户问题”。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐