问题描述
知识库启用 Rerank 后,只要在 WebUI 里保存过一次该 Rerank Provider 的配置(触发 provider 热重载),后续每一次检索都会打印一条错误信息为空的警告,并且重排序静默失效:
[Core] [WARN] [v4.28.1] [retrieval.manager:191]: Rerank 执行失败,已跳过重排序并使用融合结果:
注意结尾冒号后没有任何内容——因为抛出的异常是 AssertionError,其 str() 为空字符串。
复现步骤
- 配置一个
vllm_rerank 类型的 Rerank Provider,并在知识库中启用它。
- 触发检索,确认 Rerank 正常工作。
- 在 WebUI 中重新保存一次该 Provider 的配置(例如改动 timeout 后保存)。
- 再次触发检索。
预期结果
Rerank 继续正常工作,或在失败时给出可诊断的错误信息。
实际结果
Rerank 永久失效,且日志中的错误信息为空,无法定位原因。重启 AstrBot 后暂时恢复,再次保存 Provider 配置后复发。
根因分析
ProviderManager.terminate_provider() 会调用实例的 terminate(),关闭 aiohttp session 并将 self.client 置为 None(astrbot/core/provider/sources/vllm_rerank_source.py:85)。
- 但知识库的
FaissVecDB 在创建时就缓存了 provider 对象引用(astrbot/core/knowledge_base/kb_helper.py:197)。
- Provider 热重载只更新
ProviderManager.inst_map,没有任何代码去刷新已缓存 vec_db 中持有的旧引用。
- 于是检索时调用的仍是被
terminate() 关闭的旧实例,命中 astrbot/core/provider/sources/vllm_rerank_source.py:53 的 assert self.client is not None,抛出信息为空的 AssertionError。
相关时间线(真实日志):
[19:05:29.796] Rerank 执行失败 ...: 402, message='Payment Required', url='...' <- 异常文本正常
[21:11:08.109] Terminating provider adapter vllm_rerank ... <- 热重载,session 被关闭
[21:11:08.110] Loading model vllm_rerank(vllm_rerank) ...
[21:11:42.555] Rerank 执行失败 ...: <- 之后错误信息全为空
[21:14:29.148] Rerank 执行失败 ...:
[21:15:15.590] Rerank 执行失败 ...:
失败耗时仅 87~130ms 且无任何 HTTP 请求日志,说明请求根本没有发出。
为什么"模型测试"能通过
KnowledgeBaseService.create_kb() 中的 Rerank 测试通过 provider_manager.get_provider_by_id() 获取实例,读到的是 inst_map 中的新实例;而实际检索走的是 vec_db 缓存的旧实例。两条路径不一致,因此出现"测试能通过、实际全部失败"的现象。
相关背景
#9122 移除了原先 rerank_pi == rerank_provider.meta().id 的一致性校验,该校验原本用于确认缓存实例与知识库当前配置一致。本问题很可能由该改动引入或放大。
次要问题
astrbot/core/knowledge_base/retrieval/manager.py:191 使用 logger.warning(f"...: {e}") 捕获异常,既不带异常类型也不带 exc_info=True,导致 AssertionError 这类空信息异常完全无法诊断。
环境
- AstrBot v4.28.1(Windows,AstrBot Desktop)
- Rerank Provider 类型:
vllm_rerank(指向 SiliconFlow /v1/rerank)
- 知识库配置:
gitee_embedding + vllm_rerank
问题描述
知识库启用 Rerank 后,只要在 WebUI 里保存过一次该 Rerank Provider 的配置(触发 provider 热重载),后续每一次检索都会打印一条错误信息为空的警告,并且重排序静默失效:
注意结尾冒号后没有任何内容——因为抛出的异常是
AssertionError,其str()为空字符串。复现步骤
vllm_rerank类型的 Rerank Provider,并在知识库中启用它。预期结果
Rerank 继续正常工作,或在失败时给出可诊断的错误信息。
实际结果
Rerank 永久失效,且日志中的错误信息为空,无法定位原因。重启 AstrBot 后暂时恢复,再次保存 Provider 配置后复发。
根因分析
ProviderManager.terminate_provider()会调用实例的terminate(),关闭 aiohttp session 并将self.client置为None(astrbot/core/provider/sources/vllm_rerank_source.py:85)。FaissVecDB在创建时就缓存了 provider 对象引用(astrbot/core/knowledge_base/kb_helper.py:197)。ProviderManager.inst_map,没有任何代码去刷新已缓存 vec_db 中持有的旧引用。terminate()关闭的旧实例,命中astrbot/core/provider/sources/vllm_rerank_source.py:53的assert self.client is not None,抛出信息为空的AssertionError。相关时间线(真实日志):
失败耗时仅 87~130ms 且无任何 HTTP 请求日志,说明请求根本没有发出。
为什么"模型测试"能通过
KnowledgeBaseService.create_kb()中的 Rerank 测试通过provider_manager.get_provider_by_id()获取实例,读到的是inst_map中的新实例;而实际检索走的是 vec_db 缓存的旧实例。两条路径不一致,因此出现"测试能通过、实际全部失败"的现象。相关背景
#9122 移除了原先
rerank_pi == rerank_provider.meta().id的一致性校验,该校验原本用于确认缓存实例与知识库当前配置一致。本问题很可能由该改动引入或放大。次要问题
astrbot/core/knowledge_base/retrieval/manager.py:191使用logger.warning(f"...: {e}")捕获异常,既不带异常类型也不带exc_info=True,导致AssertionError这类空信息异常完全无法诊断。环境
vllm_rerank(指向 SiliconFlow/v1/rerank)gitee_embedding+vllm_rerank