petstore-docs/智能预约助手-M0编码任务brief-2026-08-02.md

475 lines
18 KiB
Markdown
Raw 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.

# 智能预约助手 M0 编码任务 brief
> 日期2026-08-02<br>
> 状态:**Ready for Review / 尚未进入编码**<br>
> 目标:宠主用文字或语音生成可验证预约草稿,回填现有表单,不由智能层创建 `Appointment`<br>
> Workstream`Core Booking Flow`<br>
> Owner Agent`Backend Core` + `Customer Experience FE`<br>
> Paired QA`Core Flow QA`<br>
> Service Lock`backend:booking-agent-session+read-tools` + `frontend:customer-booking-agent+shared-api`<br>
> Data Model Review Required`Yes`<br>
> Access / Privacy Review Required`Yes`<br>
> RC Included`No`
**需求来源**
- [智能预约助手产品与技术方案 v0.1](./宠小它智能预约助手-产品与技术方案-v0.1.md)
- [模型与语音供应商选型](./智能预约助手-模型与语音供应商选型-2026-08-02.md)
## 1. M0 交付结果
宠主在已登录状态进入「一句话预约」,输入文字或按住说话。系统依次:
1. 转写语音(文字输入跳过);
2. 提取宠物查询词、服务查询词、日期表达、时间偏好和备注;
3. 在当前 customer 和门店范围内解析真实 Pet 与 ServiceType
4. 调用现有容量服务获取真实号源;
5. 展示可修改草稿卡;
6. 宠主点击「带入普通预约」后,回填现有 `CustAppointmentCreate`
7. 宠主仍在现有表单上点击「提交预约」。
M0 成功的判定是 **「草稿真实、回填正确、普通预约未受影响」**,不是对话内创建预约。
## 2. 严格非目标
- 不实现 `POST /api/booking-agent/sessions/{sessionId}/confirm`
- 不调用 `AppointmentService.createBooking`
- 不新增 `Appointment` 字段或状态;
- 不做取消、改期、代客预约或指定技师;
- 不自动建立宠物档案;
- 不做匿名智能会话;
- 不开启外部搜索、知识库或模型托管 Agent
- 不持久化原始语音或完整对话原文;
- 不进入当前 RC6 tag、发布物或生产配置。
## 3. 用户流程
```mermaid
flowchart TD
A[宠主预约页] --> B[点击一句话预约]
B --> C{已登录 customer}
C -- 否 --> D[登录并保留返回路由]
D --> E[创建助手会话]
C -- 是 --> E
E --> F[文字或语音输入]
F --> G[结构化意图提取]
G --> H[服务端解析真实宠物和服务]
H --> I[查询真实号源]
I --> J{草稿完整}
J -- 否 --> K[询问一个关键缺失项]
K --> F
J -- 是 --> L[展示草稿卡]
L --> M[带入普通预约]
M --> N[CustAppointmentCreate 回填]
N --> O[用户在现有表单提交]
```
### 3.1 入口
M0 只在宠主的 `CustAppointmentCreate` 顶部增加一个次级入口:
> 不想一项项填?「一句话预约」
该入口不取代当前表单和主提交按钮,不改宠主首页主 CTA。历史预约、报告页和宠物档案深链放到后续迭代。
### 3.2 对话风格
- 回复简短,一次只问一个关键缺失项;
- 宠物、服务和号源使用固定模板回复,不由模型自由生成业务事实;
- 可选项使用芯片/卡片,不要求宠主重复说已知内容;
- 对话页固定保留「普通预约」退出口。
### 3.3 可支持的时间表达
M0 确定性解析只承诺:
- 绝对日期;
- 「今天 / 明天 / 后天」;
- 「本周 X / 下周 X」
- 精确时间、「上午 / 下午」和「X 点以后 / 以前」。
「过几天」「最近」「周末都行」等不能稳定转换的表达保留为歧义,请宠主选择日期。确认卡和回填草稿始终使用 `Asia/Shanghai` 下的绝对日期时间。
## 4. 后端设计
### 4.1 包与组件
建议新增:
```text
backend/src/main/java/com/petstore/bookingagent/
api/
BookingAgentController.java
BookingAgentDtos.java
config/
BookingAgentProperties.java
domain/
BookingAgentSession.java
BookingAgentStatus.java
BookingDraft.java
BookingIntentPatch.java
mapper/
BookingAgentSessionMapper.java
provider/
BookingIntentExtractor.java
SpeechTranscriber.java
ProviderException.java
aliyun/
QwenBookingIntentExtractor.java
Qwen3AsrSpeechTranscriber.java
service/
BookingAgentService.java
BookingAgentContextResolver.java
BookingAgentReplyRenderer.java
BookingTimeConstraintResolver.java
```
注:项目现有微信出站调用使用 JDK `HttpClient`。M0 供应商适配也优先使用可注入、有固定 connect/request timeout 的 JDK `HttpClient`,不为两个 HTTPS endpoint 引入重型 Agent SDK。
### 4.2 责任边界
| 组件 | 责任 | 禁止 |
|---|---|---|
| `BookingAgentController` | 登录上下文、输入大小、响应映射 | 不在 controller 解析时间或调用预约写服务 |
| `BookingIntentExtractor` | 当前输入 + 最小草稿 -> `BookingIntentPatch` | 不访问数据库、不调工具 |
| `BookingAgentContextResolver` | 解析当前 customer 的 Pet 和目标门店 ServiceType | 不信任模型传入 ID |
| `BookingTimeConstraintResolver` | 相对日期/时间窗 -> 绝对搜索条件 | 不猜测未支持表达 |
| `BookingAgentService` | 状态转换、上下文解析、号源查询、草稿版本 | 不调用 `createBooking` |
| `BookingAgentReplyRenderer` | 按确定数据渲染中文模板 | 不使用模型生成宠物/服务/号源事实 |
| `SpeechTranscriber` | 短音频 -> 文本 | 不保存原始音频 |
### 4.3 M0 会话状态
M0 只允许:
- `collecting`
- `proposing`
- `confirmable`
- `fallback`
- `expired`
- `cancelled`
`submitting`、`booked` 和 `needs_reselection` 属于 M1M0 的 service 不得转入这三个状态。
### 4.4 数据表
新增迁移提案:
`backend/db/migrations/20260802_create_booking_agent_session.sql`
M0 字段:
- `session_id` VARCHAR(64) 主键;
- `customer_user_id` BIGINT NOT NULL
- `store_id` BIGINT NULL
- `status` VARCHAR(32) NOT NULL
- `draft_json` TEXT NOT NULL
- `draft_version` INT NOT NULL
- `entry_source` VARCHAR(32) NOT NULL
- `input_modality` VARCHAR(16) NULL
- `expires_at` DATETIME NOT NULL
- `create_time` / `update_time`
- `deleted` TINYINT(1) NOT NULL DEFAULT 0。
索引:
- `(customer_user_id, status, expires_at)`
- `(expires_at, deleted)` 用于过期清理。
M0 不增加 `appointment_id`,也不建立 `t_booking_agent_turn`。`appointment_id` 唯一关联在 M1 幂等写入评审时再增加,避免 M0 数据模型暗示已具备直接创建能力。
M0 的 `entry_source` 只允许 `appointment_create`;历史预约、报告、首页和宠物档案入口尚未开放。
`draft_json` 只保存已验证 ID、时间约束和必要备注不保存每轮用户原文、提示词或模型原始响应。
### 4.5 API 契约
M0 只实现:
| Method | Endpoint | 用途 |
|---|---|---|
| `POST` | `/api/booking-agent/sessions` | 创建已登录 customer 会话 |
| `POST` | `/api/booking-agent/sessions/{sessionId}/messages` | 提交文字/语音转写文本,刷新草稿 |
| `POST` | `/api/booking-agent/transcriptions` | 上传短音频并获取可编辑转写 |
| `POST` | `/api/booking-agent/sessions/{sessionId}/fallback` | 返回可回填普通表单的已验证草稿 |
| `DELETE` | `/api/booking-agent/sessions/{sessionId}` | 将本人会话标记为 `cancelled` |
所有 endpoint 都要求 `CurrentUserContext.require()` 且 role 为 `customer`。每次读写 session 都以 `sessionId + current.userId` 查询;他人 session 和不存在 session 均返回统一 404 语义,避免泄漏 session 是否存在。
M0 绝对不注册 `/confirm` endpoint。
### 4.6 模型输出强校验
`BookingIntentPatch` 建议为固定 record/DTO
```json
{
"schemaVersion": "booking-intent-v1",
"intent": "book",
"petQuery": "球球",
"serviceQuery": "洗澡",
"dateExpression": "本周六",
"timeWindow": {
"start": "15:00",
"end": null
},
"remark": null,
"ambiguities": [],
"nextAction": "resolve_context"
}
```
校验规则:
- 未知字段拒绝或明确忽略,不得进业务实体;
- `schemaVersion`、`intent` 和 `nextAction` 为枚举;
- 文本字段 trim、限长
- 模型输出 ID、价格、号源或预约状态字段时整个响应降级
- JSON 解析、schema 或枚举校验失败统一映射 `AGENT_UNAVAILABLE`,不展示模型原始输出。
### 4.7 出站日志
允许记录:
- 脱敏 request ID
- provider/model/schema/prompt 版本;
- 请求字符数或音频时长区间;
- 耗时、HTTP 大类、结果码和降级类型。
禁止记录:
- API Key 或 Authorization header
- 用户原文、原始音频、Base64
- 完整模型请求/响应;
- 手机号、session token、`report_token`、私密媒体 URL。
## 5. 前端设计
### 5.1 建议写入文件
```text
frontend/src/pages/appointment/BookingAgent.vue # 新页面
frontend/src/pages/appointment/CustAppointmentCreate.vue # 次级入口 + 回填
frontend/src/api/index.js # 统一 API 封装
frontend/src/utils/bookingAgentDraft.js # 短期草稿交接
frontend/src/pages.json # 路由
```
`frontend/src/api/index.js` 为共享契约入口,写入前由 Customer Experience FE 持有 `shared-api` 锁并通知 Backend Core。
### 5.2 页面元素
- 顶部标题:「一句话预约」;
- 简短说明:「告诉我宠物、服务和想来的时间」;
- 消息区:只在当前页内保留消息用于展示,不持久化到 Storage
- 文字输入框;
- 按住说话按钮,上传前显示隐私说明;
- 转写结果先回到可编辑输入框,宠主确认后再发送意图请求;
- 宠物/服务/时段选择芯片;
- 草稿卡;
- 主操作「带入普通预约」;
- 次操作「普通预约」和「结束对话」。
### 5.3 语音适配
- 小程序录音格式、权限和真机行为必须先做小程序实测,不在文档中假定 H5 和 mp-weixin 的录音细节完全相同;
- 客户端在上传前检查时长和大小,后端再做一次权威检查;
- 音频上传完成后立即释放本地临时路径引用;
- 权限拒绝时显示「可以直接打字预约」,不反复强请求录音权限;
- H5 无可用录音能力时只显示文字输入,不阻断 M0 主链路。
### 5.4 草稿回填
`bookingAgentDraft.js` 只保存一次性回填对象:
```json
{
"source": "booking-agent-m0",
"storeId": 1,
"petId": 2,
"petName": "球球",
"petType": "狗",
"serviceType": "精洗护理",
"appointmentTime": "2026-08-08T15:00:00",
"remark": "怕吹风机"
}
```
该对象不包含 customer ID、token、手机号、模型原文或供应商 request ID。`CustAppointmentCreate` 成功消费后立即删除;店/宠物/服务不再有效时按普通表单错误处理,不静默提交。
## 6. 业务事件与本体
M0 候选事件:
- `booking_agent_started`
- `booking_agent_draft_ready`
- `booking_agent_fallback`
M0 不记录 `booking_agent_confirmed`,也不修改现有 `appointment_created` metadata因为助手没有直接确认写入而客户端的 `source` 字符串不能当作服务端归因事实。如后续需要精确联结「助手草稿 -> 表单创建」,另立 brief 设计可验证、一次性的草稿交接机制。
编码前需增加或更新:
- `ontology/objects.md``booking_agent_session` gap/implemented 证据;
- `ontology/actions.md`:创建会话、提交消息、语音转写、回填草稿、结束会话;
- `ontology/events.md`M0 三个漏斗事件;
- `ontology/rules.md`customer 数据范围、无写工具、原始语音/原文不持久化、超时降级;
- `ontology/relations.md``graph/ontology.jsonl`
- `coverage/ontology-coverage-audit.md`
## 7. 自动化测试
### 7.1 后端必测
**意图提取契约**
- 30 条 `booking-intent-v1` fixture 均可解析;
- 无效 JSON、未知 schema 版本、未知枚举、超长备注和多余 ID 字段降级;
- 模型请求不包含手机号、token 或全量客户时间线。
**会话和权限**
- 未登录、boss/staff 调用助手 endpoint 被拒绝;
- A customer 无法查询、修改或结束 B customer session
- session 过期后不再接收消息;
- M0 不存在 `/confirm` endpoint
- 全套 M0 测试不会调用 `AppointmentMapper.save`
**预约事实**
- 宠物名唯一时解析到归属 Pet多宠物/同名返回歧义选项;
- 服务必须属于当前门店;
- 只返回 `available-slots` 真实可约候选;
- 过去日期、非营业时间和无号日期不生成 `appointmentTime`
- 相对日期在固定 Clock + `Asia/Shanghai` 下可重复测试。
**语音和日志**
- 空音频、错误 MIME、超 60 秒、超 3 MB 被拒绝;
- ASR 超时/失败映射 `ASR_UNAVAILABLE`
- 测试日志不出现音频 Base64、API Key、Authorization 或用户原文。
供应商单元测试使用本地 HTTP stubCI 不访问真实云 API。真实供应商 smoke 必须显式启用、使用本地密钥存储且不作为普通 `mvn test` 的一部分。
### 7.2 前端必测/手工 smoke
- customer 能进入boss/staff 不展示入口;
- 未登录进入时先登录,返回后进助手;
- 文字输入、发送 loading、网络失败和重试可理解
- 语音权限拒绝可切换文字;
- 转写可编辑,不自动继续提交;
- 多宠物、多服务、多号源可点选;
- 「带入普通预约」的门店、宠物、服务、时间和备注正确;
- 回填数据消费后从 Storage 删除;
- 对话失败或退出不影响普通表单;
- H5 和 mp-weixin 构建通过,小程序真机录音路径单独验收。
## 8. 实施顺序
### Batch 0本体、数据与契约冻结
OwnerSystem Architect + Data Model + Product Design
- 冻结 `booking-intent-v1`、M0 状态子集、API shape 和业务码;
- 更新本体及机器图谱;
- 评审 session 表、TTL 和清理方式;
- 完成 Access / Privacy Review。
### Batch 1供应商适配与契约测试
OwnerBackend Core
- 实现 provider interface、properties 和本地 HTTP stub
- 实现 Qwen JSON 提取与 Qwen3-ASR-Flash 转写;
- 建立 30 条文字 fixture
- 确保未配置/关闭时 fail closed不影响应用启动和普通预约。
### Batch 2会话、上下文解析和号源
OwnerBackend Core
- 实现 session 实体、迁移、mapper 和 service
- 复用 Pet、ServiceType、Store 和 BookingCapacity 领域服务;
- 实现确定性回复模板和 fallback DTO
- 完成权限、过期、时间和无写路径测试。
### Batch 3宠主对话页与回填
OwnerCustomer Experience FE
- 实现 BookingAgent 页、文字链路、选择芯片和草稿卡;
- 实现语音转写及隐私告知;
- 实现一次性草稿回填;
- 完成 H5/mp-weixin 构建和小程序真机 smoke。
### Batch 4对照、QA 与禁用默认
OwnerCore Flow QA + Backend Ops
- 跑 20 条已授权语音对照,归档关键槽位和延迟;
- 检查日志、错误映射、限流和降级;
- 默认保持 `PETSTORE_BOOKING_AGENT_ENABLED=false`
- 不进生产,等待 RC6 真实门店基线和用户明确变更授权。
## 9. Definition of Done
- [ ] 对话入口仅 customer 可见,所有后端 endpoint 仅 customer 可用。
- [ ] 文字和语音转写都能产生 `booking-intent-v1`
- [ ] 模型不能产生或传入业务 ID、服务事实和号源事实。
- [ ] 宠物、服务、时段全部由后端在当前数据范围重新解析。
- [ ] 任何模型/ASR/网络失败都能切换普通表单。
- [ ] 不存在助手 `/confirm` endpoint不调用预约写服务。
- [ ] 回填草稿消费后删除,并且不包含敏感字段。
- [ ] 原始语音、对话原文、密钥、token 和私密 URL 不落库、不进日志、不进 Git。
- [ ] 后端全测、H5/mp-weixin 构建和本体校验通过。
- [ ] 功能开关默认关闭,普通预约回归通过。
- [ ] 语料对照达到选型文档的准确率、延迟和安全门槛。
## 10. 必跑验证
```bash
cd /Users/apple/_src/petstore/backend && mvn test
cd /Users/apple/_src/petstore/backend && mvn -DskipTests package
cd /Users/apple/_src/petstore/frontend && npm run build:h5
cd /Users/apple/_src/petstore/frontend && npm run build:mp-weixin
cd /Users/apple/_src/petstore && python3 docs/graph/validate_ontology.py docs
cd /Users/apple/_src/petstore && python3 docs/graph/audit_drift.py
git -C /Users/apple/_src/petstore/backend diff --check
git -C /Users/apple/_src/petstore/frontend diff --check
git -C /Users/apple/_src/petstore/docs diff --check
```
另行归档:
- 30 条文字契约结果;
- 20 条语音关键槽位准确率、p50/p95 延迟;
- 错误/降级截图或低敏日志证据;
- H5 和 mp-weixin 构建摘要;
- 小程序真机录音权限、上传、转写和回填 smoke。
## 11. 发布与回滚
M0 完成也不等于生产开启。发布前必须再获得:
- 百炼业务空间、费用与数据边界审核;
- 小程序隐私告知与语音权限验收;
- 一家真实门店的小流量范围和回滚负责人;
- 主控 PM 对新 RC 和变更窗口的明确授权。
回滚优先级:
1. 关闭 `PETSTORE_BOOKING_AGENT_ENABLED`,隐藏入口;
2. 保留惰性 session 表,不执行破坏性回滚;
3. 普通 `CustAppointmentCreate` 仍可独立使用;
4. 语音/模型供应商故障时不影响预约、报告和回访主链路。
## 12. 外部输入与阻塞
不需要真实密钥也可完成 provider interface、状态机、本地 stub 和大部分前后端开发。以下项目只阻塞真实供应商 smoke 和上线:
- 阿里云百炼华北2北京Workspace ID
- 服务端 LLM/ASR API Key
- 账单和异常费用告警负责人;
- 语音数据处理和小程序隐私告知确认;
- 20 条已知情同意的脱敏语音对照样本;
- 生产开启授权。