Ai! Jack!v2026.04.01-f12
← 홈GitHub 라이징

xzf-thu/VoiceMem

원문 보기
★ 96282 forksPython중국

AI 분석

•음성 에이전트용 기억 인프라 → 사실 정보와 감정 맥락을 분리해 관리하는 이중 기억 구조
•스트리밍 조회·추측성 사전 조회·계층형 저장으로 대화 지연과 기억 조회 비용의 절감 지향
•초기 버전이며, 낮은 지연과 비용에 관한 주장은 실제 음성 파이프라인에서 별도 검증 필요

Infrastructure for the next generation of voice agents, designed to provide universal memory. It is divided into a left brain and a right brain, storing information and emotions respectively, while a fully streaming architecture eliminates latency at the fundamental level.

검증 정보

출처
github.com
피드
GitHub 라이징
수집/분석 기준
2026. 9. 8. 오전 9:00
원문 확인
원문 열기

본문

中文 | English

项目主页 🌐 /

技术报告 📖 /

VoiceMem Utils 🤗 /

VoiceMem Model Families 🤗 /

ChatMem-400K 🤗


我们带来 VoiceMem,为语音模型增加最后一个组件:灵魂,让它真正越来越懂你。VoiceMem 建立在「流式双脑」架构之上,提供精准、有情感、懂人格、低延迟且最便宜的记忆服务。本仓库将「永久保持全部开源」。

快速理解 VoiceMem:

•左脑: 直接管理信息,在 Top-3 限制下维持 Mem0 的满载性能。
•右脑: 用长短期情绪归因管理「情商」,含交叉节点、与左脑信息联合维护。
•低延迟: 通过压缩信息、分层存储、流式查询(0–300 ms 投机预取),几乎不增加延迟。
•简单实用: 单轮查询约 300 token;架构全部解耦,全部组件(含底层记忆引擎)都可更换。

## 🔥 News

