mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-07-06 09:21:16 -03:00
fix(llm): require api_base for custom provider without preset default
This commit is contained in:
@@ -282,15 +282,17 @@ class LLMService:
|
|||||||
def is_configured(self) -> bool:
|
def is_configured(self) -> bool:
|
||||||
"""Return ``True`` when the LLM provider is minimally configured.
|
"""Return ``True`` when the LLM provider is minimally configured.
|
||||||
|
|
||||||
A provider is considered configured when ``llm_model`` is set and
|
A provider is considered configured when ``llm_model`` is set,
|
||||||
an API key is configured for providers that require one (e.g.
|
an API key is configured for providers that require one (e.g.
|
||||||
Ollama does not).
|
Ollama does not), and an API base URL is set for providers that
|
||||||
|
have no preset default (e.g. ``custom``).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cfg = self._get_config()
|
cfg = self._get_config()
|
||||||
has_model = bool(cfg["model"])
|
has_model = bool(cfg["model"])
|
||||||
has_key = bool(cfg["api_key"]) or not self._provider_requires_key(cfg["provider"])
|
has_key = bool(cfg["api_key"]) or not self._provider_requires_key(cfg["provider"])
|
||||||
return has_model and has_key
|
has_base = bool(cfg["api_base"]) or bool(_PROVIDER_DEFAULTS.get(cfg["provider"]))
|
||||||
|
return has_model and has_key and has_base
|
||||||
|
|
||||||
def _resolve_api_base(self, provider: str, api_base: str) -> str:
|
def _resolve_api_base(self, provider: str, api_base: str) -> str:
|
||||||
"""Resolve the API base URL for the given provider.
|
"""Resolve the API base URL for the given provider.
|
||||||
@@ -314,20 +316,26 @@ class LLMService:
|
|||||||
def _ensure_configured(self) -> Dict[str, Any]:
|
def _ensure_configured(self) -> Dict[str, Any]:
|
||||||
"""Validate configuration and return it, or raise.
|
"""Validate configuration and return it, or raise.
|
||||||
|
|
||||||
A provider is considered configured when ``llm_model`` is set and
|
A provider is considered configured when ``llm_model`` is set,
|
||||||
(for non-Ollama) an API key is configured.
|
an API key is configured for providers that require one, and
|
||||||
|
an API base URL is set for providers without a preset default.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cfg = self._get_config()
|
cfg = self._get_config()
|
||||||
has_model = bool(cfg["model"])
|
has_model = bool(cfg["model"])
|
||||||
needs_key = self._provider_requires_key(cfg["provider"])
|
needs_key = self._provider_requires_key(cfg["provider"])
|
||||||
has_key = bool(cfg["api_key"]) or not needs_key
|
has_key = bool(cfg["api_key"]) or not needs_key
|
||||||
if not (has_model and has_key):
|
has_base = bool(cfg["api_base"]) or bool(_PROVIDER_DEFAULTS.get(cfg["provider"]))
|
||||||
|
if not (has_model and has_key and has_base):
|
||||||
parts = []
|
parts = []
|
||||||
if not has_model:
|
if not has_model:
|
||||||
parts.append("No LLM model specified")
|
parts.append("No LLM model specified")
|
||||||
if not has_key and needs_key:
|
if not has_key and needs_key:
|
||||||
parts.append("No LLM API key configured")
|
parts.append("No LLM API key configured")
|
||||||
|
if not has_base:
|
||||||
|
parts.append(
|
||||||
|
f"No API base URL for provider '{cfg['provider']}'"
|
||||||
|
)
|
||||||
detail = "; ".join(parts) if parts else "LLM provider is not configured"
|
detail = "; ".join(parts) if parts else "LLM provider is not configured"
|
||||||
raise LLMNotConfiguredError(
|
raise LLMNotConfiguredError(
|
||||||
f"{detail}. Configure it in Settings → AI Provider."
|
f"{detail}. Configure it in Settings → AI Provider."
|
||||||
|
|||||||
@@ -136,6 +136,32 @@ class TestLLMServiceConfiguration:
|
|||||||
with pytest.raises(LLMNotConfiguredError):
|
with pytest.raises(LLMNotConfiguredError):
|
||||||
service._ensure_configured()
|
service._ensure_configured()
|
||||||
|
|
||||||
|
def test_not_configured_custom_without_api_base(self):
|
||||||
|
settings = MockSettings(
|
||||||
|
llm_enabled=True, llm_provider="custom",
|
||||||
|
llm_api_key="sk-test", llm_api_base="", llm_model="gpt-4o",
|
||||||
|
)
|
||||||
|
service = LLMService(settings)
|
||||||
|
assert service.is_configured() is False
|
||||||
|
|
||||||
|
def test_custom_configured_with_api_base(self):
|
||||||
|
settings = MockSettings(
|
||||||
|
llm_enabled=True, llm_provider="custom",
|
||||||
|
llm_api_key="sk-test",
|
||||||
|
llm_api_base="https://my.api.com/v1", llm_model="gpt-4o",
|
||||||
|
)
|
||||||
|
service = LLMService(settings)
|
||||||
|
assert service.is_configured() is True
|
||||||
|
|
||||||
|
def test_ensure_configured_raises_custom_without_api_base(self):
|
||||||
|
settings = MockSettings(
|
||||||
|
llm_enabled=True, llm_provider="custom",
|
||||||
|
llm_api_key="sk-test", llm_api_base="", llm_model="gpt-4o",
|
||||||
|
)
|
||||||
|
service = LLMService(settings)
|
||||||
|
with pytest.raises(LLMNotConfiguredError, match="API base URL"):
|
||||||
|
service._ensure_configured()
|
||||||
|
|
||||||
|
|
||||||
class TestLLMServiceChatCompletion:
|
class TestLLMServiceChatCompletion:
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
|
|||||||
Reference in New Issue
Block a user