Files
operating-room-monitor-server/docs/client-api-integration.md
Kevin 69980d8073 feat: align surgery API with schemas and extend client tooling
- Refactor app API and schemas; adjust surgery pipeline, repository, and session manager.

- Improve consumption TSV logging and consumable vision integration; trim voice resolution.

- Add Baidu Face 1:N search script, .env.example entries, and client API integration doc.

- Update demo client, staging checklist, surgery interface doc, and related tests; add sample face image.

Made-with: Cursor
2026-04-23 16:09:20 +08:00

213 lines
9.4 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.
# 手术室监控服务 — 客户端 HTTP API 对接说明
本文档面向**集成我方 FastAPI 后端的客户系统**HIS、手麻、护理工作站、自研终端等说明如何通过 HTTP 调用完成「手术开始 / 结束」「耗材结果查询」「低置信度耗材语音确认」等能力。
> **说明**:仓库内 `scripts/demo_client/` 等演示页面仅用于**内部联调与测试**,不代表生产对接规范;生产环境请按本文档与 OpenAPI 契约自行实现客户端。
---
## 1. 服务与发现
| 项目 | 说明 |
| ------- | ------------------------------------------------------------- |
| 默认监听 | 应用默认 `0.0.0.0:38080`(以实际部署为准,可能经反向代理改写路径或端口) |
| 基础路径 | 路由**无全局前缀**;下文路径均为相对服务根路径 |
| OpenAPI | 服务启动后可访问 `**/docs`Swagger UI**、`**/redoc`** 获取实时 Schema 与试调 |
| 健康检查 | `GET /health`:探活与数据库连通性(降级时可能返回 503 |
| 跨域 CORS | 仅当服务端开启演示用 CORS 配置时对浏览器页面生效;**服务端对接通常不受 CORS 限制** |
认证方式以部署约定为准;当前公开路由未在文档层强制 API Key若贵方环境增加了网关鉴权请在请求头中按网关要求携带。
---
## 2. 客户端 API 一览(`/client/...`
所有「客户集成」接口均位于 `**/client`** 命名空间下。
| 方法 | 路径 | 摘要 |
| ------ | ------------------------------------------------------------------------------- | ------------------------- |
| `POST` | `/client/surgeries/start` | 开始手术:确认摄像头开录成功后返回 |
| `POST` | `/client/surgeries/end` | 结束手术:确认停录成功后返回 |
| `GET` | `/client/surgeries/{surgery_id}/result` | 查询该台手术的耗材明细与汇总 |
| `GET` | `/client/surgeries/{surgery_id}/pending-confirmation` | 拉取一条待确认项(含 TTS 音频 Base64 |
| `POST` | `/client/surgeries/{surgery_id}/pending-confirmation/{confirmation_id}/resolve` | 上传医生语音 WAV完成确认或否认 |
路径参数 `**surgery_id`**:固定 **6 位数字**(正则 `^\d{6}$`)。
---
## 3. 端到端业务流程(推荐时序)
以下为客户系统与手术室监控服务之间的**推荐调用顺序**与并行关系。
```mermaid
sequenceDiagram
participant Client as 客户系统
participant API as 监控服务 API
Client->>API: POST /client/surgeries/start
Note over Client,API: body: surgery_id, camera_ids, candidate_consumables
API-->>Client: 200 accepted开录已确认
par 术中轮询
loop 按需轮询
Client->>API: GET .../result
API-->>Client: 200 明细+汇总 或 503 RESULT_NOT_READY
end
loop 语音确认闭环(若启用)
Client->>API: GET .../pending-confirmation
API-->>Client: 200 待确认+MP3 或 404 无待确认
opt 有待确认
Client->>Client: 播放 prompt_audio_mp3_base64
Client->>API: POST .../resolvemultipart audio
API-->>Client: 200 accepted
end
end
end
Client->>API: POST /client/surgeries/end
API-->>Client: 200 accepted停录已确认
Client->>API: GET .../result
API-->>Client: 200 归档后持久化结果(若可查)
```
### 3.1 手术生命周期(状态视角)
```mermaid
flowchart LR
A[未开始] -->|POST start 成功| B[录制中 / 推理中]
B -->|GET result 可 200| C[可查消耗]
B -->|GET pending 可 200| D[有待确认]
D -->|POST resolve| B
B -->|POST end 成功| E[已结束]
E -->|GET result| C
```
---
## 4. 接口说明与请求/响应要点
### 4.1 `POST /client/surgeries/start`
**Content-Type**`application/json`
**请求体(摘要)**
| 字段 | 类型 | 说明 |
| ----------------------- | -------- | ------------------------------------------------------------- |
| `surgery_id` | string | 6 位数字手术号 |
| `camera_ids` | string[] | 至少 1 个;需与贵方 RTSP/SDK 映射中的 **摄像头 ID** 一致 |
| `candidate_consumables` | string[] | 可选;**本台手术可能用到的耗材名称清单**。服务端仅对该清单内耗材做自动记账与待确认追问;为空则只做拉流推理、不写入消耗 |
**成功200**`SurgeryApiResponse``status` 一般为 `accepted`,表示**服务端已确认开录完成**。
**失败**:常见 `**503 Service Unavailable`**`detail` 内含业务 `code`(如录制子系统未就绪、开录未确认等)。开录/停录类错误会按服务端配置**自动重试**;仍失败则返回最后一次错误信息。
### 4.2 `POST /client/surgeries/end`
**Content-Type**`application/json`
**请求体**`{ "surgery_id": "123456" }`
**成功200**:停录已确认。
**失败**`503` 同 start表示未能在确认摄像头全部停录后完成请求。
### 4.3 `GET /client/surgeries/{surgery_id}/result`
**幂等只读**。术中返回当前内存已记账结果;结束后返回数据库持久化结果(以服务端实现为准)。
**成功200**`SurgeryResultResponse`
- `details`:多行消耗明细,字段顺序为 `**item_id``item_name``qty``doctor_id``timestamp`**
- `summary`:按 `item_id` 汇总的 `total_quantity`
`**503`**`detail.code === "RESULT_NOT_READY"` — 尚无该手术可查询结果(未开始、未成功开录或暂无可返回数据)。
### 4.4 `GET /client/surgeries/{surgery_id}/pending-confirmation`
用于**低置信度识别**的人工确认闭环(需服务端启用语音确认及相关配置)。
**成功200**:包含 `confirmation_id``prompt_text`、候选项 `options``prompt_audio_mp3_base64`(与话术一致的 **MP3 标准 Base64**,无换行)、模型 Top1 等。
`**404`**:当前无待确认或手术未在进行(`NO_PENDING_CONFIRMATION`)。
`**422` / `503`**话术为空、音频无效、ASR/TTS/MinIO/百度语音等异常时返回,详见响应 `detail.code`
### 4.5 `POST /client/surgeries/{surgery_id}/pending-confirmation/{confirmation_id}/resolve`
**Content-Type**`multipart/form-data`
**表单字段**
| 字段 | 说明 |
| ------- | -------------------------------------------------------- |
| `audio` | 单个 `**.wav`** 文件;建议 16 kHz 单声道 PCM其他格式服务端可能尝试 ffmpeg 转码 |
**成功200**`SurgeryPendingConfirmationResolveResponse` — 含 `resolved_label``rejected``asr_text``audio_object_key` 等。
**常见 HTTP 状态**`404`(确认项不存在或已失效)、`409`(已处理)、`422`(音频/解析问题)、`503`(外部依赖故障)。
---
## 5. 错误约定
FastAPI 对 `HTTPException` 的 JSON 外形一般为:
```json
{
"detail": {
"code": "业务错误码",
"message": "人类可读说明",
"surgery_id": "123456"
}
}
```
部分错误可能在 `detail` 中附带额外字段(如重试剩余次数),请以实际响应与 OpenAPI 为准。
**校验错误422**:请求体或路径不符合 Pydantic 校验时FastAPI 可能返回标准 `422` 验证错误结构(与上表「对象型 detail」不同请客户端分别解析。
---
## 6. 与内部演示能力的关系(非客户必选)
以下路由用于**内部一键联调**,客户生产系统**无需依赖**
| 路径 | 说明 |
| ------------------------------------------- | -------------------------------------------------- |
| `GET /internal/demo/orchestrator-status` | 探测演示编排是否开启、RTSP 配置文件是否设置等 |
| `POST /internal/demo/orchestrate-and-start` | 仅在服务端开启 `DEMO_ORCHESTRATOR_ENABLED` 时注册;用于演示环境串联开录 |
客户正式对接应直接调用 `**/client/...`**,并在贵方环境中配置真实的 `camera_ids` 与视频后端映射。
---
## 7. 联调建议
1. 先调用 `**GET /health`** 确认服务与数据库可用。
2.`**POST /client/surgeries/start`** 验证 `camera_ids` 与现场 RTSP/SDK 配置一致,避免 503。
3. `**candidate_consumables**` 与实际手术耗材名称尽量与院内目录或模型标签对齐,减少待确认次数。
4. 结果查询 `**503**` 时建议**退避重试**(术中数据尚未就绪属正常现象)。
5.`**/docs`** 导出或对照契约测试,与贵方 CI 中的契约测试对齐。
---
## 8. 文档修订
接口行为以部署实例的 **OpenAPI`/docs`** 与代码为准;字段含义补充见仓库内 `app/schemas.py` 中各模型的 `description`