Spaces:
Running
Running
| # imports | |
| import os | |
| import json | |
| import re | |
| from time import time | |
| from flask import Flask, request, jsonify | |
| from flask_cors import CORS | |
| from dotenv import load_dotenv | |
| from openai import OpenAI | |
| load_dotenv()# load env | |
| app = Flask(__name__) | |
| # frontend lock | |
| allowed_origins = os.getenv("ALLOWED_ORIGINS", "https://sumit989bishnoi-crypto.github.io") | |
| CORS(app, origins=allowed_origins.split(",")) | |
| # model call | |
| API_BASE_URL = os.getenv("API_BASE_URL", "https://router.huggingface.co/v1") | |
| MODEL_NAME = os.getenv("MODEL_NAME", "Qwen/Qwen2.5-Coder-7B-Instruct") | |
| API_KEY = os.getenv("API_KEY") or os.getenv("HF_TOKEN") | |
| client = OpenAI(base_url=API_BASE_URL, api_key=API_KEY) if API_KEY else None | |
| _last_request: dict[str, float] = {} | |
| # rate limit 1 requesr for 2 sec | |
| def is_rate_limited(ip: str) -> bool: | |
| now = time() | |
| if ip in _last_request and now - _last_request[ip] < 2: | |
| return True | |
| _last_request[ip] = now | |
| return False | |
| def extract_json(raw: str) -> dict | None: | |
| """Strip markdown fences then attempt JSON parse two ways.""" | |
| cleaned = re.sub(r"^```(?:json)?\s*", "", raw.strip()) | |
| cleaned = re.sub(r"\s*```$", "", cleaned).strip() | |
| try: | |
| return json.loads(cleaned) | |
| except json.JSONDecodeError: | |
| pass | |
| # stops exactly where JSON ends | |
| try: | |
| idx = cleaned.index("{") | |
| decoded, _ = json.JSONDecoder().raw_decode(cleaned, idx) | |
| return decoded | |
| except (ValueError, json.JSONDecodeError): | |
| return None | |
| # always return a valid result | |
| def safe_parse(raw: str) -> dict: | |
| """ | |
| Always returns a valid dict. | |
| Runs extract_json first; falls back to a safe default on any failure | |
| so a bad model response never crashes the endpoint. | |
| """ | |
| # low confidence | |
| if not raw: | |
| return { | |
| "language": "unknown", | |
| "explanation": "The AI returned an empty response. Please try again.", | |
| "fixed_code": "", | |
| "confidence": "low", | |
| } | |
| result = extract_json(raw) | |
| if result and isinstance(result, dict): | |
| return result | |
| # always return a valid explanation | |
| return { | |
| "language": "unknown", | |
| "explanation": "Output parsing failed — the AI did not return valid JSON.", | |
| "fixed_code": raw[:1500], | |
| "confidence": "low", | |
| } | |
| # status | |
| def index(): | |
| return jsonify({"name": "CodeRescue API", "version": "42.0", "status": "running"}) # to show when backend is running correct | |
| # health check | |
| def health(): | |
| return jsonify({"status": "ok"}) | |
| # analyze | |
| def analyze_code(): | |
| forwarded = request.headers.get("X-Forwarded-For", "") | |
| ip = forwarded.split(",")[0].strip() if forwarded else (request.remote_addr or "unknown") | |
| # rate limit error to show | |
| if is_rate_limited(ip): | |
| return jsonify({ | |
| "error": "Too many requests. Please wait a moment.", | |
| "fixed_code": "", | |
| "language": "" | |
| }), 429 | |
| if not client: | |
| return jsonify({"error": "API key not configured", "fixed_code": "", "language": ""}), 500 | |
| start = time() | |
| data = request.get_json(silent=True) | |
| if not data or not data.get("code", "").strip(): | |
| return jsonify({"error": "No code provided"}), 400 | |
| raw_code = data["code"].strip() | |
| warning = "" | |
| if len(raw_code) > 1500: | |
| warning = "Code was truncated to 1500 characters for processing." | |
| user_code = raw_code[:1500] | |
| try: | |
| response = client.chat.completions.create( | |
| model=MODEL_NAME, | |
| max_tokens=400, # max tokens usage limit | |
| messages=[ | |
| {"role": "system", | |
| "content": ( | |
| "You are a code debugger.\n" | |
| "RULES:\n" | |
| "1. Return ONLY valid JSON.\n" # always give json | |
| "2. No markdown, no extra text.\n" | |
| "3. Keep explanation to MAX 2 lines.\n" | |
| "4. Always return FULL fixed code.\n" | |
| "5. Keep code minimal and clean.\n" | |
| "6.Prefer fixes that preserve original logic and intent over simply avoiding errors.\n" # for low error | |
| "If code is too large:\n" # faster speed | |
| "- Simplify it while preserving logic.\n" | |
| "- Remove unnecessary parts if safe.\n" | |
| "JSON FORMAT:\n" # formoat to show | |
| "{\"language\":\"...\"," | |
| "\"explanation\":\"...\"," | |
| "\"fixed_code\":\"...\"," | |
| "\"confidence\":\"high|medium|low\"}" | |
| ), | |
| }, | |
| { | |
| "role": "user", | |
| "content": f"Code:\n{user_code}", | |
| }, | |
| ], | |
| ) | |
| # calculate latency | |
| end = time() | |
| raw = response.choices[0].message.content.strip() | |
| # safe_parse always returns a dict — never raises | |
| parsed = safe_parse(raw) | |
| fixed_code = parsed.get("fixed_code", "") | |
| # Unescape literal \n / \t the model emits inside JSON strings | |
| fixed_code = fixed_code.replace("\\n", "\n").replace("\\t", "\t") | |
| return jsonify({ | |
| "explanation": parsed.get("explanation", "No explanation provided."), | |
| "fixed_code": fixed_code, | |
| "language": parsed.get("language", "unknown"), | |
| "confidence": parsed.get("confidence", "medium"), | |
| "warning": warning, | |
| "time_taken": round(end - start, 3), | |
| }) | |
| # warning when it is server side error | |
| except Exception as e: | |
| return jsonify({ | |
| "explanation": f"Server error: {str(e)}", | |
| "fixed_code": "", | |
| "language": "unknown", | |
| "confidence": "low", | |
| "warning": warning | |
| }), 500 | |
| # route for /openenv/reset &&& /reset | |
| def openenv_reset(): | |
| return jsonify({"status": "success"}) | |
| # ip && port | |
| if __name__ == "__main__": | |
| port = int(os.environ.get("PORT", 7860)) | |
| app.run(host="0.0.0.0", port=port) |