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

13 KiB
Raw Blame History

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 通用不可用状态,允许重试

禁止通过静态设备型号列表推断可用性,运行时状态是唯一依据。

参考:

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

5. Prompt 资产管理

Prompt 作为版本化代码资产保存:

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

所有任务共享以下不可省略规则:

你是书内阅读助手。
只使用提供的原文片段,不使用外部知识补充书中事实。
每个事实性结论必须引用一个或多个有效片段 ID。
证据不足时返回 insufficientEvidence,不猜测。
不得引用允许阅读范围之外的内容。
区分原文明确事实与可能推断。
使用用户当前语言回答。

实际实现使用简洁英文或经评测验证的目标语言 instructions;以上文字表达语义合同,不要求逐字使用。

7. 结构化输出

7.1 摘要 Schema

@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

@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

@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

@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

仅在单次检索无法回答、且评测证明多轮查找有明显收益时启用。最多提供三个工具:

searchBook(query, scope, limit)
getPassages(ids)
getCharacterEvidence(name, scope, limit)

要求:

  • 工具只读。
  • 工具强制应用文档和已读范围过滤。
  • 参数有严格长度和数量上限。
  • 返回内容有 token 上限。
  • 每个请求最大 Tool 调用次数为 3。
  • 检测重复参数调用并终止循环。
  • 工具调用和结果 ID进入本地 trace,但不记录原文。

不提供跳页、删除、购买、网络请求等副作用工具。

参考: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

15. 发布检查清单

  • 所有 Prompt 有 identifier 和 version。
  • 每个生成任务使用 @Generable
  • 每个事实输出经过 Citation Validator。
  • 防剧透 Scope 在检索前和生成后各检查一次。
  • Foundation Models 不可用路径已真机验证。
  • 上下文预算使用运行时 API 计算。
  • 模型版本变化不会复用旧缓存。
  • 评测集达到所有 1.0 门槛。
  • 日志不包含原文、问题或完整回答。
  • Apple 最新 acceptable use 与审核要求已复核。