EN

VoiceMem:面向实时语音智能体的记忆系统

VoiceMem 是面向实时语音智能体的记忆系统。

核验日期

核心信息

以下信息由程序从官方接口读取,不经模型改写。

许可证
Apache-2.0
语言
Python
维护方
xzf-thu
核验日期

它是什么

VoiceMem 是面向实时语音智能体的记忆系统。VoiceMem 没有把每种记忆存入单一检索数据库,而是将记忆分为两个互补的部分。左脑使用 schema 和实体组织事实记忆。右脑使用独立记忆节点和跨实体记忆节点管理人格、情绪和关系。

主要能力

  1. 整个流水线是流式的。

  2. 用户仍在说话时,VoiceMem 持续进行音频分段、语音转写、提取有用记忆,并把结构化信息写入记忆图。

  3. 查询时,VoiceMem 先路由、再排序,只把 Top-K 条记忆注入模型上下文。

  4. VoiceMem 可以从真实世界音频中记住语音、说话人、声音事件、多人对话和音乐。

  5. 项目方报告,VoiceMem 在 LoCoMo 上达到 91.2%,Mem0 为 61.68%,且仅使用 Top-5 条记忆。

  6. 项目方报告,VoiceMem 的响应时间为 134 毫秒,Mem0 为 1,440 毫秒,并在语音轮次内部进行流式检索。

怎么上手

  1. 安装 VoiceMem 的前提条件是 Python 3.10 或更高版本。

  2. 可以把 VoiceMem 的流式接口看作持续处理音频的 VAD 接口。

  3. 演示代码在仓库中,pip 安装的包只包含库本身,因此需要先克隆仓库并进入仓库根目录。

  4. 演示中的插话(barge-in)在播放期间分两个阶段处理。

  5. 在插话处理中,VAD 首先暂停播放,同时保留音频队列。

  6. 演示的两种回复模式共用以 PCM 样本为基准的媒体时间轴。

摘自 README · bash
git clone https://github.com/xzf-thu/VoiceMem.git
cd VoiceMem

# Install the memory system (bundles ASR / speaker ID / scene / emotion / local embedding)
pip install voicemem

# Optional: run our fine-tuned Qwen reply model
pip install "voicemem[slm]"
摘自 README · bash
pip install -U huggingface_hub

hf download zhifeixie/VoiceMem_Default_Models_Env --local-dir ./models
摘自 README · python
from voicemem import VoiceMem

vm = VoiceMem(
    mode="normal",
    openai_key="api_xxx",
    top_k=5,
)

# Local models load lazily -- warm them up so the first call doesn't pay for it.
vm.warmup()

# Store an audio file.
# VoiceMem internally runs ASR / speaker ID / scene / emotion / embedding extraction.
print("ingest start")
vm.ingest(audio="assets/input.wav")  # I am vegetarian and allergic to nuts.
print("ingest done")

# Writing is slow because it extracts facts, tags them and builds the graph.
# Reading is a pure vector lookup -- independent of write cost.
print("search start")
result = vm.search("What are my dietary restrictions?")
print("search done")

print(result.result_leftbrain, result.result_rightbrain)

# Store Left Brain factual text directly (no emotional information).
vm = VoiceMem(
    mode="leftbrain_only",
    openai_key="api_xxx",
    top_k=5,
)

vm.ingest("I am vegetarian and allergic to nuts.")

result = vm.search("What are my dietary restrictions?")
摘自 README · python
import asyncio
import os
from pprint import pprint

import numpy as np
import soundfile as sf

from voicemem import VoiceMem

# Reuses the vm above; building one here so the block runs standalone
vm = VoiceMem(mode="normal", openai_key=os.environ["OPENAI_API_KEY"], top_k=5)

# Local models load lazily -- warm them up so the first audio chunk doesn't wait
vm.warmup()

# Store one fact first, so the question below has something to find
vm.ingest("I am vegetarian and allergic to nuts.")

SPEC_MIN_CHARS = 6
searching = False

def on_partial(text):
    """Partial transcripts as they arrive. Long enough = the search already started."""
    global searching
    print(f"\r[partial] {text}", end="", flush=True)
    if not searching and len(text) >= SPEC_MIN_CHARS:
        searching = True
        print("\n[search start] speaker isn't done yet, retrieval already running", flush=True)

async def main():
    # This audio is a question: "What are my dietary restrictions?"
    audio, sr = sf.read("assets/question.wav", dtype="float32")
    pcm = (np.clip(audio, -1, 1) * 32767).astype(np.int16)

    stream = vm.stream(src_rate=sr, vad_threshold=0.5, on_partial=on_partial)
    step = int(sr * .032)

    for i in range(0, len(pcm), step):
        st = await stream.feed(pcm[i:i + step].tobytes())
        if st.state != "turn_over":
            continue

        # VAD confirmed end of turn. Memory was fetched while the user spoke -- just read it
        print("[search end]")
        print("transcript  ", st.transcript)
        print("left brain  ", st.result_leftbrain)
        print("right brain ", st.result_rightbrain)
        pprint({k: getattr(st, k) for k in
                ["speaker_id", "speaker_voiceprint", "emotion",
                 "entity", "schema", "text_embedding"]})

        # Every turn runs the ingest decision
        print("[ingest] LLM deciding whether this is worth storing...", flush=True)
        res = vm.ingest(st.transcript)
        print(f"[ingest] extracted {res['facts_count']} facts -> {res['memory_ids']}")

asyncio.run(main())
摘自 README · bash
python web/run.py
摘自 README · text
http://localhost:8787

适合谁

可以将 VoiceMem 与自己的语音模型集成,构建带有长期记忆的实时语音智能体。项目通过三阶段 OPD 训练流程构建了 ChatMem-400K。人工编辑之后,同一流程产出 ChatMem-Bench,用于评测语音模型能否随时间形成对用户的长期理解。

开源的 VoiceMem 模型系列包括 Qwen2.5-Omni、Qwen3-Omni 和 Step-Audio2-Mini。这些模型可以在对话中接收并理解 VoiceMem 提供的记忆信息。VoiceMem 提供完整的微调流程,用于训练自己的 VoiceMem Model Family 适配器。

微调的默认训练配置与已发布的 checkpoint-3318 所用配置一致。评测流程完全开源,并且可以复现。一个 Benchmark 可以用一条命令启动。

运行完整评测之前,可以加入检查选项,检查数据集如何被解析。检查模式不调用模型,也不产生 API 费用。评测时,回答模型只接收检索到的记忆,不接收原始对话历史。

添加一个 Benchmark 只需要一个文件和两个函数。项目方报告,VoiceMem 仅使用 430 个记忆 token,Mem0 为 6,956,EverMemOS 为 1,899。项目方称,每次查询约使用 300 个 token。

VoiceMem 基于 Apache License 2.0 开源。VoiceMem 还使用 OpenAI API 提供 Chat、TTS 和 Realtime 功能。

来源

本页内容整理自以下官方来源,点击可核对原文。

核验日期 ·

本页由 AI 依据上述官方来源整理,并经自动核对,未经本站实测。 发现错误?告诉我们。