📚 项目概述

本项目将构建一个功能完整的电商智能客服系统, 整合前面所有章节学到的技术,实现一个可以直接部署到生产环境的客服机器人。

💡 核心功能
功能模块 技术方案 应用章节
FAQ 智能问答 基于 RAG 的语义检索 08-rag.html
订单查询和管理 自定义工具集成 05-tools.html
多轮对话 Checkpointer 状态管理 11-checkpointer.html
用户偏好记忆 Store 长期存储 14-long-term-memory.html
实时响应 流式输出 12-streaming.html
敏感操作审核 Human-in-the-Loop 13-human-in-loop.html

业务场景

场景背景:某电商平台每天接收大量客户咨询,包括:

  • 常见问题:配送时间、退换货政策、支付方式等(占 60%)
  • 订单查询:订单状态、物流信息、退款进度等(占 30%)
  • 售后服务:退货申请、换货处理、投诉建议等(占 10%)

目标:使用 AI 客服机器人自动处理 80% 以上的咨询, 复杂问题转人工处理,提升效率并保持服务质量。

🏗️ 系统架构设计

graph TB User[用户咨询] --> Agent[智能客服 Agent] Agent --> FAQ{FAQ 问题?} Agent --> Order{订单查询?} Agent --> Service{售后服务?} FAQ -->|是| RAG[RAG 检索工具] RAG --> VectorDB[(向量数据库
FAQ 知识库)] RAG --> Answer1[生成答案] Order -->|是| OrderTools[订单工具集] OrderTools --> OrderDB[(订单数据库)] OrderTools --> Answer2[返回订单信息] Service -->|是| ServiceTools[售后工具集] ServiceTools --> HITL{需要审核?} HITL -->|是| Human[人工审核] HITL -->|否| Execute[执行操作] Human --> Execute Execute --> Answer3[返回处理结果] Answer1 --> Stream[流式输出] Answer2 --> Stream Answer3 --> Stream Stream --> Memory[对话记忆] Memory --> Checkpointer[(Checkpointer
短期记忆)] Memory --> Store[(Store
长期记忆)] Stream --> Response[实时响应用户] style Agent fill:#3b82f6,color:#fff style RAG fill:#10b981,color:#fff style OrderTools fill:#f59e0b,color:#fff style ServiceTools fill:#ef4444,color:#fff style HITL fill:#8b5cf6,color:#fff style Stream fill:#06b6d4,color:#fff

架构说明

组件 职责 技术实现
智能客服 Agent 理解用户意图,调用合适的工具 create_agent() + GPT-4
RAG 检索工具 从 FAQ 知识库检索相关信息 Chroma + OpenAI Embeddings
订单工具集 查询订单、物流、退款信息 @tool 装饰器 + SQLite
售后工具集 处理退货、换货、投诉 @tool + HITL Middleware
流式输出 实时显示响应过程 stream_mode="messages"
对话记忆 短期对话历史 + 长期用户偏好 Checkpointer + Store

📖 第一步:FAQ 智能问答(RAG)

首先实现基于 RAG 的 FAQ 问答功能,让机器人能够回答常见问题。

FAQ 数据准备

JSON 🟢 基础
// projects/customer-service-bot/data/faq.json
[
  {
    "question": "配送时间是多久?",
    "answer": "一般情况下,订单在提交后 1-2 个工作日内发货。国内配送通常需要 3-5 个工作日,偏远地区可能需要 5-7 个工作日。您可以在订单详情页查看实时物流信息。",
    "category": "配送"
  },
  {
    "question": "如何申请退货?",
    "answer": "您可以在订单详情页点击'申请售后'按钮,选择退货原因并提交。我们会在 1-2 个工作日内审核您的申请。退货商品需保持原包装完好,未使用,收到退货后 3-5 个工作日退款。",
    "category": "售后"
  },
  {
    "question": "支持哪些支付方式?",
    "answer": "我们支持多种支付方式:1)支付宝、微信支付 2)银行卡(借记卡/信用卡)3)货到付款(部分地区支持)。所有支付渠道均采用加密技术,保障您的资金安全。",
    "category": "支付"
  },
  {
    "question": "会员等级有什么权益?",
    "answer": "我们的会员体系分为普通、银卡、金卡、钻石四个等级。等级越高,享受的折扣越多(最高可达 9.5 折),并可获得专属客服、优先配送、生日礼品等特权。会员等级根据年度消费金额自动升级。",
    "category": "会员"
  },
  {
    "question": "如何修改收货地址?",
    "answer": "订单未发货前,您可以在订单详情页点击'修改地址'进行更改。如果订单已发货,请联系客服协助修改(可能产生额外运费)。建议在个人中心预先设置常用地址,下单时可快速选择。",
    "category": "订单管理"
  }
]

