7.5 KiB
7.5 KiB
数字分身图片与病例理解详细设计
1. 目标与边界
本功能让数字分身在私聊和公开分享聊天中接收图片,并围绕图片内容继续使用现有的“标准答题对 -> 分身独立知识库 -> Qwen 兼容模型”链路回答。
第一期支持 JPEG、PNG、WebP,覆盖以下场景:
- 普通照片、截图、图表和界面图片的内容理解。
- 病例、处方、检查单、检验报告等图片文档的文字和表格提取。
- X 光、CT、MRI 等医学影像的客观可见内容描述。
第一期不把通用视觉模型的输出当作医学诊断,不自动把图片或病例写入知识库,不保存原图供长期访问,也不支持 DICOM 原始影像。
2. 核心原则
- 资料优先级不变:标准答题对最高,分身独立知识库其次,图片识别结果属于待核对的会话资料,最后才由模型组织表达。
- 病例最小留存:应用不把原图写入业务存储,上传内容在内存中归一化并调用视觉服务;数据库只保存结构化结果和必要元数据。
- 严格隔离:每条图片记录必须绑定
avatar_id,私聊校验分身所有者,公开聊天校验分享令牌对应的分身。 - 不确定性显式化:OCR 看不清、表格列错位、医学影像无法确认时必须指出待核对项,不允许补齐缺失内容。
- 可计量:视觉理解和病例 OCR 分别计入分身所有者的积分消耗,失败时释放预留积分。
- 可降级:OCR 失败但通用视觉结果有效时仍可回答;视觉主调用失败则不进入聊天发送。
3. 总体流程
用户选择图片
-> 前端本地预览
-> 私聊/公开图片上传接口
-> 文件大小、MIME、真实格式、像素数校验
-> 自动旋转、缩放、去 EXIF、统一 JPEG
-> 通用视觉模型分类并输出结构化 JSON
-> 若为病例/检查单,再调用 OCR 模型精确转录
-> 保存结构化结果,不持久化原图
-> 返回 attachmentId
-> 用户发送文字 + attachmentIds
-> 标准答题对匹配
-> 用文字 + 图片提取结果检索独立知识库
-> 把标准答案、知识片段、图片资料注入系统上下文
-> Qwen SSE 流式回答
4. 模型编排
4.1 通用视觉模型
默认 qwen3.6-flash,可在后台数字分身专用模型配置中修改。输入为归一化后的 Base64 Data URL,要求返回 JSON:
{
"category": "general_image|document|medical_document|medical_image",
"summary": "客观、完整的图片描述",
"visible_text": "图片中可确认的文字",
"key_facts": ["事实1", "事实2"],
"uncertainties": ["无法确认的内容"],
"medical": {
"document_type": "",
"patient_info": {},
"chief_complaint": "",
"findings": [],
"measurements": [],
"doctor_advice": ""
}
}
模型提示词禁止诊断、补全被遮挡文字、猜测患者身份和输出模型信息。
4.2 病例 OCR
当 category=medical_document 时追加调用 qwen-vl-ocr,按原布局转录文字和表格。OCR 文本优先替换通用视觉输出中的 visible_text,但保留通用视觉模型提供的分类、摘要和不确定项。
4.3 医学影像
当 category=medical_image 时只保存客观描述,不输出疾病结论、分期、用药或治疗方案。聊天提示词必须要求结合正规影像报告和医生意见,并显示“图片识别结果仅供辅助,不能替代医生诊断”。
5. 数据模型
新增 chat_attachments:
| 字段 | 说明 |
|---|---|
id |
不可猜测的附件 ID |
avatar_id |
所属数字分身,强制隔离 |
filename |
原文件名,去除路径 |
mime_type / file_size |
上传元数据 |
status |
processing / ready / failed |
category |
图片分类 |
summary |
通用视觉摘要 |
extracted_text |
可确认文字/OCR 结果 |
structured_data |
结构化 JSON |
warning |
不确定项和医学提示 |
vision_model / ocr_model |
实际调用模型 |
created_at / used_at |
创建和最近使用时间 |
不保存公开原图 URL。应用层不落盘原图;框架上传缓冲在请求结束时关闭,处理结果在 24 小时后自动清理。
6. API 设计
6.1 上传并解析
POST /api/avatar/{avatar_id}/chat/imagesPOST /api/public/avatar/{share_token}/chat/imagesmultipart/form-data: file
成功返回:
{
"id": "attachment-id",
"filename": "病例.jpg",
"status": "ready",
"category": "medical_document",
"summary": "门诊检查单",
"warning": "部分手写内容需要人工核对"
}
6.2 聊天
原聊天接口增加:
{
"message": "请帮我看看异常指标",
"attachmentIds": ["attachment-id"],
"history": [
{"role": "user", "content": "上一条问题", "attachmentIds": ["attachment-id"]}
]
}
当前消息最多 3 张图,历史最多引用最近 3 个不同附件。后端只读取与当前 avatar_id 相同且状态为 ready 的记录。
7. 安全与隐私
- 单图最大 8MB,解码后最大 1600 万像素,最长边归一化到 4096 像素以内。
- 使用 Pillow 验证真实图片格式并防止解压炸弹;重新编码时清除 EXIF、GPS 和其他元数据。
- 图片不会写入 FastAPI
StaticFiles或知识库目录,模型请求和日志不得输出 Base64 内容。 - 日志只记录附件 ID、分身 ID、状态、耗时和模型,不记录图片 Base64、OCR 全文、病例内容或 API Key。
- 公开分享上传仍消耗分身所有者积分;余额不足时拒绝视觉调用。
- 生产环境需要补充用户授权、数据处理协议、存储地域和模型供应商留存策略确认。
8. 前端交互
- 输入框左侧增加图片按钮,支持相册选择和移动端拍照。
- 选择后显示本地缩略图和“正在识别图片”,识别完成前禁止发送。
- 用户可删除待发送图片;发送后图片保留在当前会话气泡中,但刷新页面后不恢复原图。
- 病例和医学影像在输入区及回答下方显示辅助提示,不使用恐吓式红色告警。
- 上传或识别失败时保留文字输入,明确提示重新选择图片,不产生空白消息。
9. 配置
数字分身专用模型配置新增:
vision_model_version,默认qwen3.6-flashocr_model_version,默认qwen-vl-ocr
环境变量兜底:
VISION_MODEL=qwen3.6-flash
VISION_OCR_MODEL=qwen-vl-ocr
VISION_MAX_OUTPUT_TOKENS=2048
VISION_TIMEOUT_SECONDS=90
VISION_TOKEN_RESERVE=12000
CHAT_IMAGE_MAX_BYTES=8388608
CHAT_IMAGE_MAX_PIXELS=16000000
CHAT_ATTACHMENT_RETENTION_HOURS=24
CHAT_ATTACHMENT_CLEANUP_MINUTES=60
视觉调用复用数字分身专用配置的 api_base_url 和 api_key,不额外复制密钥。
10. 验收标准
- 普通照片、截图和图表能够返回与图片一致的描述并支持追问。
- 病例图片可以提取标题、患者字段、检查结果、异常指标和医生意见,模糊内容明确标记待核对。
- 上传后服务器业务目录不残留原图,响应和日志不包含 Base64 或完整病例正文。
- A 分身无法引用 B 分身附件;公开分享令牌无法访问其他分身附件。
- 有图片时标准答题对仍作为最高优先级事实,知识库命中次之。
- 视觉与 OCR 积分分别结算,失败调用释放预留积分。
- SSE 打字效果、Markdown、用户头像、公开分享和纯文本聊天均无回归。
- CT、MRI、X 光回答不作确定诊断,并显示人工复核提示。