Subspace Institute
Background Decoration

LAPLACE Eidolon

拉普拉斯花店模拟器

Intro

LAPLACE Eidolon 是一台主播人格的语音分身——访客通过浏览器进入「拉普拉斯花店」,与一台会说话、会记事的 AI 实时对话

技术上是一台基于 Pipecat 的级联式语音机器人,串联 STT、LLM 与 TTS,并叠加可选的多层 RAG 与每观众长期记忆,让分身能够「记得」过往直播片段、人设设定,以及与每位访客之间的私人交流

管线结构

transport.input → STT → user_aggregator
    → Mem0(每观众长期记忆,可选)
    → PersonaFacts(人设事实 RAG,可选)
    → StreamArchive(往期直播 RAG,可选)
    → LLM → TTS → transport.output → assistant_aggregator

技术栈

  • STTSoniox
  • LLMOpenRouter
  • TTSFish Audio
  • 传输:SmallWebRTC(Pipecat 自托管)
  • 向量库:LanceDB(本地)
  • 长期记忆Mem0(可选)

仅支持自托管 SmallWebRTC,依赖自有反向代理终止 TLS,不接入 Daily 或 Pipecat Cloud

四层人设记忆

机器人通过四级持久化存储为 LLM 注入上下文,每一层都可独立启停,机器人在仅启用 persona.md 的最小配置下也能稳定运行:

  1. persona.md:恒常在线的身份、语气与硬性规则,启动时直接载入 system prompt
  2. Persona facts:手工整理的「她说过的话」原子事实,按语义相关度检索(LanceDB 索引由 laplace-ingest-facts 构建)
  3. Stream archive:经过 LLM 二次精炼的往期直播片段,按语义相关度检索(LanceDB 索引由 laplace-ingest-streams 构建)
  4. Mem0:从对话中自动抽取的每观众情景记忆,按 Bilibili UID 隔离

混合检索与重排

Persona facts 与 Stream archive 两层 RAG 共用一条混合检索管线,每轮对话实时执行:

  1. 构造查询:综合最近几轮用户发言,使短促语音(如「嗯,那呢?」)也能借上下文检索
  2. 统一向量化:以 EMBED_MODEL(默认 Gemini,3072 维)嵌入一次查询
  3. 日期预过滤(仅 persona facts):查询提及日期(2026年5月9日 / 5月9号)时,先按 date 列收窄候选集
  4. 混合搜索:向量检索叠加 jieba 分词的中文 BM25/FTS,拉取 PERSONA_FACTS_CANDIDATES(默认 30)或 STREAM_ARCHIVE_CANDIDATES(默认 15)条候选,并剥离停用词以防 BM25 分数塌缩
  5. 交叉编码重排(可选):配置 COHERE_API_KEY 后由 Cohere rerank-v4.0-fast 精排至 top_k(facts 取 8、chunks 取 3);未配置则回退 LanceDB 的 RRF 融合

数据规模约 1 万行以上时强烈建议启用 Cohere 重排,它是精度的最大杠杆,生产成本约 $1 / 1000 次。laplace-eval-retrieval 可量化 recall@k / MRR,对比改动前后的回归。

自托管

仅需运行:

docker compose up --build

镜像内置 Pipecat 运行时与已构建的 LanceDB 索引,监听 7860 端口;端点 POST /api/offer 处理 SmallWebRTC SDP 信令,前端可直接对接,亦可使用 @pipecat-ai/client-js@pipecat-ai/small-webrtc-transport

生产部署需在反向代理中终止 TLS,并按需配置 TURN 以穿透对称 NAT

推荐使用 Cloudflare Realtime TURN,机器人会按需铸造凭据并自动轮换,免费额度约 1 TB/月中继流量,覆盖大多数自部署场景

HTTPS 是浏览器获取麦克风权限的硬性要求,本地 localhost~~ 之外的任何环境都需配置有效证书~~

观众身份与限流

可选的 loginSyncToken 校验通过 LAPLACE Login Sync 工作器完成:识别出的 Bilibili UID 用作 Mem0 命名空间,并跳过匿名限流;未携带或校验失败的访客则按 IP 进入滑动窗口配额,默认每小时 5 次连接尝试

登录访客还可自助管理属于自己的 Mem0 记忆——GET /api/memories 列出、POST /api/memories/forget 清除,二者均以 WebRTC 握手所携带的同一 loginSyncToken 鉴权,并严格限定在调用者本人的 Bilibili UID 范围内

运行时声线切换

分身可在通话中切换 Fish Audio 声线:当访客说出「温柔一点」「活泼一点」等口令时,change_voice_style 工具实时换用对应的 reference_id。配置 FISH_VOICE_ID_GENTLEFISH_VOICE_ID_LIVELY 即可启用,全部留空则关闭该能力

此外,前端可按音频质量逐会话选择 Opus 编码码率(EIDOLON_OPUS_BITRATE_*,默认 96 kbps),在弱网与音质之间权衡

公共 MCP 服务

机器人在 /mcp/ 额外暴露一个只读的 Model Context Protocol 端点(Streamable HTTP),向任意 MCP 客户端开放与语音管线相同的两层 RAG 索引——search_persona_factssearch_streams。公共实例位于 https://eidolon.vrp.moe/mcp,默认匿名开放。详见 MCP 服务

离线工具

构建索引、批量下载与转录均以独立 console script 提供,全部通过 uv run 调用:

命令功能
laplace-pipeline端到端流水线:下载 → 转录 → 精炼 → 入库
laplace-download基于 yt-dlp 的批量 VOD 下载
laplace-transcribeWhisper / Soniox 转录
laplace-refine将原始转录精炼为结构化记忆 JSON
laplace-ingest-streams构建 stream_chunks LanceDB 索引
laplace-ingest-facts构建 persona_facts LanceDB 索引
laplace-searchLanceDB 索引的 REPL 式检索
laplace-eval-retrieval量化检索 recall@k / MRR,回归对比基线
laplace-extract-users从弹幕 JSON 中挖掘高频用户名

源代码

On this page