Files
huihuiSquare/digital-avatar-app/docs/IMAGE_MEDICAL_UNDERSTANDING_DESIGN.md
T

7.5 KiB
Raw Blame History

数字分身图片与病例理解详细设计

1. 目标与边界

本功能让数字分身在私聊和公开分享聊天中接收图片,并围绕图片内容继续使用现有的“标准答题对 -> 分身独立知识库 -> Qwen 兼容模型”链路回答。

第一期支持 JPEG、PNG、WebP,覆盖以下场景:

  1. 普通照片、截图、图表和界面图片的内容理解。
  2. 病例、处方、检查单、检验报告等图片文档的文字和表格提取。
  3. 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/images
  • POST /api/public/avatar/{share_token}/chat/images
  • multipart/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-flash
  • ocr_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. 验收标准

  1. 普通照片、截图和图表能够返回与图片一致的描述并支持追问。
  2. 病例图片可以提取标题、患者字段、检查结果、异常指标和医生意见,模糊内容明确标记待核对。
  3. 上传后服务器业务目录不残留原图,响应和日志不包含 Base64 或完整病例正文。
  4. A 分身无法引用 B 分身附件;公开分享令牌无法访问其他分身附件。
  5. 有图片时标准答题对仍作为最高优先级事实,知识库命中次之。
  6. 视觉与 OCR 积分分别结算,失败调用释放预留积分。
  7. SSE 打字效果、Markdown、用户头像、公开分享和纯文本聊天均无回归。
  8. CT、MRI、X 光回答不作确定诊断,并显示人工复核提示。