diff --git a/docs/2.功能设计/2.NMPA注册资料法规核查与整改闭环.md b/docs/2.功能设计/2.NMPA注册资料法规核查与整改闭环.md new file mode 100644 index 0000000..a63d303 --- /dev/null +++ b/docs/2.功能设计/2.NMPA注册资料法规核查与整改闭环.md @@ -0,0 +1,730 @@ +# NMPA 注册资料法规核查与整改闭环工作流功能设计 + +## 文档信息 + +| 项目 | 内容 | +| --- | --- | +| 需求分析文档 | docs/1.需求分析/2.NMPA注册资料法规核查与整改闭环.md | +| 依赖功能设计 | docs/2.功能设计/1.自动汇总.md | +| 功能名称 | NMPA 注册资料法规核查与整改闭环 | +| 所属模块 | 审核智能体 review_agent | +| 设计日期 | 2026-06-06 | +| 设计版本 | V1.0 | + +--- + +## 一、设计目标 + +本功能在“自动汇总文件夹文件目录与页数流程”基础上扩展,不重复实现上传、解压、文件扫描、页数统计、基础导出和 SSE 推送能力。法规核查工作流复用已有 `FileSummaryBatch` 和 `FileSummaryItem` 作为资料清单输入,新增法规规则库、RAG 法规依据索引、法规核查批次、风险问题、过程产物、飞书通知和整改复核能力。 + +工作流支持两种启动方式:用户可以在已有文件汇总批次完成后发起法规核查;也可以直接在上传资料后发起法规核查,系统内部先执行自动汇总,再串联执行法规核查。若同一对话已存在最近一次成功的文件汇总批次,默认复用该批次。 + +前端需要新增独立的法规核查工作流卡片。一个对话内可能同时存在“文件汇总”和“法规核查”等多个工作流卡片,卡片区域采用类似轮播图的切换方式展示当前活跃卡片和历史卡片。底层 SSE 事件机制复用现有 `workflow` 事件,通过 `workflow_type` 区分 `file_summary` 与 `regulatory_review`。 + +--- + +## 二、与自动汇总功能的关系 + +### 2.1 复用边界 + +| 能力 | 处理方式 | 说明 | +| --- | --- | --- | +| 上传接收 | 复用 | 沿用 `FileAttachment`、`FileSummaryBatchAttachment` 和上传接收接口 | +| 压缩包解压 | 复用 | 沿用自动汇总的解压 Skill 和工作目录规则 | +| 文件清单扫描 | 复用 | 以 `FileSummaryItem` 作为法规核查文件清单 | +| 页数统计 | 复用 | 法规核查直接读取页数和解析状态 | +| 基础节点状态 | 复用 | 沿用 `WorkflowNodeRun` 事件模型,新增 workflow_type | +| Markdown/Excel 下载 | 部分复用 | 最终报告进入 `ExportedSummaryFile`,过程产物进入 `RegulatoryArtifact` | +| 产品名识别 | 不扩展 | 原 `产品信息识别 Skill` 继续只服务自动汇总标题识别 | + +### 2.2 新增边界 + +| 能力 | 说明 | +| --- | --- | +| 法规适用信息抽取 | 新增 `RegulatoryInfoExtract Skill`,抽取注册类型、临床评价路径、产品关键信息 | +| 适用条件确认 | 通过 AI 对话选择框让用户确认或自由补充 | +| 规则文件与 RAG | 结构化规则文件负责判断,RAG 负责法规依据引用和解释 | +| 法规核查批次 | 新增 `RegulatoryReviewBatch`,关联 `FileSummaryBatch` | +| 风险问题与整改状态 | 新增 `RegulatoryIssue`,记录问题、风险、证据、责任人、状态 | +| 过程产物留底 | 新增 `RegulatoryArtifact`,保存条件确认、核查矩阵、风险清单、复核记录等 | +| 飞书通知 | 新增 `FeishuNotifier` 抽象接口,Demo 实现接飞书 CLI | + +--- + +## 三、总体架构 + +### 3.1 架构原则 + +| 原则 | 说明 | +| --- | --- | +| 依赖汇总批次 | 法规核查必须绑定一个 `FileSummaryBatch`,不能跨对话读取文件 | +| 工作流独立 | 法规核查拥有独立卡片、批次和节点,但事件通道可复用 | +| 规则优先 | 合规判断以结构化规则文件为准,RAG 只做法规依据检索和解释增强 | +| 人工确认 | 适用条件缺失时停在待确认,复核通过关闭前需要人工确认 | +| 过程留底 | 所有关键过程文档都要留底,便于复核和 Demo 展示 | +| 通知可替换 | 飞书发送通过接口抽象,Demo 接 CLI,后续可替换为 Webhook/API | + +### 3.2 逻辑架构 + +```mermaid +flowchart TD + A["AI 对话页"] --> B["工作流卡片轮播区"] + A --> C["法规核查启动接口"] + C --> D{"是否已有成功 FileSummaryBatch"} + D -->|"有"| E["复用最近成功汇总批次"] + D -->|"无"| F["串联执行自动汇总工作流"] + F --> E + E --> G["RegulatoryReviewBatch"] + G --> H["RegulatoryWorkflowExecutor"] + H --> I["SkillRegistry"] + I --> I1["RegulatoryInfoExtract Skill"] + I --> I2["TextExtract Skill"] + I --> I3["CompletenessCheck Skill"] + I --> I4["StructureCheck Skill"] + I --> I5["ConsistencyCheck Skill"] + I --> I6["RiskAssess Skill"] + I --> I7["RegulatoryReportExport Skill"] + H --> J["结构化规则文件"] + H --> K["本地法规 RAG 索引"] + H --> L["RegulatoryIssue"] + H --> M["RegulatoryArtifact"] + H --> N["FeishuNotifier CLI"] + H --> O["workflow SSE 事件"] + O --> B +``` + +### 3.3 技术选型 + +| 设计项 | Demo 方案 | 后续演进 | +| --- | --- | --- | +| 工作流编排 | 复用轻量 WorkflowExecutor 思路,新增 RegulatoryWorkflowExecutor | 接入 LangGraph 子图 | +| 事件机制 | 复用 `workflow` SSE,新增 `workflow_type=regulatory_review` | 独立工作流事件中心 | +| 规则存储 | 项目内 JSON/YAML 规则文件 | 规则管理后台 + 数据库版本表 | +| 法规依据检索 | 本地 CMDE 文档构建 RAG 索引 | 法规资料定期更新和重建索引 | +| 文本抽取 | 新增统一 TextExtract Skill | 建立文档文本缓存和 OCR 能力 | +| 飞书通知 | `FeishuNotifier` 接飞书 CLI,可直接测试发送 | 飞书开放平台 Webhook/API | +| 过程产物 | Markdown、Excel、JSON 留底 | 对象存储 + 证据快照管理 | + +--- + +## 四、工作流设计 + +### 4.1 启动方式 + +| 场景 | 处理方式 | +| --- | --- | +| 已有成功文件汇总批次 | 默认复用当前对话最近一次成功 `FileSummaryBatch` | +| 无成功文件汇总批次 | 系统先串联执行自动汇总,再执行法规核查 | +| 用户修改适用条件后重核 | 创建新的 `RegulatoryReviewBatch`,保留旧批次记录 | +| 用户补充缺失文件复核 | 通过对话指令上传补充文件,合并到原问题上下文后复核 | + +### 4.2 节点图 + +```mermaid +flowchart LR + N1["准备资料"] --> N2["识别信息"] + N2 --> N3{"适用条件是否完整"} + N3 -->|"否"| W["待用户确认"] + W --> N4["裁剪规则"] + N3 -->|"是"| N4 + N4 --> N5["完整性核查"] + N5 --> N6["文本抽取"] + N6 --> N7["章节核查"] + N6 --> N8["一致性核查"] + N7 --> N9["风险分级"] + N8 --> N9 + N9 --> N10["报告导出"] + N10 --> N11["飞书通知"] + N11 --> N12["待整改复核"] + N12 --> N13["完成"] + N4 -->|"规则加载失败"| R["RAG 辅助核查"] + R --> N9 +``` + +### 4.3 主节点与子节点 + +法规核查卡片展示主节点,主节点可展开查看子节点。 + +| 主节点 | 子节点 | 说明 | +| --- | --- | --- | +| 准备资料 | 复用批次、检查文件清单、读取规则版本 | 绑定 `FileSummaryBatch` | +| 识别信息 | 产品信息抽取、适用条件识别 | 生成用户确认项 | +| 确认条件 | 对话选择框确认、自由补充 | 卡片只展示等待状态 | +| 法规核查 | 规则裁剪、完整性核查、文本抽取、章节核查、一致性核查 | 完整性先跑,章节和一致性并行 | +| 风险输出 | 风险分级、建议生成、RAG 依据引用、报告导出 | 生成问题和过程产物 | +| 通知复核 | 飞书通知、补充资料、整改复核、关闭确认 | 支持后续闭环 | + +### 4.4 节点定义 + +| 节点编码 | 节点名称 | 触发 Skill/服务 | 成功条件 | 失败或暂停处理 | +| --- | --- | --- | --- | --- | +| prepare | 准备资料 | RegulatoryWorkflowExecutor | 绑定成功的 `FileSummaryBatch` | 无汇总批次则串联自动汇总 | +| info_extract | 识别信息 | RegulatoryInfoExtract Skill | 输出适用条件候选值 | 缺少关键条件则进入待确认 | +| condition_confirm | 确认条件 | Conversation Interaction | 用户确认产品类别、注册类型、临床路径等 | 暂停等待用户输入 | +| rule_scope | 裁剪规则 | RuleLoader | 生成本次适用规则清单 | 规则加载失败则降级 RAG 辅助核查 | +| completeness_check | 完整性核查 | CompletenessCheck Skill | 输出缺失文件和文件项问题 | 单项失败记录待确认 | +| text_extract | 文本抽取 | TextExtract Skill | 抽取关键文件文本和首页内容 | 单文件失败记录问题并继续 | +| structure_check | 章节核查 | StructureCheck Skill | 输出章节缺失和格式问题 | 与一致性核查并行 | +| consistency_check | 一致性核查 | ConsistencyCheck Skill | 输出字段冲突问题 | 低置信度字段可用 LLM 辅助 | +| risk_assess | 风险分级 | RiskAssess Skill | 归并问题、生成风险等级和建议 | 无 RAG 依据时仍输出规则问题 | +| report_export | 报告导出 | RegulatoryReportExport Skill | 生成 Markdown、Excel、JSON 产物 | 导出失败记录批次失败 | +| notify | 飞书通知 | FeishuNotifier | 阻断项、高风险、中风险完成通知 | CLI 失败写入通知失败记录 | +| rectify_review | 整改复核 | RectificationReview Skill | 输出复核通过/不通过 | 关闭前等待人工确认 | + +--- + +## 五、规则库与 RAG 设计 + +### 5.1 双层法规能力 + +| 层级 | 职责 | 不承担的职责 | +| --- | --- | --- | +| 结构化规则库 | 判断文件项、章节项、关键字段、一致性字段、风险等级和整改模板 | 不负责自由解释法规 | +| RAG 法规依据索引 | 从本地 CMDE 原文材料检索法规依据片段、来源文件和引用说明 | 不直接决定合规结论 | + +### 5.2 规则文件结构 + +Demo 阶段规则采用项目内 JSON/YAML 文件维护,建议路径: + +```text +review_agent/rules/nmpa_ivd_registration_v1.yaml +``` + +规则文件需要包含版本信息: + +| 字段 | 说明 | +| --- | --- | +| version | 规则版本,如 nmpa_ivd_2021_v1 | +| source_url | https://www.cmde.org.cn/xwdt/zxyw/20210930163300622.html | +| source_path | 本地 CMDE 法规材料路径 | +| effective_date | 规则生效日期或公告发布日期 | +| rag_index_version | 对应 RAG 索引版本 | + +规则项最小结构: + +```yaml +version: nmpa_ivd_2021_v1 +source_url: https://www.cmde.org.cn/xwdt/zxyw/20210930163300622.html +source_path: docs/0.原始材料/关于公布体外诊断试剂注册申报资料要求和批准证明文件格式的公告 +effective_date: "2021-09-30" +file_items: + - rule_id: ivd_registration_test_report + title: 注册检验报告 + required_type: required + applies_when: + product_category: in_vitro_diagnostic + registration_type: initial_registration + match_keywords: + file_name: ["注册检验报告", "检验报告"] + directory: ["注册检验", "检测报告"] + first_pages: ["医疗器械注册检验报告", "检验结论"] + required_sections: ["样品信息", "检验依据", "检验项目", "检验结论", "签章"] + required_fields: ["产品名称", "型号规格", "样本类型"] + consistency_fields: ["产品名称", "型号规格"] + default_risk_level: blocking + suggestion_template: 请补充与本产品一致的注册检验报告,并确保报告包含样品信息、检验依据、检验项目、检验结论和签章页。 +``` + +### 5.3 规则加载策略 + +| 场景 | 处理方式 | +| --- | --- | +| 规则文件正常加载 | 按结构化规则执行核查,RAG 补充法规依据 | +| 规则文件加载失败 | 降级为 RAG 辅助核查,报告明确标记“仅供参考,不输出正式合规结论” | +| 规则命中但 RAG 无依据 | 仍输出问题,法规依据标记“规则库依据,原文待补充” | +| 规则版本与 RAG 版本不一致 | 批次标记提示项,允许继续但报告记录版本差异 | + +### 5.4 RAG 索引设计 + +| 项目 | 说明 | +| --- | --- | +| 资料来源 | 本地 CMDE 公告目录下的 doc/docx 文档 | +| 索引粒度 | 按标题、段落、表格行或文件项说明切分 | +| 元数据 | source_file、section_title、page_or_row、rule_version、source_url | +| 输出 | matched_snippets、source_file、score、citation_text | +| 用途 | 风险报告中的法规依据、AI 对话解释、飞书通知简要依据 | + +--- + +## 六、Skill 设计 + +### 6.1 RegulatoryInfoExtract Skill + +| 项目 | 说明 | +| --- | --- | +| 中文名称 | 法规适用信息抽取 Skill | +| 职责 | 从 `FileSummaryItem`、文件名、目录名和文本片段中抽取法规适用条件 | +| 输入 | regulatory_batch_id、file_summary_batch_id、file_items | +| 输出 | 产品类别、注册类型、临床评价路径、产品名称、型号规格、预期用途、置信度、证据 | +| 关键规则 | 不修改自动汇总的产品名识别 Skill;缺少关键条件时暂停等待用户确认 | + +用户确认字段: + +| 字段 | 是否必填 | 说明 | +| --- | --- | --- | +| 产品类别 | 是 | 医疗器械/体外诊断试剂等 | +| 注册类型 | 是 | 首次注册、变更注册、延续注册等 | +| 临床评价路径 | 是 | 临床试验、免临床、同品种比对等 | +| 产品名称 | 是 | 用于一致性核查 | +| 型号规格 | 是 | 用于一致性核查 | +| 预期用途 | 是 | 用于规则裁剪和一致性核查 | + +### 6.2 TextExtract Skill + +| 项目 | 说明 | +| --- | --- | +| 中文名称 | 文本抽取 Skill | +| 职责 | 按需抽取关键文件首页、前几页、章节文本和字段候选值 | +| 输入 | regulatory_batch_id、file_item_ids、extract_scope | +| 输出 | text_blocks、first_page_text、section_candidates、field_candidates | +| 数据写入 | RegulatoryArtifact,artifact_type=text_extract_json | +| 关键规则 | 统一抽取,避免完整性、章节、一致性节点重复读取文件 | + +### 6.3 CompletenessCheck Skill + +| 项目 | 说明 | +| --- | --- | +| 中文名称 | 法规资料完整性核查 Skill | +| 职责 | 对照适用规则清单检查文件项和文件项子项是否存在 | +| 输入 | regulatory_batch_id、file_summary_items、scoped_rules | +| 输出 | missing_items、matched_items、pending_confirm_items | +| 关键规则 | 文件匹配采用文件名、目录名、首页内容三层匹配,记录命中证据 | + +### 6.4 StructureCheck Skill + +| 项目 | 说明 | +| --- | --- | +| 中文名称 | 章节结构核查 Skill | +| 职责 | 检查关键文件是否包含规则要求章节 | +| 输入 | regulatory_batch_id、text_blocks、required_sections | +| 输出 | missing_sections、abnormal_sections、evidence | +| 关键规则 | 章节缺失按规则初始等级输出,由 RiskAssess 统一归并 | + +### 6.5 ConsistencyCheck Skill + +| 项目 | 说明 | +| --- | --- | +| 中文名称 | 跨文件一致性核查 Skill | +| 职责 | 抽取并比对产品名称、型号规格、预期用途等核心字段 | +| 输入 | regulatory_batch_id、text_blocks、consistency_fields | +| 输出 | field_values、conflicts、confidence | +| 关键规则 | 规则/正则优先,失败或置信度低时调用 LLM 辅助抽取结构化 JSON | + +### 6.6 RiskAssess Skill + +| 项目 | 说明 | +| --- | --- | +| 中文名称 | 风险分级与整改建议 Skill | +| 职责 | 归并核查问题,统一风险等级,生成整改建议和法规依据 | +| 输入 | all_check_findings、rules、rag_results | +| 输出 | RegulatoryIssue 列表、risk_summary、suggestions | +| 关键规则 | 核查节点提供初始等级,RiskAssess 负责去重、合并、升级或降级 | + +### 6.7 RegulatoryReportExport Skill + +| 项目 | 说明 | +| --- | --- | +| 中文名称 | 法规核查报告导出 Skill | +| 职责 | 生成最终报告和过程产物 | +| 输入 | regulatory_batch_id、issues、artifacts、notification_records | +| 输出 | Markdown 报告、Excel 清单、JSON 产物、下载链接 | +| 关键规则 | 最终报告进入 `ExportedSummaryFile`,过程产物进入 `RegulatoryArtifact` | + +### 6.8 FeishuNotifier + +| 项目 | 说明 | +| --- | --- | +| 中文名称 | 飞书通知适配器 | +| 职责 | 对阻断项、高风险、中风险发送飞书通知并 @ 上传人 | +| 输入 | recipient、risk_summary、message_markdown | +| 输出 | send_status、external_message_id、error_message | +| Demo 实现 | 抽象接口接飞书 CLI,并支持直接测试发送 | +| 后续演进 | 替换为飞书 Webhook/API | + +--- + +## 七、数据模型设计 + +### 7.1 RegulatoryReviewBatch + +法规核查批次,表示一次法规核查工作流执行。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| id | BigAutoField | 主键 | +| conversation | ForeignKey(Conversation) | 绑定对话 | +| user | ForeignKey(User) | 发起用户 | +| file_summary_batch | ForeignKey(FileSummaryBatch) | 关联文件汇总批次 | +| batch_no | CharField | 法规核查批次编号 | +| status | CharField | pending、running、waiting_user、success、failed、reference_only、partial_success、cancelled | +| rule_version | CharField | 使用的结构化规则版本 | +| rule_source_url | URLField | 法规来源 URL | +| rule_source_path | CharField | 本地法规资料路径 | +| rag_index_version | CharField | RAG 索引版本 | +| product_category | CharField | 用户确认后的产品类别 | +| registration_type | CharField | 用户确认后的注册类型 | +| clinical_evaluation_path | CharField | 用户确认后的临床评价路径 | +| product_name | CharField | 产品名称 | +| model_specification | CharField | 型号规格 | +| intended_use | TextField | 预期用途 | +| risk_summary_json | JSONField | 风险数量摘要 | +| error_message | TextField | 异常说明 | +| created_at | DateTimeField | 创建时间 | +| started_at | DateTimeField | 开始时间 | +| finished_at | DateTimeField | 完成时间 | + +### 7.2 RegulatoryIssue + +法规核查问题和整改状态实体。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| id | BigAutoField | 主键 | +| batch | ForeignKey(RegulatoryReviewBatch) | 所属法规核查批次 | +| issue_code | CharField | 问题编码 | +| issue_type | CharField | completeness、structure、consistency、notification、review | +| risk_level | CharField | blocking、high、medium、low、info | +| title | CharField | 问题标题 | +| description | TextField | 问题描述 | +| rule_id | CharField | 命中的规则 ID | +| regulation_basis | TextField | 法规依据或规则依据 | +| evidence_json | JSONField | 文件路径、页码、文本片段、字段值等证据 | +| suggestion | TextField | 整改建议 | +| owner | ForeignKey(User) | 默认上传人 | +| status | CharField | 待确认、待处理、已补充、复核通过、复核不通过、已关闭 | +| confirmed_by | ForeignKey(User) | 确认人,可为空 | +| closed_by | ForeignKey(User) | 关闭人,可为空 | +| created_at | DateTimeField | 创建时间 | +| updated_at | DateTimeField | 更新时间 | + +### 7.3 RegulatoryArtifact + +法规核查过程产物留底实体。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| id | BigAutoField | 主键 | +| batch | ForeignKey(RegulatoryReviewBatch) | 所属法规核查批次 | +| artifact_type | CharField | condition_record、rule_matrix、risk_list、text_extract_json、rag_result_json、notification_record、review_record | +| file_format | CharField | markdown、excel、json | +| file_name | CharField | 文件名 | +| storage_path | CharField | 存储路径 | +| summary | TextField | 产物摘要 | +| created_at | DateTimeField | 创建时间 | + +### 7.4 RegulatoryNotificationRecord + +飞书通知记录。 + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| id | BigAutoField | 主键 | +| batch | ForeignKey(RegulatoryReviewBatch) | 所属法规核查批次 | +| recipient | ForeignKey(User) | 通知对象 | +| channel | CharField | feishu_cli、feishu_api、mock | +| risk_levels | JSONField | 本次通知包含的风险等级 | +| message_summary | TextField | 通知摘要 | +| send_status | CharField | pending、success、failed | +| external_message_id | CharField | 外部消息 ID,可为空 | +| error_message | TextField | 失败原因 | +| sent_at | DateTimeField | 发送时间 | + +### 7.5 与既有模型关系 + +```text +Conversation 1:N FileSummaryBatch +FileSummaryBatch 1:N FileSummaryItem +FileSummaryBatch 1:N RegulatoryReviewBatch +RegulatoryReviewBatch 1:N RegulatoryIssue +RegulatoryReviewBatch 1:N RegulatoryArtifact +RegulatoryReviewBatch 1:N RegulatoryNotificationRecord +RegulatoryReviewBatch 1:N ExportedSummaryFile +``` + +--- + +## 八、接口设计 + +### 8.1 发起法规核查 + +| 项目 | 内容 | +| --- | --- | +| URL | POST /api/review-agent/regulatory-review/start/ | +| 认证 | 登录用户 | +| 请求 | conversation_id、file_summary_batch_id 可选、force_resummary 可选 | +| 响应 | regulatory_batch_id、workflow_type、status | + +处理规则: + +| 场景 | 说明 | +| --- | --- | +| 传入 file_summary_batch_id | 校验该批次属于当前对话和用户 | +| 未传入 file_summary_batch_id | 默认查找当前对话最近一次成功汇总批次 | +| 无成功汇总批次 | 自动启动文件汇总工作流,完成后继续法规核查 | + +### 8.2 提交适用条件确认 + +| 项目 | 内容 | +| --- | --- | +| URL | POST /api/review-agent/regulatory-review/{batch_id}/confirm-condition/ | +| 认证 | 登录用户 | +| 请求 | product_category、registration_type、clinical_evaluation_path、product_name、model_specification、intended_use | +| 响应 | batch_id、status、next_node | + +说明:对话选择框负责收集用户确认结果,接口只接收结构化确认值。用户修改已确认条件时创建新的 `RegulatoryReviewBatch`。 + +### 8.3 查询法规核查状态 + +| 项目 | 内容 | +| --- | --- | +| URL | GET /api/review-agent/regulatory-review/{batch_id}/ | +| 认证 | 登录用户 | +| 响应 | 批次状态、主节点状态、风险摘要、导出文件、过程产物 | + +用途: + +| 场景 | 说明 | +| --- | --- | +| 页面刷新恢复 | 恢复法规核查卡片状态 | +| 卡片轮播切换 | 切换历史工作流卡片时加载详情 | +| 整改复核 | 查看待处理和待确认问题 | + +### 8.4 发起整改复核 + +| 项目 | 内容 | +| --- | --- | +| URL | POST /api/review-agent/regulatory-review/{batch_id}/rectify-review/ | +| 认证 | 登录用户 | +| 请求 | issue_ids、uploaded_files 可选、review_mode | +| 响应 | review_record_id、status、updated_issues | + +Demo 阶段主要通过对话指令触发,卡片入口作为设计预留。 + +### 8.5 下载法规核查文件 + +| 项目 | 内容 | +| --- | --- | +| URL | GET /api/review-agent/regulatory-review/artifacts/{artifact_id}/download/ | +| 认证 | 登录用户 | +| 响应 | 文件流 | + +权限规则: + +```text +artifact_id -> regulatory_batch -> conversation -> user +必须等于当前登录用户,才允许下载。 +``` + +--- + +## 九、前端设计 + +### 9.1 多工作流卡片轮播 + +AI 对话页顶部或对话流内的工作流区域支持多个工作流卡片。 + +| 设计点 | 说明 | +| --- | --- | +| 展示方式 | 顶部只显示当前活跃卡片,通过左右箭头或点位切换历史卡片 | +| 卡片类型 | file_summary、regulatory_review | +| 事件更新 | 统一监听 `workflow` SSE,根据 workflow_type 和 batch_id 更新对应卡片 | +| 卡片职责 | 展示工作流状态,不承载适用条件编辑表单 | +| 历史恢复 | 页面刷新后按对话查询工作流批次并恢复卡片列表 | + +### 9.2 法规核查卡片 + +卡片主节点: + +| 主节点 | 展示文案 | +| --- | --- | +| prepare | 准备资料 | +| info_extract | 识别信息 | +| condition_confirm | 确认条件 | +| regulatory_check | 法规核查 | +| risk_output | 风险输出 | +| notify_review | 通知复核 | +| completed | 已完成 | + +节点可展开展示子节点,例如法规核查下展开“规则裁剪、完整性核查、文本抽取、章节核查、一致性核查”。 + +### 9.3 适用条件确认交互 + +适用条件确认采用 AI 对话选择框,不放在卡片内。交互形式参考计划模式:系统给出识别结果、推荐选项和自由输入能力。 + +确认字段: + +| 字段 | 交互方式 | +| --- | --- | +| 产品类别 | 选项 + 自由输入 | +| 注册类型 | 选项 + 自由输入 | +| 临床评价路径 | 选项 + 自由输入 | +| 产品名称 | 文本确认 | +| 型号规格 | 文本确认 | +| 预期用途 | 文本确认 | + +### 9.4 对话框结果展示 + +工作流完成后新增助手消息,优先展示风险摘要、待处理问题和下载链接。 + +```markdown +已完成 NMPA 注册资料法规核查。 + +| 风险等级 | 数量 | +| --- | --- | +| 阻断项 | 2 | +| 高风险 | 1 | +| 中风险 | 3 | +| 低风险 | 4 | +| 提示项 | 2 | + +| 等级 | 问题 | 状态 | 建议 | +| --- | --- | --- | --- | +| 阻断项 | 缺少注册检验报告 | 待处理 | 请补充注册检验报告并发起复核 | + +[下载 Markdown 核查报告](download-url) +[下载 Excel 缺失清单](download-url) +[下载过程产物 JSON](download-url) +``` + +--- + +## 十、事件设计 + +### 10.1 SSE 事件结构 + +复用现有 `workflow` 事件,新增字段区分工作流。 + +```json +{ + "event": "workflow", + "workflow_type": "regulatory_review", + "batch_id": 2001, + "conversation_id": 1001, + "node_code": "structure_check", + "node_group": "regulatory_check", + "status": "running", + "message": "正在核查关键文件章节结构", + "progress": 62, + "payload": { + "risk_summary": { + "blocking": 1, + "high": 2 + } + } +} +``` + +### 10.2 状态扩展 + +| 状态 | 含义 | +| --- | --- | +| pending | 已创建,等待执行 | +| running | 执行中 | +| waiting_user | 等待用户确认适用条件 | +| success | 节点成功 | +| failed | 节点失败 | +| reference_only | 规则库不可用,降级为 RAG 辅助核查 | +| partial_success | 部分节点、通知或非关键过程产物失败,但已输出主要结果 | +| cancelled | 用户或系统取消执行 | +| skipped | 当前节点跳过 | + +--- + +## 十一、输出与留底设计 + +### 11.1 最终下载文件 + +最终面向用户下载的报告沿用 `ExportedSummaryFile`。 + +| 文件 | 说明 | +| --- | --- | +| Markdown 核查报告 | 面向人工阅读的完整法规核查报告 | +| Excel 缺失清单 | 面向整改跟踪的风险和缺失清单 | +| JSON 结果包 | 面向后续复核和系统处理的结构化结果 | + +### 11.2 过程产物 + +过程产物进入 `RegulatoryArtifact`。 + +| 产物类型 | 格式 | 说明 | +| --- | --- | --- | +| condition_record | markdown/json | 适用条件识别和用户确认记录 | +| rule_matrix | excel/json | 法规核查矩阵 | +| risk_list | markdown/json | 风险清单和等级归并结果 | +| text_extract_json | json | 关键文件文本抽取结果 | +| rag_result_json | json | RAG 检索依据和引用片段 | +| notification_record | markdown/json | 飞书通知记录 | +| review_record | markdown/json | 整改复核记录 | + +--- + +## 十二、异常与降级设计 + +| 场景 | 处理 | +| --- | --- | +| 无成功文件汇总批次 | 自动串联执行文件汇总;汇总失败则法规核查不启动 | +| 规则文件加载失败 | 降级为 RAG 辅助核查,标记 `reference_only`,报告声明仅供参考 | +| RAG 检索不到依据 | 规则命中的问题仍输出,依据标记“规则库依据,原文待补充” | +| 关键适用条件缺失 | 工作流进入 `waiting_user`,用户确认后继续 | +| 文本抽取失败 | 记录文件级问题,相关章节或一致性结果标记待确认 | +| LLM 字段抽取失败 | 回退规则/正则结果,低置信度字段进入待确认 | +| 飞书 CLI 发送失败 | 记录通知失败,不阻断报告生成 | +| 过程产物导出失败 | 批次标记失败或部分失败,错误信息写入批次 | + +--- + +## 十三、安全设计 + +| 设计点 | 说明 | +| --- | --- | +| 对话隔离 | RegulatoryReviewBatch 必须绑定当前 Conversation | +| 文件访问 | 只能读取关联 FileSummaryBatch 下的 FileSummaryItem | +| 下载权限 | 导出文件和过程产物下载必须校验 conversation.user | +| 飞书脱敏 | 飞书通知只展示风险摘要和必要文件名,不直接发送敏感全文 | +| 证据留痕 | 证据片段写入受控存储,不暴露给无权限用户 | +| CLI 安全 | 飞书 CLI 参数使用结构化调用,避免拼接执行用户输入 | + +--- + +## 十四、验收设计 + +| 序号 | 验收项 | 验收标准 | +| --- | --- | --- | +| 1 | 汇总复用 | 已有成功文件汇总批次时,法规核查默认复用最近批次 | +| 2 | 串联启动 | 无成功汇总批次时,可先自动汇总再执行法规核查 | +| 3 | 多卡片切换 | 同一对话存在多个工作流时,可通过轮播切换卡片 | +| 4 | 适用条件确认 | 系统能识别条件并通过对话选择框让用户确认 | +| 5 | 规则与 RAG | 结构化规则负责判断,RAG 能补充法规依据 | +| 6 | 完整性核查 | 能识别缺失文件和文件项级缺失 | +| 7 | 章节核查 | 能识别关键文件章节缺失或异常 | +| 8 | 一致性核查 | 能识别产品名称、型号规格、预期用途等字段冲突 | +| 9 | 风险分级 | 问题能归并为阻断项、高、中、低、提示项 | +| 10 | 飞书通知 | 阻断项、高风险、中风险能通过飞书 CLI @ 上传人 | +| 11 | 过程留底 | 条件确认、核查矩阵、风险清单、RAG 结果、通知记录、复核记录均有产物 | +| 12 | 整改复核 | 用户通过对话指令上传补充资料后,可重新复核问题状态 | +| 13 | 权限隔离 | A 对话的法规核查结果和过程产物不能被 B 对话访问 | + +--- + +## 十五、实施建议 + +1. 先实现 `RegulatoryReviewBatch`、`RegulatoryIssue`、`RegulatoryArtifact`、`RegulatoryNotificationRecord` 数据模型。 +2. 增加规则文件加载器和一版 `nmpa_ivd_registration_v1` 结构化规则。 +3. 构建本地 CMDE 法规材料 RAG 索引,确保能按规则项检索依据。 +4. 实现法规核查工作流主链路:准备资料、信息抽取、条件确认、规则裁剪、完整性核查。 +5. 补齐 `TextExtract`、章节核查、一致性核查、风险归并和报告导出。 +6. 接入 `FeishuNotifier` CLI 实现并提供直接测试命令。 +7. 改造前端工作流卡片,支持 `workflow_type` 和轮播切换。 +8. 最后完善整改复核、过程产物下载和权限校验。 + +--- + +## 十六、待确认事项 + +| 序号 | 问题 | 当前建议 | 状态 | +| --- | --- | --- | --- | +| 1 | 规则文件格式使用 YAML 还是 JSON | 建议 YAML,便于人工维护和注释 | 待确认 | +| 2 | 本地 RAG 使用哪种向量库 | 可复用项目依赖中的 ChromaDB | 待技术验证 | +| 3 | 飞书 CLI 具体命令格式 | 需要结合本机飞书 CLI 或企业内部工具确认 | 待确认 | +| 4 | 对话选择框前端能力 | 参考计划模式实现选项 + 自由输入 | 待技术验证 | +| 5 | LLM 抽取是否需要人工确认阈值 | 建议低于置信度阈值进入待确认 | 待确认 | diff --git a/docs/3.详细设计/2.NMPA注册资料法规核查与整改闭环.md b/docs/3.详细设计/2.NMPA注册资料法规核查与整改闭环.md new file mode 100644 index 0000000..64d3d79 --- /dev/null +++ b/docs/3.详细设计/2.NMPA注册资料法规核查与整改闭环.md @@ -0,0 +1,666 @@ +# NMPA 注册资料法规核查与整改闭环工作流详细设计 + +## 文档信息 + +| 项目 | 内容 | +| --- | --- | +| 需求分析文档 | docs/1.需求分析/2.NMPA注册资料法规核查与整改闭环.md | +| 功能设计文档 | docs/2.功能设计/2.NMPA注册资料法规核查与整改闭环.md | +| 数据库设计文档 | docs/4.数据库设计/2.NMPA注册资料法规核查与整改闭环.md | +| 依赖详细设计 | docs/3.详细设计/1.自动汇总.md | +| 功能名称 | NMPA 注册资料法规核查与整改闭环 | +| 所属模块 | 审核智能体 review_agent | +| 设计日期 | 2026-06-06 | +| 设计版本 | V1.0 | + +--- + +## 一、详细设计目标 + +本详细设计用于指导“NMPA 注册资料法规核查与整改闭环”功能开发落地,覆盖代码结构、通用工作流改造、法规核查执行器、规则/RAG/LLM 调用边界、服务拆分、接口契约、前端交互、飞书 CLI 通知、过程产物留底、异常重试和测试建议。 + +核心约束: + +| 约束 | 说明 | +| --- | --- | +| 复用自动汇总 | 不重复实现上传、解压、扫描和页数统计,法规核查基于 `FileSummaryBatch` 执行 | +| 独立工作流 | 法规核查有独立 `RegulatoryReviewBatch` 和卡片,事件机制与文件汇总共用 | +| 通用事件模型 | `WorkflowNodeRun`、`WorkflowEvent`、`ExportedSummaryFile` 增加 workflow_type 和 workflow_batch_id | +| 异步执行 | 启动接口立即返回 batch_id,后台执行并通过 SSE 更新卡片 | +| 暂停恢复 | 遇到 waiting_user 时后台任务结束,用户确认后重新唤起执行器继续 | +| 规则优先 | 结构化规则负责合规判断,RAG 只补充依据,LLM 只用于低置信度字段抽取和建议润色 | +| 过程留底 | 文本抽取、RAG 结果、LLM 输出、通知和复核记录均生成过程产物 | + +--- + +## 二、代码结构设计 + +### 2.1 目录结构 + +在 `review_agent` 应用内新增 `regulatory_review/` 模块。法规核查与文件汇总并列,通过共享工作流事件和导出服务协同。`review_agent/workflow/` 是对模块 1 中 `file_summary/events.py`、节点状态和导出记录能力的通用化抽取,不是为法规核查重建一套并行事件体系。 + +```text +review_agent/ + models.py + urls.py + views.py + file_summary/ + ... + workflow/ + __init__.py + constants.py + events.py + node_runs.py + exports.py + regulatory_review/ + __init__.py + constants.py + schemas.py + urls.py + views.py + workflow.py + storage.py + services/ + __init__.py + rule_loader.py + rag_citation.py + info_extract.py + text_extract.py + completeness_check.py + structure_check.py + consistency_check.py + risk_assess.py + export.py + feishu_notifier.py + rectification_review.py + condition_parser.py + rules/ + nmpa_ivd_registration_v1.yaml + prompts/ + condition_parse.md + field_extract.md + suggestion_polish.md +``` + +### 2.2 文件职责 + +| 文件 | 职责 | +| --- | --- | +| workflow/constants.py | 通用 workflow_type、节点状态、事件类型 | +| workflow/events.py | 通用 SSE 事件持久化和格式化 | +| workflow/node_runs.py | 通用节点状态创建、更新和恢复 | +| workflow/exports.py | 通用导出记录和下载权限校验 | +| regulatory_review/constants.py | 法规核查节点、风险等级、问题状态常量 | +| regulatory_review/schemas.py | RegulatoryContext、NodeResult、Finding 等 dataclass | +| regulatory_review/workflow.py | RegulatoryWorkflowExecutor,负责编排节点和暂停恢复 | +| regulatory_review/storage.py | 法规核查过程产物路径、hash、文件保存 | +| services/rule_loader.py | 加载规则版本、校验 hash、裁剪适用规则 | +| services/rag_citation.py | 基于 findings 批量检索法规依据 | +| services/info_extract.py | 从文件清单和文本片段抽取适用条件候选值 | +| services/condition_parser.py | 将用户自然语言确认解析为结构化字段 | +| services/text_extract.py | 统一抽取关键文件文本并缓存为 JSON 产物 | +| services/completeness_check.py | 完整性核查,生成 findings | +| services/structure_check.py | 章节结构核查,生成 findings | +| services/consistency_check.py | 跨文件一致性核查,生成 findings | +| services/risk_assess.py | 去重、风险分级、RAG 依据引用、写入 RegulatoryIssue | +| services/export.py | 生成最终报告和过程产物,支持重试 | +| services/feishu_notifier.py | 通过飞书 CLI 发送通知,支持 3 次重试 | +| services/rectification_review.py | 补充资料后的问题复核和状态更新 | + +--- + +## 三、通用工作流改造 + +### 3.1 WorkflowNodeRun 改造 + +现有节点状态表需要兼容多类工作流。 + +| 字段 | 处理 | +| --- | --- | +| batch_id | 保留,兼容文件汇总旧逻辑 | +| workflow_type | 新增,file_summary、regulatory_review | +| workflow_batch_id | 新增,保存对应工作流批次 ID | +| node_group | 新增,可选,用于法规核查卡片主节点聚合 | + +唯一约束调整为: + +```text +unique(workflow_type, workflow_batch_id, node_code) +``` + +文件汇总旧逻辑写入时同步设置: + +```text +workflow_type = file_summary +workflow_batch_id = file_summary_batch.id +batch_id = file_summary_batch.id +``` + +### 3.2 WorkflowEvent 改造 + +事件表同样新增: + +| 字段 | 说明 | +| --- | --- | +| workflow_type | file_summary、regulatory_review | +| workflow_batch_id | 对应工作流批次 ID | +| conversation_id | 冗余记录对话 ID,便于 SSE 查询 | + +SSE 查询时按 `conversation_id` 获取多个工作流事件,前端根据 `workflow_type + workflow_batch_id` 更新对应卡片。 + +### 3.3 ExportedSummaryFile 改造 + +最终下载文件表通用化: + +| 字段 | 说明 | +| --- | --- | +| workflow_type | file_summary、regulatory_review | +| workflow_batch_id | 对应工作流批次 ID | +| export_category | summary_report、risk_report、excel_list、json_package | + +法规核查最终 Markdown、Excel、JSON 结果包进入 `ExportedSummaryFile`;过程产物进入 `RegulatoryArtifact`。 + +--- + +## 四、核心数据结构 + +### 4.1 RegulatoryContext + +节点间传递统一上下文,避免每个服务重复组装状态。 + +```python +@dataclass +class RegulatoryContext: + regulatory_batch: RegulatoryReviewBatch + file_summary_batch: FileSummaryBatch | None + rule_version: RegulatoryRuleVersion | None + rules: dict[str, Any] + scoped_rules: list[dict[str, Any]] + conditions: dict[str, Any] + file_items: list[FileSummaryItem] + text_artifacts: dict[str, Any] + findings: list["Finding"] + issues: list[RegulatoryIssue] + artifacts: list[RegulatoryArtifact] + reference_only: bool = False +``` + +### 4.2 NodeResult + +每个节点统一返回 `NodeResult`。 + +```python +@dataclass +class NodeResult: + status: str + message: str = "" + payload: dict[str, Any] = field(default_factory=dict) + findings: list["Finding"] = field(default_factory=list) + artifacts: list[RegulatoryArtifact] = field(default_factory=list) + next_node: str | None = None +``` + +### 4.3 Finding + +核查服务只返回 findings,不直接写 `RegulatoryIssue`。Issue 由 `RiskAssessService` 统一去重、分级和落库。 + +```python +@dataclass +class Finding: + finding_key: str + issue_type: str + initial_risk_level: str + title: str + description: str + rule_id: str | None = None + file_item_id: int | None = None + file_path: str | None = None + page_no: int | None = None + field_name: str | None = None + evidence: dict[str, Any] = field(default_factory=dict) + suggestion_template: str | None = None + source_node: str | None = None +``` + +--- + +## 五、工作流执行设计 + +### 5.1 启动流程 + +```text +POST /regulatory-review/start/ +-> 创建 RegulatoryReviewBatch(status=pending) +-> 查找当前对话最近一次 success FileSummaryBatch +-> 如有则绑定并异步启动法规核查 +-> 如无则创建 FileSummaryBatch 并启动自动汇总 +-> 自动汇总 success 后回填 file_summary_batch_id +-> 继续法规核查 prepare 节点 +``` + +如果用户明确说“重新核查最新上传资料”,系统强制创建新的 `FileSummaryBatch`,再创建新的 `RegulatoryReviewBatch`。 + +### 5.2 暂停与恢复 + +当适用条件缺失或解析冲突时: + +```text +RegulatoryWorkflowExecutor +-> 写入 condition_confirm 节点 status=waiting_user +-> RegulatoryReviewBatch.status=waiting_user +-> 发送 workflow SSE +-> 后台任务结束 +``` + +用户确认后: + +```text +POST /regulatory-review/{batch_id}/confirm-condition/ +-> LLM 解析自然语言为结构化 JSON +-> 字段校验器校验必填字段 +-> 如仍缺失,继续追问并保持 waiting_user +-> 如完整,写入 batch 核心字段和 condition_json +-> 重新唤起 RegulatoryWorkflowExecutor,从 rule_scope 节点继续 +``` + +### 5.3 节点调度 + +```text +prepare +-> info_extract +-> condition_confirm 或 rule_scope +-> rule_scope +-> completeness_check +-> text_extract +-> 并行执行 structure_check 和 consistency_check +-> risk_assess +-> report_export +-> notify +-> completed +``` + +章节核查和一致性核查通过后台线程池并行: + +```python +with ThreadPoolExecutor(max_workers=2) as pool: + structure_future = pool.submit(structure_service.run, context) + consistency_future = pool.submit(consistency_service.run, context) +``` + +### 5.4 关键节点 + +关键节点失败时终止批次: + +| 节点 | 失败处理 | +| --- | --- | +| prepare | 无法绑定文件汇总批次,批次 failed | +| rule_scope | 规则 hash 不一致,批次 failed;规则加载失败可降级 reference_only | +| report_export | 最终报告重试失败,批次 failed | + +非关键节点失败时生成 `Finding` 或 `RegulatoryIssue`,工作流尽量继续: + +| 节点 | 失败处理 | +| --- | --- | +| text_extract | 对相关文件生成待确认 finding | +| structure_check | 生成章节核查失败 finding | +| consistency_check | 生成一致性待确认 finding | +| notify | 写通知失败记录,批次可 partial_success | + +--- + +## 六、规则、RAG 与 LLM 设计 + +### 6.1 RuleLoader + +流程: + +```text +读取当前 active RegulatoryRuleVersion +-> 读取 rule_file_path +-> 计算文件 hash +-> 与 rule_file_hash 比对 +-> hash 一致则解析规则 +-> 按适用条件裁剪 scoped_rules +``` + +处理策略: + +| 场景 | 处理 | +| --- | --- | +| 规则文件 hash 不一致 | 停止执行并标记 failed | +| 规则文件不存在或解析失败 | 降级 RAG 辅助核查,batch.status=reference_only | +| RAG 索引版本缺失 | 记录提示项,但规则核查可继续 | + +### 6.2 RagCitationService + +RAG 在 `RiskAssessService` 阶段批量调用,而不是每个核查节点实时调用。 + +输入: + +| 字段 | 说明 | +| --- | --- | +| findings | 所有核查 findings | +| rule_version | 当前法规规则版本 | +| scoped_rules | 本次适用规则 | + +输出: + +| 字段 | 说明 | +| --- | --- | +| citations_by_finding | finding_key 到法规依据列表的映射 | +| rag_result_json | RAG 检索结果过程产物 | + +### 6.3 LLM 调用边界 + +| 场景 | 是否调用 LLM | 说明 | +| --- | --- | --- | +| 自然语言适用条件解析 | 是 | 解析为结构化 JSON,再由字段校验器校验 | +| 低置信度字段抽取 | 是 | 规则/正则失败或置信度低时调用 | +| 整改建议润色 | 是 | 规则模板生成标准动作,LLM 润色表达 | +| 风险等级判断 | 否 | 风险等级由规则和 RiskAssess 决定 | +| 法规结论判断 | 否 | 合规判断不交给 LLM | + +LLM 抽取结果需写入过程产物,可使用 `llm_extract_json` 或并入 `text_extract_json`。 + +--- + +## 七、服务详细设计 + +### 7.1 RegulatoryWorkflowExecutor + +| 方法 | 说明 | +| --- | --- | +| start(batch_id) | 创建后台任务并返回 | +| run(batch_id, start_node=None) | 运行法规核查节点 | +| build_context(batch_id) | 组装 RegulatoryContext | +| run_node(node_code, context) | 执行单个节点并处理 NodeResult | +| run_parallel_checks(context) | 并行执行章节和一致性核查 | +| pause_for_user(batch, node_code, message) | 写 waiting_user 状态并结束任务 | +| complete(batch) | 标记批次完成 | +| fail(batch, error) | 标记批次失败 | + +### 7.2 ConditionParserService + +| 方法 | 说明 | +| --- | --- | +| parse(raw_user_input, previous_conditions) | 使用 LLM 解析自然语言 | +| validate(parsed_json) | 校验产品类别、注册类型、临床路径、产品名称、型号规格、预期用途 | +| merge(batch, parsed_json) | 写入批次字段和 condition_json | + +### 7.3 RiskAssessService + +| 方法 | 说明 | +| --- | --- | +| deduplicate(findings) | 按 finding_key、rule_id、file_item_id 去重 | +| attach_citations(findings) | 批量调用 RAG 获取法规依据 | +| resolve_risk(finding) | 统一风险等级,处理升级/降级 | +| generate_suggestion(finding) | 规则模板 + LLM 润色 | +| create_issues(batch, findings) | 统一写入 RegulatoryIssue | +| build_risk_summary(batch) | 写入 risk_summary_json | + +### 7.4 RegulatoryExportService + +| 方法 | 说明 | +| --- | --- | +| export_final_markdown(batch) | 生成最终 Markdown 核查报告 | +| export_final_excel(batch) | 生成 Excel 缺失清单 | +| export_json_package(batch) | 生成结构化 JSON 结果包 | +| create_artifact(batch, artifact_type, path) | 写 RegulatoryArtifact 并计算 hash | +| create_export_record(batch, path, category) | 写 ExportedSummaryFile | +| retry_export(fn, max_retry=3) | 导出失败重试 | + +重试策略: + +| 产物 | 重试后仍失败 | +| --- | --- | +| 最终 Markdown/Excel/JSON | 批次 failed | +| 非关键过程产物 | 批次 partial_success | + +### 7.5 FeishuNotifier + +调用方式必须使用参数数组,不拼接 shell 字符串。 + +```python +subprocess.run( + [cli_path, "send", "--user", feishu_user_id, "--message", message], + check=True, + capture_output=True, + text=True, +) +``` + +处理策略: + +| 场景 | 处理 | +| --- | --- | +| 用户无 feishu_user_id | 写通知失败记录,不阻断 | +| CLI 执行失败 | 最多重试 3 次 | +| 仍失败 | send_status=failed,批次可 partial_success | +| 成功 | 写 external_message_id 和 sent_at | + +通知内容包含系统内风险报告链接,不附原始文件。 + +--- + +## 八、接口详细设计 + +### 8.1 发起法规核查 + +| 项目 | 内容 | +| --- | --- | +| URL | POST /api/review-agent/regulatory-review/start/ | +| 请求 | conversation_id、file_summary_batch_id 可选、force_resummary 可选 | +| 响应 | regulatory_batch_id、workflow_type、status | + +响应示例: + +```json +{ + "regulatory_batch_id": 2001, + "workflow_type": "regulatory_review", + "status": "pending" +} +``` + +### 8.2 确认适用条件 + +| 项目 | 内容 | +| --- | --- | +| URL | POST /api/review-agent/regulatory-review/{batch_id}/confirm-condition/ | +| 请求 | raw_user_input、可选结构化字段 | +| 响应 | status、missing_fields、next_question | + +如果解析完整: + +```json +{ + "status": "accepted", + "next_node": "rule_scope" +} +``` + +如果仍缺失: + +```json +{ + "status": "need_more_info", + "missing_fields": ["clinical_evaluation_path"], + "next_question": "请确认临床评价路径:临床试验、免临床,还是同品种比对?" +} +``` + +### 8.3 查询状态 + +| 项目 | 内容 | +| --- | --- | +| URL | GET /api/review-agent/regulatory-review/{batch_id}/ | +| 响应 | 批次、节点、风险摘要、导出文件、过程产物 | + +### 8.4 发起整改复核 + +| 项目 | 内容 | +| --- | --- | +| URL | POST /api/review-agent/regulatory-review/{batch_id}/rectify-review/ | +| 请求 | issue_ids、file_summary_batch_id 或 uploaded_file_ids | +| 响应 | review_status、updated_issues、review_artifact_id | + +补充文件必须复用自动汇总上传与汇总能力。上传后先生成新的 `FileSummaryBatch`,再由 `RectificationReviewService` 对原批次问题执行复核。复核不创建新的 `RegulatoryReviewBatch`。 + +--- + +## 九、前端与对话交互 + +### 9.1 工作流卡片 + +| 设计点 | 说明 | +| --- | --- | +| 卡片切换 | 多工作流卡片使用轮播切换 | +| 卡片识别 | 使用 workflow_type + workflow_batch_id | +| 状态来源 | SSE workflow 事件 | +| 法规卡片 | 展示主节点和可展开子节点 | +| waiting_user | 卡片显示等待确认,对话框给出选择和追问 | + +### 9.2 自然语言确认 + +对话框中用户可以用自然语言确认,例如: + +```text +按体外诊断试剂首次注册处理,临床评价路径走同品种比对,产品名称是 XXX,型号规格是 YYY,预期用途是 ZZZ。 +``` + +后端解析并校验后继续工作流。原始输入写入 `condition_json.raw_user_input`。 + +### 9.3 整改复核触发 + +Demo 阶段通过对话指令触发: + +```text +我已补充注册检验报告,请复核阻断项。 +``` + +系统识别后调用复核接口,要求用户上传补充文件或选择已上传文件。 + +--- + +## 十、过程产物与报告 + +### 10.1 文件命名 + +过程产物和最终报告采用固定模板: + +```text +{batch_no}_{artifact_type}.{ext} +``` + +示例: + +```text +RRB202606060001_rule_matrix.xlsx +RRB202606060001_risk_list.json +RRB202606060001_final_report.md +``` + +### 10.2 文件保存 + +路径: + +```text +media/regulatory_review/{user_id}/{conversation_id}/{batch_id}/ +``` + +所有 `RegulatoryArtifact` 必须计算 SHA-256 hash。 + +### 10.3 报告内容 + +最终 Markdown 报告包含: + +| 模块 | 说明 | +| --- | --- | +| 核查概览 | 批次、规则版本、RAG 版本、上传人 | +| 适用条件 | 系统抽取和用户确认结果 | +| 风险清单 | 五级风险、状态、责任人、建议 | +| 法规核查矩阵 | 应有文件、实际文件、缺失情况 | +| 章节核查结果 | 缺失章节、异常章节 | +| 一致性核查结果 | 字段冲突和来源文件 | +| 飞书通知记录 | 发送对象、状态、失败原因 | +| 整改复核记录 | 复核方式、复核结果、关闭确认 | + +--- + +## 十一、异常与重试 + +| 场景 | 处理 | +| --- | --- | +| 无成功 FileSummaryBatch | 自动启动文件汇总,成功后继续 | +| 文件汇总失败 | 法规核查批次 failed | +| 规则 hash 不一致 | 法规核查批次 failed | +| 规则加载失败 | 降级 reference_only,仅输出参考性结果 | +| 用户确认信息缺失 | waiting_user,追问缺失字段 | +| 文本抽取失败 | 生成待确认 finding,继续后续节点 | +| 章节或一致性节点失败 | 生成对应 issue,继续风险汇总 | +| RAG 检索无结果 | 规则问题仍输出,依据标记原文待补充 | +| LLM 调用失败 | 回退规则/正则结果,低置信度项待确认 | +| 飞书失败 | 重试 3 次,仍失败写通知失败记录 | +| 最终报告导出失败 | 重试 3 次,仍失败 batch failed | +| 非关键产物导出失败 | 重试 3 次,仍失败 batch partial_success | + +--- + +## 十二、测试建议 + +### 12.1 单元测试 + +| 模块 | 测试点 | +| --- | --- | +| RuleLoader | hash 校验、规则解析、规则裁剪、加载失败降级 | +| ConditionParserService | 自然语言解析、缺失字段追问、原始输入留痕 | +| TextExtractService | 首页文本、章节文本、抽取失败产物 | +| CompletenessCheckService | 文件名/目录名/首页内容三层匹配 | +| StructureCheckService | 必需章节缺失识别 | +| ConsistencyCheckService | 字段冲突、低置信度 LLM 辅助 | +| RiskAssessService | findings 去重、风险升级/降级、Issue 落库 | +| RegulatoryExportService | 文件命名、hash、导出重试 | +| FeishuNotifier | 参数数组调用、3 次重试、失败记录 | + +### 12.2 集成测试 + +| 场景 | 验证 | +| --- | --- | +| 已有汇总批次发起核查 | 默认复用最近 success 批次 | +| 无汇总批次发起核查 | 自动串联文件汇总后继续 | +| waiting_user 暂停恢复 | 用户确认后从 rule_scope 继续 | +| 章节和一致性并行 | 两个节点均完成后进入 risk_assess | +| 规则加载失败 | batch.status=reference_only | +| 飞书失败 | 不阻断报告,通知记录 failed | +| 补充文件复核 | 新 FileSummaryBatch 生成,原 Issue 状态更新 | + +### 12.3 验收测试 + +| 序号 | 验收项 | 标准 | +| --- | --- | --- | +| 1 | 多工作流卡片 | 文件汇总和法规核查卡片可切换且状态独立 | +| 2 | 条件确认 | 用户自然语言确认后能结构化入库 | +| 3 | 完整性核查 | 能识别缺失注册检验报告等问题 | +| 4 | 章节核查 | 能识别关键章节缺失 | +| 5 | 一致性核查 | 能识别产品名称、型号规格、预期用途冲突 | +| 6 | 风险报告 | 输出 Markdown、Excel、JSON 结果包 | +| 7 | 飞书通知 | 阻断项、高风险、中风险能 @ 上传人 | +| 8 | 过程留底 | RAG、文本抽取、通知、复核均有 artifact | +| 9 | 整改复核 | 补充文件后原 Issue 可进入复核通过或复核不通过 | + +--- + +## 十三、实施顺序建议 + +结合当前优先级,建议先打通 RAG 和 LLM 能力,再落完整工作流: + +1. 构建本地法规材料 RAG 索引,并实现 `RagCitationService`。 +2. 实现适用条件解析和低置信度字段抽取的 LLM 调用封装。 +3. 完成数据库模型和通用 workflow/export 表改造。 +4. 实现 `RuleLoader` 与规则 hash 校验。 +5. 实现 `RegulatoryWorkflowExecutor`、`RegulatoryContext`、`NodeResult`。 +6. 实现完整性、文本抽取、章节核查、一致性核查和风险归并。 +7. 实现报告导出、过程产物 hash 和导出重试。 +8. 接入飞书 CLI 通知和 3 次重试。 +9. 改造前端多工作流卡片和适用条件确认交互。 +10. 实现整改复核和 Issue 状态流转。 diff --git a/docs/4.数据库设计/2.NMPA注册资料法规核查与整改闭环.md b/docs/4.数据库设计/2.NMPA注册资料法规核查与整改闭环.md new file mode 100644 index 0000000..788a1ed --- /dev/null +++ b/docs/4.数据库设计/2.NMPA注册资料法规核查与整改闭环.md @@ -0,0 +1,485 @@ +# NMPA 注册资料法规核查与整改闭环工作流数据库设计 + +## 文档信息 + +| 项目 | 内容 | +| --- | --- | +| 需求分析文档 | docs/1.需求分析/2.NMPA注册资料法规核查与整改闭环.md | +| 功能设计文档 | docs/2.功能设计/2.NMPA注册资料法规核查与整改闭环.md | +| 数据库类型 | SQLite / Django ORM | +| 表名前缀 | ra_ | +| 设计日期 | 2026-06-06 | +| 设计版本 | V1.0 | + +--- + +## 一、设计原则 + +| 原则 | 说明 | +| --- | --- | +| 复用汇总批次 | 法规核查不重复保存文件清单,必须关联既有 `ra_file_summary_batch` | +| 独立核查批次 | 同一个文件汇总批次可以产生多次法规核查批次,适用条件变更时创建新批次 | +| 规则版本入库 | 结构化规则版本进入数据库,便于追溯规则文件、RAG 索引和启用状态 | +| RAG 不单独建表 | RAG 索引信息挂在规则版本和核查批次字段中,不新增索引表 | +| 枚举存值 | 数据库存英文枚举 value,前端或服务层映射为中文展示 | +| 关键字段独立 | 常用查询字段独立存储,其余过程上下文进入 JSON 或文件产物 | +| 大文本不入库 | 过程产物只在数据库保存路径、摘要和 hash,大文本内容写入文件 | +| 软删除优先 | 法规核查相关数据采用软删除/归档策略,便于审计和恢复 | +| 过程产物留底 | 条件确认、核查矩阵、风险清单、RAG 结果、通知记录、复核记录均需留底 | + +--- + +## 二、ER 图 + +```mermaid +erDiagram + AUTH_USER ||--o{ CONVERSATION : owns + CONVERSATION ||--o{ RA_FILE_SUMMARY_BATCH : has + RA_FILE_SUMMARY_BATCH ||--o{ RA_FILE_SUMMARY_ITEM : produces + RA_FILE_SUMMARY_BATCH ||--o{ RA_REGULATORY_REVIEW_BATCH : reviews + AUTH_USER ||--o{ RA_REGULATORY_REVIEW_BATCH : runs + AUTH_USER ||--o{ RA_REGULATORY_ISSUE : owns + RA_REGULATORY_RULE_VERSION ||--o{ RA_REGULATORY_REVIEW_BATCH : used_by + RA_REGULATORY_REVIEW_BATCH ||--o{ RA_REGULATORY_ISSUE : produces + RA_REGULATORY_REVIEW_BATCH ||--o{ RA_REGULATORY_ARTIFACT : keeps + RA_REGULATORY_REVIEW_BATCH ||--o{ RA_REGULATORY_NOTIFICATION_RECORD : sends + RA_REGULATORY_REVIEW_BATCH ||--o{ RA_EXPORTED_SUMMARY_FILE : exports + RA_REGULATORY_REVIEW_BATCH ||--o{ RA_WORKFLOW_NODE_RUN : tracks + RA_REGULATORY_REVIEW_BATCH ||--o{ RA_WORKFLOW_EVENT : emits +``` + +说明:`ra_workflow_node_run`、`ra_workflow_event` 在第一阶段设计中属于文件汇总批次节点记录表。法规核查工作流复用同一套事件机制,采用 `workflow_type`、`workflow_batch_id` 兼容多工作流;原 `batch_id` 保留用于兼容文件汇总旧逻辑。 + +--- + +## 三、表结构设计 + +### 3.1 ra_regulatory_rule_version + +法规结构化规则版本表。规则文件仍以 YAML/JSON 文件形式维护,数据库记录版本元数据、文件 hash、RAG 索引版本和启用状态。 + +| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 | +| --- | --- | --- | --- | --- | +| id | BigAutoField | integer | 是 | 主键 | +| version | CharField(80) | varchar(80) | 是 | 规则版本,如 nmpa_ivd_2021_v1 | +| source_url | URLField(500) | varchar(500) | 是 | 法规来源 URL | +| source_path | CharField(500) | varchar(500) | 是 | 本地法规资料路径 | +| effective_date | DateField | date | 否 | 规则生效日期或公告日期 | +| rule_file_path | CharField(500) | varchar(500) | 是 | 结构化规则文件路径 | +| rule_file_hash | CharField(128) | varchar(128) | 是 | 规则文件 hash | +| rag_index_version | CharField(80) | varchar(80) | 否 | RAG 索引版本 | +| rag_index_path | CharField(500) | varchar(500) | 否 | RAG 索引存储路径 | +| is_active | BooleanField | bool | 是 | 是否当前启用版本 | +| created_by_id | ForeignKey(User) | bigint | 否 | 创建人 | +| activated_at | DateTimeField | datetime | 否 | 启用时间 | +| description | TextField | text | 否 | 版本说明 | +| created_at | DateTimeField | datetime | 是 | 创建时间 | +| updated_at | DateTimeField | datetime | 是 | 更新时间 | +| is_deleted | BooleanField | bool | 是 | 软删除标记 | + +唯一约束: + +| 约束名 | 字段 | +| --- | --- | +| uq_ra_reg_rule_version | version | + +索引: + +| 索引名 | 字段 | 说明 | +| --- | --- | --- | +| idx_ra_reg_rule_active | is_active, is_deleted | 查询当前启用规则 | +| idx_ra_reg_rule_effective | effective_date | 按生效日期追溯 | +| idx_ra_reg_rule_created | created_at | 查看规则版本历史 | + +--- + +### 3.2 ra_regulatory_review_batch + +法规核查批次表。一次法规核查工作流对应一条记录。同一个 `ra_file_summary_batch` 可关联多个法规核查批次,用于适用条件变更或重新核查。 + +| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 | +| --- | --- | --- | --- | --- | +| id | BigAutoField | integer | 是 | 主键 | +| conversation_id | ForeignKey | bigint | 是 | 绑定对话 | +| user_id | ForeignKey | bigint | 是 | 发起用户 | +| file_summary_batch_id | ForeignKey | bigint | 是 | 关联文件汇总批次 | +| rule_version_id | ForeignKey | bigint | 否 | 使用的规则版本 | +| batch_no | CharField(64) | varchar(64) | 是 | 法规核查批次编号,唯一 | +| status | CharField(30) | varchar(30) | 是 | pending、running、waiting_user、success、failed、reference_only、partial_success、cancelled | +| product_category | CharField(80) | varchar(80) | 否 | 产品类别 | +| registration_type | CharField(80) | varchar(80) | 否 | 注册类型 | +| clinical_evaluation_path | CharField(120) | varchar(120) | 否 | 临床评价路径 | +| product_name | CharField(200) | varchar(200) | 否 | 产品名称 | +| model_specification | CharField(200) | varchar(200) | 否 | 型号规格 | +| intended_use | TextField | text | 否 | 预期用途 | +| condition_json | JSONField | text/json | 否 | 其他适用条件、用户确认记录和抽取置信度 | +| rule_version_value | CharField(80) | varchar(80) | 否 | 冗余记录规则版本值,便于历史追溯 | +| rule_source_url | URLField(500) | varchar(500) | 否 | 冗余记录法规来源 URL | +| rule_source_path | CharField(500) | varchar(500) | 否 | 冗余记录本地法规资料路径 | +| rag_index_version | CharField(80) | varchar(80) | 否 | 本次使用的 RAG 索引版本 | +| risk_summary_json | JSONField | text/json | 否 | 风险数量摘要 | +| artifact_root | CharField(500) | varchar(500) | 否 | 本批次过程产物根目录 | +| error_message | TextField | text | 否 | 批次异常说明 | +| created_at | DateTimeField | datetime | 是 | 创建时间 | +| started_at | DateTimeField | datetime | 否 | 开始时间 | +| finished_at | DateTimeField | datetime | 否 | 完成时间 | +| archived_at | DateTimeField | datetime | 否 | 归档时间 | +| is_deleted | BooleanField | bool | 是 | 软删除标记 | + +唯一约束: + +| 约束名 | 字段 | +| --- | --- | +| uq_ra_reg_batch_no | batch_no | + +索引: + +| 索引名 | 字段 | 说明 | +| --- | --- | --- | +| idx_ra_reg_batch_conv_status | conversation_id, status | 查询对话下法规核查批次状态 | +| idx_ra_reg_batch_summary | file_summary_batch_id | 根据文件汇总批次查询法规核查历史 | +| idx_ra_reg_batch_created | created_at | 按创建时间查询 | +| idx_ra_reg_batch_rule | rule_version_value | 规则版本追溯 | +| idx_ra_reg_batch_user_created | user_id, created_at | 查询用户发起记录 | + +--- + +### 3.3 ra_regulatory_issue + +法规核查问题表,记录完整性、章节结构、一致性、通知、复核等业务问题及整改状态。 + +| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 | +| --- | --- | --- | --- | --- | +| id | BigAutoField | integer | 是 | 主键 | +| batch_id | ForeignKey | bigint | 是 | 所属法规核查批次 | +| owner_id | ForeignKey(User) | bigint | 否 | 责任人,默认上传人 | +| issue_code | CharField(100) | varchar(100) | 是 | 问题编码 | +| issue_type | CharField(40) | varchar(40) | 是 | completeness、structure、consistency、notification、review | +| risk_level | CharField(20) | varchar(20) | 是 | blocking、high、medium、low、info | +| status | CharField(30) | varchar(30) | 是 | pending_confirm、pending_fix、fixed、review_passed、review_failed、closed | +| title | CharField(255) | varchar(255) | 是 | 问题标题 | +| description | TextField | text | 否 | 问题描述 | +| rule_id | CharField(120) | varchar(120) | 否 | 命中的规则 ID | +| regulation_basis | TextField | text | 否 | 法规依据或规则依据 | +| file_item_id | ForeignKey(FileSummaryItem) | bigint | 否 | 关联文件明细,可为空 | +| file_path | CharField(500) | varchar(500) | 否 | 常用证据文件路径 | +| page_no | PositiveIntegerField | integer | 否 | 常用证据页码 | +| field_name | CharField(120) | varchar(120) | 否 | 一致性或字段问题名称 | +| evidence_json | JSONField | text/json | 否 | 证据详情,如文本片段、多个来源值、RAG 引用等 | +| suggestion | TextField | text | 否 | 整改建议 | +| source_node | CharField(60) | varchar(60) | 否 | 产生问题的工作流节点 | +| confirmed_by_id | ForeignKey(User) | bigint | 否 | 确认人 | +| confirmed_at | DateTimeField | datetime | 否 | 确认时间 | +| closed_by_id | ForeignKey(User) | bigint | 否 | 关闭人 | +| closed_at | DateTimeField | datetime | 否 | 关闭时间 | +| created_at | DateTimeField | datetime | 是 | 创建时间 | +| updated_at | DateTimeField | datetime | 是 | 更新时间 | +| is_deleted | BooleanField | bool | 是 | 软删除标记 | + +唯一约束: + +| 约束名 | 字段 | +| --- | --- | +| uq_ra_reg_issue_batch_code | batch_id, issue_code | + +索引: + +| 索引名 | 字段 | 说明 | +| --- | --- | --- | +| idx_ra_reg_issue_batch | batch_id, created_at | 查询批次问题 | +| idx_ra_reg_issue_risk_status | risk_level, status | 风险列表和整改状态筛选 | +| idx_ra_reg_issue_owner_status | owner_id, status | 责任人待办 | +| idx_ra_reg_issue_rule | rule_id | 规则问题追溯 | +| idx_ra_reg_issue_file | file_item_id | 关联文件问题 | +| idx_ra_reg_issue_field | field_name | 字段一致性问题查询 | + +--- + +### 3.4 ra_regulatory_artifact + +法规核查过程产物表。只保存文件元数据,不保存大文本全文。文件内容写入受控存储目录,`file_hash` 必填。 + +| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 | +| --- | --- | --- | --- | --- | +| id | BigAutoField | integer | 是 | 主键 | +| batch_id | ForeignKey | bigint | 是 | 所属法规核查批次 | +| artifact_type | CharField(60) | varchar(60) | 是 | condition_record、rule_matrix、risk_list、text_extract_json、rag_result_json、notification_record、review_record | +| file_format | CharField(20) | varchar(20) | 是 | markdown、excel、json | +| file_name | CharField(255) | varchar(255) | 是 | 文件名 | +| storage_path | CharField(500) | varchar(500) | 是 | 存储路径 | +| file_size | BigIntegerField | bigint | 是 | 文件大小 | +| file_hash | CharField(128) | varchar(128) | 是 | 文件 hash,用于校验留底文件未被篡改 | +| summary | TextField | text | 否 | 产物摘要 | +| created_by_node | CharField(60) | varchar(60) | 否 | 产生该产物的工作流节点 | +| created_at | DateTimeField | datetime | 是 | 创建时间 | +| is_deleted | BooleanField | bool | 是 | 软删除标记 | + +索引: + +| 索引名 | 字段 | 说明 | +| --- | --- | --- | +| idx_ra_reg_artifact_batch_type | batch_id, artifact_type | 查询批次过程产物 | +| idx_ra_reg_artifact_format | file_format | 按格式查询 | +| idx_ra_reg_artifact_created | created_at | 按时间追溯 | + +--- + +### 3.5 ra_regulatory_notification_record + +法规核查通知记录表,记录飞书 CLI 发送结果。飞书失败不阻断工作流,但需要留痕。 + +| 字段名 | Django 类型 | SQLite 类型 | 必填 | 说明 | +| --- | --- | --- | --- | --- | +| id | BigAutoField | integer | 是 | 主键 | +| batch_id | ForeignKey | bigint | 是 | 所属法规核查批次 | +| recipient_id | ForeignKey(User) | bigint | 是 | 通知对象 | +| channel | CharField(30) | varchar(30) | 是 | feishu_cli、feishu_api、mock | +| risk_levels | JSONField | text/json | 是 | 本次通知包含的风险等级 | +| issue_ids | JSONField | text/json | 是 | 本次通知关联的问题 ID 列表 | +| message_summary | TextField | text | 是 | 通知内容摘要 | +| send_status | CharField(20) | varchar(20) | 是 | pending、success、failed | +| retry_count | PositiveIntegerField | integer | 是 | 已重试次数,最多 3 次 | +| external_message_id | CharField(120) | varchar(120) | 否 | 飞书外部消息 ID | +| error_message | TextField | text | 否 | 失败原因 | +| sent_at | DateTimeField | datetime | 否 | 发送成功时间 | +| created_at | DateTimeField | datetime | 是 | 创建时间 | +| updated_at | DateTimeField | datetime | 是 | 更新时间 | +| is_deleted | BooleanField | bool | 是 | 软删除标记 | + +索引: + +| 索引名 | 字段 | 说明 | +| --- | --- | --- | +| idx_ra_reg_notify_batch | batch_id, created_at | 查询批次通知记录 | +| idx_ra_reg_notify_recipient | recipient_id, send_status | 查询用户通知状态 | +| idx_ra_reg_notify_status | send_status, retry_count | 查询待重试通知 | + +--- + +## 四、枚举设计 + +### 4.1 RegulatoryReviewBatch.status + +| value | 中文展示 | 说明 | +| --- | --- | --- | +| pending | 待执行 | 已创建,等待执行 | +| running | 执行中 | 工作流正在执行 | +| waiting_user | 等待用户 | 等待用户确认适用条件或关闭复核 | +| success | 已完成 | 核查完成且无关键失败 | +| failed | 失败 | 关键节点失败,无法输出有效结果 | +| reference_only | 仅供参考 | 规则文件加载失败,降级为 RAG 辅助核查 | +| partial_success | 部分完成 | 部分节点或通知失败,但已输出主要结果 | +| cancelled | 已取消 | 用户或系统取消执行 | + +### 4.2 RegulatoryIssue.status + +| value | 中文展示 | 说明 | +| --- | --- | --- | +| pending_confirm | 待确认 | 条件性问题或低置信度问题等待人工确认 | +| pending_fix | 待处理 | 已确认需要补充或整改 | +| fixed | 已补充 | 用户已上传补充资料或声明已处理 | +| review_passed | 复核通过 | 系统复核通过,关闭前仍需人工确认 | +| review_failed | 复核不通过 | 系统复核后问题仍存在 | +| closed | 已关闭 | 用户确认问题解决并关闭 | + +### 4.3 RegulatoryIssue.risk_level + +| value | 中文展示 | 说明 | +| --- | --- | --- | +| blocking | 阻断项 | 直接影响资料能否进入有效申报或审核 | +| high | 高风险 | 可能导致注册审评补正或重大整改 | +| medium | 中风险 | 需要补充说明或修改 | +| low | 低风险 | 建议修正但影响较小 | +| info | 提示项 | 系统无法充分判断或建议人工关注 | + +### 4.4 其他枚举 + +| 字段 | value | +| --- | --- | +| issue_type | completeness、structure、consistency、notification、review | +| artifact_type | condition_record、rule_matrix、risk_list、text_extract_json、rag_result_json、notification_record、review_record | +| file_format | markdown、excel、json | +| send_status | pending、success、failed | +| channel | feishu_cli、feishu_api、mock | + +--- + +## 五、软删除与归档策略 + +| 对象 | 策略 | +| --- | --- | +| RegulatoryRuleVersion | 使用 `is_deleted` 软删除;已被批次引用的版本不允许物理删除 | +| RegulatoryReviewBatch | 使用 `is_deleted` 和 `archived_at` 归档;归档后默认不在对话主列表展示 | +| RegulatoryIssue | 使用 `is_deleted` 软删除;删除时保留批次摘要和过程产物 | +| RegulatoryArtifact | 使用 `is_deleted` 软删除;正式环境可配合对象存储生命周期归档 | +| RegulatoryNotificationRecord | 使用 `is_deleted` 软删除;保留通知失败原因和重试次数 | + +删除 Conversation 时,本期不建议物理级联法规核查数据。应先标记相关批次归档或删除,再由后台清理任务处理文件和产物。 + +--- + +## 六、过程产物存储设计 + +### 6.1 存储目录 + +法规核查过程产物使用独立目录,按用户、对话、法规核查批次隔离: + +```text +media/regulatory_review/{user_id}/{conversation_id}/{batch_id}/ +``` + +示例: + +```text +media/regulatory_review/12/1001/2001/ + condition_record.md + condition_record.json + rule_matrix.xlsx + risk_list.md + risk_list.json + text_extract.json + rag_result.json + notification_record.md + review_record.json +``` + +### 6.2 文件 hash + +`ra_regulatory_artifact.file_hash` 必填。建议使用 SHA-256。 + +| 场景 | 处理 | +| --- | --- | +| 文件生成成功 | 计算 hash 后写入记录 | +| hash 计算失败 | 产物生成视为失败,节点进入 partial_success 或 failed | +| 下载文件 | 可选重新计算 hash 校验 | + +--- + +## 七、JSON 字段结构建议 + +### 7.1 condition_json + +```json +{ + "extracted": { + "product_category": {"value": "in_vitro_diagnostic", "confidence": 0.92}, + "registration_type": {"value": "initial_registration", "confidence": 0.76} + }, + "confirmed": { + "confirmed_by": 1, + "confirmed_at": "2026-06-06T00:00:00+08:00", + "source": "dialog_choice" + }, + "raw_user_input": "按体外诊断试剂首次注册处理" +} +``` + +### 7.2 risk_summary_json + +```json +{ + "blocking": 2, + "high": 1, + "medium": 3, + "low": 4, + "info": 2, + "notified": { + "feishu": 6 + } +} +``` + +### 7.3 evidence_json + +```json +{ + "matched_rule": { + "rule_id": "ivd_registration_test_report", + "rule_title": "注册检验报告" + }, + "matched_files": [ + { + "file_item_id": 33, + "relative_path": "注册检验/检验报告.pdf", + "matched_by": "directory_keyword" + } + ], + "rag_citations": [ + { + "source_file": "体外诊断试剂注册申报资料要求及说明.doc", + "section_title": "注册申报资料要求", + "snippet": "..." + } + ] +} +``` + +--- + +## 八、与现有表的改造建议 + +### 8.1 ra_workflow_node_run + +第一阶段设计中该表通过 `batch_id` 直接关联文件汇总批次。法规核查复用同一套工作流状态机制,采用通用工作流引用: + +| 字段 | 说明 | +| --- | --- | +| workflow_type | 新增,用于区分 file_summary 和 regulatory_review | +| workflow_batch_id | 新增,记录对应工作流批次 ID | +| batch_id | 保留,兼容文件汇总旧逻辑 | + +### 8.2 ra_workflow_event + +同样增加 `workflow_type`、`workflow_batch_id`,使 SSE 能同时服务文件汇总和法规核查卡片。 + +### 8.3 ra_exported_summary_file + +最终法规核查报告复用导出文件表。现有 `batch_id` 关联文件汇总批次,需要通用化: + +| 字段 | 说明 | +| --- | --- | +| workflow_type | 新增,用于区分 file_summary 和 regulatory_review | +| workflow_batch_id | 新增,记录对应工作流批次 ID | +| batch_id | 保留,兼容文件汇总旧逻辑 | +| export_category | 新增,用于区分 summary_report、risk_report、excel_list、json_package | + +最终法规核查报告进入 `ExportedSummaryFile`,过程产物进入 `RegulatoryArtifact`。 + +--- + +## 九、Django Model 命名建议 + +| 表名 | Model 名称 | +| --- | --- | +| ra_regulatory_rule_version | RegulatoryRuleVersion | +| ra_regulatory_review_batch | RegulatoryReviewBatch | +| ra_regulatory_issue | RegulatoryIssue | +| ra_regulatory_artifact | RegulatoryArtifact | +| ra_regulatory_notification_record | RegulatoryNotificationRecord | + +--- + +## 十、验收检查点 + +| 序号 | 检查项 | 验收标准 | +| --- | --- | --- | +| 1 | 规则版本可追溯 | 每个法规核查批次能查到 rule_version、source_path、rule_file_hash 和 rag_index_version | +| 2 | 批次可多次核查 | 同一个 FileSummaryBatch 可创建多个 RegulatoryReviewBatch | +| 3 | 软删除可用 | 归档或删除法规核查批次后,默认列表不展示但历史可追溯 | +| 4 | 问题可筛选 | 可按 risk_level、status、owner 查询待处理问题 | +| 5 | 证据可追溯 | Issue 可查到 file_path、page_no、field_name 和 evidence_json | +| 6 | 产物可校验 | 每个 RegulatoryArtifact 都有 file_hash | +| 7 | 飞书可重试 | NotificationRecord 可记录 retry_count、send_status 和失败原因 | +| 8 | 权限可追溯 | 所有法规核查数据可通过 batch -> conversation -> user 校验访问权限 | + +--- + +## 十一、后续实现注意事项 + +| 序号 | 问题 | 当前建议 | +| --- | --- | --- | +| 1 | WorkflowNodeRun/Event 通用化 | 已确定新增 workflow_type 和 workflow_batch_id,保留 batch_id 兼容文件汇总 | +| 2 | ExportedSummaryFile 通用化 | 已确定新增 workflow_type、workflow_batch_id 和 export_category | +| 3 | RegulatoryArtifact 下载接口 | 按 batch -> conversation -> user 校验权限 | +| 4 | 飞书用户映射 | 暂通过 User 扩展字段或配置表映射飞书 CLI 可识别账号 | +| 5 | 规则文件 hash 计算时机 | 规则导入或激活时计算并写入 RegulatoryRuleVersion |