# AI 数据权限、隐私授权与用户设置设计 ## 1. 概述 定义 AI 分析可使用的数据范围、用户授权开关、隐私边界和字段发送规则。所有规则由 Snapshot Builder 执行,Runtime 无权绕过。 ## 2. 用户授权项 存储在 `UserAiSettings` 中: | 字段 | 默认值 | 说明 | |------|--------|------| | `allowAiAnalysis` | `true` | 总开关。关闭后禁止创建任何 AI Job | | `allowUseLearningBehavior` | `true` | 是否允许使用学习行为数据(时长、频率、pattern) | | `allowUseUserProfile` | `true` | 是否允许使用用户画像(目标、等级、偏好) | | `allowUseDocumentContent` | `false` | 是否允许使用资料原文片段。默认关闭,需用户主动开启 | | `allowStoreAiAnalysisHistory` | `true` | 是否允许保存 AI 分析历史 | | `allowUserModelCredential` | `true` | 是否允许使用自己的 DeepSeek Key | | `fallbackToPlatformKey` | `true` | 用户 Key 不可用时是否回退到平台 Key | ### 授权变更行为 | 用户操作 | HTTP | 立即影响 | |---------|------|----------| | 关闭 `allowAiAnalysis` | PUT /ai/settings | 禁止创建新 Job;pending Job → cancelled;running Job → cancelRequested | | 关闭 `allowUseDocumentContent` | PUT /ai/settings | 新 Snapshot 不包含资料原文;已生成但未消费的 Snapshot 重用不受影响 | | 开启 `allowUseDocumentContent` | PUT /ai/settings | 新 Snapshot 可包含资料原文 | | 关闭 `allowUserModelCredential` | PUT /ai/settings | 已有 credential 不删除但不再用于新 Job;running Job 若使用用户 Key 继续完成 | ## 3. 用户设置项 存储在 `UserLearningProfile` 中: | 字段 | 类型 | 说明 | 枚举值 | |------|------|------|--------| | `learningGoal` | string | 学习目标 | —(自由文本 + 预选项) | | `currentLevel` | enum | 当前水平 | `beginner` / `basic` / `intermediate` / `advanced` / `expert` | | `dailyAvailableMinutes` | int | 每日可用学习分钟 | 1-480 | | `qualityPreference` | enum | 质量偏好 | `light` / `standard` / `deep` / `exam` | | `ageRange` | enum | 年龄段(可选) | `unknown` / `under_18` / `age_18_24` / `age_25_34` / `age_35_44` / `age_45_54` / `age_55_plus` | | `occupation` | string | 职业(可选) | 自由文本 | | `aiAcceptanceLevel` | enum | AI 接受度 | `low` / `medium` / `high` | | `digitalSkillLevel` | enum | 数字技能 | `low` / `medium` / `high` | | `preferredQuestionTypes` | string[] | 偏好题型(可选) | 如 `["single_choice", "true_false"]` | | `preferredLanguage` | string | 偏好语言 | `zh-CN` / `en-US` / `auto` | ## 4. 隐私边界 ### 4.1 硬约束(不可被 AI 覆盖) | 约束 | 来源 | 说明 | |------|------|------| | `dailyAvailableMinutes` | 用户设置 | AI 推荐的 estimatedMinutes 不得超过此值 | | `allowAiAnalysis` | 用户授权 | 关闭时直接拒绝所有 Job | | `allowUseDocumentContent` | 用户授权 | 关闭时不发送原文给模型 | | `allowUseLearningBehavior` | 用户授权 | 关闭时不发送行为信号给模型 | ### 4.2 禁止收集的数据 - 精确年龄(只允许 ageRange,且为可选) - 性别 - 收入 - 精确位置(只用 timezone offset) - 设备标识符(只用 phone/tablet/desktop/web 类别) ### 4.3 优先级体系 ``` Level 0: 隐私授权 / 安全 / 合规 ← 不可覆盖 Level 1: 用户明确设置 ← AI 必须遵守 Level 2: 学习目标和任务类型 Level 3: 测评结果 Level 4: 学习行为信号 Level 5: 内容结构 Level 6: 设备与当前场景 Level 7: 用户画像辅助字段 Level 8: AI 自己的推断 ``` ### 4.4 设备信息限制 设备信息(phone / tablet / desktop / web)只能用于调整任务形式: | 设备 | 适合任务 | 不适合任务 | |------|---------|-----------| | phone | 卡片、判断、单选、短复习 | 复杂题组、长文阅读 | | tablet | 阅读、标注、笔记、轻量题组 | — | | desktop/web | 深度学习、复杂题组、资料整理 | — | **设备信息不得用于判断学习能力。** ### 4.5 年龄段限制 `ageRange` 只能作为辅助字段。不得根据年龄判断学习能力、智力水平或学习速度。`unknown` 是合法值。 ## 5. Snapshot 过滤规则 Snapshot Builder 必须执行: ```typescript function buildSnapshot(userId: string, targetType: string, targetId: string): Snapshot { const settings = getUserAiSettings(userId); const profile = getUserLearningProfile(userId); return { // 硬约束 constraints: { dailyAvailableMinutes: profile?.dailyAvailableMinutes ?? null, qualityPreference: profile?.qualityPreference ?? 'standard', learningGoal: profile?.learningGoal ?? null, }, // 授权过滤 privacyScope: { allowDocumentContent: settings?.allowUseDocumentContent ?? false, allowLearningBehavior: settings?.allowUseLearningBehavior ?? true, allowUserProfile: settings?.allowUseUserProfile ?? true, }, // 仅包含授权的数据 userProfile: settings?.allowUseUserProfile ? pickSafeFields(profile) : undefined, learningBehaviorSummary: settings?.allowUseLearningBehavior ? aggregateBehavior(userId, targetType, targetId) : undefined, materialProgressSummary: aggregateProgress(userId, targetType, targetId), // 资料原文仅当授权 contentStructureSummary: settings?.allowUseDocumentContent ? aggregateContent(targetType, targetId) : undefined, // 明确标注哪些字段可发送模型 allowedModelFields: buildAllowedFields(settings, profile), // 设备上下文 deviceContext: buildDeviceContext(), // 评分信号 scoreSignals: calculateScores(userId, targetType, targetId), // 行为信号(仅当授权) behaviorSignals: settings?.allowUseLearningBehavior ? calculateBehaviorSignals(userId, targetType, targetId) : undefined, }; } ``` ### `pickSafeFields` 从 UserLearningProfile 中只挑选安全字段: - `learningGoal`, `currentLevel`, `qualityPreference` - `ageRange`(仅辅助),`preferredLanguage` - 排除:`dailyAvailableMinutes`(进 constraints,不直接进 profile) - 排除:`occupation`(除非用户明确同意) ## 6. DeepSeek Prompt 发送规则 Prompt Render(Rust Runtime 侧)只发送 `Snapshot.allowedModelFields` 中列出的字段。未授权字段不在 Snapshot 中出现或标记为未授权。 ## 7. 验收清单 - [x] 输出 AI 数据权限设计文档 - [x] 明确哪些字段必填、建议填写、可选 - [x] 明确哪些字段可发送给模型 - [x] 明确用户关闭 AI 授权后的 API 行为 - [x] 明确 Snapshot Builder 必须遵守授权 - [x] 明确 Runtime 无权绕过 API 读取用户隐私数据 - [x] 明确用户可删除自定义 key - [x] 明确 Admin 不可查看用户 key 明文