fixes setup scripts

fixes to env handling in setup script plus other minor fixes
This commit is contained in:
Pavel
2026-01-12 23:48:52 +03:00
parent f1d714b5c1
commit 974d98b94b
5 changed files with 125 additions and 83 deletions

View File

@@ -6,6 +6,19 @@ from typing import Dict, List, Optional
logger = logging.getLogger(__name__)
def _is_valid_api_key(key: Optional[str]) -> bool:
"""
Check if an API key is valid (not None, not empty, not string 'None').
Handles Pydantic loading 'None' from .env as string "None".
"""
if key is None:
return False
if not isinstance(key, str):
return False
key_stripped = key.strip().lower()
return key_stripped != "" and key_stripped != "none"
class ModelProvider(str, Enum):
OPENAI = "openai"
AZURE_OPENAI = "azure_openai"
@@ -87,40 +100,53 @@ class ModelRegistry:
# Skip DocsGPT model if using custom OpenAI-compatible endpoint
if not settings.OPENAI_BASE_URL:
self._add_docsgpt_models(settings)
if settings.OPENAI_API_KEY or (
settings.LLM_PROVIDER == "openai" and settings.API_KEY
if (
_is_valid_api_key(settings.OPENAI_API_KEY)
or (settings.LLM_PROVIDER == "openai" and _is_valid_api_key(settings.API_KEY))
or settings.OPENAI_BASE_URL
):
self._add_openai_models(settings)
if settings.OPENAI_API_BASE or (
settings.LLM_PROVIDER == "azure_openai" and settings.API_KEY
settings.LLM_PROVIDER == "azure_openai" and _is_valid_api_key(settings.API_KEY)
):
self._add_azure_openai_models(settings)
if settings.ANTHROPIC_API_KEY or (
settings.LLM_PROVIDER == "anthropic" and settings.API_KEY
if _is_valid_api_key(settings.ANTHROPIC_API_KEY) or (
settings.LLM_PROVIDER == "anthropic" and _is_valid_api_key(settings.API_KEY)
):
self._add_anthropic_models(settings)
if settings.GOOGLE_API_KEY or (
settings.LLM_PROVIDER == "google" and settings.API_KEY
if _is_valid_api_key(settings.GOOGLE_API_KEY) or (
settings.LLM_PROVIDER == "google" and _is_valid_api_key(settings.API_KEY)
):
self._add_google_models(settings)
if settings.GROQ_API_KEY or (
settings.LLM_PROVIDER == "groq" and settings.API_KEY
if _is_valid_api_key(settings.GROQ_API_KEY) or (
settings.LLM_PROVIDER == "groq" and _is_valid_api_key(settings.API_KEY)
):
self._add_groq_models(settings)
if settings.HUGGINGFACE_API_KEY or (
settings.LLM_PROVIDER == "huggingface" and settings.API_KEY
if _is_valid_api_key(settings.HUGGINGFACE_API_KEY) or (
settings.LLM_PROVIDER == "huggingface" and _is_valid_api_key(settings.API_KEY)
):
self._add_huggingface_models(settings)
# Default model selection
if settings.LLM_NAME and settings.LLM_NAME in self.models:
self.default_model_id = settings.LLM_NAME
elif settings.LLM_PROVIDER and settings.API_KEY:
for model_id, model in self.models.items():
if model.provider.value == settings.LLM_PROVIDER:
self.default_model_id = model_id
if settings.LLM_NAME:
# Parse LLM_NAME (may be comma-separated)
model_names = self._parse_model_names(settings.LLM_NAME)
# First model in the list becomes default
for model_name in model_names:
if model_name in self.models:
self.default_model_id = model_name
break
else:
# Backward compat: try exact match if no parsed model found
if not self.default_model_id and settings.LLM_NAME in self.models:
self.default_model_id = settings.LLM_NAME
if not self.default_model_id:
if settings.LLM_PROVIDER and _is_valid_api_key(settings.API_KEY):
for model_id, model in self.models.items():
if model.provider.value == settings.LLM_PROVIDER:
self.default_model_id = model_id
break
if not self.default_model_id and self.models:
self.default_model_id = next(iter(self.models.keys()))
logger.info(
f"ModelRegistry loaded {len(self.models)} models, default: {self.default_model_id}"
@@ -132,29 +158,29 @@ class ModelRegistry:
create_custom_openai_model,
)
# Add standard OpenAI models if API key is present
if settings.OPENAI_API_KEY:
for model in OPENAI_MODELS:
self.models[model.id] = model
# Check if using local OpenAI-compatible endpoint (Ollama, LM Studio, etc.)
using_local_endpoint = bool(
settings.OPENAI_BASE_URL and settings.OPENAI_BASE_URL.strip()
)
# Add custom model if OPENAI_BASE_URL is configured with a custom LLM_NAME
if (
settings.LLM_PROVIDER == "openai"
and settings.OPENAI_BASE_URL
and settings.LLM_NAME
):
custom_model = create_custom_openai_model(
settings.LLM_NAME, settings.OPENAI_BASE_URL
)
self.models[settings.LLM_NAME] = custom_model
logger.info(
f"Registered custom OpenAI model: {settings.LLM_NAME} at {settings.OPENAI_BASE_URL}"
)
# Fallback: add all OpenAI models if none were added
if not any(m.provider.value == "openai" for m in self.models.values()):
for model in OPENAI_MODELS:
self.models[model.id] = model
if using_local_endpoint:
# When OPENAI_BASE_URL is set, ONLY register custom models from LLM_NAME
# Do NOT add standard OpenAI models (gpt-5.1, etc.)
if settings.LLM_NAME:
model_names = self._parse_model_names(settings.LLM_NAME)
for model_name in model_names:
custom_model = create_custom_openai_model(
model_name, settings.OPENAI_BASE_URL
)
self.models[model_name] = custom_model
logger.info(
f"Registered custom OpenAI model: {model_name} at {settings.OPENAI_BASE_URL}"
)
else:
# Standard OpenAI API usage - add standard models if API key is valid
if _is_valid_api_key(settings.OPENAI_API_KEY):
for model in OPENAI_MODELS:
self.models[model.id] = model
def _add_azure_openai_models(self, settings):
from application.core.model_configs import AZURE_OPENAI_MODELS
@@ -240,6 +266,15 @@ class ModelRegistry:
)
self.models[model_id] = model
def _parse_model_names(self, llm_name: str) -> List[str]:
"""
Parse LLM_NAME which may contain comma-separated model names.
E.g., 'deepseek-r1:1.5b,gemma:2b' -> ['deepseek-r1:1.5b', 'gemma:2b']
"""
if not llm_name:
return []
return [name.strip() for name in llm_name.split(",") if name.strip()]
def get_model(self, model_id: str) -> Optional[AvailableModel]:
return self.models.get(model_id)

View File

@@ -1,6 +1,6 @@
from typing import Any, Dict, Optional
from application.core.model_settings import ModelRegistry
from application.core.model_settings import ModelRegistry, _is_valid_api_key
def get_api_key_for_provider(provider: str) -> Optional[str]:
@@ -19,9 +19,11 @@ def get_api_key_for_provider(provider: str) -> Optional[str]:
}
provider_key = provider_key_map.get(provider)
if provider_key:
if provider_key and _is_valid_api_key(provider_key):
return provider_key
return settings.API_KEY
if _is_valid_api_key(settings.API_KEY):
return settings.API_KEY
return None
def get_all_available_models() -> Dict[str, Dict[str, Any]]: