Files
AIclinicalresearch/docs/03-业务模块/AIA-AI智能问答/04-开发计划/05-一键生成研究方案开发计划.md
HaHafeng 303dd78c54 feat(aia): Protocol Agent MVP complete with one-click generation and Word export
- Add one-click research protocol generation with streaming output

- Implement Word document export via Pandoc integration

- Add dynamic dual-panel layout with resizable split pane

- Implement collapsible content for StatePanel stages

- Add conversation history management with title auto-update

- Fix scroll behavior, markdown rendering, and UI layout issues

- Simplify conversation creation logic for reliability
2026-01-25 19:16:36 +08:00

16 KiB
Raw Permalink Blame History

一键生成研究方案 - 开发计划

版本: v2.0
创建日期: 2026-01-24
最后更新: 2026-01-25
负责人: AI Assistant
状态: 开发中


一、功能概述

目标

基于 Protocol Agent 收集的 5 个核心要素,一键生成完整的临床研究方案文档,支持对话式修改和 Word 导出。

核心价值

  • 将 5-10 小时的方案撰写工作缩短至 30 分钟
  • AI 生成 + 对话式修改 + Word 精修,保证专业性和个性化
  • 输出符合伦理委员会审查要求的标准文档

技术策略No-Editor First无编辑器优先

核心洞察

用户最终会在 Word 中精修,我们的价值是 "AI 生成高质量初稿",而不是 "提供一个编辑器"


二、交互设计:对话流生成

用户流程

用户完成 5 阶段要素收集
        ↓
点击"一键生成研究方案"
        ↓
AI 在对话框中流式输出完整方案Markdown
        ↓
用户对话修改:"把样本量部分改一下..."
        ↓
AI 流式输出修改后的章节
        ↓
用户满意 → 点击"导出 Word"
        ↓
下载符合伦理委员会格式的 Word 文档

交互示意

┌─────────────────────────────────────────────────────────────┐
│  ← 返回                    全流程研究方案制定                │
├────────────────────────────────────────┬────────────────────┤
│                                        │   📋 研究方案状态   │
│   [AI] 根据您确认的信息,我已生成研究方案:  │                    │
│                                        │   ✅ 科学问题       │
│   # 1. 研究题目                         │   ✅ PICO要素       │
│   糖尿病患者使用二甲双胍与格列美脲...      │   ✅ 研究设计       │
│                                        │   ✅ 样本量         │
│   # 2. 研究背景                         │   ✅ 观察指标       │
│   2型糖尿病是全球性公共卫生问题...        │                    │
│                                        │   ────────────────  │
│   ...                                  │                    │
│                                        │   [📥 导出 Word]    │
│   ┌────────────────────────────────┐   │   [🔄 重新生成]     │
│   │ 📥 导出Word │ 🔄 修改本章节      │   │                    │
│   └────────────────────────────────┘   │                    │
│                                        │                    │
│   [用户] 把样本量从200改成300并说明原因  │                    │
│                                        │                    │
│   [AI] 好的,我已修改样本量部分:         │                    │
│   ## 6. 样本量估算                      │                    │
│   根据前期预实验数据...样本量调整为300例   │                    │
│                                        │                    │
├────────────────────────────────────────┴────────────────────┤
│  [输入消息...]                                    [发送]     │
└─────────────────────────────────────────────────────────────┘

三、研究方案结构

# 临床研究方案

## 1. 研究题目
## 2. 研究背景与立题依据
## 3. 研究目的
## 4. 研究设计
## 5. 研究对象(纳入/排除标准)
## 6. 样本量估算
## 7. 研究实施步骤与技术路线
## 8. 观察指标
## 9. 数据管理与质量控制
## 10. 安全性评价
## 11. 统计分析计划
## 12. 伦理与知情同意
## 13. 研究时间表
## 14. 参考文献

四、技术方案

架构概览

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   前端      │     │  Node.js    │     │   Python    │
│  ChatArea   │ ──▶ │  Backend    │ ──▶ │  Service    │
│             │     │             │     │  (Pandoc)   │
└─────────────┘     └─────────────┘     └─────────────┘
      │                   │                   │
      │  流式输出          │  调用 LLM         │  Markdown→Word
      │  Markdown         │  生成方案          │  格式转换
      ▼                   ▼                   ▼
┌─────────────────────────────────────────────────────┐
│                    用户下载 Word                     │
└─────────────────────────────────────────────────────┘

技术栈

前端:复用现有 ChatArea + useAIStream
├── 增加"导出 Word"按钮
├── 增加"修改本章节"交互
│
后端 (Node.js)
├── POST /api/v1/aia/protocol-agent/generate/full  # 生成完整方案
├── POST /api/v1/aia/protocol-agent/regenerate     # 重新生成指定章节
├── POST /api/v1/aia/protocol-agent/export/docx    # 导出 Word
│
后端 (Python)
├── Pandoc 集成
├── Reference Doc 模板控制样式

