Files
AIclinicalresearch/docs/03-业务模块/ADMIN-运营管理端/02-技术设计/03-Prompt管理系统快速参考.md
HaHafeng 5523ef36ea feat(admin): Complete Phase 3.5.1-3.5.4 Prompt Management System (83%)
Summary:
- Implement Prompt management infrastructure and core services
- Build admin portal frontend with light theme
- Integrate CodeMirror 6 editor for non-technical users

Phase 3.5.1: Infrastructure Setup
- Create capability_schema for Prompt storage
- Add prompt_templates and prompt_versions tables
- Add prompt:view/edit/debug/publish permissions
- Migrate RVW prompts to database (RVW_EDITORIAL, RVW_METHODOLOGY)

Phase 3.5.2: PromptService Core
- Implement gray preview logic (DRAFT for debuggers, ACTIVE for users)
- Module-level debug control (setDebugMode)
- Handlebars template rendering
- Variable extraction and validation (extractVariables, validateVariables)
- Three-level disaster recovery (database -> cache -> hardcoded fallback)

Phase 3.5.3: Management API
- 8 RESTful endpoints (/api/admin/prompts/*)
- Permission control (PROMPT_ENGINEER can edit, SUPER_ADMIN can publish)

Phase 3.5.4: Frontend Management UI
- Build admin portal architecture (AdminLayout, OrgLayout)
- Add route system (/admin/*, /org/*)
- Implement PromptListPage (filter, search, debug switch)
- Implement PromptEditor (CodeMirror 6 simplified for clinical users)
- Implement PromptEditorPage (edit, save, publish, test, version history)

Technical Details:
- Backend: 6 files, ~2044 lines (prompt.service.ts 596 lines)
- Frontend: 9 files, ~1735 lines (PromptEditorPage.tsx 399 lines)
- CodeMirror 6: Line numbers, auto-wrap, variable highlight, search, undo/redo
- Chinese-friendly: 15px font, 1.8 line-height, system fonts

Next Step: Phase 3.5.5 - Integrate RVW module with PromptService

Tested: Backend API tests passed (8/8), Frontend pending user testing
Status: Ready for Phase 3.5.5 RVW integration
2026-01-11 21:25:16 +08:00

319 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# **Prompt管理系统快速参考**
> **版本:** v1.0
> **优先级:** P0核心通用能力
> **状态:** 待开发
---
## 📌 核心概念
### 什么是Prompt管理系统
一个允许**专业人员在生产环境安全调试AI Prompt**的灰度预览系统。
### 为什么需要它?
-**痛点1** 测试环境无法模拟真实医学数据20篇文献、真实病历
-**痛点2** 每次调整Prompt需要改代码→部署→等待5分钟
-**痛点3** 临床专家无法参与调试(他们不会写代码)
-**解决:** 生产环境灰度预览 + 调试者角色 + DRAFT/ACTIVE版本隔离
---
## 🗂️ 数据库Schema
### 位置:`capability_schema`
```prisma
// --- Prompt Management System ---
model PromptTemplate {
id Int @id @default(autoincrement())
code String @unique // 'ASL_SCREENING_TitleAbstract'
name String // "ASL标题摘要筛选"
module String // ASL, DC, IIT, AIA, PKB, RVW
description String?
variables Json? // ["title", "abstract"]
versions PromptVersion[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("prompt_templates")
@@schema("capability_schema")
}
model PromptVersion {
id Int @id @default(autoincrement())
templateId Int @map("template_id")
version Int // 版本号
content String @db.Text // Prompt内容
modelConfig Json? // {"temperature": 0.1}
status PromptStatus @default(DRAFT)
changelog String? // "增加了排除标准"
createdBy String? @map("created_by") // UserID审计
template PromptTemplate @relation(fields: [templateId], references: [id])
createdAt DateTime @default(now()) @map("created_at")
@@map("prompt_versions")
@@schema("capability_schema")
@@index([templateId, status])
}
enum PromptStatus {
DRAFT // 草稿仅Debug模式可见
ACTIVE // 生产版本
ARCHIVED // 归档
@@schema("capability_schema")
}
```
---
## 🔐 权限与角色
### 新增权限
| 权限 Code | 描述 | 适用角色 |
|-----------|------|---------|
| `prompt:view` | 查看Prompt列表和历史 | SUPER_ADMIN, PROMPT_ENGINEER |
| `prompt:edit` | 创建/修改DRAFT版本 | SUPER_ADMIN, PROMPT_ENGINEER |
| `prompt:debug` | ⭐ **开启调试模式** | SUPER_ADMIN, PROMPT_ENGINEER |
| `prompt:publish` | 发布DRAFT→ACTIVE | SUPER_ADMIN, PROMPT_ENGINEER |
### 新增角色
```typescript
enum UserRole {
SUPER_ADMIN = 'SUPER_ADMIN',
PROMPT_ENGINEER = 'PROMPT_ENGINEER', // 🆕 核心角色
HOSPITAL_ADMIN = 'HOSPITAL_ADMIN',
PHARMA_ADMIN = 'PHARMA_ADMIN',
USER = 'USER'
}
```
---
## 🚀 核心API
### 管理端接口
| 方法 | 路径 | 权限 | 描述 |
|------|------|------|------|
| GET | `/api/admin/prompts` | prompt:view | 获取所有模板 |
| GET | `/api/admin/prompts/:id` | prompt:view | 获取详情+历史版本 |
| POST | `/api/admin/prompts/draft` | prompt:edit | 保存草稿 |
| POST | `/api/admin/prompts/publish` | prompt:publish | 发布 |
| POST | `/api/admin/prompts/debug` | prompt:debug | **开关调试模式** |
### 业务模块集成
```typescript
// backend/src/modules/asl/services/screening.service.ts
import { promptService } from '@/common/capabilities/prompt/prompt.service';
export class ScreeningService {
async screenPaper(paper: any, userId: string) {
// 🎯 核心调用:自动处理灰度逻辑
const prompt = await promptService.get(
'ASL_SCREENING_TitleAbstract',
{ title: paper.title, abstract: paper.abstract },
userId // ⭐ 必须传入userId
);
return await llmGateway.chat(prompt);
}
}
```
---
## 🎨 前端组件
### 全局调试开关
```tsx
// frontend-v2/src/modules/admin/components/PromptDebugSwitch.tsx
export const PromptDebugSwitch = () => {
const { hasPermission } = usePermission();
const [debugMode, setDebugMode] = useState(false);
if (!hasPermission('prompt:debug')) {
return null; // 🔒 权限控制
}
return (
<>
<Switch
checked={debugMode}
onChange={(enabled) => api.post('/api/admin/prompts/debug', { enabled })}
checkedChildren="🐛 调试模式"
unCheckedChildren="生产模式"
/>
{debugMode && (
<Alert
type="warning"
message="⚠️ 调试模式已开启您当前正在使用草稿版DRAFT提示词"
banner
/>
)}
</>
);
};
```
---
## 📋 涉及模块
| 模块 | 核心场景 | 复杂度 | 优先级 |
|------|---------|-------|--------|
| **ASL** | 标题摘要初筛、全文复筛、证据合成 | ⭐⭐⭐⭐⭐ | P0 |
| **DC** | Tool B提取、Tool C清洗、冲突检测 | ⭐⭐⭐⭐⭐ | P0 |
| **IIT** | 质控检查、意图识别 | ⭐⭐⭐⭐⭐ | P1 |
| **PKB** | RAG问答、批处理阅读 | ⭐⭐⭐⭐ | P1 |
| **AIA** | 10+智能体、意图识别 | ⭐⭐⭐ | P2 |
| **RVW** | 规范性检查 | ⭐⭐⭐ | P2 |
---
## ⚙️ 核心逻辑PromptService
```typescript
// backend/src/common/capabilities/prompt/prompt.service.ts
export class PromptService {
private debugUsers = new Set<string>(); // 内存存储调试用户
private activeCache = new Map<string, string>(); // ACTIVE版本缓存
// 设置调试模式
async setDebugMode(userId: string, enabled: boolean) {
if (enabled) {
this.debugUsers.add(userId);
} else {
this.debugUsers.delete(userId);
}
}
// 获取Prompt灰度核心
async get(code: string, variables: any, userId: string): Promise<string> {
// 1. 调试者优先获取DRAFT版本
if (this.debugUsers.has(userId)) {
const draft = await this.getDraftVersion(code);
if (draft) {
return this.render(draft.content, variables);
}
}
// 2. 普通用户获取ACTIVE版本带缓存
let active = this.activeCache.get(code);
if (!active) {
const version = await prisma.promptVersion.findFirst({
where: {
template: { code },
status: 'ACTIVE'
},
orderBy: { version: 'desc' }
});
active = version?.content || this.getFallback(code);
this.activeCache.set(code, active);
}
return this.render(active, variables);
}
// Postgres LISTEN/NOTIFY 热更新
async initHotReload() {
const client = await pool.connect();
await client.query('LISTEN prompt_update');
client.on('notification', (msg) => {
this.activeCache.clear(); // 清空缓存
});
}
}
```
---
## 📅 开发计划
### Phase 0: 基础设施2天
- [ ] 创建数据库表(`prompt_templates`, `prompt_versions`
- [ ] 添加`prompt:*`权限到`platform_schema.permissions`
- [ ] 创建`PROMPT_ENGINEER`角色
- [ ] 实现`PromptService`核心逻辑
### Phase 1: 运营端MVP3天
- [ ] 前端管理界面(列表、编辑器、版本历史)
- [ ] 全局调试开关组件
- [ ] 草稿保存/发布功能
### Phase 2: 业务模块接入(随业务开发)
- [ ] ASL模块调用`promptService.get()`
- [ ] DC模块调用`promptService.get()`
- [ ] 其他模块按需接入
---
## 🔒 安全与风控
### 权限隔离
- ✅ 严格检查`prompt:debug`权限
- ✅ 调试模式状态存储在内存(登出自动失效)
### 审计日志
-`PromptVersion.createdBy`记录修改人
-`AdminOperationLog`记录发布行为module='prompt'
### 兜底机制
- ✅ 代码中保留Hardcoded Prompt作为系统级兜底
- ✅ 数据库查询失败时返回默认版本
---
## 🎯 典型工作流
1. **场景:** 临床专家Dr. Wang觉得ASL文献筛选准确率不够
2. **修改:** Dr. Wang登录运营管理端修改`ASL_SCREENING`的Prompt增加排除标准保存草稿
3. **调试:** Dr. Wang点击顶部的"开启调试模式"
4. **验证:** Dr. Wang切换到ASL业务页面上传几篇之前筛错的文献
*→ 系统后端检测到Dr. Wang在Debug列表中加载DRAFT版Prompt*
5. **确认:** 发现结果正确了
6. **发布:** Dr. Wang回到管理页点击"发布"
7. **结束:** Dr. Wang关闭调试模式
---
## 📚 相关文档
- `02-通用能力层_07-运营与机构管理端PRD_v2.1.md` - 总体需求
- `02-通用能力层_03-Prompt管理系统与灰度预览设计方案.md` - 详细设计
- `00-权限与角色体系梳理报告_v1.0.md` - 架构梳理
---
**🚀 准备开始开发了吗?**