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>
341 lines
11 KiB
Markdown
341 lines
11 KiB
Markdown
# **IIT Manager Agent V2.2 落地实施指南:极简架构版 (融合 Moltbot)**
|
||
|
||
**文档版本:** V2.2 (Moltbot Enhanced)
|
||
|
||
**日期:** 2026-02-03
|
||
|
||
**适用对象:** 2人高效开发团队
|
||
|
||
**核心原则:** **Postgres-Only**, **No New Components**, **Service-First**, **Proactive & Personalized**
|
||
|
||
**变更说明:** 在 V2.1 基础上,借鉴 Moltbot (Clawbot) 的主动性与记忆机制,增加了用户偏好存储、每日早报 Skill 和自我修正回路。
|
||
|
||
## **1\. 核心架构:回归本质 (The Pragmatic Architecture)**
|
||
|
||
我们将“Brain-Hand-Tool”模型映射到现有的 Node.js \+ Postgres 技术栈上。
|
||
|
||
graph TD
|
||
subgraph "Layer 3: 数字化大脑 (The Brain)"
|
||
DB\[(Postgres DB)\]
|
||
DB \--\>|加载 Skills & Preferences| Engine\[QcEngineService\]
|
||
|
||
subgraph "混合双引擎"
|
||
Engine \--\>|1. 执行 JSON Logic| Logic\[Engine A (硬规则)\]
|
||
Engine \--\>|2. 组装 Prompt (含偏好)| LLM\[Engine B (软指令)\]
|
||
end
|
||
end
|
||
|
||
subgraph "Layer 2: 伪 MCP 接口层 (The Hand)"
|
||
LLM \--\>|3. 调用| Tools\[ToolsService (Class)\]
|
||
Logic \--\>|3. 调用| Tools
|
||
|
||
Tools \--\>|read\_data| Tool1\[RedcapAdapter\]
|
||
Tools \--\>|search\_doc| Tool2\[VectorSearchService\]
|
||
Tools \--\>|send\_msg| Tool3\[WechatService\]
|
||
end
|
||
|
||
subgraph "Layer 1: 基础设施 (The Tool)"
|
||
Tool1 \--\> REDCap
|
||
Tool2 \--\> pgvector
|
||
Tool3 \--\> WeCom
|
||
end
|
||
|
||
## **2\. 数据层设计:Skills 即数据 (Skills as Data)**
|
||
|
||
不再使用 OSS 存文件,直接使用 Postgres iit\_schema 存储结构化配置。**新增用户偏好表。**
|
||
|
||
### **2.1 数据库 Schema**
|
||
|
||
// schema.prisma
|
||
|
||
// 核心技能表
|
||
model IitSkill {
|
||
id String @id @default(uuid())
|
||
projectId String // 绑定项目 ID (如 PID=16)
|
||
formName String // 绑定表单 (如 demographics) 或 场景 (如 daily\_briefing)
|
||
|
||
// 核心配置 (JSON 类型)
|
||
// 包含 hard\_rules, soft\_instructions, schedule (cron表达式)
|
||
config Json
|
||
|
||
isActive Boolean @default(true)
|
||
version Int @default(1)
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@unique(\[projectId, formName\])
|
||
@@map("iit\_skills")
|
||
@@schema("iit\_schema")
|
||
}
|
||
|
||
// \[New\] 用户偏好表 (Moltbot 记忆机制)
|
||
model IitUserPreference {
|
||
id String @id @default(uuid())
|
||
userId String // 绑定企业微信 UserID
|
||
projectId String // 绑定项目
|
||
|
||
// 偏好配置 (JSON)
|
||
// 例如: { "report\_style": "concise", "notification\_time": "08:30" }
|
||
preferences Json
|
||
|
||
updatedAt DateTime @updatedAt
|
||
|
||
@@unique(\[userId, projectId\])
|
||
@@map("iit\_user\_preferences")
|
||
@@schema("iit\_schema")
|
||
}
|
||
|
||
### **2.2 JSON 配置范例 (Skill)**
|
||
|
||
**范例 1:质控 Skill**
|
||
|
||
{
|
||
"description": "人口学表单质控",
|
||
"hard\_rules": \[
|
||
{
|
||
"field": "age",
|
||
"logic": { "\>=": \[{ "var": "age" }, 18\] },
|
||
"message": "年龄必须 \>= 18 岁"
|
||
}
|
||
\],
|
||
"soft\_instructions": \[
|
||
{
|
||
"instruction": "检查备注字段。如果包含'无法签署知情同意',请标记违规。",
|
||
"tools": \["read\_clinical\_data"\]
|
||
}
|
||
\]
|
||
}
|
||
|
||
**范例 2:\[New\] 每日早报 Skill (Moltbot 主动性)**
|
||
|
||
{
|
||
"description": "每日项目进展早报",
|
||
"schedule": "0 30 8 \* \* \*", // 每天 08:30 触发 (pg-boss)
|
||
"soft\_instructions": \[
|
||
{
|
||
"instruction": "请统计昨天的入组人数、待处理质疑数。生成一段简报发给 PI。注意参考用户的 report\_style 偏好。",
|
||
"tools": \["get\_project\_stats", "send\_wechat\_msg"\]
|
||
}
|
||
\]
|
||
}
|
||
|
||
## **3\. 服务层设计:伪 MCP 实现 (Service-First)**
|
||
|
||
不要引入 @modelcontextprotocol/sdk。创建一个标准的 Service 类来管理工具。
|
||
|
||
### **3.1 ToolsService.ts 实现规范**
|
||
|
||
// backend/src/modules/iit-manager/services/ToolsService.ts
|
||
|
||
import { RedcapAdapter } from '../adapters/RedcapAdapter';
|
||
import { VectorSearchService } from '@/common/rag/vectorSearchService';
|
||
|
||
// 定义工具接口 (为了给 LLM 生成菜单)
|
||
export const TOOL\_DEFINITIONS \= \[
|
||
{
|
||
name: "read\_clinical\_data",
|
||
description: "读取REDCap临床数据...",
|
||
parameters: { ... }
|
||
},
|
||
{
|
||
name: "update\_user\_preference", // \[New\] 更新偏好工具
|
||
description: "更新用户的偏好设置,如报告风格、通知时间。",
|
||
parameters: {
|
||
type: "object",
|
||
properties: {
|
||
key: { type: "string", description: "偏好键名,如 report\_style" },
|
||
value: { type: "string", description: "偏好值,如 concise (简洁) 或 detailed (详细)" }
|
||
}
|
||
}
|
||
}
|
||
\];
|
||
|
||
export class ToolsService {
|
||
constructor(
|
||
private redcap: RedcapAdapter,
|
||
private rag: VectorSearchService,
|
||
private prisma: PrismaClient
|
||
) {}
|
||
|
||
// 统一执行入口 (LLM 只认识这个)
|
||
async executeTool(name: string, args: any) {
|
||
switch (name) {
|
||
case 'read\_clinical\_data':
|
||
return this.redcap.exportRecords(args);
|
||
|
||
case 'update\_user\_preference':
|
||
// \[New\] 实现记忆更新
|
||
return this.updatePreference(args);
|
||
|
||
case 'raise\_query':
|
||
return this.savePendingAction(args);
|
||
|
||
default:
|
||
throw new Error(\`未知工具: ${name}\`);
|
||
}
|
||
}
|
||
}
|
||
|
||
## **4\. 业务层设计:混合引擎调度 (含自我修正)**
|
||
|
||
### **4.1 执行逻辑 (The Pipeline)**
|
||
|
||
// backend/src/modules/iit-manager/services/QcEngineService.ts
|
||
|
||
export class QcEngineService {
|
||
|
||
async runQualityCheck(projectId: string, formName: string, data: any, userId?: string) {
|
||
// 1\. 加载 Skill 和 用户偏好
|
||
const skill \= await prisma.iitSkill.findUnique({...});
|
||
const userPref \= userId ? await prisma.iitUserPreference.findUnique({ where: { userId, projectId } }) : null;
|
||
|
||
if (\!skill) return;
|
||
|
||
// 2\. 运行 Engine A (硬规则)
|
||
const engineA \= new HardRuleEngine();
|
||
const hardErrors \= engineA.run(skill.config.hard\_rules, data);
|
||
|
||
if (hardErrors.length \> 0\) {
|
||
await this.saveShadowState(hardErrors);
|
||
return;
|
||
}
|
||
|
||
// 3\. 运行 Engine B (软指令) \- \[New\] 注入偏好 Context
|
||
const engineB \= new SoftRuleEngine(this.llm, this.toolsService);
|
||
|
||
// 将偏好注入 Prompt: "用户偏好简洁的报告,请不要废话。"
|
||
const context \= {
|
||
...data,
|
||
user\_preferences: userPref?.preferences
|
||
};
|
||
|
||
// \[New\] 开启自我修正回路 (Self-Correction Loop)
|
||
const softSuggestions \= await engineB.runWithRetry(skill.config.soft\_instructions, context, 3);
|
||
|
||
if (softSuggestions) {
|
||
await this.saveShadowState(softSuggestions);
|
||
}
|
||
}
|
||
}
|
||
|
||
### **4.2 自我修正机制 (Self-Correction Loop)**
|
||
|
||
借鉴 Moltbot,当工具调用失败时,不报错,而是让 LLM 重试。
|
||
|
||
// SoftRuleEngine.ts (伪代码)
|
||
|
||
async runWithRetry(instruction, context, maxRetries \= 3\) {
|
||
let history \= \[...\];
|
||
|
||
for (let i \= 0; i \< maxRetries; i++) {
|
||
const response \= await llm.chat(history);
|
||
|
||
if (response.hasToolCall) {
|
||
try {
|
||
const result \= await tools.executeTool(response.toolName, response.args);
|
||
history.push({ role: 'tool', content: result });
|
||
} catch (error) {
|
||
// \[New\] 捕获错误,喂回给 LLM
|
||
console.warn(\`Tool Error: ${error.message}\`);
|
||
history.push({
|
||
role: 'user',
|
||
content: \`工具调用失败: ${error.message}。请检查参数并重试。\`
|
||
});
|
||
continue; // 让 LLM 重新思考
|
||
}
|
||
} else {
|
||
return response.content;
|
||
}
|
||
}
|
||
}
|
||
|
||
## **5\. 实施路线图 (2人团队专属)**
|
||
|
||
### **✅ Week 1: 基础建设 (Engine A)**
|
||
|
||
1. 创建 iit\_skills 和 iit\_user\_preferences 表。
|
||
2. 引入 json-logic-js 库。
|
||
3. 实现 QcEngineService 的基础骨架,只跑硬规则。
|
||
|
||
### **🚧 Week 2: AI 接入与主动性 (Engine B)**
|
||
|
||
1. 创建 ToolsService,实现基础工具。
|
||
2. 实现 SoftRuleEngine 的 **自我修正回路**。
|
||
3. **里程碑**:配置 daily\_briefing Skill,利用 pg-boss 定时触发,早上 8:30 收到测试推送。
|
||
|
||
### **📋 Week 3: 界面与优化**
|
||
|
||
1. 开发 Admin 页面 (JSON Editor) 编辑 Skill。
|
||
2. 完善影子状态 (Shadow State) 审核界面。
|
||
|
||
## **6\. 多轮对话与开放式问答支持**
|
||
|
||
### **6.1 核心策略:Intent Routing \+ General Skill**
|
||
|
||
不要把所有逻辑都写死在质控里。我们增加一个特殊的 Skill:general\_qa。
|
||
|
||
#### **A. 配置 general\_qa Skill**
|
||
|
||
在数据库插入一条 formName \= 'general\_chat' 的记录:
|
||
|
||
{
|
||
"description": "通用问答与查询助手",
|
||
"soft\_instructions": \[
|
||
{
|
||
"instruction": "你是本项目的智能助手。你可以回答关于项目进度、患者数据、方案细节的问题。请根据用户意图调用工具。",
|
||
"tools": \["read\_clinical\_data", "search\_protocol", "get\_project\_stats", "update\_user\_preference"\]
|
||
}
|
||
\]
|
||
}
|
||
|
||
### **6.2 代码实现:聊天入口 (ChatService.ts)**
|
||
|
||
// backend/src/modules/iit-manager/services/ChatService.ts
|
||
|
||
export class ChatService {
|
||
constructor(
|
||
private qcEngine: QcEngineService,
|
||
private sessionMemory: SessionMemory
|
||
) {}
|
||
|
||
async handleUserMessage(userId: string, projectId: string, message: string) {
|
||
// 1\. 获取历史对话 & 用户偏好
|
||
const history \= await this.sessionMemory.get(userId);
|
||
const userPref \= await prisma.iitUserPreference.findUnique({...});
|
||
|
||
// 2\. 加载通用 Skill
|
||
const generalSkill \= await prisma.iitSkill.findUnique({
|
||
where: { projectId, formName: 'general\_chat' }
|
||
});
|
||
|
||
// 3\. 构造 Prompt (包含 History \+ Skill \+ Preferences)
|
||
const prompt \= \`
|
||
${generalSkill.config.soft\_instructions\[0\].instruction}
|
||
|
||
\[User Preferences\]: ${JSON.stringify(userPref?.preferences || {})}
|
||
|
||
历史对话:
|
||
${history.map(h \=\> \`${h.role}: ${h.content}\`).join('\\n')}
|
||
|
||
用户当前问题: ${message}
|
||
\`;
|
||
|
||
// 4\. 调用 LLM (Engine B 逻辑复用,含自我修正)
|
||
const response \= await this.qcEngine.runSoftAgent(prompt, generalSkill.config);
|
||
|
||
// 5\. 更新记忆
|
||
await this.sessionMemory.add(userId, { role: 'user', content: message });
|
||
await this.sessionMemory.add(userId, { role: 'assistant', content: response });
|
||
|
||
return response;
|
||
}
|
||
}
|
||
|
||
## **7\. Moltbot 理念借鉴总结**
|
||
|
||
| 借鉴点 | IIT Manager 落地实现 | 价值 |
|
||
| :---- | :---- | :---- |
|
||
| **主动性 (Proactivity)** | **每日早报 Skill**:利用 pg-boss 定时触发 daily\_briefing Skill,主动推送企微消息。 | 让用户感觉系统是活的,而不是被动的数据库。 |
|
||
| **记忆 (Memory)** | **用户偏好表**:存储 report\_style, notification\_time 等,Prompt 动态注入。 | 提供千人千面的个性化体验。 |
|
||
| **自我修正 (Self-Correction)** | **重试回路**:Engine B 在工具报错时,将错误信息回传给 LLM,允许其修正参数重试。 | 极大提升系统鲁棒性,减少人工运维。 |
|
||
|
||
**结论:这就是 IIT Manager Agent 的最终形态。既有医疗的严谨(硬规则),又有个性化的温度(偏好记忆),还有极简的架构(Postgres-Only)。开干吧!** |