Files
AIclinicalresearch/docs/03-业务模块/AIA-AI智能问答/02-技术设计/Protocol_Agent_Technical_Implementation_V3.md
HaHafeng 96290d2f76 feat(aia): Implement Protocol Agent MVP with reusable Agent framework
Sprint 1-3 Completed (Backend + Frontend):

Backend (Sprint 1-2):
- Implement 5-layer Agent framework (Query->Planner->Executor->Tools->Reflection)
- Create agent_schema with 6 tables (agent_definitions, stages, prompts, sessions, traces, reflexion_rules)
- Create protocol_schema with 2 tables (protocol_contexts, protocol_generations)
- Implement Protocol Agent core services (Orchestrator, ContextService, PromptBuilder)
- Integrate LLM service adapter (DeepSeek/Qwen/GPT-5/Claude)
- 6 API endpoints with full authentication
- 10/10 API tests passed

Frontend (Sprint 3):
- Add Protocol Agent entry in AgentHub (indigo theme card)
- Implement ProtocolAgentPage with 3-column layout
- Collapsible sidebar (Gemini style, 48px <-> 280px)
- StatePanel with 5 stage cards (scientific_question, pico, study_design, sample_size, endpoints)
- ChatArea with sync button and action cards integration
- 100% prototype design restoration (608 lines CSS)
- Detailed endpoints structure: baseline, exposure, outcomes, confounders

Features:
- 5-stage dialogue flow for research protocol design
- Conversation-driven interaction with sync-to-protocol button
- Real-time context state management
- One-click protocol generation button (UI ready, backend pending)

Database:
- agent_schema: 6 tables for reusable Agent framework
- protocol_schema: 2 tables for Protocol Agent
- Seed data: 1 agent + 5 stages + 9 prompts + 4 reflexion rules

Code Stats:
- Backend: 13 files, 4338 lines
- Frontend: 14 files, 2071 lines
- Total: 27 files, 6409 lines

Status: MVP core functionality completed, pending frontend-backend integration testing

Next: Sprint 4 - One-click protocol generation + Word export
2026-01-24 17:29:24 +08:00

7.6 KiB
Raw Permalink Blame History

研究方案制定 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 += `最后,在 <response> 标签中输出给用户的回复。\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.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)

BrainHands 操作结果的质检逻辑。

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 };
}