mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
fix(proxy): use filtered router count for search pagination of DB-only models
Greptile review caught a pagination bug: _get_db_only_models used len(all_models) (full unfiltered router list) for the take calculation. When searching with a large router (e.g. 50 models, page size 50), the take would be 0 even though only 1 router model matched the search, causing DB-only models to never be fetched. Fix: accept filtered_router_count parameter and use it for pagination. Added regression test with 50 router models where only 1 matches search. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2159261da4
commit
bb176f4a10
2 changed files with 51 additions and 3 deletions
|
|
@ -8885,6 +8885,7 @@ async def _get_db_only_models(
|
|||
sort_by: Optional[str] = None,
|
||||
page: int = 1,
|
||||
size: int = 50,
|
||||
filtered_router_count: Optional[int] = None,
|
||||
) -> Tuple[List[Dict[str, Any]], int]:
|
||||
"""
|
||||
Fetch models from the database that are NOT already loaded in the router.
|
||||
|
|
@ -8894,13 +8895,16 @@ async def _get_db_only_models(
|
|||
those models still appear in the model list.
|
||||
|
||||
Args:
|
||||
all_models: Models already in the router
|
||||
all_models: Models already in the router (used to collect DB model IDs to exclude)
|
||||
prisma_client: Prisma client for database queries
|
||||
proxy_config: Proxy config for decrypting models
|
||||
search: Optional search term (case-insensitive)
|
||||
sort_by: Optional sort field
|
||||
page: Current page number
|
||||
size: Page size
|
||||
filtered_router_count: Number of router models after search filtering.
|
||||
When provided, used for pagination instead of len(all_models).
|
||||
This ensures correct pagination when search reduces the visible router models.
|
||||
|
||||
Returns:
|
||||
Tuple of (db_only_models, db_only_count)
|
||||
|
|
@ -8936,8 +8940,8 @@ async def _get_db_only_models(
|
|||
if db_only_count == 0:
|
||||
return [], 0
|
||||
|
||||
# Determine how many to fetch
|
||||
router_models_count = len(all_models)
|
||||
# Use filtered count for pagination when searching, full count otherwise
|
||||
router_models_count = filtered_router_count if filtered_router_count is not None else len(all_models)
|
||||
models_needed_for_page = size * page
|
||||
|
||||
if sort_by:
|
||||
|
|
@ -9018,6 +9022,7 @@ async def _apply_search_filter_to_models(
|
|||
sort_by=sort_by,
|
||||
page=page,
|
||||
size=size,
|
||||
filtered_router_count=len(filtered_router_models),
|
||||
)
|
||||
|
||||
total_count = len(filtered_router_models) + db_only_count
|
||||
|
|
|
|||
|
|
@ -258,3 +258,46 @@ class TestApplySearchFilterIncludesDbOnlyModels:
|
|||
|
||||
assert result == router_models
|
||||
assert total_count is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_pagination_uses_filtered_count(self):
|
||||
"""When searching, pagination should use the filtered router count, not the full count.
|
||||
|
||||
Regression test: if the router has 50 models but only 1 matches search,
|
||||
DB-only models should still be fetched (take should be based on 1, not 50).
|
||||
"""
|
||||
# 50 router models, but only "gpt-5" matches the search "gpt-5"
|
||||
router_models = [_make_router_model(f"model-{i}", f"id-{i}", db_model=True) for i in range(49)]
|
||||
router_models.append(_make_router_model("gpt-5", "id-49", db_model=True))
|
||||
|
||||
db_record = _make_db_record("gpt-5.1", "id-missing")
|
||||
|
||||
prisma_client = MagicMock()
|
||||
prisma_client.db.litellm_proxymodeltable.count = AsyncMock(return_value=1)
|
||||
prisma_client.db.litellm_proxymodeltable.find_many = AsyncMock(
|
||||
return_value=[db_record]
|
||||
)
|
||||
|
||||
decrypted_model = _make_router_model("gpt-5.1", "id-missing", db_model=True)
|
||||
proxy_config = MagicMock()
|
||||
proxy_config.decrypt_model_list_from_db = MagicMock(
|
||||
return_value=[decrypted_model]
|
||||
)
|
||||
|
||||
result, total_count = await _apply_search_filter_to_models(
|
||||
all_models=router_models,
|
||||
search="gpt-5",
|
||||
page=1,
|
||||
size=50,
|
||||
prisma_client=prisma_client,
|
||||
proxy_config=proxy_config,
|
||||
)
|
||||
|
||||
model_names = [m["model_name"] for m in result]
|
||||
# Only gpt-5 matches search from router, gpt-5.1 from DB
|
||||
assert "gpt-5" in model_names
|
||||
assert "gpt-5.1" in model_names
|
||||
assert len(result) == 2
|
||||
assert total_count == 2
|
||||
# Verify find_many was actually called (not skipped due to bad take calculation)
|
||||
prisma_client.db.litellm_proxymodeltable.find_many.assert_called_once()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue