From 2a6db11bf9034636819b750d483797a165b6e87b Mon Sep 17 00:00:00 2001 From: study8677 <867762462f@gmail.com> Date: Tue, 19 Aug 2025 11:01:29 +0800 Subject: [PATCH] feat: add support for multiple LLM providers (Gemini, Claude, DeepSeek) - add GEMINI_API_KEY / ANTHROPIC_API_KEY / DEEPSEEK_API_KEY env vars - update config.py and .env.example - add llm/factory.py for provider abstraction - update README with usage instructions --- .env.example | 16 +++++++++++++++- README.md | 17 +++++++++++------ autosurfer/config.py | 14 +++++++++++++- autosurfer/llm/client.py | 40 +++++++++++++++++++++++++++++++++------- 4 files changed, 72 insertions(+), 15 deletions(-) diff --git a/.env.example b/.env.example index 6a903a6..2d1c63a 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,17 @@ OPENAI_API_KEY=... BROWSERBASE_API_KEY=... -BROWSERBASE_PROJECT_ID=... \ No newline at end of file +BROWSERBASE_PROJECT_ID=... +# 设置 LLM 提供商,可选值:openai、gemini、claude、deepseek +LLM_PROVIDER=openai + +# OpenAI 配置 +OPENAI_API_KEY=your_openai_api_key + +# Gemini 配置 +GEMINI_API_KEY=your_gemini_api_key + +# Claude 配置 +CLAUDE_API_KEY=your_claude_api_key + +# DeepSeek 配置 +DEEPSEEK_API_KEY=your_deepseek_api_key \ No newline at end of file diff --git a/README.md b/README.md index c770467..80f0140 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ It's not just a bot. It's a digital entity. - **Python 3.11+** — Core runtime - **Playwright** — Local browser automation - **BrowserBase** — Cloud browser automation with session replay -- **OpenAI** — For reasoning and task planning +- **Multiple LLM Providers** — OpenAI, Gemini, Claude, DeepSeek for reasoning and task planning - **JavaScript** — For DOM annotation and interaction overlay --- @@ -87,13 +87,18 @@ By contributing, you're helping build a new generation of agents that live, work Whether you're a researcher, hacker, designer, or writer — **we welcome your magic.** ---- +# OpenAI +OPENAI_API_KEY=your_openai_api_key -## 🛠️ Contributing +# Gemini +GEMINI_API_KEY=your_gemini_api_key -Coming soon! For now, feel free to fork the repo, star it, and suggest features or bugfixes via Issues. +# Claude +CLAUDE_API_KEY=your_claude_api_key ---- +# DeepSeek +DEEPSEEK_API_KEY=your_deepseek_api_key +``` ## 📣 Spread the Word @@ -197,7 +202,7 @@ python -m examples.test_launch_browsers --- -## 🏗️ Architecture +## 许可证 AutoSurfer uses a clean dependency injection pattern: diff --git a/autosurfer/config.py b/autosurfer/config.py index 4c1fc8e..c4c06d4 100644 --- a/autosurfer/config.py +++ b/autosurfer/config.py @@ -15,7 +15,19 @@ class Config: OS = "unknown" OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") - + + # Gemini configuration + GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") + + # Claude configuration + CLAUDE_API_KEY = os.getenv("CLAUDE_API_KEY") + + # LLM Provider configuration + LLM_PROVIDER = os.getenv("LLM_PROVIDER", "openai") # Default to openai + + # DeepSeek configuration + DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY") + # BrowserBase configuration BROWSERBASE_API_KEY = os.getenv("BROWSERBASE_API_KEY") BROWSERBASE_PROJECT_ID = os.getenv("BROWSERBASE_PROJECT_ID") diff --git a/autosurfer/llm/client.py b/autosurfer/llm/client.py index 5ec2348..ca86cec 100644 --- a/autosurfer/llm/client.py +++ b/autosurfer/llm/client.py @@ -2,17 +2,43 @@ from autosurfer.config import Config from autosurfer.llm.response_schema.browser_actions import NextActions from langchain_core.utils import get_from_env +from langchain_google_genai import ChatGoogleGenerativeAI +from langchain_anthropic import ChatAnthropic -def get_llm_client(client): - if client == "openai": +def get_llm_client(): + llm_provider = Config.LLM_PROVIDER.lower() + + if llm_provider == "openai": if not Config.OPENAI_API_KEY: - raise ValueError("OPENAI_API_KEY environment variable is required") - - openai_model = ChatOpenAI( + raise ValueError("OPENAI_API_KEY environment variable is required for OpenAI") + llm = ChatOpenAI( model="gpt-4o", temperature=0, ) - return openai_model.with_structured_output(NextActions) + elif llm_provider == "gemini": + if not Config.GEMINI_API_KEY: + raise ValueError("GEMINI_API_KEY environment variable is required for Gemini") + llm = ChatGoogleGenerativeAI( + model="gemini-pro", + temperature=0, + ) + elif llm_provider == "claude": + if not Config.CLAUDE_API_KEY: + raise ValueError("CLAUDE_API_KEY environment variable is required for Claude") + llm = ChatAnthropic( + model="claude-3-opus-20240229", # Or another suitable Claude model + temperature=0, + ) + elif llm_provider == "deepseek": + if not Config.DEEPSEEK_API_KEY: + raise ValueError("DEEPSEEK_API_KEY environment variable is required for DeepSeek") + llm = ChatOpenAI( + model="deepseek-chat", + temperature=0, + openai_api_base="https://api.deepseek.com" + ) else: - raise ValueError(f"Unsupported LLM client: {client}") + raise ValueError(f"Unsupported LLM client: {llm_provider}") + + return llm.with_structured_output(NextActions)