构建 FAQ 检索工具

Python 🟡 中级
"""
FAQ 检索工具实现
功能:基于 RAG 的语义搜索
"""
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document
from langchain.tools import tool
import json

# 加载 FAQ 数据
def load_faq_data(file_path: str) -> list[Document]:
    """加载 FAQ 数据并转换为 Document 对象"""
    with open(file_path, 'r', encoding='utf-8') as f:
        faq_list = json.load(f)

    documents = []
    for item in faq_list:
        # 将问题和答案组合成文档
        content = f"问题:{item['question']}\n答案:{item['answer']}"
        doc = Document(
            page_content=content,
            metadata={
                "category": item["category"],
                "question": item["question"]
            }
        )
        documents.append(doc)

    return documents

# 初始化向量存储
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
documents = load_faq_data("data/faq.json")

vectorstore = Chroma.from_documents(
    documents=documents,
    embedding=embeddings,
    collection_name="faq_knowledge"
)

retriever = vectorstore.as_retriever(search_kwargs={"k": 2})

# 定义 FAQ 检索工具
@tool
def search_faq(query: str) -> str:
    """
    搜索常见问题(FAQ)知识库。

    适用于:
    - 配送时间、退换货政策、支付方式等常见问题
    - 会员权益、优惠活动等通用信息

    参数:
        query: 用户的问题描述

    返回:
        相关的 FAQ 答案
    """
    # 检索相关文档
    docs = retriever.invoke(query)

    if not docs:
        return "抱歉,我没有找到相关的常见问题解答。您可以详细描述您的问题,或者转接人工客服。"

    # 组合检索结果
    result = "根据常见问题库,我找到以下相关信息:\n\n"
    for i, doc in enumerate(docs, 1):
        result += f"{i}. {doc.metadata['question']}\n"
        result += f"   {doc.page_content.split('答案:')[1]}\n\n"

    return result.strip()

测试 FAQ 工具

Python 🟢 基础
"""
测试 FAQ 检索工具
"""
# 直接调用工具
result = search_faq.invoke({"query": "我想知道多久能收到货"})
print(result)

# 预期输出:
# 根据常见问题库,我找到以下相关信息:
#
# 1. 配送时间是多久?
#    一般情况下,订单在提交后 1-2 个工作日内发货...
#
# 2. 如何修改收货地址?
#    订单未发货前,您可以在订单详情页点击'修改地址'...

📦 第二步:订单查询和管理工具

实现订单相关的工具集,包括查询订单状态、物流信息和退款进度。

模拟订单数据库

Python 🟢 基础
"""
订单数据模拟(生产环境应连接真实数据库)
"""
import sqlite3
from datetime import datetime, timedelta

