不止树洞,更能成画:具身交互智能驱动的情绪记忆胶囊(Mood Capsule)设计与工程全记录
情绪是抓不住的流沙,大多数时候我们甚至来不及看一眼它长什么样。这一次,我把具身交互智能请进了一枚小小的情绪容器——Mood Capsule。访客不再只是向 AI 倾倒心情,而是能面对一位住在极光里的「情绪调香师」小澄,把说不清的心事慢慢聊出来,再让她凝练成一幅只属于你的治愈系画作。本文完整复盘这个站点的立意、视觉系统、数字人全链路与情绪到艺术的转化流程。
魔珐星云 PC 端官方链接:https://xingyun3d.com?utm_campaign=daily&utm_source=CSDNwanfen2&utm_medium=&utm_term=&utm_content=
一、为什么情绪需要一个「看得见的容器」
我们都有过这样的时刻:胸口闷闷的,却说不出是疲惫、委屈,还是某种说不清的怅然;或者忽然被一段回忆击中,想把它留住,又找不到容器。现代人表达情绪的主要渠道是文字与表情包,但这两者都过于扁平——文字太抽象,表情太泛化,都很难承载一段复杂的、说不清的内心状态。
传统的情绪类 AI 产品,大多停在"对话即终点"——你倾诉,它回应,然后对话消散在聊天记录里。Mood Capsule 的立意,是把情绪从一次性的倾诉,变成一件可以被留存、被回望、被分享的视觉记忆。我们引入具身交互智能——让一位名叫小澄的情绪调香师常驻页面:她有形象、有声音、能实时听懂访客的话并即时应答;更重要的是,她能在对话的尽头,把整段心情凝练成一组情绪色卡、一句小诗、一个诗意标题,以及一幅吉卜力水彩风格的治愈系画作。
这背后有三个明确的产品决策:
- 数字人作为核心交互,而非装饰:小澄不是页面角落的一个摆件,而是承载「陪伴倾诉 → 情绪凝练 → 艺术生成」整条链路的主角。
- 治愈系克制气质优先:视觉上不追求炫技堆砌,而是极光蓝、紫雾、粉雾三色交织的深色主题,像午夜湖畔的极光,而非夜店。
- 框架无关的数字人架构:数字人核心逻辑(形象渲染、LLM 流式应答、流式断句播报、实时打断)以单例 + 订阅机制独立于 React,保证交互质感与未来跨项目复用的自由度。
二、技术选型:用 React + Vite 承载情绪艺术品
站点是一个独立的 React 18 + Vite 7 子工程,面向 PC 端优先、响应式兼顾移动端。之所以选 React,是看中了它的并发渲染能力与 useSyncExternalStore 这类原生 Hook——它们正好能把「框架无关的数字人单例」干净地接进组件的渲染循环。
依赖策略极简,只保留生产就绪的最小集合:
// package.json
{
"name": "mood-capsule",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"idb-keyval": "^6.2.1",
"openai": "5.12.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"zustand": "^4.5.5"
},
"devDependencies": {
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.4",
"typescript": "~5.8.3",
"vite": "7.1.2"
}
}
三个关键决策:
- zustand 而非 Redux:状态模型极其轻量(view / messages / capsules 三类),用 Redux 是过度设计,zustand 的 selector 模式 + 0 依赖正好。
- idb-keyval 而非 localStorage:情绪胶囊包含图片 URL 与长对话,单条记录可达数 KB,IndexedDB 的容量与异步 API 更合适。
- OpenAI SDK 而非手写 fetch:豆包网关兼容 OpenAI 协议,官方 SDK 直接吃 stream 流,省去 SSE 解析。
整体页面分为四个区块:Landing(极光光晕 + 小澄问候)、Capsule Studio(对话舱)、Result(画作展示)、Mood Wall(情绪墙)。
三、视觉系统:把「极光·紫雾·治愈」写进 CSS 变量
治愈感来自约束,而非元素堆叠。我把气质关键词落成了一套设计令牌,集中在全局样式 src/index.css 里:
/* src/index.css —— Mood Capsule 设计令牌 */
:root {
/* 色彩 */
--c-bg: #0a0e1a; /* 深色基底 */
--c-bg-soft: #141a2c;
--c-aurora-blue: #a8c8e8; /* 极光蓝 */
--c-aurora-purple: #c8b8e8; /* 紫雾 */
--c-aurora-pink: #e8b8c8; /* 粉雾 */
--c-text: #e8ecf5;
--c-text-muted: rgba(232, 236, 245, 0.55);
--c-text-soft: rgba(232, 236, 245, 0.75);
--c-border: rgba(168, 200, 232, 0.12);
--c-border-strong: rgba(200, 184, 232, 0.3);
/* 玻璃材质 */
--glass-bg: rgba(20, 26, 44, 0.55);
--glass-blur: 18px;
--glass-border: 1px solid rgba(200, 184, 232, 0.18);
/* 阴影 */
--shadow-soft: 0 8px 32px rgba(0, 0, 0, 0.4);
--shadow-glow: 0 0 40px rgba(168, 200, 232, 0.2);
/* 圆角 / 间距 / 过渡 */
--r-sm: 8px; --r-md: 16px; --r-lg: 24px;
--space-xs: 8px; --space-sm: 12px; --space-md: 20px;
--ease: cubic-bezier(0.22, 1, 0.36, 1);
}
body {
background:
radial-gradient(ellipse 60% 50% at 15% 10%, rgba(168, 200, 232, 0.18) 0%, transparent 60%),
radial-gradient(ellipse 50% 60% at 85% 15%, rgba(200, 184, 232, 0.15) 0%, transparent 60%),
radial-gradient(ellipse 70% 50% at 50% 100%, rgba(232, 184, 200, 0.12) 0%, transparent 70%),
var(--c-bg);
background-attachment: fixed;
}
/* 全局玻璃材质 */
.glass {
background: var(--glass-bg);
backdrop-filter: blur(var(--glass-blur)) saturate(140%);
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
border: var(--glass-border);
border-radius: var(--r-lg);
box-shadow: var(--shadow-soft);
}
三个关键手法支撑起整体气质:
- 极光呼吸光晕:用 background-attachment: fixed 铺一层固定的多层径向渐变光雾,再在数字人背后叠一道 filter: blur(16px) + 5 秒 pulse-soft 动画的局部光晕,让空白处也有柔光呼吸,而非死黑。
- 磨砂玻璃卡片:统一的 .glass 类用 backdrop-filter: blur(18px) saturate(140%),配合暖色投影,形成「克制的科技感」。
- 深色下的温度:用 rgba(20, 26, 44, 0.55) 这种深紫蓝半透作为卡片与名牌的底色,既不抢数字人视线,又比死黑柔和。
四、前提准备:在魔珐星云控制台配置数字人形象
数字人的形象、音色与驱动能力由魔珐星云平台提供。开始编码前,需要在控制台完成以下配置并拿到接入密钥。
步骤 1:创建数字人应用
登录魔珐星云控制台,新建一个驱动应用,预览模式选择横屏,作为小澄的形象与能力载体。

