AI-powered medical misinformation detector. Users submit text or a URL; a LangGraph multi-agent pipeline (Extractor → Translator → Investigator → Health Expert) backed by Llama (via Ollama) and a fine-tuned BioBERT classifier returns a verdict (verdadera/falsa), confidence score, supporting biomedical sources, and medical explanation. The Investigator cross-checks each claim against Europe PMC literature, and the verdict's confidence is attenuated when no supporting evidence is found. Results are persisted in PostgreSQL and shown in a Next.js dashboard.
- Backend — FastAPI (web) + arq worker, LangGraph, Ollama, Transformers (BioBERT), Europe PMC evidence retrieval, psycopg3
- Frontend — Next.js 16 (App Router), React 19, Clerk, SWR, Tailwind v4
- Data — PostgreSQL, Redis (arq job queue)
- ML — BioBERT fine-tuned on PUBHEALTH
Analysis is asynchronous: POST /analysis returns immediately with a pending
id, an arq worker runs the pipeline, and the frontend polls GET /analysis/{id}
until the verdict is ready.
backend/
app/ FastAPI service (routes, agents, db, schemas)
ml/ BioBERT training and evaluation
tests/ App test suite
frontend/
src/ Next.js App Router
- Python 3.11+ and
uv - Node.js 22+ and
pnpm9+ - Ollama running locally on
:11434with the modelsllama3,llama3.2, andtranslategemmapulled - A PostgreSQL database (the Docker Compose stack provides one)
- A Redis instance on
:6379(job queue for the analysis worker) - A Clerk application for auth
cp .env.example .env # fill in Clerk values
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env
docker compose up --build
docker compose exec ollama ollama pull llama3
docker compose exec ollama ollama pull llama3.2
docker compose exec ollama ollama pull translategemmaFrontend at http://localhost:3000, backend at http://localhost:8000. The BioBERT weights under backend/models/bert_classifier/ are mounted into the backend container read-only.
Copy the example env files and fill in real values:
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.envBackend needs at minimum: DATABASE_URL, REDIS_URL, CLERK_JWKS_URL, CLERK_AUDIENCE, CORS_ALLOWED_ORIGINS, OLLAMA_BASE_URL.
Frontend needs: NEXT_PUBLIC_API_URL, NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY.
cd backend
uv sync --frozen # install serving + api deps
uv sync --frozen --extra ml # add the ML stack (only if training/evaluating)
uv run python -m app.main # web API at http://localhost:8000
uv run python -m app.worker # analysis worker (separate terminal; needs Redis + Ollama)cd frontend
pnpm install
pnpm dev # http://localhost:3000ollama pull llama3
ollama pull llama3.2
ollama pull translategemmaThe detector loads weights from backend/models/bert_classifier/. Either copy a pre-trained checkpoint there or run the training pipeline:
cd backend
uv run python -m ml.training.trainuv run pytest tests --cov=app --cov-fail-under=80 # app tests
uv run pytest ml/tests --cov=ml --cov-fail-under=80 # ML tests
uv run ruff check app ml tests # lint
uv run ruff format app ml tests # format
uv run mypy # type-checkpnpm lint
pnpm test
pnpm build
pnpm generate:api-types # regenerate src/types/api.d.ts (backend must be running)- After changing a backend Pydantic schema, regenerate the frontend types with
pnpm generate:api-types. Never editfrontend/src/types/api.d.tsby hand. - The database schema lives in
backend/db/init.sql, applied once to a fresh database (mounted into the Postgres container'sdocker-entrypoint-initdb.d). There is no migration framework yet — pre-launch, recreate the volume (docker compose down -v && docker compose up) to pick up schema changes.
MIT — see LICENSE.