Files
AIclinicalresearch/docs/03-业务模块/IIT Manager Agent/07-技术债务/IIT Manager Agent 技术债务清单.md
HaHafeng b31255031e feat(iit-manager): Add WeChat Official Account integration for patient notifications
Features:
- PatientWechatCallbackController for URL verification and message handling
- PatientWechatService for template and customer messages
- Support for secure mode (message encryption/decryption)
- Simplified route /wechat/patient/callback for WeChat config
- Event handlers for subscribe/unsubscribe/text messages
- Template message for visit reminders

Technical details:
- Reuse @wecom/crypto for encryption (compatible with Official Account)
- Relaxed Fastify schema validation to prevent early request blocking
- Access token caching (7000s with 5min pre-refresh)
- Comprehensive logging for debugging

Testing: Local URL verification passed, ready for SAE deployment

Status: Code complete, waiting for WeChat platform configuration
2026-01-04 22:53:42 +08:00

673 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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: 先使用方案ALLM判断快速验证效果
- Phase 3: 如果量大再切换到方案BBERT模型
**预计工作量**: 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<void> {
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. 存回Redis30分钟过期
await this.redis.setex(key, this.EXPIRE_TIME, JSON.stringify(session));
}
async getContext(userId: string): Promise<string> {
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<string> {
// 1. 生成缓存keyquery的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<any> {
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<string> {
// 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: 性能优化
- [ ] 上下文迁移到Redis1天
- [ ] 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完成后整理