•💬 09/01/2026 · [v0.0.2](https://github.com/xzf-thu/VoiceMem/releases/tag/v0.0.2) — 修复事件日期链路,移除右脑冗余记忆类别,开放可插拔语音合成层。
•🎉 08/27/2026 · [v0.0.1](https://github.com/xzf-thu/VoiceMem/releases/tag/v0.0.1) — 发布初代 VoiceMem 和 Technical Report。
•🤖 08/21/2026 — 开源 VoiceMem 模型系列,可直接读取并理解 VoiceMem 提供的记忆。
•🛠️ 08/21/2026 — 发布 VoiceMem Utils,开箱即用。
•📦 08/20/2026 — 开源 ChatMem-400K 数据集。

## 🎬 Demo

注意: 播放前需要先取消静音。

https://github.com/user-attachments/assets/0d919f8c-e9ba-4fdb-8078-b049e4b99a28

## 📚 目录

•[🚀 快速开始](#-快速开始)
•[🧠 VoiceMem 双脑流式架构](#-voicemem基于流式双脑架构的记忆系统)
•[🤖 VoiceMem 官方记忆模型](#-voicemem-模型系列)
•[🔌 使用 VoiceMem 定制你的语音智能体](#-使用-voicemem-定制你的语音智能体)
•[🛠️ 模型微调](#️-模型微调)
•[📊 评测代码](#-评测)
•[📖 引用](#-引用)
•[致谢](#致谢)
•[许可证](#许可证)

## 🚀 快速开始

### 安装

git clone https://github.com/xzf-thu/VoiceMem.git
cd VoiceMem

# 安装记忆系统(含 ASR / 声纹 / 场景 / 情绪 / 本地 embedding 全套内置组件)
pip install voicemem

# 可选:用我们微调的 Qwen 回复模型
pip install "voicemem[slm]"

### 下载所需模型

pip install -U huggingface_hub

hf download zhifeixie/VoiceMem_Default_Models_Env --local-dir ./models

### 基础用法

#### 作为离线记忆引擎运行

from voicemem import VoiceMem

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

# 本地模型是懒加载的,先热起来,别让第一次调用去等加载
vm.warmup()

# 存:音频文件
# 内部跑 ASR / 声纹 / 场景 / 情绪感知 / Embedding 抽取
print("入库开始")
vm.ingest(audio="assets/input.wav")  # 我是素食主义者,对坚果过敏。
print("入库结束")

# 查:写入慢是因为要抽事实、打标签、建图;查询走的是纯向量检索,跟写入无关
print("检索开始")
result = vm.search("我的饮食禁忌是什么?")
print("检索结束")

print(result.result_leftbrain, result.result_rightbrain)


# 存:左脑信息文本(无情感)
vm = VoiceMem(
    mode="leftbrain_only",
    openai_key="api_xxx",
    top_k=5,
)

vm.ingest("我是素食主义者,对坚果过敏。")

result = vm.search("我的饮食禁忌是什么?")

#### 以流式方式运行 VoiceMem

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

下面这段:先显式存一条事实,再喂一段问句音频,看记忆是怎么在人还没说完时就查好的;最后照例走一次入库判断。

import asyncio
import os
from pprint import pprint

import numpy as np
import soundfile as sf

from voicemem import VoiceMem

# 沿用上面那个 vm;单独跑这段就自己建一个
vm = VoiceMem(mode="normal", openai_key=os.environ["OPENAI_API_KEY"], top_k=5)

# 本地模型是懒加载的,先热起来,别让第一块音频去等模型加载
vm.warmup()

# 先存一条事实,等下那个问句才有东西可查
vm.ingest("我是素食主义者,对坚果过敏。")

SPEC_MIN_CHARS = 6          
searching = False


def on_partial(text):
    """边说边出字。够长了就说明后台这一刻已经开查了。"""
    global searching
    print(f"\r[partial] {text}", end="", flush=True)
    if not searching and len(text) >= SPEC_MIN_CHARS:
        searching = True
        print("\n[检索开始] 人还没说完,后台已经在查了", flush=True)


async def main():
    # 这段音频里是一个问句:「我的饮食禁忌是什么?」
    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 确认这一轮说完了。记忆早在说话过程中就查好了,这里直接取,不再等
        print("[检索结束]")
        print("转写  ", st.transcript)
        print("左脑  ", st.result_leftbrain)         
        print("右脑  ", st.result_rightbrain)
        pprint({k: getattr(st, k) for k in
                ["speaker_id", "speaker_voiceprint", "emotion",
                 "entity", "schema", "text_embedding"]})

        # 每一轮都要走一次入库判断
        print("[入库] LLM 正在判断这句话值不值得入库…", flush=True)
        res = vm.ingest(st.transcript)
        print(f"[入库] 抽出 {res['facts_count']} 条事实 -> {res['memory_ids']}")
       


asyncio.run(main())

### VoiceMem 交互式演示

演示代码在仓库里(pip 装的包只有库本身),先确认已经克隆并进入仓库目录。

python web/run.py

然后访问:

http://localhost:8787

Demo 默认把终端输出(含 Python logging 和 Uvicorn 的日志)保存一份到

results/logs/voicemem-时间-PID.log,每行带时间戳和 stdout/stderr 标记。

启动时终端会打印实际路径。指定文件或临时关闭如下。

python web/run.py --log-file results/logs/debug.log
python web/run.py --no-file-log

回复模型的上下文由当前输入、本次会话尚未入库的对话和检索记忆组成。每轮对话先

进入内存 SessionBuffer;异步记忆写入完成并确认产生持久记忆后,对应 turn 从

SessionBuffer 移除。没有产生长期记忆的临时对话会保留到本次会话结束,不同

Memory Space 和不同 WebSocket 会话互相隔离。

播放期间的插话使用两阶段控制:VAD 首先暂停并保留音频队列;明确停止指令或稳定

ASR 文本确认后才清空队列并取消回复;附和、回声、无文字声音和单音节碎片会恢复

播放。候选静音回退和最长等待时间可分别通过 BARGE_REJECT_SILENCE_MS、

BARGE_CANDIDATE_TIMEOUT_MS 调整。

两种回复模式共用以 PCM 样本位置为基准的输出时间轴。浏览器 AudioWorklet 回报

实际渲染进度,打断时只把已经播放的回复写入 SessionBuffer。TTS 后端可选返回

TimedAudioChunk 提供文字对齐;普通 PCM 后端按分段音频长度和动态语速估算。

## 🧠 VoiceMem:基于流式双脑架构的记忆系统

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

VoiceMem 不把所有记忆放进同一个检索数据库,而是将记忆拆分成两个互相配合的部分:

관련 아이템

xzf-thu/VoiceMem — Ai! Jack! — Ai! Jack!