Trisha Tomy commited on
Commit
97d2a3d
·
1 Parent(s): 824b925
Files changed (1) hide show
  1. app.py +16 -139
app.py CHANGED
@@ -1,149 +1,35 @@
1
- # import gevent.monkey
2
- # gevent.monkey.patch_all(asyncio=True)
3
- # # app.py
4
- # import asyncio
5
- # from flask import Flask, request, jsonify
6
- # from proxy_lite import Runner, RunnerConfig
7
- # import os
8
- # import logging
9
-
10
- # logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
11
- # logger = logging.getLogger(__name__)
12
-
13
- # app = Flask(__name__)
14
-
15
- # _runner = None
16
-
17
- # async def initialize_runner():
18
- # global _runner
19
- # if _runner is None:
20
- # logger.info("Initializing Proxy-lite Runner...")
21
- # hf_api_token = os.environ.get("HF_API_TOKEN")
22
- # if not hf_api_token:
23
- # logger.error("HF_API_TOKEN environment variable not set. Cannot initialize Runner.")
24
- # raise ValueError("HF_API_TOKEN environment variable not set. Please set it as a Space secret.")
25
-
26
- # config = RunnerConfig.from_dict({
27
- # "environment": {
28
- # "name": "webbrowser",
29
- # "homepage": "https://www.google.com",
30
- # "headless": True,
31
- # },
32
- # "solver": {
33
- # "name": "simple",
34
- # "agent": {
35
- # "name": "proxy_lite",
36
- # "client": {
37
- # "name": "convergence",
38
- # "model_id": "convergence-ai/proxy-lite-3b",
39
- # "api_base": "https://api-inference.huggingface.co/models/convergence-ai/proxy-lite-3b",
40
- # "api_key": hf_api_token
41
- # }
42
- # }
43
- # }
44
- # })
45
- # _runner = Runner(config)
46
- # logger.info("Proxy-lite Runner initialized successfully.")
47
- # return _runner
48
-
49
- # # --- MODIFIED run_async_task FUNCTION ---
50
- # def run_async_task(coro):
51
- # """
52
- # Helper to run async coroutines in a synchronous context (like Flask routes).
53
- # Ensures an event loop exists and runs the coroutine.
54
- # """
55
- # try:
56
- # # Try to get the running loop (for current thread/greenlet)
57
- # loop = asyncio.get_running_loop()
58
- # except RuntimeError:
59
- # # If no loop is running, create a new one for this thread
60
- # loop = asyncio.new_event_loop()
61
- # asyncio.set_event_loop(loop)
62
-
63
- # # Run the coroutine until it completes
64
- # return loop.run_until_complete(coro)
65
- # # --- END MODIFIED run_async_task FUNCTION ---
66
-
67
-
68
- # @app.route('/run_proxy_task', methods=['POST'])
69
- # def run_proxy_task_endpoint():
70
- # data = request.json
71
- # task = data.get('task')
72
- # if not task:
73
- # logger.warning("Received request without 'task' field. Returning 400.")
74
- # return jsonify({"error": "No 'task' provided in request body"}), 400
75
-
76
- # logger.info(f"Received task for proxy-lite: '{task}'")
77
- # try:
78
- # runner = run_async_task(initialize_runner())
79
- # result = run_async_task(runner.run(task))
80
-
81
- # logger.info(f"Proxy-lite task completed. Output: {result[:200]}...")
82
- # return jsonify({"output": result})
83
- # except Exception as e:
84
- # logger.exception(f"Error processing task '{task}':")
85
- # return jsonify({"error": f"An error occurred: {str(e)}. Check logs for details."}), 500
86
-
87
- # @app.route('/')
88
- # def root():
89
- # logger.info("Root endpoint accessed.")
90
- # return "Proxy-lite API is running. Send POST requests to /run_proxy_task with a 'task' in JSON body."
91
-
92
- # if __name__ == '__main__':
93
- # if not os.environ.get("HF_API_TOKEN"):
94
- # logger.error("HF_API_TOKEN environment variable is not set. Please set it for local testing.")
95
- # exit(1)
96
- # logger.info("Starting Flask development server on 0.0.0.0:7860...")
97
- # app.run(host='0.0.0.0', port=7860, debug=True)
98
- # app.py
99
- # IMPORTANT: These two lines MUST be at the very top, before any other imports.
100
- # They patch asyncio to work cooperatively with gevent workers.
101
  import gevent.monkey
