用 Spring AI Alibaba JManus 构建零售智能客服工单系统:从 0 到日处理 10 万单

用 Spring AI Alibaba JManus 构建零售智能客服工单系统:从 0 到日处理 10 万单

技术栈:Spring AI Alibaba 1.2 · JManus 0.9 · Qwen3 · Redis 7.0 · MySQL 8.0

场景:电商零售客服工单自动化处理

关键指标:客服响应效率提升 40%,人工干预率降低 30%,日处理 10 万+ 工单


一、为什么零售行业需要 AI 工单系统

每逢大促,零售平台客服部门都会经历一场硬仗:数以万计的用户同时涌来,咨询物流进度、申请退款、反映商品质量问题。传统处理模式有三个致命缺陷:

任务耦合:一个客服系统同时处理分类、查询、退款、通知,业务逻辑深度耦合,改动一处、全盘受影响。

状态丢失:用户描述一半、换个渠道继续说,对话上下文断掉,客服需要反复确认,体验极差。

服务孤岛:物流系统、支付系统、ERP 各自独立,人工要在多个后台之间来回切换,效率极低。

JManus 的多智能体协作架构恰好对症下药------用 Planning Agent 拆分复合任务,用 Redis 持久化对话状态,用 MCP 协议打通异构服务。


二、整体架构设计

系统由四类 Agent 协作完成工单处理全流程:

markdown 复制代码
用户消息
    │
    ▼
Planning Agent(任务路由与分解)
    ├──► ClassifierAgent(工单分类 + 优先级判定)
    ├──► LogisticsAgent(物流查询 + 异常处理)
    ├──► RefundAgent(退款审核 + 资金操作)
    └──► NotifyAgent(短信/钉钉通知 + 工单归档)

Planning Agent 接收原始用户消息,自动拆分成子任务并分配给专业 Agent,各 Agent 并发执行后汇总结果,整个过程状态持久化在 Redis 中。


三、环境准备

3.1 依赖版本

组件 版本
JDK 17+
Spring Boot 3.3.x
Spring AI Alibaba 1.2.x
JManus 0.9.x
Redis 7.0+
MySQL 8.0+

3.2 Maven 依赖

xml 复制代码
<dependencies>
    <!-- Spring AI Alibaba 核心 -->
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
        <version>1.2.0</version>
    </dependency>

    <!-- JManus 智能体框架 -->
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-jmanus</artifactId>
        <version>0.9.0</version>
    </dependency>

    <!-- Redis 状态持久化 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    <!-- 监控 -->
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-registry-prometheus</artifactId>
    </dependency>
</dependencies>

3.3 生产环境配置

yaml 复制代码
# application-prod.yml
spring:
  ai:
    alibaba:
      api-key: ${DASHSCOPE_API_KEY}
      chat:
        options:
          model: qwen3-72b-instruct
  jmanus:
    max-retries: 3
    timeout: 5000ms
    memory-store: redis
    thread-pool:
      core-size: 20
      max-size: 100
      queue-capacity: 200
  redis:
    host: redis-cluster.prod
    port: 6379
    password: ${REDIS_PWD}
    timeout: 2000ms
  datasource:
    url: jdbc:mysql://mysql.prod:3306/retail_agent
    username: ${DB_USER}
    password: ${DB_PWD}

四、核心代码实现

4.1 客服工单 Agent 定义

这是整个系统的核心 Bean,定义了 Agent 的行为规则、工具链和记忆存储:

typescript 复制代码
@Configuration
public class CustomerServiceAgentConfig {

    @Bean
    @Description("电商客服工单智能体")
    public Agent customerServiceAgent(
            ChatClient chatClient,
            ToolExecutor toolExecutor,
            RedisTemplate<String, Object> redisTemplate) {

        return new Agent.Builder()
            .withSystemPrompt("""
                您是企业级电商客服智能体,严格遵守以下规则:
                1. 工单分类:一级分类 [物流 | 质量 | 售后 | 支付]
                2. 优先级算法:涉及金额 > 100 元标记为紧急工单
                3. 输出格式:{"category":"物流","urgency":3,"action":"refund"}
                4. 异常处理:置信度 < 0.8 时,自动转人工并说明原因
                """)
            .withMemory(new RedisChatMemoryRepository(redisTemplate))
            .withTools("refundTool", "logisticsQueryTool", "compensationTool")
            .withExecutor(toolExecutor)
            .build();
    }
}

4.2 物流查询工具(MCP 接入示例)

JManus 通过 @Tool 注解将业务方法暴露给大模型调用,无需额外编写 prompt 描述,框架会自动生成工具描述:

kotlin 复制代码
@Component
public class LogisticsQueryTool {

    @Autowired
    private LogisticsApiClient logisticsClient;

