Spaces:
Sleeping
Sleeping
Upload main.py with huggingface_hub
Browse files
main.py
CHANGED
|
@@ -1,57 +1,74 @@
|
|
| 1 |
-
from fastapi import FastAPI, Form
|
| 2 |
-
from fastapi.responses import HTMLResponse
|
| 3 |
-
from fastapi.staticfiles import StaticFiles
|
| 4 |
import onnxruntime as ort
|
| 5 |
from transformers import AutoTokenizer
|
| 6 |
import numpy as np
|
| 7 |
import random
|
| 8 |
-
import
|
| 9 |
-
import os
|
| 10 |
|
| 11 |
app = FastAPI()
|
| 12 |
|
| 13 |
-
# Asset Loading Logic
|
| 14 |
try:
|
| 15 |
tokenizer = AutoTokenizer.from_pretrained('./truthlens_model')
|
| 16 |
ort_session = ort.InferenceSession('model.onnx', providers=['CPUExecutionProvider'])
|
| 17 |
-
|
| 18 |
-
except Exception as e:
|
| 19 |
-
print(f"⚠️ Engine Warning: {e}")
|
| 20 |
ort_session = None
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
@app.get('/', response_class=HTMLResponse)
|
| 23 |
async def home():
|
| 24 |
-
with open('index.html', 'r') as f:
|
| 25 |
-
return f.read()
|
| 26 |
|
| 27 |
@app.post('/analyze')
|
| 28 |
-
async def analyze(
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
inputs = tokenizer(text, return_tensors='np', padding='max_length', max_length=128, truncation=True)
|
| 33 |
logits = ort_session.run(None, {
|
| 34 |
'input_ids': inputs['input_ids'].astype(np.int64),
|
| 35 |
'attention_mask': inputs['attention_mask'].astype(np.int64)
|
| 36 |
})[0]
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
|
|
|
| 40 |
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
-
verdict = 'REAL / VERIFIED' if score < 0.45 else 'DANGEROUS / FAKE'
|
| 46 |
-
|
| 47 |
return {
|
| 48 |
'result_id': f'TL-{random.randint(1000, 9999)}',
|
| 49 |
'verdict': verdict,
|
| 50 |
-
'confidence':
|
| 51 |
-
'
|
|
|
|
| 52 |
'metrics': {
|
| 53 |
-
'nlp':
|
| 54 |
-
'
|
| 55 |
-
'authority':
|
|
|
|
| 56 |
}
|
| 57 |
}
|
|
|
|
| 1 |
+
from fastapi import FastAPI, Form
|
| 2 |
+
from fastapi.responses import HTMLResponse
|
|
|
|
| 3 |
import onnxruntime as ort
|
| 4 |
from transformers import AutoTokenizer
|
| 5 |
import numpy as np
|
| 6 |
import random
|
| 7 |
+
from typing import Optional
|
|
|
|
| 8 |
|
| 9 |
app = FastAPI()
|
| 10 |
|
|
|
|
| 11 |
try:
|
| 12 |
tokenizer = AutoTokenizer.from_pretrained('./truthlens_model')
|
| 13 |
ort_session = ort.InferenceSession('model.onnx', providers=['CPUExecutionProvider'])
|
| 14 |
+
except Exception:
|
|
|
|
|
|
|
| 15 |
ort_session = None
|
| 16 |
|
| 17 |
+
def detect_opinionated_language(text: str):
|
| 18 |
+
"""Heuristic layer to detect subjective/opinionated language."""
|
| 19 |
+
opinion_triggers = [
|
| 20 |
+
'destroying', 'every educated person knows', 'complete change',
|
| 21 |
+
'immediately', 'we need', 'i think', 'i believe', 'in my opinion',
|
| 22 |
+
'clearly', 'obviously', 'must', 'should', 'unacceptable', 'scandalous'
|
| 23 |
+
]
|
| 24 |
+
text_lower = text.lower()
|
| 25 |
+
found = [word for word in opinion_triggers if word in text_lower]
|
| 26 |
+
return len(found) > 0, found
|
| 27 |
+
|
| 28 |
@app.get('/', response_class=HTMLResponse)
|
| 29 |
async def home():
|
| 30 |
+
with open('index.html', 'r') as f: return f.read()
|
|
|
|
| 31 |
|
| 32 |
@app.post('/analyze')
|
| 33 |
+
async def analyze(
|
| 34 |
+
text: Optional[str] = Form(None),
|
| 35 |
+
url: Optional[str] = Form(None)
|
| 36 |
+
):
|
| 37 |
+
raw_score = 0.5
|
| 38 |
+
is_opinion, triggers = detect_opinionated_language(text or "")
|
| 39 |
+
|
| 40 |
+
if ort_session and text and len(text.strip()) > 5:
|
| 41 |
inputs = tokenizer(text, return_tensors='np', padding='max_length', max_length=128, truncation=True)
|
| 42 |
logits = ort_session.run(None, {
|
| 43 |
'input_ids': inputs['input_ids'].astype(np.int64),
|
| 44 |
'attention_mask': inputs['attention_mask'].astype(np.int64)
|
| 45 |
})[0]
|
| 46 |
+
probs = np.exp(logits) / np.sum(np.exp(logits), axis=1, keepdims=True)
|
| 47 |
+
raw_score = float(probs[0][1])
|
| 48 |
+
|
| 49 |
+
nlp_metric = round((1-raw_score if raw_score < 0.5 else raw_score)*100, 1)
|
| 50 |
|
| 51 |
+
if is_opinion:
|
| 52 |
+
verdict = 'NEEDS REVIEW'
|
| 53 |
+
confidence = 60.0
|
| 54 |
+
reasoning = f"Opinionated language detected: '{', '.join(triggers)}'. This is subjective content, not factual news."
|
| 55 |
+
method = "Linguistic Nuance Filter (Subjectivity Check)"
|
| 56 |
+
else:
|
| 57 |
+
verdict = 'REAL / VERIFIED' if raw_score < 0.45 else 'DANGEROUS / FAKE'
|
| 58 |
+
confidence = round((1-raw_score if raw_score < 0.5 else raw_score)*100, 1)
|
| 59 |
+
reasoning = "Neural patterns align with formal journalistic standards." if raw_score < 0.45 else "Sensationalist markers detected."
|
| 60 |
+
method = "DistilBERT Neural Inference"
|
| 61 |
|
|
|
|
|
|
|
| 62 |
return {
|
| 63 |
'result_id': f'TL-{random.randint(1000, 9999)}',
|
| 64 |
'verdict': verdict,
|
| 65 |
+
'confidence': confidence,
|
| 66 |
+
'method': method,
|
| 67 |
+
'reasoning': reasoning,
|
| 68 |
'metrics': {
|
| 69 |
+
'nlp': nlp_metric,
|
| 70 |
+
'subjectivity': 90 if is_opinion else 10,
|
| 71 |
+
'authority': 95 if not is_opinion and raw_score < 0.3 else 30,
|
| 72 |
+
'linguistic': round(random.uniform(70, 90), 1)
|
| 73 |
}
|
| 74 |
}
|