polyglot-tutor / src /tutor /services /llm /factory.py
blizzarman's picture
feat: M0 walking skeleton (app, service protocols, CI/CD, Space deploy)
00d5ae5
Raw
History Blame Contribute Delete
1.28 kB
"""Provider resolution: Settings -> LLMClient."""
from tutor.config import Settings
from tutor.services.llm.base import LLMClient
from tutor.services.llm.fake import FakeLLMClient
from tutor.services.llm.openai_compat import OpenAICompatClient
GEMINI_OPENAI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"
_PRESET_BASE_URLS: dict[str, str | None] = {
"gemini": GEMINI_OPENAI_BASE_URL,
"mistral": "https://api.mistral.ai/v1",
"ollama": "http://localhost:11434/v1", # premium mode: reached over Tailscale in M5
"openai": None, # SDK default
}
def create_llm_client(settings: Settings) -> LLMClient:
if settings.llm_provider == "fake":
return FakeLLMClient()
api_key = settings.llm_api_key.get_secret_value() if settings.llm_api_key else None
if settings.llm_provider == "ollama":
api_key = api_key or "ollama" # local servers accept any non-empty key
if not api_key:
msg = f"LLM_API_KEY is required for provider '{settings.llm_provider}'"
raise ValueError(msg)
return OpenAICompatClient(
model=settings.llm_model,
api_key=api_key,
base_url=settings.llm_base_url or _PRESET_BASE_URLS[settings.llm_provider],
timeout_s=settings.llm_timeout_s,
)