    @Tool(description = "根据订单号查询物流状态,返回运单号、当前位置和预计送达时间")
    public LogisticsResult queryLogistics(
            @ToolParam(description = "电商平台订单号,格式如 2024XXXXXXXXXX") String orderId) {

        try {
            return logisticsClient.query(orderId);
        } catch (LogisticsException e) {
            return LogisticsResult.failed("物流信息暂时无法获取,建议 2 小时后重试");
        }
    }
}

4.3 退款处理工具

退款涉及资金操作,需要在工具层做严格的幂等控制:

less 复制代码
@Component
public class RefundTool {

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Tool(description = "发起订单退款,支持全额和部分退款,退款到原支付渠道")
    public RefundResult processRefund(
            @ToolParam(description = "订单号") String orderId,
            @ToolParam(description = "退款金额,单位元") BigDecimal amount,
            @ToolParam(description = "退款原因") String reason) {

        // 幂等检查,防止重复退款
        String idempotencyKey = "refund:" + orderId;
        Boolean isFirst = redisTemplate.opsForValue()
            .setIfAbsent(idempotencyKey, "processing", Duration.ofMinutes(10));

        if (Boolean.FALSE.equals(isFirst)) {
            return RefundResult.duplicate("该订单退款正在处理中,请勿重复操作");
        }

        try {
            RefundResult result = paymentService.refund(orderId, amount, reason);
            redisTemplate.opsForValue().set(idempotencyKey, "done");
            return result;
        } catch (Exception e) {
            redisTemplate.delete(idempotencyKey); // 失败时释放锁,允许重试
            throw new RefundException("退款失败: " + e.getMessage());
        }
    }
}

4.4 多智能体协作入口

Planning Agent 接收用户消息后自动分解任务,这里展示如何触发整个工单处理流程:

typescript 复制代码
@Service
public class WorkOrderService {

    @Autowired
    private JManusRunner jManusRunner;

    /**
     * 处理用户工单
     * JManus 会自动:1) 理解意图 2) 拆分子任务 3) 调用对应工具 4) 汇总结果
     */
    public WorkOrderResult processWorkOrder(String userId, String userMessage) {
        String sessionId = "session:" + userId;

        AgentTask task = AgentTask.builder()
            .sessionId(sessionId)
            .userMessage(userMessage)
            .agentName("customerServiceAgent")
            .build();

        AgentResult result = jManusRunner.run(task);

        return WorkOrderResult.builder()
            .orderId(result.getExtract("orderId"))
            .category(result.getExtract("category"))
            .action(result.getExtract("action"))
            .replyMessage(result.getContent())
            .build();
    }
}

五、关键能力解析

5.1 PLAN-ACT 模式:为什么工单处理不乱

当用户说"我的订单 2024001234 还没到,已经 7 天了,我要申请退款",JManus 的 Planning Agent 会自动拆解为:

  1. 查询订单 2024001234 的物流信息
  2. 判断是否超出承诺时效
  3. 如果超时,自动发起退款申请
  4. 发送退款成功通知给用户

每一步都是确定性执行,不会出现"跳步"或"重复执行"的问题,这正是 JManus 相比纯 LLM 调用的核心优势。

5.2 Redis 状态持久化:多轮对话不丢失

vbnet 复制代码
// 框架自动处理,开发者只需在 Agent 中声明 withMemory
.withMemory(new RedisChatMemoryRepository(redisTemplate))

// 实际存储结构(Redis Hash)
// key:   session:user_123
// field: history
// value: [{"role":"user","content":"我的订单..."},
//          {"role":"assistant","content":"已查询到..."}]

用户换一个渠道继续咨询,只要 sessionId 不变,上下文完整保留。

5.3 MCP 协议:一键接入 300+ 企业服务

通过 Nacos MCP Registry,无需为每个外部系统写适配层:

yaml 复制代码
# application.yml 中声明 MCP 服务
spring:
  ai:
    mcp:
      client:
        servers:
          - name: alipay-mcp
            url: https://mcp.alipay.internal/sse
          - name: dingtalk-mcp
            url: https://mcp.dingtalk.internal/sse
          - name: logistics-mcp
            url: https://mcp.logistics.internal/sse

Agent 可以直接调用这些服务,就像调用本地方法一样。


六、性能优化与生产部署

6.1 三级缓存加速高频查询

kotlin 复制代码
@Tool(description = "查询商品库存")
public StockResult queryStock(String skuId) {
    // L1:本地缓存(Caffeine),命中率约 70%,延迟 < 1ms
    StockResult local = localCache.get(skuId);
    if (local != null) return local;

    // L2:Redis 缓存,命中率约 25%,延迟 < 5ms
    StockResult redis = redisCache.get("stock:" + skuId);
    if (redis != null) {
        localCache.put(skuId, redis);
        return redis;
    }

    // L3:数据库查询,兜底
    StockResult db = stockRepository.findBySkuId(skuId);
    redisCache.set("stock:" + skuId, db, Duration.ofMinutes(5));
    localCache.put(skuId, db);
    return db;
}

