Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Domains/AI-ML/MiniProjects/factreal
Submodule factreal deleted from 5da0c7
16 changes: 16 additions & 0 deletions Domains/AI-ML/MiniProjects/factreal/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.git
.gitignore
__pycache__
*.pyc
.venv
.env
.vscode
.idea
backend/data/*.csv
backend/data/*.tsv
backend/data/*.json
backend/data/*.jsonl
backend/scripts/*.sh
backend/scripts/*.bat
backend/scripts/*.ps1
backend/postman
6 changes: 6 additions & 0 deletions Domains/AI-ML/MiniProjects/factreal/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

MODEL_BIAS=facebook/bart-large-mnli
MODEL_REASONING=google/flan-t5-base
THRESHOLD_BIAS=0.55
ENABLE_FACT_CHECK=false
# NEWS_API_KEY=your_news_api_key_here
33 changes: 33 additions & 0 deletions Domains/AI-ML/MiniProjects/factreal/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: CI

on:
push:
paths:
- 'k4niz/factreal/**'
pull_request:
paths:
- 'k4niz/factreal/**'

jobs:
test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: k4niz/factreal
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.13'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest

- name: Run tests
run: pytest -q
45 changes: 45 additions & 0 deletions Domains/AI-ML/MiniProjects/factreal/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
.venv/
env/
venv/
ENV/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/

# IDE/editor
.vscode/
.idea/

# OS
.DS_Store
Thumbs.db

# Project
.env
*.log
__pycache__/
.pytest_cache/
.venv/
env/
venv/
.env
*.pyc
*.pyo
*.pyd
.DS_Store
27 changes: 27 additions & 0 deletions Domains/AI-ML/MiniProjects/factreal/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Lightweight production-like image for FactReal
FROM python:3.13-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1 \
HF_HOME=/root/.cache/huggingface

WORKDIR /app

# System deps (optional; add git if models need it)
RUN apt-get update -y && apt-get install -y --no-install-recommends \
build-essential \
&& rm -rf /var/lib/apt/lists/*

# Install Python deps first for better cache
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

# Copy backend code
COPY backend ./backend

# Expose port
EXPOSE 8000

# Default command
CMD ["python", "-m", "uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8000"]
113 changes: 113 additions & 0 deletions Domains/AI-ML/MiniProjects/factreal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
**Contributor:** k4niz



FactReal — AI Backend for Bias/Misinformation Detection
=======================================================

FactReal is an AI-powered backend system that detects bias, misinformation, and propaganda in text (e.g., social posts, articles). It returns classifications with confidence scores and explainable reasoning, and optionally performs lightweight fact checking.

- Tech: FastAPI, Hugging Face Transformers
- Targets: Hacktoberfest-friendly, modular, easy to extend


Features
--------
- Bias detection: neutral, biased, misleading, propaganda
- Explainable reasoning: natural language explanation
- Optional fact verification: Wikipedia / NewsAPI (stubs included)
- Modular layers: models → services → controllers → routes

Project Structure
-----------------
```
backend/
models/
bias_model.py # Transformer zero-shot bias classifier (with offline fallback)
reasoning_model.py # Text-to-text reasoning generator (with offline fallback)
fact_checker.py # Optional fact check (Wikipedia/NewsAPI)
services/
preprocessing_service.py
classification_service.py
explainability_service.py
api_service.py
controllers/
classify_controller.py
explain_controller.py
routes/
classify_router.py
explain_router.py
utils/
logger.py
config.py
data/
sample_dataset.jsonl # Small sample data to try
scripts/
sample_requests.py # Example client calls
run_server.ps1 # Windows: start dev server
main.py # FastAPI app entry

requirements.txt # Python dependencies
README.md # You are here
```

Cleanup
-------
If you see stray files like `controllers.py` or `models.py` in this folder root, they are not used by the modular backend and can be safely deleted.

Quickstart
----------
1) Create and activate a virtual environment (recommended).

2) Install requirements:
```powershell
pip install -r requirements.txt
```

3) Run the API server (Windows PowerShell):
```powershell
./backend/scripts/run_server.ps1
```
This starts Uvicorn with auto-reload at http://127.0.0.1:8000.

4) Try example requests in a new terminal:
```powershell
python ./backend/scripts/sample_requests.py
```
Or use the interactive docs at:
- Swagger UI: http://127.0.0.1:8000/docs
- ReDoc: http://127.0.0.1:8000/redoc

Environment Configuration
-------------------------
Environment variables (optional) are loaded via `utils/config.py`:
- MODEL_BIAS (default: "facebook/bart-large-mnli")
- MODEL_REASONING (default: "google/flan-t5-base")
- THRESHOLD_BIAS (default: 0.55)
- ENABLE_FACT_CHECK (default: false)
- NEWS_API_KEY (optional)

Create a `.env` file next to `requirements.txt` if desired:
```
MODEL_BIAS=facebook/bart-large-mnli
MODEL_REASONING=google/flan-t5-base
THRESHOLD_BIAS=0.6
ENABLE_FACT_CHECK=true
NEWS_API_KEY=...
```

Hacktoberfest Contribution Guide
--------------------------------
- Good first issues: implement new models, improve heuristics, add datasets, expand fact-checkers
- Coding style: type hints, docstrings, small functions, tests where reasonable
- Folder-first design: add new models in `backend/models/`, new services in `backend/services/`, and wire via controllers/routes
- Please add comments to every function you create; keep public APIs stable

Data & Models
-------------
- The code uses Hugging Face pipelines. If models can’t be downloaded (e.g., offline), the code falls back to safe heuristic baselines so the API keeps working for demos and local development.
- To change models, set env vars or edit `utils/config.py`.

License
-------
This project follows the repository’s LICENSE.
1 change: 1 addition & 0 deletions Domains/AI-ML/MiniProjects/factreal/backend/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Backend package initializer for FactReal."""
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"""Controllers package for FastAPI request handling."""
"""Controllers for FactReal API."""
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Controllers for classification endpoints.

Defines request/response schemas close to HTTP layer and calls services.
"""
from __future__ import annotations

from pydantic import BaseModel, Field

from ..services.api_service import ApiService


class ClassifyRequest(BaseModel):
text: str = Field(..., description="Input text to analyze")


class ClassifyResponse(BaseModel):
label: str
confidence: float
scores: dict
flagged: bool
explanation: str
fact_check: dict | None = None


class ClassifyController:
def __init__(self, api: ApiService | None = None) -> None:
self.api = api or ApiService()

def classify(self, req: ClassifyRequest) -> ClassifyResponse:
analysis = self.api.analyze(req.text)
payload = analysis.to_json()
return ClassifyResponse(
label=payload["classification"]["label"],
confidence=payload["classification"]["confidence"],
scores=payload["classification"]["scores"],
flagged=payload["classification"]["flagged"],
explanation=payload["explanation"],
fact_check=payload.get("fact_check"),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Controllers for explanation endpoints."""
from __future__ import annotations

from pydantic import BaseModel, Field

from ..services.explainability_service import ExplainabilityService


class ExplainRequest(BaseModel):
text: str = Field(..., description="Input text to explain")
label: str = Field(..., description="Label to explain, e.g., biased")


class ExplainResponse(BaseModel):
explanation: str


class ExplainController:
def __init__(self, service: ExplainabilityService | None = None) -> None:
self.service = service or ExplainabilityService()

def explain(self, req: ExplainRequest) -> ExplainResponse:
res = self.service.explain(req.text, req.label)
return ExplainResponse(explanation=res.text)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{"text": "Elections are always rigged and the media hides the truth."}
{"text": "The sky is blue on a clear day."}
{"text": "Experts claim this vaccine is a hoax without any real evidence."}
32 changes: 32 additions & 0 deletions Domains/AI-ML/MiniProjects/factreal/backend/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""FastAPI application entry point for FactReal."""
from __future__ import annotations

from fastapi import FastAPI
from .controllers.classify_controller import (
ClassifyController,
ClassifyRequest,
ClassifyResponse,
)

from .routes.classify_router import router as classify_router
from .routes.explain_router import router as explain_router

app = FastAPI(title="FactReal", version="0.1.0")


@app.get("/")
def health() -> dict:
return {"status": "ok", "service": "FactReal"}


app.include_router(classify_router)
app.include_router(explain_router)


# Convenience: allow POST / to behave like /classify for ease of testing
_root_classify_controller = ClassifyController()


@app.post("/", response_model=ClassifyResponse)
def classify_root(req: ClassifyRequest) -> ClassifyResponse:
return _root_classify_controller.classify(req)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Model wrappers for FactReal."""
Loading