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
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
# **Protocol Agent 降本增效开发指南:从 MVP 到最终形态**
|
||||
|
||||
核心原则: "Think Big, Start Small" (大处着眼,小处着手)。
|
||||
当前状态: 感到 PRD 工作量过大,需要削减范围,聚焦核心价值。
|
||||
目标: 将 V3 架构拆解为可落地的 MVP,优先保证核心流程跑通,暂缓非关键特性的开发。
|
||||
|
||||
## **1\. 心理减负:我们到底在做什么?**
|
||||
|
||||
其实 Protocol Agent V3 的核心代码并没有 PRD 看起来那么吓人。剥去那些高大上的名词,它的本质其实很简单:
|
||||
|
||||
1. **Orchestrator** ≈ 一个 switch/case 语句,根据当前步骤加载不同的 Prompt。
|
||||
2. **Context** ≈ 往数据库存一个 JSON 对象。
|
||||
3. **Action Card** ≈ 给前端发一个特定格式的 JSON,让它渲染个按钮。
|
||||
4. **Backend CoT** ≈ 把一大段 Prompt 拆成 3 段小 Prompt 拼起来。
|
||||
|
||||
**结论:** 技术本身不难(都是 CRUD 和字符串拼接),难的是逻辑梳理。只要逻辑理顺了,代码量其实可控。
|
||||
|
||||
## **2\. 战术削减:MVP 阶段可以“砍”掉什么?(Phase 1 Scope)**
|
||||
|
||||
为了在第一阶段快速上线并验证价值,建议**暂时砍掉**以下 50% 的非核心功能:
|
||||
|
||||
| 功能模块 | PRD 定义 (V3) | MVP 策略 (Phase 1\) | 理由 (为什么砍掉?) |
|
||||
| :---- | :---- | :---- | :---- |
|
||||
| **🧠 大脑 (Brain)** | 复杂的意图识别 Router | **线性流转** | 用户只要完成 PICO,就自动跳到样本量。不需要 AI 猜意图,强制按顺序来。 |
|
||||
| **💾 记忆 (Memory)** | 复杂的增量提取算法 | **全量覆盖** | 不要做复杂的 diff 提取。每次对话结束后,直接让 AI 提取一次 PICO 覆盖存入 DB 即可。 |
|
||||
| **📚 知识 (Knowledge)** | EKB V2 混合检索 | **Mock 数据 / 暂缓** | 第一版先用通用大模型的能力,暂不接自建知识库。或者仅接入最简单的关键词检索。 |
|
||||
| **🛠️ 手脚 (Hands)** | 通用的 Action Card 协议 | **硬编码** | 不要写通用的 Deep Link 协议。直接硬编码:if (stage \== 'SAMPLE') return { type: 'sample\_card' }。 |
|
||||
| **⚙️ 配置 (Ops)** | 可视化 SOP 编排后台 | **JSON 文件** | 不要开发 Admin UI。直接在代码里写一个 const SOP\_CONFIG \= \[...\] JSON 对象。 |
|
||||
| **🛡️ 风控 (Reflexion)** | 复杂的规则引擎 | **Prompt 校验** | 不写代码规则。直接在 System Prompt 里加一句:“请检查样本量是否过小”。 |
|
||||
|
||||
**MVP 核心交付物:**
|
||||
|
||||
1. 一个能聊天的界面。
|
||||
2. 右侧能显示 PICO 表格(数据存 DB)。
|
||||
3. 能弹出一个样本量计算器,算完能把数填回右侧表格。
|
||||
(这就足够震撼了!)
|
||||
|
||||
## **3\. 分阶段实施路线图 (Step-by-Step)**
|
||||
|
||||
我们把原本宏大的 V3 计划,重新拆解为三个“舒适区”内的小目标。
|
||||
|
||||
### **✅ Phase 1: 核心链路打通 (2周)**
|
||||
|
||||
**目标:** "跑通 Happy Path"。用户能进来,能聊,能算,能存。
|
||||
|
||||
1. **数据库**:建 ProtocolContext 表 (JSONB)。
|
||||
2. **后端**:写一个简单的 Orchestrator,只支持 SCIENTIFIC\_QUESTION \-\> PICO \-\> SAMPLE\_SIZE 三个阶段的线性切换。
|
||||
3. **前端**:
|
||||
* 左侧聊天。
|
||||
* 右侧面板(只读,显示 Context JSON)。
|
||||
* 一个写死的“样本量计算”卡片。
|
||||
4. **验证**:用户说完 PICO,右侧面板能变;点击卡片能算数;算完数右侧面板能更新。**(这就够了!)**
|
||||
|
||||
### **⏩ Phase 2: 配置化与逻辑增强 (2周)**
|
||||
|
||||
**目标:** "把硬编码变成配置"。
|
||||
|
||||
1. **配置化**:把 Phase 1 里写死在代码里的 Prompt 和 SOP,提取到 prompt\_templates 表中。
|
||||
2. **管理后台**:做一个极其简陋的 Admin 页面(哪怕是纯文本框编辑 JSON),用来改 Prompt。
|
||||
3. **知识库接入**:此时再把 EKB V2 接入进来,增强“选题评价”环节的专业度。
|
||||
|
||||
### **🚀 Phase 3: 平台化与反思 (2周)**
|
||||
|
||||
**目标:** "更聪明,更通用"。
|
||||
|
||||
1. **Reflexion**:加上 reflexionGuard,开始对用户算出的结果指指点点(“你这个样本量太小了”)。
|
||||
2. **通用化**:重构代码,提取 BaseOrchestrator,准备开发统计 Agent。
|
||||
|
||||
## **4\. 给开发团队的具体建议 (Actionable Advice)**
|
||||
|
||||
1. **不要过度设计 (YAGNI)**:
|
||||
* 不要一开始就写 interface IAgent,不要写复杂的 AbstractFactory。
|
||||
* 就写一个 ProtocolService.ts,里面的逻辑哪怕有点面条代码也没关系,先跑通。
|
||||
2. **利用现有资源**:
|
||||
* **前端**:你们已经有了 Ant Design X,聊天界面和卡片组件几乎是现成的。
|
||||
* **后端**:你们已经有了 pg-boss,异步提取任务直接套用以前的代码。
|
||||
* **工具**:样本量计算器已经是现成的 Web 页面,只要加一行代码 window.parent.postMessage 就能和 Chat 通信(如果是 iframe 嵌入)或通过 URL 回调。
|
||||
3. **关于“力不从心”**:
|
||||
* 这种感觉通常来自于\*\*“不确定性”\*\*。
|
||||
* **解决办法**:把 PRD 里的所有“待定”、“可能”、“未来支持”全部划掉。只做确定的、具体的、最简单的功能。
|
||||
|
||||
## **5\. 总结**
|
||||
|
||||
**您不需要现在就造出完美的 AIA-OS。**
|
||||
|
||||
现在的任务只是:
|
||||
用 Postgres 存一个 JSON,让 LLM 根据这个 JSON 说话,再让一个网页计算器改一下这个 JSON。
|
||||
仅此而已。把这个做出来,就是巨大的成功。其他的(可视化编排、混合检索、多Agent协同)都是在这个核心循环跑通之后,自然生长出来的枝叶。
|
||||
|
||||
**建议:** 拿着这份“减负版”计划,跟团队说:“我们先不看那份几十页的 PRD 了,我们先花两周时间,把这三个核心功能(聊天、状态同步、工具调用)做出来。”
|
||||
158
docs/03-业务模块/AIA-AI智能问答/00-系统设计/Protocol_Agent_PRD_v1.0.md
Normal file
158
docs/03-业务模块/AIA-AI智能问答/00-系统设计/Protocol_Agent_PRD_v1.0.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# **产品需求文档 (PRD): 研究方案制定智能体 (Protocol Agent) & AIA 基础平台**
|
||||
|
||||
文档版本: v1.0
|
||||
状态: Final Draft
|
||||
日期: 2026-01-20
|
||||
项目代号: AIA-Protocol-V3
|
||||
核心理念: Plan-Execute-Reflexion (规划-执行-反思) | Backend-Driven SOP (后端驱动) | Deep Link Action (深度链接)
|
||||
|
||||
## **1\. 项目背景与目标 (Background & Goals)**
|
||||
|
||||
### **1.1 背景**
|
||||
|
||||
当前 AIA 模块包含 7 个独立运行的 AI 问答工具(科学问题、PICO、选题评价等)。这种“散点式”的交互导致用户体验割裂,上下文(Context)无法流转,且缺乏对复杂逻辑(如样本量计算)的深度支持。
|
||||
|
||||
### **1.2 核心目标**
|
||||
|
||||
1. **统一入口 (Unified Entry)**:将 7 个模块整合为一个 **Protocol Agent**,通过自然语言对话引导用户完成全流程。
|
||||
2. **长程记忆 (Long-term Memory)**:利用结构化数据 (JSONB) 维护一份“活的”研究方案,突破 LLM Context 限制。
|
||||
3. **专业深度 (Professional Depth)**:引入 **自建知识库 (EKB)** 和 **后端配置化思维链 (CoT)**,确保输出符合医学逻辑。
|
||||
4. **平台化基石 (Platform Foundation)**:沉淀一套通用的 Agent 开发框架 (AIA-OS),为未来的统计、清洗 Agent 打下地基。
|
||||
|
||||
## **2\. 产品核心理念:仿生架构 (The Bionic Architecture)**
|
||||
|
||||
产品设计严格遵循 **"Brain-Memory-Knowledge-Hands"** 四位一体架构:
|
||||
|
||||
| 组件 | 对应系统模块 | 核心职责 |
|
||||
| :---- | :---- | :---- |
|
||||
| **🧠 大脑 (Brain)** | **Orchestrator Engine** | 负责意图识别 (Router)、流程规划 (Plan)、思维链执行 (SOP) 和结果反思 (Reflexion)。 |
|
||||
| **💾 记忆 (Memory)** | **ProtocolContext (DB)** | 存储结构化的方案数据(PICO、N值、指标),实现跨会话、跨工具的状态同步。 |
|
||||
| **📚 知识 (Knowledge)** | **EKB (Self-built RAG)** | 基于 Postgres 的混合检索系统,提供 RCT 案例、指南、评分标准等外部知识。 |
|
||||
| **🛠️ 手脚 (Hands)** | **Deep Link Action** | 通过 **Action Card** 协议唤起现有的 Web 工具(样本量计算器、清洗工具),并回写结果。 |
|
||||
|
||||
## **3\. 用户流程 (User Journey)**
|
||||
|
||||
### **3.1 典型交互路径**
|
||||
|
||||
1. **意图识别**:用户输入“我想做一个阿司匹林的研究”。
|
||||
* *Brain*: 识别为 SCIENTIFIC\_QUESTION 阶段,加载对应 SOP。
|
||||
2. **多轮对话 (Plan)**:AI 引导用户完善 PICO 信息。
|
||||
* *Memory*: 实时提取 P, I, C, O 并存入数据库。
|
||||
* *UI*: 右侧 **状态面板 (State Panel)** 实时点亮已确认的字段。
|
||||
3. **工具执行 (Execute)**:用户确认 PICO 后,AI 判断需要计算样本量。
|
||||
* *Brain*: 生成 Action Card。
|
||||
* *UI*: 聊天窗显示“🚀 前往计算样本量”卡片。
|
||||
* *Hands*: 用户点击跳转 \-\> 在工具页完成计算 \-\> 点击“同步”。
|
||||
4. **反思校验 (Reflexion)**:数据回写后。
|
||||
* *Brain*: 触发后端校验规则(如 N \< 20)。
|
||||
* *UI*: AI 发送消息:“⚠️ 样本量过小,建议重新调整 Alpha 值。”
|
||||
5. **阶段流转**:校验通过后,自动进入下一阶段(观察指标设计)。
|
||||
|
||||
## **4\. 功能需求详情 (Functional Requirements)**
|
||||
|
||||
### **4.1 核心交互界面 (Unified Interface)**
|
||||
|
||||
#### **F1. 流式对话窗口 (Chat Interface)**
|
||||
|
||||
* **支持格式**:Markdown, Latex, **XML Thinking Block** (深度思考折叠区)。
|
||||
* **Action Card 渲染**:识别后端返回的 type: action\_card JSON,渲染为操作卡片。
|
||||
* **Reflexion 反馈**:识别系统级通知(System Message),以特殊样式(如紫色边框)展示 AI 的反思结果。
|
||||
|
||||
#### **F2. 实时状态面板 (Protocol State Panel)**
|
||||
|
||||
* **位置**:屏幕右侧(桌面端)/ 抽屉式(移动端)。
|
||||
* **数据源**:实时订阅 ProtocolContext.data。
|
||||
* **展示内容**:
|
||||
* 科学问题 (Text)
|
||||
* PICO (Table)
|
||||
* 样本量 (Highlight Number)
|
||||
* 核心指标 (Tags)
|
||||
* **交互**:支持用户**手动编辑**面板内容,编辑结果优先级高于 AI 提取。
|
||||
|
||||
### **4.2 编排引擎 (Orchestrator Backend)**
|
||||
|
||||
#### **F3. 动态 SOP 编排 (Backend CoT)**
|
||||
|
||||
* **机制**:从数据库 prompt\_templates.chain\_config 加载 SOP 步骤。
|
||||
* **执行**:将 SOP 编译为 System Prompt,强制 AI 输出 XML 思考标签。
|
||||
* **配置项**:支持在 Admin 后台配置 Step 顺序、指令内容、输出 Key。
|
||||
|
||||
#### **F4. 反思卫士 (Reflexion Guard)**
|
||||
|
||||
* **触发时机**:工具回写数据后、阶段切换前。
|
||||
* **校验逻辑**:
|
||||
* **硬规则**:N \< 10 (Fail), Power \< 0.8 (Warning)。
|
||||
* **软规则**:Prompt-based check ("检查对照组设置是否符合伦理?")。
|
||||
|
||||
### **4.3 知识库集成 (EKB Integration)**
|
||||
|
||||
#### **F5. 混合检索 (Hybrid Search)**
|
||||
|
||||
* **场景**:选题评价、指标设计。
|
||||
* **逻辑**:
|
||||
* SQL 过滤:WHERE study\_design-\>\>'sample\_size' \> 500。
|
||||
* Vector 检索:ORDER BY embedding \<=\> query。
|
||||
* Rerank:调用重排序模型取 Top 3。
|
||||
|
||||
### **4.4 工具集成 (Deep Link)**
|
||||
|
||||
#### **F6. 通用回写协议 (Universal Sync API)**
|
||||
|
||||
* **API**: POST /api/v1/aia/context/:id/sync
|
||||
* **Payload**: { "agent\_type": "PROTOCOL", "key": "sample\_size", "value": {...} }
|
||||
* **工具端改造**:现有样本量计算器需支持解析 URL 参数 (?ctx\_id=...) 并在计算完成后调用回写 API。
|
||||
|
||||
## **5\. 后端配置与运营 (LLM Ops)**
|
||||
|
||||
为了支持“后端配置化”,需要构建一个简易的运营后台。
|
||||
|
||||
### **5.1 配置管理**
|
||||
|
||||
* **全局配置**:Base Persona, Memory Schema。
|
||||
* **阶段配置**:7 个阶段的 Prompt, SOP (JSON Array), Reflexion Rules。
|
||||
|
||||
### **5.2 可观测性 (Trace)**
|
||||
|
||||
* **会话回放**:查看每一次 Router 决策、CoT 思考过程、Tool 调用结果。
|
||||
* **Bad Case 修正**:基于 Trace ID 快速定位问题,调整 Prompt 后一键重测。
|
||||
|
||||
## **6\. 平台化扩展策略 (Platform Strategy)**
|
||||
|
||||
本项目的交付物不仅仅是一个 Agent,而是一套 **AIA-OS 规范**。
|
||||
|
||||
### **6.1 通用能力抽象**
|
||||
|
||||
* **Context Interface**:定义 IContext 接口,未来支持 StatsContext (统计)、CleaningContext (清洗)。
|
||||
* **Action Card Protocol**:action\_card JSON 结构在所有 Agent 中通用。
|
||||
* **Orchestrator Core**:状态机引擎与业务逻辑解耦,未来只需编写不同的 Config 即可生成新 Agent。
|
||||
|
||||
## **7\. 技术架构 (Technical Architecture)**
|
||||
|
||||
* **前端**:React 19 \+ Ant Design X \+ Tailwind CSS
|
||||
* **后端**:Node.js (Fastify)
|
||||
* **语言**:TypeScript (全栈)
|
||||
* **数据库**:PostgreSQL 15+ (pgvector 插件)
|
||||
* **ORM**:Prisma (Schema-first)
|
||||
* **异步队列**:pg-boss (处理耗时任务如 PDF 解析、结构化提取)
|
||||
* **模型层**:OpenAI Compatible API (DeepSeek/Qwen)
|
||||
|
||||
## **8\. 实施路线图 (Roadmap)**
|
||||
|
||||
### **Phase 1: 核心骨架 (Week 1\)**
|
||||
|
||||
* \[后端\] 建立 protocol\_contexts 和 prompt\_templates (含 CoT 字段) 表。
|
||||
* \[后端\] 实现 ProtocolOrchestrator 基础状态机。
|
||||
* \[前端\] 搭建 Chat \+ State Panel 布局。
|
||||
|
||||
### **Phase 2: 智能增强 (Week 2\)**
|
||||
|
||||
* \[后端\] 实现动态 CoT 组装与 XML 解析。
|
||||
* \[后端\] 集成 EKB V2 混合检索服务。
|
||||
* \[后端\] 实现异步 PICO 提取 Worker。
|
||||
|
||||
### **Phase 3: 闭环打通 (Week 3\)**
|
||||
|
||||
* \[前端\] 开发 Action Card 组件。
|
||||
* \[工具\] 改造样本量计算器,支持 Deep Link 回写。
|
||||
* \[后端\] 实现 Reflexion Guard 校验逻辑。
|
||||
* \[Ops\] 上线简易配置后台 (Admin UI)。
|
||||
381
docs/03-业务模块/AIA-AI智能问答/00-系统设计/后端配置原型图V3.html
Normal file
381
docs/03-业务模块/AIA-AI智能问答/00-系统设计/后端配置原型图V3.html
Normal file
@@ -0,0 +1,381 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>AIA Protocol Agent Ops - V3.0</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
<!-- 引入 Alpine.js 用于简单的状态管理 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=JetBrains+Mono:wght@400;500&display=swap');
|
||||
|
||||
body { font-family: 'Inter', 'Noto Sans SC', sans-serif; }
|
||||
.font-mono { font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
/* 滚动条 */
|
||||
::-webkit-scrollbar { width: 6px; height: 6px; }
|
||||
::-webkit-scrollbar-track { background: transparent; }
|
||||
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 3px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
|
||||
|
||||
[x-cloak] { display: none !important; }
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-slate-50 h-screen flex flex-col text-slate-800" x-data="{
|
||||
currentTab: 'global-persona', // global-persona, global-memory, stage-prompt, stage-cot, stage-reflexion
|
||||
currentStage: 'SAMPLE_SIZE_CALC'
|
||||
}">
|
||||
|
||||
<!-- 1. 顶部栏 (Global Status) -->
|
||||
<header class="bg-white border-b border-slate-200 h-16 px-6 flex items-center justify-between shadow-sm z-20 shrink-0">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-9 h-9 bg-indigo-600 rounded-lg flex items-center justify-center text-white shadow-md">
|
||||
<i data-lucide="cpu" class="w-5 h-5"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="font-bold text-lg text-slate-800">Protocol Agent Ops</h1>
|
||||
<div class="flex items-center gap-2 text-[10px] text-slate-500 uppercase tracking-wider font-medium">
|
||||
<span>Env: Production</span>
|
||||
<span class="w-1 h-1 bg-slate-300 rounded-full"></span>
|
||||
<span>Orchestrator V3.0</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="flex items-center gap-2 px-3 py-1.5 bg-slate-100 rounded text-xs text-slate-600">
|
||||
<span class="w-2 h-2 bg-green-500 rounded-full"></span>
|
||||
API Status: Healthy
|
||||
</div>
|
||||
<button class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-lg text-sm font-medium transition flex items-center gap-2 shadow-sm">
|
||||
<i data-lucide="save" class="w-4 h-4"></i>
|
||||
发布变更
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex flex-1 overflow-hidden">
|
||||
|
||||
<!-- 2. 左侧导航 (Global -> Stages) -->
|
||||
<aside class="w-64 bg-white border-r border-slate-200 flex flex-col overflow-y-auto shrink-0">
|
||||
|
||||
<!-- Global Config Section -->
|
||||
<div class="p-4">
|
||||
<div class="text-xs font-bold text-slate-400 uppercase tracking-wider mb-3 px-2">Level 1: 全局设定</div>
|
||||
<nav class="space-y-1">
|
||||
<button @click="currentTab = 'global-persona'" :class="currentTab === 'global-persona' ? 'bg-indigo-50 text-indigo-700' : 'text-slate-700 hover:bg-slate-50'" class="w-full text-left block px-3 py-2 text-sm rounded-lg flex items-center gap-3 transition">
|
||||
<i data-lucide="settings" class="w-4 h-4" :class="currentTab === 'global-persona' ? 'text-indigo-600' : 'text-slate-400'"></i>
|
||||
全局人设 (Persona)
|
||||
</button>
|
||||
<button @click="currentTab = 'global-memory'" :class="currentTab === 'global-memory' ? 'bg-indigo-50 text-indigo-700' : 'text-slate-700 hover:bg-slate-50'" class="w-full text-left block px-3 py-2 text-sm rounded-lg flex items-center gap-3 transition">
|
||||
<i data-lucide="database" class="w-4 h-4" :class="currentTab === 'global-memory' ? 'text-indigo-600' : 'text-slate-400'"></i>
|
||||
记忆与知识库
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<!-- Stages Config Section -->
|
||||
<div class="p-4 pt-0">
|
||||
<div class="text-xs font-bold text-slate-400 uppercase tracking-wider mb-3 px-2 flex justify-between items-center">
|
||||
Level 2: 阶段配置
|
||||
<span class="bg-indigo-100 text-indigo-700 px-1.5 rounded text-[10px]">7</span>
|
||||
</div>
|
||||
<nav class="space-y-1">
|
||||
<template x-for="(stage, idx) in ['科学问题梳理', 'PICO 分析', '选题评价', '观察指标设计', '样本量计算', 'CRF 设计', '方案撰写']">
|
||||
<button
|
||||
@click="currentStage = stage; currentTab = 'stage-cot'"
|
||||
:class="currentStage === stage ? 'bg-indigo-50 text-indigo-700 border border-indigo-100 shadow-sm' : 'text-slate-600 hover:bg-slate-50'"
|
||||
class="w-full text-left px-3 py-2 text-sm rounded-lg flex items-center gap-3 transition relative group"
|
||||
>
|
||||
<span
|
||||
class="w-5 text-center text-xs font-mono"
|
||||
:class="currentStage === stage ? 'text-indigo-500' : 'text-slate-400'"
|
||||
x-text="'0' + (idx + 1)"
|
||||
></span>
|
||||
<span x-text="stage" :class="currentStage === stage ? 'font-medium' : ''"></span>
|
||||
<span x-show="currentStage === stage" class="absolute right-3 w-1.5 h-1.5 bg-indigo-500 rounded-full"></span>
|
||||
</button>
|
||||
</template>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- 3. 主内容区 -->
|
||||
<main class="flex-1 flex flex-col bg-slate-50/50 overflow-hidden relative">
|
||||
|
||||
<!-- Global & Memory Tabs (Only show when Global is selected) -->
|
||||
<div x-show="currentTab.startsWith('global')" class="px-8 py-6 border-b border-slate-200 bg-white">
|
||||
<h2 class="text-xl font-bold text-slate-800 mb-1 flex items-center gap-2">
|
||||
<i data-lucide="globe" class="w-5 h-5 text-indigo-600"></i>
|
||||
全局配置中心
|
||||
</h2>
|
||||
<p class="text-sm text-slate-500">定义 Protocol Agent 的底层逻辑、记忆结构和通用知识库挂载。</p>
|
||||
</div>
|
||||
|
||||
<!-- Stage Header (Only show when Stage is selected) -->
|
||||
<div x-show="currentTab.startsWith('stage')" class="px-8 py-6 border-b border-slate-200 bg-white flex justify-between items-start">
|
||||
<div>
|
||||
<h2 class="text-xl font-bold text-slate-800 mb-1 flex items-center gap-2">
|
||||
<span x-text="currentStage"></span>
|
||||
<span class="text-xs bg-slate-100 text-slate-500 px-2 py-0.5 rounded font-mono font-normal">ID: SAMPLE_SIZE_CALC</span>
|
||||
</h2>
|
||||
<p class="text-sm text-slate-500">配置该阶段的任务指令、思维链逻辑和反思规则。</p>
|
||||
</div>
|
||||
<!-- Logic Layer Tabs -->
|
||||
<div class="flex bg-slate-100 p-1 rounded-lg">
|
||||
<button @click="currentTab = 'stage-prompt'" :class="currentTab === 'stage-prompt' ? 'bg-white text-indigo-600 shadow-sm' : 'text-slate-600 hover:text-slate-900'" class="px-4 py-1.5 text-sm font-medium rounded-md transition">Prompt (指令)</button>
|
||||
<button @click="currentTab = 'stage-cot'" :class="currentTab === 'stage-cot' ? 'bg-white text-indigo-600 shadow-sm' : 'text-slate-600 hover:text-slate-900'" class="px-4 py-1.5 text-sm font-medium rounded-md transition flex items-center gap-2"><i data-lucide="git-merge" class="w-3 h-3"></i>思维链 (CoT)</button>
|
||||
<button @click="currentTab = 'stage-reflexion'" :class="currentTab === 'stage-reflexion' ? 'bg-white text-indigo-600 shadow-sm' : 'text-slate-600 hover:text-slate-900'" class="px-4 py-1.5 text-sm font-medium rounded-md transition flex items-center gap-2"><i data-lucide="shield-check" class="w-3 h-3"></i>反思卫士</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scrollable Content Area -->
|
||||
<div class="flex-1 overflow-y-auto p-8">
|
||||
<div class="max-w-4xl mx-auto space-y-6">
|
||||
|
||||
<!-- ========================================== -->
|
||||
<!-- 1. 全局人设 (Global Persona) -->
|
||||
<!-- ========================================== -->
|
||||
<div x-show="currentTab === 'global-persona'" x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 translate-y-2">
|
||||
<div class="bg-white border border-slate-200 rounded-xl p-6 shadow-sm mb-6">
|
||||
<h3 class="font-bold text-slate-700 mb-4">Base System Prompt (基座人设)</h3>
|
||||
<textarea class="w-full h-48 text-sm border border-slate-200 rounded-lg p-4 bg-slate-50 focus:bg-white focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 outline-none resize-none font-mono leading-relaxed">
|
||||
你是一个严谨的临床研究方法学专家助手 (Protocol Agent)。
|
||||
你的核心目标是辅助用户制定一份科学、合规、可执行的临床研究方案。
|
||||
|
||||
核心原则:
|
||||
1. 循证医学:所有建议必须基于可靠的医学证据。
|
||||
2. 逻辑严密:在回答前,必须先进行逻辑推演 (Chain of Thought)。
|
||||
3. 状态感知:始终基于 Context 中已确认的信息(PICO等)进行回答,不要重复索要已知信息。
|
||||
4. 语气风格:专业、客观、理性,避免过度热情的营销式语气。
|
||||
</textarea>
|
||||
<div class="flex justify-end mt-4">
|
||||
<button class="text-sm text-indigo-600 hover:underline">查看历史版本 (v1.2)</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========================================== -->
|
||||
<!-- 2. 记忆与知识库 (Global Memory & Knowledge)-->
|
||||
<!-- ========================================== -->
|
||||
<div x-show="currentTab === 'global-memory'" x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 translate-y-2">
|
||||
|
||||
<!-- Memory Schema -->
|
||||
<div class="bg-white border border-slate-200 rounded-xl p-6 shadow-sm mb-6">
|
||||
<h3 class="font-bold text-slate-700 mb-4 flex items-center gap-2">
|
||||
<i data-lucide="hard-drive" class="w-4 h-4 text-indigo-500"></i>
|
||||
记忆结构定义 (Memory Schema)
|
||||
</h3>
|
||||
<div class="bg-slate-900 rounded-lg p-4 font-mono text-xs text-slate-300 overflow-x-auto">
|
||||
<pre>{
|
||||
"scientific_question": "string",
|
||||
"pico": {
|
||||
"p": "string (Patient)",
|
||||
"i": "string (Intervention)",
|
||||
"c": "string (Comparison)",
|
||||
"o": "string (Outcome)"
|
||||
},
|
||||
"sample_size": {
|
||||
"n_total": "number",
|
||||
"power": "number",
|
||||
"alpha": "number"
|
||||
},
|
||||
...
|
||||
}</pre>
|
||||
</div>
|
||||
<p class="text-xs text-slate-500 mt-2">此 Schema 定义了 Agent 可以“记住”的结构化数据字段。修改此配置需同步更新后端 Prisma Schema。</p>
|
||||
</div>
|
||||
|
||||
<!-- Knowledge Base -->
|
||||
<div class="bg-white border border-slate-200 rounded-xl p-6 shadow-sm">
|
||||
<h3 class="font-bold text-slate-700 mb-4 flex items-center gap-2">
|
||||
<i data-lucide="library" class="w-4 h-4 text-green-500"></i>
|
||||
知识库挂载 (EKB Mounting)
|
||||
</h3>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-center justify-between p-3 border border-slate-200 rounded-lg bg-slate-50">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-8 h-8 bg-white border border-slate-200 rounded flex items-center justify-center">
|
||||
<i data-lucide="book" class="w-4 h-4 text-indigo-500"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm font-medium text-slate-800">Clinical Guidelines (临床指南库)</div>
|
||||
<div class="text-xs text-slate-500">包含 2020-2025 全球核心指南 | 12,400 篇</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-xs bg-green-100 text-green-700 px-2 py-0.5 rounded">Active</span>
|
||||
<button class="text-slate-400 hover:text-slate-600"><i data-lucide="more-horizontal" class="w-4 h-4"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between p-3 border border-slate-200 rounded-lg bg-slate-50">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-8 h-8 bg-white border border-slate-200 rounded flex items-center justify-center">
|
||||
<i data-lucide="file-text" class="w-4 h-4 text-indigo-500"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm font-medium text-slate-800">RCT Protocols (RCT 方案库)</div>
|
||||
<div class="text-xs text-slate-500">高质量 RCT 注册方案 | 5,300 篇</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-xs bg-green-100 text-green-700 px-2 py-0.5 rounded">Active</span>
|
||||
<button class="text-slate-400 hover:text-slate-600"><i data-lucide="more-horizontal" class="w-4 h-4"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========================================== -->
|
||||
<!-- 3. 阶段 Prompt (Stage Prompt) -->
|
||||
<!-- ========================================== -->
|
||||
<div x-show="currentTab === 'stage-prompt'" x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 translate-y-2">
|
||||
<div class="bg-white border border-slate-200 rounded-xl p-6 shadow-sm">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h3 class="font-bold text-slate-700">Task Instruction (阶段任务指令)</h3>
|
||||
<div class="text-xs text-slate-500">这将覆盖到 System Prompt 的 [Stage Instruction] 部分</div>
|
||||
</div>
|
||||
<textarea class="w-full h-64 text-sm border border-slate-200 rounded-lg p-4 bg-slate-50 focus:bg-white focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 outline-none resize-none font-mono leading-relaxed">
|
||||
当前任务阶段:【样本量计算】
|
||||
|
||||
你的目标是帮助用户确定合适的研究样本量。
|
||||
请遵循以下逻辑:
|
||||
1. 识别研究设计类型(RCT、队列、病例对照)。
|
||||
2. 询问或确认计算所需的统计学参数(Alpha, Power, Effect Size, 组间比例)。
|
||||
- 如果用户不知道,给出该领域的常用默认值(如 Alpha=0.05, Power=0.8)。
|
||||
3. 一旦参数齐全,请生成 Action Card 引导用户调用计算器。
|
||||
4. 计算完成后,对结果进行解读(是否过大/过小,是否符合伦理)。
|
||||
|
||||
注意:严禁自己口算样本量,必须调用工具。
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========================================== -->
|
||||
<!-- 4. 思维链编排 (Stage CoT) -->
|
||||
<!-- ========================================== -->
|
||||
<div x-show="currentTab === 'stage-cot'" x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 translate-y-2">
|
||||
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="font-bold text-slate-700">思维链 SOP 可视化编排</h3>
|
||||
<button class="text-xs bg-slate-100 hover:bg-slate-200 text-slate-600 px-3 py-1.5 rounded transition">查看 JSON 源码</button>
|
||||
</div>
|
||||
|
||||
<!-- Step List -->
|
||||
<div class="space-y-4">
|
||||
|
||||
<!-- Step 1 -->
|
||||
<div class="bg-white border border-slate-200 rounded-xl p-5 shadow-sm hover:border-indigo-300 transition-colors group relative">
|
||||
<div class="absolute left-0 top-0 bottom-0 w-1.5 bg-slate-300 rounded-l-xl group-hover:bg-indigo-500 transition-colors"></div>
|
||||
<div class="flex gap-4">
|
||||
<div class="shrink-0 flex flex-col items-center gap-2 pt-1">
|
||||
<span class="w-6 h-6 rounded-full bg-slate-100 text-slate-500 text-xs font-bold flex items-center justify-center border border-slate-200">1</span>
|
||||
</div>
|
||||
<div class="flex-1 space-y-3">
|
||||
<div class="flex justify-between items-center">
|
||||
<input type="text" value="Check Parameters (参数完整性检查)" class="font-bold text-slate-800 bg-transparent border-none p-0 focus:ring-0 w-full text-sm">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="text-[10px] bg-slate-100 text-slate-500 px-2 py-0.5 rounded font-mono">Output: <completeness_check></div>
|
||||
<i data-lucide="trash-2" class="w-4 h-4 text-slate-300 hover:text-red-500 cursor-pointer"></i>
|
||||
</div>
|
||||
</div>
|
||||
<textarea class="w-full text-xs border border-slate-200 rounded-lg p-2 bg-slate-50 focus:bg-white outline-none resize-none h-16">检查用户输入的 Context 中是否包含样本量计算所需的全部参数(Alpha, Power, 预期效应量)。</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="bg-white border border-slate-200 rounded-xl p-5 shadow-sm hover:border-indigo-300 transition-colors group relative">
|
||||
<div class="absolute left-0 top-0 bottom-0 w-1.5 bg-slate-300 rounded-l-xl group-hover:bg-indigo-500 transition-colors"></div>
|
||||
<div class="flex gap-4">
|
||||
<div class="shrink-0 flex flex-col items-center gap-2 pt-1">
|
||||
<span class="w-6 h-6 rounded-full bg-slate-100 text-slate-500 text-xs font-bold flex items-center justify-center border border-slate-200">2</span>
|
||||
</div>
|
||||
<div class="flex-1 space-y-3">
|
||||
<div class="flex justify-between items-center">
|
||||
<input type="text" value="Match Methodology (方法学匹配)" class="font-bold text-slate-800 bg-transparent border-none p-0 focus:ring-0 w-full text-sm">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="text-[10px] bg-slate-100 text-slate-500 px-2 py-0.5 rounded font-mono">Output: <method_match></div>
|
||||
<i data-lucide="trash-2" class="w-4 h-4 text-slate-300 hover:text-red-500 cursor-pointer"></i>
|
||||
</div>
|
||||
</div>
|
||||
<textarea class="w-full text-xs border border-slate-200 rounded-lg p-2 bg-slate-50 focus:bg-white outline-none resize-none h-16">基于 PICO 中的 Study Design (RCT/Cohort),推荐最合适的样本量计算公式。若无法确定,推荐通用公式。</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Step -->
|
||||
<button class="w-full py-3 border-2 border-dashed border-slate-300 rounded-xl text-slate-500 text-sm font-medium hover:border-indigo-500 hover:text-indigo-600 hover:bg-indigo-50 transition flex items-center justify-center gap-2">
|
||||
<i data-lucide="plus" class="w-4 h-4"></i>
|
||||
添加思考步骤
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========================================== -->
|
||||
<!-- 5. 反思卫士 (Stage Reflexion) -->
|
||||
<!-- ========================================== -->
|
||||
<div x-show="currentTab === 'stage-reflexion'" x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0 translate-y-2">
|
||||
|
||||
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6 flex gap-3">
|
||||
<i data-lucide="shield-check" class="w-5 h-5 text-blue-600 shrink-0 mt-0.5"></i>
|
||||
<div class="text-sm text-blue-800">
|
||||
<p class="font-bold mb-1">Reflexion Guard (反思卫士)</p>
|
||||
<p>当工具执行完毕并回写数据时,后端会自动运行这些规则。如果校验失败,Agent 将拒绝推进流程并报警。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white border border-slate-200 rounded-lg overflow-hidden shadow-sm">
|
||||
<div class="px-4 py-3 bg-slate-50 border-b border-slate-200 flex justify-between items-center">
|
||||
<h3 class="text-sm font-bold text-slate-700">规则列表 (Rule-based)</h3>
|
||||
<button class="text-xs text-indigo-600 hover:underline">+ 添加规则</button>
|
||||
</div>
|
||||
<table class="w-full text-sm text-left">
|
||||
<thead class="bg-slate-50 text-slate-500 border-b border-slate-200">
|
||||
<tr>
|
||||
<th class="px-4 py-3 font-medium">校验字段</th>
|
||||
<th class="px-4 py-3 font-medium">逻辑</th>
|
||||
<th class="px-4 py-3 font-medium">阈值</th>
|
||||
<th class="px-4 py-3 font-medium">报警消息</th>
|
||||
<th class="px-4 py-3 text-right">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-slate-100">
|
||||
<tr>
|
||||
<td class="px-4 py-3 font-mono text-indigo-600">sample_size.n</td>
|
||||
<td class="px-4 py-3 text-slate-600"><</td>
|
||||
<td class="px-4 py-3 font-mono">10</td>
|
||||
<td class="px-4 py-3 text-slate-600">样本量过小,无法通过伦理审查</td>
|
||||
<td class="px-4 py-3 text-right text-slate-400 hover:text-indigo-600 cursor-pointer"><i data-lucide="edit-2" class="w-4 h-4 inline"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-4 py-3 font-mono text-indigo-600">sample_size.n</td>
|
||||
<td class="px-4 py-3 text-slate-600">></td>
|
||||
<td class="px-4 py-3 font-mono">100000</td>
|
||||
<td class="px-4 py-3 text-slate-600">样本量过大,请确认可行性</td>
|
||||
<td class="px-4 py-3 text-right text-slate-400 hover:text-indigo-600 cursor-pointer"><i data-lucide="edit-2" class="w-4 h-4 inline"></i></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 bg-white border border-slate-200 rounded-lg p-6 shadow-sm">
|
||||
<h3 class="text-sm font-bold text-slate-700 mb-3">AI 软校验 (Prompt-based)</h3>
|
||||
<textarea class="w-full text-xs border border-slate-200 rounded-lg p-3 bg-slate-50 focus:bg-white outline-none resize-none h-20" placeholder="在此输入给 AI 的反思指令...">请结合用户的研究病种(如罕见病),判断该样本量是否合理。如果是罕见病,样本量小是可以接受的。</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
lucide.createIcons();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
442
docs/03-业务模块/AIA-AI智能问答/00-系统设计/研究方案原型图0119.html
Normal file
442
docs/03-业务模块/AIA-AI智能问答/00-系统设计/研究方案原型图0119.html
Normal file
@@ -0,0 +1,442 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Protocol Agent V2.0 - 产品原型</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<!-- 引入 Lucide 图标 -->
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap');
|
||||
|
||||
body { font-family: 'Inter', 'Noto Sans SC', sans-serif; }
|
||||
|
||||
/* 模拟 Ant Design X 的 ultramodern 风格 */
|
||||
.chat-bubble-ai {
|
||||
background-color: #F3F4F6;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 12px;
|
||||
border-bottom-right-radius: 12px;
|
||||
border-bottom-left-radius: 12px;
|
||||
}
|
||||
|
||||
.chat-bubble-user {
|
||||
background-color: #4F46E5; /* Indigo-600 */
|
||||
color: white;
|
||||
border-top-left-radius: 12px;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 12px;
|
||||
border-bottom-left-radius: 12px;
|
||||
}
|
||||
|
||||
.reflexion-border {
|
||||
border-left: 4px solid #9333EA; /* Purple-600 */
|
||||
background: #F3E8FF; /* Purple-100 */
|
||||
}
|
||||
|
||||
/* 状态面板动画 */
|
||||
.flash-update {
|
||||
animation: flash 1.5s ease-out;
|
||||
}
|
||||
|
||||
@keyframes flash {
|
||||
0% { background-color: #dbeafe; } /* blue-100 */
|
||||
100% { background-color: transparent; }
|
||||
}
|
||||
|
||||
/* 滚动条美化 */
|
||||
::-webkit-scrollbar { width: 6px; }
|
||||
::-webkit-scrollbar-track { background: transparent; }
|
||||
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 3px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-gray-100 h-screen flex flex-col overflow-hidden">
|
||||
|
||||
<!-- Top Navigation -->
|
||||
<header class="bg-white border-b border-gray-200 h-14 flex items-center justify-between px-4 shadow-sm z-10">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-8 h-8 bg-indigo-600 rounded-lg flex items-center justify-center text-white font-bold shadow-lg shadow-indigo-200">
|
||||
<i data-lucide="bot" class="w-5 h-5"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="font-bold text-gray-800 text-sm">研究方案制定 Agent</h1>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<span class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></span>
|
||||
<span class="text-xs text-gray-500">Orchestrator Online</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="hidden md:flex items-center gap-2 px-3 py-1.5 bg-gray-50 rounded-full border border-gray-200">
|
||||
<span class="text-xs font-medium text-gray-500">当前阶段:</span>
|
||||
<span class="text-xs font-bold text-indigo-600 bg-indigo-50 px-2 py-0.5 rounded border border-indigo-100">Step 5: 样本量计算</span>
|
||||
</div>
|
||||
<button class="p-2 hover:bg-gray-100 rounded-full text-gray-600">
|
||||
<i data-lucide="settings" class="w-5 h-5"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Main Workspace -->
|
||||
<main class="flex-1 flex overflow-hidden">
|
||||
|
||||
<!-- Left: Chat Interface (70%) -->
|
||||
<section class="flex-1 flex flex-col bg-white relative">
|
||||
|
||||
<!-- Chat History -->
|
||||
<div id="chat-container" class="flex-1 overflow-y-auto p-4 md:p-6 space-y-6 pb-20">
|
||||
|
||||
<!-- Welcome Message -->
|
||||
<div class="flex gap-4">
|
||||
<div class="w-8 h-8 rounded-full bg-indigo-100 flex items-center justify-center shrink-0">
|
||||
<i data-lucide="sparkles" class="w-4 h-4 text-indigo-600"></i>
|
||||
</div>
|
||||
<div class="space-y-1 max-w-[80%]">
|
||||
<div class="text-xs text-gray-400 ml-1">Protocol Agent • 10:00 AM</div>
|
||||
<div class="chat-bubble-ai p-4 text-sm text-gray-800 shadow-sm">
|
||||
<p>您好!我是您的研究方案制定助手。</p>
|
||||
<p class="mt-2">我已经记录了您关于<strong>“阿司匹林预防老年高血压患者中风”</strong>的科学问题和 PICO 信息。</p>
|
||||
<p class="mt-2">根据当前的 RCT 设计,我们需要进行<strong>样本量计算</strong>以支撑伦理审查。您准备好开始了吗?</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Message -->
|
||||
<div class="flex gap-4 flex-row-reverse">
|
||||
<div class="w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center shrink-0">
|
||||
<i data-lucide="user" class="w-4 h-4 text-gray-500"></i>
|
||||
</div>
|
||||
<div class="space-y-1 max-w-[80%]">
|
||||
<div class="text-xs text-gray-400 text-right mr-1">User • 10:02 AM</div>
|
||||
<div class="chat-bubble-user p-4 text-sm shadow-sm">
|
||||
好的,帮我计算一下样本量。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI Plan & Action Card (Deep Link) -->
|
||||
<div class="flex gap-4">
|
||||
<div class="w-8 h-8 rounded-full bg-indigo-100 flex items-center justify-center shrink-0">
|
||||
<i data-lucide="brain-circuit" class="w-4 h-4 text-indigo-600"></i>
|
||||
</div>
|
||||
<div class="space-y-1 max-w-[80%]">
|
||||
<div class="text-xs text-gray-400 ml-1">Protocol Agent • 10:02 AM</div>
|
||||
|
||||
<!-- The Action Card Component -->
|
||||
<div class="border border-indigo-200 bg-indigo-50/50 rounded-xl p-4 shadow-sm w-[380px]">
|
||||
<div class="flex items-start gap-3 mb-3">
|
||||
<div class="bg-indigo-100 p-2 rounded-lg">
|
||||
<i data-lucide="calculator" class="w-5 h-5 text-indigo-600"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-bold text-gray-900 text-sm">建议执行:样本量计算</h3>
|
||||
<p class="text-xs text-gray-500 mt-0.5">基于双侧两样本均数比较 (RCT)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Prefilled Parameters Preview -->
|
||||
<div class="bg-white rounded border border-indigo-100 p-2 mb-3 space-y-1">
|
||||
<div class="flex justify-between text-xs">
|
||||
<span class="text-gray-500">Alpha (α):</span>
|
||||
<span class="font-mono font-medium">0.05</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-xs">
|
||||
<span class="text-gray-500">Power (1-β):</span>
|
||||
<span class="font-mono font-medium">0.80</span>
|
||||
</div>
|
||||
<div class="flex justify-between text-xs">
|
||||
<span class="text-gray-500">Effect Size:</span>
|
||||
<span class="font-mono font-medium">预估 0.15 vs 0.10</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button onclick="openToolModal()" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white text-sm font-medium py-2 rounded-lg transition flex items-center justify-center gap-2 shadow-sm shadow-indigo-200">
|
||||
<span>🚀 前往计算工具</span>
|
||||
<i data-lucide="external-link" class="w-3 h-3"></i>
|
||||
</button>
|
||||
<p class="text-[10px] text-center text-gray-400 mt-2">点击将打开工具面板,参数已自动预填</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dynamic Content Will Be Appended Here -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Input Area -->
|
||||
<div class="p-4 border-t border-gray-100 bg-white absolute bottom-0 w-full">
|
||||
<div class="relative">
|
||||
<input type="text" placeholder="输入您的指令..." class="w-full pl-4 pr-12 py-3 bg-gray-50 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:bg-white transition text-sm">
|
||||
<button class="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">
|
||||
<i data-lucide="send" class="w-4 h-4"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Right: Protocol State Panel (30%) -->
|
||||
<aside class="w-[350px] bg-gray-50 border-l border-gray-200 flex flex-col hidden md:flex">
|
||||
<div class="p-4 border-b border-gray-200 bg-white flex justify-between items-center">
|
||||
<h2 class="font-bold text-gray-800 text-sm flex items-center gap-2">
|
||||
<i data-lucide="file-text" class="w-4 h-4 text-gray-500"></i>
|
||||
方案状态 (Context)
|
||||
</h2>
|
||||
<span class="text-[10px] bg-green-100 text-green-700 px-2 py-0.5 rounded-full font-medium">Synced</span>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 overflow-y-auto p-4 space-y-4">
|
||||
|
||||
<!-- Section 1: Scientific Question -->
|
||||
<div class="bg-white p-3 rounded-lg border border-gray-200 shadow-sm">
|
||||
<h3 class="text-xs font-bold text-gray-400 uppercase mb-2 tracking-wider">01 科学问题</h3>
|
||||
<p class="text-xs text-gray-700 leading-relaxed font-medium">
|
||||
阿司匹林预防老年高血压患者中风的疗效与安全性研究
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Section 2: PICO -->
|
||||
<div class="bg-white p-3 rounded-lg border border-gray-200 shadow-sm">
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<h3 class="text-xs font-bold text-gray-400 uppercase tracking-wider">02 PICO</h3>
|
||||
<button class="text-[10px] text-indigo-600 hover:underline">编辑</button>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<div class="flex gap-2">
|
||||
<span class="bg-blue-100 text-blue-700 px-1.5 py-0.5 rounded text-[10px] font-bold w-6 text-center">P</span>
|
||||
<span class="text-xs text-gray-600">≥65岁原发性高血压患者</span>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<span class="bg-indigo-100 text-indigo-700 px-1.5 py-0.5 rounded text-[10px] font-bold w-6 text-center">I</span>
|
||||
<span class="text-xs text-gray-600">阿司匹林肠溶片 100mg/d</span>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<span class="bg-orange-100 text-orange-700 px-1.5 py-0.5 rounded text-[10px] font-bold w-6 text-center">C</span>
|
||||
<span class="text-xs text-gray-600">安慰剂</span>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<span class="bg-green-100 text-green-700 px-1.5 py-0.5 rounded text-[10px] font-bold w-6 text-center">O</span>
|
||||
<span class="text-xs text-gray-600">5年内缺血性脑卒中发生率</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section 3: Study Design -->
|
||||
<div class="bg-white p-3 rounded-lg border border-gray-200 shadow-sm">
|
||||
<h3 class="text-xs font-bold text-gray-400 uppercase mb-2 tracking-wider">03 研究设计</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="text-[10px] border border-gray-200 px-2 py-1 rounded bg-gray-50 text-gray-600">RCT</span>
|
||||
<span class="text-[10px] border border-gray-200 px-2 py-1 rounded bg-gray-50 text-gray-600">双盲</span>
|
||||
<span class="text-[10px] border border-gray-200 px-2 py-1 rounded bg-gray-50 text-gray-600">多中心</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section 4: Sample Size (The Active One) -->
|
||||
<div id="state-sample-size" class="bg-white p-3 rounded-lg border-2 border-indigo-100 shadow-sm transition-colors duration-500">
|
||||
<h3 class="text-xs font-bold text-indigo-600 uppercase mb-2 tracking-wider flex justify-between">
|
||||
04 样本量
|
||||
<i data-lucide="loader-2" class="w-3 h-3 animate-spin"></i>
|
||||
</h3>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-xs text-gray-500">总样本量 (N)</span>
|
||||
<span id="n-value-display" class="text-lg font-bold text-gray-300 font-mono">待计算...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
</main>
|
||||
|
||||
<!-- Modal: Simulated External Tool (Deep Link Destination) -->
|
||||
<div id="tool-modal" class="fixed inset-0 bg-black/50 hidden z-50 flex items-center justify-center backdrop-blur-sm opacity-0 transition-opacity duration-300">
|
||||
<div class="bg-white rounded-xl shadow-2xl w-[600px] overflow-hidden transform scale-95 transition-transform duration-300" id="tool-modal-content">
|
||||
<!-- Tool Header -->
|
||||
<div class="bg-gray-800 text-white p-4 flex justify-between items-center">
|
||||
<div class="flex items-center gap-2">
|
||||
<i data-lucide="calculator" class="w-5 h-5 text-indigo-400"></i>
|
||||
<span class="font-bold">统计工具箱 v3.0 | 样本量计算器</span>
|
||||
</div>
|
||||
<button onclick="closeToolModal()" class="text-gray-400 hover:text-white">
|
||||
<i data-lucide="x" class="w-5 h-5"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Tool Body (Simulated Form) -->
|
||||
<div class="p-6 bg-gray-50">
|
||||
<div class="bg-blue-50 border border-blue-200 text-blue-800 text-xs p-3 rounded mb-4 flex gap-2">
|
||||
<i data-lucide="info" class="w-4 h-4 shrink-0"></i>
|
||||
已从 Protocol Agent 自动填充参数。修改参数后请点击“重新计算”。
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4 mb-4">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-500 mb-1">检验类型</label>
|
||||
<select class="w-full text-sm border-gray-300 rounded p-2 border">
|
||||
<option>双侧两样本均数比较</option>
|
||||
<option>卡方检验</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-500 mb-1">检验水准 (α)</label>
|
||||
<input type="number" value="0.05" class="w-full text-sm border-gray-300 rounded p-2 border">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-500 mb-1">把握度 (1-β)</label>
|
||||
<input type="number" value="0.80" class="w-full text-sm border-gray-300 rounded p-2 border">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-500 mb-1">脱落率 (%)</label>
|
||||
<input type="number" value="10" class="w-full text-sm border-gray-300 rounded p-2 border">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Effect Size Params -->
|
||||
<div class="bg-white p-3 rounded border border-gray-200 mb-4">
|
||||
<h4 class="text-xs font-bold text-gray-800 mb-2">效应量参数 (Effect Size)</h4>
|
||||
<div class="flex gap-4">
|
||||
<div class="flex-1">
|
||||
<label class="block text-[10px] text-gray-400">实验组预估发生率</label>
|
||||
<input type="number" value="0.10" class="w-full font-mono text-sm border-gray-300 rounded p-1 border">
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="block text-[10px] text-gray-400">对照组预估发生率</label>
|
||||
<input type="number" value="0.15" class="w-full font-mono text-sm border-gray-300 rounded p-1 border">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Result Area -->
|
||||
<div class="flex items-center justify-between bg-gray-100 p-4 rounded-lg mb-6">
|
||||
<span class="text-sm font-bold text-gray-600">计算结果 (N):</span>
|
||||
<span id="tool-result" class="text-2xl font-bold text-indigo-600 font-mono">---</span>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="flex justify-end gap-3">
|
||||
<button onclick="calculate()" class="px-4 py-2 bg-white border border-gray-300 text-gray-700 text-sm font-medium rounded hover:bg-gray-50">
|
||||
试算
|
||||
</button>
|
||||
<button id="btn-sync" onclick="syncAndClose()" disabled class="px-4 py-2 bg-indigo-600 text-white text-sm font-medium rounded hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2">
|
||||
<i data-lucide="refresh-cw" class="w-4 h-4"></i>
|
||||
确认并同步到方案
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// 初始化 Lucide 图标
|
||||
lucide.createIcons();
|
||||
|
||||
// Modal 控制逻辑
|
||||
const modal = document.getElementById('tool-modal');
|
||||
const modalContent = document.getElementById('tool-modal-content');
|
||||
const btnSync = document.getElementById('btn-sync');
|
||||
const toolResult = document.getElementById('tool-result');
|
||||
|
||||
function openToolModal() {
|
||||
modal.classList.remove('hidden');
|
||||
// 简单的淡入动画
|
||||
setTimeout(() => {
|
||||
modal.classList.remove('opacity-0');
|
||||
modalContent.classList.remove('scale-95');
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function closeToolModal() {
|
||||
modal.classList.add('opacity-0');
|
||||
modalContent.classList.add('scale-95');
|
||||
setTimeout(() => {
|
||||
modal.classList.add('hidden');
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// 模拟计算过程
|
||||
function calculate() {
|
||||
toolResult.innerText = "Calculing...";
|
||||
setTimeout(() => {
|
||||
toolResult.innerText = "386";
|
||||
btnSync.disabled = false;
|
||||
btnSync.classList.add('animate-pulse');
|
||||
}, 600);
|
||||
}
|
||||
|
||||
// 核心:同步回写逻辑 (Reflexion Loop)
|
||||
function syncAndClose() {
|
||||
closeToolModal();
|
||||
|
||||
// 1. 更新右侧状态面板 (State Panel Update)
|
||||
const stateCard = document.getElementById('state-sample-size');
|
||||
const nValueDisplay = document.getElementById('n-value-display');
|
||||
|
||||
// 视觉反馈:闪烁一下
|
||||
stateCard.classList.add('flash-update');
|
||||
stateCard.classList.remove('border-indigo-100');
|
||||
stateCard.classList.add('border-green-500'); // 变成绿色边框
|
||||
|
||||
// 移除 Loading 图标
|
||||
stateCard.querySelector('i').remove();
|
||||
|
||||
// 更新数值
|
||||
setTimeout(() => {
|
||||
nValueDisplay.innerText = "N = 386";
|
||||
nValueDisplay.classList.remove('text-gray-300');
|
||||
nValueDisplay.classList.add('text-indigo-600');
|
||||
}, 500);
|
||||
|
||||
// 2. 更新聊天界面 (Chat Update with Reflexion)
|
||||
const chatContainer = document.getElementById('chat-container');
|
||||
|
||||
// 插入系统消息
|
||||
const systemMsgHTML = `
|
||||
<div class="flex justify-center my-4">
|
||||
<span class="text-[10px] bg-gray-100 text-gray-500 px-2 py-1 rounded-full border border-gray-200">
|
||||
<i data-lucide="check-circle" class="w-3 h-3 inline mr-1 text-green-500"></i>
|
||||
系统消息: 用户已同步样本量结果 N=386
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
chatContainer.insertAdjacentHTML('beforeend', systemMsgHTML);
|
||||
|
||||
// 模拟 AI 思考 (Reflexion)
|
||||
setTimeout(() => {
|
||||
const aiReflexionHTML = `
|
||||
<div class="flex gap-4 animate-fade-in-up">
|
||||
<div class="w-8 h-8 rounded-full bg-purple-100 flex items-center justify-center shrink-0 border border-purple-200">
|
||||
<i data-lucide="check-check" class="w-4 h-4 text-purple-600"></i>
|
||||
</div>
|
||||
<div class="space-y-1 max-w-[80%]">
|
||||
<div class="text-xs text-purple-500 ml-1 font-bold">Reflexion Guard • 刚刚</div>
|
||||
<div class="chat-bubble-ai p-4 text-sm text-gray-800 shadow-sm reflexion-border">
|
||||
<p class="font-bold text-purple-700 text-xs mb-1 mb-2 flex items-center gap-1">
|
||||
<i data-lucide="shield-check" class="w-3 h-3"></i>
|
||||
质量校验通过
|
||||
</p>
|
||||
<p>我已校验您的计算结果:</p>
|
||||
<ul class="list-disc list-inside mt-1 text-gray-600 text-xs space-y-1">
|
||||
<li>N=386 满足 RCT 设计对统计效能 (Power=0.8) 的要求。</li>
|
||||
<li>参数设置符合心血管预防研究的常规标准。</li>
|
||||
</ul>
|
||||
<p class="mt-3">数值已同步到方案中。接下来,建议我们进行<strong>第五步:CRF (病例报告表) 设计</strong>。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
chatContainer.insertAdjacentHTML('beforeend', aiReflexionHTML);
|
||||
lucide.createIcons(); // 重新渲染新插入的图标
|
||||
|
||||
// 自动滚动到底部
|
||||
chatContainer.scrollTop = chatContainer.scrollHeight;
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// 点击遮罩关闭
|
||||
modal.addEventListener('click', (e) => {
|
||||
if (e.target === modal) closeToolModal();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user