Skip to content

fix: filter stale fallback chat models#8480

Open
Clhikari wants to merge 1 commit into
AstrBotDevs:masterfrom
Clhikari:fix/provider-fallback-filter
Open

fix: filter stale fallback chat models#8480
Clhikari wants to merge 1 commit into
AstrBotDevs:masterfrom
Clhikari:fix/provider-fallback-filter

Conversation

@Clhikari
Copy link
Copy Markdown
Contributor

@Clhikari Clhikari commented Jun 1, 2026

Fixes #8479

这个 PR 修复“回退对话模型列表”里会保留已禁用或已删除模型的问题

之前如果某个对话模型已经被删除、禁用,或者因为配置变更不再可用,它仍然可能留在“回退对话模型列表”中。主对话模型请求失败后,AstrBot 会继续尝试读取这个无效模型,然后在日志里出现类似下面的警告:

没有找到 ID 为 openai_1/gemini-3.5-flash 的提供商,这可能是由于您修改了提供商(模型)ID 导致的。
Fallback chat provider `openai_1/gemini-3.5-flash` not found, skip.

本次改动在后端做了统一过滤:

  • 保存核心配置时,清理无效的回退对话模型
  • 创建、更新、删除 provider 后,同步清理回退对话模型列表
  • provider 选择列表只返回当前启用且已加载的 provider
  • 保留 agent runner 的特殊处理,避免被普通 provider 实例过滤误伤
  • 补充回归测试,覆盖禁用、删除、重复、非对话模型和 provider/source 分离后的类型判断

设计说明

这里没有新增 hook,也没有在聊天请求运行时直接写配置

原因是这个问题本质上是 provider 配置的一致性问题,放在配置保存和 provider 生命周期管理处处理更直观;如果在普通聊天请求里发现无效 ID 后再持久化配置,副作用会更大,也更难排查

测试

已运行:

uv run ruff format .
uv run ruff check .
uv run pytest -q tests/unit/test_config_route_provider_list.py tests/unit/test_provider_fallbacks.py tests/unit/test_astr_main_agent.py -k "fallback_chat_models or image_fallback or without_image_fallback or provider_config"

测试结果:

8 passed, 80 deselected

Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。

  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”

  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

Summary by Sourcery

Ensure fallback chat model configuration only references currently enabled and loaded chat providers and stays consistent with provider lifecycle changes.

Bug Fixes:

  • Remove disabled, deleted, non-chat, duplicate, or invalid providers from the fallback chat model list when saving core config or modifying providers.
  • Hide providers from selection lists when they are disabled or not currently loaded, except for agent runner configurations.

Enhancements:

  • Introduce shared helpers to determine enabled and selectable providers based on config and loaded instances.
  • Log and track pruned fallback chat provider IDs to aid in diagnosing configuration issues.

Tests:

  • Add unit tests covering fallback pruning behavior, including disabled/missing/duplicate IDs, non-list settings, and provider-source type resolution.
  • Add unit tests for provider config enablement and selectability logic, including agent runner handling.

@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. area:core The bug / feature is about astrbot's core, backend area:provider The bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner. labels Jun 1, 2026
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="tests/unit/test_config_route_provider_list.py" line_range="13-21" />
<code_context>
+    assert not _provider_config_enabled({"id": "disabled-provider", "enable": False})
+
+
+def test_provider_config_selectable_requires_loaded_non_agent_provider():
+    inst_map = {"loaded-provider": object()}
+
+    assert _provider_config_selectable(
+        {"id": "loaded-provider", "enable": True},
+        ["chat_completion"],
+        inst_map,
+    )
+    assert not _provider_config_selectable(
+        {"id": "unloaded-provider", "enable": True},
+        ["chat_completion"],
</code_context>
<issue_to_address>
**suggestion (testing):** Include tests for `_provider_config_selectable` when `id` is missing or not a string.

Since the helper does `provider_id = provider_config.get("id")` and `isinstance(provider_id, str)`, please add tests that cover configs with no `id` key and with a non-string `id`, asserting they are treated as non-selectable. This will document and preserve behavior for malformed or legacy configs.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread tests/unit/test_config_route_provider_list.py
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces functionality to prune stale or disabled provider IDs from fallback chat models and adds helper functions to filter selectable provider configurations. The review feedback highlights a potential bug in _provider_config_selectable where checking for agent_runner in the type list could incorrectly bypass loaded checks for other provider types, and suggests checking the provider's type directly instead. Additionally, the feedback recommends using boolean or for default values to handle None or empty strings correctly, and suggests simplifying the fallback logic for provider_type in get_enabled_chat_provider_ids.

Comment thread astrbot/dashboard/routes/config.py Outdated
Comment thread tests/unit/test_config_route_provider_list.py
Comment thread astrbot/core/provider/fallbacks.py Outdated
Comment thread astrbot/core/provider/fallbacks.py
- prune disabled, missing, duplicate, and non-chat providers from fallback_chat_models when core config or provider configs change

- hide disabled or unloaded providers from provider selection lists while keeping agent runners selectable

- add regression coverage for fallback pruning and provider list filtering
@Clhikari Clhikari force-pushed the fix/provider-fallback-filter branch from 0fe77e0 to b7e8b95 Compare June 1, 2026 05:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core The bug / feature is about astrbot's core, backend area:provider The bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner. size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 回退对话模型列表会保留已禁用或已删除的模型

1 participant