fix: normalize LLM provider key lookup and skip disabled HyDE ping (final review)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -8,7 +8,7 @@ from fastapi import APIRouter
|
||||
|
||||
from app.config.settings import settings
|
||||
from app.domain.retrieval import RetrievedChunk
|
||||
from app.services.llm.llm_factory import get_llm_client
|
||||
from app.services.llm.llm_factory import get_llm_client, get_llm_factory
|
||||
from app.shared.bootstrap import (
|
||||
get_bm25_retriever,
|
||||
get_binary_store,
|
||||
@@ -129,6 +129,27 @@ async def get_health():
|
||||
}
|
||||
|
||||
|
||||
def _normalize_llm_provider(raw_provider: str) -> str:
|
||||
"""Normalize a raw LLM_PROVIDER/HYDE_LLM_PROVIDER settings string to the
|
||||
canonical LLMProvider enum value, the SAME way LLMFactory.create() does.
|
||||
|
||||
TrackedLLMClient.chat() (tracked_client.py) always records usage under
|
||||
`self._inner.config.provider.value` — the NORMALIZED enum value produced by
|
||||
LLMFactory._parse_provider() — never the raw string a caller passed to
|
||||
get_llm_client(). Reusing that same normalization here (instead of
|
||||
duplicating the alias table) guarantees the tracker key this route reads
|
||||
always agrees with the key TrackedLLMClient wrote, even when the raw
|
||||
settings value is a non-canonical alias (e.g. "deepseek-v3") or different
|
||||
casing. Falls back to the raw string, unchanged, if it does not match any
|
||||
known provider/alias, so this passive status endpoint still renders
|
||||
(as "never_called") instead of raising on a misconfigured provider string.
|
||||
"""
|
||||
try:
|
||||
return get_llm_factory()._parse_provider(raw_provider).value
|
||||
except ValueError:
|
||||
return raw_provider
|
||||
|
||||
|
||||
def _resolve_role_provider_model(role: str) -> tuple[str, str]:
|
||||
"""Return the (provider, model) pair currently configured for one AI model role.
|
||||
|
||||
@@ -138,10 +159,10 @@ def _resolve_role_provider_model(role: str) -> tuple[str, str]:
|
||||
recorded when HyDE actually ran.
|
||||
"""
|
||||
if role == "main_llm":
|
||||
return settings.llm_provider, settings.llm_model
|
||||
return _normalize_llm_provider(settings.llm_provider), settings.llm_model
|
||||
if role == "hyde_llm":
|
||||
return (
|
||||
settings.hyde_llm_provider or settings.llm_provider,
|
||||
_normalize_llm_provider(settings.hyde_llm_provider or settings.llm_provider),
|
||||
settings.hyde_llm_model or settings.llm_model,
|
||||
)
|
||||
if role == "embedding":
|
||||
@@ -204,7 +225,16 @@ async def get_model_statuses():
|
||||
|
||||
|
||||
async def _ping_main_or_hyde(role: str) -> None:
|
||||
"""Send one minimal chat completion to the LLM configured for `role`."""
|
||||
"""Send one minimal chat completion to the LLM configured for `role`.
|
||||
|
||||
Skipped entirely for "hyde_llm" when settings.hyde_enabled is False,
|
||||
mirroring _ping_reranker()'s disabled-skip pattern: when HyDE is turned
|
||||
off (or reuses the main LLM, the default), issuing this ping would just be
|
||||
a redundant duplicate chat call against the same model for no benefit.
|
||||
"main_llm" is always pinged regardless of this check.
|
||||
"""
|
||||
if role == "hyde_llm" and not settings.hyde_enabled:
|
||||
return
|
||||
provider, model = _resolve_role_provider_model(role)
|
||||
try:
|
||||
client = get_llm_client(provider=provider, model=model)
|
||||
|
||||
Reference in New Issue
Block a user