先分清短时与长时记忆——VoxMem 的评测切入口

文章导读
VoxMem 评测的到底是短时记忆还是长时记忆,答案通常不在工具本身,而在你选了哪个子任务:同一个评测实例里往往同时挂着两类任务,短时任务把问题限制在单次会话的上下文范围内,长时任务则要求模型跨会话或跨长音频把早先出现过的信息取回来。所以第一步不是跑分,而是先把任务清单里的子任务按记忆类型归类,再决定加载哪份测试集。
📋 目录
  1. 一 在 VoxMem 的评测项说明里找出短时记忆与长时记忆的任务划分
  2. 二 为短时记忆设计 3 个连续对话轮次的用例
  3. 三 为长时记忆设计跨 20 分钟音频的用例
  4. 四 对比模型在两类任务上的得分差异
  5. 五 根据使用场景选择评测子集
A A

VoxMem 评测的到底是短时记忆还是长时记忆,答案通常不在工具本身,而在你选了哪个子任务:同一个评测实例里往往同时挂着两类任务,短时任务把问题限制在单次会话的上下文范围内,长时任务则要求模型跨会话或跨长音频把早先出现过的信息取回来。所以第一步不是跑分,而是先把任务清单里的子任务按记忆类型归类,再决定加载哪份测试集。

判断路径:先在 VoxMem 的任务列表或评测项说明里按子任务名归类,凡答案只依赖单次会话内几轮上下文的归为短时,凡需要跨会话、跨长音频检索的归为长时。操作动作是只加载对应子集,先跑通一条样本,看日志里模型实际引用了哪些记忆片段。验证方式是核对日志中的记忆读取范围是否与任务声明一致。风险边界:不同版本的任务命名和分组可能调整,跑分前需结合本机配置确认,不要直接套用别处的子任务名。

在 VoxMem 的评测项说明里找出短时记忆与长时记忆的任务划分

先看清单再看代码。多数实现会把任务写在配置目录或任务目录下的清单文件里,用一次检索就能把子任务名和分组字段列出来:

# 先看名字和分组,再决定加载哪一类
# 目录名以本机实际安装位置为准,替换 ./config ./tasks
grep -RIn -E "task|suite|memory_type|category" ./config ./tasks 2>/dev/null | head -n 40

清单里常见的命名大致分两类,具体以你本机的任务列表为准:

  • 短时记忆侧:multi_turn_qa(多轮问答,答案依赖前几轮出现的实体)、coreference_resolve(指代消解,把“他”“那个方案”绑回上文)、session_state_track(单会话内状态跟踪,例如改期、数量累加)。
  • 长时记忆侧:cross_session_qa(跨会话问答)、long_audio_recall(长音频回忆)、fact_persistence(早期提出的事实到末尾才被问到)、retrieval_at_time(按时间点定位某句话)。

边界判断的口径是:答案所需的全部信息都能放进一次会话的上下文,就算短时;答案所需信息在提问时刻已经不在当前上下文里,必须靠持久化或检索取回,就算长时。任务名只是线索,最终以日志里模型实际读取的记忆范围为准。

先分清短时与长时记忆——VoxMem 的评测切入口

为短时记忆设计 3 个连续对话轮次的用例

短时用例的关键是“每轮只动一部分槽位”。下面这份 JSON 可以直接作为自定义测试集骨架,字段名按你的评测框架替换即可:

{
  "suite": "short_term",
  "turns": [
    {"turn": 1, "user": "我们下周三下午三点开评审会,会议室定了 A302。",
     "must_remember": ["时间=下周三15:00", "地点=A302"]},
    {"turn": 2, "user": "再把运维的两位同事加进来。",
     "must_remember": ["新增参会人=运维2人", "沿用 turn1 的时间与地点"]},
    {"turn": 3, "user": "地点改到 B 座 5 层,时间往后挪一小时,参会人不变。",
     "question": "最终会议在什么时间、什么地点,谁来参加?",
     "expected": "下周三16:00 / B座5层 / 原参会人+运维2人",
     "must_remember": ["覆盖地点", "覆盖时间", "保留参会人"]}
  ]
}

