1 line
14 KiB
JSON
1 line
14 KiB
JSON
{"repo": "amrglacier/football-prediction", "files": {"app/providers/registry.py": {"bb49357b77db5899fd0cd2d3fb84a64db4bcbe02": {"t": 1785745450.4481244, "n": 6873, "h": "bf0de75c41abf7b6", "c": "\"\"\"Provider registry: maps factor IDs to their AI providers with fallback chains.\n\nPriority strategy for free / low-cost operation:\n F1 (Claude) -> Anthropic -> DeepSeek (fallback) -> Mock\n F2 (Qwen) -> Qwen DashScope -> DeepSeek (fallback) -> Mock\n F3 (Kimi) -> Moonshot -> DeepSeek (fallback) -> Mock\n F4 (GPT-4o) -> OpenAI -> DeepSeek (fallback) -> Mock\n F5 (Gemini) -> Gemini -> DeepSeek (fallback) -> Mock\n F6 (DeepSeek-R1) -> DeepSeek -> Qwen (fallback) -> Mock\n F7 (ERNIE) -> ERNIE/Qianfan -> Qwen (fallback) -> Mock\n F8 (Llama 3.1) -> Groq -> DeepSeek (fallback) -> Mock\n\"\"\"\n\nimport logging\nfrom typing import Dict, List\n\nfrom app.providers.base import (\n AIProvider,\n MockProvider,\n OpenAICompatibleProvider,\n AnthropicProvider,\n GeminiProvider,\n ERNIEProvider,\n)\nfrom app.config import settings\n\nlogger = logging.getLogger(__name__)\n\n# Singleton mock provider for fallback\n_mock_provider = MockProvider()\n\n\ndef _build_provider_chain(factor_id: str) -> List[AIProvider]:\n \"\"\"Build a fallback chain of providers for a given factor.\"\"\"\n chain: List[AIProvider] = []\n\n s = settings\n\n if factor_id == \"F1\":\n # Claude Opus -> DeepSeek fallback\n if s.anthropic_api_key:\n chain.append(AnthropicProvider(s.anthropic_api_key, \"claude-3-5-sonnet-20241022\"))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n elif factor_id == \"F2\":\n # Qwen-Max\n if s.qwen_api_key:\n chain.append(OpenAICompatibleProvider(\"qwen\", \"qwen-max\",\n s.qwen_api_key, s.qwen_base_url))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n elif factor_id == \"F3\":\n # Kimi / Moonshot\n if s.kimi_api_key:\n chain.append(OpenAICompatibleProvider(\"kimi\", \"moonshot-v1-8k\",\n s.kimi_api_key, s.kimi_base_url))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n elif factor_id == \"F4\":\n # GPT-4o -> DeepSeek fallback\n if s.openai_api_key:\n chain.append(OpenAICompatibleProvider(\"openai\", \"gpt-4o\",\n s.openai_api_key, \"https://api.openai.com/v1\"))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n elif factor_id == \"F5\":\n # Gemini 1.5 Pro\n if s.gemini_api_key:\n chain.append(GeminiProvider(s.gemini_api_key, \"gemini-1.5-pro\"))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n elif factor_id == \"F6\":\n # DeepSeek-R1 (reasoner)\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek-reasoner\", \"deepseek-reasoner\",\n s.deepseek_api_key, s.deepseek_base_url))\n if s.qwen_api_key:\n chain.append(OpenAICompatibleProvider(\"qwen\", \"qwen-max\",\n s.qwen_api_key, s.qwen_base_url))\n\n elif factor_id == \"F7\":\n # ERNIE / 文心一言\n if s.ernie_api_key and s.ernie_secret_key:\n chain.append(ERNIEProvider(s.ernie_api_key, s.ernie_secret_key, \"ernie-bot-8k\"))\n if s.qwen_api_key:\n chain.append(OpenAICompatibleProvider(\"qwen\", \"qwen-max\",\n s.qwen_api_key, s.qwen_base_url))\n\n elif factor_id == \"F8\":\n # Llama 3.1 via Groq\n if s.groq_api_key:\n chain.append(OpenAICompatibleProvider(\"groq\", \"llama-3.1-70b-versatile\",\n s.groq_api_key, s.groq_base_url))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n # Always add mock as last resort\n chain.append(_mock_provider)\n\n return chain\n\n\n# Cache provider chains\n_provider_chains: Dict[str, List[AIProvider]] = {}\n\n\ndef get_provider_chain(factor_id: str) -> List[AIProvider]:\n \"\"\"Get the cached provider chain for a factor.\"\"\"\n if factor_id not in _provider_chains:\n _provider_chains[factor_id] = _build_provider_chain(factor_id)\n return _provider_chains[factor_id]\n\n\ndef get_primary_provider(factor_id: str) -> AIProvider:\n \"\"\"Get the primary (first available) provider for a factor.\"\"\"\n chain = get_provider_chain(factor_id)\n for provider in chain:\n if provider.is_available():\n return provider\n return _mock_provider\n\n\nasync def call_with_fallback(factor_id: str, system_prompt: str, user_prompt: str,\n temperature: float = 0.3, max_tokens: int = 2000) -> str:\n \"\"\"\n Call AI completion with automatic fallback.\n Tries each provider in the chain until one succeeds.\n \"\"\"\n chain = get_provider_chain(factor_id)\n last_error = None\n\n for provider in chain:\n if not provider.is_available():\n continue\n try:\n result = await provider.chat_completion(\n system_prompt, user_prompt, temperature, max_tokens\n )\n if result:\n return result\n except Exception as e:\n logger.warning(f\"Provider {provider.name} failed for {factor_id}: {e}\")\n last_error = e\n continue\n\n logger.error(f\"All providers failed for {factor_id}, last error: {last_error}\")\n return await _mock_provider.chat_completion(system_prompt, user_prompt, temperature, max_tokens)\n\n\ndef get_provider_status() -> Dict[str, dict]:\n \"\"\"Get the status of all factor providers for the monitoring dashboard.\"\"\"\n status = {}\n for factor_id in [\"F1\", \"F2\", \"F3\", \"F4\", \"F5\", \"F6\", \"F7\", \"F8\"]:\n chain = get_provider_chain(factor_id)\n primary = get_primary_provider(factor_id)\n status[factor_id] = {\n \"primary_provider\": primary.name,\n \"model\": primary.model,\n \"available\": primary.is_available(),\n \"chain_length\": len(chain),\n \"chain\": [p.name for p in chain],\n }\n return status\n"}, "2604f22ff8caec86fe5b0fc67b05f49f0e5c7504": {"t": 1785753385.603631, "n": 6873, "h": "bf0de75c41abf7b6", "c": "\"\"\"Provider registry: maps factor IDs to their AI providers with fallback chains.\n\nPriority strategy for free / low-cost operation:\n F1 (Claude) -> Anthropic -> DeepSeek (fallback) -> Mock\n F2 (Qwen) -> Qwen DashScope -> DeepSeek (fallback) -> Mock\n F3 (Kimi) -> Moonshot -> DeepSeek (fallback) -> Mock\n F4 (GPT-4o) -> OpenAI -> DeepSeek (fallback) -> Mock\n F5 (Gemini) -> Gemini -> DeepSeek (fallback) -> Mock\n F6 (DeepSeek-R1) -> DeepSeek -> Qwen (fallback) -> Mock\n F7 (ERNIE) -> ERNIE/Qianfan -> Qwen (fallback) -> Mock\n F8 (Llama 3.1) -> Groq -> DeepSeek (fallback) -> Mock\n\"\"\"\n\nimport logging\nfrom typing import Dict, List\n\nfrom app.providers.base import (\n AIProvider,\n MockProvider,\n OpenAICompatibleProvider,\n AnthropicProvider,\n GeminiProvider,\n ERNIEProvider,\n)\nfrom app.config import settings\n\nlogger = logging.getLogger(__name__)\n\n# Singleton mock provider for fallback\n_mock_provider = MockProvider()\n\n\ndef _build_provider_chain(factor_id: str) -> List[AIProvider]:\n \"\"\"Build a fallback chain of providers for a given factor.\"\"\"\n chain: List[AIProvider] = []\n\n s = settings\n\n if factor_id == \"F1\":\n # Claude Opus -> DeepSeek fallback\n if s.anthropic_api_key:\n chain.append(AnthropicProvider(s.anthropic_api_key, \"claude-3-5-sonnet-20241022\"))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n elif factor_id == \"F2\":\n # Qwen-Max\n if s.qwen_api_key:\n chain.append(OpenAICompatibleProvider(\"qwen\", \"qwen-max\",\n s.qwen_api_key, s.qwen_base_url))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n elif factor_id == \"F3\":\n # Kimi / Moonshot\n if s.kimi_api_key:\n chain.append(OpenAICompatibleProvider(\"kimi\", \"moonshot-v1-8k\",\n s.kimi_api_key, s.kimi_base_url))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n elif factor_id == \"F4\":\n # GPT-4o -> DeepSeek fallback\n if s.openai_api_key:\n chain.append(OpenAICompatibleProvider(\"openai\", \"gpt-4o\",\n s.openai_api_key, \"https://api.openai.com/v1\"))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n elif factor_id == \"F5\":\n # Gemini 1.5 Pro\n if s.gemini_api_key:\n chain.append(GeminiProvider(s.gemini_api_key, \"gemini-1.5-pro\"))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n elif factor_id == \"F6\":\n # DeepSeek-R1 (reasoner)\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek-reasoner\", \"deepseek-reasoner\",\n s.deepseek_api_key, s.deepseek_base_url))\n if s.qwen_api_key:\n chain.append(OpenAICompatibleProvider(\"qwen\", \"qwen-max\",\n s.qwen_api_key, s.qwen_base_url))\n\n elif factor_id == \"F7\":\n # ERNIE / 文心一言\n if s.ernie_api_key and s.ernie_secret_key:\n chain.append(ERNIEProvider(s.ernie_api_key, s.ernie_secret_key, \"ernie-bot-8k\"))\n if s.qwen_api_key:\n chain.append(OpenAICompatibleProvider(\"qwen\", \"qwen-max\",\n s.qwen_api_key, s.qwen_base_url))\n\n elif factor_id == \"F8\":\n # Llama 3.1 via Groq\n if s.groq_api_key:\n chain.append(OpenAICompatibleProvider(\"groq\", \"llama-3.1-70b-versatile\",\n s.groq_api_key, s.groq_base_url))\n if s.deepseek_api_key:\n chain.append(OpenAICompatibleProvider(\"deepseek\", \"deepseek-chat\",\n s.deepseek_api_key, s.deepseek_base_url))\n\n # Always add mock as last resort\n chain.append(_mock_provider)\n\n return chain\n\n\n# Cache provider chains\n_provider_chains: Dict[str, List[AIProvider]] = {}\n\n\ndef get_provider_chain(factor_id: str) -> List[AIProvider]:\n \"\"\"Get the cached provider chain for a factor.\"\"\"\n if factor_id not in _provider_chains:\n _provider_chains[factor_id] = _build_provider_chain(factor_id)\n return _provider_chains[factor_id]\n\n\ndef get_primary_provider(factor_id: str) -> AIProvider:\n \"\"\"Get the primary (first available) provider for a factor.\"\"\"\n chain = get_provider_chain(factor_id)\n for provider in chain:\n if provider.is_available():\n return provider\n return _mock_provider\n\n\nasync def call_with_fallback(factor_id: str, system_prompt: str, user_prompt: str,\n temperature: float = 0.3, max_tokens: int = 2000) -> str:\n \"\"\"\n Call AI completion with automatic fallback.\n Tries each provider in the chain until one succeeds.\n \"\"\"\n chain = get_provider_chain(factor_id)\n last_error = None\n\n for provider in chain:\n if not provider.is_available():\n continue\n try:\n result = await provider.chat_completion(\n system_prompt, user_prompt, temperature, max_tokens\n )\n if result:\n return result\n except Exception as e:\n logger.warning(f\"Provider {provider.name} failed for {factor_id}: {e}\")\n last_error = e\n continue\n\n logger.error(f\"All providers failed for {factor_id}, last error: {last_error}\")\n return await _mock_provider.chat_completion(system_prompt, user_prompt, temperature, max_tokens)\n\n\ndef get_provider_status() -> Dict[str, dict]:\n \"\"\"Get the status of all factor providers for the monitoring dashboard.\"\"\"\n status = {}\n for factor_id in [\"F1\", \"F2\", \"F3\", \"F4\", \"F5\", \"F6\", \"F7\", \"F8\"]:\n chain = get_provider_chain(factor_id)\n primary = get_primary_provider(factor_id)\n status[factor_id] = {\n \"primary_provider\": primary.name,\n \"model\": primary.model,\n \"available\": primary.is_available(),\n \"chain_length\": len(chain),\n \"chain\": [p.name for p in chain],\n }\n return status\n"}}}} |