情绪是抓不住的流沙,大多数时候我们甚至来不及看一眼它长什么样。这一次,我把具身交互智能请进了一枚小小的情绪容器——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 生成一幅吉卜力水彩风格的治愈系画作。访客可以把它「收藏到情绪墙」,让每一次说不清的心情,都变成日后可以回望的视觉记忆。

核心能力覆盖情绪陪伴的四个关键环节:

  1. 共情对话:温柔、克制、简短,先回应情绪再谈建议,让访客愿意继续说下去
  2. 情绪凝练:从整段倾诉中提炼情绪标签、色彩、意象、标题、小诗
  3. 艺术生成:把英文画面描述喂给文生图模型,生成一幅治愈系画作
  4. 记忆留存:基于 IndexedDB 的本地情绪墙,所有胶囊都保存在浏览器里,隐私友好

七、总结:一次具身交互智能的轻量落地

情绪记忆胶囊证明了一件事:具身交互智能不必是重型系统,它可以是一枚小小的情绪容器里的一位陪伴者。我们做的其实是三件事:

  • 用一套极光色设计系统,把「治愈、克制、有温度」落成可复用的 CSS 令牌;
  • 用单例 + 订阅机制,让数字人全链路与 React 解耦,未来无论换到什么框架都能即插即用;
  • 用「共情 prompt + 情绪凝练 prompt + 文生图」的组合,把原本会消散在对话框里的文字,变成一幅幅可以被收藏、被回望的视觉记忆。

对访客而言,情绪不再是一次性的倾诉,而是一件可以被安放的艺术品——这正是具身交互智能带来的体验跃迁。

魔珐星云 PC 端官方链接https://xingyun3d.com?utm_campaign=daily&utm_source=CSDNwanfen2&utm_medium=&utm_term=&utm_content=

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