fix(admin): LLM provider/model switching now reads DB overrides correctly
- get_llm_provider() now accepts provider + model args so DB overrides propagate through to all provider constructors (was always reading env vars, ignoring the admin UI selection) - /test-llm replaced with lightweight ping (max_tokens=20) instead of running a full bill analysis; shows model name + reply, no truncation - /api/settings/llm-models endpoint fetches available models live from each provider's API (OpenAI, Anthropic REST, Gemini, Ollama) - Admin UI model picker dynamically populated from provider API; falls back to manual text input on error; Custom model name option kept - Default Gemini model updated: gemini-1.5-pro → gemini-2.0-flash Co-Authored-By: Jack Levy
This commit is contained in:
@@ -185,10 +185,10 @@ class LLMProvider(ABC):
|
||||
|
||||
|
||||
class OpenAIProvider(LLMProvider):
|
||||
def __init__(self):
|
||||
def __init__(self, model: str | None = None):
|
||||
from openai import OpenAI
|
||||
self.client = OpenAI(api_key=settings.OPENAI_API_KEY)
|
||||
self.model = settings.OPENAI_MODEL
|
||||
self.model = model or settings.OPENAI_MODEL
|
||||
|
||||
def generate_brief(self, doc_text: str, bill_metadata: dict) -> ReverseBrief:
|
||||
prompt = build_prompt(doc_text, bill_metadata, MAX_TOKENS_DEFAULT)
|
||||
@@ -220,10 +220,10 @@ class OpenAIProvider(LLMProvider):
|
||||
|
||||
|
||||
class AnthropicProvider(LLMProvider):
|
||||
def __init__(self):
|
||||
def __init__(self, model: str | None = None):
|
||||
import anthropic
|
||||
self.client = anthropic.Anthropic(api_key=settings.ANTHROPIC_API_KEY)
|
||||
self.model = settings.ANTHROPIC_MODEL
|
||||
self.model = model or settings.ANTHROPIC_MODEL
|
||||
|
||||
def generate_brief(self, doc_text: str, bill_metadata: dict) -> ReverseBrief:
|
||||
prompt = build_prompt(doc_text, bill_metadata, MAX_TOKENS_DEFAULT)
|
||||
@@ -249,11 +249,11 @@ class AnthropicProvider(LLMProvider):
|
||||
|
||||
|
||||
class GeminiProvider(LLMProvider):
|
||||
def __init__(self):
|
||||
def __init__(self, model: str | None = None):
|
||||
import google.generativeai as genai
|
||||
genai.configure(api_key=settings.GEMINI_API_KEY)
|
||||
self._genai = genai
|
||||
self.model_name = settings.GEMINI_MODEL
|
||||
self.model_name = model or settings.GEMINI_MODEL
|
||||
|
||||
def _make_model(self, system_prompt: str):
|
||||
return self._genai.GenerativeModel(
|
||||
@@ -274,9 +274,9 @@ class GeminiProvider(LLMProvider):
|
||||
|
||||
|
||||
class OllamaProvider(LLMProvider):
|
||||
def __init__(self):
|
||||
def __init__(self, model: str | None = None):
|
||||
self.base_url = settings.OLLAMA_BASE_URL.rstrip("/")
|
||||
self.model = settings.OLLAMA_MODEL
|
||||
self.model = model or settings.OLLAMA_MODEL
|
||||
|
||||
def _generate(self, system_prompt: str, user_prompt: str) -> str:
|
||||
import requests as req
|
||||
@@ -327,15 +327,20 @@ class OllamaProvider(LLMProvider):
|
||||
return parse_brief_json(raw2, "ollama", self.model)
|
||||
|
||||
|
||||
def get_llm_provider() -> LLMProvider:
|
||||
"""Factory — returns the configured LLM provider."""
|
||||
provider = settings.LLM_PROVIDER.lower()
|
||||
def get_llm_provider(provider: str | None = None, model: str | None = None) -> LLMProvider:
|
||||
"""Factory — returns the configured LLM provider.
|
||||
|
||||
Pass ``provider`` and/or ``model`` explicitly (e.g. from DB overrides) to bypass env defaults.
|
||||
"""
|
||||
if provider is None:
|
||||
provider = settings.LLM_PROVIDER
|
||||
provider = provider.lower()
|
||||
if provider == "openai":
|
||||
return OpenAIProvider()
|
||||
return OpenAIProvider(model=model)
|
||||
elif provider == "anthropic":
|
||||
return AnthropicProvider()
|
||||
return AnthropicProvider(model=model)
|
||||
elif provider == "gemini":
|
||||
return GeminiProvider()
|
||||
return GeminiProvider(model=model)
|
||||
elif provider == "ollama":
|
||||
return OllamaProvider()
|
||||
return OllamaProvider(model=model)
|
||||
raise ValueError(f"Unknown LLM_PROVIDER: '{provider}'. Must be one of: openai, anthropic, gemini, ollama")
|
||||
|
||||
Reference in New Issue
Block a user