# IIT Manager Agent 技术债务清单 **文档版本**: v1.0 **最后更新**: 2026-01-04 **当前阶段**: Phase 1.5 完成 --- ## 📋 文档说明 本文档记录IIT Manager Agent模块的技术债务,包括当前的临时方案、已知限制、待优化项,以及未来改进计划。 --- ## 🎯 技术债务优先级定义 | 优先级 | 说明 | 处理时机 | |-------|------|---------| | **P0 - 阻塞性** | 影响核心功能,必须立即处理 | 立即 | | **P1 - 高优先级** | 影响用户体验或性能,建议Phase 2处理 | 1个月内 | | **P2 - 中优先级** | 功能增强,可在Phase 3处理 | 3个月内 | | **P3 - 低优先级** | 优化项,长期规划 | 6个月内 | --- ## 🔴 P0 - 阻塞性债务 **当前状态**: ✅ 无P0级债务 --- ## 🟠 P1 - 高优先级债务 ### 1. 意图识别升级 **当前方案**: 关键词匹配(正则表达式) **问题**: - ⚠️ 无法理解复杂的自然语言 - ⚠️ 容易误判边缘case - ⚠️ 需要人工维护关键词列表 **影响**: - 当用户使用非标准表达时,可能无法正确识别意图 - 例如:"帮我看一下那个7号的数据" 可能无法识别为`query_record` **改进方案**: **方案A: LLM意图判断**(推荐) ```typescript // 使用LLM进行意图分类 const intentPrompt = `你是意图识别专家。用户消息:${userMessage} 请判断用户意图,从以下选项中选择: 1. query_record - 查询特定患者记录 2. count_records - 统计患者数量 3. query_protocol - 查询研究方案文档 4. project_info - 查询项目信息 5. general_chat - 普通对话 只返回JSON: {"intent": "xxx", "params": {...}} `; const intentResult = await llm.chat([{ role: 'user', content: intentPrompt }]); ``` **优势**: - ✅ 理解能力强,支持复杂表达 - ✅ 无需维护关键词 - ✅ 适应性好 **劣势**: - ❌ 增加一次LLM调用(~1秒,+¥0.0001成本) - ❌ 总响应时间增加到~6秒 **方案B: BERT分类模型** ```python # 训练意图分类模型 from transformers import BertForSequenceClassification model = BertForSequenceClassification.from_pretrained( 'bert-base-chinese', num_labels=5 ) # 训练数据:100-200个标注样本 # 推理速度:<100ms ``` **优势**: - ✅ 速度快(<100ms) - ✅ 理解能力强 - ✅ 成本低 **劣势**: - ❌ 需要标注训练数据 - ❌ 需要部署模型服务 - ❌ 需要持续迭代 **建议**: - Phase 2: 先使用方案A(LLM判断),快速验证效果 - Phase 3: 如果量大,再切换到方案B(BERT模型) **预计工作量**: 2-3天 --- ### 2. 上下文存储迁移到Redis **当前方案**: 内存缓存(Node.js Map) **问题**: - ⚠️ 单机内存,不支持分布式部署 - ⚠️ 服务重启后上下文丢失 - ⚠️ 内存占用无限制(虽有自动清理,但仍有风险) **影响**: - 当后端服务重启时,所有用户的对话上下文会丢失 - 如果部署多个实例,用户请求可能路由到不同实例,导致上下文丢失 **改进方案**: ```typescript // backend/src/modules/iit-manager/agents/SessionMemory.ts import Redis from 'ioredis'; export class SessionMemory { private redis: Redis; private readonly EXPIRE_TIME = 1800; // 30分钟 constructor() { this.redis = new Redis(config.redisUrl); } async addMessage(userId: string, role: 'user' | 'assistant', content: string): Promise { const key = `session:${userId}`; const message = { role, content, timestamp: Date.now() }; // 1. 获取当前会话 const sessionData = await this.redis.get(key); const session = sessionData ? JSON.parse(sessionData) : { messages: [] }; // 2. 添加消息 session.messages.push(message); // 3. 保持最近3轮 if (session.messages.length > 6) { session.messages = session.messages.slice(-6); } // 4. 存回Redis(30分钟过期) await this.redis.setex(key, this.EXPIRE_TIME, JSON.stringify(session)); } async getContext(userId: string): Promise { const key = `session:${userId}`; const sessionData = await this.redis.get(key); if (!sessionData) return ''; const session = JSON.parse(sessionData); return session.messages .map(m => `${m.role === 'user' ? '用户' : 'AI'}: ${m.content}`) .join('\n\n'); } } ``` **优势**: - ✅ 支持分布式部署 - ✅ 服务重启不丢失上下文 - ✅ 内存占用可控 **劣势**: - ❌ 增加Redis依赖 - ❌ 每次读写需要网络IO(~1-2ms) **建议**: Phase 2实施,优先级中高 **预计工作量**: 1天 --- ### 3. Dify检索结果缓存 **当前方案**: 每次都调用Dify API检索 **问题**: - ⚠️ 相同问题重复检索,浪费时间 - ⚠️ Dify API响应时间占30%(1.5-1.7秒) **影响**: - 响应速度有提升空间 - 相同问题第二次询问仍需1.5秒 **改进方案**: ```typescript // 使用Redis缓存Dify检索结果 private async queryDifyKnowledge(query: string): Promise { // 1. 生成缓存key(query的hash) const cacheKey = `dify:${md5(query)}`; // 2. 尝试从缓存获取 const cached = await redis.get(cacheKey); if (cached) { logger.info('Dify检索命中缓存', { query }); return cached; } // 3. 调用Dify API const result = await difyClient.retrieveKnowledge(...); // 4. 格式化结果 const formattedKnowledge = this.formatDifyResult(result); // 5. 缓存结果(1小时) await redis.setex(cacheKey, 3600, formattedKnowledge); return formattedKnowledge; } ``` **优势**: - ✅ 相同问题响应速度提升1.5秒(从4.8秒降到3.3秒) - ✅ 减少Dify API调用次数 - ✅ 降低Dify服务器负载 **劣势**: - ❌ 文档更新后需要清除缓存 - ❌ 缓存占用Redis内存 **缓存失效策略**: - 文档上传/更新/删除时,清除对应Dataset的所有缓存 - 缓存过期时间:1小时 **建议**: Phase 2实施,优先级中 **预计工作量**: 1天 --- ### 4. REDCap数据缓存 **当前方案**: 每次都调用REDCap API查询 **问题**: - ⚠️ REDCap API响应时间占25%(1.2-1.3秒) - ⚠️ 患者基本信息变化频率低,不需要每次实时查询 **影响**: - 响应速度有提升空间 - 增加REDCap服务器负载 **改进方案**: ```typescript // 分层缓存策略 private async queryRedcapRecord(recordId: string): Promise { const cacheKey = `redcap:record:${recordId}`; // 1. 尝试从缓存获取 const cached = await redis.get(cacheKey); if (cached) { return JSON.parse(cached); } // 2. 调用REDCap API const records = await redcap.exportRecords({ records: [recordId] }); // 3. 缓存结果(5分钟) await redis.setex(cacheKey, 300, JSON.stringify(records[0])); return records[0]; } ``` **缓存策略**: | 数据类型 | 缓存时间 | 原因 | |---------|---------|------| | 患者基本信息 | 5分钟 | 变化频率低 | | 统计数据 | 1分钟 | 需要较实时 | | 项目配置 | 1小时 | 几乎不变 | **优势**: - ✅ 响应速度提升1.2秒 - ✅ 减少REDCap服务器负载 **劣势**: - ❌ 数据可能有5分钟延迟 **建议**: Phase 2实施,需与用户确认是否接受5分钟延迟 **预计工作量**: 1天 --- ## 🟡 P2 - 中优先级债务 ### 5. 文档上传API开发 **当前方案**: 手动通过Dify界面上传文档 **问题**: - ⚠️ 不支持批量上传 - ⚠️ 需要登录Dify系统 - ⚠️ 无法自动化 **影响**: - PI无法自助上传研究文档 - 需要技术人员协助 **改进方案**: ```typescript // backend/src/modules/iit-manager/routes/index.ts // 上传文档到项目知识库 router.post('/projects/:projectId/documents', async (request, reply) => { const { projectId } = request.params; const file = await request.file(); // 1. 获取项目配置 const project = await prisma.iitProject.findUnique({ where: { id: projectId }, select: { difyDatasetId: true } }); // 2. 上传到Dify const buffer = await file.toBuffer(); const result = await difyClient.uploadDocumentDirectly( project.difyDatasetId, buffer, file.filename ); // 3. 等待索引完成 await difyClient.waitForDocumentProcessing( project.difyDatasetId, result.document.id ); return reply.send({ success: true, documentId: result.document.id }); }); // 删除文档 router.delete('/projects/:projectId/documents/:documentId', async (request, reply) => { // 实现文档删除 }); // 获取文档列表 router.get('/projects/:projectId/documents', async (request, reply) => { // 实现文档列表查询 }); ``` **前端界面**(可选): - 文档上传表单 - 文档列表展示 - 文档状态追踪(uploading → indexing → completed) **建议**: Phase 3实施,优先级中 **预计工作量**: 2-3天 --- ### 6. 用户绑定默认项目 **当前方案**: 所有用户共享同一个活跃项目(`status='active'`) **问题**: - ⚠️ 无法支持多项目 - ⚠️ 不同用户可能关注不同项目 **影响**: - 如果有多个IIT项目,无法区分用户属于哪个项目 **改进方案**: **数据模型更新**: ```typescript // backend/prisma/schema.prisma model IitUserMapping { // ... 现有字段 ... // 新增:用户的默认项目 defaultProjectId String? @map("default_project_id") } ``` **ChatService更新**: ```typescript async handleMessage(userId: string, userMessage: string): Promise { // 1. 获取用户的默认项目 const userMapping = await prisma.iitUserMapping.findFirst({ where: { wecomUserId: userId } }); const projectId = userMapping?.defaultProjectId; // 2. 基于项目查询数据 const project = await prisma.iitProject.findUnique({ where: { id: projectId } }); // 后续逻辑... } ``` **建议**: Phase 2后期实施,当有多个项目时 **预计工作量**: 1-2天 --- ### 7. Function Calling升级 **当前方案**: 关键词意图识别 → 手动调用工具 **问题**: - ⚠️ 无法自动决定是否调用工具 - ⚠️ 无法根据上下文自动提取参数 **影响**: - 如果用户问"7号患者和8号患者哪个更严重?",当前无法自动查询两个患者 **改进方案**: 使用DeepSeek-V3的**Native Function Calling**: ```typescript // 定义工具 const tools = [ { type: 'function', function: { name: 'query_redcap_record', description: '查询REDCap中特定患者的记录', parameters: { type: 'object', properties: { recordId: { type: 'string', description: '患者记录ID' } }, required: ['recordId'] } } }, { type: 'function', function: { name: 'query_dify_knowledge', description: '检索研究方案、CRF表格等文档', parameters: { type: 'object', properties: { query: { type: 'string', description: '查询问题' } }, required: ['query'] } } } ]; // LLM自动决定调用哪些工具 const response = await llm.chat(messages, { tools }); // 处理工具调用 if (response.tool_calls) { for (const toolCall of response.tool_calls) { if (toolCall.function.name === 'query_redcap_record') { const args = JSON.parse(toolCall.function.arguments); const result = await this.queryRedcapRecord(args.recordId); // 继续对话... } } } ``` **优势**: - ✅ LLM自动决定是否调用工具 - ✅ 自动提取参数(如recordId) - ✅ 支持多工具并行调用 - ✅ 更智能、更灵活 **劣势**: - ❌ 增加一次LLM调用 - ❌ 总响应时间可能增加到7-8秒 **建议**: Phase 3实施,作为高级功能 **预计工作量**: 3-5天 --- ### 8. 智能引用系统 **当前方案**: Dify返回的文档片段直接显示 **问题**: - ⚠️ 无法溯源到具体文档和位置 - ⚠️ 用户无法验证信息来源 **影响**: - 用户体验不够透明 **改进方案**: 参考ASL模块的智能引用系统: ```typescript // 1. 收集引用信息 interface Citation { id: number; documentName: string; segmentIndex: number; score: number; content: string; } // 2. AI回答中插入引用标记 const answer = `根据研究方案[1]和CRF表格[2],纳入标准包括: 1. 年龄18-75岁[1] 2. 符合诊断标准[1][2] 3. 签署知情同意书[3] --- 📚 **参考文献** [1] 📄 **研究方案.pdf** - 第3段 (相关度95%) "纳入标准:年龄18-75岁,符合诊断标准..." [2] 📄 **CRF表格.docx** - 第5段 (相关度92%) "基线评估包括:诊断标准、入组时间..." `; // 3. 前端高亮显示引用 // 点击[1]跳转到引用详情 ``` **建议**: Phase 3实施,作为体验优化 **预计工作量**: 3-4天 --- ## 🟢 P3 - 低优先级债务 ### 9. 批量数据查询优化 **当前方案**: 单条记录查询 **问题**: - ⚠️ 如果用户问"所有患者的入组情况",需要多次查询 **改进方案**: - 支持批量查询 - 生成数据摘要 **建议**: Phase 4实施 **预计工作量**: 2-3天 --- ### 10. 多轮对话优化 **当前方案**: 保留最近3轮对话 **问题**: - ⚠️ 长对话可能丢失重要上下文 **改进方案**: - 智能上下文压缩(提取关键信息) - 长期记忆(存储重要信息到数据库) **建议**: Phase 4实施 **预计工作量**: 5-7天 --- ## 📊 债务优先级总览 | 债务项 | 优先级 | 影响 | 工作量 | 建议时间 | |-------|--------|------|--------|----------| | 意图识别升级 | P1 | 准确率 | 2-3天 | Phase 2 | | 上下文迁移Redis | P1 | 可用性 | 1天 | Phase 2 | | Dify结果缓存 | P1 | 性能 | 1天 | Phase 2 | | REDCap数据缓存 | P1 | 性能 | 1天 | Phase 2 | | 文档上传API | P2 | 功能 | 2-3天 | Phase 3 | | 用户绑定项目 | P2 | 功能 | 1-2天 | Phase 2后期 | | Function Calling | P2 | 智能化 | 3-5天 | Phase 3 | | 智能引用系统 | P2 | 体验 | 3-4天 | Phase 3 | | 批量查询优化 | P3 | 功能 | 2-3天 | Phase 4 | | 多轮对话优化 | P3 | 体验 | 5-7天 | Phase 4 | --- ## 🎯 Phase 2 债务清偿计划 ### Week 1-2: 性能优化 - [ ] 上下文迁移到Redis(1天) - [ ] Dify结果缓存(1天) - [ ] REDCap数据缓存(1天) - [ ] 性能测试与调优(1天) **预期效果**: - 响应时间从4.8秒降到2-3秒 - 支持分布式部署 - 服务重启不丢失上下文 ### Week 3-4: 意图识别升级 - [ ] 实现LLM意图判断(2天) - [ ] A/B测试对比(1天) - [ ] 上线灰度发布(1天) **预期效果**: - 意图识别准确率保持100% - 支持复杂自然语言表达 ### Week 5: 多项目支持 - [ ] 用户绑定默认项目(2天) **预期效果**: - 支持多个IIT项目并行 --- ## 📝 债务跟踪 ### 已清偿债务 | 债务项 | 清偿时间 | 方案 | |-------|---------|------| | AI幻觉问题 | 2026-01-03 | RAG数据注入 + 严格System Prompt | | 上下文丢失 | 2026-01-03 | SessionMemory(最近3轮) | | 响应速度慢 | 2026-01-04 | 优化意图识别 + 异步处理 | ### 进行中债务 | 债务项 | 负责人 | 预计完成 | |-------|--------|----------| | 无 | - | - | ### 待处理债务 见上文优先级列表 --- ## 🔗 相关文档 - [IIT Manager Agent 技术路径与架构设计](../02-技术设计/IIT Manager Agent 技术路径与架构设计.md) - [Phase1.5-AI对话能力开发计划](../04-开发计划/Phase1.5-AI对话能力开发计划.md) - [MVP开发任务清单](../04-开发计划/MVP开发任务清单.md) --- **文档维护**: 技术团队 **最后更新**: 2026-01-04 **版本历史**: - v1.0 (2026-01-04): 初始版本,Phase 1.5完成后整理