Spaces:
Running
Running
| from flask import Flask, request, jsonify, send_from_directory | |
| from flask_cors import CORS | |
| import asyncio | |
| import os | |
| import sys | |
| from threading import Thread | |
| import json | |
| from dotenv import load_dotenv | |
| # Load environment variables | |
| load_dotenv() | |
| # Import browser-use components and LLM libraries | |
| try: | |
| from langchain_openai import ChatOpenAI | |
| from langchain_anthropic import ChatAnthropic | |
| from langchain_google_genai import ChatGoogleGenerativeAI | |
| from browser_use import Agent | |
| except ImportError as e: | |
| print(f"Import error: {e}") | |
| print("Make sure to install browser-use, langchain-openai, langchain-anthropic, and langchain-google-genai") | |
| app = Flask(__name__, static_folder=\'static\') | |
| CORS(app) # Enable CORS for all routes | |
| # Global variables for managing async operations | |
| loop = None | |
| thread = None | |
| def start_background_loop(loop): | |
| """Start the asyncio event loop in a background thread""" | |
| asyncio.set_event_loop(loop) | |
| loop.run_forever() | |
| def get_or_create_eventloop(): | |
| """Get or create the asyncio event loop""" | |
| global loop, thread | |
| if loop is None: | |
| loop = asyncio.new_event_loop() | |
| thread = Thread(target=start_background_loop, args=(loop,)) | |
| thread.daemon = True | |
| thread.start() | |
| return loop | |
| async def run_browser_task(task, model="gpt-4o-mini"): | |
| """Run a browser automation task using browser-use""" | |
| try: | |
| # Initialize the LLM based on the model name | |
| if model.startswith(\'gpt\'): | |
| llm = ChatOpenAI(model=model, temperature=0.1) | |
| elif model.startswith(\'claude\'): | |
| llm = ChatAnthropic(model=model, temperature=0.1) | |
| elif model.startswith(\'gemini\'): | |
| llm = ChatGoogleGenerativeAI(model=model, temperature=0.1) | |
| else: | |
| raise ValueError(f"Unsupported model: {model}") | |
| # Create the agent | |
| agent = Agent(task=task, llm=llm) | |
| # Run the task | |
| result = await agent.run() | |
| return { | |
| "success": True, | |
| "result": str(result), | |
| "task": task | |
| } | |
| except Exception as e: | |
| return { | |
| "success": False, | |
| "error": str(e), | |
| "task": task | |
| } | |
| @app.route(\'/\') | |
| def home(): | |
| """Serve the HTML interface""" | |
| return send_from_directory(\'static\', \'index.html\') | |
| @app.route(\'/api\') | |
| def api_docs(): | |
| """API documentation endpoint""" | |
| return jsonify({ | |
| "message": "Browser-Use Server API", | |
| "endpoints": { | |
| "/": "Web interface", | |
| "/api": "This API documentation", | |
| "/health": "Health check", | |
| "/run-task": "POST - Run a browser automation task", | |
| "/status": "Get server status" | |
| }, | |
| "usage": { | |
| "run_task": { | |
| "method": "POST", | |
| "url": "/run-task", | |
| "body": { | |
| "task": "Description of the task to perform", | |
| "model": "gpt-4o-mini (optional, default)" | |
| }, | |
| "example": { | |
| "task": "Go to google.com and search for \'Python programming\'", | |
| "model": "gpt-4o-mini" | |
| } | |
| } | |
| } | |
| }) | |
| @app.route(\'/health\') | |
| def health(): | |
| """Health check endpoint""" | |
| return jsonify({ | |
| "status": "healthy", | |
| "service": "browser-use-server", | |
| "version": "1.0.0" | |
| }) | |
| @app.route(\'/status\') | |
| def status(): | |
| """Get server status and configuration""" | |
| return jsonify({ | |
| "status": "running", | |
| "environment": { | |
| "python_version": sys.version, | |
| "has_openai_key": bool(os.getenv("OPENAI_API_KEY")), | |
| "has_anthropic_key": bool(os.getenv("ANTHROPIC_API_KEY")), | |
| "has_google_api_key": bool(os.getenv("GOOGLE_API_KEY")) | |
| }, | |
| "supported_models": [ | |
| "gpt-4o", | |
| "gpt-4o-mini", | |
| "gpt-4-turbo", | |
| "claude-3-sonnet-20240229", | |
| "claude-3-haiku-20240307", | |
| "gemini-pro", | |
| "gemini-1.5-pro-latest" | |
| ] | |
| }) | |
| @app.route(\'/run-task\', methods=[\'POST\']) | |
| def run_task(): | |
| """Run a browser automation task""" | |
| try: | |
| # Get request data | |
| data = request.get_json() | |
| if not data or \'task\' not in data: | |
| return jsonify({ | |
| "success": False, | |
| "error": "Missing \'task\' in request body" | |
| }), 400 | |
| task = data[\'task\'] | |
| model = data.get(\'model\', \'gpt-4o-mini\') | |
| # Validate API keys | |
| if not os.getenv("OPENAI_API_KEY") and not os.getenv("ANTHROPIC_API_KEY") and not os.getenv("GOOGLE_API_KEY"): | |
| return jsonify({ | |
| "success": False, | |
| "error": "No API keys configured. Please set OPENAI_API_KEY, ANTHROPIC_API_KEY, or GOOGLE_API_KEY environment variable." | |
| }), 500 | |
| # Get the event loop | |
| loop = get_or_create_eventloop() | |
| # Run the task asynchronously | |
| future = asyncio.run_coroutine_threadsafe( | |
| run_browser_task(task, model), | |
| loop | |
| ) | |
| # Wait for the result (with timeout) | |
| try: | |
| result = future.result(timeout=300) # 5 minute timeout | |
| return jsonify(result) | |
| except asyncio.TimeoutError: | |
| return jsonify({ | |
| "success": False, | |
| "error": "Task timed out after 5 minutes" | |
| }), 408 | |
| except Exception as e: | |
| return jsonify({ | |
| "success": False, | |
| "error": f"Server error: {str(e)}" | |
| }), 500 | |
| if __name__ == \'__main__\': | |
| print("Starting Browser-Use Server...") | |
| print("Make sure you have set your API keys:") | |
| print("- OPENAI_API_KEY for OpenAI models") | |
| print("- ANTHROPIC_API_KEY for Anthropic models") | |
| print("- GOOGLE_API_KEY for Google Gemini models") | |
| # Run the Flask app | |
| app.run(host=\'0.0.0.0\', port=7860, debug=False) | |