三轮各自考的东西不同:第 1 轮建立实体,第 2 轮是增量追加,考的是新信息进来时旧槽位不被冲掉;第 3 轮是覆盖与保留混合,考的是“部分更新”能力。判定时把每个槽位单独算一个记分点,三个槽位分别命中才算这轮全对,这样能看出模型是整体遗忘还是只错在某一类槽位上。

为长时记忆设计跨 20 分钟音频的用例

长时用例要区分“出现时刻”和“提问时刻”。标注时建议按 30 秒到 1 分钟切段,每段带起止时间戳、转写文本和该段承载的事实点:

先分清短时与长时记忆——VoxMem 的评测切入口
{
  "suite": "long_term",
  "audio": "meeting_20min.wav",
  "segments": [
    {"start": "00:00:00", "end": "00:05:00", "transcript": "...", "facts": []},
    {"start": "00:05:00", "end": "00:11:30", "transcript": "...",
     "facts": ["项目代号=青禾"]},
    {"start": "00:11:30", "end": "00:12:00", "transcript": "...",
     "facts": ["本次预算上限调整,全片仅在此处出现一次"]},
    {"start": "00:12:00", "end": "00:19:40", "transcript": "...", "facts": []}
  ],
  "query": {
    "at": "00:19:40",
    "question": "项目代号是什么?预算上限这次是怎么定的?",
    "expected": ["青禾", "引用 00:11:30 段的事实"]
  }
}

关键信息不要放在开头一分钟内,也不必压到结尾,建议落在中间位置,例子里放在 00:11:30 前后,提问放在 00:19:40,中间隔开一段无关内容,这样测的是检索而不是短期复述。同时建议在同段附近放一条形式相近的干扰项(比如另一组数字),用来观察模型是否会把相似记录混在一起。事实点在整段音频里只出现一次,是被反复强调的原则。

对比模型在两类任务上的得分差异

两类任务的准确率都用“命中点数 / 应记点数”口径,不要只按整条用例对错记分,否则槽位级的差异会被掩盖。短时按槽位算,长时按事实点算,填下面这张表:

先分清短时与长时记忆——VoxMem 的评测切入口
子任务记忆类型用例数命中点应记点准确率
multi_turn_qa短时
coreference_resolve短时
long_audio_recall长时
fact_persistence长时

计算方式:短时准确率 = Σ命中槽位 / Σ应记槽位;长时准确率 = Σ命中事实点 / Σ应记事实点。读表时注意两条判断规则。短时明显高于长时,说明模型在上下文内跟随没问题,弱在跨会话检索和持久化,优化方向应放在检索命中而非对话策略。长时反而不低于短时的情况比较少见,遇到先怀疑用例泄漏——检查短时用例的关键信息是否被写进了系统提示或前置上下文,导致模型不用“记”也能答。分差本身不解释原因,需要回到日志看模型实际读取了哪几段记忆。

根据使用场景选择评测子集

三类场景的侧重点不一样,先定场景再选子集,比全量跑一遍更省事:

  • 会议助手:以长时为主,跨议程、跨会议的决议和待办才是用户真正要回查的东西;短时作为辅助,覆盖当前议题内的指代。建议先跑 long_audio_recall 和 cross_session_qa,再补 multi_turn_qa 看是否拖后腿。验证方式是把同一条决议分别放在单场会议中段和上一场会议里提问,看两次答案是否一致。
  • 语音日记:长时为主,而且偏跨天、跨周检索,建议侧重 fact_persistence 和 retrieval_at_time;短时权重可以压低,因为用户很少在一次会话里连续追问。验证方式是问一个只在前几天录音里提过的人名或数字,看是否命中原始片段。
  • 实时对话:以短时为主,重点是 multi_turn_qa 和 coreference_resolve;长时只保留一个轻量子集做回归即可,不宜把长音频子集塞进实时链路的评测,否则单次评测时长会明显拉长。验证方式是观察多轮中槽位覆盖后是否仍保留未变更的旧槽位。

选定子集后,把配置里的任务列表固定下来并记录版本,后续对比才有可比性;换版本时先重新确认子任务命名,再复用同一批用例。