All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 42s
定义 7 项用户授权开关、12 项用户设置字段、4 层硬约束、8 级优先级体系、 设备信息限制规则、Snapshot 过滤伪代码、DeepSeek Prompt 发送规则。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
165 lines
6.7 KiB
Markdown
165 lines
6.7 KiB
Markdown
# 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 明文
|