# **研究方案制定 Agent 技术实现手册 V3.0** 版本: v3.0 关联文档: Protocol\_Agent\_Architecture\_Design\_V3.md 核心内容: 数据库 Schema、核心服务代码、API 协议。 ## **1\. 数据库设计 (Prisma Schema)** ### **1.1 记忆层 (Memory Layer)** 存储“活的”方案数据,实现长程记忆。 // aia\_schema.prisma model ProtocolContext { id String @id @default(uuid()) conversationId String @unique @map("conversation\_id") userId String @map("user\_id") // 状态机 currentStage String @default("SCIENTIFIC\_QUESTION") status String @default("IN\_PROGRESS") // 活的方案数据 (JSONB) // 包含: scientific\_question, pico, study\_design, outcomes, sample\_size 等 data Json @default("{}") // V3 新增: 存储上一次的反思结果,避免重复报错 lastReflexion Json? @map("last\_reflexion") createdAt DateTime @default(now()) @map("created\_at") updatedAt DateTime @updatedAt @map("updated\_at") @@table("protocol\_contexts") @@schema("aia\_schema") } ### **1.2 配置层 (Configuration Layer)** 这是 V3 的核心,支持后端配置 CoT。 // capability\_schema.prisma model PromptTemplate { id String @id @default(uuid()) code String @unique // e.g., AIA\_SAMPLE\_SIZE version Int @default(1) // 基础人设 content String @db.Text // V3 新增: 思维链配置 (JSONB) // 存储 ChainStep\[\] 数组 chainConfig Json? @map("chain\_config") // V3 新增: 路由规则配置 (JSONB, 可选) // 用于定义何时切出该阶段 routerConfig Json? @map("router\_config") isActive Boolean @default(true) updatedAt DateTime @updatedAt @@table("prompt\_templates") @@schema("capability\_schema") } model AgentTrace { id String @id @default(uuid()) conversationId String @map("conversation\_id") stage String // 记录完整上下文 inputPayload Json @map("input\_payload") outputPayload Json @map("output\_payload") // 耗时与消耗 latencyMs Int @map("latency\_ms") tokens Int @default(0) createdAt DateTime @default(now()) @@table("agent\_traces") @@schema("capability\_schema") } ## **2\. 核心服务代码 (Orchestrator Engine)** ### **2.1 动态 CoT 组装器 (promptBuilder.ts)** 负责将 DB 中的 SOP 配置编译成 System Prompt。 import { prisma } from '@/common/db'; interface ChainStep { key: string; desc: string; instruction: string; } export async function buildDynamicSystemPrompt(stage: string, contextData: any) { // 1\. 加载配置 const template \= await prisma.promptTemplate.findUnique({ where: { code: stage } }); if (\!template) throw new Error(\`Prompt not found: ${stage}\`); const chainSteps \= template.chainConfig as ChainStep\[\] || \[\]; // 2\. 组装基础 Prompt (Persona) let systemPrompt \= \`${template.content}\\n\\n\`; // 3\. 注入当前上下文 (Memory) systemPrompt \+= \`=== 当前方案状态 (Context) \===\\n${JSON.stringify(contextData, null, 2)}\\n\\n\`; // 4\. 注入思维链 SOP (V3 核心) if (chainSteps.length \> 0\) { systemPrompt \+= \`=== 思考步骤 (SOP) \===\\n\`; systemPrompt \+= \`请严格按照以下步骤进行思考,并使用 XML 标签包裹每一步的内容:\\n\`; chainSteps.forEach((step, idx) \=\> { systemPrompt \+= \`${idx \+ 1}. \<${step.key}\>: ${step.instruction}\\n\`; }); systemPrompt \+= \`最后,在 \ 标签中输出给用户的回复。\\n\`; } return systemPrompt; } ### **2.2 编排器主逻辑 (ProtocolOrchestrator.ts)** 协调 Brain, Memory, Knowledge 和 Hands。 export class ProtocolOrchestrator { async handleMessage(userId: string, conversationId: string, content: string) { // 1\. 获取上下文 (Memory) let ctx \= await prisma.protocolContext.findUnique({ where: { conversationId } }); // 2\. \[Reflexion Guard\] 检查数据变更 // 如果之前状态是 WAITING\_USER 且数据变了,说明工具执行回来了 (Hands 回调) if (ctx.status \=== 'WAITING\_USER\_ACTION' && await this.checkDataChanged(ctx)) { const validation \= await this.runReflexionCheck(ctx); if (\!validation.pass) { return this.streamResponse(\`⚠️ \*\*校验未通过\*\*: ${validation.reason}\`); } // 校验通过,重置状态 await this.updateStatus(ctx.id, 'IN\_PROGRESS'); } // 3\. \[Knowledge RAG\] 混合检索 (自建 EKB) // 仅在需要知识的阶段调用 const ragContext \= await knowledgeService.search(content, ctx.currentStage); // 4\. \[Prompt Build\] 动态组装 (Brain) const systemPrompt \= await buildDynamicSystemPrompt(ctx.currentStage, ctx.data); // 5\. \[Execution\] 流式生成 const traceId \= await traceService.startTrace(conversationId, 'GENERATE'); return streamingService.streamGenerate({ systemPrompt, userMessage: content \+ (ragContext ? \`\\n\\n参考资料:\\n${ragContext}\` : ''), onFinish: async (output) \=\> { await traceService.endTrace(traceId, output); // 异步触发:结构化提取任务 (更新 Memory) await pgBoss.send('extract-protocol-data', { conversationId, text: output }); } }); } } ## **3\. 交互协议 (Deep Link Protocol)** ### **3.1 Action Card Payload (Backend \-\> Frontend)** Orchestrator 决定需要用户操作时,发送此 JSON。 { "type": "action\_card", "data": { "title": "建议:样本量计算", "tool\_code": "SAMPLE\_SIZE\_CALC", "path": "/tools/st/sample-size", "params": { "ctx\_id": "uuid-1234", // 关键:传递上下文ID,让工具知道往哪里回写 "alpha": 0.05, "power": 0.8 } } } ### **3.2 同步回写 API (Tool \-\> Backend)** 工具端(如样本量计算器)计算完成后,调用此接口回写结果。 **POST** /api/v1/aia/protocol/:ctxId/sync { "stage": "SAMPLE\_SIZE", "data": { "n\_total": 386, "method": "t-test", "params": { "alpha": 0.05, "power": 0.8 } } } ## **4\. 提取与反思 (Extraction & Reflexion)** ### **4.1 异步提取 Worker** 负责从非结构化对话中“提纯”信息存入 Memory。 // workers/extractionWorker.ts export async function extractProtocolData(job) { const { conversationId, text } \= job.data; // 调用廉价模型 (DeepSeek-Flash) 进行 JSON 提取 const extracted \= await llm.extractJson(text, EXTRACT\_PROMPT); if (extracted) { // 智能合并策略 (Deep Merge) await prisma.protocolContext.update({ where: { conversationId }, data: { data: deepMerge(currentData, extracted) } }); } } ### **4.2 反思校验规则 (Reflexion Rules)** **Brain** 对 **Hands** 操作结果的质检逻辑。 function runReflexionCheck(ctx: ProtocolContext) { const { sample\_size } \= ctx.data; if (\!sample\_size) return { pass: true }; // 规则 1: 伦理红线 if (sample\_size.n\_total \< 10\) return { pass: false, reason: "样本量过小 (\<10),无法通过伦理审查" }; // 规则 2: 可行性预警 if (sample\_size.n\_total \> 10000\) return { pass: false, reason: "样本量过大,请确认经费和周期是否支持" }; return { pass: true }; }