102
  gevent.monkey.patch_all(asyncio=True)
103
-
104
  import asyncio
105
  from flask import Flask, request, jsonify
106
  from proxy_lite import Runner, RunnerConfig
107
- from proxy_lite.config import RecorderConfig # <--- This import is CRUCIAL
108
  import os
109
  import logging
110
 
111
- # Configure logging for better visibility in Hugging Face Space logs
112
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
113
  logger = logging.getLogger(__name__)
114
 
115
  app = Flask(__name__)
116
 
117
- # Global runner instance. It will be initialized once per worker process/greenlet
118
- # upon the first request to ensure correct event loop binding.
119
  _runner = None
120
 
121
  async def initialize_runner():
122
- """Initializes the Proxy-lite Runner asynchronously."""
123
  global _runner
124
  if _runner is None:
125
  logger.info("Initializing Proxy-lite Runner...")
126
- # Retrieve Hugging Face API Token from environment variables (set as Space Secret)
127
  hf_api_token = os.environ.get("HF_API_TOKEN")
128
  if not hf_api_token:
129
  logger.error("HF_API_TOKEN environment variable not set. Cannot initialize Runner.")
130
  raise ValueError("HF_API_TOKEN environment variable not set. Please set it as a Space secret.")
131
 
132
- # --- NEW: Explicitly create RecorderConfig instance ---
133
- # This addresses the PermissionError by ensuring the root_path is explicitly set
134
- # and passed as a Pydantic object, rather than relying on nested dict parsing.
135
- recorder_config_instance = RecorderConfig(root_path="/tmp/proxy_lite_runs")
136
- # --- END NEW ---
137
-
138
- # --- MODIFIED: Pass recorder_config_instance directly to RunnerConfig constructor ---
139
- # Pass all configuration parameters as keyword arguments to the Pydantic model.
140
- config = RunnerConfig(
141
- environment={
142
  "name": "webbrowser",
143
  "homepage": "https://www.google.com",
144
- "headless": True, # Keep headless for server environment
145
  },
146
- solver={
147
  "name": "simple",
148
  "agent": {
149
  "name": "proxy_lite",
@@ -154,36 +40,33 @@ async def initialize_runner():
154
  "api_key": hf_api_token
155
  }
156
  }
157
- },
158
- recorder=recorder_config_instance # Pass the explicitly created instance
159
- )
160
- # --- END MODIFIED ---
161
-
162
- # Instantiate the Runner, passing the config as a keyword argument (Pydantic style)
163
- _runner = Runner(config=config) # <--- This ensures config is passed as keyword
164
  logger.info("Proxy-lite Runner initialized successfully.")
165
  return _runner
166
 
 
167
  def run_async_task(coro):
168
  """
169
  Helper to run async coroutines in a synchronous context (like Flask routes).
170
- Ensures an event loop exists for the current thread/greenlet and runs the coroutine.
171
- This addresses the "no current event loop" errors.
172
  """
173
  try:
174
  # Try to get the running loop (for current thread/greenlet)
175
  loop = asyncio.get_running_loop()
176
  except RuntimeError:
177
- # If no loop is running, create a new one for this thread/greenlet
178
  loop = asyncio.new_event_loop()
179
  asyncio.set_event_loop(loop)
180
 
181
  # Run the coroutine until it completes
182
  return loop.run_until_complete(coro)
 
 
183
 
184
  @app.route('/run_proxy_task', methods=['POST'])
185
  def run_proxy_task_endpoint():
186
- """API endpoint to receive a task and execute it with Proxy-lite."""
187
  data = request.json
188
  task = data.get('task')
189
  if not task:
@@ -192,29 +75,23 @@ def run_proxy_task_endpoint():
192
 
193
  logger.info(f"Received task for proxy-lite: '{task}'")
194
  try:
195
- # Ensure runner is initialized (and event loop handled) before use
196
  runner = run_async_task(initialize_runner())
197
- # Run the task using the proxy-lite runner
198
  result = run_async_task(runner.run(task))
199
 
200
- logger.info(f"Proxy-lite task completed. Output: {result[:200]}...") # Log truncated output
201
- # Return the result as a JSON response
202
  return jsonify({"output": result})
203
  except Exception as e:
204
- logger.exception(f"Error processing task '{task}':") # Logs full traceback for debugging
205
  return jsonify({"error": f"An error occurred: {str(e)}. Check logs for details."}), 500
206
 