6.2 熔断机制保障系统稳定性

less 复制代码
@Tool(description = "查询物流状态(含熔断保护)")
@CircuitBreaker(name = "logistics", fallbackMethod = "logisticsFallback")
@TimeLimiter(name = "logistics")
public LogisticsResult queryWithCircuitBreaker(String orderId) {
    return logisticsClient.query(orderId);
}

// 熔断降级:返回友好提示,不让用户等待超时
public LogisticsResult logisticsFallback(String orderId, Exception e) {
    return LogisticsResult.builder()
        .status("查询受限")
        .message("物流系统繁忙,预计 10 分钟后恢复,我们会主动推送最新状态")
        .build();
}

6.3 Prometheus 监控指标

yaml 复制代码
management:
  endpoints:
    web:
      exposure:
        include: health,metrics,prometheus
  metrics:
    tags:
      application: retail-agent

重点关注以下指标:

  • jmanus_agent_execution_seconds:Agent 执行耗时
  • jmanus_tool_call_total:各工具调用次数
  • jmanus_plan_steps_count:平均任务拆分步数
  • spring_ai_chat_tokens_used:Token 消耗量(直接影响成本)

七、落地效果

某电商平台引入该架构后,核心指标变化如下:

指标 改造前 改造后
日均工单处理量 3 万单(含人工) 10 万+ 单
平均响应时间 8 分钟 45 秒
人工干预率 100% 约 30%(复杂/高风险工单转人工)
客服人力成本 基准 100% 降至约 55%
用户满意度(NPS) 62 78

八、踩坑记录

坑 1:大模型输出不稳定

工具调用参数有时格式不对,导致下游系统报错。解法:在 @Tool 的 description 中明确说明参数格式(如"金额单位为元,保留两位小数"),并在工具层加参数校验,而非依赖模型100%输出正确格式。

坑 2:Redis 连接池耗尽

高并发下 Redis 连接池不够用,Agent 执行超时。解法:将 max-active 从默认 8 调整至 100,并开启连接池监控告警。

坑 3:Token 成本超预期

多轮对话历史全量传入模型,Token 消耗是预期的 3 倍。解法:对历史消息做滑动窗口截断,只保留最近 10 轮,并对重复性描述做压缩摘要。

坑 4:首次任务规划耗时长

Planning Agent 第一次规划平均 8 秒,用户体验差。解法:对常见工单类型(物流、退款)做计划模板缓存,命中模板时跳过规划阶段,直接执行。


九、快速上手

bash 复制代码
# 1. 克隆仓库
git clone https://github.com/spring-ai-alibaba/JManus.git
cd JManus

# 2. 配置 DashScope API Key(阿里云百炼平台获取)
export DASHSCOPE_API_KEY=your_key_here

# 3. 启动(默认使用 H2 内存数据库,零配置)
mvn spring-boot:run

# 4. 访问 Web UI(内置可视化配置界面)
open http://localhost:18080

生产环境切换 MySQL:在 application.yml 中激活 mysql profile,框架会自动建表。


十、小结

JManus 在零售客服工单场景的价值,不在于它"有多智能",而在于它让 AI 的行为可预测、可调试、可扩展。PLAN-ACT 模式把复杂业务流程变成可审计的执行计划,MCP 协议消除了异构系统集成的技术债,Redis 状态持久化解决了多轮对话的工程难题。

对于已有 Spring Boot 技术栈的团队,这是目前门槛最低、与现有架构契合度最高的 AI Agent 落地方案之一。

项目地址

JManus:github.com/spring-ai-a...

Spring AI Alibaba:github.com/alibaba/spr...

官网文档:java2ai.com

相关推荐
常威正在打来福2 小时前
【omc】Claude Code 必备神器:Oh-My-ClaudeCode 让你的 AI 编程效率翻倍
aigc·ai编程·claude
叫我少年2 小时前
C# 基础数据类型:布尔类型
后端
Apifox2 小时前
如何在 Apifox 中快速构建和调试 AI Agent
前端·agent·ai编程
鹏程十八少2 小时前
12. Android 协程通关秘籍:31 道资深工程师面试题精讲
前端·后端·面试
子昕3 小时前
4 个我常用的 Claude Code Skills 推荐给你
ai编程
白宇横流学长3 小时前
基于Spring Boot的校园考勤管理系统的设计与实现
java·spring boot·后端
ReSearch3 小时前
sfsEdgeStore:边缘计算时代的轻量级数据存储解决方案
数据库·后端·github
terryso3 小时前
BMAD Story Automator上手实录:把5个待办Story交给 AI 自主推进
ai编程
清_秋3 小时前
从0到1开始安装vibe coding环境
ai编程