Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/binison_academic-research-agent.json

1 line
16 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "binison/academic-research-agent", "files": {"llm_config.py": {"23548fdf7e28d2beedfa3a8e3a826e6388e39557": {"t": 1785746880.9571998, "n": 7314, "h": "9304787fb6aa7834", "c": "\"\"\"\n通用 LLM 配置模块\n支持 OpenAI 格式和 Anthropic 格式的所有第三方模型\n\"\"\"\n\nimport os\nfrom typing import Optional, Dict, Any\nfrom dataclasses import dataclass\n\n\n@dataclass\nclass ModelConfig:\n \"\"\"模型配置\"\"\"\n name: str\n format: str # \"openai\" 或 \"anthropic\"\n api_key: str\n base_url: Optional[str] = None\n model: str = \"\"\n temperature: float = 0.3\n extra_headers: Optional[Dict[str, str]] = None\n\n\ndef get_model_config() -> ModelConfig:\n \"\"\"\n 从环境变量读取模型配置\n\n 支持的配置方式:\n\n 1. OpenAI 官方:\n OPENAI_API_KEY=sk-xxx\n OPENAI_MODEL=gpt-4o\n\n 2. OpenAI 兼容 (Ollama/Groq/OpenRouter/DeepSeek 等):\n LLM_FORMAT=openai\n LLM_API_KEY=xxx\n LLM_BASE_URL=https://api.deepseek.com/v1\n LLM_MODEL=deepseek-chat\n\n 3. Anthropic 官方:\n ANTHROPIC_API_KEY=sk-ant-xxx\n ANTHROPIC_MODEL=claude-3-5-sonnet-20241022\n\n 4. Anthropic 兼容 (代理服务):\n LLM_FORMAT=anthropic\n LLM_API_KEY=xxx\n LLM_BASE_URL=https://your-proxy.com\n LLM_MODEL=claude-3-5-sonnet\n \"\"\"\n\n # 首先检查通用配置\n llm_format = os.getenv(\"LLM_FORMAT\", \"\").lower()\n llm_api_key = os.getenv(\"LLM_API_KEY\", \"\")\n llm_base_url = os.getenv(\"LLM_BASE_URL\", \"\")\n llm_model = os.getenv(\"LLM_MODEL\", \"\")\n llm_temperature = float(os.getenv(\"LLM_TEMPERATURE\", \"0.3\"))\n\n # 构建额外请求头(某些服务需要)\n extra_headers = {}\n if os.getenv(\"LLM_HTTP_REFERER\"):\n extra_headers[\"HTTP-Referer\"] = os.getenv(\"LLM_HTTP_REFERER\")\n if os.getenv(\"LLM_X_TITLE\"):\n extra_headers[\"X-Title\"] = os.getenv(\"LLM_X_TITLE\")\n\n # 标准化 base_url\n if llm_base_url:\n llm_base_url = llm_base_url.rstrip('/')\n # 移除可能的 /v1/chat/completions 后缀\n for suffix in ['/v1/chat/completions', '/chat/completions', '/v1/messages']:\n if llm_base_url.endswith(suffix):\n llm_base_url = llm_base_url[:-len(suffix)]\n break\n\n # 方式1: 通用配置 (LLM_ 前缀)\n if llm_api_key and llm_format:\n # 设置默认模型名称\n if not llm_model:\n if llm_format == \"openai\":\n llm_model = \"gpt-4o\"\n else:\n llm_model = \"claude-3-5-sonnet-20241022\"\n\n return ModelConfig(\n name=llm_model,\n format=llm_format,\n api_key=llm_api_key,\n base_url=llm_base_url or None,\n model=llm_model,\n temperature=llm_temperature,\n extra_headers=extra_headers if extra_headers else None\n )\n\n # 方式2: OpenAI 官方\n openai_key = os.getenv(\"OPENAI_API_KEY\")\n if openai_key:\n openai_base = os.getenv(\"OPENAI_BASE_URL\", \"\")\n if openai_base:\n openai_base = openai_base.rstrip('/')\n for suffix in ['/v1/chat/completions', '/chat/completions']:\n if openai_base.endswith(suffix):\n openai_base = openai_base[:-len(suffix)]\n break\n\n return ModelConfig(\n name=os.getenv(\"OPENAI_MODEL\", \"gpt-4o\"),\n format=\"openai\",\n api_key=openai_key,\n base_url=openai_base or None,\n model=os.getenv(\"OPENAI_MODEL\", \"gpt-4o\"),\n temperature=llm_temperature,\n extra_headers=extra_headers if extra_headers else None\n )\n\n # 方式3: Anthropic 官方\n anthropic_key = os.getenv(\"ANTHROPIC_API_KEY\")\n if anthropic_key:\n anthropic_base = os.getenv(\"ANTHROPIC_BASE_URL\", \"\")\n if anthropic_base:\n anthropic_base = anthropic_base.rstrip('/')\n for suffix in ['/v1/messages', '/messages']:\n if anthropic_base.endswith(suffix):\n anthropic_base = anthropic_base[:-len(suffix)]\n break\n\n return ModelConfig(\n name=os.getenv(\"ANTHROPIC_MODEL\", \"claude-3-5-sonnet-20241022\"),\n format=\"anthropic\",\n api_key=anthropic_key,\n base_url=anthropic_base or None,\n model=os.getenv(\"ANTHROPIC_MODEL\", \"claude-3-5-sonnet-20241022\"),\n temperature=llm_temperature,\n extra_headers=extra_headers if extra_headers else None\n )\n\n raise ValueError(\n \"请配置以下环境变量之一:\\n\"\n \" 1. LLM_FORMAT + LLM_API_KEY + LLM_BASE_URL (通用配置)\\n\"\n \" 2. OPENAI_API_KEY (OpenAI 官方)\\n\"\n \" 3. ANTHROPIC_API_KEY (Anthropic 官方)\\n\"\n \"\\n示例 .env 文件:\\n\"\n \" LLM_FORMAT=openai\\n\"\n \" LLM_API_KEY=your-key\\n\"\n \" LLM_BASE_URL=https://api.deepseek.com/v1\\n\"\n \" LLM_MODEL=deepseek-chat\"\n )\n\n\ndef create_llm_client(config: Optional[ModelConfig] = None):\n \"\"\"\n 创建 LLM 客户端\n 支持 OpenAI 格式和 Anthropic 格式\n \"\"\"\n if config is None:\n config = get_model_config()\n\n if config.format == \"openai\":\n from langchain_openai import ChatOpenAI\n\n kwargs = {\n \"model\": config.model,\n \"temperature\": config.temperature,\n \"api_key\": config.api_key,\n }\n if config.base_url:\n kwargs[\"base_url\"] = config.base_url\n if config.extra_headers:\n kwargs[\"default_headers\"] = config.extra_headers\n\n return ChatOpenAI(**kwargs)\n\n elif config.format == \"anthropic\":\n from langchain_anthropic import ChatAnthropic\n\n kwargs = {\n \"model\": config.model,\n \"temperature\": config.temperature,\n \"api_key\": config.api_key,\n }\n if config.base_url:\n kwargs[\"base_url\"] = config.base_url\n if config.extra_headers:\n kwargs[\"default_headers\"] = config.extra_headers\n\n return ChatAnthropic(**kwargs)\n\n else:\n raise ValueError(f\"不支持的格式: {config.format}\")\n\n\n# 预定义的常见第三方配置(方便复制到 .env)\nPRESET_CONFIGS = {\n \"ollama\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"http://localhost:11434/v1\",\n \"LLM_API_KEY\": \"ollama\", # Ollama 需要任意字符串\n \"LLM_MODEL\": \"llama3.2\",\n },\n \"groq\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"https://api.groq.com/openai/v1\",\n \"LLM_API_KEY\": \"your-groq-key\",\n \"LLM_MODEL\": \"llama-3.2-90b-vision-preview\",\n },\n \"openrouter\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"https://openrouter.ai/api/v1\",\n \"LLM_API_KEY\": \"your-openrouter-key\",\n \"LLM_MODEL\": \"anthropic/claude-3.5-sonnet\",\n },\n \"deepseek\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"https://api.deepseek.com/v1\",\n \"LLM_API_KEY\": \"your-deepseek-key\",\n \"LLM_MODEL\": \"deepseek-chat\",\n },\n \"siliconflow\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"https://api.siliconflow.cn/v1\",\n \"LLM_API_KEY\": \"your-siliconflow-key\",\n \"LLM_MODEL\": \"deepseek-ai/DeepSeek-V2.5\",\n },\n \"dashscope\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n \"LLM_API_KEY\": \"your-dashscope-key\",\n \"LLM_MODEL\": \"qwen-max\",\n },\n}\n\n\ndef print_preset_configs():\n \"\"\"打印预设配置示例\"\"\"\n print(\"=\" * 60)\n print(\"常用第三方模型配置示例\")\n print(\"=\" * 60)\n\n for name, config in PRESET_CONFIGS.items():\n print(f\"\\n【{name.upper()}】\")\n for key, value in config.items():\n print(f\"{key}={value}\")\n\n print(\"\\n\" + \"=\" * 60)\n print(\"使用方式:将上述配置复制到 .env 文件中\")\n print(\"=\" * 60)\n\n\nif __name__ == \"__main__\":\n print_preset_configs()\n"}, "6b9556420976905dd33f24b381a4340e981c7e43": {"t": 1785768409.5387626, "n": 7314, "h": "9304787fb6aa7834", "c": "\"\"\"\n通用 LLM 配置模块\n支持 OpenAI 格式和 Anthropic 格式的所有第三方模型\n\"\"\"\n\nimport os\nfrom typing import Optional, Dict, Any\nfrom dataclasses import dataclass\n\n\n@dataclass\nclass ModelConfig:\n \"\"\"模型配置\"\"\"\n name: str\n format: str # \"openai\" 或 \"anthropic\"\n api_key: str\n base_url: Optional[str] = None\n model: str = \"\"\n temperature: float = 0.3\n extra_headers: Optional[Dict[str, str]] = None\n\n\ndef get_model_config() -> ModelConfig:\n \"\"\"\n 从环境变量读取模型配置\n\n 支持的配置方式:\n\n 1. OpenAI 官方:\n OPENAI_API_KEY=sk-xxx\n OPENAI_MODEL=gpt-4o\n\n 2. OpenAI 兼容 (Ollama/Groq/OpenRouter/DeepSeek 等):\n LLM_FORMAT=openai\n LLM_API_KEY=xxx\n LLM_BASE_URL=https://api.deepseek.com/v1\n LLM_MODEL=deepseek-chat\n\n 3. Anthropic 官方:\n ANTHROPIC_API_KEY=sk-ant-xxx\n ANTHROPIC_MODEL=claude-3-5-sonnet-20241022\n\n 4. Anthropic 兼容 (代理服务):\n LLM_FORMAT=anthropic\n LLM_API_KEY=xxx\n LLM_BASE_URL=https://your-proxy.com\n LLM_MODEL=claude-3-5-sonnet\n \"\"\"\n\n # 首先检查通用配置\n llm_format = os.getenv(\"LLM_FORMAT\", \"\").lower()\n llm_api_key = os.getenv(\"LLM_API_KEY\", \"\")\n llm_base_url = os.getenv(\"LLM_BASE_URL\", \"\")\n llm_model = os.getenv(\"LLM_MODEL\", \"\")\n llm_temperature = float(os.getenv(\"LLM_TEMPERATURE\", \"0.3\"))\n\n # 构建额外请求头(某些服务需要)\n extra_headers = {}\n if os.getenv(\"LLM_HTTP_REFERER\"):\n extra_headers[\"HTTP-Referer\"] = os.getenv(\"LLM_HTTP_REFERER\")\n if os.getenv(\"LLM_X_TITLE\"):\n extra_headers[\"X-Title\"] = os.getenv(\"LLM_X_TITLE\")\n\n # 标准化 base_url\n if llm_base_url:\n llm_base_url = llm_base_url.rstrip('/')\n # 移除可能的 /v1/chat/completions 后缀\n for suffix in ['/v1/chat/completions', '/chat/completions', '/v1/messages']:\n if llm_base_url.endswith(suffix):\n llm_base_url = llm_base_url[:-len(suffix)]\n break\n\n # 方式1: 通用配置 (LLM_ 前缀)\n if llm_api_key and llm_format:\n # 设置默认模型名称\n if not llm_model:\n if llm_format == \"openai\":\n llm_model = \"gpt-4o\"\n else:\n llm_model = \"claude-3-5-sonnet-20241022\"\n\n return ModelConfig(\n name=llm_model,\n format=llm_format,\n api_key=llm_api_key,\n base_url=llm_base_url or None,\n model=llm_model,\n temperature=llm_temperature,\n extra_headers=extra_headers if extra_headers else None\n )\n\n # 方式2: OpenAI 官方\n openai_key = os.getenv(\"OPENAI_API_KEY\")\n if openai_key:\n openai_base = os.getenv(\"OPENAI_BASE_URL\", \"\")\n if openai_base:\n openai_base = openai_base.rstrip('/')\n for suffix in ['/v1/chat/completions', '/chat/completions']:\n if openai_base.endswith(suffix):\n openai_base = openai_base[:-len(suffix)]\n break\n\n return ModelConfig(\n name=os.getenv(\"OPENAI_MODEL\", \"gpt-4o\"),\n format=\"openai\",\n api_key=openai_key,\n base_url=openai_base or None,\n model=os.getenv(\"OPENAI_MODEL\", \"gpt-4o\"),\n temperature=llm_temperature,\n extra_headers=extra_headers if extra_headers else None\n )\n\n # 方式3: Anthropic 官方\n anthropic_key = os.getenv(\"ANTHROPIC_API_KEY\")\n if anthropic_key:\n anthropic_base = os.getenv(\"ANTHROPIC_BASE_URL\", \"\")\n if anthropic_base:\n anthropic_base = anthropic_base.rstrip('/')\n for suffix in ['/v1/messages', '/messages']:\n if anthropic_base.endswith(suffix):\n anthropic_base = anthropic_base[:-len(suffix)]\n break\n\n return ModelConfig(\n name=os.getenv(\"ANTHROPIC_MODEL\", \"claude-3-5-sonnet-20241022\"),\n format=\"anthropic\",\n api_key=anthropic_key,\n base_url=anthropic_base or None,\n model=os.getenv(\"ANTHROPIC_MODEL\", \"claude-3-5-sonnet-20241022\"),\n temperature=llm_temperature,\n extra_headers=extra_headers if extra_headers else None\n )\n\n raise ValueError(\n \"请配置以下环境变量之一:\\n\"\n \" 1. LLM_FORMAT + LLM_API_KEY + LLM_BASE_URL (通用配置)\\n\"\n \" 2. OPENAI_API_KEY (OpenAI 官方)\\n\"\n \" 3. ANTHROPIC_API_KEY (Anthropic 官方)\\n\"\n \"\\n示例 .env 文件:\\n\"\n \" LLM_FORMAT=openai\\n\"\n \" LLM_API_KEY=your-key\\n\"\n \" LLM_BASE_URL=https://api.deepseek.com/v1\\n\"\n \" LLM_MODEL=deepseek-chat\"\n )\n\n\ndef create_llm_client(config: Optional[ModelConfig] = None):\n \"\"\"\n 创建 LLM 客户端\n 支持 OpenAI 格式和 Anthropic 格式\n \"\"\"\n if config is None:\n config = get_model_config()\n\n if config.format == \"openai\":\n from langchain_openai import ChatOpenAI\n\n kwargs = {\n \"model\": config.model,\n \"temperature\": config.temperature,\n \"api_key\": config.api_key,\n }\n if config.base_url:\n kwargs[\"base_url\"] = config.base_url\n if config.extra_headers:\n kwargs[\"default_headers\"] = config.extra_headers\n\n return ChatOpenAI(**kwargs)\n\n elif config.format == \"anthropic\":\n from langchain_anthropic import ChatAnthropic\n\n kwargs = {\n \"model\": config.model,\n \"temperature\": config.temperature,\n \"api_key\": config.api_key,\n }\n if config.base_url:\n kwargs[\"base_url\"] = config.base_url\n if config.extra_headers:\n kwargs[\"default_headers\"] = config.extra_headers\n\n return ChatAnthropic(**kwargs)\n\n else:\n raise ValueError(f\"不支持的格式: {config.format}\")\n\n\n# 预定义的常见第三方配置(方便复制到 .env)\nPRESET_CONFIGS = {\n \"ollama\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"http://localhost:11434/v1\",\n \"LLM_API_KEY\": \"ollama\", # Ollama 需要任意字符串\n \"LLM_MODEL\": \"llama3.2\",\n },\n \"groq\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"https://api.groq.com/openai/v1\",\n \"LLM_API_KEY\": \"your-groq-key\",\n \"LLM_MODEL\": \"llama-3.2-90b-vision-preview\",\n },\n \"openrouter\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"https://openrouter.ai/api/v1\",\n \"LLM_API_KEY\": \"your-openrouter-key\",\n \"LLM_MODEL\": \"anthropic/claude-3.5-sonnet\",\n },\n \"deepseek\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"https://api.deepseek.com/v1\",\n \"LLM_API_KEY\": \"your-deepseek-key\",\n \"LLM_MODEL\": \"deepseek-chat\",\n },\n \"siliconflow\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"https://api.siliconflow.cn/v1\",\n \"LLM_API_KEY\": \"your-siliconflow-key\",\n \"LLM_MODEL\": \"deepseek-ai/DeepSeek-V2.5\",\n },\n \"dashscope\": {\n \"LLM_FORMAT\": \"openai\",\n \"LLM_BASE_URL\": \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n \"LLM_API_KEY\": \"your-dashscope-key\",\n \"LLM_MODEL\": \"qwen-max\",\n },\n}\n\n\ndef print_preset_configs():\n \"\"\"打印预设配置示例\"\"\"\n print(\"=\" * 60)\n print(\"常用第三方模型配置示例\")\n print(\"=\" * 60)\n\n for name, config in PRESET_CONFIGS.items():\n print(f\"\\n【{name.upper()}】\")\n for key, value in config.items():\n print(f\"{key}={value}\")\n\n print(\"\\n\" + \"=\" * 60)\n print(\"使用方式:将上述配置复制到 .env 文件中\")\n print(\"=\" * 60)\n\n\nif __name__ == \"__main__\":\n print_preset_configs()\n"}}}}