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
847 lines
26 KiB
Markdown
847 lines
26 KiB
Markdown
# Protocol Agent 数据库设计
|
||
|
||
> 版本:v1.0
|
||
> 创建日期:2026-01-24
|
||
|
||
---
|
||
|
||
## 一、Schema规划
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ 数据库Schema架构 │
|
||
├─────────────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ agent_schema (通用Agent框架 - 可复用) │
|
||
│ ├── agent_configs Agent配置表 │
|
||
│ ├── agent_stages 阶段配置表 │
|
||
│ ├── agent_tools 工具注册表 │
|
||
│ ├── action_cards Action Card配置表 │
|
||
│ ├── reflexion_rules 反思规则表 │
|
||
│ ├── agent_sessions Agent会话表 │
|
||
│ └── agent_traces 追踪日志表 │
|
||
│ │
|
||
│ protocol_schema (研究方案Agent专用) │
|
||
│ ├── protocol_contexts 研究方案上下文表 │
|
||
│ ├── protocol_versions 版本历史表 │
|
||
│ └── protocol_exports 导出记录表 │
|
||
│ │
|
||
│ knowledge_schema (知识库 - Phase 2) │
|
||
│ ├── knowledge_docs 知识文档表 │
|
||
│ ├── knowledge_chunks 知识块表 │
|
||
│ └── knowledge_embeddings 向量嵌入表 │
|
||
│ │
|
||
│ aia_schema (已有 - 复用) │
|
||
│ ├── conversations 对话表 │
|
||
│ └── messages 消息表 │
|
||
│ │
|
||
│ capability_schema (已有 - 复用) │
|
||
│ └── prompt_templates Prompt模板表 │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 二、agent_schema - 通用Agent框架表
|
||
|
||
### 2.1 agent_configs (Agent配置表)
|
||
|
||
```prisma
|
||
/// Agent配置表 - 定义每个Agent的基础信息
|
||
model AgentConfig {
|
||
id String @id @default(uuid())
|
||
agentId String @unique @map("agent_id")
|
||
agentName String @map("agent_name")
|
||
agentDescription String? @map("agent_description")
|
||
baseSystemPrompt String @map("base_system_prompt") @db.Text
|
||
|
||
// 全局配置
|
||
toneOfVoice String? @map("tone_of_voice")
|
||
globalKnowledge String[] @map("global_knowledge")
|
||
memoryStrategy String @default("full") @map("memory_strategy")
|
||
maxHistoryTurns Int @default(20) @map("max_history_turns")
|
||
|
||
// LLM配置
|
||
defaultModel String @default("deepseek-v3") @map("default_model")
|
||
temperature Float @default(0.7)
|
||
maxTokens Int @default(4096) @map("max_tokens")
|
||
|
||
// 状态
|
||
isActive Boolean @default(true) @map("is_active")
|
||
version Int @default(1)
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
// 关联
|
||
stages AgentStage[] @relation("AgentConfigStages")
|
||
tools AgentTool[] @relation("AgentConfigTools")
|
||
reflexionRules ReflexionRule[] @relation("AgentConfigReflexion")
|
||
|
||
@@index([agentId, isActive])
|
||
@@map("agent_configs")
|
||
@@schema("agent_schema")
|
||
}
|
||
```
|
||
|
||
**字段说明**:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| agentId | string | Agent唯一标识,如 `protocol_agent` |
|
||
| baseSystemPrompt | text | 基础系统Prompt |
|
||
| toneOfVoice | string | 语气风格,如"专业但亲和" |
|
||
| memoryStrategy | string | 记忆策略:full/sliding_window/summary |
|
||
| maxHistoryTurns | int | 最大保留对话轮数 |
|
||
|
||
### 2.2 agent_stages (阶段配置表)
|
||
|
||
```prisma
|
||
/// 阶段配置表 - 定义Agent的各个阶段
|
||
model AgentStage {
|
||
id String @id @default(uuid())
|
||
agentConfigId String @map("agent_config_id")
|
||
|
||
stageId String @map("stage_id")
|
||
stageName String @map("stage_name")
|
||
stageOrder Int @map("stage_order")
|
||
|
||
// Prompt配置
|
||
instruction String @db.Text
|
||
extractionSchema Json @map("extraction_schema")
|
||
completionCriteria String? @map("completion_criteria") @db.Text
|
||
|
||
// 流转配置
|
||
nextStageId String? @map("next_stage_id")
|
||
transitionMode String @default("user_confirm") @map("transition_mode")
|
||
transitionCondition Json? @map("transition_condition")
|
||
|
||
// 工具配置
|
||
availableToolIds String[] @map("available_tool_ids")
|
||
|
||
isActive Boolean @default(true) @map("is_active")
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
agentConfig AgentConfig @relation("AgentConfigStages", fields: [agentConfigId], references: [id], onDelete: Cascade)
|
||
actionCards ActionCard[] @relation("StageActionCards")
|
||
|
||
@@unique([agentConfigId, stageId])
|
||
@@index([agentConfigId, stageOrder])
|
||
@@map("agent_stages")
|
||
@@schema("agent_schema")
|
||
}
|
||
```
|
||
|
||
**extractionSchema 示例** (PICO阶段):
|
||
|
||
```json
|
||
{
|
||
"type": "object",
|
||
"properties": {
|
||
"P": {
|
||
"type": "object",
|
||
"properties": {
|
||
"value": { "type": "string", "description": "研究人群" },
|
||
"details": { "type": "string" },
|
||
"confidence": { "type": "number" }
|
||
}
|
||
},
|
||
"I": { ... },
|
||
"C": { ... },
|
||
"O": { ... }
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.3 agent_tools (工具注册表)
|
||
|
||
```prisma
|
||
/// 工具注册表 - 定义Agent可用的工具
|
||
model AgentTool {
|
||
id String @id @default(uuid())
|
||
agentConfigId String? @map("agent_config_id")
|
||
|
||
toolId String @unique @map("tool_id")
|
||
toolName String @map("tool_name")
|
||
toolDescription String @map("tool_description") @db.Text
|
||
toolType String @map("tool_type")
|
||
|
||
// Function定义
|
||
functionSchema Json? @map("function_schema")
|
||
|
||
// 执行配置
|
||
handlerType String @map("handler_type")
|
||
handlerConfig Json @map("handler_config")
|
||
|
||
// 权限和限制
|
||
requiresAuth Boolean @default(false) @map("requires_auth")
|
||
rateLimit Int? @map("rate_limit")
|
||
timeout Int @default(30000)
|
||
|
||
isActive Boolean @default(true) @map("is_active")
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
agentConfig AgentConfig? @relation("AgentConfigTools", fields: [agentConfigId], references: [id], onDelete: Cascade)
|
||
|
||
@@index([agentConfigId, isActive])
|
||
@@index([toolType])
|
||
@@map("agent_tools")
|
||
@@schema("agent_schema")
|
||
}
|
||
```
|
||
|
||
**toolType 枚举值**:
|
||
- `internal`: 内部计算工具
|
||
- `external`: 外部API工具
|
||
- `deep_link`: 深度链接跳转
|
||
- `rag`: RAG知识检索
|
||
|
||
### 2.4 action_cards (Action Card配置表)
|
||
|
||
```prisma
|
||
/// Action Card配置表
|
||
model ActionCard {
|
||
id String @id @default(uuid())
|
||
stageId String @map("stage_id")
|
||
|
||
cardId String @map("card_id")
|
||
title String
|
||
description String? @db.Text
|
||
iconType String? @map("icon_type")
|
||
|
||
// 触发配置
|
||
triggerType String @map("trigger_type")
|
||
triggerCondition Json? @map("trigger_condition")
|
||
|
||
// Action配置
|
||
actionType String @map("action_type")
|
||
actionPayload Json @map("action_payload")
|
||
|
||
// 回调配置
|
||
onCompleteAction String? @map("on_complete_action")
|
||
resultMapping Json? @map("result_mapping")
|
||
|
||
displayOrder Int @default(0) @map("display_order")
|
||
isActive Boolean @default(true) @map("is_active")
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
stage AgentStage @relation("StageActionCards", fields: [stageId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([stageId, cardId])
|
||
@@map("action_cards")
|
||
@@schema("agent_schema")
|
||
}
|
||
```
|
||
|
||
**actionPayload 示例** (Deep Link):
|
||
|
||
```json
|
||
{
|
||
"targetAgent": "sample_calculator",
|
||
"targetPath": "/aia/sample-calculator",
|
||
"params": {
|
||
"studyType": "{{studyDesign.type}}",
|
||
"primaryEndpoint": "{{endpoints.primary[0].name}}"
|
||
},
|
||
"openMode": "modal"
|
||
}
|
||
```
|
||
|
||
### 2.5 reflexion_rules (反思规则表)
|
||
|
||
```prisma
|
||
/// Reflexion规则表
|
||
model ReflexionRule {
|
||
id String @id @default(uuid())
|
||
agentConfigId String @map("agent_config_id")
|
||
|
||
ruleId String @map("rule_id")
|
||
ruleName String @map("rule_name")
|
||
ruleDescription String? @map("rule_description") @db.Text
|
||
|
||
// 触发配置
|
||
triggerStageId String? @map("trigger_stage_id")
|
||
triggerTiming String @map("trigger_timing")
|
||
|
||
// 规则内容
|
||
ruleType String @map("rule_type")
|
||
promptTemplate String? @map("prompt_template") @db.Text
|
||
ruleLogic Json? @map("rule_logic")
|
||
|
||
// 失败处理
|
||
severity String @default("warning")
|
||
failureAction String @map("failure_action")
|
||
|
||
isActive Boolean @default(true) @map("is_active")
|
||
priority Int @default(0)
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
agentConfig AgentConfig @relation("AgentConfigReflexion", fields: [agentConfigId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([agentConfigId, ruleId])
|
||
@@index([triggerStageId, triggerTiming])
|
||
@@map("reflexion_rules")
|
||
@@schema("agent_schema")
|
||
}
|
||
```
|
||
|
||
### 2.6 agent_sessions (Agent会话表)
|
||
|
||
```prisma
|
||
/// Agent会话表 - 扩展conversation的Agent状态
|
||
model AgentSession {
|
||
id String @id @default(uuid())
|
||
conversationId String @unique @map("conversation_id")
|
||
agentId String @map("agent_id")
|
||
userId String @map("user_id")
|
||
|
||
// 状态管理
|
||
currentStageId String @map("current_stage_id")
|
||
stageStatus String @default("in_progress") @map("stage_status")
|
||
|
||
// 元数据
|
||
sessionMetadata Json? @map("session_metadata")
|
||
|
||
// 生命周期
|
||
startedAt DateTime @default(now()) @map("started_at")
|
||
lastActiveAt DateTime @default(now()) @map("last_active_at")
|
||
completedAt DateTime? @map("completed_at")
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
@@index([agentId, userId])
|
||
@@index([currentStageId])
|
||
@@index([lastActiveAt])
|
||
@@map("agent_sessions")
|
||
@@schema("agent_schema")
|
||
}
|
||
```
|
||
|
||
### 2.7 agent_traces (追踪日志表)
|
||
|
||
```prisma
|
||
/// Agent追踪日志表 - 可观测性
|
||
model AgentTrace {
|
||
id String @id @default(uuid())
|
||
conversationId String @map("conversation_id")
|
||
messageId String? @map("message_id")
|
||
traceId String @map("trace_id")
|
||
|
||
// 步骤信息
|
||
stepType String @map("step_type")
|
||
stepOrder Int @map("step_order")
|
||
|
||
// 输入输出
|
||
stepInput Json? @map("step_input")
|
||
stepOutput Json? @map("step_output")
|
||
|
||
// LLM信息
|
||
llmModel String? @map("llm_model")
|
||
llmPromptTokens Int? @map("llm_prompt_tokens")
|
||
llmCompletionTokens Int? @map("llm_completion_tokens")
|
||
|
||
// 性能
|
||
durationMs Int? @map("duration_ms")
|
||
|
||
// 状态
|
||
status String @default("success")
|
||
errorMessage String? @map("error_message") @db.Text
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
|
||
@@index([conversationId, traceId])
|
||
@@index([traceId, stepOrder])
|
||
@@index([createdAt])
|
||
@@index([stepType, status])
|
||
@@map("agent_traces")
|
||
@@schema("agent_schema")
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 三、protocol_schema - 研究方案专用表
|
||
|
||
### 3.1 protocol_contexts (研究方案上下文表)
|
||
|
||
```prisma
|
||
/// Protocol上下文表 - 研究方案的结构化数据存储
|
||
model ProtocolContext {
|
||
id String @id @default(uuid())
|
||
sessionId String @unique @map("session_id")
|
||
conversationId String @unique @map("conversation_id")
|
||
userId String @map("user_id")
|
||
|
||
// ===== Phase 1 核心字段 =====
|
||
|
||
/// 阶段1:科学问题
|
||
scientificQuestion Json? @map("scientific_question") @db.JsonB
|
||
|
||
/// 阶段2:PICO
|
||
pico Json? @db.JsonB
|
||
|
||
/// 阶段3:研究设计
|
||
studyDesign Json? @map("study_design") @db.JsonB
|
||
|
||
/// 阶段4:样本量
|
||
sampleSize Json? @map("sample_size") @db.JsonB
|
||
|
||
/// 阶段5:终点指标
|
||
endpoints Json? @db.JsonB
|
||
|
||
// ===== Phase 2 扩展字段 =====
|
||
|
||
/// 入选标准
|
||
inclusionCriteria Json? @map("inclusion_criteria") @db.JsonB
|
||
|
||
/// 排除标准
|
||
exclusionCriteria Json? @map("exclusion_criteria") @db.JsonB
|
||
|
||
/// 统计分析计划
|
||
statisticalPlan Json? @map("statistical_plan") @db.JsonB
|
||
|
||
// ===== Phase 3 扩展字段 =====
|
||
|
||
/// 伦理考量
|
||
ethicsConsiderations Json? @map("ethics_considerations") @db.JsonB
|
||
|
||
/// 研究时间线
|
||
timeline Json? @db.JsonB
|
||
|
||
/// 预算估算
|
||
budget Json? @db.JsonB
|
||
|
||
// ===== 元数据 =====
|
||
|
||
/// 总体进度 0-100
|
||
overallProgress Float @default(0) @map("overall_progress")
|
||
|
||
/// 已完成阶段
|
||
completedStages String[] @map("completed_stages")
|
||
|
||
/// 版本号
|
||
version Int @default(1)
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
versions ProtocolVersion[] @relation("ProtocolContextVersions")
|
||
|
||
@@index([userId])
|
||
@@index([conversationId])
|
||
@@map("protocol_contexts")
|
||
@@schema("protocol_schema")
|
||
}
|
||
```
|
||
|
||
**各字段JSON结构**:
|
||
|
||
#### scientificQuestion
|
||
|
||
```json
|
||
{
|
||
"content": "探究新型降糖药X对2型糖尿病患者的降糖效果及安全性",
|
||
"clinicalBackground": "2型糖尿病患病率逐年上升...",
|
||
"researchGap": "目前缺乏针对中国人群的大规模临床研究",
|
||
"significance": "填补该领域空白,为临床用药提供依据",
|
||
"confidence": 0.95,
|
||
"sourceMessageIds": ["msg_123", "msg_125"],
|
||
"lastUpdated": "2026-01-24T10:30:00Z"
|
||
}
|
||
```
|
||
|
||
#### pico
|
||
|
||
```json
|
||
{
|
||
"P": {
|
||
"value": "2型糖尿病患者",
|
||
"details": "年龄18-70岁,HbA1c 7.0-10.0%",
|
||
"confidence": 0.9
|
||
},
|
||
"I": {
|
||
"value": "新型降糖药X",
|
||
"details": "口服,每日一次,剂量10mg",
|
||
"confidence": 0.95
|
||
},
|
||
"C": {
|
||
"value": "二甲双胍",
|
||
"details": "口服,每日两次,剂量500mg",
|
||
"confidence": 0.88
|
||
},
|
||
"O": {
|
||
"value": "HbA1c变化",
|
||
"details": "治疗12周后HbA1c相对基线的变化值",
|
||
"confidence": 0.92
|
||
},
|
||
"sourceMessageIds": ["msg_130", "msg_132"],
|
||
"lastUpdated": "2026-01-24T11:00:00Z"
|
||
}
|
||
```
|
||
|
||
#### studyDesign
|
||
|
||
```json
|
||
{
|
||
"type": "RCT",
|
||
"phase": "III",
|
||
"blinding": "双盲",
|
||
"randomization": "中心随机",
|
||
"allocationRatio": "1:1",
|
||
"controlType": "阳性对照",
|
||
"multiCenter": true,
|
||
"centerCount": 20,
|
||
"duration": "12周治疗期 + 4周随访期",
|
||
"confidence": 0.9,
|
||
"sourceMessageIds": ["msg_140"],
|
||
"lastUpdated": "2026-01-24T11:30:00Z"
|
||
}
|
||
```
|
||
|
||
#### sampleSize
|
||
|
||
```json
|
||
{
|
||
"total": 500,
|
||
"perGroup": 250,
|
||
"groups": 2,
|
||
"calculationMethod": "优效性检验",
|
||
"assumptions": {
|
||
"alpha": 0.05,
|
||
"power": 0.8,
|
||
"effectSize": 0.5,
|
||
"dropoutRate": 0.15,
|
||
"standardDeviation": 1.2
|
||
},
|
||
"justification": "基于既往研究,预期效应量0.5%...",
|
||
"toolUsed": "sample_calculator",
|
||
"confidence": 0.95,
|
||
"sourceMessageIds": ["msg_150"],
|
||
"lastUpdated": "2026-01-24T12:00:00Z"
|
||
}
|
||
```
|
||
|
||
#### endpoints
|
||
|
||
```json
|
||
{
|
||
"primary": [{
|
||
"name": "HbA1c变化值",
|
||
"definition": "治疗12周后HbA1c相对基线的变化",
|
||
"measurementMethod": "高效液相色谱法",
|
||
"timePoint": "第12周",
|
||
"analysisMethod": "ANCOVA"
|
||
}],
|
||
"secondary": [{
|
||
"name": "空腹血糖",
|
||
"definition": "...",
|
||
"measurementMethod": "...",
|
||
"timePoint": "第4、8、12周"
|
||
}],
|
||
"safety": [{
|
||
"name": "低血糖发生率",
|
||
"definition": "血糖<3.9mmol/L的事件"
|
||
}],
|
||
"exploratory": [],
|
||
"sourceMessageIds": ["msg_160", "msg_162"],
|
||
"lastUpdated": "2026-01-24T12:30:00Z"
|
||
}
|
||
```
|
||
|
||
### 3.2 protocol_versions (版本历史表)
|
||
|
||
```prisma
|
||
/// Protocol版本历史表 - 支持回溯
|
||
model ProtocolVersion {
|
||
id String @id @default(uuid())
|
||
contextId String @map("context_id")
|
||
|
||
version Int
|
||
changeType String @map("change_type")
|
||
changedFields String[] @map("changed_fields")
|
||
previousSnapshot Json @map("previous_snapshot") @db.JsonB
|
||
changeReason String? @map("change_reason")
|
||
changedBy String @map("changed_by")
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
|
||
context ProtocolContext @relation("ProtocolContextVersions", fields: [contextId], references: [id], onDelete: Cascade)
|
||
|
||
@@unique([contextId, version])
|
||
@@index([contextId, createdAt])
|
||
@@map("protocol_versions")
|
||
@@schema("protocol_schema")
|
||
}
|
||
```
|
||
|
||
### 3.3 protocol_generations (研究方案生成表)
|
||
|
||
```prisma
|
||
/// Protocol生成记录表 - 一键生成研究方案
|
||
model ProtocolGeneration {
|
||
id String @id @default(uuid())
|
||
contextId String @map("context_id")
|
||
userId String @map("user_id")
|
||
|
||
// 生成内容
|
||
generatedContent String @map("generated_content") @db.Text // 生成的研究方案全文
|
||
contentVersion Int @default(1) @map("content_version") // 版本号(重新生成时递增)
|
||
|
||
// 使用的Prompt和参数
|
||
promptUsed String @map("prompt_used") @db.Text
|
||
generationParams Json? @map("generation_params") @db.JsonB // 生成参数
|
||
|
||
// LLM调用信息
|
||
modelUsed String @map("model_used")
|
||
tokensUsed Int? @map("tokens_used")
|
||
durationMs Int? @map("duration_ms")
|
||
|
||
// 导出记录
|
||
wordFileKey String? @map("word_file_key") // Word文件OSS Key
|
||
pdfFileKey String? @map("pdf_file_key") // PDF文件OSS Key
|
||
lastExportedAt DateTime? @map("last_exported_at")
|
||
|
||
// 用户编辑(如有)
|
||
userEditedContent String? @map("user_edited_content") @db.Text
|
||
isEdited Boolean @default(false) @map("is_edited")
|
||
|
||
status String @default("completed") // generating, completed, failed
|
||
errorMessage String? @map("error_message")
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
@@index([contextId])
|
||
@@index([userId, createdAt])
|
||
@@map("protocol_generations")
|
||
@@schema("protocol_schema")
|
||
}
|
||
```
|
||
|
||
**字段说明**:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| generatedContent | text | LLM生成的完整研究方案 |
|
||
| contentVersion | int | 版本号,重新生成时递增 |
|
||
| promptUsed | text | 使用的Prompt(便于复现和调试) |
|
||
| userEditedContent | text | 用户编辑后的内容(可选) |
|
||
| wordFileKey | string | 导出的Word文件在OSS中的Key |
|
||
|
||
### 3.4 protocol_exports (导出记录表)
|
||
|
||
```prisma
|
||
/// Protocol导出记录表
|
||
model ProtocolExport {
|
||
id String @id @default(uuid())
|
||
contextId String @map("context_id")
|
||
userId String @map("user_id")
|
||
|
||
exportType String @map("export_type")
|
||
exportVersion Int @map("export_version")
|
||
fileKey String? @map("file_key")
|
||
|
||
status String @default("pending")
|
||
errorMessage String? @map("error_message")
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
completedAt DateTime? @map("completed_at")
|
||
|
||
@@index([contextId])
|
||
@@index([userId, createdAt])
|
||
@@map("protocol_exports")
|
||
@@schema("protocol_schema")
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 四、knowledge_schema - 知识库表 (Phase 2)
|
||
|
||
### 4.1 knowledge_docs (知识文档表)
|
||
|
||
```prisma
|
||
/// 专家知识文档表
|
||
model KnowledgeDoc {
|
||
id String @id @default(uuid())
|
||
agentId String? @map("agent_id")
|
||
|
||
docType String @map("doc_type")
|
||
title String
|
||
description String? @db.Text
|
||
content String @db.Text
|
||
|
||
source String?
|
||
author String?
|
||
publishDate DateTime? @map("publish_date")
|
||
tags String[]
|
||
|
||
status String @default("active")
|
||
isPublic Boolean @default(true) @map("is_public")
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
updatedAt DateTime @updatedAt @map("updated_at")
|
||
|
||
chunks KnowledgeChunk[] @relation("DocChunks")
|
||
|
||
@@index([agentId, docType])
|
||
@@index([status, isPublic])
|
||
@@map("knowledge_docs")
|
||
@@schema("knowledge_schema")
|
||
}
|
||
```
|
||
|
||
### 4.2 knowledge_chunks (知识块表)
|
||
|
||
```prisma
|
||
/// 知识块表(用于RAG检索)
|
||
model KnowledgeChunk {
|
||
id String @id @default(uuid())
|
||
docId String @map("doc_id")
|
||
|
||
chunkIndex Int @map("chunk_index")
|
||
content String @db.Text
|
||
contentHash String @map("content_hash")
|
||
|
||
metadata Json? @db.JsonB
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
|
||
doc KnowledgeDoc @relation("DocChunks", fields: [docId], references: [id], onDelete: Cascade)
|
||
embedding KnowledgeEmbedding? @relation("ChunkEmbedding")
|
||
|
||
@@unique([docId, chunkIndex])
|
||
@@index([contentHash])
|
||
@@map("knowledge_chunks")
|
||
@@schema("knowledge_schema")
|
||
}
|
||
```
|
||
|
||
### 4.3 knowledge_embeddings (向量嵌入表)
|
||
|
||
```prisma
|
||
/// 向量嵌入表(pgvector)
|
||
model KnowledgeEmbedding {
|
||
id String @id @default(uuid())
|
||
chunkId String @unique @map("chunk_id")
|
||
|
||
embedding Unsupported("vector(1536)")
|
||
embeddingModel String @map("embedding_model")
|
||
|
||
createdAt DateTime @default(now()) @map("created_at")
|
||
|
||
chunk KnowledgeChunk @relation("ChunkEmbedding", fields: [chunkId], references: [id], onDelete: Cascade)
|
||
|
||
@@map("knowledge_embeddings")
|
||
@@schema("knowledge_schema")
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 五、数据库迁移计划
|
||
|
||
### 5.1 迁移步骤
|
||
|
||
```bash
|
||
# 1. 创建新Schema
|
||
CREATE SCHEMA IF NOT EXISTS agent_schema;
|
||
CREATE SCHEMA IF NOT EXISTS protocol_schema;
|
||
CREATE SCHEMA IF NOT EXISTS knowledge_schema;
|
||
|
||
# 2. 更新Prisma schema.prisma中的schemas配置
|
||
schemas = ["...", "agent_schema", "protocol_schema", "knowledge_schema"]
|
||
|
||
# 3. 生成迁移
|
||
npx prisma migrate dev --name add_agent_framework
|
||
|
||
# 4. 应用迁移
|
||
npx prisma migrate deploy
|
||
```
|
||
|
||
### 5.2 初始数据
|
||
|
||
```sql
|
||
-- 插入Protocol Agent配置
|
||
INSERT INTO agent_schema.agent_configs (
|
||
id, agent_id, agent_name, base_system_prompt,
|
||
memory_strategy, max_history_turns, default_model, is_active
|
||
) VALUES (
|
||
gen_random_uuid(),
|
||
'protocol_agent',
|
||
'研究方案制定助手',
|
||
'你是一位经验丰富的临床研究方法学专家,正在帮助研究者制定研究方案...',
|
||
'full',
|
||
20,
|
||
'deepseek-v3',
|
||
true
|
||
);
|
||
|
||
-- 插入阶段配置(示例:科学问题阶段)
|
||
INSERT INTO agent_schema.agent_stages (
|
||
id, agent_config_id, stage_id, stage_name, stage_order,
|
||
instruction, extraction_schema, next_stage_id, transition_mode
|
||
) VALUES (
|
||
gen_random_uuid(),
|
||
(SELECT id FROM agent_schema.agent_configs WHERE agent_id = 'protocol_agent'),
|
||
'scientific_question',
|
||
'科学问题澄清',
|
||
1,
|
||
'引导用户明确研究的核心科学问题...',
|
||
'{"type": "object", "properties": {...}}',
|
||
'pico',
|
||
'user_confirm'
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
## 六、ER关系图
|
||
|
||
```
|
||
agent_schema
|
||
┌───────────────────┐
|
||
│ AgentConfig │
|
||
│ (agent_configs) │
|
||
└────────┬──────────┘
|
||
│
|
||
┌────┴────┬─────────────┐
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
┌─────────┐ ┌─────────┐ ┌─────────────┐
|
||
│AgentStage│ │AgentTool│ │ReflexionRule│
|
||
└────┬────┘ └─────────┘ └─────────────┘
|
||
│
|
||
▼
|
||
┌─────────────┐
|
||
│ ActionCard │
|
||
└─────────────┘
|
||
|
||
┌─────────────┐ ┌─────────────┐
|
||
│AgentSession │ ───────→│ AgentTrace │
|
||
└─────────────┘ └─────────────┘
|
||
│
|
||
│ conversationId
|
||
▼
|
||
aia_schema
|
||
┌─────────────┐ ┌─────────────┐
|
||
│Conversation │────────<│ Message │
|
||
└─────────────┘ └─────────────┘
|
||
|
||
protocol_schema
|
||
┌─────────────────┐ ┌─────────────────┐
|
||
│ProtocolContext │────<│ProtocolVersion │
|
||
└─────────────────┘ └─────────────────┘
|
||
```
|
||
|