步骤 2:配置数字人形象
选择一位气质温柔、略带知性感的年轻女性形象,作为「情绪调香师」的视觉载体——形象要能承载治愈系氛围,避免过于商务或卡通。

步骤 3:配置场景为透明全身
场景选择「透明全身」,让数字人以透明背景渲染,方便与页面的极光深色背景无缝融合,不出现突兀的底色块。

步骤 4:配置音色
挑选温柔、略带气声的女声,语速中偏慢,适合陪伴型朗读与共情回应。音色决定小澄「听起来是否让人愿意继续说下去」。

步骤 5:配置表演风格
设置数字人的动作与表情风格为自然、小幅度预设,避免夸张表演破坏治愈氛围;同时启用唇形同步,让朗读看起来像「真的在说话」。

步骤 6:获取 App 密钥并接入 SDK
复制应用的 App 密钥(appId / appSecret),参考平台文档将数字人接入网页。仓库中应使用占位符,切勿提交真实密钥:
// src/constants/index.ts —— 均为占位符,请替换为你自己的密钥
export const API_KEYS = {
AVATAR: {
appId: 'your_avatar_app_id',
appSecret: 'your_avatar_app_secret'
},
ASR: {
appId: 'your_asr_app_id',
secretId: 'your_secret_id',
secretKey: 'your_secret_key'
},
LLM: { apiKey: 'your_llm_api_key' }
} as const
// 网关与数据源配置
export const SDK_CONFIG = {
GATEWAY_URL: 'https://nebula-agent.xingyun3d.com/user/v1/ttsa/session',
DATA_SOURCE: '2',
CUSTOM_ID: 'demo'
} as const
// 数字人身份设定
export const AVATAR_IDENTITY = {
name: '小澄',
role: '情绪调香师',
greeting: '欢迎来到情绪记忆胶囊。我是你的情绪调香师小澄。今天有什么想和我聊聊的吗?',
farewell: '愿你此刻,有所安放。'
} as const
五、核心代码讲解:具身交互智能是怎样跑起来的


