1 line
16 KiB
JSON
1 line
16 KiB
JSON
{"repo": "aashishravindran/agentic-fitness-app", "files": {"llm.py": {"e724b69fd3bea4f12d41a49fafd508899ab4ccd8": {"t": 1785674064.7850623, "n": 7941, "h": "2dd648893fb0db4b", "c": "\"\"\"\nLLM client interface: single place to choose and configure the LLM backend.\n\nSet LLM_PROVIDER to one of: gemini | openai | bedrock | ollama | deepseek\nIf unset, provider is auto-detected from API keys (Gemini > OpenAI > DeepSeek > Ollama).\n\nEnvironment variables per provider:\n- gemini: GOOGLE_API_KEY or GEMINI_API_KEY, optional GEMINI_MODEL\n- openai: OPENAI_API_KEY, optional OPENAI_MODEL\n- bedrock: AWS credentials, optional BEDROCK_MODEL\n- ollama: optional OLLAMA_BASE_URL, OLLAMA_MODEL\n- deepseek: DEEPSEEK_API_KEY, optional DEEPSEEK_MODEL (default: deepseek-chat)\n\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nfrom typing import Any\n\n# Load .env so API keys are available\nimport config # noqa: F401\n\n# Lazy model imports to avoid requiring all backends\n_GoogleModel: Any = None\n_OpenAIModel: Any = None\n_OllamaModel: Any = None\n_BedrockModel: Any = None\n\n\ndef _get_google_model():\n global _GoogleModel\n if _GoogleModel is None:\n try:\n from pydantic_ai.models.google import GoogleModel as M\n _GoogleModel = M\n except ImportError:\n try:\n from pydantic_ai.models.gemini import GeminiModel as M\n _GoogleModel = M\n except ImportError:\n pass\n return _GoogleModel\n\n\ndef _get_openai_model():\n global _OpenAIModel\n if _OpenAIModel is None:\n try:\n from pydantic_ai.models.openai import OpenAIModel as M\n _OpenAIModel = M\n except ImportError:\n pass\n return _OpenAIModel\n\n\ndef _get_ollama_model():\n global _OllamaModel\n if _OllamaModel is None:\n try:\n from pydantic_ai.models.ollama import OllamaModel as M\n _OllamaModel = M\n except ImportError:\n try:\n from pydantic_ai.models import OllamaModel as M\n _OllamaModel = M\n except ImportError:\n pass\n return _OllamaModel\n\n\ndef _get_bedrock_model():\n global _BedrockModel\n if _BedrockModel is None:\n try:\n from pydantic_ai.models.bedrock import BedrockConverseModel as M\n _BedrockModel = M\n except ImportError:\n pass\n return _BedrockModel\n\n\ndef _create_gemini_model():\n GoogleModel = _get_google_model()\n if not GoogleModel:\n raise ImportError(\"Gemini support not installed. pip install pydantic-ai[google]\")\n key = os.getenv(\"GOOGLE_API_KEY\") or os.getenv(\"GEMINI_API_KEY\")\n if not key:\n raise ValueError(\"Set GOOGLE_API_KEY or GEMINI_API_KEY for Gemini.\")\n model_name = os.getenv(\"GEMINI_MODEL\", \"gemini-2.0-flash\")\n models_to_try = [model_name, \"gemini-2.0-flash\", \"gemini-2.5-flash\", \"gemini-1.5-pro\", \"gemini-1.0-pro\"]\n last_error = None\n for name in models_to_try:\n if not name:\n continue\n try:\n return GoogleModel(name, api_key=key)\n except Exception as e:\n last_error = e\n raise ValueError(f\"Could not initialize Gemini. Last error: {last_error}\") from last_error\n\n\ndef _create_openai_model():\n OpenAIModel = _get_openai_model()\n if not OpenAIModel:\n raise ImportError(\"OpenAI support not installed. pip install pydantic-ai[openai]\")\n key = os.getenv(\"OPENAI_API_KEY\")\n if not key:\n raise ValueError(\"Set OPENAI_API_KEY for OpenAI.\")\n model_name = os.getenv(\"OPENAI_MODEL\", \"gpt-4o-mini\")\n return OpenAIModel(model_name, api_key=key)\n\n\ndef _create_ollama_model():\n \"\"\"Create Ollama model: use native OllamaModel if available, else OpenAI-compatible API.\"\"\"\n base = os.getenv(\"OLLAMA_BASE_URL\", \"http://localhost:11434\").rstrip(\"/\")\n base_v1 = f\"{base}/v1\"\n model_name = os.getenv(\"OLLAMA_MODEL\", \"llama3.2\")\n\n # 1) Prefer pydantic-ai's native Ollama model\n OllamaModel = _get_ollama_model()\n if OllamaModel:\n return OllamaModel(model_name, base_url=base)\n\n # 2) Fallback: Ollama exposes OpenAI-compatible API at http://localhost:11434/v1\n try:\n # Try passing base_url (older pydantic-ai OpenAIModel may support it)\n OpenAIModel = _get_openai_model()\n if OpenAIModel:\n return OpenAIModel(model_name, api_key=\"ollama\", base_url=base_v1)\n except TypeError:\n pass\n\n try:\n # Newer pydantic-ai: use OpenAIChatModel + OpenAIProvider with custom client\n from openai import AsyncOpenAI\n from pydantic_ai.models.openai import OpenAIChatModel\n from pydantic_ai.providers.openai import OpenAIProvider\n async_client = AsyncOpenAI(base_url=base_v1, api_key=\"ollama\")\n provider = OpenAIProvider(openai_client=async_client)\n return OpenAIChatModel(model_name, provider=provider)\n except (ImportError, TypeError, AttributeError):\n pass\n\n raise ImportError(\n \"Ollama support requires either: (1) pydantic-ai with Ollama model, or \"\n \"(2) pydantic-ai[openai] with openai package for Ollama's OpenAI-compatible API. \"\n \"Install: pip install 'pydantic-ai[openai]' openai\"\n )\n\n\ndef _create_bedrock_model():\n BedrockModel = _get_bedrock_model()\n if not BedrockModel:\n raise ImportError(\"Bedrock support not installed. pip install pydantic-ai[bedrock]\")\n model_id = os.getenv(\"BEDROCK_MODEL\", \"anthropic.claude-3-5-sonnet-20241022-v2:0\")\n return BedrockModel(model_id)\n\n\ndef _create_deepseek_model():\n \"\"\"DeepSeek uses an OpenAI-compatible API at https://api.deepseek.com.\"\"\"\n key = os.getenv(\"DEEPSEEK_API_KEY\")\n if not key:\n raise ValueError(\"Set DEEPSEEK_API_KEY for DeepSeek. Get one at https://platform.deepseek.com\")\n base = \"https://api.deepseek.com\"\n model_name = os.getenv(\"DEEPSEEK_MODEL\", \"deepseek-chat\")\n\n OpenAIModel = _get_openai_model()\n if OpenAIModel:\n try:\n return OpenAIModel(model_name, api_key=key, base_url=base)\n except TypeError:\n pass\n\n try:\n from openai import AsyncOpenAI\n from pydantic_ai.models.openai import OpenAIChatModel\n from pydantic_ai.providers.openai import OpenAIProvider\n async_client = AsyncOpenAI(base_url=base, api_key=key)\n provider = OpenAIProvider(openai_client=async_client)\n return OpenAIChatModel(model_name, provider=provider)\n except (ImportError, TypeError, AttributeError) as e:\n raise ImportError(\n \"DeepSeek uses the OpenAI-compatible API. Install: pip install 'pydantic-ai[openai]' openai\"\n ) from e\n\n\ndef get_llm_model():\n \"\"\"\n Return the configured LLM model for workers/trainer (structured workout generation).\n Use LLM_PROVIDER=gemini|openai|bedrock|ollama|deepseek to force a provider; otherwise auto-detect.\n \"\"\"\n provider = (os.getenv(\"LLM_PROVIDER\") or \"\").strip().lower()\n\n if provider == \"gemini\":\n return _create_gemini_model()\n if provider == \"openai\":\n return _create_openai_model()\n if provider == \"bedrock\":\n return _create_bedrock_model()\n if provider == \"ollama\":\n return _create_ollama_model()\n if provider == \"deepseek\":\n return _create_deepseek_model()\n\n # Auto-detect from API keys: Gemini > OpenAI > DeepSeek > Ollama\n if (os.getenv(\"GOOGLE_API_KEY\") or os.getenv(\"GEMINI_API_KEY\")) and _get_google_model():\n return _create_gemini_model()\n if os.getenv(\"OPENAI_API_KEY\") and _get_openai_model():\n return _create_openai_model()\n if os.getenv(\"DEEPSEEK_API_KEY\") and _get_openai_model():\n return _create_deepseek_model()\n if _get_ollama_model():\n return _create_ollama_model()\n\n raise ValueError(\n \"No LLM configured. Set LLM_PROVIDER (gemini|openai|bedrock|ollama|deepseek) and the corresponding API keys.\"\n )\n\n\ndef get_supervisor_model():\n \"\"\"\n Return the configured LLM model for the supervisor (routing and safety).\n Uses the same LLM_PROVIDER and fallbacks as get_llm_model().\n \"\"\"\n return get_llm_model()\n"}, "8330c40fe41123f69ad9c0ffa2475c4065aff2be": {"t": 1785752905.3753564, "n": 7941, "h": "2dd648893fb0db4b", "c": "\"\"\"\nLLM client interface: single place to choose and configure the LLM backend.\n\nSet LLM_PROVIDER to one of: gemini | openai | bedrock | ollama | deepseek\nIf unset, provider is auto-detected from API keys (Gemini > OpenAI > DeepSeek > Ollama).\n\nEnvironment variables per provider:\n- gemini: GOOGLE_API_KEY or GEMINI_API_KEY, optional GEMINI_MODEL\n- openai: OPENAI_API_KEY, optional OPENAI_MODEL\n- bedrock: AWS credentials, optional BEDROCK_MODEL\n- ollama: optional OLLAMA_BASE_URL, OLLAMA_MODEL\n- deepseek: DEEPSEEK_API_KEY, optional DEEPSEEK_MODEL (default: deepseek-chat)\n\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nfrom typing import Any\n\n# Load .env so API keys are available\nimport config # noqa: F401\n\n# Lazy model imports to avoid requiring all backends\n_GoogleModel: Any = None\n_OpenAIModel: Any = None\n_OllamaModel: Any = None\n_BedrockModel: Any = None\n\n\ndef _get_google_model():\n global _GoogleModel\n if _GoogleModel is None:\n try:\n from pydantic_ai.models.google import GoogleModel as M\n _GoogleModel = M\n except ImportError:\n try:\n from pydantic_ai.models.gemini import GeminiModel as M\n _GoogleModel = M\n except ImportError:\n pass\n return _GoogleModel\n\n\ndef _get_openai_model():\n global _OpenAIModel\n if _OpenAIModel is None:\n try:\n from pydantic_ai.models.openai import OpenAIModel as M\n _OpenAIModel = M\n except ImportError:\n pass\n return _OpenAIModel\n\n\ndef _get_ollama_model():\n global _OllamaModel\n if _OllamaModel is None:\n try:\n from pydantic_ai.models.ollama import OllamaModel as M\n _OllamaModel = M\n except ImportError:\n try:\n from pydantic_ai.models import OllamaModel as M\n _OllamaModel = M\n except ImportError:\n pass\n return _OllamaModel\n\n\ndef _get_bedrock_model():\n global _BedrockModel\n if _BedrockModel is None:\n try:\n from pydantic_ai.models.bedrock import BedrockConverseModel as M\n _BedrockModel = M\n except ImportError:\n pass\n return _BedrockModel\n\n\ndef _create_gemini_model():\n GoogleModel = _get_google_model()\n if not GoogleModel:\n raise ImportError(\"Gemini support not installed. pip install pydantic-ai[google]\")\n key = os.getenv(\"GOOGLE_API_KEY\") or os.getenv(\"GEMINI_API_KEY\")\n if not key:\n raise ValueError(\"Set GOOGLE_API_KEY or GEMINI_API_KEY for Gemini.\")\n model_name = os.getenv(\"GEMINI_MODEL\", \"gemini-2.0-flash\")\n models_to_try = [model_name, \"gemini-2.0-flash\", \"gemini-2.5-flash\", \"gemini-1.5-pro\", \"gemini-1.0-pro\"]\n last_error = None\n for name in models_to_try:\n if not name:\n continue\n try:\n return GoogleModel(name, api_key=key)\n except Exception as e:\n last_error = e\n raise ValueError(f\"Could not initialize Gemini. Last error: {last_error}\") from last_error\n\n\ndef _create_openai_model():\n OpenAIModel = _get_openai_model()\n if not OpenAIModel:\n raise ImportError(\"OpenAI support not installed. pip install pydantic-ai[openai]\")\n key = os.getenv(\"OPENAI_API_KEY\")\n if not key:\n raise ValueError(\"Set OPENAI_API_KEY for OpenAI.\")\n model_name = os.getenv(\"OPENAI_MODEL\", \"gpt-4o-mini\")\n return OpenAIModel(model_name, api_key=key)\n\n\ndef _create_ollama_model():\n \"\"\"Create Ollama model: use native OllamaModel if available, else OpenAI-compatible API.\"\"\"\n base = os.getenv(\"OLLAMA_BASE_URL\", \"http://localhost:11434\").rstrip(\"/\")\n base_v1 = f\"{base}/v1\"\n model_name = os.getenv(\"OLLAMA_MODEL\", \"llama3.2\")\n\n # 1) Prefer pydantic-ai's native Ollama model\n OllamaModel = _get_ollama_model()\n if OllamaModel:\n return OllamaModel(model_name, base_url=base)\n\n # 2) Fallback: Ollama exposes OpenAI-compatible API at http://localhost:11434/v1\n try:\n # Try passing base_url (older pydantic-ai OpenAIModel may support it)\n OpenAIModel = _get_openai_model()\n if OpenAIModel:\n return OpenAIModel(model_name, api_key=\"ollama\", base_url=base_v1)\n except TypeError:\n pass\n\n try:\n # Newer pydantic-ai: use OpenAIChatModel + OpenAIProvider with custom client\n from openai import AsyncOpenAI\n from pydantic_ai.models.openai import OpenAIChatModel\n from pydantic_ai.providers.openai import OpenAIProvider\n async_client = AsyncOpenAI(base_url=base_v1, api_key=\"ollama\")\n provider = OpenAIProvider(openai_client=async_client)\n return OpenAIChatModel(model_name, provider=provider)\n except (ImportError, TypeError, AttributeError):\n pass\n\n raise ImportError(\n \"Ollama support requires either: (1) pydantic-ai with Ollama model, or \"\n \"(2) pydantic-ai[openai] with openai package for Ollama's OpenAI-compatible API. \"\n \"Install: pip install 'pydantic-ai[openai]' openai\"\n )\n\n\ndef _create_bedrock_model():\n BedrockModel = _get_bedrock_model()\n if not BedrockModel:\n raise ImportError(\"Bedrock support not installed. pip install pydantic-ai[bedrock]\")\n model_id = os.getenv(\"BEDROCK_MODEL\", \"anthropic.claude-3-5-sonnet-20241022-v2:0\")\n return BedrockModel(model_id)\n\n\ndef _create_deepseek_model():\n \"\"\"DeepSeek uses an OpenAI-compatible API at https://api.deepseek.com.\"\"\"\n key = os.getenv(\"DEEPSEEK_API_KEY\")\n if not key:\n raise ValueError(\"Set DEEPSEEK_API_KEY for DeepSeek. Get one at https://platform.deepseek.com\")\n base = \"https://api.deepseek.com\"\n model_name = os.getenv(\"DEEPSEEK_MODEL\", \"deepseek-chat\")\n\n OpenAIModel = _get_openai_model()\n if OpenAIModel:\n try:\n return OpenAIModel(model_name, api_key=key, base_url=base)\n except TypeError:\n pass\n\n try:\n from openai import AsyncOpenAI\n from pydantic_ai.models.openai import OpenAIChatModel\n from pydantic_ai.providers.openai import OpenAIProvider\n async_client = AsyncOpenAI(base_url=base, api_key=key)\n provider = OpenAIProvider(openai_client=async_client)\n return OpenAIChatModel(model_name, provider=provider)\n except (ImportError, TypeError, AttributeError) as e:\n raise ImportError(\n \"DeepSeek uses the OpenAI-compatible API. Install: pip install 'pydantic-ai[openai]' openai\"\n ) from e\n\n\ndef get_llm_model():\n \"\"\"\n Return the configured LLM model for workers/trainer (structured workout generation).\n Use LLM_PROVIDER=gemini|openai|bedrock|ollama|deepseek to force a provider; otherwise auto-detect.\n \"\"\"\n provider = (os.getenv(\"LLM_PROVIDER\") or \"\").strip().lower()\n\n if provider == \"gemini\":\n return _create_gemini_model()\n if provider == \"openai\":\n return _create_openai_model()\n if provider == \"bedrock\":\n return _create_bedrock_model()\n if provider == \"ollama\":\n return _create_ollama_model()\n if provider == \"deepseek\":\n return _create_deepseek_model()\n\n # Auto-detect from API keys: Gemini > OpenAI > DeepSeek > Ollama\n if (os.getenv(\"GOOGLE_API_KEY\") or os.getenv(\"GEMINI_API_KEY\")) and _get_google_model():\n return _create_gemini_model()\n if os.getenv(\"OPENAI_API_KEY\") and _get_openai_model():\n return _create_openai_model()\n if os.getenv(\"DEEPSEEK_API_KEY\") and _get_openai_model():\n return _create_deepseek_model()\n if _get_ollama_model():\n return _create_ollama_model()\n\n raise ValueError(\n \"No LLM configured. Set LLM_PROVIDER (gemini|openai|bedrock|ollama|deepseek) and the corresponding API keys.\"\n )\n\n\ndef get_supervisor_model():\n \"\"\"\n Return the configured LLM model for the supervisor (routing and safety).\n Uses the same LLM_PROVIDER and fallbacks as get_llm_model().\n \"\"\"\n return get_llm_model()\n"}}}} |