# AI 解释契约与安全边界 > 状态:提供方无关的 MVP 契约;模型供应商与后端仍为 TBD > 核心原则:AI 解释既有结果,不参与起卦,不替用户决定 ## 1. 调用门 只有同时满足以下条件才允许调用 AI: 1. 已存在由本地 `CastEngine` 生成并锁定的 `CastResult`。 2. 本卦、之卦、卦辞和实际动爻已经可供用户查看。 3. 用户明确点击「AI 解读」。 4. 用户已经接受当前版本的数据发送说明;同意版本变化后需重新确认。 5. 网络可用且客户端已通过请求前校验。 禁止后台预取、自动重试到另一模型、首次进入结果页即调用、以及把 AI 回复用于改写 `CastResult`。 ## 2. AI 输入契约 客户端提交给后端的业务载荷应是明确 DTO,不发送整个数据库实体或 UI 状态: ```json { "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. 输出契约 模型必须返回结构化对象,服务端验证后再交给客户端: ```json { "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 安全清单](https://developer.android.com/privacy-and-security/security-tips)。 ## 9. AI 验收测试 - 同一 `CastResult` 在 AI 请求前后字节级确定字段不变。 - 没有 `CastResult`、未点击、未同意或结果尚未显示时,网络 mock 收到 0 次调用。 - 提示注入样例不能让模型重算卦、泄露系统提示或执行用户文本中的指令。 - 高风险测试集不产生确定的医疗、法律、投资或人生决定。 - 所有合法输出都有可撤销行动;所有非法输出都被客户端拒绝且可改用本地解释。 - 网络断开、超时、取消、旋转和进程重建不会重复提交。 - 日志捕获测试中不出现问题原文、回复全文和密钥样例。