207
  @app.route('/')
208
  def root():
209
- """Basic root endpoint for health check and user info."""
210
  logger.info("Root endpoint accessed.")
211
  return "Proxy-lite API is running. Send POST requests to /run_proxy_task with a 'task' in JSON body."
212
 
213
  if __name__ == '__main__':
214
- # During local development, ensure HF_API_TOKEN is set manually
215
  if not os.environ.get("HF_API_TOKEN"):
216
  logger.error("HF_API_TOKEN environment variable is not set. Please set it for local testing.")
217
  exit(1)
218
  logger.info("Starting Flask development server on 0.0.0.0:7860...")
219
- # Hugging Face Spaces expects binding to 0.0.0.0 and listening on port 7860
220
- app.run(host='0.0.0.0', port=7860, debug=True) # debug=True for local testing, disable for production
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gevent.monkey
2
  gevent.monkey.patch_all(asyncio=True)
3
+ # app.py
4
  import asyncio
5
  from flask import Flask, request, jsonify
6
  from proxy_lite import Runner, RunnerConfig
 
7
  import os
8
  import logging
9
 
 
10
  logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
11
  logger = logging.getLogger(__name__)
12
 
13
  app = Flask(__name__)
14
 
 
 
15
  _runner = None
16
 
17
  async def initialize_runner():
 
18
  global _runner
19
  if _runner is None:
20
  logger.info("Initializing Proxy-lite Runner...")
 
21
  hf_api_token = os.environ.get("HF_API_TOKEN")
22
  if not hf_api_token:
23
  logger.error("HF_API_TOKEN environment variable not set. Cannot initialize Runner.")
24
  raise ValueError("HF_API_TOKEN environment variable not set. Please set it as a Space secret.")
25
 
26
+ config = RunnerConfig.from_dict({
27
+ "environment": {
 
 
 
 
 
 
 
 
28
  "name": "webbrowser",
29
  "homepage": "https://www.google.com",
30
+ "headless": True,
31
  },
32
+ "solver": {
33
  "name": "simple",
34
  "agent": {
35
  "name": "proxy_lite",
 
40
  "api_key": hf_api_token
41
  }
42
  }
43
+ }
44
+ })
45
+ _runner = Runner(config)
 
 
 
 
46
  logger.info("Proxy-lite Runner initialized successfully.")
47
  return _runner
48
 
49
+ # --- MODIFIED run_async_task FUNCTION ---
50
  def run_async_task(coro):
51
  """
52
  Helper to run async coroutines in a synchronous context (like Flask routes).
53
+ Ensures an event loop exists and runs the coroutine.
 
54
  """
55
  try:
56
  # Try to get the running loop (for current thread/greenlet)
57
  loop = asyncio.get_running_loop()
58
  except RuntimeError:
59
+ # If no loop is running, create a new one for this thread
60
  loop = asyncio.new_event_loop()
61
  asyncio.set_event_loop(loop)
62
 
63
  # Run the coroutine until it completes
64
  return loop.run_until_complete(coro)
65
+ # --- END MODIFIED run_async_task FUNCTION ---
66
+
67
 
68
  @app.route('/run_proxy_task', methods=['POST'])
69
  def run_proxy_task_endpoint():
 
70
  data = request.json
71
  task = data.get('task')
72
  if not task:
 
75
 
76
  logger.info(f"Received task for proxy-lite: '{task}'")
77
  try:
 
78
  runner = run_async_task(initialize_runner())
 
79
  result = run_async_task(runner.run(task))
80
 
81
+ logger.info(f"Proxy-lite task completed. Output: {result[:200]}...")
 
82
  return jsonify({"output": result})
83
  except Exception as e:
84
+ logger.exception(f"Error processing task '{task}':")
85
  return jsonify({"error": f"An error occurred: {str(e)}. Check logs for details."}), 500
86
 
87
  @app.route('/')
88
  def root():
 
89
  logger.info("Root endpoint accessed.")
90
  return "Proxy-lite API is running. Send POST requests to /run_proxy_task with a 'task' in JSON body."
91
 
92
  if __name__ == '__main__':
 
93
  if not os.environ.get("HF_API_TOKEN"):
94
  logger.error("HF_API_TOKEN environment variable is not set. Please set it for local testing.")
95
  exit(1)
96
  logger.info("Starting Flask development server on 0.0.0.0:7860...")
97
+ app.run(host='0.0.0.0', port=7860, debug=True)