Files
ai-customer-service/specs/功能清单.md
Your Name cf46b27610 fix: P0-1 RateLimiter并发写安全 + P0-2工单操作错误码区分 + P1 rows.Close修复
P0-1 (limits.go): Allow()方法改为全程使用写锁保护counters map读写,避免RLock写入时的data race
P0-2 (ticket_workflow.go+ticket_handler.go): Assign/Resolve/Close操作先查询ticket存在性和状态,返回明确的CS_TICKET_4001/CS_TKT_4002/CS_TICKET_4092/CS_TICKET_4093错误码,handler根据错误前缀路由HTTP状态码
P1-1 (ticket_store.go): 移除GetStats中3处手动rows.Close(),只保留defer Close()
2026-05-01 20:56:25 +08:00

289 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AI Customer Service 功能清单(按钮级任务版)
> 版本v1.0
> 日期2026-04-27
> 说明:每个任务 5 分钟可完成,可直接安排进任务管理
---
## Phase 1Widget 渠道 + RAG 知识库 + 基础对话
### 模块 1.1:网页 Widget 接入
#### 1.1.1 Widget 嵌入
- [ ] **任务**:实现 Widget 组件HTML snippet + JS可通过 `<script>` 标签嵌入任意网页
- [ ] **任务**Widget 组件渲染浮动按钮(右下角,点击展开对话窗口)
- [ ] **任务**:对话窗口渲染:标题栏("智能客服"/ 消息区(滚动)/ 输入框(支持 Enter 发送)/ 发送按钮
- [ ] **任务**:实现 Widget 最小化按钮,点击后收起为悬浮球
- [ ] **任务**:实现 Widget 消息气泡:用户消息(右侧蓝色)/ 机器人消息(左侧灰色)
- [ ] **任务**:机器人消息支持 Markdown 格式渲染(支持代码块、粗体、链接)
- [ ] **任务**:机器人消息支持展示链接按钮(点击可跳转外部页面)
#### 1.1.2 Webhook 对接
- [ ] **任务**:实现 Widget Webhook 端点 `POST /api/v1/ai-customer-service/webhook/widget`
- [ ] **任务**Webhook 接收消息后,解析 `session_id`(从 cookie 或 localStorage 生成)、`user_message``channel=widget`
- [ ] **任务**Webhook 返回 HTTP 200异步处理模式消息处理结果通过 WebSocket 推送回 Widget
- [ ] **任务**:实现 WebSocket 连接管理Widget 端建立长连接 `/ws/widget`
### 模块 1.2:对话引擎
#### 1.2.1 意图识别
- [ ] **任务**:实现 `IntentEngine.Recognize()` 接口,输入用户消息,输出意图 + 置信度
- [ ] **任务**实现意图分类列表api_key_管理 / 模型路由配置 / 配额计费 / 错误码诊断 / 账户问题 / 转人工
- [ ] **任务**:实现置信度计算,阈值:>=0.85 = 高置信 / 0.60-0.85 = 中置信 / <0.60 = 低置信
- [ ] **任务**:低置信度意图自动触发转人工流程
- [ ] **任务**:实现"退款/账户封禁/数据泄露"等敏感意图识别(关键词匹配 + 意图分类),命中时强制转人工
#### 1.2.2 RAG 检索
- [ ] **任务**:实现知识库向量库初始化脚本(使用 Qdrant / PGVector接入产品文档内容
- [ ] **任务**:实现 `RAGEngine.Retrieve(query, top_k)` 接口,输入用户问题,输出 top_k 相关知识库片段
- [ ] **任务**RAG 检索使用混合策略sentence embedding语义+ keyword match关键词兜底
- [ ] **任务**:实现检索结果重排序(使用 cross-encoder 对 top_k*2 结果重新打分,取 top_k
- [ ] **任务**RAG 检索 P99 延迟目标 <200ms
#### 1.2.3 回复生成
- [ ] **任务**:实现 `ReplyGenerator.Generate(ctx, intent, rag_results, conversation_history)` 接口
- [ ] **任务**Prompt 模板System Prompt你是立连桥智能客服专回答产品使用问题只引用知识库内容+ User Query + RAG 结果 + 对话历史
- [ ] **任务**:实现回复 Markdown 渲染(飞书/企微渠道),代码示例使用语法高亮
- [ ] **任务**:涉及用户个人数据查询时,在 Prompt 中注入 `user_id`,强制模型只返回当前用户数据
- [ ] **任务**实现回复缓存Redis相同意图+相同用户问题的回复缓存 5 分钟)
### 模块 1.3:会话管理
#### 1.3.1 会话状态机
- [ ] **任务**实现会话状态枚举initializing / waiting / bot_replied / waiting_human / closed
- [ ] **任务**:实现会话超时逻辑:用户 30 分钟无消息 → 自动发送"还在吗?";仍无回复 → 30 分钟后关闭会话
- [ ] **任务**:实现会话关闭事件记录:用户点击"已解决"或超时关闭 → 记录 `session_resolved`
#### 1.3.2 上下文管理
- [ ] **任务**:实现上下文窗口:保留最近 5 轮对话(用户+机器人各 5 条)
- [ ] **任务**:上下文存储在 RedisKey = `cs:session:{session_id}`TTL = 24 小时)
- [ ] **任务**实现跨会话用户识别Widget 用户首次访问时生成 `anonymous_id` 存入 cookie
### 模块 1.4:知识库管理
#### 1.4.1 知识库后台
- [ ] **任务**:实现知识库管理页路由 `/cs/dashboard/knowledge`
- [ ] **任务**知识库列表每行显示条目ID / 标题 / 分类 / 覆盖意图 / 引用次数 / 状态 / 操作
- [ ] **任务**:渲染"新增条目"按钮,点击进入条目编辑器
- [ ] **任务**:知识库编辑器字段:标题(必填)/ 分类下拉API Key/路由/配额/错误码/账户/其他)/ 正文Markdown 富文本)/ 覆盖意图标签(多选)/ 状态(草稿/发布)
- [ ] **任务**:编辑器实现 Markdown 实时预览
- [ ] **任务**条目发布后自动触发向量库更新异步30 秒内生效)
- [ ] **任务**每个知识库条目支持上传附件PDF/图片),附件存储在 OSS
- [ ] **任务**:知识库列表支持按分类筛选 / 按标题搜索 / 按引用次数排序
#### 1.4.2 知识库导入导出
- [ ] **任务**:实现"批量导入"按钮,支持上传 Markdown zip 包批量导入条目
- [ ] **任务**:实现"导出全部"按钮,导出为 Markdown zip 包
---
## Phase 2Telegram + Discord + 意图识别 + 转人工
### 模块 2.1:多渠道接入适配
#### 2.1.1 Telegram Bot 接入
- [ ] **任务**:申请 Telegram Bot通过 @BotFather),获取 Bot Token
- [ ] **任务**:实现 Telegram Webhook 端点 `POST /api/v1/ai-customer-service/webhook/telegram`
- [ ] **任务**Webhook 解析 Telegram Update提取 `chat.id`(作为 user_id`message.text`(作为 user_message
- [ ] **任务**:实现 Telegram 回复方法:调用 Bot API `sendMessage`,传入 `chat.id` 和回复内容
- [ ] **任务**:实现 Telegram 消息格式化Markdown → Telegram MarkdownV2 格式转换
- [ ] **任务**:在 Gateway 配置 Telegram Bot Webhook URL 指向本系统
#### 2.1.2 Discord Bot 接入
- [ ] **任务**:创建 Discord Application开通 Bot 功能,获取 Bot Token
- [ ] **任务**:实现 Discord Webhook 端点 `POST /api/v1/ai-customer-service/webhook/discord`
- [ ] **任务**Webhook 解析 Discord interaction提取 `channel_id` / `member.user.id` / `content`
- [ ] **任务**:实现 Discord 回复方法:调用 Discord Webhook API 或 Bot sendMessage
- [ ] **任务**Discord 支持 slash command`/客服问题`)触发对话
- [ ] **任务**:在 Gateway 配置 Discord Webhook 指向本系统
#### 2.1.3 统一消息格式
- [ ] **任务**:实现 `ChannelAdapter` 接口族TelegramAdapter / DiscordAdapter / WidgetAdapter / WechatAdapter
- [ ] **任务**:每个 Adapter 将各自渠道的消息格式统一转换为 `UnifiedMessage`包含message_id / channel / open_id / user_id / content / timestamp
- [ ] **任务**:实现统一会话 ID 生成规则:`{channel}:{open_id}`
### 模块 2.2:身份核验
#### 2.2.1 绑定用户身份识别
- [ ] **任务**:实现 `GET /api/v1/ai-customer-service/auth/check?channel={ch}&open_id={id}` 接口,返回绑定状态
- [ ] **任务**:已绑定用户:返回 `{bound: true, user_id: "xxx"}`
- [ ] **任务**:未绑定用户:返回 `{bound: false}`,触发身份核验流程
#### 2.2.2 邮箱验证码核验
- [ ] **任务**:未绑定用户输入邮箱后,点击"验证"按钮POST `/api/v1/ai-customer-service/auth/verify-code/send`
- [ ] **任务**:后端验证邮箱是否存在(调用 `supply-api` 的邮箱查询接口),存在则发送 6 位数字验证码(有效期 5 分钟)
- [ ] **任务**用户输入验证码POST `/api/v1/ai-customer-service/auth/verify-code/check`
- [ ] **任务**:验证成功后,将 `{channel, open_id, user_id}` 写入 `cs_user_bindings`
- [ ] **任务**:验证失败 3 次后自动触发转人工工单标签identity_verification_failed
#### 2.2.3 API Key 前缀核验
- [ ] **任务**:用户输入 API Key 前缀POST `/api/v1/ai-customer-service/auth/apikey/lookup`
- [ ] **任务**:后端用前缀模糊查询 `supply_api_keys` 表(前 8 位),返回匹配到的账户列表(隐藏中间位)
- [ ] **任务**:若匹配到 1 个 → 直接绑定;若匹配到多个 → 要求补充邮箱二次确认;若 0 个 → 提示"未找到账户"
- [ ] **任务**:验证过程不存储用户输入的完整 API Key仅记录前缀用于关联
### 模块 2.3:转人工流程
#### 2.3.1 触发转人工
- [ ] **任务**实现转人工触发条件检测a用户发送"人工客服/找人工/投诉"关键词 b意图置信度 <0.60 c身份核验失败 3 次 d用户反馈"未解决"累计 3 轮
- [ ] **任务**:触发转人工时,更新会话状态 = waiting_human
- [ ] **任务**:触发转人工时,显示机器人消息:"正在为您转接人工客服,请稍候..."
#### 2.3.2 工单生成
- [ ] **任务**:触发转人工时,自动写入 `cs_tickets`字段ticket_id / session_id / user_id / channel / priority / status=open / created_at / 原始问题 / 会话历史摘要)
- [ ] **任务**:转人工时,若用户处于多轮对话,附加最近 5 轮对话历史到工单 `conversation_history` 字段
- [ ] **任务**触发转人工时发送飞书通知到客服群包含用户ID/渠道/问题摘要/排队位置)
- [ ] **任务**:实现 `GET /api/v1/ai-customer-service/tickets/queue-position?ticket_id={id}`,返回当前排队人数
#### 2.3.3 人工接管
- [ ] **任务**:客服人员点击"接单"按钮POST `/api/v1/ai-customer-service/tickets/{id}/accept`
- [ ] **任务**:接单后,工单状态更新为 processinglocked_by = 客服ID
- [ ] **任务**:机器人向用户发送:"人工客服已接单,预计 {X} 分钟内回复"
- [ ] **任务**客服在工单处理页发送消息POST `/api/v1/ai-customer-service/tickets/{id}/reply`,消息推送给用户
---
## Phase 3微信渠道 + 用户数据查询 + 工单后台
### 模块 3.1:微信接入
#### 3.1.1 微信公众号 Webhook
- [ ] **任务**配置微信公众号服务器地址URL + Token + EncodingAESKey
- [ ] **任务**:实现微信公众号 Webhook 验证GET 请求,验证 Token
- [ ] **任务**:实现微信公众号消息接收 `POST /api/v1/ai-customer-service/webhook/wechat`
- [ ] **任务**:解析微信 XML 消息格式:提取 `FromUserName`(作为 open_id`MsgType``Content`
- [ ] **任务**:实现被动回复(用户发消息后,微信服务端在 5 秒内必须回复,否则重试)
- [ ] **任务**:支持接收事件推送(用户关注/取关)
#### 3.1.2 微信公众号客服消息
- [ ] **任务**:实现模板消息发送(用于通知类消息,如工单状态变更)
- [ ] **任务**:客服在后台发送的消息,通过微信公众号客服消息接口推送(调用 `https://api.weixin.qq.com/cgi-bin/message/custom/send`
### 模块 3.2:用户数据查询(只读)
#### 3.2.1 Token 消耗查询
- [ ] **任务**:用户发送"我的 Token 消耗是多少",识别意图为 quota_check
- [ ] **任务**:后端调用 `GET /api/v1/ai-customer-service/diagnostics/token-usage?user_id={uid}&date=today`
- [ ] **任务**:内部调用 `platform-token-runtime` 的只读接口获取今日 Token 消耗
- [ ] **任务**:机器人回复格式:"今日已消耗 {N} Tokens剩余配额 {M} Tokens{percent}%"
#### 3.2.2 错误日志诊断
- [ ] **任务**:用户发送"我的请求报错了"或错误码,识别意图为 error_diagnosis
- [ ] **任务**:后端调用 `GET /api/v1/ai-customer-service/diagnostics/recent-errors?user_id={uid}&limit=5`
- [ ] **任务**:内部调用 `supply-api` 的只读接口获取用户最近 5 条错误日志
- [ ] **任务**:机器人回复展示:请求时间 / 错误码 / 错误描述 / 建议操作
#### 3.2.3 供应商状态查询
- [ ] **任务**:用户发送"供应商X是不是挂了",识别意图为 supplier_status_check
- [ ] **任务**:后端调用 `GET /api/v1/ai-customer-service/diagnostics/supplier-status?supplier={name}`
- [ ] **任务**:内部调用 `supply-intelligence` 的供应商状态 API
- [ ] **任务**:机器人回复格式:"供应商 {X} 当前状态:正常运行(延迟 {N}ms/ 部分可用({详情}"
### 模块 3.3:工单后台
#### 3.3.1 工单列表页
- [ ] **任务**:实现工单列表页路由 `/cs/dashboard/tickets`
- [ ] **任务**:工单列表顶部渲染状态 Tab全部 / 待处理open/ 处理中processing/ 已关闭closed
- [ ] **任务**:工单列表顶部渲染优先级 Tab全部 / P1红色/ P2橙色/ P3灰色
- [ ] **任务**工单列表每行显示工单ID / 用户ID / 渠道图标 / 问题摘要 / 优先级 / 状态 / 等待时长 / 客服 / 创建时间
- [ ] **任务**工单行按优先级P1>P2>P3和等待时长升序排列
- [ ] **任务**:工单行渲染"接单"按钮(仅 open 状态且未锁定的工单可见)
- [ ] **任务**:工单行渲染"查看"按钮,点击进入工单详情页
#### 3.3.2 工单详情页
- [ ] **任务**:工单详情页路由 `/cs/dashboard/tickets/{ticket_id}`
- [ ] **任务**:详情页左侧渲染会话历史时间线(用户消息+机器人回复+系统消息)
- [ ] **任务**详情页右侧渲染工单信息面板用户ID / 渠道 / 优先级 / 状态 / 等待时长 / 关联会话数
- [ ] **任务**:详情页底部渲染回复输入框(支持 Markdown + 附件上传)+ "发送"按钮
- [ ] **任务**:发送回复后,通过对应渠道推送给用户
- [ ] **任务**:详情页渲染"关闭工单"按钮(仅 processing 状态),点击后确认,确认后状态 = closed
- [ ] **任务**:详情页渲染"转交"按钮(选择其他客服接手)
#### 3.3.3 统计分析
- [ ] **任务**:实现统计页路由 `/cs/dashboard/stats`
- [ ] **任务**统计页渲染转人工原因分布饼图Top 10
- [ ] **任务**:统计页渲染每日会话量柱状图(近 30 天)
- [ ] **任务**:统计页渲染自助解决率趋势折线图(近 30 天)
- [ ] **任务**:统计页渲染平均首次响应时长趋势(近 30 天)
- [ ] **任务**:统计页渲染知识库未命中率趋势(近 30 天)
### 模块 3.4:模型 Failover
#### 3.4.1 多模型配置
- [ ] **任务**:实现模型配置页路由 `/cs/dashboard/settings/models`
- [ ] **任务**:模型列表每行显示:模型名称 / 类型(主/备) / 供应商 / 状态(启用/禁用) / 操作
- [ ] **任务**:渲染"添加备选模型"按钮,点击后弹出配置表单(模型名称 / API Endpoint / API Key / 优先级)
- [ ] **任务**:模型配置支持拖拽排序(设置优先级顺序)
#### 3.4.2 Failover 执行
- [ ] **任务**:主模型 API 调用超时5 秒内无响应)→ 自动切换到优先级最高的可用备模型
- [ ] **任务**:主模型 API 返回 5xx → 自动切换到备模型,记录 failover 事件
- [ ] **任务**:备模型也失败时(双故障)→ 返回兜底静态回复 + 生成工单
- [ ] **任务**Failover 事件写入 `cs_model_failover_events`字段session_id / from_model / to_model / reason / occurred_at
#### 3.4.3 兜底回复
- [ ] **任务**:预配置兜底回复模板(静态文本,不依赖大模型)
- [ ] **任务**:双故障时返回兜底回复:"抱歉,当前客服系统繁忙,请稍后再试,或联系 support@example.com"
- [ ] **任务**双故障时飞书通知技术负责人P1 告警)
---
## 全局模块
### 模块 G1权限与认证
- [ ] **任务**:实现 JWT 认证中间件(与立连桥统一认证打通)
- [ ] **任务**:实现客服角色:客服(处理工单)/ 运营(知识库+统计)/ 管理员(全部)
- [ ] **任务**:权限不足返回 HTTP 403错误码 `CS_AUTH_1001`
### 模块 G2健康检查
- [ ] **任务**:实现 `GET /actuator/health` / `/actuator/health/live` / `/actuator/health/ready`
- [ ] **任务**Readiness probe 检查PostgreSQL 连接 + Redis 连接 + Qdrant 连接
### Module G3: OpenAPI
- [ ] **任务**:实现 Swagger UI 路由 `/docs`
- [ ] **任务**:实现 OpenAPI 3.0 spec 端点 `/openapi.json`
### 模块 G4Webhook 安全
- [ ] **任务**:实现 Telegram Webhook Secret Token 校验X-Telegram-Bot-Api-Secret-Token
- [ ] **任务**:实现 Discord Request Signature 校验X-Signature-Ed25519
- [ ] **任务**实现微信消息体签名校验msg_signature
- [ ] **任务**:校验失败返回 HTTP 403
---
## 技术基础设施
### T1项目骨架
- [ ] **任务**:初始化 Go module `github.com/lijiaoliao/ai-customer-service`
- [ ] **任务**:创建 `cmd/ai-customer-service/main.go`,支持 `api``worker` 两种运行模式
- [ ] **任务**:创建 `internal/` 目录结构domain/service/handler/infrastructure/repository
- [ ] **任务**:配置 Viper 读取 `config.yaml`
- [ ] **任务**:配置 `log/slog` 结构化日志
- [ ] **任务**:创建 PostgreSQL schema migration表前缀 `cs_`
- [ ] **任务**:配置 Redis 连接池
- [ ] **任务**:配置 Dockerfile 和 docker-compose.yml
### T2单元测试
- [ ] **任务**:为 domain 层函数编写单元测试,覆盖率 >= 70%
- [ ] **任务**:为 service 层函数编写单元测试,覆盖率 >= 80%
- [ ] **任务**:配置 GitHub Actions CI
### T3IntegrationPlugin 接口
- [ ] **任务**:实现 `IntegrationPlugin` 接口
- [ ] **任务**:实现插件模式下各渠道的开关配置
- [ ] **任务**:实现 Webhook 路径前缀可配置(默认 `/api/v1/ai-customer-service/`
---
## 任务估算汇总
| Phase | 模块 | 任务数 | 估计工时 |
|-------|------|--------|---------|
| Phase 1 | 1.1 Widget + 1.2 对话引擎 + 1.3 会话 + 1.4 知识库 | 38 | 5 人天 |
| Phase 2 | 2.1 TG/Discord + 2.2 身份核验 + 2.3 转人工 | 30 | 4 人天 |
| Phase 3 | 3.1 微信 + 3.2 数据查询 + 3.3 工单后台 + 3.4 Failover | 38 | 5 人天 |
| 全局 | G1 权限 + G2 健康 + G3 文档 + G4 Webhook安全 | 14 | 1.5 人天 |
| 技术基础设施 | T1 骨架 + T2 测试 + T3 插件 | 12 | 1.5 人天 |
| **合计** | | **132** | **~17 人天** |