crabbly commited on
Commit
e894ef0
·
1 Parent(s): 8aa0d3e

Add labelling studio

Browse files
Files changed (2) hide show
  1. __pycache__/main.cpython-313.pyc +0 -0
  2. main.py +151 -1
__pycache__/main.cpython-313.pyc ADDED
Binary file (25.3 kB). View file
 
main.py CHANGED
@@ -2,7 +2,7 @@ import os
2
  import time
3
  import requests
4
  from fastapi import FastAPI, UploadFile, File, Form, Query, Request, Body
5
- from fastapi.responses import Response
6
  from fastapi.middleware.cors import CORSMiddleware
7
  from fastapi.concurrency import run_in_threadpool # <--- FIX: Added Threadpool
8
  import uvicorn
@@ -178,6 +178,156 @@ async def proxy_compatibility(request: Request, password: str = Form(""), userna
178
  return {"success": False, "message": f"Proxy Error (Internal): {str(e)}", "results": []}
179
 
180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  @app.post("/proxy_batch_stage")
182
  async def proxy_batch_stage(payload: dict = Body(...)):
183
  username = str(payload.get("username", ""))
 
2
  import time
3
  import requests
4
  from fastapi import FastAPI, UploadFile, File, Form, Query, Request, Body
5
+ from fastapi.responses import Response, JSONResponse
6
  from fastapi.middleware.cors import CORSMiddleware
7
  from fastapi.concurrency import run_in_threadpool # <--- FIX: Added Threadpool
8
  import uvicorn
 
178
  return {"success": False, "message": f"Proxy Error (Internal): {str(e)}", "results": []}
179
 
180
 
181
+ @app.get("/proxy_experts")
182
+ async def proxy_experts(username: str = Query(""), password: str = Query("")):
183
+ base_url = DEV_URL if username.strip().lower() == "devtest" else PROD_URL
184
+ target_url = f"{base_url}/experts"
185
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
186
+
187
+ def make_get():
188
+ return requests.get(target_url, headers=headers, params={"username": username, "password": password}, timeout=20)
189
+
190
+ try:
191
+ response = await run_in_threadpool(make_get)
192
+ response.raise_for_status()
193
+ return response.json()
194
+ except requests.exceptions.RequestException as e:
195
+ return proxy_error_payload("Proxy Error (Hugging Face)", e, experts=[])
196
+ except Exception as e:
197
+ return {"success": False, "message": f"Proxy Error (Internal): {str(e)}", "experts": []}
198
+
199
+
200
+ @app.post("/proxy_finetune")
201
+ async def proxy_finetune(payload: dict = Body(...)):
202
+ username = str(payload.get("username", ""))
203
+ expert_id = str(payload.get("expert_id", "")).strip()
204
+ base_url = DEV_URL if username.strip().lower() == "devtest" else PROD_URL
205
+ target_url = f"{base_url}/experts/{expert_id}/finetune"
206
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
207
+
208
+ def make_post():
209
+ return request_with_hf_backoff(requests.post, target_url, max_retries=0, headers=headers, json=payload, timeout=60)
210
+
211
+ try:
212
+ response = await run_in_threadpool(make_post)
213
+ response.raise_for_status()
214
+ return response.json()
215
+ except requests.exceptions.RequestException as e:
216
+ return proxy_error_payload("Proxy Error (Hugging Face)", e)
217
+ except Exception as e:
218
+ return {"success": False, "message": f"Proxy Error (Internal): {str(e)}"}
219
+
220
+
221
+ @app.get("/proxy_train_job")
222
+ async def proxy_train_job(job_id: str = Query(...), username: str = Query(""), password: str = Query("")):
223
+ base_url = DEV_URL if username.strip().lower() == "devtest" else PROD_URL
224
+ target_url = f"{base_url}/train_jobs/status/{job_id}"
225
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
226
+
227
+ def make_get():
228
+ return requests.get(target_url, headers=headers, params={"username": username, "password": password}, timeout=20)
229
+
230
+ try:
231
+ response = await run_in_threadpool(make_get)
232
+ response.raise_for_status()
233
+ return response.json()
234
+ except requests.exceptions.RequestException as e:
235
+ return proxy_error_payload("Proxy Error (Hugging Face)", e)
236
+ except Exception as e:
237
+ return {"success": False, "message": f"Proxy Error (Internal): {str(e)}"}
238
+
239
+
240
+ @app.get("/proxy_train_jobs")
241
+ async def proxy_train_jobs(username: str = Query(""), password: str = Query("")):
242
+ base_url = DEV_URL if username.strip().lower() == "devtest" else PROD_URL
243
+ target_url = f"{base_url}/train_jobs"
244
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
245
+
246
+ def make_get():
247
+ return requests.get(target_url, headers=headers, params={"username": username, "password": password}, timeout=20)
248
+
249
+ try:
250
+ response = await run_in_threadpool(make_get)
251
+ response.raise_for_status()
252
+ return response.json()
253
+ except requests.exceptions.RequestException as e:
254
+ return proxy_error_payload("Proxy Error (Hugging Face)", e, jobs=[])
255
+ except Exception as e:
256
+ return {"success": False, "message": f"Proxy Error (Internal): {str(e)}", "jobs": []}
257
+
258
+
259
+ DATASET_PROXY_TIMEOUT_SECONDS = 180
260
+
261
+
262
+ @app.api_route("/proxy_datasets{rest:path}", methods=["GET", "POST", "PUT", "DELETE"])
263
+ async def proxy_datasets(rest: str, request: Request):
264
+ """Generic forwarder for all Labeling Studio dataset endpoints.
265
+
266
+ Mirrors /proxy_datasets{rest} -> {base}/datasets{rest}, preserving the query
267
+ string, body (multipart / JSON), and returning either JSON or raw binary
268
+ (image/zip) responses. Routes dev vs prod by username (query, form, or JSON).
269
+ """
270
+ username = request.query_params.get("username", "")
271
+ content_type = request.headers.get("content-type", "")
272
+
273
+ files = []
274
+ data = {}
275
+ json_body = None
276
+ if request.method in ("POST", "PUT", "DELETE"):
277
+ if "multipart/form-data" in content_type:
278
+ form = await request.form()
279
+ for key, value in form.multi_items():
280
+ if hasattr(value, "filename"):
281
+ files.append((key, (value.filename, await value.read(), value.content_type)))
282
+ else:
283
+ data[key] = str(value)
284
+ username = username or data.get("username", "")
285
+ elif "application/json" in content_type:
286
+ try:
287
+ json_body = await request.json()
288
+ except Exception:
289
+ json_body = None
290
+ if isinstance(json_body, dict):
291
+ username = username or str(json_body.get("username", ""))
292
+
293
+ base_url = DEV_URL if username.strip().lower() == "devtest" else PROD_URL
294
+ target_url = f"{base_url}/datasets{rest}"
295
+ if request.url.query:
296
+ target_url += f"?{request.url.query}"
297
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
298
+
299
+ def make_request():
300
+ return request_with_hf_backoff(
301
+ getattr(requests, request.method.lower()),
302
+ target_url,
303
+ max_retries=0,
304
+ headers=headers,
305
+ files=files or None,
306
+ data=data or None,
307
+ json=json_body if json_body is not None else None,
308
+ timeout=DATASET_PROXY_TIMEOUT_SECONDS,
309
+ )
310
+
311
+ try:
312
+ response = await run_in_threadpool(make_request)
313
+ except requests.exceptions.RequestException as e:
314
+ return JSONResponse(status_code=502, content=proxy_error_payload("Proxy Error (Hugging Face)", e))
315
+ except Exception as e:
316
+ return JSONResponse(status_code=500, content={"success": False, "message": f"Proxy Error (Internal): {str(e)}"})
317
+
318
+ resp_ct = response.headers.get("content-type", "application/octet-stream")
319
+ passthrough_headers = {}
320
+ disposition = response.headers.get("content-disposition")
321
+ if disposition:
322
+ passthrough_headers["content-disposition"] = disposition
323
+ return Response(
324
+ content=response.content,
325
+ status_code=response.status_code,
326
+ media_type=resp_ct,
327
+ headers=passthrough_headers,
328
+ )
329
+
330
+
331
  @app.post("/proxy_batch_stage")
332
  async def proxy_batch_stage(payload: dict = Body(...)):
333
  username = str(payload.get("username", ""))