数据模型

-- 方案生成记录表(复用现有 protocol_generations
ALTER TABLE protocol_schema.protocol_generations ADD COLUMN IF NOT EXISTS
  sections JSONB;  -- 分章节存储,支持局部修改

-- sections 结构示例
{
  "title": "糖尿病患者使用二甲双胍...",
  "background": "2型糖尿病是全球性...",
  "objectives": "...",
  "design": "...",
  "subjects": "...",
  "sample_size": "...",
  "implementation": "...",
  "endpoints": "...",
  "data_management": "...",
  "safety": "...",
  "statistics": "...",
  "ethics": "...",
  "timeline": "...",
  "references": "..."
}

API 设计

// 生成完整方案(流式)
POST /api/v1/aia/protocol-agent/generate/full
Request: { conversationId: string }
Response: SSE 流式输出完整 Markdown

// 重新生成指定章节(流式)
POST /api/v1/aia/protocol-agent/regenerate
Request: { 
  conversationId: string,
  section: 'sample_size' | 'background' | ...,
  instruction: "把样本量从200改成300"
}
Response: SSE 流式输出该章节

// 导出 Word
POST /api/v1/aia/protocol-agent/export/docx
Request: { conversationId: string }
Response: Binary (application/vnd.openxmlformats-officedocument.wordprocessingml.document)

// 获取当前方案内容
GET /api/v1/aia/protocol-agent/generation/:conversationId
Response: { sections: {...}, fullMarkdown: "...", version: 3 }

五、核心实现

5.1 Python 微服务Pandoc 转换器

Dockerfile 增加依赖:

RUN apt-get update && apt-get install -y pandoc
RUN pip install pypandoc

Service 代码:

# python-service/app/services/doc_service.py
import pypandoc
import os

def convert_md_to_docx(markdown_text: str, output_path: str):
    # 使用参考文档控制样式(字体、字号、页眉)
    reference_doc = os.path.join(
        os.path.dirname(__file__), 
        'assets/protocol_template.docx'
    )
    
    pypandoc.convert_text(
        markdown_text,
        'docx',
        format='markdown',
        outputfile=output_path,
        extra_args=[f'--reference-doc={reference_doc}']
    )
    return output_path

API 端点:

# python-service/app/routers/doc_router.py
from fastapi import APIRouter, Response
from ..services.doc_service import convert_md_to_docx
import tempfile

router = APIRouter()

@router.post("/convert/docx")
async def convert_to_docx(request: dict):
    markdown = request.get("content", "")
    
    with tempfile.NamedTemporaryFile(suffix='.docx', delete=False) as f:
        output_path = f.name
    
    convert_md_to_docx(markdown, output_path)
    
    with open(output_path, 'rb') as f:
        content = f.read()
    
    return Response(
        content=content,
        media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
    )

5.2 Node.js 后端:导出 API

// backend/src/modules/agent/protocol/controllers/ProtocolGenerateController.ts

export class ProtocolGenerateController {
  
  // 生成完整方案
  async generateFull(request: FastifyRequest, reply: FastifyReply) {
    const { conversationId } = request.body as { conversationId: string };
    
    // 获取 Protocol Context5 阶段数据)
    const context = await this.contextService.getContext(conversationId);
    
    // 构建生成 Prompt
    const prompt = this.buildGeneratePrompt(context);
    
    // 流式生成
    const streamingService = createStreamingService(reply, {
      onChunk: async (chunk) => {
        // 保存到数据库
        await this.saveChunk(conversationId, chunk);
      }
    });
    
    await streamingService.streamGenerate([
      { role: 'system', content: this.getSystemPrompt() },
      { role: 'user', content: prompt }
    ]);
  }
  
  // 重新生成指定章节
  async regenerateSection(request: FastifyRequest, reply: FastifyReply) {
    const { conversationId, section, instruction } = request.body;
    
    const context = await this.contextService.getContext(conversationId);
    const currentGeneration = await this.getGeneration(conversationId);
    
    const prompt = `
请根据以下指令修改"${section}"章节:

用户指令:${instruction}

当前章节内容:
${currentGeneration.sections[section]}

研究背景信息:
${JSON.stringify(context)}

请输出修改后的完整章节内容Markdown 格式):
`;
    
    // 流式输出修改后的章节
    const streamingService = createStreamingService(reply);
    await streamingService.streamGenerate([
      { role: 'system', content: '你是临床研究方案撰写专家...' },
      { role: 'user', content: prompt }
    ]);
  }
  
  // 导出 Word
  async exportDocx(request: FastifyRequest, reply: FastifyReply) {
    const { conversationId } = request.body as { conversationId: string };
    
    // 获取完整 Markdown
    const generation = await this.getGeneration(conversationId);
    const markdown = this.sectionsToMarkdown(generation.sections);
    
    // 调用 Python 微服务转换
    const response = await axios.post(
      `${PYTHON_SERVICE_URL}/convert/docx`,
      { content: markdown },
      { responseType: 'arraybuffer' }
    );
    
    reply.header('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
    reply.header('Content-Disposition', 'attachment; filename="research_protocol.docx"');
    return reply.send(response.data);
  }
}

5.3 前端ChatArea 增强

// frontend-v2/src/modules/aia/protocol-agent/components/ChatArea.tsx

// 在消息气泡中增加导出按钮
const ProtocolMessageActions = ({ content, conversationId }) => {
  const [exporting, setExporting] = useState(false);
  
  const handleExport = async () => {
    setExporting(true);
    try {
      const response = await fetch('/api/v1/aia/protocol-agent/export/docx', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ conversationId })
      });
      
      const blob = await response.blob();
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = '研究方案.docx';
      a.click();
    } finally {
      setExporting(false);
    }
  };
  
  return (
    <div className="protocol-message-actions">
      <Button 
        icon={<DownloadOutlined />} 
        onClick={handleExport}
        loading={exporting}
      >
        导出 Word
      </Button>
      <Button icon={<EditOutlined />}>
        修改章节
      </Button>
    </div>
  );
};

