Trisha Tomy commited on
Commit
0d53358
·
1 Parent(s): f19a4ca

Fix asyncio event loop management in app.py for Gunicorn workers

Browse files
Files changed (1) hide show
  1. app.py +22 -24
app.py CHANGED
@@ -5,21 +5,17 @@ from proxy_lite import Runner, RunnerConfig
5
  import os
6
  import logging
7
 
8
- # Configure logging for better visibility in Space logs
9
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
10
  logger = logging.getLogger(__name__)
11
 
12
  app = Flask(__name__)
13
 
14
- # Global runner instance. It will be initialized once.
15
  _runner = None
16
 
17
  async def initialize_runner():
18
- """Initializes the Proxy-lite Runner asynchronously."""
19
  global _runner
20
  if _runner is None:
21
  logger.info("Initializing Proxy-lite Runner...")
22
- # Retrieve Hugging Face API Token from environment variables (set as Space Secret)
23
  hf_api_token = os.environ.get("HF_API_TOKEN")
24
  if not hf_api_token:
25
  logger.error("HF_API_TOKEN environment variable not set. Cannot initialize Runner.")
@@ -29,7 +25,7 @@ async def initialize_runner():
29
  "environment": {
30
  "name": "webbrowser",
31
  "homepage": "https://www.google.com",
32
- "headless": True, # Runs browser without a visible UI
33
  },
34
  "solver": {
35
  "name": "simple",
@@ -38,9 +34,8 @@ async def initialize_runner():
38
  "client": {
39
  "name": "convergence",
40
  "model_id": "convergence-ai/proxy-lite-3b",
41
- # THIS IS THE HUGGING FACE INFERENCE API ENDPOINT
42
  "api_base": "https://api-inference.huggingface.co/models/convergence-ai/proxy-lite-3b",
43
- "api_key": hf_api_token # Use the token from environment variable
44
  }
45
  }
46
  }
@@ -49,15 +44,27 @@ async def initialize_runner():
49
  logger.info("Proxy-lite Runner initialized successfully.")
50
  return _runner
51
 
52
- # Helper function to run asynchronous code within a synchronous Flask route
53
  def run_async_task(coro):
54
- """Helper to run async coroutines in a synchronous context (like Flask routes)."""
55
- loop = asyncio.get_event_loop()
 
 
 
 
 
 
 
 
 
 
 
56
  return loop.run_until_complete(coro)
 
 
57
 
58
  @app.route('/run_proxy_task', methods=['POST'])
59
  def run_proxy_task_endpoint():
60
- """API endpoint to receive a task and execute it with Proxy-lite."""
61
  data = request.json
62
  task = data.get('task')
63
  if not task:
@@ -66,32 +73,23 @@ def run_proxy_task_endpoint():
66
 
67
  logger.info(f"Received task for proxy-lite: '{task}'")
68
  try:
69
- # Initialize runner if not already done
70
  runner = run_async_task(initialize_runner())
71
- # Run the task using the proxy-lite runner
72
  result = run_async_task(runner.run(task))
73
 
74
- logger.info(f"Proxy-lite task completed. Output: {result[:200]}...") # Log truncated output
75
- # Return the result as a JSON response
76
  return jsonify({"output": result})
77
  except Exception as e:
78
- logger.exception(f"Error processing task '{task}':") # Logs full traceback for debugging
79
  return jsonify({"error": f"An error occurred: {str(e)}. Check logs for details."}), 500
80
 
81
  @app.route('/')
82
  def root():
83
- """Basic root endpoint for health check."""
84
  logger.info("Root endpoint accessed.")
85
  return "Proxy-lite API is running. Send POST requests to /run_proxy_task with a 'task' in JSON body."
86
 
87
  if __name__ == '__main__':
88
- # Check if HF_API_TOKEN is set during local development/testing
89
  if not os.environ.get("HF_API_TOKEN"):
