""" Lazy singleton loader for all LLM instances and the CrewAI agents. Ensures models are initialised once and reused across requests. """ import logging import os from functools import lru_cache from typing import Optional from crewai import LLM from langchain_openai import ChatOpenAI from langchain_google_genai import ChatGoogleGenerativeAI from app.core.config import settings logger = logging.getLogger(__name__) # ── LLM singletons ──────────────────────────────────────────────────────────── @lru_cache(maxsize=1) def get_llm_gemini() -> LLM: """Return the cached Gemini CrewAI LLM instance.""" logger.info("Initialising Gemini LLM (%s)", settings.LLM_GEMINI_MODEL) return LLM( model=settings.LLM_GEMINI_MODEL, temperature=0.2, api_key=settings.GOOGLE_API_KEY, ) @lru_cache(maxsize=1) def get_llm_groq() -> LLM: """Return the cached Groq CrewAI LLM instance.""" logger.info("Initialising Groq LLM (%s)", settings.LLM_GROQ_MODEL) return LLM( model=settings.LLM_GROQ_MODEL, temperature=0, api_key=settings.GROQ_API_KEY, ) @lru_cache(maxsize=1) def get_llm_open_router() -> LLM: """Return the cached OpenRouter CrewAI LLM instance.""" logger.info("Initialising OpenRouter LLM (%s)", settings.LLM_OPENROUTER_MODEL) return LLM( api_key=settings.OPENROUTER_API_KEY, base_url=settings.LLM_OPENROUTER_BASE_URL, model=settings.LLM_OPENROUTER_MODEL, ) @lru_cache(maxsize=1) def get_langchain_llm() -> ChatOpenAI: """Return the cached LangChain ChatOpenAI (OpenRouter) instance.""" logger.info("Initialising LangChain ChatOpenAI via OpenRouter") return ChatOpenAI( model=settings.LLM_OPENROUTER_MODEL.replace("openrouter/", ""), api_key=settings.OPENROUTER_API_KEY, base_url=settings.LLM_OPENROUTER_BASE_URL, ) @lru_cache(maxsize=1) def get_gemini_langchain() -> ChatGoogleGenerativeAI: """Return the cached LangChain Google Generative AI (Gemini) instance.""" logger.info("Initialising LangChain Gemini") # Strip the crewai prefix for the raw model name raw_model = settings.LLM_GEMINI_MODEL.replace("gemini/", "") return ChatGoogleGenerativeAI( model=raw_model, google_api_key=settings.GOOGLE_API_KEY, temperature=0, )