Features: - Add V2.9 enhancements: Cron Skill, User Profiling, Feedback Loop, Multi-Intent Handling - Create modular development plan documents (database, engines, services, memory, tasks) - Add V2.5/V2.6/V2.8/V2.9 design documents for architecture evolution - Add system design white papers and implementation guides Architecture: - Dual-Brain Architecture (SOP + ReAct engines) - Three-layer memory system (Flow Log, Hot Memory, History Book) - ProfilerService for personalized responses - SchedulerService with Cron Skill support Also includes: - Frontend nginx config updates - Backend test scripts for WeChat signature - Database backup files Co-authored-by: Cursor <cursoragent@cursor.com>
143 lines
6.2 KiB
Markdown
143 lines
6.2 KiB
Markdown
# **IIT Manager Agent V2.8:记忆检索与路由逻辑详解**
|
||
|
||
**核心机制:** 意图驱动的按需检索 (Intent-Driven Retrieval)
|
||
|
||
**目的:** 既保证 AI 懂当下(Hot),又保证 AI 懂历史(History),同时节省 Token。
|
||
|
||
## **1\. 记忆存储全景图 (Storage Map)**
|
||
|
||
在 V2.8 中,我们有三个核心存储位置,各司其职:
|
||
|
||
| 记忆类型 | 存储表 | 字段 | 内容特征 | 更新频率 |
|
||
| :---- | :---- | :---- | :---- | :---- |
|
||
| **1\. 流水账 (Raw Stream)** | iit\_conversation\_history | content (JSON) | 未经加工的原始对话。 | **实时** (每秒) |
|
||
| **2\. 热记忆 (Hot Context)** | iit\_project\_memory | config (Markdown) | 用户偏好、当前状态、系统禁令。 | **每日** (AI 提炼) |
|
||
| **3\. 历史书 (Weekly Reports)** | iit\_weekly\_reports | summary (Text) | 高度浓缩的周报、关键决策、踩坑记录。 | **每周** (AI 归档) |
|
||
|
||
## **2\. 调取顺序与逻辑 (Retrieval Logic)**
|
||
|
||
当 PI 发问时,系统并不是一股脑把所有记忆都塞进去,而是分三步走:
|
||
|
||
### **第一步:无条件注入 (Always On)**
|
||
|
||
**无论 PI 问什么,必须先注入“热记忆”。**
|
||
|
||
* **来源**:iit\_project\_memory
|
||
* **内容**:用户偏好(如“PI 喜欢简报”)、当前项目状态。
|
||
* **理由**:这是 Agent 的“人设”和“底线”,一刻也不能忘。
|
||
|
||
### **第二步:意图识别 (Intent Detection)**
|
||
|
||
系统分析 PI 的问题,判断他想问“现在”还是“过去”。
|
||
|
||
* **情况 A:问现在/执行任务** (如 "查下 P001", "生成本周周报")
|
||
* **动作**:**不调取** 历史书。
|
||
* **理由**:解决当下问题不需要翻阅 3 年前的老黄历,避免干扰 AI。
|
||
* **Context** \= Hot Memory \+ Current Task Data
|
||
* **情况 B:问历史/趋势/回顾** (如 "回顾下去年的入组情况", "我们为什么暂停了筛选?")
|
||
* **动作**:**全量调取** 历史书 (iit\_weekly\_reports)。
|
||
* **理由**:需要上帝视角。
|
||
* **Context** \= Hot Memory \+ All Weekly Reports
|
||
|
||
### **第三步:上下文组装 (Prompt Assembly)**
|
||
|
||
最终发给 LLM 的 Prompt 是这样组装的:
|
||
|
||
\[System Prompt\]
|
||
你是一个临床研究助手...
|
||
|
||
\[Hot Memory\] (来自 iit\_project\_memory)
|
||
\- 用户偏好: 简洁、数据驱动
|
||
\- 当前状态: 入组阶段
|
||
|
||
\[History Context\] (仅在情况 B 下注入)
|
||
Week 1: 启动项目...
|
||
Week 2: 发现 P001 不良事件...
|
||
...
|
||
Week 50: 决定放宽标准...
|
||
|
||
\[User Question\]
|
||
我们之前为什么暂停筛选?
|
||
|
||
## **3\. 实战场景演示 (Scenario Walkthrough)**
|
||
|
||
### **场景 1:PI 问 "P001 入组了吗?"**
|
||
|
||
1. **加载 Hot Memory**:获取偏好(简洁回复)。
|
||
2. **意图识别**:QUERY\_DATA (查数据)。
|
||
3. **决策**:**不需要** 查历史书。
|
||
4. **行动**:调用 read\_clinical\_data 工具去 REDCap 查实时数据。
|
||
5. **回答**:"已入组,时间是 2026-02-05。"
|
||
|
||
### **场景 2:PI 问 "最近入组太慢了,我们之前有没有讨论过怎么解决?"**
|
||
|
||
1. **加载 Hot Memory**:获取偏好。
|
||
2. **意图识别**:QUERY\_HISTORY (查历史决策)。
|
||
3. **决策**:**需要** 查历史书。
|
||
4. **行动**:
|
||
* 从 iit\_weekly\_reports 拉取过去 20 周的 summary。
|
||
* 拼接成 3000 字的文本。
|
||
* 喂给 LLM。
|
||
5. **LLM 思考**:阅读周报,发现 Week 12 记录了“增加受试者交通补贴”的决策,Week 15 记录了“在门诊增派 CRC”的决策。
|
||
6. **回答**:"我们曾在第 12 周尝试增加补贴,第 15 周增派了 CRC,当时效果有短暂提升..."
|
||
|
||
### **场景 3:PI 问 "我上次跟你说的那个只要看结果的规矩,你记得吗?"**
|
||
|
||
1. **加载 Hot Memory**:获取偏好。
|
||
2. **AI 自检**:在 Hot Memory 里看到了 \- \[PI\]: 只要看结果 这条记录。
|
||
3. **回答**:"记得的,教授。您要求汇报时只列数据结论,不要冗长的过程描述。我会严格遵守。"
|
||
* *注意:这个问题不需要查周报,也不需要查流水账,直接看 Hot Memory 就行。*
|
||
|
||
## **4\. 总结:给开发者的伪代码**
|
||
|
||
// ChatService.ts
|
||
|
||
async handleMessage(userId, message) {
|
||
// 1\. 总是加载热记忆 (Hot)
|
||
const hotMem \= await prisma.iitProjectMemory.findUnique(...);
|
||
|
||
// 2\. 意图识别
|
||
const intent \= await this.intentService.detect(message);
|
||
|
||
let historyContext \= "";
|
||
|
||
// 3\. 按需加载历史书 (History)
|
||
if (intent.type \=== 'QUERY\_HISTORY' || intent.type \=== 'ANALYZE\_TREND') {
|
||
const reports \= await prisma.iitWeeklyReport.findMany({
|
||
orderBy: { weekNumber: 'asc' }
|
||
});
|
||
historyContext \= reports.map(r \=\> \`\[W${r.weekNumber}\]: ${r.summary}\`).join('\\n');
|
||
}
|
||
|
||
// 4\. 组装最终 Prompt
|
||
const finalPrompt \= \`
|
||
${hotMem.content}
|
||
${historyContext}
|
||
User: ${message}
|
||
\`;
|
||
|
||
// 5\. 调用 LLM
|
||
return await this.llm.chat(finalPrompt);
|
||
}
|
||
|
||
**记住这个口诀:**
|
||
|
||
**“偏好时刻带,历史按需查,流水账只用来生成周报。”**
|
||
|
||
## **5\. 复杂度控制与防失控指南 (Safety Guardrails)**
|
||
|
||
为了防止系统变得“复杂不可控”,请严格遵守以下开发军规:
|
||
|
||
### **5.1 容量限制 (The Cap)**
|
||
|
||
* **Hot Memory**: 限制在 **2000 Tokens** 以内。如果超标,触发 MemoryPruningJob (记忆修剪任务),让 AI 自动总结或通知管理员手动删除。
|
||
* **History Book**: 每次加载不超过 **50 周** 的周报。如果项目运行了 10 年,只加载最近 1 年的周报,或者先让 AI 生成“年度总结”。
|
||
|
||
### **5.2 隔离原则 (Isolation)**
|
||
|
||
* **任务隔离**:执行 QC\_TASK (质控) 时,**严禁**加载 History Context。质控必须基于当下的事实,不能受历史干扰。
|
||
* **数据隔离**:LLM 永远没有权限直接读取 iit\_conversation\_history 表。这条物理隔绝保证了 Agent 永远不会被海量噪音淹没。
|
||
|
||
### **5.3 人工介入 (The Kill Switch)**
|
||
|
||
* **可读可改**:后台必须提供 Hot Memory 的编辑器。如果 Agent 记住了错误的规则(例如“不需要查年龄”),医生可以直接进去删掉那一行 Markdown。**这是系统失控时的“急停按钮”。** |