90
  logger.error("HF_API_TOKEN environment variable is not set. Please set it for local testing.")
91
- # For local execution, you might choose to exit or just log
92
- # For deployment on Hugging Face Spaces, it MUST be set as a Secret.
93
- # exit(1) # Uncomment this if you want to force exit without token locally
94
-
95
  logger.info("Starting Flask development server on 0.0.0.0:7860...")
96
- # Hugging Face Spaces requires binding to 0.0.0.0 and listening on port 7860
97
- app.run(host='0.0.0.0', port=7860, debug=True) # debug=True for local, disable for production
 
5
  import os
6
  import logging
7
 
 
8
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
9
  logger = logging.getLogger(__name__)
10
 
11
  app = Flask(__name__)
12
 
 
13
  _runner = None
14
 
15
  async def initialize_runner():
 
16
  global _runner
17
  if _runner is None:
18
  logger.info("Initializing Proxy-lite Runner...")
 
19
  hf_api_token = os.environ.get("HF_API_TOKEN")
20
  if not hf_api_token:
21
  logger.error("HF_API_TOKEN environment variable not set. Cannot initialize Runner.")
 
25
  "environment": {
26
  "name": "webbrowser",
27
  "homepage": "https://www.google.com",
28
+ "headless": True,
29
  },
30
  "solver": {
31
  "name": "simple",
 
34
  "client": {
35
  "name": "convergence",
36
  "model_id": "convergence-ai/proxy-lite-3b",
 
37
  "api_base": "https://api-inference.huggingface.co/models/convergence-ai/proxy-lite-3b",
38
+ "api_key": hf_api_token
39
  }
40
  }
41
  }
 
44
  logger.info("Proxy-lite Runner initialized successfully.")
45
  return _runner
46
 
47
+ # --- MODIFIED run_async_task FUNCTION ---
48
  def run_async_task(coro):
49
+ """
50
+ Helper to run async coroutines in a synchronous context (like Flask routes).
51
+ Ensures an event loop exists and runs the coroutine.
52
+ """
53
+ try:
54
+ # Try to get the running loop (for current thread/greenlet)
55
+ loop = asyncio.get_running_loop()
56
+ except RuntimeError:
57
+ # If no loop is running, create a new one for this thread
58
+ loop = asyncio.new_event_loop()
59
+ asyncio.set_event_loop(loop)
60
+
61
+ # Run the coroutine until it completes
62
  return loop.run_until_complete(coro)
63
+ # --- END MODIFIED run_async_task FUNCTION ---
64
+
65
 
66
  @app.route('/run_proxy_task', methods=['POST'])
67
  def run_proxy_task_endpoint():
 
68
  data = request.json
69
  task = data.get('task')
70
  if not task:
 
73
 
74
  logger.info(f"Received task for proxy-lite: '{task}'")
75
  try:
 
76
  runner = run_async_task(initialize_runner())
 
77
  result = run_async_task(runner.run(task))
78
 
79
+ logger.info(f"Proxy-lite task completed. Output: {result[:200]}...")
 
80
  return jsonify({"output": result})
81
  except Exception as e:
82
+ logger.exception(f"Error processing task '{task}':")
83
  return jsonify({"error": f"An error occurred: {str(e)}. Check logs for details."}), 500
84
 
85
  @app.route('/')
86
  def root():
 
87
  logger.info("Root endpoint accessed.")
88
  return "Proxy-lite API is running. Send POST requests to /run_proxy_task with a 'task' in JSON body."
89
 
90
  if __name__ == '__main__':
 
91
  if not os.environ.get("HF_API_TOKEN"):
92
  logger.error("HF_API_TOKEN environment variable is not set. Please set it for local testing.")
93
+ exit(1)
 
 
 
94
  logger.info("Starting Flask development server on 0.0.0.0:7860...")
95
+ app.run(host='0.0.0.0', port=7860, debug=True)