docs(regulatory-info-package): 新增第1章监管信息设计文档
This commit is contained in:
860
docs/2.功能设计/5.第1章监管信息材料包生成.md
Normal file
860
docs/2.功能设计/5.第1章监管信息材料包生成.md
Normal file
@@ -0,0 +1,860 @@
|
||||
# 第1章监管信息材料包生成功能设计
|
||||
|
||||
## 文档信息
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 需求分析文档 | docs/1.需求分析/5.第1章监管信息材料包生成.md |
|
||||
| 参考功能设计 | docs/2.功能设计/3.产品关键信息提取与申报文件自动填表.md |
|
||||
| 功能名称 | 第1章监管信息材料包生成 |
|
||||
| 工作流编码 | regulatory_info_package |
|
||||
| 所属模块 | 审核智能体 review_agent |
|
||||
| 设计日期 | 2026-06-10 |
|
||||
| 设计版本 | V1.0 |
|
||||
|
||||
---
|
||||
|
||||
## 一、设计目标
|
||||
|
||||
新增独立工作流 `regulatory_info_package`,用于根据产品说明书生成第1章监管信息材料包。用户在对话中上传或选择一个产品说明书,发送“根据说明书生成第1章监管信息”等指令后,系统复制 `docs/0.原始材料/第1章 监管信息` 下的 7 个样例模板,抽取说明书中的产品关键信息,生成一套新的第1章监管信息文件,并打包为 `第1章 监管信息(预生成版).zip` 作为主下载入口。
|
||||
|
||||
本功能与 `application_form_fill` 平级,不复用其 workflow_type 和批次表;但复用其已形成的服务思想和部分可拆能力,包括字段抽取、LLM 调用、Word 写入、追溯清单、导出下载、通知、工作流事件和前端卡片。
|
||||
|
||||
本期重点实现:
|
||||
|
||||
| 目标 | 说明 |
|
||||
| --- | --- |
|
||||
| 独立工作流 | 新增 `regulatory_info_package` 批次、节点和卡片 |
|
||||
| 单说明书输入 | 直接从当前对话 active 附件中选择唯一说明书;兼容最近成功文件汇总批次 |
|
||||
| 模板驱动 | 通过 YAML 配置维护 7 个模板、字段映射和生成策略 |
|
||||
| 规则 + LLM 并行抽取 | 代码抽取与 LLM 抽取并行,合并后写入模板 |
|
||||
| 待确认高亮 | 系统新填入的 `/`、LLM-only 字段、冲突字段均高亮 |
|
||||
| `.doc` 等价处理 | 设计 `LegacyWordDocumentService`,提供与 `.docx` 一致的文档操作接口 |
|
||||
| zip 主输出 | 扩展 `ExportedSummaryFile.ExportType.ZIP`,统一下载权限 |
|
||||
| LLM 意图路由 | 扩展路由 action,支持固定话术和 LLM 语义判断 |
|
||||
|
||||
---
|
||||
|
||||
## 二、规范依据与裁决
|
||||
|
||||
| 规范来源 | 命中内容 | 设计处理 |
|
||||
| --- | --- | --- |
|
||||
| GYRX 后端开发规范 | 服务层职责清晰、接口响应统一、记录必要日志 | Django 项目沿用现有 JsonResponse/SSE 模式;服务拆入独立模块,记录批次与节点日志 |
|
||||
| GYRX 前端开发规范 | 前端样式复用、交互一致、下载图标语义 | 当前项目为 Django 模板 + 原生 JS,按现有工具 chip、工作流卡片和下载链接风格扩展 |
|
||||
| 既有自动填表设计 | 独立工作流、YAML 配置、字段抽取、追溯清单、导出记录 | 复用模式,不复用批次表和 workflow_type |
|
||||
| 需求分析确认 | `.doc` 不只依赖转换、zip 主入口、LLM-only 高亮 | 在服务抽象和验收标准中作为强约束 |
|
||||
|
||||
冲突裁决:GYRX 规范中部分 Java/Spring 约束不适用于当前 Django 项目,按当前项目既有 Django 架构落地;通用原则如服务拆分、日志、权限和前端交互一致性继续采用。
|
||||
|
||||
---
|
||||
|
||||
## 三、与既有功能关系
|
||||
|
||||
### 3.1 复用边界
|
||||
|
||||
| 能力 | 处理方式 | 现有代码/模块 |
|
||||
| --- | --- | --- |
|
||||
| 对话与消息 | 复用 | `Conversation`、`Message`、`stream_message` |
|
||||
| 附件上传 | 复用 | `FileAttachment`、`file_summary.storage` |
|
||||
| 文件汇总结果 | 兼容复用 | `FileSummaryBatch`、`FileSummaryItem` |
|
||||
| 文本抽取 | 复用并扩展 | `regulatory_review/services/text_extract.py`、`rag_index.py` |
|
||||
| LLM 调用 | 复用 | `review_agent/llm.py` |
|
||||
| 知识库搜索 | 复用系统现有能力 | `knowledge_base.py`、法规 RAG 相关服务 |
|
||||
| 导出下载 | 扩展复用 | `ExportedSummaryFile`、`file_summary.views.export_download` |
|
||||
| 工作流事件 | 复用 | `WorkflowNodeRun`、`WorkflowEvent` |
|
||||
| 通知 | 复用统一通知链路 | `review_agent.notifications` |
|
||||
| 前端卡片 | 扩展复用 | `templates/home.html`、`static/js/app.js` |
|
||||
|
||||
### 3.2 新增边界
|
||||
|
||||
| 能力 | 说明 |
|
||||
| --- | --- |
|
||||
| 独立批次 | 新增 `RegulatoryInfoPackageBatch`,批次号 `RIP-...` |
|
||||
| 独立产物 | 新增 `RegulatoryInfoPackageArtifact` 记录模板副本、抽取结果、生成文件、zip 和追溯清单 |
|
||||
| 独立通知记录 | 新增 `RegulatoryInfoPackageNotificationRecord`,结构与自动填表通知保持一致 |
|
||||
| 模板配置 | 新增 `regulatory_info_package_templates_v1.yaml` |
|
||||
| 说明书选择 | 新增输入选择服务,优先从 active 附件选择,兼容文件汇总批次 |
|
||||
| 材料包生成 | 新增 7 个文件的生成策略和 zip 打包服务 |
|
||||
| `.doc` 适配 | 新增旧版 Word 文档适配层 |
|
||||
|
||||
---
|
||||
|
||||
## 四、总体架构
|
||||
|
||||
### 4.1 目录结构
|
||||
|
||||
新增模块:
|
||||
|
||||
```text
|
||||
review_agent/
|
||||
regulatory_info_package/
|
||||
__init__.py
|
||||
constants.py
|
||||
schemas.py
|
||||
storage.py
|
||||
events.py
|
||||
workflow.py
|
||||
views.py
|
||||
services/
|
||||
__init__.py
|
||||
input_select.py
|
||||
template_config.py
|
||||
template_repository.py
|
||||
instruction_extract.py
|
||||
field_extract.py
|
||||
field_merge.py
|
||||
standard_candidates.py
|
||||
document_writer.py
|
||||
docx_document.py
|
||||
legacy_doc_document.py
|
||||
package_generate.py
|
||||
traceability_export.py
|
||||
zip_export.py
|
||||
summary.py
|
||||
notifier.py
|
||||
templates/
|
||||
regulatory_info_package_templates_v1.yaml
|
||||
prompts/
|
||||
field_extract.md
|
||||
router_intent.md
|
||||
standard_candidate.md
|
||||
```
|
||||
|
||||
### 4.2 逻辑架构
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["AI 对话页"] --> B["意图路由"]
|
||||
B --> C{"action = regulatory_info_package"}
|
||||
C --> D["RegulatoryInfoPackageBatch"]
|
||||
D --> E["RegulatoryInfoPackageWorkflowExecutor"]
|
||||
E --> F["输入说明书选择"]
|
||||
E --> G["模板配置 YAML"]
|
||||
F --> H["说明书文本与表格抽取"]
|
||||
H --> I1["规则/代码抽取"]
|
||||
H --> I2["LLM 结构化抽取"]
|
||||
I1 --> J["字段合并与高亮决策"]
|
||||
I2 --> J
|
||||
J --> K["标准候选服务"]
|
||||
J --> L["材料包生成服务"]
|
||||
K --> L
|
||||
L --> M1["DOCX 文档适配器"]
|
||||
L --> M2["Legacy DOC 文档适配器"]
|
||||
M1 --> N["7 个目标文件"]
|
||||
M2 --> N
|
||||
N --> O["追溯清单"]
|
||||
N --> P["ZIP 打包"]
|
||||
O --> Q["ExportedSummaryFile"]
|
||||
P --> Q
|
||||
E --> R["WorkflowEvent/SSE"]
|
||||
E --> S["通知服务"]
|
||||
```
|
||||
|
||||
### 4.3 技术选型
|
||||
|
||||
| 设计项 | 本期方案 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| Web 框架 | Django | 沿用当前项目 |
|
||||
| 工作流执行 | 轻量 Executor + 后台线程 | 与文件汇总、法规核查、自动填表一致 |
|
||||
| 工作流状态 | `WorkflowNodeRun`、`WorkflowEvent` | 使用 `workflow_type=regulatory_info_package` |
|
||||
| 模板配置 | YAML | 便于维护 7 个模板和字段映射 |
|
||||
| `.docx` 操作 | `python-docx` | 表格、段落、run、底色和字体可控 |
|
||||
| `.doc` 操作 | 适配器抽象 | Python 标准库不支持 `.doc` 二进制 Word 写入;设计为 COM/UNO/第三方库适配器 |
|
||||
| zip 打包 | Python `zipfile` 标准库 | 标准库可满足打包需求 |
|
||||
| Excel 追溯 | `openpyxl` | 复用现有依赖 |
|
||||
| LLM | `review_agent.llm.generate_completion` | 统一模型调用 |
|
||||
| 知识库 | 系统现有知识库/RAG | 不新增单独 RAG 模块 |
|
||||
|
||||
关于 `.doc`:Python 自带库不能实现类似 Apache POI HWPF 的 Word 97-2003 二进制文档完整读写。项目依赖中有 `olefile`,可读取 OLE 复合文档结构,但不足以可靠修改 Word 文本、表格和样式。因此设计上必须使用文档适配器屏蔽实现差异,底层可选 Word COM、LibreOffice UNO、专用第三方库或受控转换兜底。
|
||||
|
||||
---
|
||||
|
||||
## 五、触发与路由设计
|
||||
|
||||
### 5.1 action 扩展
|
||||
|
||||
`skill_router.py` 扩展:
|
||||
|
||||
| 项 | 设计 |
|
||||
| --- | --- |
|
||||
| 新 action | `regulatory_info_package` |
|
||||
| 新属性 | `starts_regulatory_info_package` |
|
||||
| ROUTE_ACTIONS | 增加 `regulatory_info_package` |
|
||||
| LLM prompt | 描述该 action 用于“根据说明书生成第1章监管信息、监管信息材料包、申请表/产品列表/声明材料包” |
|
||||
|
||||
### 5.2 固定规则
|
||||
|
||||
规则预判关键词:
|
||||
|
||||
```python
|
||||
REGULATORY_INFO_PACKAGE_TRIGGER_KEYWORDS = [
|
||||
"根据说明书生成第1章监管信息",
|
||||
"生成监管信息材料包",
|
||||
"从说明书生成第1章材料",
|
||||
"第1章监管信息",
|
||||
"监管信息材料包",
|
||||
]
|
||||
```
|
||||
|
||||
规则命中时直接进入本工作流。规则未命中时,继续走 LLM 路由判断,避免自然表达漏触发。
|
||||
|
||||
### 5.3 对话启动
|
||||
|
||||
`review_agent/services.py::stream_message` 增加分支:
|
||||
|
||||
```text
|
||||
if route.starts_regulatory_info_package:
|
||||
-> 选择说明书输入
|
||||
-> 创建 RegulatoryInfoPackageBatch
|
||||
-> start_regulatory_info_package_workflow
|
||||
-> SSE workflow_started
|
||||
-> 回复“已启动第1章监管信息材料包生成工作流,批次号:RIP-...”
|
||||
```
|
||||
|
||||
如果没有 active 附件,也没有可复用的最近文件汇总批次,则回复“请先上传产品说明书”。
|
||||
如果存在多个候选说明书且用户消息无法唯一命中文件名,则不展示选择弹窗,由对话反问用户确认具体文件名后再启动工作流。
|
||||
|
||||
---
|
||||
|
||||
## 六、输入选择设计
|
||||
|
||||
### 6.1 选择优先级
|
||||
|
||||
| 优先级 | 来源 | 规则 |
|
||||
| --- | --- | --- |
|
||||
| 1 | 用户消息指定文件名 | 按 active 附件名或可复用文件名模糊匹配,唯一命中则使用 |
|
||||
| 2 | 当前对话 active 附件 | 文件名包含“说明书”且扩展名为 `.docx` |
|
||||
| 3 | 当前对话 active 附件 | 唯一 `.docx` 文件 |
|
||||
| 4 | 最近成功 `FileSummaryBatch.items` | 文件名包含“说明书”且扩展名为 `.docx` |
|
||||
| 5 | 无法唯一选择 | 对话反问用户确认使用哪个说明书;必要时批次进入 `waiting_user` |
|
||||
|
||||
本期直接输入只支持 `.docx` 产品说明书。`.doc`、PDF、扫描件说明书作为后续扩展;但输出模板中的 `.doc` 必须支持。
|
||||
|
||||
### 6.2 输入绑定
|
||||
|
||||
批次记录:
|
||||
|
||||
| 字段 | 来源 |
|
||||
| --- | --- |
|
||||
| source_attachment | 直接选择的 FileAttachment |
|
||||
| source_summary_batch | 可选,来自最近成功文件汇总 |
|
||||
| source_summary_item | 可选,来自汇总条目 |
|
||||
| source_file_name | 原始说明书文件名 |
|
||||
| source_storage_path | 说明书存储路径 |
|
||||
|
||||
---
|
||||
|
||||
## 七、模板配置设计
|
||||
|
||||
配置路径:
|
||||
|
||||
```text
|
||||
review_agent/regulatory_info_package/templates/regulatory_info_package_templates_v1.yaml
|
||||
```
|
||||
|
||||
配置结构:
|
||||
|
||||
```yaml
|
||||
version: regulatory_info_package_templates_v1
|
||||
source_dir: docs/0.原始材料/第1章 监管信息
|
||||
output_zip_name: 第1章 监管信息(预生成版).zip
|
||||
templates:
|
||||
- code: ch1_2_directory
|
||||
output_name: CH1.2 监管信息目录.docx
|
||||
source_file: CH1.2 监管信息目录.docx
|
||||
file_format: docx
|
||||
strategy: directory
|
||||
include_in_zip: true
|
||||
fields:
|
||||
- key: product_name
|
||||
targets:
|
||||
- type: paragraph_contains_replace
|
||||
match: 呼吸道合胞病毒、肺炎支原体核酸检测试剂盒(荧光PCR法)
|
||||
- code: ch1_4_application_form
|
||||
output_name: CH1.4 申请表.docx
|
||||
source_file: CH1.4 申请表.docx
|
||||
file_format: docx
|
||||
strategy: application_form
|
||||
include_in_zip: true
|
||||
- code: ch1_9_pre_submission
|
||||
output_name: CH1.9 产品申报前沟通的说明.doc
|
||||
source_file: CH1.9 产品申报前沟通的说明.doc
|
||||
file_format: doc
|
||||
strategy: pre_submission
|
||||
require_legacy_doc_native: true
|
||||
include_in_zip: true
|
||||
```
|
||||
|
||||
### 7.1 配置项说明
|
||||
|
||||
| 配置项 | 说明 |
|
||||
| --- | --- |
|
||||
| version | 配置版本,写入批次 |
|
||||
| source_dir | 样例模板目录 |
|
||||
| output_zip_name | zip 主输出文件名 |
|
||||
| templates | 7 个目标模板 |
|
||||
| code | 模板编码 |
|
||||
| output_name | 生成文件名 |
|
||||
| source_file | 样例文件 |
|
||||
| file_format | docx/doc |
|
||||
| strategy | 生成策略 |
|
||||
| include_in_zip | 是否进入 zip |
|
||||
| fields | 字段映射与替换目标 |
|
||||
| require_legacy_doc_native | `.doc` 是否要求原生处理能力 |
|
||||
|
||||
---
|
||||
|
||||
## 八、字段抽取设计
|
||||
|
||||
### 8.1 说明书解析
|
||||
|
||||
`instruction_extract.py` 输出:
|
||||
|
||||
| 数据 | 说明 |
|
||||
| --- | --- |
|
||||
| paragraphs | 按顺序提取段落 |
|
||||
| sections | 按 `【章节名】` 切分 |
|
||||
| tables | 提取表格二维数据 |
|
||||
| component_tables | 识别主要组成成分表 |
|
||||
| front_text | 前 4000 字,供 LLM 使用 |
|
||||
|
||||
### 8.2 规则抽取
|
||||
|
||||
规则抽取覆盖:
|
||||
|
||||
| 字段 | 规则 |
|
||||
| --- | --- |
|
||||
| product_name | `【产品名称】` 下一段 |
|
||||
| package_specification | `【包装规格】` 到下一章节 |
|
||||
| intended_use | `【预期用途】` 到下一章节 |
|
||||
| detection_principle | `【检测原理】` 到下一章节 |
|
||||
| main_components | `【主要组成成分】` 表格摘要 |
|
||||
| storage_condition_and_validity | `【储存条件及有效期】` 到下一章节 |
|
||||
| sample_type | `样本要求` 中“适用样本类型” |
|
||||
| detection_targets | 从预期用途/检测原理中抽取基因、病原体、靶标 |
|
||||
| applicable_instruments | `【适用仪器】` 到下一章节 |
|
||||
| test_method | `【检验方法】` 摘要 |
|
||||
| standards | 正则抽取 `GB/T`、`YY/T`、`YY`、`GB` 等标准号 |
|
||||
|
||||
### 8.3 LLM 抽取
|
||||
|
||||
LLM prompt 要求只输出 JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
"fields": [
|
||||
{
|
||||
"key": "product_name",
|
||||
"label": "产品名称",
|
||||
"value": "...",
|
||||
"evidence": "...",
|
||||
"confidence": 0.9
|
||||
}
|
||||
],
|
||||
"product_list_rows": [
|
||||
{
|
||||
"package_specification": "...",
|
||||
"composition": "...",
|
||||
"component_name": "...",
|
||||
"main_component": "...",
|
||||
"quantity": "..."
|
||||
}
|
||||
],
|
||||
"standards": []
|
||||
}
|
||||
```
|
||||
|
||||
LLM 不允许填企业信息、分类编码、管理类别、临床评价路径等说明书无法证明的内容。
|
||||
|
||||
### 8.4 字段合并
|
||||
|
||||
`field_merge.py` 输出 `MergedField`:
|
||||
|
||||
| 字段 | 说明 |
|
||||
| --- | --- |
|
||||
| key | 字段编码 |
|
||||
| label | 中文名 |
|
||||
| value | 最终写入值 |
|
||||
| source | rule、llm、missing、conflict |
|
||||
| evidence | 来源片段 |
|
||||
| confidence | 置信度 |
|
||||
| highlight_reason | none、missing、llm_only、conflict、rag_candidate |
|
||||
| needs_review | 是否需人工复核 |
|
||||
|
||||
合并规则:
|
||||
|
||||
| 场景 | 处理 |
|
||||
| --- | --- |
|
||||
| rule 与 LLM 一致 | 采用值,不高亮 |
|
||||
| rule 与 LLM 不一致 | 采用规则优先或配置优先,标记 conflict |
|
||||
| rule 缺失、LLM 命中 | 采用 LLM 值,标记 llm_only |
|
||||
| 全部缺失 | 写 `/`,标记 missing |
|
||||
|
||||
---
|
||||
|
||||
## 九、文档生成设计
|
||||
|
||||
### 9.1 文档适配器接口
|
||||
|
||||
`document_writer.py` 定义统一接口:
|
||||
|
||||
```python
|
||||
class DocumentAdapter:
|
||||
def replace_text(self, old: str, new: str, *, highlight: bool = False) -> int: ...
|
||||
def fill_table_cell(self, row_label: str, value: str, *, highlight: bool = False) -> bool: ...
|
||||
def replace_table(self, marker: str, rows: list[dict], *, highlight_columns: list[str] = None) -> bool: ...
|
||||
def highlight_value(self, value: str, reason: str) -> int: ...
|
||||
def save(self, path: Path) -> Path: ...
|
||||
```
|
||||
|
||||
`.docx` 使用 `DocxDocumentAdapter`。`.doc` 使用 `LegacyDocDocumentAdapter`。
|
||||
|
||||
### 9.2 `.docx` 处理
|
||||
|
||||
能力:
|
||||
|
||||
| 能力 | 实现 |
|
||||
| --- | --- |
|
||||
| 段落替换 | 遍历 paragraph runs |
|
||||
| 表格行填充 | 按首列 label 定位 |
|
||||
| 单元格高亮 | `w:shd` 黄色底色 |
|
||||
| 字体颜色 | 冲突项可红色字体 |
|
||||
| 产品列表重建 | 清空目标表格数据行后追加 |
|
||||
| 声明日期替换 | 按日期正则或段落末尾替换 |
|
||||
|
||||
### 9.3 `.doc` 处理
|
||||
|
||||
设计 `LegacyDocDocumentAdapter`,对外提供与 `.docx` 一致能力。底层按可用性选择适配器:
|
||||
|
||||
| 适配器 | 定位 |
|
||||
| --- | --- |
|
||||
| `WordComDocAdapter` | Windows + Microsoft Word 环境下优先,直接打开 `.doc`、查找替换、设置高亮并保存 `.doc` |
|
||||
| `LibreOfficeUnoDocAdapter` | LibreOffice UNO/API 环境下使用,直接操作文档模型 |
|
||||
| `OleDocReadOnlyAdapter` | 仅可读取时用于诊断,不满足写入验收 |
|
||||
| `ConversionFallbackAdapter` | 兜底路径,可转换为 `.docx` 后处理,但不能作为唯一实现 |
|
||||
|
||||
功能设计约束:
|
||||
|
||||
| 约束 | 说明 |
|
||||
| --- | --- |
|
||||
| 不静默降级 | `.doc` 原生写入失败时必须记录适配器失败原因,随后尝试 `.docx` 兜底;兜底仍失败时该文件失败并触发 partial_success |
|
||||
| 不只靠转换 | 转换可作为兜底,但设计主路径必须是文档适配器 |
|
||||
| 能力探测 | 启动时或节点执行时检测适配器可用性 |
|
||||
| 追溯记录 | 写入 `.doc` 的适配器类型和失败信息写入 artifact metadata |
|
||||
|
||||
### 9.4 7 个文件生成策略
|
||||
|
||||
| 模板 | 策略服务 | 关键动作 |
|
||||
| --- | --- | --- |
|
||||
| CH1.2 监管信息目录 | `generate_directory_doc` | 替换产品名称;页码沿用样例 |
|
||||
| CH1.4 申请表 | `generate_application_form_doc` | 填表格行;缺失字段 `/` 黄底 |
|
||||
| CH1.5 产品列表 | `generate_product_list_doc` | 使用样例表头重建产品列表;货号 `/` 黄底 |
|
||||
| CH1.9 申报前沟通说明 | `generate_pre_submission_doc` | `.doc` 原生替换产品名和公司名;原生失败则输出 `.docx` 兜底文件;两者均失败才不进入 zip |
|
||||
| CH1.11.1 符合标准清单 | `generate_standard_list_doc` | 说明书标准号直接写;候选/缺失高亮 |
|
||||
| CH1.11.5 真实性声明 | `generate_authenticity_statement_doc` | 保留正文,替换产品名,公司名 `/` 黄底,日期当天 |
|
||||
| CH1.11.6 符合性声明 | `generate_compliance_statement_doc` | 保留正文,替换产品名,公司名 `/` 黄底,日期当天 |
|
||||
|
||||
`generate_docs` 节点内部允许多线程并发处理 7 个目标文件。每个文档使用独立模板副本,子线程只返回生成结果,数据库 artifact/export 记录由主线程统一写入,避免并发写库和共享文件冲突。
|
||||
|
||||
---
|
||||
|
||||
## 十、标准清单设计
|
||||
|
||||
系统中已有知识库/RAG 能力,不新增单独 RAG 模块。本功能只新增 `standard_candidates.py` 作为业务服务,调用既有知识库搜索能力。
|
||||
|
||||
处理规则:
|
||||
|
||||
| 来源 | 处理 |
|
||||
| --- | --- |
|
||||
| 说明书明确标准号 | 写入标准清单,记录 `source=instruction` |
|
||||
| 知识库候选标准 | 可写入候选区或追溯清单,标记 `rag_candidate` 并高亮 |
|
||||
| 无命中 | 写 `/` 并黄底 |
|
||||
| 样例标准 | 不无条件沿用 |
|
||||
|
||||
查询建议:
|
||||
|
||||
```text
|
||||
体外诊断试剂 核酸扩增 检测试剂 标准 清单
|
||||
新型冠状病毒 2019-nCoV 核酸检测试剂盒 荧光PCR 标准
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十一、zip 与导出设计
|
||||
|
||||
### 11.1 ExportType 扩展
|
||||
|
||||
`ExportedSummaryFile.ExportType` 增加:
|
||||
|
||||
```python
|
||||
ZIP = "zip", "ZIP"
|
||||
```
|
||||
|
||||
下载 content type 增加:
|
||||
|
||||
```python
|
||||
"zip": "application/zip"
|
||||
```
|
||||
|
||||
### 11.2 导出记录
|
||||
|
||||
| 文件 | export_category | export_type |
|
||||
| --- | --- | --- |
|
||||
| 第1章 监管信息(预生成版).zip | regulatory_info_package | zip |
|
||||
| 7 个生成文件 | generated_document | word 或 legacy_word |
|
||||
| 追溯清单 Excel | traceability | excel |
|
||||
|
||||
追溯 JSON 和抽取过程 JSON 只保存到后台 `logs/` 目录和 artifact 记录,不作为用户下载入口。用户侧只提供追溯 Excel 下载。
|
||||
|
||||
如果不新增 `legacy_word` export_type,则 `.doc` 也可暂用 `word`,通过文件扩展名和 content type 判断下载 MIME。功能设计建议新增 content type 映射时按扩展名兜底,避免 `.doc` 被当作 `.docx`。
|
||||
|
||||
### 11.3 权限
|
||||
|
||||
`file_summary.views._export_for_user` 增加:
|
||||
|
||||
```text
|
||||
if exported.workflow_type == "regulatory_info_package":
|
||||
查询 RegulatoryInfoPackageBatch
|
||||
校验 conversation__user == request.user 且 is_deleted=False
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十二、数据模型设计
|
||||
|
||||
### 12.1 RegulatoryInfoPackageBatch
|
||||
|
||||
```python
|
||||
class RegulatoryInfoPackageBatch(models.Model):
|
||||
class Status(models.TextChoices):
|
||||
PENDING = "pending", "待执行"
|
||||
RUNNING = "running", "执行中"
|
||||
WAITING_USER = "waiting_user", "等待用户"
|
||||
SUCCESS = "success", "成功"
|
||||
PARTIAL_SUCCESS = "partial_success", "部分成功"
|
||||
FAILED = "failed", "失败"
|
||||
CANCELLED = "cancelled", "已取消"
|
||||
```
|
||||
|
||||
字段建议:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| conversation | FK Conversation | 所属对话 |
|
||||
| user | FK User | 发起用户 |
|
||||
| trigger_message | FK Message | 触发消息 |
|
||||
| source_attachment | FK FileAttachment | 直接选中的说明书附件 |
|
||||
| source_summary_batch | FK FileSummaryBatch | 可选文件汇总批次 |
|
||||
| source_summary_item_id | PositiveBigIntegerField | 可选汇总条目 ID |
|
||||
| batch_no | CharField unique | RIP 批次号 |
|
||||
| status | CharField | 状态 |
|
||||
| source_file_name | CharField | 说明书原文件名 |
|
||||
| source_storage_path | CharField | 说明书路径 |
|
||||
| product_name | CharField | 抽取产品名 |
|
||||
| output_zip_name | CharField | zip 文件名 |
|
||||
| generated_files | JSONField | 7 个文件状态 |
|
||||
| missing_fields | JSONField | 缺失项 |
|
||||
| llm_only_fields | JSONField | LLM-only 项 |
|
||||
| conflict_fields | JSONField | 冲突项 |
|
||||
| risk_notes | JSONField | 风险提示 |
|
||||
| template_config_version | CharField | 配置版本 |
|
||||
| template_config_hash | CharField | 配置 hash |
|
||||
| adapter_summary | JSONField | `.doc`/`.docx` 适配器信息 |
|
||||
| work_dir | CharField | 工作目录 |
|
||||
| error_message | TextField | 错误信息 |
|
||||
| started_at/finished_at | DateTimeField | 执行时间 |
|
||||
| is_deleted | BooleanField | 软删除 |
|
||||
|
||||
索引:
|
||||
|
||||
| 索引 | 字段 |
|
||||
| --- | --- |
|
||||
| idx_ra_rip_batch_conv_status | conversation, status |
|
||||
| idx_ra_rip_batch_user_created | user, created_at |
|
||||
| idx_ra_rip_batch_attachment | source_attachment |
|
||||
| idx_ra_rip_batch_summary | source_summary_batch |
|
||||
|
||||
### 12.2 RegulatoryInfoPackageArtifact
|
||||
|
||||
产物类型:
|
||||
|
||||
| 类型 | 说明 |
|
||||
| --- | --- |
|
||||
| template_copy | 模板副本 |
|
||||
| instruction_extract | 说明书抽取结果 |
|
||||
| field_extract_result | 字段抽取结果 |
|
||||
| merged_fields | 合并字段 |
|
||||
| generated_document | 生成文件 |
|
||||
| traceability | 追溯清单 |
|
||||
| zip_package | zip 包 |
|
||||
| notification_record | 通知记录 |
|
||||
|
||||
字段与 `ApplicationFormFillArtifact` 保持一致:`batch`、`artifact_type`、`file_format`、`name`、`file_name`、`storage_path`、`file_size`、`content_hash`、`metadata`、`created_by_node`、`is_deleted`。
|
||||
|
||||
`file_format` 增加 `DOC`、`ZIP`。
|
||||
|
||||
### 12.3 RegulatoryInfoPackageNotificationRecord
|
||||
|
||||
结构对齐 `ApplicationFormFillNotificationRecord`:
|
||||
|
||||
| 字段 | 说明 |
|
||||
| --- | --- |
|
||||
| batch | 所属 RIP 批次 |
|
||||
| recipient | 通知对象 |
|
||||
| channel | feishu_cli、feishu_api、mock |
|
||||
| export_ids | 导出 ID |
|
||||
| message_summary | 通知摘要 |
|
||||
| send_status | pending、success、failed |
|
||||
| retry_count | 重试次数 |
|
||||
| external_message_id | 外部消息 ID |
|
||||
| error_message | 错误 |
|
||||
| sent_at | 发送时间 |
|
||||
|
||||
---
|
||||
|
||||
## 十三、工作流设计
|
||||
|
||||
### 13.1 节点定义
|
||||
|
||||
| 节点编码 | 节点名称 | 触发服务 | 成功条件 | 失败处理 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| prepare | 准备资料 | `RegulatoryInfoPackageWorkflowExecutor` | 找到唯一说明书 | 缺失或多候选进入 waiting_user |
|
||||
| template_copy | 复制模板 | `TemplateRepository` | 7 个模板进入批次目录 | 缺关键模板则 failed |
|
||||
| text_extract | 抽取说明书 | `InstructionExtractService` | 提取文本、章节和表格 | 失败则 failed |
|
||||
| field_extract | 抽取字段 | `FieldExtractionService` | 规则/LLM 结果留底 | LLM 失败可继续 |
|
||||
| field_merge | 合并字段 | `FieldMergeService` | 输出 merged_fields | 无产品名仍继续,产品名 `/` |
|
||||
| generate_docs | 生成材料 | `PackageGenerateService` | 生成 7 个文件 | 单文件失败可 partial_success |
|
||||
| highlight_review_items | 标记待确认 | 文档适配器 | 缺失/LLM-only/冲突完成高亮 | 失败则对应文件失败 |
|
||||
| trace_export | 追溯清单 | `TraceabilityExportService` | 生成 Excel/JSON | 不阻断 zip |
|
||||
| zip_export | 打包下载 | `ZipExportService` | 生成 zip 并创建导出记录 | zip 失败则保留单文件 |
|
||||
| notify | 通知 | `Notifier` | 写通知记录 | 不阻断下载 |
|
||||
| completed | 完成 | Executor | 状态落定、摘要写入对话 | - |
|
||||
|
||||
### 13.2 状态落定
|
||||
|
||||
| 结果 | 批次状态 |
|
||||
| --- | --- |
|
||||
| 7 个文件、zip、追溯清单均成功 | success |
|
||||
| zip 成功但部分单文件/追溯/通知失败 | partial_success |
|
||||
| 单文件成功但 zip 失败 | partial_success |
|
||||
| 关键输入或模板缺失 | failed 或 waiting_user |
|
||||
| 所有目标文件生成失败 | failed |
|
||||
|
||||
---
|
||||
|
||||
## 十四、接口设计
|
||||
|
||||
### 14.1 URL
|
||||
|
||||
```text
|
||||
GET /api/review-agent/regulatory-info-package/health/
|
||||
POST /api/review-agent/regulatory-info-package/start/
|
||||
GET /api/review-agent/regulatory-info-package/<batch_id>/status/
|
||||
POST /api/review-agent/regulatory-info-package/<batch_id>/select-input/
|
||||
```
|
||||
|
||||
### 14.2 start
|
||||
|
||||
请求:
|
||||
|
||||
```json
|
||||
{
|
||||
"conversation_id": 1,
|
||||
"attachment_id": 10,
|
||||
"file_summary_batch_id": 20,
|
||||
"source_summary_item_id": 30
|
||||
}
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"batch_id": 1,
|
||||
"workflow_type": "regulatory_info_package",
|
||||
"batch_no": "RIP-20260610153000-abcdef",
|
||||
"status": "pending"
|
||||
}
|
||||
```
|
||||
|
||||
### 14.3 status
|
||||
|
||||
响应包含:
|
||||
|
||||
| 字段 | 说明 |
|
||||
| --- | --- |
|
||||
| batch | 批次基础信息、产品名、缺失数、LLM-only 数、冲突数 |
|
||||
| nodes | 工作流节点 |
|
||||
| generated_files | 7 个文件状态 |
|
||||
| exports | zip、单文件、追溯清单下载 |
|
||||
| missing_fields | 缺失项摘要 |
|
||||
| llm_only_fields | LLM-only 摘要 |
|
||||
| conflict_fields | 冲突摘要 |
|
||||
| risk_notes | 风险提示 |
|
||||
| notifications | 通知记录 |
|
||||
|
||||
---
|
||||
|
||||
## 十五、前端设计
|
||||
|
||||
### 15.1 对话框底部快捷提示
|
||||
|
||||
`templates/home.html` 增加 tool chip:
|
||||
|
||||
```text
|
||||
根据说明书生成第1章监管信息
|
||||
```
|
||||
|
||||
点击后填入 prompt,不自动发送,保持现有交互一致。
|
||||
|
||||
### 15.2 工作流卡片
|
||||
|
||||
`build_workflow_cards()` 增加 RIP 批次,前端复用现有卡片样式,展示:
|
||||
|
||||
| 信息 | 说明 |
|
||||
| --- | --- |
|
||||
| 批次号 | RIP-... |
|
||||
| 状态 | pending/running/success/partial_success/failed |
|
||||
| 风险摘要 | 缺失字段 N、LLM复核 N、提示 N |
|
||||
| 节点 | RIP 节点 |
|
||||
|
||||
### 15.3 状态轮询
|
||||
|
||||
`summaryPanel` 增加:
|
||||
|
||||
```html
|
||||
data-regulatory-info-package-status-url-template="/api/review-agent/regulatory-info-package/__batch_id__/status/"
|
||||
```
|
||||
|
||||
`static/js/app.js` 在工作流类型判断中增加 `regulatory_info_package`。
|
||||
|
||||
### 15.4 结果展示
|
||||
|
||||
状态 payload 中 `exports` 按类别展示:
|
||||
|
||||
| 类别 | 展示 |
|
||||
| --- | --- |
|
||||
| zip | 主下载按钮 |
|
||||
| generated_document | 单文件下载列表 |
|
||||
| traceability | 追溯清单下载 |
|
||||
|
||||
---
|
||||
|
||||
## 十六、通知设计
|
||||
|
||||
复用统一通知服务,新增 `build_regulatory_info_package_context(batch)`:
|
||||
|
||||
| 摘要项 | 说明 |
|
||||
| --- | --- |
|
||||
| 工作流 | 第1章监管信息材料包生成 |
|
||||
| 批次号 | RIP-... |
|
||||
| 产品名称 | 抽取产品名 |
|
||||
| 导出文件 | zip + 单文件数量 |
|
||||
| 待确认 | 缺失项、LLM-only、冲突项数量 |
|
||||
| 下载提示 | 进入系统下载 zip |
|
||||
|
||||
通知失败不影响下载。
|
||||
|
||||
---
|
||||
|
||||
## 十七、异常与降级
|
||||
|
||||
| 异常 | 处理 |
|
||||
| --- | --- |
|
||||
| 未找到说明书 | 返回提示,不创建或创建 waiting_user 批次 |
|
||||
| 多说明书候选 | waiting_user,等待选择 |
|
||||
| YAML 配置错误 | failed,提示配置错误 |
|
||||
| 样例模板缺失 | failed,列出缺失模板 |
|
||||
| LLM 失败 | 使用规则抽取继续,写 risk_notes |
|
||||
| 规则抽取为空 | 使用 LLM-only 继续并高亮 |
|
||||
| 知识库不可用 | 标准清单填 `/` 并高亮,写 risk_notes |
|
||||
| `.doc` 适配器不可用 | CH1.9 失败,批次 partial_success 或 failed,明确原因 |
|
||||
| zip 打包失败 | 保留单文件下载,状态 partial_success |
|
||||
| 下载文件不存在 | 返回 404,记录日志 |
|
||||
|
||||
---
|
||||
|
||||
## 十八、安全与权限
|
||||
|
||||
| 控制点 | 设计 |
|
||||
| --- | --- |
|
||||
| 批次访问 | `conversation__user == request.user` |
|
||||
| 附件访问 | 附件必须属于当前对话和当前用户 |
|
||||
| 汇总批次访问 | 批次必须属于当前对话和当前用户 |
|
||||
| 导出下载 | `workflow_type=regulatory_info_package` 时反查 RIP 批次 |
|
||||
| 工作目录 | `media/regulatory_info_package/{user_id}/{conversation_id}/{batch_no}` |
|
||||
| 路径安全 | 所有复制/输出路径必须校验位于批次工作目录内 |
|
||||
| 原始模板保护 | 只读复制,不允许覆盖 `docs/0.原始材料` |
|
||||
|
||||
---
|
||||
|
||||
## 十九、测试设计
|
||||
|
||||
| 测试文件 | 覆盖 |
|
||||
| --- | --- |
|
||||
| `tests/test_regulatory_info_package_models.py` | 批次、产物、通知、zip 导出类型 |
|
||||
| `tests/test_regulatory_info_package_trigger.py` | 固定规则与 LLM 路由 |
|
||||
| `tests/test_regulatory_info_package_input_select.py` | 说明书选择、多候选 waiting_user |
|
||||
| `tests/test_regulatory_info_package_template_config.py` | YAML 加载、模板存在性校验 |
|
||||
| `tests/test_regulatory_info_package_field_extract.py` | 说明书字段、表格、标准号抽取 |
|
||||
| `tests/test_regulatory_info_package_field_merge.py` | missing、llm_only、conflict 高亮决策 |
|
||||
| `tests/test_regulatory_info_package_docx_writer.py` | docx 替换、表格填充、黄底 |
|
||||
| `tests/test_regulatory_info_package_legacy_doc.py` | `.doc` 适配器能力探测和失败提示 |
|
||||
| `tests/test_regulatory_info_package_zip.py` | zip 只包含 success/fallback_success 文件 |
|
||||
| `tests/test_regulatory_info_package_workflow.py` | 工作流节点和状态落定 |
|
||||
| `tests/test_regulatory_info_package_views.py` | start/status/权限 |
|
||||
| `tests/test_regulatory_info_package_frontend.py` | 卡片、快捷提示、状态 URL |
|
||||
|
||||
回归测试:
|
||||
|
||||
```bash
|
||||
python manage.py check
|
||||
pytest tests/test_application_form_fill_*.py tests/test_file_summary_views.py tests/test_regulatory_*tests.py
|
||||
```
|
||||
|
||||
实际执行时按项目现有测试命名拆分运行。
|
||||
|
||||
---
|
||||
|
||||
## 二十、实施顺序建议
|
||||
|
||||
| 阶段 | 内容 |
|
||||
| --- | --- |
|
||||
| RIP-1 | 模型、迁移、ExportType.ZIP、下载权限 |
|
||||
| RIP-2 | 模块骨架、YAML 配置、输入说明书选择 |
|
||||
| RIP-3 | 路由 action、对话启动、工作流节点 |
|
||||
| RIP-4 | 说明书文本/表格抽取、规则 + LLM 字段抽取 |
|
||||
| RIP-5 | docx 文档生成、黄底高亮、产品列表重建 |
|
||||
| RIP-6 | `.doc` 适配器、CH1.9 处理能力 |
|
||||
| RIP-7 | 追溯清单、zip 导出、助手摘要 |
|
||||
| RIP-8 | 前端卡片、快捷提示、状态轮询 |
|
||||
| RIP-9 | 通知、权限、全量回归 |
|
||||
|
||||
---
|
||||
|
||||
## 二十一、待确认与风险
|
||||
|
||||
| 风险 | 说明 | 建议 |
|
||||
| --- | --- | --- |
|
||||
| `.doc` 原生写入难度 | Python 标准库不支持 Word `.doc` 完整写入 | 优先调研 Word COM 或 LibreOffice UNO;设计适配器隔离风险 |
|
||||
| 样例模板文本碎片 | Word run 拆分可能导致简单字符串替换失败 | 文档写入服务需支持跨 run 替换 |
|
||||
| 产品列表结构复杂 | 说明书表格可能存在合并单元格和多规格 | 先覆盖目标说明书结构,再扩展通用表格归一化 |
|
||||
| 标准清单准确性 | 说明书未必包含标准号,知识库候选不能直接作为结论 | 候选全部高亮并进入追溯清单 |
|
||||
| LLM-only 风险 | LLM 推断可能过度补全 | 写入但高亮,追溯清单标记需复核 |
|
||||
|
||||
---
|
||||
|
||||
## 二十二、设计结论
|
||||
|
||||
| 编号 | 结论 |
|
||||
| --- | --- |
|
||||
| D1 | 功能设计文档新增为 `docs/2.功能设计/5.第1章监管信息材料包生成.md` |
|
||||
| D2 | 新增独立模块 `review_agent/regulatory_info_package/` |
|
||||
| D3 | 新建独立批次、产物、通知三张表 |
|
||||
| D4 | 输入选择以 active 附件为主,兼容最近成功文件汇总批次 |
|
||||
| D5 | `ExportedSummaryFile.ExportType` 扩展 `zip` |
|
||||
| D6 | 采用 YAML 配置驱动 7 个模板 |
|
||||
| D7 | `.doc` 通过 `LegacyWordDocumentService` 适配器实现与 `.docx` 等价接口 |
|
||||
| D8 | 标准候选复用系统已有知识库/RAG,不新增独立 RAG |
|
||||
| D9 | 前端只扩展现有对话页、工作流卡片、快捷提示和状态轮询 |
|
||||
| D10 | 本轮先产出功能设计;数据库设计先在本文档中给出,后续可拆成正式数据库设计文档 |
|
||||
Reference in New Issue
Block a user