# Hail Mary Chat — Project Knowledge > 一个星际视频通话产品:3D 全息投影的 Rocky + AI 对话 + 外星原声/翻译 TTS,让你真的能跟《挽救计划》里的外星朋友聊天。 ## Quick Facts | 指标 | 值 | |---|---| | What | 跟《挽救计划》Rocky 的沉浸式星际通话体验 | | Built by | 开发者 + Claude Code | | Timeline | 2026-03-23 → 2026-03-24(2 天) | | Commits | 2 | | Tech stack | React 19 + Three.js + Vite 8 + TypeScript + MiniMax-M2.7 + ElevenLabs TTS | | Monthly cost | ~¥400(CC token ¥200 + ElevenLabs <¥100 + 域名几十 + LLM 调用极少) | | Repo | private(无远程仓库) | ## The Problem 看完电影《挽救计划》后,Rocky 这个外星朋友让人念念不忘。电影留下了大量开放空间——Rocky 回到 Erid 后怎样了?他和 Adrian 之间是什么关系?Meburger 是什么味道? 相比去读原著,一个更有趣的想法浮现:**为什么不直接问 Rocky 本人呢?** 不是做一个普通的 chatbot,而是做一个**星际通话**——像电影里那样,有外星原声、有翻译器、有全息投影、有信号延迟。用噬星体能源不足来限制通话时长,既忠于原作设定,又控制了 API 成本。 > "喜欢 Rocky 这个外星朋友。电影中没暴露的细节、开放式结局,想进一步去探究。相比看原著,为什么不问 Rocky 本人呢?" ## Key Decisions ### Decision: 星际通话模式(而非普通 chatbot) - **Context**: 需要一个交互形式来承载"跟 Rocky 聊天"这个核心功能 - **Options considered**: 纯文字聊天、语音助手、视频通话风格 - **Chosen**: 星际通话模式——全息投影 + 外星原声 + 翻译器 + 噬星体能源限制 - **Why**: 一石三鸟:沉浸感(你真的在跟外星人通话)、叙事合理性(限制是故事的一部分)、成本控制(避免无限长对话烧 token) ### Decision: MiniMax-M2.7 作为 LLM - **Context**: 需要一个能角色扮演、中文好、成本低的模型 - **Options considered**: GPT-4、Claude、MiniMax、其他开源模型 - **Chosen**: MiniMax-M2.7,通过 arco.ai 中转(Anthropic Messages 协议) - **Why**: 角色扮演能力强,中文表现好,成本极低。通过 arco.ai 中转可以用 Anthropic 协议统一调用 ### Decision: ElevenLabs TTS(替代 Web Speech API) - **Context**: Day 1 先用 Web Speech API 验证流程,但语音质量差 - **Options considered**: Web Speech API、MiniMax TTS、ElevenLabs - **Chosen**: ElevenLabs(eleven_turbo_v2_5,流式) - **Why**: 声音质量高、支持流式播放、多语言支持好。月费不到 ¥100 可接受 ### Decision: 预置问答 + LLM fallback - **Context**: 高频问题(Grace 怎么样了、你的伴侣是谁)每次都走 LLM 浪费成本且质量不稳定 - **Options considered**: 全部走 LLM、全部预置、混合模式 - **Chosen**: 6 组精调预置问答(含预生成音频) + 自由输入走 LLM - **Why**: 预置问答秒回、音频质量稳定、零 API 成本;自由输入保留开放性 ### Decision: 10 轮对话限制 + 分享解锁 - **Context**: 需要控制 API 成本,但不想直接做付费 - **Options considered**: 无限对话、固定付费、按次付费、分享解锁 - **Chosen**: 10 轮免费 + 分享解锁额外轮次(最多 3 次分享,每次 +1 轮)+ referral bonus - **Why**: 噬星体能源不足是原作设定,自然融入叙事。分享机制促进传播 ### Decision: CGTrader 免费模型 + Blender 优化 - **Context**: 需要 Rocky 的 3D 模型做全息投影 - **Options considered**: 自建模型、购买模型、找免费模型 - **Chosen**: CGTrader 免费 .blend("Hail Mary Space Ships" by blackapplecloth)→ Blender decimated → 152KB GLB - **Why**: Claude Code 搜索推荐的模型比开发者自己找的更合适。30K 顶点对全息效果足够,文件小加载快 ## Architecture ### Tech Stack | 层 | 选择 | 为什么 | |---|---|---| | 前端框架 | React 19 + TypeScript | 组件化、快速迭代 | | 3D 引擎 | Three.js 0.183 | 浏览器原生 3D,无需插件 | | 构建工具 | Vite 8 | 快速 HMR | | LLM | MiniMax-M2.7 via arco.ai | 角色扮演强、中文好、成本低 | | TTS | ElevenLabs (streaming) | 语音质量高、流式播放 | | 3D 模型 | Blender → GLB (152KB) | 轻量全息够用 | | 部署 | YouWare(计划迁移 EdgeSpark) | 快速上线 | ### System Design ``` ┌─────────────────────────────────────────────────────┐ │ Browser (SPA) │ │ │ │ ┌──────────┐ ┌────────────┐ ┌────────────────┐ │ │ │StartScreen│→ │ChatInterface│→ │ ShareGate │ │ │ │(连接动画) │ │(主聊天界面) │ │(分享/裂变机制) │ │ │ └──────────┘ └──────┬─────┘ └────────────────┘ │ │ │ │ │ ┌────────────────────┼────────────────────────┐ │ │ │ ┌───────┴───────┐ │ │ │ │ │ useChat.ts │ │ │ │ │ │ (对话状态机) │ │ │ │ │ └──┬────────┬──┘ │ │ │ │ ┌─────────┘ └─────────┐ │ │ │ │ ▼ ▼ │ │ │ │ defaultDialogs.ts streamChat() │ │ │ │ (预置问答, 秒回) (LLM SSE 流式) │ │ │ │ │ │ │ │ ┌──────────────────────────────────────┐ │ │ │ │ │ useRockyTTS.ts │ │ │ │ │ │ 外星原声(预录) → 翻译语音(TTS) │ │ │ │ │ └──────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ Three.js Scene │ │ │ │ Starfield + RockyModel(全息shader) + Rings │ │ │ │ OrbitControls + 说话时动画加速 │ │ │ └─────────────────────────────────────────────┘ │ └──────────────────────┬──────────────────────────────┘ │ ┌────────────┴────────────┐ ▼ ▼ arco.ai Gateway ElevenLabs API (Anthropic 协议) (流式 TTS) │ ▼ MiniMax-M2.7 ``` ### Data Model **对话状态** (`useChat.ts`): ```typescript messages: DisplayMessage[] // 对话历史 userTurns: number // 用户发言计数(上限 10) isEnded: boolean // 是否结束 usedSuggestions: Set // 已用过的推荐问题 ``` **游玩限制** (`playLimit.ts`): ```typescript { used: number, // 已消耗次数 bonus: number, // 分享/referral 奖励 shareCount: number, // 分享次数(上限 3) referralCode: string, // 用户专属 referral code referralClaimed: string[] // 已领取的 referral } // 存储: localStorage + IndexedDB 备份 // 反作弊: 浏览器指纹(UA + 屏幕 + 时区 + CPU 核数 hash) ``` **Rocky 回复格式**: ``` [MOOD:happy] ← 情绪标签,驱动动画和音频 [INTRO][LIKE] ← 可选特殊标签 ♫♩♪ ← 外星音乐(Rocky 的"原声") [翻译] ← 翻译标记 Rocky 的回复内容 ← 实际显示给用户的文字 ``` ### Key Files | 文件 | 职责 | |---|---| | `src/App.tsx` | 三阶段状态机:start → chat → exhausted | | `src/components/RockyModel.tsx` | Three.js 全息投影 + 自定义 shader | | `src/components/ChatInterface.tsx` | 主聊天界面 | | `src/components/Starfield.tsx` | 1200 粒子星空背景 | | `src/hooks/useChat.ts` | 对话逻辑 + LLM 调用 | | `src/hooks/useRockyTTS.ts` | 音频管理:外星音 + TTS | | `src/prompts/rocky_update.ts` | 350+ 行 Rocky system prompt | | `src/prompts/rocky_afewshot.ts` | 29 组 few-shot(选 12 组注入) | | `src/utils/defaultDialogs.ts` | 6 组预置问答(per language) | | `src/utils/playLimit.ts` | 游玩限制 + referral 系统 | | `src/utils/rockyAudio.ts` | 音频预加载 + 播放队列 | | `src/i18n/index.ts` | 40+ 翻译键,中/英/日 | | `src/styles/terminal.css` | 星际终端 UI 风格 | ## Development Timeline | 日期 | 里程碑 | Commits | |---|---|---| | 2026-03-23 | MVP:3D 全息 Rocky + AI 对话 + 终端 UI + 推荐问题 + 移动端适配 | 1 | | 2026-03-24 | i18n 三语 + 开屏连接动画 + TTS 原型(Web Speech → ElevenLabs) | 1 | **速度要点**:2 天从零到可演示 MVP。Day 1 跑通核心链路,Day 2 打磨体验层。 ## How Builder & AI Collaborated ### 没有 CLAUDE.md,直接动手 这个项目没有 CLAUDE.md,没有复杂的规则文件。开发者和 Claude Code 的协作方式是: 1. 开发者提出创意方向("做成星际通话"、"用噬星体能源限制") 2. Claude Code 实现全部代码(3D shader、API 集成、CSS 动画、prompt 工程、i18n) 3. 开发者体验产品、找出戏/bug 的地方,反馈给 Claude Code 修改 ### Claude Code 亮点 > "给 Rocky 找合适的模型时,发现 Claude Code 找的比我找的好。我听他的去下载后放文件夹就行。" Claude Code 在这个项目中的角色不仅是"写代码的",还包括: - **资源搜索**:找到比开发者自己搜到的更合适的 3D 模型 - **Shader 编写**:从零写出全息投影效果(Fresnel + 扫描线 + 闪烁 + 波纹) - **Prompt 工程**:350 行 system prompt + 29 组 few-shot 锚定角色 - **全栈实现**:从 Three.js 3D 场景到 CSS 终端风格到 referral 系统 ### 开发者的判断力 开发者在以下方面的判断是 AI 无法替代的: - **核心创意**:星际通话模式(不是 chatbot) - **叙事设计**:噬星体能源 = 对话限制 - **体验打磨**:自己去找"出戏"的部分然后改 - **情感投入**:因为真的喜欢 Rocky,所以会追求细节 ## Pitfalls & Solutions ### Pitfall: Web Speech API 语音质量差 - **Symptom**: Day 1 用浏览器原生 TTS 朗读 Rocky 的回复,声音像机器人,破坏沉浸感 - **Root cause**: Web Speech API 没有高质量的"外星翻译器"风格声音 - **Fix**: 替换为 ElevenLabs TTS(eleven_turbo_v2_5),流式播放,选择合适的 voice - **Prevention**: 如果语音是核心体验,从 Day 1 就用专业 TTS 服务 ### Pitfall: 移动端音频自动播放被阻止 - **Symptom**: iOS Safari 静默拦截音频播放,Rocky 的外星原声和 TTS 都不出声 - **Root cause**: 浏览器安全策略要求用户手势才能播放音频 - **Fix**: 实现 shared Audio element 模式——在用户点击"建立链路"按钮时 unlock,后续复用同一个 Audio 元素 - **Prevention**: 移动端项目从一开始就要考虑 autoplay 策略 ### Pitfall: 非英文 few-shot 会让模型困惑 - **Symptom**: 中文/日文模式下注入英文 few-shot,模型回复风格不稳定 - **Root cause**: 混合语言的 few-shot 让模型在语言切换时行为不可预测 - **Fix**: 只在英文模式注入 few-shot,中日文依赖 system prompt 指引 - **Prevention**: 多语言 prompt 工程时,few-shot 按语言分开管理 ## Build Guide (For Someone Starting Fresh) ### Prerequisites - Node.js 18+ - 一个 LLM API(推荐 MiniMax,成本低角色扮演好;或任何兼容 Anthropic/OpenAI 协议的 API) - ElevenLabs 账号(TTS,首月订阅 ~¥100) - 一个你真的喜欢的虚构角色(这是最重要的前提) - 可选:域名(GoDaddy 几十元) ### Recommended Build Order 1. **Day 1 上午 — 基础对话** - Vite + React 脚手架 - 简单 UI(一个输入框 + 消息列表) - 接入 LLM API,跑通一轮对话 - 写角色 system prompt(先短后长,迭代调优) 2. **Day 1 下午 — 3D 场景** - Three.js 场景(星空/背景) - 加载角色 3D 模型(找免费/低价模型) - 基础动画(浮动、旋转) - 全息/科幻效果(shader) 3. **Day 2 上午 — 音频体验** - TTS 集成(ElevenLabs 或其他) - 角色"原声"音效(预录或合成) - 移动端 autoplay 适配 4. **Day 2 下午 — 体验打磨** - 开屏/连接动画 - 对话轮次限制 + 分享解锁 - i18n(如果需要多语言) - 移动端适配 5. **Day 3 — 部署 + 分享** - 构建 + 部署(Vercel / YouWare / EdgeSpark) - 录屏做短视频素材 - 分享给会懂你的人 ### CLAUDE.md Template ```markdown # {角色名} Chat ## 项目概述 跟 {角色名} 的沉浸式对话体验。{角色来源}。 ## 核心原则 - 角色一致性是最高优先级——宁可功能少,也不能让角色"出戏" - 每次修改 prompt 后都要测试至少 5 轮对话 - 移动端是主要使用场景,所有功能必须移动端适配 ## 技术栈 - React + TypeScript + Vite - Three.js(3D 场景) - {LLM API}(角色对话) - {TTS API}(语音合成) ## 角色 Prompt 规则 - system prompt 在 src/prompts/ 目录 - 修改 prompt 时不要删除已有的 few-shot,追加新的 - 情绪标签(mood tag)用于驱动 3D 动画和音频选择 ## 音频 - 移动端使用 shared Audio element 模式 - 音频播放顺序:原声 → 翻译语音 - 预置问答使用本地音频,不走 TTS API ## 成本控制 - 高频问题用预置问答覆盖(零 API 成本) - 对话轮次限制 + 分享解锁(裂变 > 付费) ``` ## Lessons Learned ### On Product - **叙事内嵌限制**:把技术限制(API 成本 → 对话轮数)包装成故事设定(噬星体能源不足),用户不会觉得被限制,反而觉得更沉浸 - **预置 + 开放混合**:高频问题预置(稳定 + 免费),长尾问题走 LLM(灵活),是成本和体验的最佳平衡 - **分享机制**:让用户通过分享解锁功能,比直接付费的转化率高得多 ### On Vibe Coding - **直接动手比想半天强**:跟 agent 先 plan 一下方向然后立刻开始写,2 天能出 MVP - **真的喜欢才会做好**:开发者会自己去找 bug、找出戏的地方。热爱是最好的 QA - **AI 比你更会搜索**:让 AI 帮你找模型、找素材、找 API,它的搜索范围比你广 - **记得分享**:会有人懂你和喜欢你做的东西 ### On Technical Choices - **移动端音频从 Day 1 就要考虑**:shared Audio element 模式是必须的,不要等上线才发现没声音 - **多语言 prompt 要分开管理**:英文 few-shot 不要注入到中文/日文模式 - **全息 shader 效果 > 高精度模型**:152KB 的低模 + 好的 shader = 比高精度模型更好的全息效果 - **SSE 流式是必须的**:对话体验中,流式输出 + 打字光标 = 基本体验底线