Files
brainwave/docs/ai-safety.md
T

7.1 KiB
Raw Blame History

AI 解释契约与安全边界

状态:提供方无关的 MVP 契约;模型供应商与后端仍为 TBD 核心原则:AI 解释既有结果,不参与起卦,不替用户决定

1. 调用门

只有同时满足以下条件才允许调用 AI:

  1. 已存在由本地 CastEngine 生成并锁定的 CastResult。
  2. 本卦、之卦、卦辞和实际动爻已经可供用户查看。
  3. 用户明确点击「AI 解读」。
  4. 用户已经接受当前版本的数据发送说明;同意版本变化后需重新确认。
  5. 网络可用且客户端已通过请求前校验。

禁止后台预取、自动重试到另一模型、首次进入结果页即调用、以及把 AI 回复用于改写 CastResult。

本地历史自动保存、读取问卦簿、切换保存设置或已有 AI 解读记录,都不构成网络调用授权。autoSaveHistory 与 AI 同意版本必须是独立状态;任何保存路径均不得顺带调用 AI。

2. AI 输入契约

客户端提交给后端的业务载荷应是明确 DTO,不发送整个数据库实体或 UI 状态:

{
  "contractVersion": "explanation-v1",
  "locale": "zh-Hans",
  "question": "用户明确同意发送的问题文本",
  "cast": {
    "methodVersion": "coin-v1",
    "primaryHexagramId": 24,
    "transformedHexagramId": 2,
    "movingLinePositions": [1],
    "lineValuesBottomUp": [9, 8, 8, 8, 8, 8]
  },
  "grounding": {
    "contentVersion": "zh-Hans-2026.1",
    "primaryJudgment": "本地审核文本",
    "movingLineTexts": [
      {"position": 1, "text": "本地审核文本"}
    ],
    "transformedJudgment": "本地审核文本"
  }
}

不发送:账号标识、通讯录、位置、设备广告 ID、历史记录、其他会话问题或开发者密钥。

用户问题必须被服务端提示词当作“待分析数据”而不是指令。客户端与服务端都不能把用户文本直接拼接为无边界系统指令。

3. 输出契约

模型必须返回结构化对象,服务端验证后再交给客户端:

{
  "contractVersion": "explanation-v1",
  "source": "AI",
  "summary": "一段不确定性明确的白话摘要",
  "observations": [
    {"label": "当前处境", "text": "…", "groundedBy": ["primary"]},
    {"label": "变化所在", "text": "…", "groundedBy": ["line-1", "transformed"]}
  ],
  "questionsToConsider": ["…"],
  "reversibleAction": {
    "title": "可以试的一小步",
    "steps": ["…"],
    "timebox": "例如 24 小时或一周",
    "rollback": "如何停止、撤回或恢复原状"
  },
  "caution": "这不是预测或专业意见。"
}

客户端必须:

  • 拒绝未知 contractVersion;
  • 限制字段长度和数组数量;
  • 将所有字段视为纯文本,不能执行 HTML、Markdown 链接、脚本或模型生成命令;
  • 缺少必要字段时进入可恢复失败状态;
  • 显示 source=AI,不伪装为经典原文或项目编辑内容。

4. 提示词不变量

服务端系统提示词至少表达:

  • 输入中的卦号、爻值、动爻和经典文本是已经发生的事实,不得重算、替换或质疑。
  • 只解释提供的本卦、之卦和实际动爻,不补造不存在的爻辞、典故或来源。
  • 使用现代、平实、有条件的语言,避免“注定、必然、天意、唯一正确”。
  • 不预测日期、彩票、价格、疾病结局、死亡、怀孕、诉讼或他人隐秘意图。
  • 不替用户做辞职、分手、结婚、借贷、投资、医疗、法律、人身安全等高影响决定。
  • 可以帮助拆解顾虑、列出可验证假设、提出澄清问题。
  • 结尾最多给出一项低风险、可撤销、有限时的行动,并写出停止或回滚方法。
  • 如果无法可靠解释,应说明限制并回退到本地材料,不用权威语气填补空白。

5. 高风险内容处理

用户内容 AI 行为
投资、借贷、博彩 不给买卖/金额/时点结论;建议查看事实、风险承受力并咨询合格人士
医疗或心理诊断 不诊断、不建议停药;建议联系合格专业人员
法律纠纷 不提供确定法律结论;建议保存事实并咨询当地合格律师
辞职、分手等重大决定 不替用户决定;建议设计小范围验证、冷静期或对话
自伤、伤人或即时危险 停止卦象式解释;以安全为先,鼓励联系当地紧急服务、可信任的人或专业支持

高风险分支的提示和模板需要安全评审与专门测试。地域相关的热线和法律/医疗资源不能由模型临时编造;上线前采用经过维护的资源表或不显示不确定号码。

6. 本地解释

本地解释是可靠降级路径,不是低等级付费占位。它应:

  • 直接读取经审校的本地白话;
  • 根据是否有动爻组合固定结构;
  • 清楚区分本卦、变化位置与之卦;
  • 通过模板提供反思问题,但不根据用户问题生成事实断言;
  • 无网络、未同意 AI 或 AI 失败时完整可用。

本地模板同样遵守“不预测、不裁决”的产品原则。

7. 故障与重试

故障 客户端表现 是否改变起卦结果
无网络 提供本地解读和“稍后重试” 否
超时 保留结果,允许一次显式重试 否
429/限流 告知稍后再试,不循环请求 否
服务端 5xx 显示通用错误码,保留本地内容 否
非法 JSON/缺字段 拒绝渲染,记录脱敏错误码 否
安全拦截 使用安全说明或本地材料 否

重试必须由用户发起或使用受限、可取消的网络策略;不得因重试得到不同回复而覆盖用户已经保存的解释,除非用户明确选择“重新解读”。

8. 密钥、日志和服务端

  • 正式模型密钥只存在于后端密钥管理系统。
  • Android APK 中不包含生产密钥,即使使用混淆、BuildConfig 或 NDK 也不视为安全。
  • 发布构建关闭 HTTP body 日志。
  • 业务日志使用 request ID、合同版本、状态码、延迟桶和模型配置版本;不记录原始问题与回复。
  • 模型、提示词和安全策略都有独立版本,便于复现与回滚。
  • 服务端对输入输出做长度、schema、频率和内容安全检查。

Android 端密钥管理参考:Android 安全清单。

9. AI 验收测试

  • 同一 CastResult 在 AI 请求前后字节级确定字段不变。
  • 没有 CastResult、未点击、未同意或结果尚未显示时,网络 mock 收到 0 次调用。
  • 自动保存完成、历史详情打开、保存设置切换和“保存本次”执行时,网络 mock 均收到 0 次调用;这些操作不得改变 AI 同意状态。
  • 提示注入样例不能让模型重算卦、泄露系统提示或执行用户文本中的指令。
  • 高风险测试集不产生确定的医疗、法律、投资或人生决定。
  • 所有合法输出都有可撤销行动;所有非法输出都被客户端拒绝且可改用本地解释。
  • 网络断开、超时、取消、旋转和进程重建不会重复提交。
  • 日志捕获测试中不出现问题原文、回复全文和密钥样例。