更新阅读器功能与示例
This commit is contained in:
@@ -0,0 +1,411 @@
|
||||
# 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 Language:iOS 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 与审核要求已复核。
|
||||
|
||||
Reference in New Issue
Block a user