# 初始化数据库
def init_order_database():
    """创建订单数据库并插入测试数据"""
    conn = sqlite3.connect("data/orders.db")
    cursor = conn.cursor()

    # 创建订单表
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS orders (
            order_id TEXT PRIMARY KEY,
            user_id TEXT NOT NULL,
            product_name TEXT NOT NULL,
            quantity INTEGER NOT NULL,
            total_price REAL NOT NULL,
            status TEXT NOT NULL,
            shipping_address TEXT,
            tracking_number TEXT,
            created_at TEXT NOT NULL,
            updated_at TEXT NOT NULL
        )
    """)

    # 插入测试数据
    test_orders = [
        ("ORDER-2024001", "user_123", "iPhone 15 Pro", 1, 7999.0,
         "已发货", "北京市朝阳区xxx小区", "SF1234567890",
         (datetime.now() - timedelta(days=3)).isoformat(),
         (datetime.now() - timedelta(days=1)).isoformat()),

        ("ORDER-2024002", "user_123", "AirPods Pro 2", 1, 1899.0,
         "配送中", "北京市朝阳区xxx小区", "SF0987654321",
         (datetime.now() - timedelta(days=2)).isoformat(),
         datetime.now().isoformat()),

        ("ORDER-2024003", "user_123", "MacBook Pro 14", 1, 14999.0,
         "处理中", "北京市朝阳区xxx小区", None,
         (datetime.now() - timedelta(hours=6)).isoformat(),
         (datetime.now() - timedelta(hours=6)).isoformat()),
    ]

    cursor.executemany("""
        INSERT OR REPLACE INTO orders VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    """, test_orders)

    conn.commit()
    conn.close()
    print("订单数据库初始化完成")

# 执行初始化
init_order_database()

订单查询工具集

Python 🟡 中级
"""
订单查询工具集
功能:查询订单状态、物流信息
"""
from langchain.tools import tool
from langchain.tools import ToolRuntime
from typing_extensions import TypedDict
import sqlite3

# 定义上下文 Schema
class CustomerContext(TypedDict):
    user_id: str
    session_id: str

@tool
def get_my_orders(runtime: ToolRuntime[CustomerContext]) -> str:
    """
    查询当前用户的所有订单。

    返回:
        订单列表,包括订单号、商品名称、状态等信息
    """
    user_id = runtime.context["user_id"]

    conn = sqlite3.connect("data/orders.db")
    cursor = conn.cursor()

    cursor.execute("""
        SELECT order_id, product_name, quantity, total_price, status, created_at
        FROM orders
        WHERE user_id = ?
        ORDER BY created_at DESC
    """, (user_id,))

    orders = cursor.fetchall()
    conn.close()

    if not orders:
        return "您目前没有任何订单记录。"

    result = f"您共有 {len(orders)} 个订单:\n\n"
    for order in orders:
        order_id, product, qty, price, status, created = order
        result += f"📦 订单号:{order_id}\n"
        result += f"   商品:{product} x{qty}\n"
        result += f"   金额:¥{price:.2f}\n"
        result += f"   状态:{status}\n"
        result += f"   下单时间:{created[:10]}\n\n"

    return result.strip()

@tool
def get_order_details(order_id: str, runtime: ToolRuntime[CustomerContext]) -> str:
    """
    查询特定订单的详细信息,包括物流信息。

    参数:
        order_id: 订单号(例如:ORDER-2024001)

    返回:
        订单详细信息和物流状态
    """
    user_id = runtime.context["user_id"]

    conn = sqlite3.connect("data/orders.db")
    cursor = conn.cursor()

    cursor.execute("""
        SELECT * FROM orders
        WHERE order_id = ? AND user_id = ?
    """, (order_id, user_id))

    order = cursor.fetchone()
    conn.close()

    if not order:
        return f"未找到订单 {order_id},请检查订单号是否正确。"

    _, _, product, qty, price, status, address, tracking, created, updated = order

    result = f"📦 订单详情\n\n"
    result += f"订单号:{order_id}\n"
    result += f"商品:{product} x{qty}\n"
    result += f"金额:¥{price:.2f}\n"
    result += f"状态:{status}\n"
    result += f"收货地址:{address}\n"
    result += f"下单时间:{created[:16]}\n"
    result += f"更新时间:{updated[:16]}\n"

    if tracking:
        result += f"\n🚚 物流信息\n"
        result += f"快递单号:{tracking}\n"
        result += f"物流状态:{status}\n"

        # 模拟物流轨迹
        if status == "已发货":
            result += "最新轨迹:您的包裹已从仓库发出,正在运输途中\n"
        elif status == "配送中":
            result += "最新轨迹:您的包裹已到达北京分拨中心,即将派送\n"

    return result

@tool
def cancel_order(order_id: str, reason: str, runtime: ToolRuntime[CustomerContext]) -> str:
    """
    取消订单(仅限未发货的订单)。

    参数:
        order_id: 订单号
        reason: 取消原因

    返回:
        取消结果
    """
    user_id = runtime.context["user_id"]

    conn = sqlite3.connect("data/orders.db")
    cursor = conn.cursor()

    # 检查订单状态
    cursor.execute("""
        SELECT status FROM orders
        WHERE order_id = ? AND user_id = ?
    """, (order_id, user_id))

    result = cursor.fetchone()

    if not result:
        conn.close()
        return f"未找到订单 {order_id}"

    status = result[0]

    if status != "处理中":
        conn.close()
        return f"订单 {order_id} 当前状态为 '{status}',无法取消。已发货的订单请申请退货。"

    # 更新订单状态
    cursor.execute("""
        UPDATE orders
        SET status = '已取消', updated_at = ?
        WHERE order_id = ? AND user_id = ?
    """, (datetime.now().isoformat(), order_id, user_id))

    conn.commit()
    conn.close()

    return f"订单 {order_id} 已成功取消。取消原因:{reason}\n退款将在 3-5 个工作日内原路退回。"

💬 第三步:多轮对话和记忆管理

整合 Checkpointer(短期对话历史)和 Store(长期用户偏好)实现智能对话。

用户偏好管理工具

Python 🟡 中级
"""
用户偏好管理(长期记忆)
功能:记住用户的语言偏好、常用地址等信息
"""
from langchain.tools import tool, ToolRuntime
from langgraph.store.memory import InMemoryStore

# 初始化 Store
store = InMemoryStore()

@tool
def save_user_preference(
    preference_type: str,
    preference_value: str,
    runtime: ToolRuntime[CustomerContext]
) -> str:
    """
    保存用户偏好设置。

    参数:
        preference_type: 偏好类型(language, default_address, notification 等)
        preference_value: 偏好值

    返回:
        保存结果
    """
    user_id = runtime.context["user_id"]
    store_obj = runtime.store

    # 获取现有偏好
    current_prefs = store_obj.get(("users", user_id), "preferences")

    if current_prefs:
        prefs = current_prefs.value
    else:
        prefs = {}

    # 更新偏好
    prefs[preference_type] = preference_value

    # 保存到 Store
    store_obj.put(("users", user_id), "preferences", prefs)

    return f"已保存您的偏好:{preference_type} = {preference_value}"

@tool
def get_user_preference(
    preference_type: str,
    runtime: ToolRuntime[CustomerContext]
) -> str:
    """
    获取用户偏好设置。

    参数:
        preference_type: 偏好类型

    返回:
        偏好值
    """
    user_id = runtime.context["user_id"]
    store_obj = runtime.store

    prefs = store_obj.get(("users", user_id), "preferences")

    if not prefs:
        return f"未设置 {preference_type} 偏好"

    value = prefs.value.get(preference_type)

    if not value:
        return f"未设置 {preference_type} 偏好"

    return f"您的 {preference_type} 偏好为:{value}"

@tool
def record_interaction_history(
    interaction_summary: str,
    runtime: ToolRuntime[CustomerContext]
) -> str:
    """
    记录重要的交互历史(用于后续分析和改进服务)。

    参数:
        interaction_summary: 交互摘要

    返回:
        记录结果
    """
    user_id = runtime.context["user_id"]
    store_obj = runtime.store

    # 获取历史记录
    history = store_obj.get(("users", user_id, "history"), "interactions")

    if history:
        interactions = history.value
    else:
        interactions = []

    # 添加新记录
    interactions.append({
        "timestamp": datetime.now().isoformat(),
        "summary": interaction_summary
    })

    # 保留最近 50 条
    interactions = interactions[-50:]

    # 保存
    store_obj.put(("users", user_id, "history"), "interactions", interactions)

    return "交互历史已记录"

🎯 第四步:完整系统整合

将所有组件整合成一个完整的客服机器人系统,包含流式输出和人工介入。

Python 🔴 高级 - 完整系统
"""
完整的电商客服机器人系统
整合:RAG + 工具 + 对话管理 + 流式输出 + 人工介入 + 长期记忆
"""
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.store.memory import InMemoryStore
from typing_extensions import TypedDict
import uuid

# ==================== 上下文定义 ====================

class CustomerContext(TypedDict):
    user_id: str
    session_id: str

# ==================== 工具集合 ====================

# 前面定义的所有工具
all_tools = [
    # FAQ 工具
    search_faq,

    # 订单工具
    get_my_orders,
    get_order_details,
    cancel_order,

    # 用户偏好工具
    save_user_preference,
    get_user_preference,
    record_interaction_history,
]

# ==================== 敏感操作审核配置 ====================

# 退款和取消订单需要人工审核
hitl_middleware = HumanInTheLoopMiddleware(
    interrupt_on={
        "cancel_order": True,  # 取消订单需要审核
        "search_faq": False,
        "get_my_orders": False,
        "get_order_details": False,
        "save_user_preference": False,
        "get_user_preference": False,
        "record_interaction_history": False,
    },
    description=lambda req: f"用户请求:{req['name']}({req['args']})"
)

# ==================== 创建客服 Agent ====================

# 初始化 Checkpointer 和 Store
checkpointer = InMemorySaver()
store = InMemoryStore()

customer_service_agent = create_agent(
    model="gpt-4o",
    tools=all_tools,
    middleware=[hitl_middleware],
    checkpointer=checkpointer,
    store=store,
    context_schema=CustomerContext,
    system_prompt="""你是一个专业的电商客服助手。

