Commit a568b28
fix(memory): recall_memory 弱模型健壮性 + 首次调用即时占位语音 (#1528)
* fix(memory): recall_memory 弱模型健壮性 + 首次调用即时占位语音
测试 free-model 时发现问她"昨天聊了啥"会"似掉"(整轮无回复):弱模型在
recall_memory 上反复换措辞死循环调用,达工具迭代上限后无文本产出、整轮静音。
- 工具调用迭代上限 6→3;封顶后做一次去 tools 的 forced-finalize,逼模型基于
已积累的 tool 结果输出最终文本,避免封顶即静默(openai + genai 两条路径对偶)
- recall 同时带 query+time 却 0 命中时,返回提示让模型放宽过滤(只用 time 或只用
query)再查一次,而不是干巴巴"没有找到相关记忆"让其直接放弃
- 本轮首次真正发起 recall 时立即喂一段"让我回忆一下"占位语音填补检索空窗:用
独立 worker-sid 自成一段 utterance 立即合成出声,正文用真正 turn sid 入队不受
影响(避免被 worker 当 text_done 残余丢弃);voice 模式 use_tts=False 自动 no-op
- 新增 i18n: RECALL_MEMORY_TOOL_NO_RESULT_LOOSEN / RECALL_MEMORY_TOOL_FILLER(全语种)
- 更新 test_offline_iteration_cap_breaks_runaway_loop 覆盖 forced-finalize
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(memory): recall filler 音频对前端归一回 turn sid,修打断失效
Codex P1:filler 用合成 worker-sid (`{turn_sid}::recall-filler`) 切 utterance,但
在「把 request-id 透传进音频事件」的 provider(minimax 的 ("__audio__", sid, ...)
路径)下,该合成 sid 会经 send_speech 原样发到前端。前端打断 skip 按 turn sid 精确
匹配,filler chunk 匹配不上 → 用户打断后 filler 仍继续播,barge-in 失效。
在唯一的客户端音频出口 send_speech 把 `::recall-filler` 后缀剥掉、归一回 turn sid:
worker 层仍用合成 sid 切分 utterance,前端永远只看到 turn sid,打断正常取消 filler。
StepFun/free 路径发裸音频(无 sid,回落 current_speech_id) 不受影响。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(memory): 处理 CodeRabbit 评审 — filler 入队成功才标记、loosen 仅限请求成功、genai forced-finalize 不吞异常
- _recall_filler_spoken_sid 改为仅在 _emit_recall_filler_tts 真正入队成功后才置位:
否则 worker 未 ready 返回 False 时会误标"已预热",同轮后续 recall 不再补发 filler、
barge-in 守卫也误跳
- NO_RESULT_LOOSEN 仅在 memory server 请求成功且 0 命中时返回:加 recall_request_ok
守卫,避免 non-2xx / 异常的临时故障被当成"过滤太窄"误导模型换条件重试、白烧迭代预算
- genai forced-finalize 不再 try/except 吞异常:与 openai 路径一致让 SDK 失败上抛,
交给上层 retry / 状态上报 / 清泡泡逻辑,避免把真实失败伪装成空回复
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(memory): 移除 filler 对正文首包 TTS 清理的例外,恢复无条件 barge-in
Codex P1:handle_text_data 首包清理是某些路径(no-server-VAD 的 response.done 只
rotate sid、不清 TTS)下唯一的打断点;为 recall filler 跳过它会让上一轮残留音频漏
清、与新轮重叠,破坏 barge-in。
该例外是早期同-sid 设计的遗留(防正文首包冲掉同 sid 的 filler pending)。现在 filler
走独立 worker sid 并在检索期间立即 flush + 发往前端,正文首包到达时 filler 早已送达,
pending / response_queue 里不再有它,清理碰不到——例外已无必要。移除后恢复无条件清理。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(memory): genai forced-finalize 补齐空回复诊断字段
CodeRabbit Minor:新增的 genai forced-finalize 只透传文本,未像常规 genai 分支那样
回填 finish_reason / block_reason / prompt_tokens。若兜底生成被 safety / recitation /
max-tokens 挡住而无文本,上层 empty-completion 诊断只能引用上一轮 tool-iteration 的
过期 finish_reason。现采集这三个字段落 self._last_*,并在无文本时打 INFO 诊断,与
常规 genai 分支对偶。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(memory): openai forced-finalize 过滤 reasoning-only chunk + filler 冷启动有界等待
- openai forced-finalize 与常规 tool-loop 一致,跳过 thinking 模型的纯 reasoning
chunk(有 reasoning_content、无 content/tool delta/finish/usage):否则 stream_text
会在隐藏推理 token 上记 TTFT,污染封顶轮的延迟埋点(Codex P2)。genai 兜底已靠
part.thought 过滤,不受影响。
- recall filler 冷启动有界等待:ensure_tts_pipeline_alive 不等 __ready__,首轮 recall
紧接 emit 时 tts_ready 可能仍 False 导致 filler 被丢、首轮空窗。加 ~1s 有界轮询等
待 tts_ready(TTS 通常 ~0.1s 就绪),超时优雅放弃、sid 变化提前退出,不阻塞检索主
流程(CodeRabbit Major)。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(memory): genai forced-finalize 用局部 final_prompt_tokens,避免回填上一轮 token
CodeRabbit Minor:之前 self._last_prompt_tokens 只在本次 forced-finalize 有 usage 时
更新;若被 safety/recitation 挡住且无 usage,INFO log 与上层 LLM_NO_RESPONSE 警告会
沿用上一轮 tool-iteration 的 token 数(诊断串台)。改用局部 final_prompt_tokens
(默认 None)流内收集、流结束后无条件回填 self._last_prompt_tokens(可能为 None),
与 finish_reason / block_reason 同口径。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(memory): filler 冷启动等待提前退出 + openai forced-finalize 局部 prompt_tokens
- recall filler 冷启动等待循环:sid 变化、worker 没起/已挂、或已进入 NO_RETRY_TTS_CODES
不可恢复错误时立即退出,不再白等满 ~1s;否则 TTS 确定失败时同轮每次 recall 都吃满
这段延迟(CodeRabbit Minor)。
- openai forced-finalize 与 genai 路径对齐:prompt_tokens 走局部 final_prompt_tokens、
流结束后无条件回填 self._last_prompt_tokens(无 usage 写 None),避免上层 empty-
completion 诊断沿用上一轮 tool-iteration 的旧 token 数(CodeRabbit outside-diff)。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(memory): filler 切 sid 前先 flush+commit 本轮 pre-tool 正文,防截断
Codex P2:provider 在同一 turn 先吐 content 再进 tool_calls 时,pre-tool 正文可能还
卡在 turn_sid 的 normalizer/stripper 里没 flush。直接用合成 filler_sid 调
_enqueue_tts_text_chunk 会因 sid 变化 reset stripper 丢掉这段 pending,且 worker 换
连接也会丢 server 端缓冲,造成同轮正文缺字。
切 filler sid 前:若本轮确有 turn_sid 文本入队(_tts_norm_speech_id == turn_sid),
先把 stripper pending flush 出去、再用 (None,None) 把 turn_sid utterance commit 掉
(worker 发 text.done 后才换 sid,不丢内容);直接放 (None,None) 不置
_tts_done_queued_for_turn,正文/收尾仍各自正常 flush。模型首动作即调 recall(无
pre-tool 文本)时该块跳过,行为不变。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(memory): NO_RETRY_TTS 态下不为 filler 重启 worker
CodeRabbit Minor:ensure_tts_pipeline_alive 在 NO_RETRY_TTS_CODES 检查之前就无条件
调用,而它直接调 _start_tts_thread、绕过 _respawn_tts_worker 的 no-retry 闸。于是
API_ARREARS / API_KEY_REJECTED 这类不可恢复态下,同轮每次 recall 都会重启一次注定
失败的 worker。改为仅在非 NO_RETRY 态才拉起管线,不可恢复时直接走下面的早退放弃 filler。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Hongzhi Wen <cartabio.coder1@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 5b07a59 commit a568b28
4 files changed
Lines changed: 294 additions & 12 deletions
File tree
- config/prompts
- main_logic
- tests/unit
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3029 | 3029 | | |
3030 | 3030 | | |
3031 | 3031 | | |
| 3032 | + | |
| 3033 | + | |
| 3034 | + | |
| 3035 | + | |
| 3036 | + | |
| 3037 | + | |
| 3038 | + | |
| 3039 | + | |
| 3040 | + | |
| 3041 | + | |
| 3042 | + | |
| 3043 | + | |
| 3044 | + | |
| 3045 | + | |
| 3046 | + | |
| 3047 | + | |
| 3048 | + | |
| 3049 | + | |
| 3050 | + | |
| 3051 | + | |
| 3052 | + | |
| 3053 | + | |
| 3054 | + | |
| 3055 | + | |
| 3056 | + | |
3032 | 3057 | | |
3033 | 3058 | | |
3034 | 3059 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
| 78 | + | |
| 79 | + | |
78 | 80 | | |
79 | 81 | | |
80 | 82 | | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
81 | 90 | | |
82 | 91 | | |
83 | 92 | | |
| |||
1174 | 1183 | | |
1175 | 1184 | | |
1176 | 1185 | | |
| 1186 | + | |
| 1187 | + | |
| 1188 | + | |
| 1189 | + | |
| 1190 | + | |
| 1191 | + | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + | |
| 1195 | + | |
| 1196 | + | |
| 1197 | + | |
| 1198 | + | |
| 1199 | + | |
| 1200 | + | |
| 1201 | + | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
| 1206 | + | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
| 1215 | + | |
| 1216 | + | |
| 1217 | + | |
| 1218 | + | |
| 1219 | + | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + | |
| 1224 | + | |
| 1225 | + | |
| 1226 | + | |
| 1227 | + | |
| 1228 | + | |
| 1229 | + | |
| 1230 | + | |
| 1231 | + | |
| 1232 | + | |
| 1233 | + | |
| 1234 | + | |
| 1235 | + | |
| 1236 | + | |
| 1237 | + | |
| 1238 | + | |
| 1239 | + | |
| 1240 | + | |
1177 | 1241 | | |
1178 | 1242 | | |
1179 | 1243 | | |
| |||
1409 | 1473 | | |
1410 | 1474 | | |
1411 | 1475 | | |
| 1476 | + | |
| 1477 | + | |
| 1478 | + | |
| 1479 | + | |
| 1480 | + | |
| 1481 | + | |
| 1482 | + | |
1412 | 1483 | | |
1413 | 1484 | | |
1414 | 1485 | | |
| |||
2853 | 2924 | | |
2854 | 2925 | | |
2855 | 2926 | | |
| 2927 | + | |
| 2928 | + | |
| 2929 | + | |
| 2930 | + | |
| 2931 | + | |
| 2932 | + | |
| 2933 | + | |
| 2934 | + | |
| 2935 | + | |
| 2936 | + | |
| 2937 | + | |
| 2938 | + | |
| 2939 | + | |
| 2940 | + | |
| 2941 | + | |
| 2942 | + | |
| 2943 | + | |
| 2944 | + | |
| 2945 | + | |
| 2946 | + | |
| 2947 | + | |
| 2948 | + | |
| 2949 | + | |
| 2950 | + | |
| 2951 | + | |
| 2952 | + | |
| 2953 | + | |
| 2954 | + | |
| 2955 | + | |
| 2956 | + | |
| 2957 | + | |
| 2958 | + | |
| 2959 | + | |
| 2960 | + | |
| 2961 | + | |
| 2962 | + | |
| 2963 | + | |
| 2964 | + | |
| 2965 | + | |
| 2966 | + | |
| 2967 | + | |
| 2968 | + | |
| 2969 | + | |
| 2970 | + | |
| 2971 | + | |
| 2972 | + | |
| 2973 | + | |
| 2974 | + | |
| 2975 | + | |
| 2976 | + | |
| 2977 | + | |
| 2978 | + | |
| 2979 | + | |
| 2980 | + | |
| 2981 | + | |
| 2982 | + | |
| 2983 | + | |
2856 | 2984 | | |
2857 | 2985 | | |
2858 | 2986 | | |
| |||
2861 | 2989 | | |
2862 | 2990 | | |
2863 | 2991 | | |
| 2992 | + | |
2864 | 2993 | | |
2865 | 2994 | | |
2866 | 2995 | | |
| |||
2884 | 3013 | | |
2885 | 3014 | | |
2886 | 3015 | | |
| 3016 | + | |
2887 | 3017 | | |
2888 | 3018 | | |
2889 | 3019 | | |
| |||
2911 | 3041 | | |
2912 | 3042 | | |
2913 | 3043 | | |
| 3044 | + | |
| 3045 | + | |
| 3046 | + | |
| 3047 | + | |
| 3048 | + | |
| 3049 | + | |
| 3050 | + | |
| 3051 | + | |
2914 | 3052 | | |
2915 | 3053 | | |
2916 | 3054 | | |
| |||
6862 | 7000 | | |
6863 | 7001 | | |
6864 | 7002 | | |
| 7003 | + | |
| 7004 | + | |
| 7005 | + | |
| 7006 | + | |
| 7007 | + | |
6865 | 7008 | | |
6866 | 7009 | | |
6867 | 7010 | | |
| |||
0 commit comments