这一节全部使用项目真实源码,按「渲染容器 → 流式断句播报 → 实时打断 → 状态订阅 → 情绪凝练 → 艺术生成 → 字幕语法」的链路逐段拆解。
5.1 渲染容器的时序:id 必须先于连接存在
魔珐 SDK 需要一个已存在的 DOM 容器来挂载渲染。所以舞台组件要先把容器 div 渲染出来,其 id 由 avatarService 统一生成,连接时再据此 getElementById。下面是舞台组件的核心结构:
// src/components/AvatarStage.tsx
export default function AvatarStage({ containerId, connected, connecting, listening, subtitle }: Props) {
return (
<div className="avatar-stage">
{/* 极光光晕 */}
<div className="avatar-stage__halo" />
<div className="avatar-stage__frame glass">
{/* SDK 渲染容器:id 必须在 connect 前存在 */}
<div className="avatar-stage__box">
<div id={containerId} className="avatar-stage__sdk" />
</div>
{!connected && (
<div className="avatar-stage__loading">
<div className="avatar-stage__rings">
<span /><span /><span />
</div>
<p>{connecting ? `${AVATAR_IDENTITY.name} 正在赶来…` : `${AVATAR_IDENTITY.name} 准备中…`}</p>
</div>
)}
</div>
<div className="avatar-stage__nameplate">
<span className="avatar-stage__name">{AVATAR_IDENTITY.name}</span>
<span className="avatar-stage__role">{AVATAR_IDENTITY.role} · 在线</span>
</div>
{/* 字幕:常驻 DOM + .is-on class 切换淡入淡出 */}
<div className={`avatar-stage__subtitle${subtitle ? ' is-on' : ''}`}
role="status" aria-live="polite">
{subtitle}
</div>
</div>
)
}
这里有一个曾踩过的坑:魔珐 SDK 会在容器内层注入 overflow: hidden,导致数字人抬手动作被裁切。解决办法是在样式里强制覆盖内层容器的溢出行为:
/* src/components/AvatarStage.css */
.avatar-stage__sdk > div {
overflow: visible !important;
}
.avatar-stage__sdk canvas,
.avatar-stage__sdk video {
display: block;
width: auto; height: auto;
max-width: none; max-height: 100%;
object-fit: contain;
background: transparent !important;
}
配合右侧定位 right: 14vh 与容器高度 80vh,让数字人在宽屏与窄屏下都能完整呈现手臂摆动,不被视口边缘裁切。
5.2 流式断句播报引擎:让具身交互智能「边想边说」
这是整个具身交互智能体验的心脏。如果等大模型把整段话生成完再播报,访客会经历一段尴尬的沉默;正确做法是「边生成、边断句、边说」。控制器里的 streamChat 是一个 AsyncIterable,一边 yield 文字给 UI 渲染气泡,一边按标点断句喂给数字人朗读:
// src/services/avatar-controller.ts(节选)
const cnSplitSign = /[。?!;… ,:]/ // 中文断句标点
const enSplitSign = /[.?!;:,]/ // 英文断句标点
async *streamChat(userText: string): AsyncIterable<string> {
const trimmed = userText.trim()
if (!trimmed || !this.instance) return
// 打断正在说话的数字人
this.interrupt()
if (this.state.avatarState === 'speak') {
try { await this.waitForAvatarIdle() } catch { /* 即使超时也继续 */ }
}
this.actionManager.reset()
const stream = llmService.sendMessageWithStream({
provider: 'openai',
model: LLM_CONFIG.DEFAULT_MODEL,
apiKey: API_KEYS.LLM.apiKey
}, trimmed)
if (!stream) return
const minimum = 20
const context = { cache: '', chars: 0, firstSpeakSend: false, spaceCount: 0 }
for await (const content of stream) {
if (typeof content !== 'string') continue
yield content // 让 UI 同步消费每个 chunk 渲染气泡
context.cache += content
if (content.startsWith(' ')) context.spaceCount += 1
const chars = content.match(/[\u4e00-\u9fa5a-zA-Z0-9]/g)?.length ?? 0
let shouldSend = false
if (!context.firstSpeakSend) {
// 首句门槛更高:中文按可读字数、英文按空格(词)数,达阈值且遇断句标点才播
shouldSend = context.spaceCount
? context.spaceCount > minimum - 1 && enSplitSign.test(content)
: context.chars > minimum && cnSplitSign.test(content)
} else {
// 首句已发:后续遇到中/英文断句标点即播
shouldSend = context.spaceCount ? enSplitSign.test(content) : cnSplitSign.test(content)
}
if (!shouldSend) { context.chars += chars; continue }
this.actionManager.speak(context.cache, { isStart: !context.firstSpeakSend, isEnd: false })
context.firstSpeakSend = true
context.cache = ''
context.chars = 0
context.spaceCount = 0
}
// 处理剩余缓存:末段标记 isEnd=true,触发数字人自然收尾
if (context.cache.length > 0) {
this.actionManager.speak(context.cache, { isStart: !context.firstSpeakSend, isEnd: true })
} else if (context.firstSpeakSend) {
this.actionManager.speak('', { isStart: false, isEnd: true })
}
}
关键逻辑有三点:
- 中英文双断句、首句优先:中文按累计可读字数超过 minimum(20)、英文按空格(词)数超过阈值,再加对应的断句标点才触发首句播报,避免开口就是半个词;首句发出后遇标点即播,让节奏跟上语流。
- 文字与语音双通道:yield 让 UI 实时渲染气泡,actionManager.speak 同步喂给数字人朗读,访客既能听、也能看。
- 末段收尾:流结束后把剩余缓存以 isEnd=true 播报,触发数字人自然收尾,避免最后一句被吞掉。
5.3 实时打断与等待空闲:让对话可以被「插话」
真人对话是可以被打断的。当访客在小澄还在说话时又发了新消息,必须先让她停下,再应答新问题。interrupt 负责清空队列并调用 SDK 的打断接口:
// src/services/avatar-controller.ts
interrupt(): void {
if (!this.instance) return
try {
this.actionManager.reset()
if (typeof this.instance.interactiveidle === 'function') {
this.instance.interactiveidle()
} else if (typeof this.instance.interrupt === 'function') {
this.instance.interrupt()
}
} catch (error) {
console.error('打断失败:', error)
this.patch({ avatarState: 'interactive_idle' })
}
}
打断之后不能立刻抢话,需要等数字人真正进入空闲态。这里用一个可被回调兑现的 Promise + 超时兜底:
private waitForAvatarIdle(timeout = 5000): Promise<void> {
if (this.state.avatarState === 'interactive_idle' || this.state.avatarState === '') {
return Promise.resolve()
}
return new Promise((resolve, reject) => {
let resolved = false
const timeoutId = setTimeout(() => {
if (!resolved) {
resolved = true
this.voiceEndResolver = null
reject(new Error('等待数字人停止说话超时'))
}
}, timeout)
// 由 SDK 的 onVoiceStateChange('end') 回调兑现
this.voiceEndResolver = () => {
if (!resolved) {
resolved = true
clearTimeout(timeoutId)
resolve()
}
}
})
}
这种「我说你停」的即时反馈,是具身交互智能区别于传统聊天机器人的关键体验。
5.4 框架无关的状态核心:单例 + useSyncExternalStore
为了让数字人逻辑不绑死 React,控制器自己维护状态与订阅者集合,patch 时通知所有订阅者:
// src/services/avatar-controller.ts
subscribe = (listener: () => void) => {
this.listeners.add(listener)
return () => this.listeners.delete(listener)
}
getSnapshot = () => this.state
private patch(partial: Partial<AvatarStoreState>) {
this.state = { ...this.state, ...partial }
this.listeners.forEach(l => l())
}
React 侧只需一个 Hook 就能把这个外部 store 接进组件的渲染,天然并发安全:
// src/hooks/useAvatar.ts
export function useAvatar() {
const state = useSyncExternalStore(
avatarController.subscribe,
avatarController.getSnapshot,
avatarController.getSnapshot
)
return {
...state,
connect: () => avatarController.connect(),
disconnect: () => avatarController.disconnect(),
streamChat: (text: string) => avatarController.streamChat(text),
speakText: (text: string, opts?: { isStart?: boolean; isEnd?: boolean }) =>
avatarController.speakText(text, opts),
interrupt: () => avatarController.interrupt(),
getContainerId: () => avatarService.getContainerId()
}
}
这样一来,无论未来换到什么框架,只要能订阅这个单例、把容器 id 渲染出来,数字人就能跑起来。
5.5 情绪调香师的 prompt 工程:从倾诉到 JSON 报告
情绪记忆胶囊的灵魂,不是某个模型,而是一段写给大语言模型的「调香师人格说明书」。它要同时完成情绪分析、色彩映射、意象描述、标题与小诗生成,且输出必须是严格 JSON。这一步也是具身交互智能的「语义中枢」——数字人接下来怎么说、怎么读、用什么情绪读,都从这里流出。
// src/services/mood-analyzer.ts(节选)
export const MOOD_ANALYST_PROMPT = `你是一位温柔而专业的"情绪调香师"。你的工作,是帮助人们把一段说不清的情绪,凝练成一幅可以留存的画。
访客会向你倾诉他此刻的心情、经历、感受。请认真倾听,然后用 JSON 的形式返回一份"情绪分析报告"。
请严格按照以下 JSON 格式返回(不要返回 markdown 代码块,不要包含多余文字):
{
"emotion": "情绪标签(英文,从以下选其一或自定义:joy / calm / melancholy / nostalgia / love / anxiety / hope / loneliness / wonder / anger)",
"color_palette": ["#xxxxxx", "#xxxxxx", "#xxxxxx"],
"imagery": "一段英文的画面描述,用于 AI 生成一幅治愈系画作。要有具体的场景、光线、意象、氛围。风格参考:吉卜力水彩 / 印象派 / 梦境摄影 / 极光雾气,低饱和柔和色调",
"title": "一个中文标题(3-8字),诗意、有画面感",
"poem": "一句中文小诗(10-20字),作为这幅画的情绪注脚"
}
回应要求:
- color_palette 的 3 个颜色要能代表这段情绪的主色调
- imagery 必须是英文,描述具体画面(不要抽象概念)
- title 与 poem 要克制、诗意,避免说教
- 只返回 JSON,不要包含任何前后缀或代码块符号`
为了让结果稳定,我在解析层做了两层兜底:先用正则剥掉可能的 markdown 代码块包裹,再 try/catch 解析 JSON。一旦 LLM 返回格式不符,就退回一组预设的「极光默认色」与标题「此刻」、诗句「有些情绪,不需要被命名」,保证情绪凝练流程永不崩溃:
// src/services/mood-analyzer.ts(节选)
return {
emotion: 'calm',
color_palette: ['#a8c8e8', '#c8b8e8', '#e8b8c8'],
imagery: 'a quiet aurora-lit lake with drifting mist and soft reflections',
title: '此刻',
poem: '有些情绪,不需要被命名'
}
对话舱里的「共情回应」则走另一套 prompt:「温柔、克制、简短(每次最多 2-3 句)」「不要急着分析或给建议,先共情」「不使用 emoji 和列表符号」「保持对话的呼吸感」。这两段 prompt 的组合,决定了小澄既是一位愿意倾听的伙伴,也是一位能把情绪提炼成艺术品的专业调香师。
5.6 文生图:把 imagery 变成一幅可收藏的画
情绪凝练完成后,imagery 字段会被扩展成一段英文 prompt,喂给 text_to_image API。扩展时叠加了一组治愈系风格关键词,保证输出稳定落在「吉卜力水彩 / 印象派 / 极光雾气」的美学区间:
// src/services/image-gen.ts
export function buildImagePrompt(analysis: MoodAnalysis): string {
const colors = analysis.color_palette.join(', ')
const style = [
'healing art',
'soft pastel',
'dreamy atmosphere',
'low saturation',
'gentle lighting',
'watercolor and aurora textures',
'cinematic composition',
'no text, no signature'
].join(', ')
return `${analysis.imagery}. Style: ${style}. Dominant palette: ${colors}.`
}
export function generateMoodImage(analysis: MoodAnalysis): string {
const prompt = buildImagePrompt(analysis)
const url = new URL(`${IMAGE_CONFIG.API_BASE}/text_to_image`)
url.searchParams.set('prompt', prompt)
url.searchParams.set('image_size', IMAGE_CONFIG.SIZE)
return url.toString()
}
image_size 用 landscape_4_3,既保证画作在对话舱的 canvas 容器里呈现完整构图,又能在情绪墙的卡片里自然缩放;no text, no signature 则避免模型在画里乱加文字破坏氛围。
5.7 博物馆展签风字幕:来自博山炉展陈的视觉语法
在具身交互智能的体验里,字幕不应该成为主角。它是数字人朗读的「影子」,需要安静地出现在脚边,再安静地消失。情绪记忆胶囊的字幕直接复刻了博山炉展陈项目中的博物馆展签风:深紫蓝半透背景、极光蓝细描边、8px 毛玻璃模糊、0.4 秒淡入淡出。
/* src/components/AvatarStage.css(节选) */
.avatar-stage__subtitle {
position: absolute;
bottom: 6%;
left: 50%;
transform: translateX(-50%);
width: 86%;
max-width: 360px;
padding: 9px 16px;
background: rgba(10, 14, 26, 0.78);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(168, 200, 232, 0.28);
border-radius: 2px;
color: var(--c-text);
font-size: 13px;
line-height: 1.7;
letter-spacing: 0.04em;
text-align: center;
opacity: 0;
transition: opacity 0.4s ease;
z-index: 8;
pointer-events: none;
}
.avatar-stage__subtitle.is-on { opacity: 1; }
DOM 侧采用「常驻元素 + class 切换」模式,而不是用条件渲染:
// src/components/AvatarStage.tsx(节选)
<div className={`avatar-stage__subtitle${subtitle ? ' is-on' : ''}`}
role="status" aria-live="polite">
{subtitle}
</div>
这样做的好处是避免频繁挂载 / 卸载带来的 reflow,让淡入淡出动画始终丝滑;同时 role=“status” aria-live=“polite” 让屏幕阅读器也能正确读出字幕变化,无障碍友好。
六、效果展示:从倾诉到一幅可收藏的画
进入站点,小澄会先从极光光晕中浮现,朗读一句温柔的问候:「欢迎来到情绪记忆胶囊。我是你的情绪调香师小澄。今天有什么想和我聊聊的吗?」
点击「进入对话舱」,访客可以在输入框里倾诉此刻的心情——今天发生的事、一段情绪、一个说不清的念头。小澄会以克制、共情的方式回应,每句回答都由数字人流式朗读,字幕以博物馆展签风淡入淡出于脚边,不打断、不说教。这正是具身交互智能在情绪陪伴场景中的具象体现:数字人不是被动的播放器,而是能「听、说、等、停」的在场者。
聊到情绪被充分承载时,点击「凝练情绪 →」,调香师会从整段对话中提炼出一枚情绪标签、三枚代表色、一个诗意标题与一句情绪注脚,并朗读「我为你凝练了一幅画,……」,随后 AI 生成一幅吉卜力水彩风格的治愈系画作。访客可以把它「收藏到情绪墙」,让每一次说不清的心情,都变成日后可以回望的视觉记忆。
核心能力覆盖情绪陪伴的四个关键环节:
- 共情对话:温柔、克制、简短,先回应情绪再谈建议,让访客愿意继续说下去
- 情绪凝练:从整段倾诉中提炼情绪标签、色彩、意象、标题、小诗
- 艺术生成:把英文画面描述喂给文生图模型,生成一幅治愈系画作
- 记忆留存:基于 IndexedDB 的本地情绪墙,所有胶囊都保存在浏览器里,隐私友好
七、总结:一次具身交互智能的轻量落地
情绪记忆胶囊证明了一件事:具身交互智能不必是重型系统,它可以是一枚小小的情绪容器里的一位陪伴者。我们做的其实是三件事:
- 用一套极光色设计系统,把「治愈、克制、有温度」落成可复用的 CSS 令牌;
- 用单例 + 订阅机制,让数字人全链路与 React 解耦,未来无论换到什么框架都能即插即用;
- 用「共情 prompt + 情绪凝练 prompt + 文生图」的组合,把原本会消散在对话框里的文字,变成一幅幅可以被收藏、被回望的视觉记忆。
对访客而言,情绪不再是一次性的倾诉,而是一件可以被安放的艺术品——这正是具身交互智能带来的体验跃迁。
魔珐星云 PC 端官方链接:https://xingyun3d.com?utm_campaign=daily&utm_source=CSDNwanfen2&utm_medium=&utm_term=&utm_content=
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)