职责:
1. 解答客户关于配送、退换货、支付等常见问题(使用 search_faq 工具)
2. 查询和管理订单信息(使用订单相关工具)
3. 记住用户的偏好,提供个性化服务
4. 对于复杂或敏感的问题,及时转接人工客服

工作原则:
- 始终保持礼貌、专业、耐心
- 优先使用工具查询准确信息,不要猜测
- 对于订单取消、退款等敏感操作,需要人工审核
- 记录重要的交互历史,帮助改进服务
- 如果无法解决问题,主动建议转接人工

回答风格:
- 简洁明了,重点突出
- 使用列表和段落增强可读性
- 提供具体的操作步骤
"""
)

# ==================== 流式对话处理 ====================

def chat_with_customer_service(
    user_message: str,
    user_id: str = "user_123",
    thread_id: str = None
):
    """
    与客服机器人进行流式对话

    参数:
        user_message: 用户消息
        user_id: 用户 ID
        thread_id: 会话 ID(用于多轮对话)
    """
    if thread_id is None:
        thread_id = str(uuid.uuid4())

    config = {
        "configurable": {
            "thread_id": thread_id,
        },
        "context": {
            "user_id": user_id,
            "session_id": thread_id
        }
    }

    print(f"\n{'='*60}")
    print(f"用户: {user_message}")
    print('='*60)

    # 流式调用
    print("\n🤖 客服: ", end="", flush=True)

    full_response = ""
    interrupted = False

    for stream_mode, chunk in customer_service_agent.stream(
        {"messages": [{"role": "user", "content": user_message}]},
        config=config,
        stream_mode=["messages", "updates"]
    ):
        if stream_mode == "messages":
            token, metadata = chunk
            if token:
                print(token, end="", flush=True)
                full_response += token

        elif stream_mode == "updates":
            for step, data in chunk.items():
                if "__interrupt__" in data:
                    interrupted = True
                    print("\n\n⏸️ 需要人工审核,请稍候...")

    print("\n" + "="*60)

    return {
        "thread_id": thread_id,
        "response": full_response,
        "interrupted": interrupted
    }

# ==================== 测试场景 ====================

def run_test_scenarios():
    """运行多个测试场景"""

    print("\n" + "🧪 开始测试电商客服机器人".center(60, "="))

    # 场景 1:FAQ 问答
    print("\n\n📌 场景 1:查询配送时间")
    result1 = chat_with_customer_service(
        "我想知道订单一般多久能送到?",
        user_id="user_123"
    )
    thread_id = result1["thread_id"]

    input("\n按回车继续下一个场景...")

    # 场景 2:查询订单(多轮对话,使用相同 thread_id)
    print("\n\n📌 场景 2:查询我的订单")
    result2 = chat_with_customer_service(
        "帮我查一下我的订单",
        user_id="user_123",
        thread_id=thread_id  # 继续之前的对话
    )

    input("\n按回车继续下一个场景...")

    # 场景 3:查询特定订单详情
    print("\n\n📌 场景 3:查询订单详情")
    result3 = chat_with_customer_service(
        "帮我查一下 ORDER-2024002 的物流信息",
        user_id="user_123",
        thread_id=thread_id
    )

    input("\n按回车继续下一个场景...")

    # 场景 4:取消订单(会触发人工审核)
    print("\n\n📌 场景 4:取消订单(触发审核)")
    result4 = chat_with_customer_service(
        "我想取消订单 ORDER-2024003,因为买错了",
        user_id="user_123",
        thread_id=thread_id
    )

    if result4["interrupted"]:
        print("\n💡 提示:此操作需要人工审核")
        print("   在生产环境中,客服人员会在后台审核此请求")

        # 模拟审核通过
        from langgraph.types import Command
        print("\n✅ 模拟审核通过,继续执行...")

        approval_result = customer_service_agent.invoke(
            Command(resume={"decisions": [{"type": "approve"}]}),
            config={
                "configurable": {"thread_id": thread_id},
                "context": {"user_id": "user_123", "session_id": thread_id}
            }
        )

        print(f"\n最终结果: {approval_result['messages'][-1].content}")

    input("\n按回车继续下一个场景...")

    # 场景 5:保存用户偏好
    print("\n\n📌 场景 5:保存常用地址")
    result5 = chat_with_customer_service(
        "帮我把常用地址设为:北京市朝阳区xxx小区",
        user_id="user_123",
        thread_id=thread_id
    )

    print("\n\n" + "✅ 测试完成!".center(60, "="))
    print("\n系统演示了以下功能:")
    print("  1. ✅ FAQ 智能问答(RAG)")
    print("  2. ✅ 订单查询和管理")
    print("  3. ✅ 多轮对话(Checkpointer)")
    print("  4. ✅ 人工审核(HITL)")
    print("  5. ✅ 用户偏好(Store)")
    print("  6. ✅ 流式输出")

# ==================== 主程序 ====================

if __name__ == "__main__":
    # 初始化数据
    print("正在初始化系统...")
    init_order_database()
    print("系统初始化完成!\n")

    # 运行测试场景
    run_test_scenarios()

🔄 完整对话流程

sequenceDiagram participant U as 用户 participant A as Agent participant FAQ as FAQ工具 participant Order as 订单工具 participant HITL as 人工审核 participant CP as Checkpointer participant ST as Store U->>A: 配送时间是多久? A->>FAQ: search_faq("配送时间") FAQ->>A: 返回FAQ答案 A->>CP: 保存对话历史 A->>U: 流式返回答案 U->>A: 查询我的订单 A->>CP: 加载对话上下文 A->>Order: get_my_orders() Order->>A: 返回订单列表 A->>CP: 更新对话历史 A->>U: 流式返回订单信息 U->>A: 取消订单 ORDER-2024003 A->>Order: cancel_order(ORDER-2024003) Order->>HITL: 触发审核 HITL-->>U: 等待人工审核 Note over HITL: 客服审核中... HITL->>Order: 审核通过,执行取消 Order->>A: 返回取消结果 A->>CP: 记录操作 A->>ST: 记录交互历史 A->>U: 返回取消确认 U->>A: 保存常用地址 A->>ST: save_user_preference() ST->>A: 保存成功 A->>U: 确认保存

🚀 部署和优化建议

生产环境配置

Python 🔴 高级
"""
生产环境配置示例
"""
from langgraph.checkpoint.postgres import PostgresSaver
from langgraph.store.postgres import PostgresStore
import os

# 数据库连接
DB_URI = os.getenv("DATABASE_URL", "postgresql://user:pass@localhost:5432/customer_service")

# 使用 PostgreSQL 持久化
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
    checkpointer.setup()

    with PostgresStore.from_conn_string(DB_URI) as store:
        store.setup()

        # 创建生产级 Agent
        production_agent = create_agent(
            model="gpt-4o",
            tools=all_tools,
            middleware=[
                hitl_middleware,
                # 可添加更多中间件:日志、监控、限流等
            ],
            checkpointer=checkpointer,
            store=store,
            context_schema=CustomerContext,
            system_prompt="""..."""  # 生产级提示词
        )

性能优化清单

优化项 方案 预期提升
FAQ 检索速度 使用 Redis 缓存热门问题 响应时间减少 70%
数据库查询 添加索引、使用连接池 查询速度提升 3-5 倍
并发处理 使用异步 Agent(async/await) 支持 10x 并发用户
成本控制 使用更小的模型(GPT-3.5)处理简单问题 成本降低 50%
响应速度 启用流式输出 首字延迟减少 80%

监控指标

  • 响应时间:P50 < 2s, P95 < 5s
  • FAQ 命中率:> 60%
  • 问题解决率:> 80%(无需转人工)
  • 用户满意度:> 4.0/5.0
  • 每日成本:< $50(1000 次对话)

❓ 常见问题

Q1: 如何处理多个用户同时对话?

使用不同的 thread_id 区分不同用户的会话。 每个用户的对话历史独立存储在 Checkpointer 中。

Python
# 用户 A 的会话
config_a = {
    "configurable": {"thread_id": "user_a_session_001"},
    "context": {"user_id": "user_a"}
}

# 用户 B 的会话
config_b = {
    "configurable": {"thread_id": "user_b_session_002"},
    "context": {"user_id": "user_b"}
}

# 两个用户可以并发对话,互不影响
agent.invoke({...}, config=config_a)
agent.invoke({...}, config=config_b)

Q2: FAQ 知识库如何更新?

方案 1:定期重建

  • 每天凌晨自动从 CMS 或数据库拉取最新 FAQ
  • 重新生成 embeddings 并更新向量数据库
  • 适合变化不频繁的场景

方案 2:增量更新

Python
# 添加新的 FAQ
new_faq = Document(
    page_content="问题:xxx\n答案:xxx",
    metadata={"category": "新增"}
)

vectorstore.add_documents([new_faq])

# 删除过时的 FAQ
vectorstore.delete(ids=["outdated_faq_id"])

Q3: 如何防止 Agent 给出错误答案?

多层防护策略

  1. 明确工具边界:在工具的 docstring 中说明适用场景
  2. 验证工具输入:在工具内部验证参数合法性
  3. 提示词引导:在 system_prompt 中强调"优先使用工具,不要猜测"
  4. 输出验证:添加中间件检查答案的合理性
  5. 人工监督:定期审查对话记录,发现问题及时调整

Q4: 对话历史会无限增长吗?

不会。可以通过以下方式控制:

  • 限制历史长度:只保留最近 N 轮对话
  • 摘要历史:使用 LLM 定期总结对话,替换详细历史
  • 定期清理:超过一定时间的会话自动归档

Q5: 如何评估客服机器人的效果?

建立多维度评估体系:

指标 计算方法 目标值
问题解决率 无需转人工的对话数 / 总对话数 > 80%
首次响应时间 用户发送消息到收到首个 Token 的时间 < 1s
平均对话轮次 解决问题平均需要的对话轮数 < 5 轮
用户满意度 对话结束后的用户评分 > 4.0/5.0
答案准确率 人工抽查答案的正确率 > 95%

✨ 最佳实践

1. 提示词设计

  • 明确角色定位:"你是专业的电商客服"
  • 列举职责范围:解答 FAQ、查询订单、处理售后
  • 强调工具优先:不要猜测,优先使用工具
  • 设定行为准则:礼貌、专业、及时转人工
  • 提供示例:展示期望的回答风格

2. 工具设计

  • 单一职责:每个工具只做一件事
  • 清晰的 docstring:说明功能、参数、适用场景
  • 错误处理:返回友好的错误消息
  • 性能优化:添加缓存、批量查询
  • 安全验证:验证用户权限和参数合法性

3. 对话管理

  • 合理的 thread_id 策略:每个独立咨询一个 thread
  • 主动结束会话:问题解决后询问是否还需帮助
  • 上下文引用:"您刚才提到的订单"而非"订单"
  • 记录关键信息:用户偏好、常见问题保存到 Store

4. 生产环境注意事项

  • 使用 PostgreSQL:替代 InMemorySaver 和 InMemoryStore
  • 启用监控:集成 LangSmith 追踪执行过程
  • 设置限流:防止恶意调用
  • 异常告警:工具失败、响应超时等及时通知
  • 定期备份:对话历史和用户数据

🔮 扩展方向

功能扩展

功能 实现思路 难度
多语言支持 检测用户语言 + 翻译工具 🟡 中级
语音输入 集成 Whisper ASR 🟡 中级
图片识别 使用 GPT-4V 处理产品图片 🔴 高级
情感分析 检测用户情绪,调整回答风格 🟡 中级
智能推荐 基于用户历史推荐商品 🔴 高级
主动问候 识别老客户,个性化问候 🟢 基础

技术升级

  • LangGraph 编排:用状态图实现更复杂的对话流程
  • 多 Agent 协作:订单 Agent + FAQ Agent + 售后 Agent 分工协作
  • 强化学习:根据用户反馈持续优化回答
  • 知识图谱:构建商品和问题的关系图谱

📖 参考资源