mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 09:50:21 +08:00
Fix replay fallback when model mapping is missing
This commit is contained in:
@@ -1946,19 +1946,19 @@ async def _resolve_replay_model_name(
|
||||
)
|
||||
return mapped_name, "model_mapping"
|
||||
|
||||
if same_provider and same_endpoint:
|
||||
return source_model, "none"
|
||||
if not (same_provider and same_endpoint):
|
||||
logger.debug(
|
||||
"[replay] No explicit model mapping for '{}' on provider '{}' (endpoint={}, api_format={}); "
|
||||
"forwarding original source model",
|
||||
source_model,
|
||||
target_provider.name or str(target_provider.id),
|
||||
str(getattr(target_endpoint, "id", "") or "unknown"),
|
||||
target_api_format or "unknown",
|
||||
)
|
||||
|
||||
provider_name = target_provider.name or str(target_provider.id)
|
||||
endpoint_id = str(getattr(target_endpoint, "id", "") or "unknown")
|
||||
api_format = target_api_format or "unknown"
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=(
|
||||
f"Target provider '{provider_name}' does not support model '{source_model}' "
|
||||
f"(endpoint={endpoint_id}, api_format={api_format})"
|
||||
),
|
||||
)
|
||||
# Keep replay aligned with the normal request path: if no global-model mapping exists,
|
||||
# forward the original source model name and let the target provider validate it.
|
||||
return source_model, "none"
|
||||
|
||||
|
||||
def _apply_replay_model_to_body(
|
||||
|
||||
@@ -7,7 +7,11 @@ from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from src.api.admin.usage.routes import AdminUsageDetailAdapter, AdminUsageRecordsAdapter
|
||||
from src.api.admin.usage.routes import (
|
||||
AdminUsageDetailAdapter,
|
||||
AdminUsageRecordsAdapter,
|
||||
_resolve_replay_model_name,
|
||||
)
|
||||
|
||||
|
||||
class _FakeQuery:
|
||||
@@ -273,3 +277,42 @@ async def test_admin_usage_detail_defers_large_body_columns_when_bodies_excluded
|
||||
assert (
|
||||
"ORM Path[Mapper[Usage(usage)] -> Usage.client_response_body_compressed]" in deferred_paths
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
("same_provider", "same_endpoint"),
|
||||
[
|
||||
(True, False),
|
||||
(False, False),
|
||||
],
|
||||
ids=["same-provider-cross-endpoint", "cross-provider"],
|
||||
)
|
||||
async def test_resolve_replay_model_name_falls_back_to_source_model_when_mapping_missing(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
same_provider: bool,
|
||||
same_endpoint: bool,
|
||||
) -> None:
|
||||
class _FakeMapper:
|
||||
def __init__(self, db: Any) -> None:
|
||||
self.db = db
|
||||
|
||||
async def get_mapping(self, source_model: str, provider_id: str) -> None:
|
||||
return None
|
||||
|
||||
monkeypatch.setattr("src.services.model.mapper.ModelMapperMiddleware", _FakeMapper)
|
||||
|
||||
resolved_model, mapping_source = await _resolve_replay_model_name(
|
||||
SimpleNamespace(),
|
||||
source_model="gpt-4o-mini",
|
||||
original_target_model="provider-specific-model",
|
||||
target_provider=SimpleNamespace(id="provider-2", name="OpenAI Compatible"),
|
||||
target_endpoint=SimpleNamespace(id="endpoint-2", api_format="openai:responses"),
|
||||
target_api_key=None,
|
||||
same_provider=same_provider,
|
||||
same_endpoint=same_endpoint,
|
||||
force_remap=False,
|
||||
)
|
||||
|
||||
assert resolved_model == "gpt-4o-mini"
|
||||
assert mapping_source == "none"
|
||||
|
||||
Reference in New Issue
Block a user