Haqeeqat-Check / app.py
Hamid191's picture
Update app.py
5a65a78 verified
Raw
History Blame Contribute Delete
8.73 kB
"""Haqeeqat Check — Gradio interface for Hugging Face Spaces.
Run locally: python app.py
"""
import os
import subprocess
import sys
from pathlib import Path
# ---------------------------------------------------------------------------
# Ensure GROQ_API_KEY is loaded from Space secrets before any module import
# ---------------------------------------------------------------------------
if not os.environ.get("GROQ_API_KEY"):
pass # will be read at runtime by verification/config.py
import gradio as gr
try:
import spaces
_HAS_SPACES = True
except ImportError:
_HAS_SPACES = False
# ---------------------------------------------------------------------------
# Model bootstrap — runs once at import time
# ---------------------------------------------------------------------------
_MODEL_FILES = ["best_norm_ED.pth", "yolov8m_UrduDoc.pt"]
def _ensure_models():
"""Download OCR + Whisper models if not already present."""
root = Path(__file__).resolve().parent
models_dir = root / "models"
if os.environ.get("SPACE_ID"):
models_dir = Path("/home/user/app/models")
if all((models_dir / name).is_file() for name in _MODEL_FILES):
return
subprocess.run(
[sys.executable, str(root / "download_models.py")],
check=True,
)
_ensure_models()
# ---------------------------------------------------------------------------
# Lazy singletons — heavy imports deferred until first request
# ---------------------------------------------------------------------------
_ingestor = None
_agent = None
def _get_ingestor():
global _ingestor
if _ingestor is None:
from ingestion.ingestor import HaqeeqatIngestor
_ingestor = HaqeeqatIngestor()
return _ingestor
def _get_agent():
global _agent
if _agent is None:
from verification.verdict_agent import VerdictAgent
_agent = VerdictAgent()
return _agent
# ---------------------------------------------------------------------------
# Labels
# ---------------------------------------------------------------------------
URDU_LABELS = {"sacha": "سچا", "jhoota": "جھوٹا", "mashkook": "مشکوک"}
ENGLISH_LABELS = {"sacha": "True", "jhoota": "False", "mashkook": "Unverified"}
VERDICT_ICONS = {"sacha": "✔", "jhoota": "✗", "mashkook": "?"}
# ---------------------------------------------------------------------------
# Core processing
# ---------------------------------------------------------------------------
if _HAS_SPACES:
@spaces.GPU
def _gpu_startup():
"""Dummy function so Gradio 6.x detects a GPU-capable handler at startup."""
pass
def _resolve_path(file_data) -> str | None:
"""Extract a filesystem path from a Gradio FileData object or plain string."""
if isinstance(file_data, str):
return file_data
# Gradio 6.x FileData: object with .path or dict-like access
if hasattr(file_data, "path"):
return file_data.path
if isinstance(file_data, dict):
return file_data.get("path")
return None
def _process_media_inner(file_data) -> tuple[str, str]:
"""Ingest a media file, verify claims, return (verdict_box, reasoning_box)."""
if file_data is None:
return "کوئی فائل منتخب نہیں / No file selected.", ""
# Gradio 6.x passes a FileData object; extract the path string
file_path = _resolve_path(file_data)
if not file_path:
return "کوئی فائل منتخب نہیں / No file selected.", ""
ingestor = _get_ingestor()
agent = _get_agent()
report = ingestor.ingest(file_path)
text = report.get("combined_text", "")
if not text or not text.strip():
return "کوئی متن نکالا نہیں جا سکا / No text was extracted from the file.", ""
if report.get("metadata", {}).get("ocr_garbled"):
return (
"تصحیح OCR ناکام رہی / OCR failed to read this image properly.\n"
"براہ کرم واضح تصویر اپ لوڈ کریں / Please upload a clearer image."
), f"استخراج شدہ متن:\n{text[:300]}"
result = agent.run(text)
if not result.is_checkworthy:
return "کوئی قابلِ تصدیق دعویٰ نہیں / No checkworthy claim found.", (
f"استخراج شدہ متن:\n{text[:500]}"
)
verdict_box = _format_verdict(result)
reasoning_box = _format_reasoning(result)
return verdict_box, reasoning_box
def _process_text(text: str) -> tuple[str, str]:
"""Verify a pasted text claim, return (verdict_box, reasoning_box)."""
if not text or not text.strip():
return "براہ کرم متن لکھیں / Please enter some text.", ""
agent = _get_agent()
result = agent.run(text)
if not result.is_checkworthy:
return "کوئی قابلِ تصدیق دعویٰ نہیں / No checkworthy claim found.", ""
verdict_box = _format_verdict(result)
reasoning_box = _format_reasoning(result)
return verdict_box, reasoning_box
# Wrap _process_media_inner with @spaces.GPU on HF so UTRNet gets a GPU.
if _HAS_SPACES:
@spaces.GPU
def _process_media(file_data) -> tuple[str, str]:
return _process_media_inner(file_data)
else:
_process_media = _process_media_inner
def _format_verdict(result) -> str:
key = result.verdict.value
icon = VERDICT_ICONS[key]
urdu_label = URDU_LABELS[key]
eng_label = ENGLISH_LABELS[key]
lines = [
f"{icon} فیصلہ / Verdict: {urdu_label} ({eng_label})",
f" Confidence: {result.confidence:.0%}",
"",
f"دعویٰ / Claim:",
f" {result.claim_urdu}",
f" {result.claim_english}",
]
return "\n".join(lines)
def _format_reasoning(result) -> str:
parts = [
"وجوہات / Reasoning:",
"",
result.reasoning_urdu,
"",
result.reasoning_english,
]
if result.evidence:
parts.append("")
parts.append("شواہد / Sources:")
for item in result.evidence:
parts.append(f" [{item.source_domain}] {item.title}")
parts.append(f" {item.url}")
if item.snippet:
parts.append(f" {item.snippet[:200]}")
parts.append("")
return "\n".join(parts)
# ---------------------------------------------------------------------------
# Gradio UI
# ---------------------------------------------------------------------------
def build_ui() -> gr.Blocks:
with gr.Blocks(
title="Haqeeqat Check — Urdu Misinformation Detector",
) as demo:
gr.Markdown(
"# Uraan Techathon 2.0\n"
"# Haqeeqat Check: Urdu Misinformation Detector\n"
"### حقیقت چیک: اردو غلط معلومات کی جانچ پڑتال"
)
with gr.Tabs():
with gr.Tab("Image"):
img_input = gr.Image(label="تصویر اپ لوڈ کریں / Upload Image", type="filepath")
img_btn = gr.Button("Check / چیک کریں", variant="primary")
with gr.Tab("Audio"):
aud_input = gr.Audio(label="آڈیو اپ لوڈ کریں / Upload Audio", type="filepath")
aud_btn = gr.Button("Check / چیک کریں", variant="primary")
with gr.Tab("Video"):
vid_input = gr.Video(label="ویڈیو اپ لوڈ کریں / Upload Video")
vid_btn = gr.Button("Check / چیک کریں", variant="primary")
with gr.Tab("Paste Text"):
txt_input = gr.Textbox(
label="اردو متن لکھیں یا پیسٹ کریں / Enter or paste Urdu text",
lines=5,
)
txt_btn = gr.Button("Check / چیک کریں", variant="primary")
gr.Markdown("---")
verdict_output = gr.Textbox(
label="فیصلہ / Verdict",
lines=8,
interactive=False,
)
reasoning_output = gr.Textbox(
label="وجوہات و شواہد / Reasoning & Sources",
lines=14,
interactive=False,
)
img_btn.click(fn=_process_media, inputs=img_input, outputs=[verdict_output, reasoning_output])
aud_btn.click(fn=_process_media, inputs=aud_input, outputs=[verdict_output, reasoning_output])
vid_btn.click(fn=_process_media, inputs=vid_input, outputs=[verdict_output, reasoning_output])
txt_btn.click(fn=_process_text, inputs=txt_input, outputs=[verdict_output, reasoning_output])
return demo
if __name__ == "__main__":
demo = build_ui()
demo.launch(theme=gr.themes.Soft())