{"repo": "ajithkumar31082004-bit/vibe-trading", "files": {"Vibe-Trading-main/agent/tests/test_llm.py": {"1c0da4e50b242f3c7584ed672a65955812c0ae5e": {"t": 1785746638.9476101, "n": 8224, "h": "691ef217b93d769c", "c": "\"\"\"Tests for LLM provider mapping and JSON extraction.\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nfrom unittest.mock import patch\n\nimport pytest\n\nfrom src.providers.llm import _extract_balanced_json, _sync_provider_env, build_llm\n\n\n# ---------------------------------------------------------------------------\n# _sync_provider_env\n# ---------------------------------------------------------------------------\n\n\nclass TestSyncProviderEnv:\n \"\"\"Provider-specific env vars → OPENAI_* mapping.\"\"\"\n\n def _run_sync(self, env: dict[str, str]) -> dict[str, str]:\n \"\"\"Run _sync_provider_env with a clean env and return relevant keys.\"\"\"\n # Reset the dotenv guard so it doesn't skip\n import src.providers.llm as llm_mod\n llm_mod._dotenv_loaded = True # pretend already loaded\n\n clean = {k: v for k, v in os.environ.items() if not k.startswith((\"OPENAI_\", \"LANGCHAIN_\", \"DEEPSEEK_\", \"GROQ_\", \"OLLAMA_\", \"DASHSCOPE_\", \"ZAI_\"))}\n clean.update(env)\n with patch.dict(os.environ, clean, clear=True):\n _sync_provider_env()\n return {\n \"OPENAI_API_KEY\": os.environ.get(\"OPENAI_API_KEY\", \"\"),\n \"OPENAI_API_BASE\": os.environ.get(\"OPENAI_API_BASE\", \"\"),\n \"OPENAI_BASE_URL\": os.environ.get(\"OPENAI_BASE_URL\", \"\"),\n }\n\n def test_openai_default(self) -> None:\n result = self._run_sync({\n \"OPENAI_API_KEY\": \"sk-test\",\n })\n assert result[\"OPENAI_API_KEY\"] == \"sk-test\"\n\n def test_deepseek_provider(self) -> None:\n result = self._run_sync({\n \"LANGCHAIN_PROVIDER\": \"deepseek\",\n \"DEEPSEEK_API_KEY\": \"ds-key-123\",\n \"DEEPSEEK_BASE_URL\": \"https://api.deepseek.com/v1\",\n })\n assert result[\"OPENAI_API_KEY\"] == \"ds-key-123\"\n assert result[\"OPENAI_API_BASE\"] == \"https://api.deepseek.com/v1\"\n\n def test_groq_provider(self) -> None:\n result = self._run_sync({\n \"LANGCHAIN_PROVIDER\": \"groq\",\n \"GROQ_API_KEY\": \"gsk-test\",\n \"GROQ_BASE_URL\": \"https://api.groq.com/openai/v1\",\n })\n assert result[\"OPENAI_API_KEY\"] == \"gsk-test\"\n assert \"groq\" in result[\"OPENAI_API_BASE\"]\n\n def test_ollama_no_key_required(self) -> None:\n result = self._run_sync({\n \"LANGCHAIN_PROVIDER\": \"ollama\",\n \"OLLAMA_BASE_URL\": \"http://localhost:11434/v1\",\n })\n # Ollama uses \"ollama\" as fallback key\n assert result[\"OPENAI_API_KEY\"] in (\"ollama\", \"\")\n assert \"localhost\" in result[\"OPENAI_API_BASE\"]\n\n def test_qwen_alias_to_dashscope(self) -> None:\n result = self._run_sync({\n \"LANGCHAIN_PROVIDER\": \"qwen\",\n \"DASHSCOPE_API_KEY\": \"qwen-key\",\n \"DASHSCOPE_BASE_URL\": \"https://dashscope.aliyuncs.com/v1\",\n })\n assert result[\"OPENAI_API_KEY\"] == \"qwen-key\"\n\n def test_zai_provider(self) -> None:\n result = self._run_sync({\n \"LANGCHAIN_PROVIDER\": \"zai\",\n \"ZAI_API_KEY\": \"zai-key-test\",\n \"ZAI_BASE_URL\": \"https://api.z.ai/api/coding/paas/v4\",\n })\n assert result[\"OPENAI_API_KEY\"] == \"zai-key-test\"\n assert result[\"OPENAI_API_BASE\"] == \"https://api.z.ai/api/coding/paas/v4\"\n\n def test_unknown_provider_falls_back_to_openai(self) -> None:\n result = self._run_sync({\n \"LANGCHAIN_PROVIDER\": \"unknown_provider_xyz\",\n \"OPENAI_API_KEY\": \"sk-fallback\",\n })\n assert result[\"OPENAI_API_KEY\"] == \"sk-fallback\"\n\n def test_provider_key_fallback_to_openai_key(self) -> None:\n \"\"\"If provider-specific key is missing, fall back to OPENAI_API_KEY.\"\"\"\n result = self._run_sync({\n \"LANGCHAIN_PROVIDER\": \"deepseek\",\n \"OPENAI_API_KEY\": \"sk-shared\",\n })\n assert result[\"OPENAI_API_KEY\"] == \"sk-shared\"\n\n def test_minimax_provider(self) -> None:\n result = self._run_sync({\n \"LANGCHAIN_PROVIDER\": \"minimax\",\n \"MINIMAX_API_KEY\": \"minimax-key-123\",\n \"MINIMAX_BASE_URL\": \"https://api.minimax.io/v1\",\n })\n assert result[\"OPENAI_API_KEY\"] == \"minimax-key-123\"\n assert result[\"OPENAI_API_BASE\"] == \"https://api.minimax.io/v1\"\n\n def test_minimax_base_url_in_openai_base_url(self) -> None:\n result = self._run_sync({\n \"LANGCHAIN_PROVIDER\": \"minimax\",\n \"MINIMAX_API_KEY\": \"minimax-key\",\n \"MINIMAX_BASE_URL\": \"https://api.minimax.io/v1\",\n })\n assert \"minimax.io\" in result[\"OPENAI_BASE_URL\"]\n\n\n# ---------------------------------------------------------------------------\n# MiniMax temperature clamping\n# ---------------------------------------------------------------------------\n\n\nclass TestMinimaxTemperature:\n \"\"\"MiniMax requires temperature > 0; build_llm should clamp the default.\"\"\"\n\n def test_minimax_temperature_clamped_from_zero(self) -> None:\n \"\"\"When LANGCHAIN_TEMPERATURE=0.0 and provider=minimax, temperature must be clamped to 0.01.\"\"\"\n import src.providers.llm as llm_mod\n llm_mod._dotenv_loaded = True\n\n captured: dict[str, float] = {}\n\n class _FakeChatOpenAI:\n def __init__(self, **kwargs: object) -> None:\n captured[\"temperature\"] = float(kwargs.get(\"temperature\", -1))\n\n env = {\n \"LANGCHAIN_PROVIDER\": \"minimax\",\n \"MINIMAX_API_KEY\": \"minimax-key\",\n \"MINIMAX_BASE_URL\": \"https://api.minimax.io/v1\",\n \"LANGCHAIN_MODEL_NAME\": \"MiniMax-M2.7\",\n \"LANGCHAIN_TEMPERATURE\": \"0.0\",\n }\n with patch.dict(os.environ, env, clear=True):\n with patch.object(llm_mod, \"ChatOpenAI\", _FakeChatOpenAI):\n build_llm()\n assert captured[\"temperature\"] == 0.01, (\n \"MiniMax temperature must be clamped to 0.01 when 0.0 is configured\"\n )\n\n def test_minimax_positive_temperature_preserved(self) -> None:\n \"\"\"When an explicit positive temperature is set, it should be preserved.\"\"\"\n import src.providers.llm as llm_mod\n llm_mod._dotenv_loaded = True\n\n captured: dict[str, float] = {}\n\n class _FakeChatOpenAI:\n def __init__(self, **kwargs: object) -> None:\n captured[\"temperature\"] = float(kwargs.get(\"temperature\", -1))\n\n env = {\n \"LANGCHAIN_PROVIDER\": \"minimax\",\n \"MINIMAX_API_KEY\": \"minimax-key\",\n \"MINIMAX_BASE_URL\": \"https://api.minimax.io/v1\",\n \"LANGCHAIN_MODEL_NAME\": \"MiniMax-M2.7\",\n \"LANGCHAIN_TEMPERATURE\": \"0.7\",\n }\n with patch.dict(os.environ, env, clear=True):\n with patch.object(llm_mod, \"ChatOpenAI\", _FakeChatOpenAI):\n build_llm()\n assert captured[\"temperature\"] == 0.7\n\n\nclass TestExtractBalancedJson:\n def test_simple_json(self) -> None:\n result = _extract_balanced_json('{\"key\": \"value\"}')\n assert result == {\"key\": \"value\"}\n\n def test_json_embedded_in_text(self) -> None:\n text = 'Here is the config: {\"a\": 1, \"b\": 2} and some more text.'\n result = _extract_balanced_json(text)\n assert result == {\"a\": 1, \"b\": 2}\n\n def test_nested_json(self) -> None:\n text = '{\"outer\": {\"inner\": [1, 2, 3]}}'\n result = _extract_balanced_json(text)\n assert result[\"outer\"][\"inner\"] == [1, 2, 3]\n\n def test_escaped_quotes(self) -> None:\n text = r'{\"msg\": \"he said \\\"hello\\\"\"}'\n result = _extract_balanced_json(text)\n assert result is not None\n assert \"hello\" in result[\"msg\"]\n\n def test_no_json(self) -> None:\n assert _extract_balanced_json(\"no json here\") is None\n\n def test_empty_string(self) -> None:\n assert _extract_balanced_json(\"\") is None\n\n def test_braces_in_strings(self) -> None:\n text = '{\"pattern\": \"if (x > 0) { return x; }\"}'\n result = _extract_balanced_json(text)\n assert result is not None\n assert \"return x\" in result[\"pattern\"]\n\n def test_multiple_objects_returns_first(self) -> None:\n text = '{\"a\": 1} {\"b\": 2}'\n result = _extract_balanced_json(text)\n assert result == {\"a\": 1}\n"}}}}