A multi-tenant AI customer-service platform with governed RAG, AI Skills, MCP tools, and human handoff.
SupportFlow 面向企业多租户客服场景,提供带来源引用的知识库问答、受控业务工具调用、人工坐席接管和运营看板。项目重点不是简单封装模型 API,而是针对生成模型的高延迟、高成本与供应商限流,构建可治理、可隔离、可审计的应用链路。
当前状态: M0~M7、AI Skills 管理执行闭环(M8.1)和 MCP 工具中心(M9)已经完成;已发布 Skill 自动接入聊天能力路由(M8.2)仍在规划中。
| 主线 | 已实现能力 |
|---|---|
| 多租户知识库 | 服务端身份贯穿 MySQL 查询、Redis Key 与向量检索过滤;RocketMQ 异步完成切片、向量化和状态追踪 |
| 语义缓存与治理 | 首轮相似问答案复用;租户/用户双层限流、租户级 Bulkhead、Redis 熔断、超时与静态降级 |
| 人工坐席 | Redisson 互斥与 MySQL 条件更新防止重复派单;WebSocket + Redis Pub/Sub 实现跨实例实时分发 |
| AI Skills | 租户级 Prompt、输入 Schema 和模型参数;草稿、测试、发布、停用、不可变版本与执行审计 |
| MCP Tools | 标准 Spring AI MCP Server;服务端身份注入、RBAC、读写分级、一次性确认令牌、幂等与脱敏审计 |
| 运营与验证 | 每租户累计指标、真实 Token Usage、坐席效率;JMeter 吞吐计划与 PowerShell 并发断言 |
| 角色 | 主要能力 |
|---|---|
| VISITOR | 匿名访客挂件、流式问答、转人工、查询本人工单、实时会话 |
| AGENT | 查看待处理工单、并发抢单、实时接待和关闭工单 |
| ADMIN | 知识库、AI Skills、MCP Tools、治理状态和运营看板 |
flowchart TB
USER[访客 / 坐席 / 管理员] --> FE[Vue 3 SPA]
FE --> API[Spring Boot API]
API --> AUTH[多租户鉴权]
AUTH --> RATE[租户 + 用户双层限流]
RATE --> ROUTER[ChatToolRouter]
ROUTER -->|动态工单状态| TOOL[共享工具策略与执行层]
ROUTER -->|知识问题| CACHE{首轮语义缓存}
CACHE -->|命中| ANSWER[直接复用答案]
CACHE -->|未命中| TOOL
CLIENT[标准 MCP Client] --> SERVER[MCP WebMVC SSE Server]
SERVER --> TOOL
TOOL -->|search_knowledge| VECTOR[(RediSearch)]
TOOL -->|create/query ticket| TICKET[(MySQL 工单)]
VECTOR --> RAG[RAG Prompt + 有界历史]
RAG --> GOV[Bulkhead / 熔断 / 超时 / 降级]
GOV --> LLM[百炼 ChatModel]
DOC[文档上传] --> MQ[RocketMQ]
MQ --> INGEST[切片 + Embedding]
INGEST --> VECTOR
AUTH --> SKILL[AI Skills 管理与执行]
SKILL --> GOV
TICKET --> WS[WebSocket]
WS --> PUBSUB[Redis Pub/Sub 跨实例扇出]
- HTTP 拦截器恢复
LoginUser,控制器在请求线程捕获完整租户和用户身份。 - Redis Lua 依次执行租户桶与用户桶限流,拒绝请求返回 HTTP 429。
- 动态工单状态意图在语义缓存之前调用
query_ticket_status,避免缓存过期状态。 - 首轮知识问题先查询语义缓存;未命中后经受控
search_knowledge工具召回知识片段。 - 聊天服务组装 RAG Prompt、引用来源和 Redis 有界多轮历史。
- 真实生成调用经过租户 Bulkhead、Redis 熔断器和超时保护;异常时返回静态转人工提示。
- 成功响应记录真实 Usage,保存会话历史,并按缓存边界决定是否回填语义缓存。
动态工具结果、多轮回答和降级答案均不会进入语义答案缓存。
SupportFlow 当前通过 Spring AI WebMVC SSE 暴露三个真实工具:
| 工具 | 类型 | 数据边界 |
|---|---|---|
search_knowledge |
READ | 只检索当前租户已启用知识库,返回原始片段,不在工具内调用 LLM |
create_ticket |
WRITE | 只为当前访客创建工单,要求一次性确认令牌与幂等键 |
query_ticket_status |
READ | 只允许查询当前租户、当前访客自己的工单 |
工具 Schema 不接收 tenantId、userId 或 role。身份由服务端登录态注入,调用统一经过租户启停、RBAC、READ/WRITE 分类、参数校验、独立有界执行器、租户级工具 Bulkhead、超时和脱敏审计。工具故障与 LLM 熔断器相互隔离。
当前 MCP 传输端点为:
- SSE:
/mcp/sse - Client message:
/mcp/message
| 领域 | 技术 |
|---|---|
| 后端 | Java 21、Spring Boot 3.4.5、Spring AI 1.0 GA、MyBatis-Plus |
| 模型 | 百炼 OpenAI 兼容 ChatModel:qwen3.8-27b;DashScope EmbeddingModel:text-embedding-v3 |
| 数据 | MySQL 8、Redis Stack、RediSearch |
| 消息与并发 | RocketMQ 5.x、Redis Lua、Redisson、JVM Semaphore |
| 实时通信 | SSE、WebSocket、Redis Pub/Sub |
| 前端 | Vue 3、Vite、Element Plus、Pinia、Vue Router |
| 验证 | JUnit、JMeter、PowerShell 并发断言 |
对话和向量模型共用一把百炼 API Key,但使用不同协议入口:对话走 OpenAI 兼容接口,Embedding 继续走 DashScope 原生接口。
- JDK 21、Maven 3.9+
- Node.js 18+、npm
- Docker Desktop / Docker Compose
- 阿里百炼 API Key
日常开发只在 Docker 中运行 MySQL、Redis Stack 和 RocketMQ:
Set-Location deploy
docker compose up -d
docker compose ps首次创建数据卷时,deploy/mysql/init/ 下的 SQL 会按顺序建立 M1~M9 所需表和演示数据。已有数据卷不会自动重放新增脚本。
$env:DASHSCOPE_API_KEY = "sk-your-dashscope-key"
Set-Location ..\backend
mvn spring-boot:run后端地址:http://localhost:8081
可选配置:
| 环境变量 | 默认值 | 说明 |
|---|---|---|
DASHSCOPE_API_KEY |
无 | 百炼 API Key;不要提交到 Git |
DASHSCOPE_CHAT_BASE_URL |
https://dashscope.aliyuncs.com/compatible-mode |
对话模型兼容入口 |
DASHSCOPE_CHAT_MODEL |
qwen3.8-27b |
对话模型名称 |
为兼容既有本机环境,后端也支持从系统变量 API-KEY 回退读取。
Set-Location ..\frontend-new
npm install
npm run dev访问 http://localhost:5173。Vite 会将 /api 和 /ws 代理到后端 8081。
| 租户 | 用户名 | 密码 | 角色 |
|---|---|---|---|
| Acme | acme_admin |
123456 |
ADMIN |
| Acme | acme_agent1 / acme_agent2 |
123456 |
AGENT |
| Globex | globex_admin |
123456 |
ADMIN |
演示账号和默认数据库密码仅用于本地环境,生产部署必须替换。
全栈 Docker 部署验证
根目录 Compose 会复用 deploy_* 数据卷,并把后端和前端一起构建到镜像。请先运行一次开发中间件 Compose 创建数据卷,再停止它,避免容器名和端口冲突:
Set-Location deploy
docker compose up -d
docker compose down
Set-Location ..
Copy-Item .env.example .env
# 编辑 .env,填入 DASHSCOPE_API_KEY
docker compose up -d --build访问 http://localhost:8080。应用代码变化后需要重新构建镜像,因此该方式主要用于部署验证,不作为日常开发入口。
| 模块 | 主要端点 |
|---|---|
| 鉴权 | /auth/register、/auth/login、/auth/me、/auth/logout |
| 知识库 | /kb、/kb/{kbId}/documents |
| 智能问答 | /chat、/chat/stream |
| 工单 | /ticket/transfer、/ticket/pending、/ticket/{id}/claim、/ticket/{id}/close |
| 实时会话 | /ws/chat |
| AI Skills | /skills 相关管理、测试、发布与执行接口 |
| MCP Tools | /mcp-tools 相关策略、确认、调用与审计接口 |
| 标准 MCP | /mcp/sse、/mcp/message |
| 看板与治理 | /dashboard/overview、/governance/status、/governance/fault |
除注册、登录和匿名访客入口外,业务接口均需携带 authorization Token。ADMIN 页面和工具调用还会执行角色检查。
# 后端构建
Set-Location backend
mvn clean package -DskipTests
# 当前平台的核心单元测试
mvn "-Dtest=AiSkillServiceImplTest,ChatToolRouterTest" test
# 前端生产构建
Set-Location ..\frontend-new
npm run buildloadtest/ 提供两类验证资产:
- JMeter:
chat-load.jmx、chat-llm.jmx、chat-isolation.jmx - PowerShell:工单 only-one-winner、熔断状态机、限流与跨租户隔离断言
运行方法与测试前置条件见 loadtest/README.md。
supportflow/
├── backend/ # Spring Boot 主工程
│ └── src/main/java/com/hmdp/
│ ├── auth/ # 多租户身份上下文与拦截器
│ ├── cache/ # 语义缓存
│ ├── governance/ # 限流、Bulkhead、熔断、故障注入
│ ├── mcp/ # MCP Server 适配与聊天工具路由
│ ├── mq/ # RocketMQ 文档摄入
│ ├── metrics/ # 租户级指标采集
│ ├── service/ # RAG、Skills、Tools、工单业务
│ └── ws/ # WebSocket 与 Redis Pub/Sub
├── frontend-new/ # Vue 3 管理端与访客挂件
├── deploy/ # 本地中间件与 MySQL 初始化脚本
├── loadtest/ # JMeter 与 PowerShell 验证资产
└── frontend/ # 已停用的原点评前端,仅作参考
- 多租户鉴权、知识库 CRUD 与异步摄入
- RAG、引用来源、SSE 与 Redis 有界多轮历史
- 语义缓存和 LLM 高并发治理
- 人工工单、抢单和跨实例实时会话
- 统计看板、真实 Token Usage 和压测资产
- AI Skills 管理、不可变版本、直接执行与审计
- 三个 MCP 工具、标准协议、安全策略与聊天读工具路由
- M8.2:已发布 Skill 接入聊天意图/能力路由
- MCP Streamable HTTP 迁移评估
当前采用共享数据库的逻辑租户隔离;知识库上传实现文本与 Markdown 内容;MCP 传输使用 WebMVC SSE。更完整的生产化改进见设计文档。
SupportFlow 由经典练习项目“黑马点评”进行业务域重构而来,复用了其鉴权、缓存、分布式锁、ID 生成和消息中间件经验。原点评业务代码仍保留用于基础设施参考,但对应数据表和前端已经退出当前业务链路。