CoolFace
Apppublic

samikshabatra18/legal-document-analyzer

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
App README

Legal Document Intelligence Platform

An end-to-end Retrieval-Augmented Generation (RAG) system for legal contract analysis. Upload a contract (NDA, lease, vendor agreement) and ask questions, extract clauses, surface commercial risks, and compare terms across documents — every answer grounded in page/section citations from the source PDF.

Features

  • —Grounded Q&A with citations — answers cite (Page X, Section Y) for every claim and refuse when the answer isn't in the document (hallucination control).
  • —Hybrid retrieval + reranking — semantic (vector) + BM25 keyword search, refined by a cross-encoder so exact references ("Section 5") and conceptual queries both work.
  • —Clause extraction — auto-tags every chunk into a clause taxonomy (Termination, Liability, Payment, Renewal, …) in one batched LLM call.
  • —Risk detection — flags commercially risky clauses (unlimited liability, one-sided termination, silent auto-renewal) with severity ratings, from a config-file rubric.
  • —Multi-document comparison — diffs key terms across contracts in a cited table.
  • —Evaluation harness — labeled eval set + precision@k / citation-accuracy scoring to catch regressions.

Retrieval quality (eval set, 24 items)

MetricScore
hit@51.000
precision@50.950
MRR1.000

python -m evaluation.run_eval (retrieval metrics are local — no LLM/API cost).

Architecture

PDF upload
  → parse (pdfplumber, pypdf fallback) + clean headers/footers
  → page-aware, section-tagged chunking
  → embed (sentence-transformers BGE-small) → FAISS index
  → hybrid retrieve (vector + BM25) → cross-encoder rerank
  → grounded prompt → LLM → answer + page/section citations

Clause extraction, the risk engine, and multi-document comparison run on the same ingested/indexed corpus.

Tech stack

LayerChoice
BackendPython + FastAPI
FrontendStreamlit
RAG frameworkLangChain
Embeddingssentence-transformers (BAAI/bge-small-en-v1.5)
Vector DBFAISS
Rerankercross-encoder (ms-marco-MiniLM-L-6-v2)
Keyword searchBM25 (rank-bm25)
LLMGoogle Gemini (swappable behind call_llm())

Project structure

backend/
  app.py                         # FastAPI entrypoint
  config.py                      # settings loaded from .env
  loaders/pdf_loader.py          # PDF -> clean page text
  chunking/chunker.py            # page text -> section-tagged chunks
  embeddings/embedding_model.py  # text -> vectors
  vector_db/faiss_manager.py     # FAISS index + metadata
  retrieval/retriever.py         # vector + BM25 hybrid search
  reranker/cross_encoder.py      # cross-encoder rerank
  qa/                            # LLM interface, prompt, RAG pipeline
  clause_extraction/extractor.py # clause classification
  risk_analysis/                 # risk rubric (json) + analyzer
  comparison/comparator.py       # multi-document comparison
  routes/                        # FastAPI routers
frontend/app.py                  # Streamlit UI
evaluation/                      # eval set + scoring script
data/                            # sample contracts
tests/                           # pytest (39 tests)

API

EndpointPurpose
GET /healthLiveness probe
POST /documents/uploadIngest a PDF (parse → chunk → embed → classify)
POST /searchHybrid search over a document's chunks
POST /qa/askGrounded, cited answer to a question
GET /documents/{id}/clausesClauses by category
GET /documents/{id}/risksSeverity-rated risk report
POST /compareSide-by-side comparison of multiple documents

Setup

bash
python -m venv venv
venv\Scripts\activate          # Windows  (use: source venv/bin/activate on macOS/Linux)
pip install -r requirements.txt

cp .env.example .env           # then add your GEMINI_API_KEY

Get a free Gemini key at <https://aistudio.google.com/apikey>. The key is read from .env locally (gitignored) or from the environment in deployment — never committed.

Run

bash
# Backend (terminal 1)
uvicorn backend.app:app --reload --port 8020

# Frontend (terminal 2)
streamlit run frontend/app.py

Open <http://localhost:8501> and upload a contract. (The backend runs on 8020 here to avoid a port conflict; set API_BASE if you use a different port.)

Tests & evaluation

bash
pytest -q                                     # 39 tests (LLM-dependent paths mocked)
python -m evaluation.run_eval                 # retrieval metrics (no API cost)
python -m evaluation.run_eval --with-answers  # + citation accuracy (uses the LLM)

Deployment

Ships as a single container (see Dockerfile): FastAPI internally on :8000, Streamlit publicly on :7860. On Hugging Face Spaces (Docker SDK), set GEMINI_API_KEY as a Space secret — it is never stored in the repo.

Notes

  • —The LLM sits behind a single call_llm() interface, so Gemini can be swapped for OpenAI or a local Ollama model without touching the pipeline.
  • —Clause extraction and risk detection fall back to keyword heuristics if no LLM key is configured, so the app still runs (Q&A requires the LLM).
  • —data/sample_vendor_agreement.pdf and ..._b.pdf are synthetic contracts for testing/demo (regenerate with the scripts in data/).