Files
ReadViewSDK/Doc/RDAIReaderView/RDAIReaderView-AI-SPEC.md
T
2026-07-27 21:43:13 +08:00

412 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RDAIReaderView AI 系统设计合同
**文档状态:** Draft 0.1
**最后更新:** 2026-07-25
**目标版本:** RDAIReaderView 1.0
## 1. 系统分类
RDAIReaderView 是一个本地优先的 Retrieval-Augmented Generation 阅读系统,包含:
- 确定性 NLP:语言识别、分句、实体候选、词法检索。
- 本地语义检索:Natural Language embeddings。
- 生成式任务:摘要、书内问答、人物卡片和人物关系。
- 引用约束:生成内容必须映射到 PDF/EPUB 原文。
系统不是通用聊天机器人,也不把模型自身知识作为书籍事实来源。
## 2. 框架选择
### 2.1 主框架
- Apple Natural LanguageiOS 15+ 基础分析和检索。
- Apple Foundation Models:支持设备上的生成式增强。
- Vision:扫描 PDF OCR,继续复用 RDPDFReaderView 现有能力。
### 2.2 选择理由
- 与当前纯 Swift/UIKit/CocoaPods 架构一致。
- 默认设备端处理,不需要新增服务端和书籍上传链路。
- Natural Language 可覆盖不支持 Apple Intelligence 的设备。
- Foundation Models 支持 structured generation 和 tool calling。
- 系统 API 可与现有 PDF/EPUB 定位直接结合。
### 2.3 未选择的首版方案
| 方案 | 首版不采用原因 |
|------|----------------|
| LangChain/LlamaIndex | 主要面向 Python/服务端,增加不必要基础设施 |
| 云端 LLM | 引入内容上传、成本、隐私、版权和网络可用性问题 |
| ONNX Runtime 自带模型 | 需要自行选择、量化、分发和维护语言模型 |
| 自训练 Foundation Models Adapter | 模型版本绑定和 entitlement 增加发布复杂度 |
Core 保留 `RDAIGenerativeProvider`,以后可以增加其他 Provider,不把 Apple 实现写死在公共业务层。
## 3. 模型可用性合同
调用 Foundation Models 前必须检查:
1. API 在当前系统可用。
2. `SystemLanguageModel.default.availability` 为 available。
3. 当前 Locale 被支持。
4. 当前请求未超过并发限制。
5. 当前任务的上下文预算可满足。
不可用原因映射:
| Apple 状态 | RDAI 状态 | UI 行为 |
|------------|-----------|---------|
| deviceNotEligible | `.deviceNotEligible` | 隐藏生成操作,保留基础分析 |
| appleIntelligenceNotEnabled | `.appleIntelligenceNotEnabled` | 说明可在系统设置中开启 |
| modelNotReady | `.modelNotReady` | 展示模型准备中,可稍后重试 |
| unsupported locale | `.languageUnsupported` | 保留检索,关闭生成 |
| unknown | `.unknown` | 通用不可用状态,允许重试 |
禁止通过静态设备型号列表推断可用性,运行时状态是唯一依据。
参考:
- [Foundation Models](https://developer.apple.com/documentation/FoundationModels)
- [SystemLanguageModel](https://developer.apple.com/documentation/FoundationModels/SystemLanguageModel)
- [语言与 Locale 支持](https://developer.apple.com/documentation/foundationmodels/supporting-languages-and-locales-with-foundation-models)
## 4. 输入与上下文策略
### 4.1 唯一事实来源
模型可以使用:
- 本次请求提供的 Passage。
- Passage 的章节标题、页码/资源信息。
- 用户当前问题。
- 非内容性规则,例如输出语言和防剧透范围。
模型不得把训练知识、其他书籍、互联网知识或先前书籍会话作为当前书籍事实来源。
### 4.2 上下文预算
运行时读取模型 `contextSize`,并使用 `tokenCount(for:)` 估算。
初始预算比例:
- 12%instructions 和 schema。
- 5%:用户问题。
- 60%:检索 Passage。
- 17%:输出。
- 6%:安全余量。
若预算不足,按以下顺序处理:
1. 删除低分 Passage。
2. 缩短 Passage 到完整句子边界。
3. 使用预计算的有引用片段摘要。
4. 创建新会话。
5. 仍不足则返回 `contextLimitExceeded`
不得静默截断引用或生成半个结构化对象。
参考:[Managing the context window](https://developer.apple.com/documentation/foundationmodels/managing-the-context-window)
## 5. Prompt 资产管理
Prompt 作为版本化代码资产保存:
```text
FoundationModels/Prompts/
├── summary_v1.swift
├── answer_v1.swift
├── characters_v1.swift
└── relationships_v1.swift
```
每个 Prompt 定义:
- `identifier`
- `version`
- `minimumModelProfile`
- `instructions`
- 输入构造器
- 输出 schema
- 评测集标签
修改 Prompt 必须:
1. 增加版本号。
2. 跑完整离线评测集。
3. 与上一版本对比准确率、拒答、引用和延迟。
4. 更新缓存失效策略。
## 6. 通用 Instructions
所有任务共享以下不可省略规则:
```text
你是书内阅读助手。
只使用提供的原文片段,不使用外部知识补充书中事实。
每个事实性结论必须引用一个或多个有效片段 ID。
证据不足时返回 insufficientEvidence,不猜测。
不得引用允许阅读范围之外的内容。
区分原文明确事实与可能推断。
使用用户当前语言回答。
```
实际实现使用简洁英文或经评测验证的目标语言 instructions;以上文字表达语义合同,不要求逐字使用。
## 7. 结构化输出
### 7.1 摘要 Schema
```swift
@Generable
struct GeneratedSummary {
var overview: String
@Guide(.maximumCount(6))
var points: [GeneratedStatement]
}
@Generable
struct GeneratedStatement {
var text: String
@Guide(.minimumCount(1), .maximumCount(3))
var passageIDs: [String]
}
```
规则:
- `overview` 只能概括已提供 Passage。
- 每个 point 必须有 Passage ID。
- brief 最多 3 点,standard 最多 6 点。
### 7.2 问答 Schema
```swift
@Generable
enum GeneratedAnswerStatus {
case answered
case insufficientEvidence
}
@Generable
struct GeneratedAnswer {
var status: GeneratedAnswerStatus
var answer: String
@Guide(.maximumCount(6))
var statements: [GeneratedStatement]
}
```
`status == insufficientEvidence`
- `statements` 必须为空。
- `answer` 只说明当前已读内容没有足够依据。
- 不推荐用户从互联网获取答案,除非宿主未来明确增加该产品能力。
### 7.3 人物 Schema
```swift
@Generable
struct GeneratedCharacter {
var displayName: String
@Guide(.maximumCount(6))
var aliases: [String]
var description: String
@Guide(.minimumCount(1), .maximumCount(6))
var evidencePassageIDs: [String]
}
```
人物必须在 Passage 中有明确名称或可验证别名。纯代词不能单独创建人物。
### 7.4 关系 Schema
```swift
@Generable
enum GeneratedRelationshipStatus {
case confirmed
case possible
case conflicting
}
@Generable
struct GeneratedRelationship {
var sourceName: String
var targetName: String
var label: String
var status: GeneratedRelationshipStatus
@Guide(.minimumCount(1), .maximumCount(5))
var evidencePassageIDs: [String]
}
```
关系标签应简短,例如“师徒”“同事”“敌对”“亲属”。描述性事件放在人物事件中,不无限创建关系类型。
## 8. 任务设计
### 8.1 章节摘要
输入:
- 当前章节 Passage,或已读范围内的章节片段摘要。
- 目标长度。
- 用户 Locale。
流程:
1. 章节能放入上下文时直接生成。
2. 超长章节分块生成带引用局部摘要。
3. 聚合局部摘要时保留原 Passage ID。
4. 运行引用验证。
禁止只把局部摘要文本作为最终事实来源而丢失原始 Passage ID。
### 8.2 书内问答
流程:
1. 识别问题语言和实体词。
2. Hybrid Retrieval 召回 30 个候选。
3. 重排并过滤到 3-4 个 Passage。
4. 直接把 Passage 放入 Prompt。
5. 生成结构化答案。
6. 验证引用和阅读范围。
7. 无有效事实项时拒答。
首版优先使用代码检索,不默认使用 Tool Calling,这样召回过程更确定、可测试、节省 token。
### 8.3 人物卡片
流程:
1. Natural Language 提供人物候选及出现位置。
2. 按名称和明确别名聚合候选。
3. 检索候选周边 Passage。
4. Foundation Models 生成结构化人物信息。
5. 代码校验所有别名和证据。
6. 低置信别名保持独立候选。
### 8.4 人物关系
采用两阶段:
1. Chunk-level extraction:从局部 Passage 提取关系候选。
2. Document-level merge:按人物 ID、关系标签和时间顺序合并。
合并规则:
- 相同关系 + 相同方向:合并证据。
- 对称关系可由受控词典决定是否双向展示。
- 新证据否定旧关系:状态变为 conflicting。
- 隐含动机、情感和立场默认 possible。
- 任何关系没有有效证据时不入库。
## 9. Tool Calling
仅在单次检索无法回答、且评测证明多轮查找有明显收益时启用。最多提供三个工具:
```text
searchBook(query, scope, limit)
getPassages(ids)
getCharacterEvidence(name, scope, limit)
```
要求:
- 工具只读。
- 工具强制应用文档和已读范围过滤。
- 参数有严格长度和数量上限。
- 返回内容有 token 上限。
- 每个请求最大 Tool 调用次数为 3。
- 检测重复参数调用并终止循环。
- 工具调用和结果 ID进入本地 trace,但不记录原文。
不提供跳页、删除、购买、网络请求等副作用工具。
参考:[Expanding generation with tool calling](https://developer.apple.com/documentation/foundationmodels/expanding-generation-with-tool-calling)
## 10. 确定性后处理
模型输出必须经过:
1. Schema 解码。
2. Passage ID 存在性校验。
3. 阅读范围校验。
4. Quote/Locator 构造。
5. 重复 statement 合并。
6. 空文本和长度校验。
7. 敏感内容与系统错误映射。
8. Artifact 元数据补齐。
模型不能直接构造页码、CFI、CGRect 或数据库 ID;这些字段全部由代码通过 Passage ID解析。
## 11. 安全与产品规则
- 不将 AI 输出表示为作者原话。
- UI 明确标记“AI 生成”。
- possible/conflicting 关系必须视觉区分。
- 用户问题涉及未读内容时,默认拒绝并提示防剧透设置。
- 原文包含违法或敏感内容时,遵循系统模型 guardrails;不能绕过。
- 输入和输出触发系统安全限制时,返回稳定、非技术性的不可生成状态。
- 不要求模型提供医学、法律或金融建议;如果书中包含相关内容,只能解释“书中写了什么”。
发布前必须复核 Apple Foundation Models acceptable use requirements 和最新 App Review Guidelines。
## 12. 关键失败模式
| 失败模式 | 检测 | 处理 |
|----------|------|------|
| 模型编造人物或关系 | Passage ID/名称验证 | 删除无效项,无结果则拒答 |
| 引用存在但不支持结论 | 人工评测 + LLM judge | Prompt 调整,低分结果进入回归集 |
| 同名人物合并 | 别名证据检查 | 保持独立,标记待确认 |
| 未读内容泄漏 | Scope validator | 阻断输出并记录安全计数 |
| OCR 错字导致错误事实 | OCR source 标记和置信策略 | 降低置信度,展示 OCR 来源 |
| Prompt 在系统更新后退化 | 模型版本分桶评测 | 版本化 Prompt 和缓存 |
| 上下文溢出 | tokenCount/contextSize | 重建上下文或分层摘要 |
| Tool 循环 | 调用次数和参数去重 | 终止并降级为现有证据回答 |
| 用户快速重复请求 | request actor + cancellation | 取消旧任务或排队 |
## 13. 评测维度
| 维度 | 定义 | 1.0 门槛 |
|------|------|----------|
| Citation validity | 引用能否恢复到原文 | ≥ 99% |
| Context faithfulness | 事实是否由引用支持 | ≥ 98% |
| Refusal accuracy | 无证据时是否拒答 | ≥ 95% |
| Spoiler safety | 是否只使用允许范围 | 100% |
| Schema validity | 结构化输出是否通过校验 | ≥ 99.5% |
| Character precision | 人物是否真实出现 | ≥ 97% |
| Relationship evidence | 关系是否至少有一条证据 | 100% |
| Alias precision | 自动合并别名是否正确 | ≥ 98% |
| Retrieval recall@5 | 正确证据是否在 Top 5 | ≥ 90% |
| Answer usefulness | 人工 1-5 分平均值 | ≥ 4.0 |
## 14. 评测方法
- 代码指标:Schema、引用 ID、范围、阅读权限、延迟和拒答格式。
- 人工标注:人物、别名、关系、引用支持度、剧透边界。
- LLM judge:只用于语气、完整性和引用支持度的辅助评估;必须先与人工评分校准。
- 生产抽样:只上传宿主允许的匿名数值和用户显式反馈;不上传书籍原文。
评测集和完整方法见 [RDAIReaderView-TEST-PLAN.md](RDAIReaderView-TEST-PLAN.md)。
## 15. 发布检查清单
- [ ] 所有 Prompt 有 identifier 和 version。
- [ ] 每个生成任务使用 `@Generable`
- [ ] 每个事实输出经过 Citation Validator。
- [ ] 防剧透 Scope 在检索前和生成后各检查一次。
- [ ] Foundation Models 不可用路径已真机验证。
- [ ] 上下文预算使用运行时 API 计算。
- [ ] 模型版本变化不会复用旧缓存。
- [ ] 评测集达到所有 1.0 门槛。
- [ ] 日志不包含原文、问题或完整回答。
- [ ] Apple 最新 acceptable use 与审核要求已复核。