Inventory: 17 AI workflows cataloged. 6 migrated, 4 in M-AI-08 scope, 5 deferred, 2 legacy pending retirement. Confirmed M-AI-08 as final core business migration milestone. Contract: 4 Runtime job types (learning_state/weak_point/next_action/ flashcard) to be merged into unified learning_analysis Job. Data source matrix, snapshot schema, evidence schema, topology frozen. Co-Authored-By: Claude <noreply@anthropic.com>
15 KiB
15 KiB
M-AI-08 学习综合分析迁移契约
审计日期:2026-06-22 契约状态:冻结(待 M-AI-08-01 验收) 对应里程碑:M-AI-08 学习综合分析、学习建议与 AI 迁移闭环
目录
- 当前链路审计
- 目标链路
- 数据源矩阵
- 聚合窗口
- Snapshot Schema
- Output Schema
- Evidence Schema
- 触发模型
- 幂等契约
- Artifact 矩阵
- 权限与隐私
- Feature Flag
- 回滚流程
- 架构异常与不确定项
1. 当前链路审计
1.1 四种 Runtime 作业类型
| Job Type | 产出实体 | promptVersion | outputSchemaVersion | 现状 |
|---|---|---|---|---|
learning_state_analysis |
AiLearningAnalysis | learning_state_v1 | analysis_output_v1 | Runtime 轮询 |
weak_point_analysis |
WeakPointCandidate | weak_point_v1 | weak_point_output_v1 | Runtime 轮询 |
next_action_planning |
NextActionRecommendation | next_action_v1 | next_action_output_v1 | Runtime 轮询 |
flashcard_generation |
Flashcard | flashcard_gen_v1 | flashcard_output_v1 | Runtime 轮询 |
1.2 当前时序(Runtime 轮询路径)
POST /api/ai/jobs { jobType: "learning_state_analysis", targetType, targetId }
→ UserAiService.createAnalysisJob()
`src/modules/ai-runtime/user-ai.service.ts:199`
├─ settings 检查 (:201-206)
├─ jobType 验证 (:210-214)
├─ 幂等检查 (:225-233)
├─ 配额+预算 (:252-267)
├─ SnapshotBuilderService.buildSnapshot() (:270)
│ `src/modules/ai-runtime/snapshot-builder.service.ts:75`
│ ├─ fetchBehaviorData() — DailyLearningActivity, LearningSession
│ ├─ aggregateProgress() — MaterialReadingProgress
│ ├─ aggregateContent() — KnowledgeItem(可选)
│ ├─ calculateScores() — Quiz/Review/ActiveRecall/Feynman metrics
│ ├─ computeSignals() — engagement/consistency/streaks/patterns
│ └─ buildDeviceContext() — 平台/时区/设备
├─ PriorityRulesService.computeJobPriority() (:279)
└─ aiRuntimeJob.create (:282-299)
外部 Runtime 轮询
→ POST /internal/runtime/jobs/poll → pollJobs() (:22)
→ POST /internal/runtime/jobs/:id/lock → lockJob() (:85)
→ GET /internal/runtime/jobs/:id/snapshot → getSnapshot() (:153)
→ Runtime 执行 AI 调用(prompt/schema 外部管理)
→ POST /internal/runtime/jobs/:id/result → submitResult() (:220)
└─ persistResult() (:286)
├─ learning_state_analysis → AiLearningAnalysis.create (:295-311)
├─ weak_point_analysis → WeakPointCandidate.create (:313-337)
└─ next_action_planning → NextActionRecommendation.create (:339-365)
1.3 数据模型
AiLearningAnalysis (schema.prisma:2173-2194):
id, userId, jobId, snapshotId, targetType, targetId,
learningState, summary, riskLevel, confidence, evidence (Json),
nextActionIds (Json), promptVersion, schemaVersion
WeakPointCandidate (schema.prisma:2198-2216):
id, userId, jobId, snapshotId, targetType, targetId,
knowledgePointId, title, reason, confidence, evidence (Json),
status (active/resolved)
NextActionRecommendation (schema.prisma:2220-2239):
id, userId, jobId, snapshotId, actionType, targetType, targetId,
title, reason, priority, estimatedMinutes, deviceSuitability,
status (active/resolved)
LearningAnalysisSnapshot (schema.prisma:2058-2083):
id, userId, scopeType, scopeId, snapshotVersion, sourceDataVersion,
privacyScope, userProfile, aiSettings, deviceContext,
learningBehaviorSummary, materialProgressSummary, contentStructureSummary,
behaviorSignals, scoreSignals, constraints, allowedModelFields
1.4 拓扑(冻结)
审计确认:learning_state_analysis、weak_point_analysis、next_action_planning 三者各自独立调用模型,由外部 Runtime 分别执行。
M-AI-08 迁移决策:将三者合并为一个 learning_analysis Job,一次模型调用同时产出综合分析 + 薄弱点 + 建议。
单一 learning_analysis Job
→ 一次 AiGateway 调用
→ LearningAnalysisProjector
→ AiLearningAnalysis(综合分析)
→ WeakPointCandidate × N(薄弱点)
→ NextActionRecommendation × N(建议)
→ AiJobArtifact × N
flashcard_generation 保持独立(不属于"学习分析"范畴)。
1.5 数据来源分类
| 数据 | 来源 | 可信度 | Snapshot 处理 |
|---|---|---|---|
| userId | JWT | 可信 | 直接包含 |
| learningGoal | UserLearningProfile | 可信 | 直接包含 |
| dailyAvailableMinutes | UserLearningProfile | 可信 | 聚合 |
| qualityPreference | UserAiSettings | 可信 | 直接包含 |
| 学习时长 | DailyLearningActivity | 可信 | 仅聚合后进入 |
| 活跃天数 | DailyLearningActivity | 可信 | 聚合指标 |
| 复习完成率 | ReviewCard + ReviewLog | 可信 | 聚合指标 |
| Quiz 正确率 | QuizAttempt | 可信 | 聚合指标 |
| Active Recall 表现 | AiAnalysisResult | 可信 | 聚合指标 |
| Feynman 弱点 | FocusItem + AiAnalysisResult | 可信 | 聚合指标 |
| 知识点进度 | KnowledgeItem + MaterialReadingProgress | 可信 | 列表(限量+截断) |
| 设备/时区 | DeviceContext(服务端推断) | 可信 | 直接包含 |
| 学习时长(客户端声明) | — | 不可信 | 禁止进入 |
| 掌握度(客户端声明) | — | 不可信 | 禁止进入 |
| JWT / API Key | Request Header | — | 禁止进入 |
| 完整对话历史 | — | — | 禁止进入 |
1.6 副作用矩阵
| 副作用 | 当前 | Unified |
|---|---|---|
| 配额消耗 | quota.incrementJobCount | 保持 |
| UsageLog | Runtime 记录 | Engine 记录 |
| 更新用户画像 | 否 | 否 |
| 更新知识点掌握度 | 否 | 否 |
| 创建通知 | 否 | 否 |
| 自动生成复习卡 | 否 | 否 |
| 自动执行建议 | 否 | 否(禁止) |
| Snapshot 创建 | SnapshotBuilderService | SnapshotBuilder(复用) |
2. 目标链路
手动/定时触发
→ LearningAnalysisExecutionRouter
├─ [legacy] → UserAiService.createAnalysisJob()
└─ [unified] →
LearningAnalysisSnapshotBuilder.build()
→ AiJobCreationService.createJob()
→ Job + Snapshot + Outbox
→ BullMQ (ai-background)
→ Worker → AiJobExecutionEngine
EXECUTE: LearningAnalysisExecutor (AiGateway)
VALIDATE: SchemaValidator + EvidenceValidator + BusinessValidator
PROJECT: LearningAnalysisProjector
→ AiLearningAnalysis + WeakPointCandidate × N
+ NextActionRecommendation × N + Artifact
→ markSucceeded
3. 数据源矩阵
| 数据源 | Prisma 模型 | Snapshot 包含方式 |
|---|---|---|
| 用户学习目标 | UserLearningProfile | 直接字段 |
| AI 设置 | UserAiSettings | 直接字段 |
| 每日学习活动 | DailyLearningActivity | 聚合(totalDuration/activeDays/sessionCount) |
| 学习会话 | LearningSession | 聚合(avgSessionDuration/completionRate) |
| 阅读进度 | MaterialReadingProgress | 列表(限量 50,仅标题+进度) |
| 知识项 | KnowledgeItem | 列表(限量 200,仅标题+摘要) |
| 复习记录 | ReviewCard + ReviewLog | 聚合(dueCount/completedCount/accuracy/overdue) |
| Quiz 结果 | QuizAttempt + QuizAnswer | 聚合(accuracy/byType/byKnowledgeItem) |
| Active Recall | AiAnalysisResult | 聚合(count/avgScore/weaknesses) |
| Feynman 评估 | AiAnalysisResult + FocusItem | 聚合(count/weaknesses/focusItems) |
| 设备上下文 | 服务端推断 | 直接字段(platform/timezone) |
| 连续学习 | StreakRecord | 聚合指标 |
4. 聚合窗口
| 参数 | 默认值 | 说明 |
|---|---|---|
| windowStart | 请求时确定 | Snapshot 固定,不漂移 |
| windowEnd | 请求时确定 | 与 windowStart 配对 |
| timezone | 服务端推断 | 用户设备时区 |
| sourceCutoffAt | 请求时 | 数据截止时间 |
| aggregationVersion | 语义版本 | 算法版本,变化时重新分析 |
| 行为窗口 | 7 天 | 学习行为数据 |
| 成绩窗口 | 30 天 | Quiz/复习/Active Recall 成绩 |
5. Snapshot Schema
interface LearningAnalysisSnapshot {
schemaVersion: string; // "learning-analysis-v1"
snapshot: {
userId: string;
triggerType: 'manual' | 'scheduled';
operationId: string;
windowStart: string; // ISO8601
windowEnd: string;
timezone: string; // IANA
aggregationVersion: string;
sourceCutoffAt: string;
learningGoal?: string;
qualityPreference?: string;
dailyAvailableMinutes?: number;
studyMetrics: {
totalStudyDuration: number;
activeDays: number;
sessionCount: number;
averageSessionDuration: number;
completionRate: number;
};
reviewMetrics: {
reviewDueCount: number;
reviewCompletedCount: number;
reviewAccuracy: number;
overdueCount: number;
retentionTrend: number; // -1 to 1
};
quizMetrics: {
quizCount: number;
attemptCount: number;
accuracy: number;
accuracyByQuestionType: Record<string, number>;
};
activeRecallMetrics: {
count: number;
avgScore: number;
weaknessCount: number;
};
feynmanMetrics: {
count: number;
weaknessCount: number;
focusItemCount: number;
};
knowledgeProgress: {
totalItems: number;
completedItems: number;
inProgressItems: number;
weakItems: Array<{ id: string; title: string }>;
};
dataQuality: {
availableSources: string[];
missingSources: string[];
sampleSize: number;
coverageStart?: string;
coverageEnd?: string;
insufficientDataReasons: string[];
};
promptKey: string;
promptVersion: string;
modelTier: string;
inputSchemaVersion: string;
outputSchemaVersion: string;
createdAt: string;
};
}
6. Output Schema
interface LearningAnalysisOutput {
summary: string;
strengths: Array<{
title: string;
description: string;
evidenceRefs: EvidenceRef[];
}>;
weaknesses: Array<{
title: string;
description: string;
knowledgePointId?: string;
evidenceRefs: EvidenceRef[];
}>;
trends: Array<{
metricKey: string;
direction: 'improving' | 'declining' | 'stable';
description: string;
evidenceRefs: EvidenceRef[];
}>;
risks: Array<{
title: string;
severity: 'low' | 'medium' | 'high';
description: string;
evidenceRefs: EvidenceRef[];
}>;
recommendations: Array<{
actionType: string;
title: string;
reason: string;
priority: number;
estimatedMinutes?: number;
targetType?: string;
targetId?: string;
evidenceRefs: EvidenceRef[];
}>;
confidence: number; // 0.0-1.0
dataQuality: {
overall: 'sufficient' | 'limited' | 'insufficient';
};
insufficientData: boolean;
}
7. Evidence Schema
每个结论必须附带 evidenceRefs:
interface EvidenceRef {
sourceType: 'study_metric' | 'review_metric' | 'quiz_metric'
| 'active_recall' | 'feynman' | 'knowledge_progress';
metricKey: string; // e.g. "reviewAccuracy", "quizAccuracy"
entityId?: string; // knowledgeItemId / quizId / analysisResultId
windowStart: string;
windowEnd: string;
}
8. 触发模型
| 触发类型 | 幂等键 | 说明 |
|---|---|---|
| manual | learning-analysis:manual:<operationId> |
用户手动触发,同一操作重试相同 Job |
| scheduled | learning-analysis:scheduled:<userId>:<windowStart>:<windowEnd>:<policyVersion> |
定时触发,同一窗口唯一 |
9. 幂等契约
请求级
- 同一 operationId → 同一 Job
- 同一 scheduled window → 同一 Job
- 禁止 Date.now()/random 回退
投影级
- analysisId = deterministic(jobId)
- recommendationId = deterministic(jobId + ordinal)
- 入口 Artifact 检查 + P2002 catch
10. Artifact 矩阵
| 实体 | artifactType | artifactId |
|---|---|---|
| AiLearningAnalysis | learning_analysis |
analysis.id |
| WeakPointCandidate | weak_point |
candidate.id |
| NextActionRecommendation | recommendation |
recommendation.id |
| Flashcard (单独) | flashcard |
flashcard.id |
注:M-AI-02 已冻结 learning_analysis、recommendation 等 artifactType。
11. 权限与隐私
- 所有数据必须属于同一 userId
- 禁止其他用户数据进入 Snapshot
- 禁止跨用户 evidenceRefs
- 公开错误不泄漏 Snapshot/validatedOutput
- Admin 可查看所有(现有权限制)
12. Feature Flag
Flag Name: LEARNING_ANALYSIS_ENGINE_MODE
Values: legacy | unified
Default: legacy
13. 回滚流程
unified → legacy:
1. 修改 Flag → legacy
2. 新触发走 Legacy Runtime 轮询
3. 已创建 Unified Job 继续完成
4. 已生成分析保留
5. 无需数据库回滚
14. 架构异常与不确定项
阻塞项
| # | 异常 | 说明 | 处理 |
|---|---|---|---|
| A1 | 无 learning_state/weak_point/next_action Prompt 模板 | 当前由 Runtime 管理 | M-AI-08-03 需新增内联 Prompt |
| A2 | 无对应 Output Schema | 同上 | M-AI-08-03 需新增 Zod Schema |
| A3 | flashcard_generation prompt/schema 缺失 | 同 Quiz 模式 | 延期或并入 M-AI-08 |
不确定项
| 项 | 问题 | 建议 |
|---|---|---|
| 三个 Job Type 合并策略 | 当前三者独立,合并为一个 learning_analysis 需验证业务合理性 | M-AI-08-01 中确认后冻结 |
| flashcard_generation 归属 | 语义上更接近 Quiz 生成而非学习分析 | 建议纳入 M-AI-08 作为独立 Definition |
附录:关键文件索引
| 用途 | 路径 | 关键行号 |
|---|---|---|
| 分析入口 | src/modules/ai-runtime/user-ai.service.ts |
:199 createAnalysisJob, :11-17 JOB_TYPE_CONFIG |
| Runtime 持久化 | src/modules/ai-runtime/internal/runtime-internal.service.ts |
:286 persistResult, :295-365 四种类型分支 |
| Snapshot 构建 | src/modules/ai-runtime/snapshot-builder.service.ts |
:75 buildSnapshot, :259 aggregateBehavior |
| Priority 规则 | src/modules/ai-runtime/priority-rules.service.ts |
:45 computePriorityRules |
| AiLearningAnalysis | prisma/schema.prisma |
:2173-2194 |
| WeakPointCandidate | prisma/schema.prisma |
:2198-2216 |
| NextActionRecommendation | prisma/schema.prisma |
:2220-2239 |
| LearningAnalysisSnapshot | prisma/schema.prisma |
:2058-2083 |
| UserLearningProfile | prisma/schema.prisma |
:1912-1932 |
| UserAiSettings | prisma/schema.prisma |
:1936-1953 |
| 学习趋势 Workflow | src/modules/ai/workflows/learning-trend.workflow.ts |
:30 execute |
| 学习趋势 Prompt | src/modules/ai/prompts/learning-trend.prompt.ts |
:1 system prompt |