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
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
# **提示词管理系统与生产环境灰度预览方案技术设计**
|
||||
|
||||
文档版本: v1.1
|
||||
状态: 待开发
|
||||
优先级: P1 (核心通用能力)
|
||||
适用环境: 阿里云 SAE (生产环境)
|
||||
核心架构: Postgres-Only \+ Hot Reload \+ Preview Mode \+ RBAC
|
||||
|
||||
## **1\. 核心理念:把生产环境变成调试者的“超级游乐场”**
|
||||
|
||||
传统的开发流程是 开发环境 \-\> 测试环境 \-\> 生产环境。对于大模型应用(LLM App),这种流程存在致命缺陷:**测试环境很难模拟真实的文献数据、复杂的上下文和 Token 消耗**。
|
||||
|
||||
本方案采用 **“生产环境灰度预览 (Production Preview Mode)”** 策略,并引入 **“调试者 (Debugger)”** 角色:
|
||||
|
||||
1. **代码与配置分离**:Prompt 不再是硬编码的字符串,而是数据库中的动态配置。
|
||||
2. **角色化调试 (RBAC)**:不局限于管理员,系统支持 **“调试者”**(如临床专家、Prompt 工程师)角色。只要拥有 prompt:debug 权限,即可在生产环境开启调试模式。
|
||||
3. **灰度路由**:系统根据当前操作者的身份(是否开启调试模式),动态决定加载 **“正式版 (Active)”** 还是 **“草稿版 (Draft)”** 的提示词。
|
||||
4. **真实验证**:调试者可以直接使用生产环境的真实数据(如 ASL 的 20 篇文献)来验证新 Prompt 的效果,确认无误后一键发布。
|
||||
|
||||
## **2\. 系统架构设计**
|
||||
|
||||
### **2.1 架构图**
|
||||
|
||||
graph TD
|
||||
User\[普通用户\] \--\>|请求业务| API\_Gateway
|
||||
Debugger\[调试者/专家\] \--\>|请求业务| API\_Gateway
|
||||
Debugger \--\>|管理 Prompt| Admin\_Dashboard
|
||||
|
||||
subgraph "阿里云 SAE (生产环境)"
|
||||
API\_Gateway\[Nginx\] \--\> Backend\_App
|
||||
|
||||
subgraph "Node.js Backend Pods (多实例)"
|
||||
Backend\_App\[Backend Service\]
|
||||
|
||||
PromptService\[Prompt Service\]
|
||||
MemoryCache\[内存缓存 (Map)\]
|
||||
DebugSet\[调试会话集合 (Set)\]
|
||||
|
||||
Backend\_App \--\>|1. 获取 Prompt| PromptService
|
||||
PromptService \--\>|2. 查缓存/DB| MemoryCache
|
||||
PromptService \--\>|3. 校验 Debug 权限| DebugSet
|
||||
end
|
||||
end
|
||||
|
||||
subgraph "RDS PostgreSQL"
|
||||
DB\[(Database)\]
|
||||
PlatformTable\[Users & Permissions Table\]
|
||||
PromptTable\[Prompt Versions Table\]
|
||||
|
||||
PromptService \--\>|4. 拉取 Active/Draft| DB
|
||||
Admin\_Dashboard \--\>|5. 更新/发布| DB
|
||||
DB \--\>|6. NOTIFY prompt\_update| PromptService
|
||||
end
|
||||
|
||||
### **2.2 核心特性**
|
||||
|
||||
1. **Postgres-Only**:利用 PostgreSQL 的 LISTEN/NOTIFY 机制实现多实例缓存同步,无需引入 Redis。
|
||||
2. **无状态设计**:DebugSet 和 MemoryCache 均存储在内存中,配合数据库实现最终一致性。
|
||||
3. **零侵入性**:普通用户完全感知不到 Prompt 正在被调整,只有开启了 Debug 模式的特定角色能看到变化。
|
||||
|
||||
## **3\. 数据库与权限设计**
|
||||
|
||||
### **3.1 提示词 Schema (capability\_schema)**
|
||||
|
||||
请将以下 Schema 添加到 backend/prisma/schema.prisma 的 capability\_schema 部分。
|
||||
|
||||
// \--- Prompt Management System \---
|
||||
|
||||
model PromptTemplate {
|
||||
id Int @id @default(autoincrement())
|
||||
code String @unique // 唯一标识符,如 'ASL\_SCREENING\_TitleAbstract'
|
||||
name String // 人类可读名称
|
||||
module String // 所属模块: ASL, DC, AIA, IIT
|
||||
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 // 版本号 1, 2, 3...
|
||||
content String // 提示词内容 (Handlebars/Mustache 格式)
|
||||
modelConfig Json? // 模型参数: { "temperature": 0.1, "model": "deepseek-chat" }
|
||||
status PromptStatus @default(DRAFT)
|
||||
changelog String? // 修改说明
|
||||
createdBy String? @map("created\_by") // 记录是哪个调试者修改的
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
### **3.2 权限定义 (platform\_schema)**
|
||||
|
||||
利用现有的 RBAC 系统,需要在 permissions 表中预置以下权限:
|
||||
|
||||
|
|
||||
|
||||
| 权限 Code | 描述 | 适用角色 |
|
||||
| prompt:view | 查看 Prompt 列表和详情 | 管理员, 调试者 |
|
||||
| prompt:edit | 创建草稿、修改 Draft 版本 | 管理员, 调试者 |
|
||||
| prompt:debug | 核心权限:开启/关闭调试模式 | 管理员, 调试者 |
|
||||
| prompt:publish | 将 Draft 发布为 Active | 管理员, 资深调试者 |
|
||||
建议创建一个新角色 **PROMPT\_ENGINEER**,赋予上述所有权限。
|
||||
|
||||
## **4\. 后端核心实现 (PromptService)**
|
||||
|
||||
文件路径:backend/src/common/capabilities/prompt/prompt.service.ts
|
||||
|
||||
### **4.1 核心逻辑**
|
||||
|
||||
* **setDebugMode(userId, enabled)**:
|
||||
1. **鉴权**:首先检查该 userId 是否拥有 prompt:debug 权限(通过 UserContext 或查库)。只有拥有权限的用户允许加入 Debug 集合。
|
||||
2. **状态维护**:在内存中维护 Set\<string\>,记录开启了调试模式的用户 ID。
|
||||
* **get(code, variables, userId)**:
|
||||
1. 检查 userId 是否在 debugUsers 集合中。
|
||||
2. **是**:优先查询数据库中状态为 DRAFT 的最新版本。
|
||||
3. **否**(或无 Draft):查询内存缓存中的 ACTIVE 版本。
|
||||
4. **缓存未命中**:从数据库查询 ACTIVE 版本并写入缓存。
|
||||
5. 使用 Handlebars 渲染变量。
|
||||
|
||||
### **4.2 热更新 (Hot Reload)**
|
||||
|
||||
* 监听 Postgres 的 prompt\_update 频道。
|
||||
* 收到通知后,清空内存缓存。
|
||||
|
||||
## **5\. API 接口设计**
|
||||
|
||||
### **5.1 管理端接口 (PromptController)**
|
||||
|
||||
| 方法 | 路径 | 权限要求 | 描述 |
|
||||
| GET | /api/admin/prompts | prompt:view | 获取所有 Prompt 模板列表 |
|
||||
| GET | /api/admin/prompts/:id | prompt:view | 获取特定模板详情及历史版本 |
|
||||
| POST | /api/admin/prompts/draft | prompt:edit | 保存草稿 (生成新版本,状态为 DRAFT) |
|
||||
| POST | /api/admin/prompts/publish | prompt:publish | 发布版本 (状态 Draft \-\> Active) |
|
||||
| POST | /api/admin/prompts/debug | prompt:debug | 开关调试模式 ({ enabled: true }) |
|
||||
|
||||
### **5.2 业务集成示例 (ASL 模块)**
|
||||
|
||||
在 ASL 模块中调用 Prompt 时,**必须传入 userId**,系统会自动处理灰度逻辑:
|
||||
|
||||
// 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) {
|
||||
// 动态获取 Prompt
|
||||
// 如果 userId 是开启了调试模式的“调试者”,这里会自动拿到 DRAFT 版 Prompt
|
||||
const prompt \= await promptService.get(
|
||||
'ASL\_SCREENING\_TitleAbstract',
|
||||
{ title: paper.title, abstract: paper.abstract },
|
||||
userId
|
||||
);
|
||||
|
||||
// 调用 LLM...
|
||||
return await llmGateway.chat(prompt);
|
||||
}
|
||||
}
|
||||
|
||||
## **6\. 前端管理端设计 (Frontend-V2)**
|
||||
|
||||
在 frontend-v2/src/modules/admin 下新增 Prompt 管理模块。
|
||||
|
||||
### **6.1 界面功能**
|
||||
|
||||
1. **列表页**:展示所有 Prompt 模板。
|
||||
2. **全局调试开关**:
|
||||
* **位置**:界面顶部导航栏或右下角悬浮球。
|
||||
* **权限控制**:仅当用户拥有 prompt:debug 权限时显示该开关。
|
||||
* **状态反馈**:开启后,全站顶部出现黄色警告条:“⚠️ 调试模式已开启:您当前正在使用草稿版 (DRAFT) 提示词进行操作”。
|
||||
3. **编辑器**:
|
||||
* 支持 Markdown 高亮。
|
||||
* 操作栏根据权限动态显示:如果没有 prompt:publish 权限,则“发布”按钮置灰。
|
||||
|
||||
### **6.2 典型工作流 (Workflow)**
|
||||
|
||||
1. **场景**:临床专家 Dr. Wang (角色: Debugger) 觉得文献筛选的准确率不够。
|
||||
2. **修改**:Dr. Wang 登录系统,进入 Prompt 管理页,修改 ASL\_SCREENING 的提示词,增加了一条排除标准,点击“保存草稿”。
|
||||
3. **调试**:Dr. Wang 点击顶部的 **“开启调试模式”**。
|
||||
4. **验证**:Dr. Wang 切换到 ASL 业务页面,上传几篇之前筛错的文献,点击运行。
|
||||
* *系统后端检测到 Dr. Wang 在 Debug 列表中,加载 Draft 版 Prompt。*
|
||||
5. **确认**:发现结果正确了。
|
||||
6. **发布**:Dr. Wang 回到管理页,点击“发布”(或者通知管理员发布)。
|
||||
7. **结束**:Dr. Wang 关闭调试模式。
|
||||
|
||||
## **7\. 实施计划**
|
||||
|
||||
### **Phase 1: 基础设施建设 (1-2天)**
|
||||
|
||||
1. 创建数据库表 prompt\_templates, prompt\_versions。
|
||||
2. 在 permissions 表中插入 prompt:\* 相关权限。
|
||||
3. 实现 PromptService 后端逻辑。
|
||||
|
||||
### **Phase 2: 业务模块接入 (随 ASL 开发同步)**
|
||||
|
||||
1. 在开发 ASL 模块时,通过 promptService.get() 获取 Prompt。
|
||||
|
||||
### **Phase 3: 管理端 MVP (3-4天)**
|
||||
|
||||
1. 开发前端管理界面。
|
||||
2. 实现全局调试开关组件。
|
||||
|
||||
## **8\. 安全与风控**
|
||||
|
||||
1. **权限隔离**:严格检查 prompt:debug 权限,防止普通用户误入调试模式。
|
||||
2. **审计日志**:PromptVersion 表中的 createdBy 字段必须记录实际修改人的 ID,便于追溯是哪位调试者修改了 Prompt。
|
||||
3. **兜底机制**:代码中保留 Hardcoded Prompt 作为系统级兜底。
|
||||
|
||||
## **9\. 需要配置Prompt的所有模块列表**
|
||||
|
||||
| 业务模块 | 调用场景 | 核心 Prompt 优化方向 | 复杂度 |
|
||||
| :---- | :---- | :---- | :---- |
|
||||
| **ASL (AI 智能文献)** | **1\. 标题摘要初筛** | **二分类判别**:需要极高的精准度(Recall 优先)。Prompt 需要包含明确的纳入/排除标准(PICOS),并要求输出 JSON 格式的 bool 值。 | ⭐⭐⭐⭐⭐ |
|
||||
| | **2\. 全文复筛** | **复杂信息提取**:从 PDF 提取 PICO 具体数值。Prompt 需要处理长文本(Context Window 限制),并且要有很强的抗幻觉机制(Verification)。 | ⭐⭐⭐⭐⭐ |
|
||||
| | **3\. 证据合成** | **逻辑推理**:综合多篇文献生成 Meta 分析结论。需要 Chain-of-Thought (CoT) 提示词。 | ⭐⭐⭐⭐ |
|
||||
| **DC (数据清洗)** | **1\. Tool B (双模型提取)** | **结构化抽取**:从病历文本提取字段。Prompt 需要包含医学术语定义、同义词映射规则。 | ⭐⭐⭐⭐⭐ |
|
||||
| | **2\. Tool C (数据清洗)** | **代码生成/规则判断**:如“将 A 列的文本映射为标准值”。Prompt 需要精确理解数据上下文,甚至生成 Python/JS 代码片段。 | ⭐⭐⭐⭐ |
|
||||
| | **3\. 冲突检测** | **逻辑仲裁**:判断两个模型提取结果哪个更可信。 | ⭐⭐⭐ |
|
||||
| **AIA (智能问答)** | **1\. 10+ 智能体** | **角色扮演 (Persona)**:不同的 Agent(如统计师、临床专家)需要不同的 Tone (语气) 和知识边界。 | ⭐⭐⭐ |
|
||||
| | **2\. 意图识别** | **路由分发**:判断用户是在闲聊、问诊还是查文献。 | ⭐⭐⭐ |
|
||||
| **PKB (知识库)** | **1\. RAG 问答** | **基于上下文回答**:严格限制仅根据检索到的 chunks 回答,杜绝外部知识幻觉。 | ⭐⭐⭐⭐ |
|
||||
| | **2\. 批处理阅读** | **摘要生成**:高度浓缩的学术摘要。 | ⭐⭐⭐ |
|
||||
| **IIT (IIT Manager)** | **1\. 质控检查** | **规则匹配**:根据 Protocol 检查入组数据。Prompt 需将自然语言的入排标准转化为逻辑判断。 | ⭐⭐⭐⭐⭐ |
|
||||
| | **2\. 意图识别** | **数据库查询生成**:将自然语言转为 Prisma 查询或 SQL(需极高安全性)。 | ⭐⭐⭐⭐ |
|
||||
| **RVW (稿件审查)** | **1\. 规范性检查** | **Checklist 对照**:逐条核对 CONSORT/STROBE 声明。 | ⭐⭐⭐ |
|
||||
|
||||
318
docs/03-业务模块/ADMIN-运营管理端/02-技术设计/03-Prompt管理系统快速参考.md
Normal file
318
docs/03-业务模块/ADMIN-运营管理端/02-技术设计/03-Prompt管理系统快速参考.md
Normal file
@@ -0,0 +1,318 @@
|
||||
# **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: 运营端MVP(3天)
|
||||
|
||||
- [ ] 前端管理界面(列表、编辑器、版本历史)
|
||||
- [ ] 全局调试开关组件
|
||||
- [ ] 草稿保存/发布功能
|
||||
|
||||
### 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` - 架构梳理
|
||||
|
||||
---
|
||||
|
||||
**🚀 准备开始开发了吗?**
|
||||
|
||||
235
docs/03-业务模块/ADMIN-运营管理端/02-技术设计/Prompt管理后台设计.md
Normal file
235
docs/03-业务模块/ADMIN-运营管理端/02-技术设计/Prompt管理后台设计.md
Normal file
@@ -0,0 +1,235 @@
|
||||
# **提示词管理系统与生产环境灰度预览方案技术设计**
|
||||
|
||||
文档版本: v1.1
|
||||
状态: 待开发
|
||||
优先级: P1 (核心通用能力)
|
||||
适用环境: 阿里云 SAE (生产环境)
|
||||
核心架构: Postgres-Only \+ Hot Reload \+ Preview Mode \+ RBAC
|
||||
|
||||
## **1\. 核心理念:把生产环境变成调试者的“超级游乐场”**
|
||||
|
||||
传统的开发流程是 开发环境 \-\> 测试环境 \-\> 生产环境。对于大模型应用(LLM App),这种流程存在致命缺陷:**测试环境很难模拟真实的文献数据、复杂的上下文和 Token 消耗**。
|
||||
|
||||
本方案采用 **“生产环境灰度预览 (Production Preview Mode)”** 策略,并引入 **“调试者 (Debugger)”** 角色:
|
||||
|
||||
1. **代码与配置分离**:Prompt 不再是硬编码的字符串,而是数据库中的动态配置。
|
||||
2. **角色化调试 (RBAC)**:不局限于管理员,系统支持 **“调试者”**(如临床专家、Prompt 工程师)角色。只要拥有 prompt:debug 权限,即可在生产环境开启调试模式。
|
||||
3. **灰度路由**:系统根据当前操作者的身份(是否开启调试模式),动态决定加载 **“正式版 (Active)”** 还是 **“草稿版 (Draft)”** 的提示词。
|
||||
4. **真实验证**:调试者可以直接使用生产环境的真实数据(如 ASL 的 20 篇文献)来验证新 Prompt 的效果,确认无误后一键发布。
|
||||
|
||||
## **2\. 系统架构设计**
|
||||
|
||||
### **2.1 架构图**
|
||||
|
||||
graph TD
|
||||
User\[普通用户\] \--\>|请求业务| API\_Gateway
|
||||
Debugger\[调试者/专家\] \--\>|请求业务| API\_Gateway
|
||||
Debugger \--\>|管理 Prompt| Admin\_Dashboard
|
||||
|
||||
subgraph "阿里云 SAE (生产环境)"
|
||||
API\_Gateway\[Nginx\] \--\> Backend\_App
|
||||
|
||||
subgraph "Node.js Backend Pods (多实例)"
|
||||
Backend\_App\[Backend Service\]
|
||||
|
||||
PromptService\[Prompt Service\]
|
||||
MemoryCache\[内存缓存 (Map)\]
|
||||
DebugSet\[调试会话集合 (Set)\]
|
||||
|
||||
Backend\_App \--\>|1. 获取 Prompt| PromptService
|
||||
PromptService \--\>|2. 查缓存/DB| MemoryCache
|
||||
PromptService \--\>|3. 校验 Debug 权限| DebugSet
|
||||
end
|
||||
end
|
||||
|
||||
subgraph "RDS PostgreSQL"
|
||||
DB\[(Database)\]
|
||||
PlatformTable\[Users & Permissions Table\]
|
||||
PromptTable\[Prompt Versions Table\]
|
||||
|
||||
PromptService \--\>|4. 拉取 Active/Draft| DB
|
||||
Admin\_Dashboard \--\>|5. 更新/发布| DB
|
||||
DB \--\>|6. NOTIFY prompt\_update| PromptService
|
||||
end
|
||||
|
||||
### **2.2 核心特性**
|
||||
|
||||
1. **Postgres-Only**:利用 PostgreSQL 的 LISTEN/NOTIFY 机制实现多实例缓存同步,无需引入 Redis。
|
||||
2. **无状态设计**:DebugSet 和 MemoryCache 均存储在内存中,配合数据库实现最终一致性。
|
||||
3. **零侵入性**:普通用户完全感知不到 Prompt 正在被调整,只有开启了 Debug 模式的特定角色能看到变化。
|
||||
|
||||
## **3\. 数据库与权限设计**
|
||||
|
||||
### **3.1 提示词 Schema (capability\_schema)**
|
||||
|
||||
请将以下 Schema 添加到 backend/prisma/schema.prisma 的 capability\_schema 部分。
|
||||
|
||||
// \--- Prompt Management System \---
|
||||
|
||||
model PromptTemplate {
|
||||
id Int @id @default(autoincrement())
|
||||
code String @unique // 唯一标识符,如 'ASL\_SCREENING\_TitleAbstract'
|
||||
name String // 人类可读名称
|
||||
module String // 所属模块: ASL, DC, AIA, IIT
|
||||
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 // 版本号 1, 2, 3...
|
||||
content String // 提示词内容 (Handlebars/Mustache 格式)
|
||||
modelConfig Json? // 模型参数: { "temperature": 0.1, "model": "deepseek-chat" }
|
||||
status PromptStatus @default(DRAFT)
|
||||
changelog String? // 修改说明
|
||||
createdBy String? @map("created\_by") // 记录是哪个调试者修改的
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
### **3.2 权限定义 (platform\_schema)**
|
||||
|
||||
利用现有的 RBAC 系统,需要在 permissions 表中预置以下权限:
|
||||
|
||||
| 权限 Code | 描述 | 适用角色 |
|
||||
| :---- | :---- | :---- |
|
||||
| prompt:view | 查看 Prompt 列表和详情 | 管理员, 调试者 |
|
||||
| prompt:edit | 创建草稿、修改 Draft 版本 | 管理员, 调试者 |
|
||||
| **prompt:debug** | **核心权限**:开启/关闭调试模式 | **管理员, 调试者** |
|
||||
| prompt:publish | 将 Draft 发布为 Active | 管理员, 资深调试者 |
|
||||
|
||||
建议创建一个新角色 **PROMPT\_ENGINEER**,赋予上述所有权限。
|
||||
|
||||
## **4\. 后端核心实现 (PromptService)**
|
||||
|
||||
文件路径:backend/src/common/capabilities/prompt/prompt.service.ts
|
||||
|
||||
### **4.1 核心逻辑**
|
||||
|
||||
* **setDebugMode(userId, enabled)**:
|
||||
1. **鉴权**:首先检查该 userId 是否拥有 prompt:debug 权限(通过 UserContext 或查库)。只有拥有权限的用户允许加入 Debug 集合。
|
||||
2. **状态维护**:在内存中维护 Set\<string\>,记录开启了调试模式的用户 ID。
|
||||
* **get(code, variables, userId)**:
|
||||
1. 检查 userId 是否在 debugUsers 集合中。
|
||||
2. **是**:优先查询数据库中状态为 DRAFT 的最新版本。
|
||||
3. **否**(或无 Draft):查询内存缓存中的 ACTIVE 版本。
|
||||
4. **缓存未命中**:从数据库查询 ACTIVE 版本并写入缓存。
|
||||
5. 使用 Handlebars 渲染变量。
|
||||
|
||||
### **4.2 热更新 (Hot Reload)**
|
||||
|
||||
* 监听 Postgres 的 prompt\_update 频道。
|
||||
* 收到通知后,清空内存缓存。
|
||||
|
||||
## **5\. API 接口设计**
|
||||
|
||||
### **5.1 管理端接口 (PromptController)**
|
||||
|
||||
| 方法 | 路径 | 权限要求 | 描述 |
|
||||
| :---- | :---- | :---- | :---- |
|
||||
| GET | /api/admin/prompts | prompt:view | 获取所有 Prompt 模板列表 |
|
||||
| GET | /api/admin/prompts/:id | prompt:view | 获取特定模板详情及历史版本 |
|
||||
| POST | /api/admin/prompts/draft | prompt:edit | 保存草稿 (生成新版本,状态为 DRAFT) |
|
||||
| POST | /api/admin/prompts/publish | prompt:publish | 发布版本 (状态 Draft \-\> Active) |
|
||||
| POST | /api/admin/prompts/debug | **prompt:debug** | **开关调试模式** ({ enabled: true }) |
|
||||
|
||||
### **5.2 业务集成示例 (ASL 模块)**
|
||||
|
||||
在 ASL 模块中调用 Prompt 时,**必须传入 userId**,系统会自动处理灰度逻辑:
|
||||
|
||||
// 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) {
|
||||
// 动态获取 Prompt
|
||||
// 如果 userId 是开启了调试模式的“调试者”,这里会自动拿到 DRAFT 版 Prompt
|
||||
const prompt \= await promptService.get(
|
||||
'ASL\_SCREENING\_TitleAbstract',
|
||||
{ title: paper.title, abstract: paper.abstract },
|
||||
userId
|
||||
);
|
||||
|
||||
// 调用 LLM...
|
||||
return await llmGateway.chat(prompt);
|
||||
}
|
||||
}
|
||||
|
||||
## **6\. 前端管理端设计 (Frontend-V2)**
|
||||
|
||||
在 frontend-v2/src/modules/admin 下新增 Prompt 管理模块。
|
||||
|
||||
### **6.1 界面功能**
|
||||
|
||||
1. **列表页**:展示所有 Prompt 模板。
|
||||
2. **全局调试开关**:
|
||||
* **位置**:界面顶部导航栏或右下角悬浮球。
|
||||
* **权限控制**:仅当用户拥有 prompt:debug 权限时显示该开关。
|
||||
* **状态反馈**:开启后,全站顶部出现黄色警告条:“⚠️ 调试模式已开启:您当前正在使用草稿版 (DRAFT) 提示词进行操作”。
|
||||
3. **编辑器**:
|
||||
* 支持 Markdown 高亮。
|
||||
* 操作栏根据权限动态显示:如果没有 prompt:publish 权限,则“发布”按钮置灰。
|
||||
|
||||
### **6.2 典型工作流 (Workflow)**
|
||||
|
||||
1. **场景**:临床专家 Dr. Wang (角色: Debugger) 觉得文献筛选的准确率不够。
|
||||
2. **修改**:Dr. Wang 登录系统,进入 Prompt 管理页,修改 ASL\_SCREENING 的提示词,增加了一条排除标准,点击“保存草稿”。
|
||||
3. **调试**:Dr. Wang 点击顶部的 **“开启调试模式”**。
|
||||
4. **验证**:Dr. Wang 切换到 ASL 业务页面,上传几篇之前筛错的文献,点击运行。
|
||||
* *系统后端检测到 Dr. Wang 在 Debug 列表中,加载 Draft 版 Prompt。*
|
||||
5. **确认**:发现结果正确了。
|
||||
6. **发布**:Dr. Wang 回到管理页,点击“发布”(或者通知管理员发布)。
|
||||
7. **结束**:Dr. Wang 关闭调试模式。
|
||||
|
||||
## **7\. 实施计划**
|
||||
|
||||
### **Phase 1: 基础设施建设 (1-2天)**
|
||||
|
||||
1. 创建数据库表 prompt\_templates, prompt\_versions。
|
||||
2. 在 permissions 表中插入 prompt:\* 相关权限。
|
||||
3. 实现 PromptService 后端逻辑。
|
||||
|
||||
### **Phase 2: 业务模块接入 (随 ASL 开发同步)**
|
||||
|
||||
1. 在开发 ASL 模块时,通过 promptService.get() 获取 Prompt。
|
||||
|
||||
### **Phase 3: 管理端 MVP (3-4天)**
|
||||
|
||||
1. 开发前端管理界面。
|
||||
2. 实现全局调试开关组件。
|
||||
|
||||
## **8\. 安全与风控**
|
||||
|
||||
1. **权限隔离**:严格检查 prompt:debug 权限,防止普通用户误入调试模式。
|
||||
2. **审计日志**:PromptVersion 表中的 createdBy 字段必须记录实际修改人的 ID,便于追溯是哪位调试者修改了 Prompt。
|
||||
3. **兜底机制**:代码中保留 Hardcoded Prompt 作为系统级兜底。
|
||||
|
||||
## **9\. 结论**
|
||||
|
||||
引入 **“调试者”** 角色和 RBAC 机制,使得该方案不仅是一个技术实现,更是一套完整的 **AIOps 协作流程**。它允许业务专家在不干扰线上用户的前提下,安全、独立地对 AI 效果进行调优,完美适配医疗场景对准确性的高要求。
|
||||
Reference in New Issue
Block a user