Spaces:
Sleeping
Sleeping
roll back to params
Browse files- cve_factchecker/app.py +68 -19
cve_factchecker/app.py
CHANGED
|
@@ -49,30 +49,79 @@ start_time = time.time()
|
|
| 49 |
# Start ingestion in background as soon as the module is imported / app is created
|
| 50 |
_start_ingest_thread()
|
| 51 |
|
| 52 |
-
@app.route('/
|
| 53 |
-
def
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
claim = payload.get('claim')
|
| 60 |
-
if not claim:
|
| 61 |
-
return jsonify({"error": "claim field required in JSON body"}), 400
|
| 62 |
-
|
| 63 |
-
# Check if ingestion is still in progress
|
| 64 |
if not INGEST_STATUS.get("finished"):
|
| 65 |
-
return
|
| 66 |
-
|
| 67 |
-
# Perform fact check
|
| 68 |
result = system.fact_check(claim)
|
| 69 |
-
|
| 70 |
-
# Handle LLM quota/credit issues gracefully
|
| 71 |
if result.get('verdict') == 'ERROR' and '402' in result.get('reasoning',''):
|
| 72 |
result['verdict'] = 'UNVERIFIED'
|
| 73 |
result['reasoning'] = 'LLM quota/credits insufficient. Retrieval performed; provide API key to enable full analysis.'
|
| 74 |
-
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
if __name__ == '__main__':
|
| 78 |
port = int(os.environ.get('PORT', '7860'))
|
|
|
|
| 49 |
# Start ingestion in background as soon as the module is imported / app is created
|
| 50 |
_start_ingest_thread()
|
| 51 |
|
| 52 |
+
@app.route('/health')
|
| 53 |
+
def health() -> Any:
|
| 54 |
+
return jsonify({"status": "ok", "uptime_sec": round(time.time()-start_time,2)})
|
| 55 |
+
|
| 56 |
+
## Simplified API: only /health and /fact-check provided. Data ingestion occurs automatically on startup.
|
| 57 |
+
|
| 58 |
+
def _run_fact_check(claim: str): # internal helper
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
if not INGEST_STATUS.get("finished"):
|
| 60 |
+
return {"verdict": "INITIALIZING", "reasoning": "Ingestion still in progress. Try again soon.", "confidence": 0.0}, 503
|
|
|
|
|
|
|
| 61 |
result = system.fact_check(claim)
|
|
|
|
|
|
|
| 62 |
if result.get('verdict') == 'ERROR' and '402' in result.get('reasoning',''):
|
| 63 |
result['verdict'] = 'UNVERIFIED'
|
| 64 |
result['reasoning'] = 'LLM quota/credits insufficient. Retrieval performed; provide API key to enable full analysis.'
|
| 65 |
+
return result, 200
|
| 66 |
+
|
| 67 |
+
@app.route('/fact-check', methods=['POST','GET'])
|
| 68 |
+
def fact_check() -> Any:
|
| 69 |
+
claim: Any = None
|
| 70 |
+
if request.method == 'GET':
|
| 71 |
+
claim = request.args.get('claim') or request.args.get('text')
|
| 72 |
+
else: # POST
|
| 73 |
+
content_type = (request.content_type or '').lower()
|
| 74 |
+
# Prefer form-data / urlencoded strictly when provided (Postman Body: form-data)
|
| 75 |
+
if 'multipart/form-data' in content_type or 'application/x-www-form-urlencoded' in content_type:
|
| 76 |
+
# form fields first
|
| 77 |
+
claim = request.form.get('claim') or request.form.get('text')
|
| 78 |
+
# then file fields
|
| 79 |
+
if not claim and request.files:
|
| 80 |
+
f = (request.files.get('file') or request.files.get('claim') or request.files.get('claim_file'))
|
| 81 |
+
if f:
|
| 82 |
+
try:
|
| 83 |
+
claim = (f.read() or b'').decode('utf-8', errors='ignore').strip()
|
| 84 |
+
except Exception:
|
| 85 |
+
claim = None
|
| 86 |
+
if not claim:
|
| 87 |
+
return jsonify({"error": "Please provide claim via form-data: key 'claim' or 'text' (or upload file as 'file')."}), 400
|
| 88 |
+
else:
|
| 89 |
+
# JSON payload
|
| 90 |
+
payload = request.get_json(silent=True) or {}
|
| 91 |
+
claim = payload.get('claim') or payload.get('text')
|
| 92 |
+
# raw text/plain
|
| 93 |
+
if not claim and 'text/plain' in content_type:
|
| 94 |
+
raw = request.get_data(cache=False, as_text=True) or ''
|
| 95 |
+
claim = raw.strip()
|
| 96 |
+
# query fallback
|
| 97 |
+
if not claim:
|
| 98 |
+
claim = request.args.get('claim') or request.args.get('text')
|
| 99 |
+
if not claim:
|
| 100 |
+
return jsonify({"error": "claim parameter or JSON field 'claim' required"}), 400
|
| 101 |
+
result, code = _run_fact_check(claim)
|
| 102 |
+
return jsonify(result), code
|
| 103 |
+
|
| 104 |
+
@app.route('/')
|
| 105 |
+
def index():
|
| 106 |
+
# Convenience: allow GET /?claim=... for Postman users
|
| 107 |
+
q_claim = request.args.get('claim')
|
| 108 |
+
if q_claim:
|
| 109 |
+
result, code = _run_fact_check(q_claim)
|
| 110 |
+
return jsonify(result), code
|
| 111 |
+
return jsonify({
|
| 112 |
+
"name": "CVE Fact Checker API (Simplified)",
|
| 113 |
+
"status": {
|
| 114 |
+
"ingestion_finished": INGEST_STATUS.get("finished"),
|
| 115 |
+
"synced_articles": INGEST_STATUS.get("synced"),
|
| 116 |
+
"ingestion_error": INGEST_STATUS.get("error")
|
| 117 |
+
},
|
| 118 |
+
"endpoints": [
|
| 119 |
+
"GET /health",
|
| 120 |
+
"GET /fact-check?claim=...",
|
| 121 |
+
"POST /fact-check (JSON: {claim}, form-data: claim|text, x-www-form-urlencoded, text/plain, or file upload)",
|
| 122 |
+
"GET /?claim=... (alias)"
|
| 123 |
+
]
|
| 124 |
+
})
|
| 125 |
|
| 126 |
if __name__ == '__main__':
|
| 127 |
port = int(os.environ.get('PORT', '7860'))
|