本项目目前已完成 Demo 开发并已部署上线,可以点击链接体验 Demo,也可前往 GitHub 仓库查看源代码。
一、项目简介 #
Her 是一个以图像记忆为入口的中文 AI 语音陪伴 Demo,尝试让图片、对话、声音与记忆保存共同构成一次可以重新进入的交流。用户上传一张照片,大模型将画面中的可见线索作为对话起点,随后通过文字或语音展开交流,并把这次交流保存为一段可以重新进入、聆听和回看的设备本地记忆。
Her 的产品逻辑十分简单:
照片 → 图像理解 → 文字 / 语音交流 → 保存为记忆 → 再次进入
在开发 Her 这一项目的进程中,我独立发起并主导了产品定义、需求拆解、模型选择、交互设计、迭代验收与部署上线,主要借助 Gemini 与 Codex 完成技术调研、工程实现、测试与部署。
项目第一版 Demo 的开发时间段为 2026 年 7 月 15 日至 2026 年 7 月 30 日,在两周窗口内用 8 个活跃开发日完成从想法、可交互 Demo 到公网部署,累计 56 次 Git 提交。
二、我想解决的问题 #
1. 项目缘起 #
需要指出的是,Her 这一项目的 idea 原型来自 Spike Jonze 的电影 Her,以及博主「秒秒 Guo」更早的 Demo 实现。在此基础上,结合我个人使用语音模型的体验,我认为**以图片为媒介的特殊视觉展示,结合音乐、语音、停顿与上下文,可以更容易捕捉用户的私密情绪,甚至是某种难以言明且不知如何表达的思绪,进而使 AI 产品比以往语言或纯语音模型更能产生一种「在场的陪伴」**。
相对而言,普通的 AI 对话产品面临着以下三个问题:
- 对话从空白输入框开始。 用户需要先想清楚「我要说什么」,仍然存在较高的开口成本。
- 对话结束后只剩聊天记录。 一段有意义的交流很快沉入时间线,缺少可供记录与重新进入的载体。
- 缺少独特的视觉与声音体验。 视觉与声音的多样化体验常在普通产品中处于缺位状态,即便有的产品引入视觉与声音实验,它们也没有与用户正在谈论的对象、说话状态和记忆结果形成同一套体验。
基于此,我对 Her 的产品假设逐渐明确为,如果让一张照片成为用户和 AI 共同注意的对象,再让图像、语音与记忆保存共同参与交互,AI 陪伴就可能不只是如传统设计一般只是「得到一句回复」,还能帮助用户重新接近一段经历。
2. 目标用户与场景 #
以下定位来自个人观察、参考产品 Demo 拆解与开发中的体验假设,尚未经过正式市场调研与用户访谈验证。Demo 首版面向习惯通过照片回看生活、抒发情感与思绪的中文用户——具体来说,其实第一个面向者就是我自己。
相对而言,日常生活中往往是那些安静(夜深人静)、等待(比如在公交车上)的时刻会勾起人缅怀过往的思绪。但我认为重要的并非场景,而是「触发点」——或许是某次醒来后对出现在梦中的已故之人的思念,或许是一天劳作以后的疲惫让人渴望能有人分享这一刻的所见所想,又或许是睡前涌现出的情绪让人渴望能被聆听……因而场景并不固定,毕竟谁能说清楚何时何地会产生「万千思绪」?
不变的是人一定会有渴望安放情绪的时刻,那么「此时此刻」,我希望 AI 能从画面出发,用克制的方式陪我谈一会儿,并将这次交流整理成日后可以重新进入的记忆。
3. 设计原则 #
在多次与 Codex 协作以后,我逐渐提炼出以下设计原则以约束大模型进行开发。
- 记忆优先于聊天。 聊天是过程,照片与保存后的记忆才是用户反复进入的对象。
- 氛围服务于内容。 粒子、音乐和动效必须回应图像与声音,不能遮挡主体或拖慢关键操作。
- AI 的判断必须可被纠正。 模型只能提出低置信度的氛围假设,用户的自述永远优先。
- 让数据边界可理解、可控制。 用户应当清楚什么内容只保存在设备、什么内容会发送给云端模型,并能在发送前主动决定。当前版本可以关闭图像理解,但默认仍为开启,尚未做到逐次主动授权。
- 先闭环,再加功能。 每一个新增功能都需要 Codex 回答:当前项目是否保证「照片—对话—记忆」的闭环可以更加完整?
三、核心体验 #
1. 将照片转换为「粒子记忆」 #
用户在网站上传照片后,系统会将图像重构为高密度、可交互的 WebGL 粒子画面,以营造出一种记忆的模糊感与梦核1感。粒子会响应鼠标的悬浮拖拽、背景音乐节奏和用户语音音量而发生位移、光晕闪烁等效果。另外,用户可以缩放画面或隐藏界面,只保留粒子图像。
关于背景音乐,用户可以在 Demo 中添加 .mp3 或 .flac 格式的音乐,并可以在可展开的音乐列表中进行音乐切换。目前,我在 Demo 中内置了电影 Her 中的一首曲子 Song On The Beach 作为默认背景音乐。
目前系统默认上限为 262,144 个粒子,并会根据设备内存、CPU、屏幕和 reduced-motion 设置调整粒子数量。由于需要平衡粒子化与图像主体的清晰度,因此粒子并非越多越好。
- 上传图像的主体需要保持可辨认度,否则照片会失去记忆锚点。
- 上传图像边缘在保持可辨认度的同时,需要有自然的溶解、流动和呼吸感,否则效果只是套在原图上的滤镜。
保存后的照片会进入「记忆」画廊,成为漂浮在黑色空间中的粒子对象,支持滚轮、拖动和点击进入,以为用户营造一种正在浏览一组记忆的感受。
2. AI「看见」粒子记忆 #
当前版本的图像理解默认开启,浏览器会通过 Cloudflare Worker 将图片内容发送给 Qwen,Qwen 则会根据图片内容主动与用户交流。2
图片理解结果会被拆成几类结构化信息:
- 画面中可以直接观察到的对象与关系
- 可能的氛围线索及其依据
- 对这一判断的置信度
- 一个从画面自然引出,但不替用户下结论的问题
这套设计主动避免通过人物外观推断用户的真实情绪、身份、健康或敏感属性。例如,AI 可以根据图像说「冷色和空旷构图让我联想到安静」,但不会对用户说「你当时一定很孤独」。我认为这是当前 Demo 需要明确的判断,即模型的「能看图」不等于有能力替用户解释记忆。
不过关于图像部分的交互,还需要在多次测试后专门给大模型写一份 .md 的 Prompts。
3. 语音交互的完整链路 #
用户可以输入文字,也可以通过浏览器语音识别完成中文转写,以与 AI 进行对话。AI 的回复由 qwen-audio-3.0-tts-plus 合成为语音,前端则使用真实音频能量驱动波形和粒子。
语音会被拆成独立能力,不与聊天模型绑定:
- 浏览器语音识别负责将用户声音转成文字
- 对话模型负责理解上下文和组织回复
- TTS 模型负责音色、语速和表达风格
- 播放层负责流式接收、缓存、波形与被打断后的状态恢复
4. 让对话成为可回顾的对象 #
当用户认为可以结束与 AI 的交互时,点击「留住记忆」,系统会根据会话生成标题、摘要和整理后的正文,并保存以下内容:
- 原始照片与粒子展示
- 用户和 AI 的逐轮文本
- 时间戳与会话时长
- 在设置中启用的用户原声保存(当前默认开启)
- 图片理解上下文与记忆摘要
另外,用户可以在回廊中阅读记忆卡片、重放语音、删除内容,也可以把记忆固定到当天的日历。当前记忆数据默认保存在浏览器 IndexedDB 中,不会自动上传或跨设备同步。这里的「本地记忆」并不等于「完全离线」:图片理解、对话、总结和 TTS 启用时,相应内容仍会经过服务端发送给云端模型。
四、Eval 评测 #
当前项目完成的进度是开发一个可以进行基本功能运行的 Demo,但还有许多方面需要测试。
| 要验证的问题 | 当前方法与证据 | 仍然缺少 |
|---|---|---|
| 核心闭环能否跑通 | 1. lint、类型检查、生产构建通过; 2. 服务端渲染、Mock API、关键交互契约 3 组 smoke / contract tests; 3. 线上冒烟验证 |
浏览器端 E2E、多设备、弱网与长会话稳定性测试 |
| 图片理解是否克制 | 1. 使用风景、人物和情绪不明确图片测试; 2. 加入「可见事实—氛围假设—依据—置信度—问题」结构; 3. 验证用户否认后模型会修正 |
固定测试集、评分 Rubric 与多人一致性评审 |
| 语音是否比系统朗读自然 | 从浏览器 speechSynthesis 迁移至 Qwen TTS,真实检查 WAV、播放链路和连续多轮录音 |
目标用户盲听、音色偏好与中断率 |
| 粒子效果是否兼顾辨识与氛围 | 1. 对参考视频逐帧拆解,使用同图、固定音频反复对照; 2. 对失败版本执行回退 |
不同设备 FPS、GPU 占用和视觉可读性量表 |
| 服务是否足以公开展示 | GitHub 版本管理、Cloudflare 自动构建、密钥隔离、限频与错误边界 | 真实访问量、成本、完成率与留存数据 |
五、迭代 #
一个完整、可持续的产品定然不是一次性完成,因此 Demo 需要经过一次又一次的迭代。回顾我对项目的迭代,大致可以归纳为以下五次。
迭代一:从静态参考图到可验收的交互状态 #
最初的迭代需求源于 UI 与 UX 设计。我直接给 Codex 提供静态图片,但这些静态图像无法清晰说明粒子速度、回弹、声音映射和页面转场。经过多次尝试都无法得到期望效果,我同时给 Codex 提供了 9 张理想效果图片与 8 段参考视频,并明确让其将视觉拆解为待机、聆听、思考、回复、保存和回廊六类状态,才让 Demo 效果差强人意。
让大模型根据参考资料直接实现相应的效果一点也不现实,大模型只会在此基础上「自行发散思维」,「做成」其自认为开发者期望的感觉,因此需要开发者将需求明确转译为可观察的验收条件,例如同一张图片在静止、鼠标经过、拖拽和强音频下分别应发生什么,才是开发可以执行的需求。
迭代二:图片如何既能粒子化,又看得清主体 #
图片的粒子化视觉经历过几次明显失败:
- 粒子过强,主体只剩光点
- 为了保真加入清晰底图,拖动时却暴露出「底图 + 特效层」的割裂
- 把已经粒子化的参考图再次处理,造成双重粒子化
- 为追求上缘羽流加入触须式扩散,反而侵蚀主体
- 某次着色器变量被误删,导致整张图不显示
最终方案不再依赖固定底图,让高密度粒子共同构成有厚度的图像表面:图像的主体区域更加稳定,轮廓与外围承担扩散,音乐的节奏幅度和音量大小只让主体粒子呈现轻微的呼吸浮动感。不过,在调试多次都无法达到我最为期望的效果,反而还使得图像效果变得更为糟糕后,我还是做出了妥协,选择复现已经验证过的提交,而非继续堆补丁。
迭代三:从卡片列表改成真正的记忆画廊 #
第一版回廊设计为横向卡片,拖动、滚轮、点击与删除之间经常发生争抢。改成无边框粒子画廊后,又先后出现「点击无法进入」「删除被父级吞掉」「滚轮切换卡顿」等问题。
解决方案并非继续调动画速度,转而从重新划分手势职责出发:
- 拖动画廊空白区域才移动画廊
- 拖动粒子对象只影响粒子
- 移动超过阈值才进入拖拽模式
- 删除按钮使用独立点击层和更大的触摸热区
- 同时运行的实时粒子画布受控,其余记忆使用轻量预览
在此次迭代中,可以看出「丝滑」的交互不一定只关乎界面的帧率,也包括用户操作意图是否会遭受系统的误判。
迭代四:删除「看起来很 AI」的功能 #
早期版本包含多个 AI 角色彼此对谈的 AI Salon,也保留了英文回复和点击翻译。乍一看它们视觉上有趣且……高级(?),但实际上没有强化目标用户的核心任务——本质还是用户与 AI 基于图片发生的交互——还增加了页面、接口、数据结构和维护成本。
因此,在明确中文用户和「照片—对话—记忆」主线后,我删除了 AI Salon、翻译 API 与相关模型能力,并将导航收敛为「记忆 / 回廊 / 音乐」,同时将对话改为中文优先。
迭代五:从「能出声」到连续多轮可用 #
项目的语音最初使用浏览器系统朗读,虽然成本低,但音色机械,只会破坏产品试图营造的梦核感,断然不可使用。接入 Qwen TTS 后,项目又遇到临时音频域名、HTTPS、浏览器自动播放和录音后扬声器无法恢复等问题。
连续语音失败的根因是浏览器在录音结束后仍占用音频会话,错过了恢复扬声器的用户手势窗口。修复后的顺序变成「停止录音—释放麦克风—恢复扬声器—提交对话—播放回复」,并加入流式 PCM 播放、缓存和本地语音兜底。
六、当前结果、限制与下一步 #
当前, Her 是将范围限制在一个单用户、可运行、可展示的 Demo,可以将图片、文字与语音构成一次完整会话,且会话可被总结、保存、再次查看和删除。不过目前还没有增加账号,无法进行数据的云端同步,也无法像 Agent 一样可以自主执行外部任务。
当然,更重要的是,Her 离真正能判断用户情绪,具备真正陪伴感还有很多距离。
开发过程中,我曾试图将产品设计为 Agent,但从回顾期望实现的功能,我认为可以先只实现一个具备多模态理解、语音交互和本地记忆闭环的 AI 产品 Demo。在保证基础功能得以稳定实现后,未来再考虑丰富功能。
关于项目的当前限制,包括以下几点:
- 尚未对目标用户开展正式访谈、可用性测试或留存观察,因此无法说明解决了真实市场需求
- 图像理解和原声保存当前默认为开启,逐次主动授权、数据说明与图片压缩实现仍需优先补齐
- 浏览器语音识别的可用性依赖设备和浏览器,移动端与弱网还需要进行系统测试
- 本地记忆不会跨设备同步,清除网站数据也会清除内容
- 缺少面向陪伴类产品的完整安全机制,例如危机情境处理、依赖风险与模型输出治理
- 现有测试以构建、接口与源码契约为主,尚无浏览器 E2E、视觉回归和系统化 AI Eval
- 还没有埋点,因此不能提供转化率、保存率、复访率等业务指标
基于上述限制,下一阶段不适合继续扩展功能,而应当进行「验证」:
- 将图像理解与原声保存改为清晰的主动授权,补齐数据去向说明与真实图片压缩
- 邀请 5—8 位目标用户完成「上传—对话—保存—再次进入—删除」的任务测试
- 记录首轮对话完成率、首次回复等待、记忆保存率、误触点与主动退出原因
- 建立图片理解、对话、摘要与安全评测集,检查事实准确、过度推断、可纠正性与问题质量
- 对桌面和移动设备记录 FPS、首屏耗时、首字 / 首段语音等待、失败率和无障碍问题
- 只有在用户确实需要跨设备回看时,再评估账号、加密同步与云端成本
总的来说,Her 是我将一个模糊的体验想法,逐步拆成产品范围、AI 能力、交互状态、数据结构、评测方法和可公开访问的 Demo 的第二个项目。我并不期望从这样一次实践中就能把握成熟的产品经验,事实上这或许也不现实?但我想我还是持有在北师大计算暑校中受到的启发:在一次次的项目中「做中学」。
-
梦核(Dreamcore)指一种超现实主义美学,主要利用模模糊糊的低画质照片、柔和或明亮的色彩以及超脱现实的场景,进而重现人们在睡梦中的一种熟悉又陌生的感觉。 ↩︎
-
原始图片则同时保存在设备本地,用于之后恢复记忆。设置文案曾写「发送压缩副本」,但当前实现只是对符合大小限制的原文件编码后发送,并没有真正进行重采样压缩——这是在代码核对中发现、需要修正的产品与实现偏差。 ↩︎