【开源】灵魂讲述者:基于魔珐星云的AI交互式分支叙事应用,免费体验啦!

人们眼中的天才之所以卓越非凡,并非天资超人一等而是付出了持续不断的努力。1万小时的锤炼是任何人从平凡变成超凡的必要条件。------------ 马尔科姆·格拉德威尔

🌟 Hello,我是Xxtaoaooo!

🌈 "代码是逻辑的诗篇,架构是思想的交响"


项目简介

大家好!今天给大家分享我最近做的一个开源项目------ 灵魂讲述者(Soul Teller)

这是一个基于魔珐星云具身智能平台的AI交互式叙事应用。简单来说:你选择一个故事世界,3D数字人实时给你讲故事,你可以通过对话和分支选择影响剧情走向,每一条选择都会带来不同的结局。

和传统的文字冒险游戏不同,这个故事没有预设脚本------所有剧情都由AI实时生成,每一次体验都是独一无二的。

新用户注册魔珐星云可以填写邀请码:J36AKZEFMK,可免费获取积分体验数字人,快来试试吧!

魔法星云地址: https://xingyun3d.com/

GitHub 项目地址: https://github.com/xtdexw/soul-teller


一、效果展示

1.1 故事世界选择

用户进入应用后,首先选择一个故事世界。目前支持赛博朋克、奇幻森林、悬疑推理等多种风格。

1.2 互动播放室

进入故事后,界面分为两个区域:

  • 左侧:3D数字人实时渲染,配合语音讲述剧情
  • 右侧:1. 分支选项面板,AI生成3个分支供选择 2. 剧情面板,展示当前剧情内容 3. Ai对话面板:实时沟通改变分支、剧情走向

同时支持故事剧情导出。

1.3 设置面板

所有API密钥都在页面内配置,密钥存储在浏览器本地,支持掩码显示,安全开箱即用。


二、核心功能

2.1 3D数字人实时讲述

通过魔珐星云SDK实现数字人实时渲染与语音合成:

复制代码
// 数字人初始化
const sdk = new XmovAvatar({
  containerId: '#avatar-container',
  appId: config.appId,
  appSecret: config.appSecret,
  gatewayServer: config.gatewayServer,
});

数字人支持:

  • 流式语音合成(TTS),边生成边朗读
  • 文本分块朗读与状态同步
  • 手动/自动连接控制

2.2 AI分支剧情系统

这是整个项目最核心的部分。一次API调用同时获取:续写内容(200-400字)+ 3个分支选项

