# Tool B - 病历结构化机器人 技术债务清单 > **创建日期?* 2025-12-03 > **状态:** 待处? > **优先级:** P1=高优先级, P2=中优先级, P3=低优先级 --- ## 📋 技术债务列表 ### **[P1] #1 - Excel导出与前端显示结果不一?* **问题描述?* - 用户在步?交叉验证页面看到的提取结果,与导出的Excel文件内容不一? - 列顺序混乱,部分字段缺失或数据错? **重现步骤?* 1. 完成双模型提取并进入步骤4 2. 点击"导出当前结果"或在步骤5点击"下载结果Excel" 3. 打开Excel,对比前端显示的结果 **根本原因?* - JavaScript对象展开`...extractedData`时顺序不固定 - 未按模板定义的字段顺序构建Excel? **当前状态:** - ?已部分修复:按targetFields顺序导出 - ?仍需验证:多次导出结果是否稳定一? **解决方案?* 1. 严格按照`task.targetFields`定义的字段顺序导? 2. 添加表头样式(加粗、冻结首行) 3. 添加数据验证(确保所有字段都存在? 4. 添加导出测试用例 **预计工时?* 2小时 **影响范围?* 后端 ExtractionController.exportResults方法 --- ### **[P2] #2 - 步骤3进度条显示不够细?* **问题描述?* - 当前进度条直接从0%跳到100%,缺少中间过? - 用户无法感知大模型正在处理第几条记录 - 没有实时反馈当前处理状态(?正在处理?/9?? **期望效果?* ``` 提取进度: 33% (3/9条已完成) 日志输出? [13:43:12] 正在创建提取任务... [13:43:12] 任务创建成功 (ID: xxx) [13:43:12] 初始化双模型引擎 (DeepSeek-V3 & Qwen-Max)... [13:43:13] [1/9] 正在提取: 【右肺下叶】浸润性腺?.. [13:43:18] [1/9] ?提取完成 (DeepSeek: 549 tokens, Qwen: 627 tokens) [13:43:19] [2/9] 正在提取: 【右肺上叶】浸润性腺?.. [13:43:24] [2/9] ?提取完成 (DeepSeek: 486 tokens, Qwen: 551 tokens) ... [13:43:30] PII 脱敏完成 [13:43:30] ?所有记录提取完成! ``` **解决方案?* **后端改动?* 1. 在`DualModelExtractionService.batchExtract`的for循环中,每处理完一条记录就更新进度 2. 添加`currentItem`字段到Task表(可选,用于实时显示当前处理的记录) 3. 或者使用Redis存储实时进度信息(更云原生) **前端改动?* 1. 轮询API时,解析`processedCount`和`totalCount` 2. 动态生成日志:`[${processedCount}/${totalCount}] 正在提取...` 3. 进度条平滑过渡(CSS transition? **预计工时?* 3小时 **影响范围?* - 后端:DualModelExtractionService.batchExtract - 前端:Step3Processing.tsx --- ### **[P1] #3 - Excel文件预处理与脏数据清?* **问题描述?* 医疗科研场景下,Excel文件质量参差不齐,存在大量脏数据导致解析失败或结果错误? #### **子问?:表头特殊字?* - **现象?* 列名包含换行符`\n`、空格、制表符等,导致列名匹配失败 - **示例?* `"病人ID\n(Patient ID)"` ?前端下拉框显示异? - **影响?* 用户无法选择正确的列 #### **子问?:公?(Formulas)** - **现象?* 单元格包含公式`=A1+B1`,xlsx库读取时返回公式文本而非计算结果 - **示例?* - 原始值:`=SUM(A1:A10)` - 读取结果:字符串`"=SUM(A1:A10)"`(而非数字? - 外部引用:`=[外部文件]Sheet1!A1` ?`#REF!` - **影响?* 数值型字段(如年龄、血糖值)变成文本,无法统? #### **子问?:合并单元格 (Merged Cells)** - **现象?* 医生习惯合并"住院?列,对应多行化验记录 - **示例?* ``` 住院? 检查项? 结果 H001 血常规 正常 ?只有这行有住院号 (合并) 肝功? 异常 ?这行住院号为null (合并) 肾功? 正常 ?这行住院号为null ``` - **影响?* 后续行的关联字段丢失,无法追溯到患? #### **子问?:日期地?(Date Parsing Hell)** - **现象?* Excel日期存储为数字(Serial Number),或多种文本格? - **示例?* - `44927` ?应该解析?`2023-01-01` - `2023.1.1`(文本) - `2023??日`(中文) - `Jan 1, 2023`(英文) - **影响?* 日期字段无法排序、筛选、统? #### **子问?:不可见字符与脏文本 (Ghost Characters)** - **现象?* 看起来是"?,实际包含不可见字符 - **示例?* - `"?"` (尾部空格) - `"男\u200b"` (零宽空格 Zero-Width Space) - `"男\ufeff"` (BOM字符) - **影响?* 条件判断失败:`if (sex === '?)` ?false - **医学场景特例?* - 化验单复制粘贴时带入富文本格? - 不同医院HIS系统导出编码不统一 **解决方案?* #### **架构设计:独立的Excel预处理服?* ```typescript // backend/src/modules/dc/services/ExcelPreprocessor.ts export class ExcelPreprocessor { /** * 清洗表头 */ cleanHeaders(headers: string[]): string[] { return headers.map(h => h .replace(/[\n\r\t]/g, ' ') // 移除换行、制表符 .trim() // 去除首尾空格 .replace(/\s+/g, ' ') // 多个空格合并为一? ); } /** * 处理公式单元? */ processFormulas(worksheet: xlsx.WorkSheet): void { // 使用 xlsx ?{ cellFormula: false } 选项 // 或手动遍历单元格,计算公式结? } /** * 展开合并单元? */ unflattenMergedCells(worksheet: xlsx.WorkSheet): void { // 1. 找到所有合并区?worksheet['!merges'] // 2. 将主单元格的值填充到所有子单元? } /** * 统一日期格式 */ normalizeDates(value: any): string | null { if (typeof value === 'number') { // Excel Serial Number ?ISO Date return this.excelSerialToDate(value); } if (typeof value === 'string') { // 尝试多种格式解析 return this.parseChineseDate(value) || this.parseSlashDate(value) || this.parseDotDate(value); } return null; } /** * 清除不可见字? */ cleanInvisibleChars(text: string): string { return text .replace(/\u200b/g, '') // 零宽空格 .replace(/\ufeff/g, '') // BOM .replace(/\u00a0/g, ' ') // 不间断空??普通空? .trim(); } } ``` #### **使用位置?* 1. **uploadFile API** - 上传后立即预处理,返回清洗后的列? 2. **healthCheck API** - 使用清洗后的数据进行检? 3. **createTask API** - 使用清洗后的数据创建items **预计工时?* 16小时(复杂度高,需要大量测试) **影响范围?* - 新增:`ExcelPreprocessor.ts` (~400? - 修改:`ExtractionController.ts` 的文件处理逻辑 - 测试:覆盖各种脏数据场景 **依赖?* - xlsx库的高级功能(cellFormula?merges等) - dayjs或date-fns(日期解析) --- ### **[P2] #4 - 支持用户自定义提取模?* **问题描述?* 当前系统只支?个预设模板(肺癌病理、糖尿病入院、高血压门诊),无法满足用户的多样化需求? **需求场景:** 1. 科研人员研究罕见病(如:系统性红斑狼疮、重症肌无力? 2. 需要提取的字段与预设模板不? 3. 每个研究项目的数据规范可能不? **期望功能?* #### **1. 前端:自定义模板编辑?* ``` 步骤2.1:选择模板来源 - [ ] 使用系统预设模板 - [x] 创建自定义模? 步骤2.2:定义模板信? - 模板名称:[我的肺癌研究模板] - 疾病类型:[自定义:系统性红斑狼疮] - 报告类型:[自定义:实验室检查] 步骤2.3:定义提取字段(可视化编辑) ┌─────────────────────────────────────? ?字段1: [抗核抗体滴度] ? ?描述: [?1:320, 1:640] ? ?宽度: [w-32] ? ? ?[ 删除 ] ? ├─────────────────────────────────────? ?字段2: [补体C3] ? ?描述: [单位g/L] ? ?[ 删除 ] ? └─────────────────────────────────────? [+ 添加字段] 步骤2.4:AI生成Prompt(自动化? [ 🤖 让AI帮我生成提示?] 后台自动生成? ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 你是一名风湿免疫科专家。请从以下系统性红斑狼? 患者的实验室检查报告中提取关键信息? 提取字段(必须返回以下所有字段)? - 抗核抗体滴度:如 1:320, 1:640 - 补体C3:单位g/L **输出格式:严格的JSON格式?* ```json { "抗核抗体滴度": "...", "补体C3": "..." } ``` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [ 编辑Prompt ] [ 预览效果 ] [ 保存模板 ] ``` #### **2. 后端:模板管理API** ```typescript // 新增API端点 POST /api/v1/dc/tool-b/templates // 创建自定义模? PUT /api/v1/dc/tool-b/templates/:id // 更新模板 DELETE /api/v1/dc/tool-b/templates/:id // 删除模板 GET /api/v1/dc/tool-b/templates/:id // 获取模板详情 // Prompt自动生成服务 POST /api/v1/dc/tool-b/templates/generate-prompt Request: { "diseaseType": "系统性红斑狼?, "reportType": "实验室检?, "fields": [ { "name": "抗核抗体滴度", "desc": "?1:320, 1:640" }, { "name": "补体C3", "desc": "单位g/L" } ] } Response: { "promptTemplate": "你是一名风湿免疫科专家...", "estimatedTokens": 450 } ``` #### **3. AI Prompt生成逻辑** ```typescript // 使用元Prompt(Meta-Prompt? async generatePrompt( diseaseType: string, reportType: string, fields: { name: string; desc: string }[] ): Promise { const metaPrompt = ` 你是一名医学AI Prompt工程师。请为病历结构化提取任务生成专业的提示词? 任务背景? - 疾病类型?{diseaseType} - 报告类型?{reportType} 提取字段? ${fields.map((f, i) => `${i + 1}. ${f.name}?{f.desc}`).join('\n')} 要求? 1. 模拟该疾病领域的专家角色 2. 清晰说明每个字段的提取规? 3. 要求输出严格的JSON格式 4. 处理"未提?的情? 请生成完整的Prompt。`; // 调用GPT-5或Claude生成Prompt const llm = LLMFactory.getAdapter('gpt-5'); const response = await llm.chat([ { role: 'user', content: metaPrompt } ]); return response.content; } ``` **技术亮点:** - ?**Prompt即代码(Prompt-as-Code?*:模板可版本控制、A/B测试 - ?**AI生成AI的Prompt(Meta-Prompt?*:降低用户门? - ?**模板市场(未来)**:用户可分享、下载优质模? **预计工时?* 12小时 **影响范围?* - 新增:`CustomTemplateService.ts` (~300? - 新增:`PromptGeneratorService.ts` (~200? - 前端:Step2Schema.tsx 新增自定义模板编辑UI - 数据库:DCTemplate表已支持,无需改动 --- ## 📊 优先级评? | 债务ID | 问题 | 优先?| 工时 | 影响用户 | 技术风?| |--------|------|--------|------|----------|----------| | #1 | Excel导出不一?| P1 | 2h | 高(核心功能?| ?| | #2 | 进度条显示优?| P2 | 3h | 中(体验优化?| ?| | #3 | Excel预处?| P1 | 16h | 高(数据质量?| ?| | #4 | 自定义模?| P2 | 12h | 中(扩展性) | ?| **总计?* 33小时(约4个工作日? --- ## 🎯 建议处理顺序 ### **Sprint 1:核心功能修复(P1优先?* 1. ?#1 - Excel导出修复?小时)→ **立即处理** 2. #3 - Excel预处理(16小时)→ **分阶段实?* - Phase 1:表头清洗(2小时? - Phase 2:合并单元格展开?小时? - Phase 3:公式处理(3小时? - Phase 4:日期统一?小时? - Phase 5:不可见字符清理?小时? - Phase 6:集成测试(2小时? ### **Sprint 2:体验优化(P2?* 1. #2 - 进度条优化(3小时? 2. #4 - 自定义模板(12小时? - Phase 1:后端模板CRUD?小时? - Phase 2:Prompt自动生成?小时? - Phase 3:前端模板编辑器?小时? --- ## 💡 长期优化建议 ### **1. 数据质量评分系统** 为上传的Excel文件打分?-100分)? - ?90-100:优质数据,直接处理 - ⚠️ 60-89:一般质量,提示可能问题 - ?0-59:低质量,强制要求用户清洗后再上? ### **2. Excel模板标准?* 提供标准Excel模板下载,用户按模板填写,减少脏数据? ``` 病历结构化标准模?v1.0.xlsx - 表头行冻? - 数据验证(下拉框? - 字段说明(批注) - 示例数据 ``` ### **3. 智能修复建议** 检测到问题时,AI给出修复建议? ``` ⚠️ 检测到22个合并单元格,可能导致数据丢? 建议操作? [ 自动展开合并单元?] [ 忽略并继?] ``` --- ## 📝 开发记? | 日期 | 处理内容 | 状?| 备注 | |------|---------|------|------| | 2025-12-03 | 创建技术债务文档 | ?| 初始记录4个问?| | 2025-12-03 | #1 Excel导出顺序修复 | 🔄 | 已修改代码,待验?| | - | #2 进度条优?| ⏸️ | 待开?| | - | #3 Excel预处?| ⏸️ | 待开?| | - | #4 自定义模?| ⏸️ | 待开?| --- ## 🔗 相关文档 - [技术设计文档:工具 B](../02-技术设?技术设计文档:工具%20B%20-%20病历结构化机器人%20(The%20AI%20Structurer).md) - [API设计文档](../02-技术设?API设计文档-DC模块(完整版?md) - [开发计划](../04-开发计?DC模块Tool-B开发计?md) - [云原生开发规范](../../../04-开发规?08-云原生开发规?md) --- **文档维护?* 每次处理技术债务时更新此文档