0a9588abb7
- Add pagination support to findAll (page, limit query params) - Add findByTemplateId method to service - Add GET /by-template/:templateId endpoint to controller - Service already includes CRUD for QuestionBank and QuestionBankItem
593 lines
19 KiB
Markdown
593 lines
19 KiB
Markdown
# AuraK 评估系统完整实施计划
|
||
|
||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||
|
||
**Goal:** 构建完整的AI人才评估系统,包含题库管理、维度均衡抽取、审核流程、评估统计
|
||
|
||
**Architecture:**
|
||
- 题库通过模板间接关联知识库分组
|
||
- 评估时从题库维度均衡抽取,不足时实时生成备用
|
||
- 管理员通过独立页面管理题库和查看统计
|
||
|
||
**Tech Stack:** NestJS + TypeORM + LangGraph + React + TypeScript
|
||
|
||
---
|
||
|
||
## 一、问题与方案对照表
|
||
|
||
| # | 待修复问题 | 解决思路 | 对应Task |
|
||
|---|------------|----------|----------|
|
||
| 1 | 评分计算错误 | 已修复 | ✅ |
|
||
| 2 | 题目维度分配不均 | 已修复 | ✅ |
|
||
| 3 | 多轮对话中断 | 已修复 | ✅ |
|
||
| 4 | 计数器显示错误 | 已修复 | ✅ |
|
||
| 5 | 历史问答查询 | 统计页面 | Task 4 |
|
||
| 6 | 知识覆盖度来源 | 用户不 care | - |
|
||
| 7 | 实时反馈无内容 | 用户确认已有内容 | - |
|
||
| 8 | 预生成题目功能 | 题库+抽取 | Task 1,2,3 |
|
||
| 9 | 题目生成不稳定 | 题库前置 | Task 1,7 |
|
||
| 10 | 题目来源不是知识库 | 题库+范围控制 | Task 1,3 |
|
||
| 11 | 选择题实际无选项 | 题库管理 | Task 1,5 |
|
||
|
||
---
|
||
|
||
## 二、系统架构
|
||
|
||
### 2.1 数据层级
|
||
|
||
```
|
||
KnowledgeGroup(知识库分组)
|
||
↓
|
||
AssessmentTemplate(模板)→ 题目数量、知识库配置
|
||
↓
|
||
QuestionBank(题库)→ 审核状态
|
||
↓
|
||
QuestionBankItem(题目)→ 维度/难度/答案
|
||
↓
|
||
评估抽取使用
|
||
```
|
||
|
||
### 2.2 评估流程
|
||
|
||
```
|
||
开始评估
|
||
↓
|
||
1. 加载模板配置(题目数量、维度配置)
|
||
↓
|
||
2. 检查已发布题库题目数量
|
||
↓
|
||
充足 → 维度均衡随机抽取 → 进入答题
|
||
不足 → 实时生成题目(备用) → 进入答题
|
||
↓
|
||
3. 用户答题 → 即时评分 → 实时反馈
|
||
↓
|
||
4. 追问(如Grader判断需要)
|
||
↓
|
||
5. 答题完成 → 生成报告 + 记录统计
|
||
```
|
||
|
||
---
|
||
|
||
## 三、数据模型
|
||
|
||
### 3.1 QuestionBank(题库)
|
||
|
||
```typescript
|
||
// server/src/assessment/entities/question-bank.entity.ts
|
||
@Entity('question_banks')
|
||
export class QuestionBank {
|
||
@PrimaryGeneratedColumn('uuid')
|
||
id: string;
|
||
|
||
@Column({ name: 'template_id' })
|
||
templateId: string;
|
||
|
||
@ManyToOne(() => AssessmentTemplate)
|
||
@JoinColumn({ name: 'template_id' })
|
||
template: AssessmentTemplate;
|
||
|
||
@Column({ name: 'name' })
|
||
name: string; // 题库名称
|
||
|
||
@Column({ type: 'text', description: '题库描述' })
|
||
description: string;
|
||
|
||
@Column({ type: 'enum', enum: QuestionBankStatus, default: QuestionBankStatus.DRAFT })
|
||
status: QuestionBankStatus; // DRAFT | PENDING_REVIEW | PUBLISHED
|
||
|
||
@Column({ name: 'created_by' })
|
||
createdBy: string;
|
||
|
||
@Column({ name: 'reviewed_by', nullable: true })
|
||
reviewedBy: string;
|
||
|
||
@Column({ name: 'reviewed_at', nullable: true })
|
||
reviewedAt: Date;
|
||
|
||
@Column({ name: 'review_comment', nullable: true })
|
||
reviewComment: string; // 审核意见
|
||
|
||
@OneToMany(() => QuestionBankItem, item => item.bank)
|
||
items: QuestionBankItem[];
|
||
|
||
@CreateDateColumn({ name: 'created_at' })
|
||
createdAt: Date;
|
||
|
||
@UpdateDateColumn({ name: 'updated_at' })
|
||
updatedAt: Date;
|
||
}
|
||
|
||
enum QuestionBankStatus {
|
||
DRAFT = 'DRAFT', // 草稿
|
||
PENDING_REVIEW = 'PENDING_REVIEW', // 待审核
|
||
PUBLISHED = 'PUBLISHED', // 已发布
|
||
REJECTED = 'REJECTED', // 审核拒绝
|
||
}
|
||
```
|
||
|
||
### 3.2 QuestionBankItem(题目)
|
||
|
||
```typescript
|
||
// server/src/assessment/entities/question-bank-item.entity.ts
|
||
@Entity('question_bank_items')
|
||
export class QuestionBankItem {
|
||
@PrimaryGeneratedColumn('uuid')
|
||
id: string;
|
||
|
||
@Column({ name: 'bank_id' })
|
||
bankId: string;
|
||
|
||
@ManyToOne(() => QuestionBank, bank => bank.items)
|
||
@JoinColumn({ name: 'bank_id' })
|
||
bank: QuestionBank;
|
||
|
||
@Column({ type: 'text', name: 'question_text' })
|
||
questionText: string;
|
||
|
||
@Column({ type: 'enum', enum: QuestionType })
|
||
questionType: QuestionType; // SHORT_ANSWER | MULTIPLE_CHOICE | TRUE_FALSE
|
||
|
||
@Column({ type: 'simple-json', nullable: true })
|
||
options: string[]; // 选择题选项 ["A. xxx", "B. xxx", ...]
|
||
|
||
@Column({ type: 'text', nullable: true })
|
||
correctAnswer: string; // 正确答案
|
||
|
||
@Column({ type: 'simple-json', name: 'key_points' })
|
||
keyPoints: string[]; // 关键点 ["point1", "point2"]
|
||
|
||
@Column({ type: 'enum', enum: QuestionDifficulty })
|
||
difficulty: QuestionDifficulty; // STANDARD | ADVANCED | SPECIALIST
|
||
|
||
@Column({ type: 'enum', enum: QuestionDimension })
|
||
dimension: QuestionDimension; // PROMPT | LLM | IDE | DEV_PATTERN | WORK_CAPABILITY
|
||
|
||
@Column({ type: 'text', name: ' basis', nullable: true })
|
||
basis: string; // 出题依据
|
||
|
||
@Column({ name: 'created_by' })
|
||
createdBy: string;
|
||
|
||
@CreateDateColumn({ name: 'created_at' })
|
||
createdAt: Date;
|
||
}
|
||
|
||
enum QuestionType {
|
||
SHORT_ANSWER = 'SHORT_ANSWER', // 简答题
|
||
MULTIPLE_CHOICE = 'MULTIPLE_CHOICE', // 选择题
|
||
TRUE_FALSE = 'TRUE_FALSE', // 判断题
|
||
}
|
||
|
||
enum QuestionDifficulty {
|
||
STANDARD = 'STANDARD', // 标准
|
||
ADVANCED = 'ADVANCED', // 进阶
|
||
SPECIALIST = 'SPECIALIST', // 专家
|
||
}
|
||
|
||
enum QuestionDimension {
|
||
PROMPT = 'PROMPT', // 提示词
|
||
LLM = 'LLM', // LLM原理
|
||
IDE = 'IDE', // IDE协作
|
||
DEV_PATTERN = 'DEV_PATTERN', // 开发范式
|
||
WORK_CAPABILITY = 'WORK_CAPABILITY', // 工作能力
|
||
}
|
||
```
|
||
|
||
### 3.3 评估统计
|
||
|
||
```typescript
|
||
// API返回结构
|
||
interface AssessmentStats {
|
||
// 统计卡片
|
||
totalAttempts: number; // 总考核次数
|
||
highestScore: number; // 最高分
|
||
averageScore: number; // 平均分
|
||
completionRate: number; // 完成率
|
||
|
||
// 得分趋势(可选用于图表)
|
||
scoreTrend: { date: string; score: number }[];
|
||
|
||
// 历史记录
|
||
recentRecords: {
|
||
id: string;
|
||
knowledgeBase: string;
|
||
template: string;
|
||
score: number;
|
||
status: 'IN_PROGRESS' | 'COMPLETED';
|
||
createdAt: string;
|
||
}[];
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 四、API设计
|
||
|
||
### 4.1 题库管理API
|
||
|
||
```typescript
|
||
// 题库CRUD
|
||
POST /api/question-banks // 创建题库
|
||
GET /api/question-banks // 列表(带分页)
|
||
GET /api/question-banks/:id // 详情(含题目)
|
||
PUT /api/question-banks/:id // 更新题库信息
|
||
DELETE /api/question-banks/:id // 删除题库
|
||
|
||
// 题目管理
|
||
POST /api/question-banks/:bankId/items // 添加单题
|
||
PUT /api/question-banks/:bankId/items/:id // 更新题目
|
||
DELETE /api/question-banks/:bankId/items/:id // 删除题目
|
||
|
||
// 批量操作
|
||
POST /api/question-banks/:bankId/batch-add // 批量添加题目(AI生成或Excel导入)
|
||
POST /api/question-banks/:bankId/generate // AI批量生成待审核
|
||
|
||
// 审核流程
|
||
PUT /api/question-banks/:id/submit // 提交审核(草稿→待审核)
|
||
PUT /api/question-banks/:id/review // 审核(通过/拒绝,附带意见)
|
||
PUT /api/question-banks/:id/publish // 发布(审核通过→已发布)
|
||
PUT /api/question-banks/:id/unpublish // 下架
|
||
|
||
// 模板关联
|
||
GET /api/question-banks/by-template/:templateId // 按模板查询题库
|
||
```
|
||
|
||
### 4.2 统计API
|
||
|
||
```typescript
|
||
// 评估统计
|
||
GET /api/assessment/stats // 当前用户统计
|
||
GET /api/assessment/stats/admin // 管理员统计(所有用户)
|
||
Query: startDate, endDate, templateId, knowledgeGroupId
|
||
```
|
||
|
||
---
|
||
|
||
## 五、前端页面设计
|
||
|
||
### 5.1 题库管理页面(QuestionBankView)
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────────────┐
|
||
│ 题库管理 [新建题库] │
|
||
├────────────┬─────────────────────────────────────────────────────┤
|
||
│ 我的题库 │ 筛选: [模板▼] [状态▼] [维度▼] [难度▼] [搜索...] │
|
||
│ ├─────────────────────────────────────────────────────┤
|
||
│ □ AI开发 │ ┌────┬────────┬────────┬──────┬────────────┐ │
|
||
│ □ Python │ │选择│ 题目内容│ 题型 │ 维度 │ 难度 │ 操作│ │
|
||
│ │ ├────┼────────┼────────┼──────┼────────────┤ │
|
||
│ │ │ ○ │xxx │ 简答 │ llm │ 标准 │编辑│ │
|
||
│ │ │ ○ │xxx │ 选择 │ ide │ 进阶 │编辑│ │
|
||
│ │ │ ○ │xxx │ 判断 │ Work │ 专家 │删除│ │
|
||
│ │ └────┴────────┴────────┴──────┴────────────┘ │
|
||
│ │ [批量导入] │
|
||
│ ├─────────────────────────────────────────────────────┤
|
||
│ │ [AI批量生成] [提交审核] [全选] [取消选择] │
|
||
└────────────┴─────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 5.2 题库详情/编辑面板
|
||
|
||
```
|
||
┌────────────────────────────────────┐
|
||
│ 编辑题目 [保存] │
|
||
├────────────────────────────────────┤
|
||
│ 题目内容 │
|
||
│ ┌──────────────────────────────┐ │
|
||
│ │ │ │
|
||
│ └────────────────────────────┘ │
|
||
│ │
|
||
│ 题型: ●简答 ○选择 ○判断 │
|
||
│ │
|
||
│ [选择题时显示] │
|
||
│ 选项: │
|
||
│ A. ___________________ │
|
||
│ B. ___________________ │
|
||
│ C. ___________________ │
|
||
│ D. ___________________ │
|
||
│ │
|
||
│ 正确答案: ________________ │
|
||
│ │
|
||
│ 关键点: │
|
||
│ _________________________ │
|
||
│ _________________________ │
|
||
│ │
|
||
│ 维度: [prompt▼] 难度: [标准▼] │
|
||
│ │
|
||
│ 出题依据: │
|
||
│ _________________________ │
|
||
└────────────────────────────────────┘
|
||
```
|
||
|
||
### 5.3 统计页面(AssessmentStatsView)
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ 评估统计 [导出] │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ 筛选: [时间范围▼] [知识库▼] [重置] │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ 总考核 │ 最高分 │ 平均分 │ 完成率 │
|
||
│ 15 │ 9.2 │ 7.8 │ 80% │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ 得分趋势(折线图 - 可选) │
|
||
│ 10 ____ │
|
||
│ 8 ____▓▓▓____▓▓ │
|
||
│ 6 ____▓▓▓▓▓____▓▓▓▓___ │
|
||
│ 4 _______________________________________ │
|
||
│ 2 ____________________________________________│
|
||
│ 04/10 04/12 04/14 04/16 04/18 │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ 历史记录 │
|
||
│ 日期 知识库 模板 得分 状态 操作│
|
||
│ 04/18 AI开发 AI基础 9.2 完成 查看 │
|
||
│ 04/15 Python 编程基础 7.5 完成 查看 │
|
||
│ 04/12 AI开发 AI基础 8.1 完成 查看 │
|
||
│ 04/10 - LLM原理 - 进行中 查看 │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 六、实施计划
|
||
|
||
### Task 1: 题库管理功能(核心)
|
||
|
||
**Files:**
|
||
- Create: `server/src/assessment/entities/question-bank.entity.ts`
|
||
- Create: `server/src/assessment/entities/question-bank-item.entity.ts`
|
||
- Create: `server/src/assessment/question-bank.service.ts`
|
||
- Create: `server/src/assessment/question-bank.controller.ts`
|
||
- Modify: `server/src/assessment/assessment.module.ts` (import)
|
||
- Create: 迁移文件 `add_question_banks.sql`
|
||
|
||
**实施步骤:**
|
||
|
||
1. 创建 QuestionBank 实体 + 迁移
|
||
2. 创建 QuestionBankItem 实体 + 迁移
|
||
3. 实现 QuestionBankService(CRUD)
|
||
4. 实现 QuestionBankController(API)
|
||
5. 注册模块
|
||
|
||
**验收标准:**
|
||
- [ ] 可以创建题库
|
||
- [ ] 可以添加/编辑/删除题目
|
||
- [ ] 可以设置题目维度/难度/答案
|
||
- [ ] 支持审核流程(草稿→待审核→发布)
|
||
|
||
---
|
||
|
||
### Task 2: AI批量生成
|
||
|
||
**目标:** 调用AI批量生成题目,待人工审核
|
||
|
||
**Files:**
|
||
- Modify: `server/src/assessment/question-bank.service.ts` (generate)
|
||
- Modify: `server/src/assessment/graph/nodes/generator.node.ts` (复用)
|
||
|
||
**实施步骤:**
|
||
|
||
1. 实现批量生成逻辑
|
||
2. 调用generator node生成题目
|
||
3. 保存为草稿状态
|
||
4. 提供审核界面
|
||
|
||
**验收标准:**
|
||
- [ ] 点击生成按钮,调用AI生成题目
|
||
- [ ] 生成的题目进入草稿状态
|
||
- [ ] 可以批量审核通过
|
||
|
||
---
|
||
|
||
### Task 3: 题目抽取逻��
|
||
|
||
**目标:** 评估时从题库维度均衡随机抽取
|
||
|
||
**Files:**
|
||
- Modify: `server/src/assessment/question-bank.service.ts` (selectQuestions)
|
||
|
||
**实施步骤:**
|
||
|
||
1. 实现维度均衡抽取算法
|
||
2. 处理题目不足情况
|
||
3. 单元测试
|
||
|
||
**验收标准:**
|
||
- [ ] 抽取的题目维度大致均衡
|
||
- [ ] 不重复抽取同一题目
|
||
- [ ] 数量不足时有补充逻辑
|
||
|
||
---
|
||
|
||
### Task 4: 评估接入题库
|
||
|
||
**目标:** 评估优先使用题库题目
|
||
|
||
**Files:**
|
||
- Modify: `server/src/assessment/assessment.service.ts` (startSession)
|
||
|
||
**实施步骤:**
|
||
|
||
1. 修改startSession逻辑
|
||
2. 先查询题库
|
||
3. 题库不足时使用实时生成
|
||
4. 测试完整流程
|
||
|
||
**验收标准:**
|
||
- [ ] 有题库时优先从题库抽取
|
||
- [ ] 题库不足时使用实时生成
|
||
- [ ] 两者都可正常工作
|
||
|
||
---
|
||
|
||
### Task 5: 统计页面
|
||
|
||
**目标:** 独立统计页面
|
||
|
||
**Files:**
|
||
- Create: `server/src/assessment/assessment.controller.ts` (stats API)
|
||
- Create: `web/src/services/assessmentStatsService.ts`
|
||
- Create: `web/components/views/AssessmentStatsView.tsx`
|
||
- Modify: `web/index.tsx` (路由)
|
||
- Modify: `web/components/layouts/WorkspaceLayout.tsx` (侧边栏)
|
||
|
||
**验收标准:**
|
||
- [ ] 统计卡片显示正确
|
||
- [ ] 支持时间筛选
|
||
- [ ] 管理员可查看所有用户
|
||
- [ ] 历史记录表格完整
|
||
|
||
---
|
||
|
||
### Task 6: 选择题渲染
|
||
|
||
**目标:** 前端支持选择题渲染
|
||
|
||
**Files:**
|
||
- Modify: `web/components/views/AssessmentView.tsx`
|
||
|
||
**验收标准:**
|
||
- [ ] 选择题显示选项按钮
|
||
- [ ] 点击选项提交答案
|
||
|
||
---
|
||
|
||
### Task 7: 判断题渲染
|
||
|
||
**目标:** 前端支持判断题渲染
|
||
|
||
**Files:**
|
||
- Modify: `web/components/views/AssessmentView.tsx`
|
||
|
||
**验收标准:**
|
||
- [ ] 判断题显示True/False按钮
|
||
- [ ] 点击提交答案
|
||
|
||
---
|
||
|
||
### Task 8: 稳定性优化
|
||
|
||
**目标:** 提高AI生成稳定性
|
||
|
||
**Files:**
|
||
- Modify: `server/src/assessment/graph/nodes/generator.node.ts`
|
||
|
||
**实施步骤:**
|
||
|
||
1. 添加重试逻辑
|
||
2. 优化prompt
|
||
3. 错误处理
|
||
|
||
---
|
||
|
||
## 七、执行顺序
|
||
|
||
```
|
||
Task 1 (题库管理)
|
||
↓
|
||
Task 2 (AI批量生成)
|
||
↓
|
||
Task 3 (抽取逻辑)
|
||
↓
|
||
Task 4 (评估接入)
|
||
↓
|
||
Task 5 (统计页面)
|
||
↓
|
||
Task 6 (选择题)
|
||
↓
|
||
Task 7 (判断题)
|
||
↓
|
||
Task 8 (稳定性)
|
||
```
|
||
|
||
---
|
||
|
||
## 八、技术要点
|
||
|
||
### 8.1 维度均衡算法
|
||
|
||
```typescript
|
||
// 伪代码
|
||
function selectQuestions(bankId: string, count: number): Question[] {
|
||
const allItems = getPublishedItems(bankId);
|
||
const dimensions = ['prompt', 'llm', 'ide', 'devPattern', 'workCapability'];
|
||
const selected: Question[] = [];
|
||
const usedIds = new Set<string>();
|
||
|
||
// 轮询从各维度选取
|
||
let dimIdx = 0;
|
||
while (selected.length < count && dimIdx < count * dimensions.length) {
|
||
const dim = dimensions[dimIdx % dimensions.length];
|
||
const available = allItems.filter(
|
||
(i) => i.dimension === dim && !usedIds.has(i.id)
|
||
);
|
||
|
||
if (available.length > 0) {
|
||
const random = available[Math.floor(Math.random() * available.length)];
|
||
selected.push(random);
|
||
usedIds.add(random.id);
|
||
}
|
||
dimIdx++;
|
||
}
|
||
|
||
// 补充不足的题目(随机)
|
||
if (selected.length < count) {
|
||
const remaining = allItems.filter((i) => !usedIds.has(i.id));
|
||
// ... 随机补充
|
||
}
|
||
|
||
return selected;
|
||
}
|
||
```
|
||
|
||
### 8.2 审核工作流
|
||
|
||
```
|
||
草稿(DRAFT) → 提交审核 → 待审核(PENDING_REVIEW)
|
||
↓
|
||
审核通过 → 已发布(PUBLISHED)
|
||
↓
|
||
审核拒绝 → 草稿(DRAFT) + 意见
|
||
```
|
||
|
||
---
|
||
|
||
## 九、注意事项
|
||
|
||
1. **权限控制**:题库管理、统计只对管理员开放
|
||
2. **数据隔离**:用户只能看到自己的评估记录,管理员可见所有
|
||
3. **维度映射**:确保题目维度与评估维度一致
|
||
4. **题库状态**:只有已发布的题目才能被抽取
|
||
5. **回退机制**:题库不足时使用实时生成作为备用
|
||
|
||
---
|
||
|
||
## Plan Complete
|
||
|
||
**Two execution options:**
|
||
|
||
**1. Subagent-Driven (this session)** - 继续在此会话,使用 subagent 逐个执行任务
|
||
|
||
**2. Parallel Session (separate)** - 开新会话使用 executing-plans,分批执行
|
||
|
||
**Which approach?** |