复制代码
// 统一故事生成API
async generateStory(context: StoryContext): Promise<StoryNode> {
  const response = await fetch(config.apiUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${config.apiKey}`,
    },
    body: JSON.stringify({
      model: 'qwen2.5-72b-instruct',
      messages: this.buildPrompt(context),
    }),
  });
  // 同时返回剧情续写 + 3个分支选项
  return this.parseStoryResponse(response);
}

用户选择任意一个分支,AI会基于你的选择继续生成下一段剧情,形成真正的分支叙事体验。

2.3 智能上下文管理

为了让AI记住之前的剧情走向,我实现了一套混合上下文策略:

复制代码
// 混合上下文策略
buildContext(currentNode: StoryNode): string {
  return [
    this.getRecentStory(10),      // 最近10段剧情
    this.vectorSearch(2),         // 语义检索2个最相关历史节点
    this.getUserDialogue(),       // 用户的实时对话输入
  ].join('\n');
}
  • 最近剧情:内存中保存最近10段,保证连贯性
  • 向量检索:基于IndexedDB实现的本地向量存储,语义检索最相关的历史节点
  • 用户对话:实时纳入用户的对话输入

这套机制确保AI在长篇故事中也能"记住"之前的情节和伏笔。

2.4 动态背景系统

根据故事进展自动切换背景,10张背景图片循环使用,配合1秒淡入淡出的平滑过渡:

复制代码
// 根据节点序号切换背景
const bgIndex = (nodeIndex % 10) + 1;
setBackgroundWithTransition(`/images/back${bgIndex}.webp`);

2.5 智能连接状态管理

未连接数字人时,AI对话和分支选择会被禁用,避免用户在未就绪时操作:

复制代码
// 连接状态控制
const isConnected = useStore(state => state.isConnected);
// 未连接时禁用交互
disabled={!isConnected}

三、技术架构

3.1 技术栈

|------------|--------------------------------------------|
| 技术 | 说明 |
| 前端框架 | React 18 + TypeScript |
| 构建工具 | Vite |
| 状态管理 | Zustand + persist(持久化) |
| 样式方案 | TailwindCSS |
| 数字人SDK | 魔珐星云具身驱动SDK (xmovAvatar) |
| 大语言模型 | 通义千问 Qwen2.5-72B-Instruct (ModelScope API) |
| 向量模型 | 通义千问 Embedding-8B |
| 向量存储 | 自研轻量级向量存储(基于IndexedDB) |

3.2 项目结构

复制代码
soul-teller/
├── src/
│   ├── components/          # UI组件
│   │   ├── StoryHub/        # 故事世界选择
│   │   ├── PlayRoom/        # 互动播放室(核心页面)
│   │   ├── Settings/        # 设置面板
│   │   ├── Dialogue/        # AI对话面板
│   │   └── StoryTeller/     # 数字人容器
│   ├── services/            # 服务层
│   │   ├── StoryEngine.ts       # 故事引擎(核心调度)
│   │   ├── StoryGenerator.ts    # 故事生成器(AI调用)
│   │   ├── VectorStore.ts       # 向量存储(IndexedDB)
│   │   └── XingyunSDK.ts        # 星云SDK封装
│   ├── hooks/               # 自定义Hooks
│   │   └── useAvatar.ts         # 数字人生命周期管理
│   ├── store/               # Zustand状态管理
│   │   └── useStore.ts          # 全局状态(含persist)
│   ├── utils/               # 工具函数
│   │   ├── secureStorage.ts     # 安全存储(密钥掩码)
│   │   └── textChunker.ts       # 文本分块(TTS朗读)
│   ├── types/               # TypeScript类型定义
│   │   ├── story.ts             # 故事节点、分支类型
│   │   └── interaction.ts       # 交互事件类型
│   └── App.tsx
├── public/                  # 静态资源(背景图片等)
└── package.json

3.3 核心架构图

复制代码
flowchart TB
    %%{init: {'theme':'base', 'themeVariables':{'primaryColor':'#7c3aed'}}}%%
    subgraph UI ["UI Layer"]
        A["StoryHub<br/>故事世界选择"]:::ui
        B["PlayRoom<br/>互动播放室"]:::ui
        C["Dialogue<br/>AI对话面板"]:::ui
        D["StoryTeller<br/>数字人容器"]:::ui
    end

    subgraph Service ["Service Layer"]
        E["StoryEngine<br/>故事引擎"]:::svc
        F["StoryGenerator<br/>AI故事生成"]:::svc
        G["VectorStore<br/>向量存储"]:::svc
    end

    subgraph External ["External APIs"]
        H["魔珐星云SDK<br/>3D数字人"]:::ext
        I["通义千问API<br/>Qwen2.5-72B"]:::ext
        J["IndexedDB<br/>本地存储"]:::ext
    end

    B --> E
    C --> E
    D --> H
    E --> F
    E --> G
    F --> I
    G --> J

    classDef ui fill:#ede9fe,stroke:#7c3aed,stroke-width:2px
    classDef svc fill:#dbeafe,stroke:#2563eb,stroke-width:2px
    classDef ext fill:#fef3c7,stroke:#d97706,stroke-width:2px

图1:灵魂讲述者系统架构图


四、快速开始

4.1 克隆项目

复制代码
git clone https://github.com/xtdexw/soul-teller.git
cd soul-teller

4.2 安装依赖

复制代码
npm install

4.3 启动开发服务器

复制代码
npm run dev

4.4 配置API密钥

打开应用后,点击右上角设置按钮:

通义千问配置:

  1. 访问 ModelScope
  2. 注册并获取API Key
  3. 在设置面板的"API密钥"标签中填入密钥

魔珐星云配置:

  1. 访问 魔珐星云官网
  2. 注册账号(填写邀请码 J36AKZEFMK 可免费获取积分体验数字人!)
  3. 创建应用,获取App ID和App Secret
  4. 在设置面板的"数字人连接"标签中配置

4.5 开始体验

连接数字人 → 选择故事世界 → 点击"开始冒险" → 选择分支或对话推动剧情


五、项目亮点

5.1 一个API调用搞定剧情 + 分支

传统做法是分两次调用------先生成剧情,再生成选项。我把这两步合并成一次调用,既减少了延迟,又保证了选项和剧情的语义连贯性。

5.2 本地向量存储,零服务端依赖

基于IndexedDB自研了一套轻量级向量存储,不需要部署Pinecone或Milvus这类向量数据库,全部在浏览器本地完成。对于这种中小规模的上下文检索场景,完全够用。

5.3 密钥安全设计

  • 所有API密钥存储在浏览器localStorage中,不上传任何服务器
  • 设置面板中密钥仅显示前4位和后4位,防止泄露
  • 用户完全控制数字人的连接与断开

六、使用流程

复制代码
flowchart TD
    %%{init: {'theme':'base', 'themeVariables':{'primaryColor':'#059669'}}}%%
    A["启动应用"]:::step --> B["连接数字人"]:::step
    B --> C["选择故事世界"]:::step
    C --> D["点击开始冒险"]:::step
    D --> E["数字人朗读开场剧情"]:::step
    E --> F{"选择分支 or AI对话?"}:::choice
    F -->|选择分支| G["AI生成新剧情"]:::step
    F -->|自由对话| H["AI调整分支选项"]:::step
    G --> E
    H --> E

    classDef step fill:#d1fae5,stroke:#059669,stroke-width:2px
    classDef choice fill:#fef3c7,stroke:#d97706,stroke-width:2px

图2:用户使用流程图


七、写在最后

这个项目探索了一种新的互动叙事形式------不是预设脚本的选择题,而是AI实时生成的开放世界故事。每一次对话、每一个选择,都会让故事走向不同的方向。

如果你对AI叙事、数字人、向量存储这些方向感兴趣,欢迎一起交流贡献!

如果觉得这个项目对你有帮助,欢迎给个Star ️!

GitHub地址: https://github.com/xtdexw/soul-teller


🌟 嗨,我是Xxtaoaooo!
⚙️ 【点赞】让更多同行看见深度干货
🚀 【关注】持续获取行业前沿技术与经验
🧩 【评论】分享你的实战经验或技术困惑
作为一名技术实践者,我始终相信:
每一次技术探讨都是认知升级的契机,期待在评论区与你碰撞灵感火花🔥

相关推荐
奔跑中的小象10 小时前
统信UOS + 天数AI卡部署SGLang服务手册
人工智能·uos·sglang·天数智芯
DevSecOps选型指南10 小时前
中国版Mythos,为何是悬镜安全灵脉CodeAI?
人工智能·安全
Shockang10 小时前
LangGraph 状态机实战
人工智能
刹那芳华199210 小时前
循环神经网络的从零开始实现(RNN)
人工智能·rnn·深度学习
阿童木写作10 小时前
跨境图片翻译工具多合一,批量图片视频字幕翻译加智能抠图
人工智能·python·音视频·语音识别
科技之门10 小时前
AI3D从建模到贴图、绑骨和动画的完整流程怎么做?V2Fun完整工作流指南
人工智能·3d·贴图
宇宙第一小趴菜10 小时前
二、机器学习的应用领域和发展史
人工智能·机器学习
前端开发江鸟10 小时前
我写过 MCP Server,却一直以为 MCP 只有 Tool
人工智能
天国梦11 小时前
自习室智能化升级避坑指南:天学网AI智习室方案实测与选型建议
大数据·人工智能
阿里云云原生11 小时前
可用性从 99.9% 跃升至 99.995%:畅捷通如何用 AI 重塑运维底座?
运维·网络·人工智能