六、开发计划

Phase 1MVP 核心功能2 天)

天数 任务 交付物
Day 1 Python 微服务集成 Pandoc /convert/docx API 可用
Day 1 Node.js 导出 API /export/docx 端点完成
Day 2 前端导出按钮 ChatArea 增加导出功能
Day 2 完整方案生成 Prompt 生成质量优化

Phase 1 交付

  • 一键生成完整研究方案Markdown
  • 导出符合格式的 Word 文档
  • 基础对话式修改

Phase 2分章节修改2 天)

天数 任务 交付物
Day 3 分章节存储模型 sections JSONB 字段
Day 3 章节重新生成 API /regenerate 端点
Day 4 前端章节选择器 点击章节触发修改对话
Day 4 版本历史 修改记录存储

Phase 2 交付

  • 分章节存储和修改
  • 智能识别修改章节
  • 版本历史追踪

Phase 3体验优化1 天)

天数 任务 交付物
Day 5 Word 模板优化 符合伦理委员会格式
Day 5 UI 美化 导出进度、预览
Day 5 测试与修复 完整功能测试

七、与编辑器方案对比

维度 无编辑器方案(当前) 编辑器方案(备选)
开发周期 5 天 10 天
维护成本 低(复用现有组件) Fork Novel
格式控制 Pandoc 精确控制 需自己处理
修改体验 对话式(稍慢) 直接编辑(更快)
用户习惯 符合Word 精修) 需适应新界面
适用场景 MVP / 快速验证 高频编辑场景

何时考虑上编辑器?

如果用户反馈以下问题,再考虑引入编辑器:

  1. "对话修改太慢,我想直接改某个字"
  2. "我需要频繁调整段落顺序"
  3. "我想同时看到多个章节并对比"

八、验收标准

功能验收

  • 点击"一键生成",对话框流式输出完整方案
  • 点击"导出 Word",下载格式正确的 docx 文件
  • 输入"修改样本量"AI 只重新生成该章节
  • Word 文档符合伦理委员会格式要求

性能指标

指标 目标
完整方案生成时间 < 2 分钟
Word 导出时间 < 5 秒
章节修改响应时间 < 30 秒

九、Word 模板设计

格式要求(伦理委员会标准)

字体:正文宋体小四,标题黑体三号
行距1.5 倍
页边距:上下 2.54cm,左右 3.17cm
页眉:研究方案 + 版本号
页脚:页码

Reference Doc 制作

  1. 在 Word 中创建符合格式的模板文档
  2. 定义样式标题1、标题2、正文、表格等
  3. 保存为 protocol_template.docx
  4. 放置到 python-service/app/services/assets/

十、后续迭代

v1.1:编辑器增强(可选)

如果用户反馈需要更直接的编辑体验:

  • 引入 Novel/Tiptap 编辑器
  • 支持实时编辑 + AI 辅助

v1.2:模板库

  • 不同研究类型的方案模板
  • RCT、队列研究、病例对照等

v1.3:协作与审核

  • 多人协作编辑
  • 方案审核流程
  • 与伦理系统对接

十一、参考文档


文档更新记录

  • 2026-01-24 v1.0: 初始版本技术选型Tiptap/BlockNote
  • 2026-01-24 v1.1: 技术选型改为 Novel (Fork)
  • 2026-01-25 v2.0: 重大调整:采用无编辑器方案,优先实现对话流生成 + Word 导出