LiteSpec
LiteSpec is a versioned specification for building business applications with AI coding agents: architecture, code, records, and tests, in a form agents can...
A 6-module NLP research platform for document preprocessing, entity extraction, ambiguity resolution, QA, and summarization.
Developer toolsTypeScript · PythonGitHub @MKD2004OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Context-Aware Document Intelligence System
Translation pending
Loading the full README.
Read the full README ↗
A document intelligence platform that runs a six-module NLP pipeline over any PDF, DOCX or pasted text — preprocessing, sentence embeddings, named entity recognition, ambiguity resolution, extractive question answering and abstractive summarization — and walks you through each stage in an interactive Next.js dashboard.
flowchart LR
subgraph Client ["Frontend — Vercel"]
UI["Next.js 16 / React 19<br/>Tailwind / Framer Motion"]
end
subgraph ML ["ML Backend — HuggingFace Spaces (Docker)"]
API["FastAPI — api_server.py"]
subgraph Models ["NLP Models"]
SPACY["spaCy en_core_web_sm<br/>Tokens · POS · Deps · Sents"]
MiniLM["all-MiniLM-L6-v2<br/>384-d Embeddings"]
BERT["dslim/bert-base-NER<br/>Entity Recognition"]
RoBERTa["roberta-base-squad2<br/>Extractive QA"]
BART["distilbart-cnn-12-6<br/>Summarization"]
end
end
UI -- "POST /api/extract" --> API
UI -- "POST /api/process" --> API
UI -- "POST /api/qa-ask" --> API
API --> SPACY
API --> MiniLM
API --> BERT
API --> RoBERTa
API --> BART
style Client fill:#0d1117,stroke:#22d3ee,color:#e2e8f0
style ML fill:#0d1117,stroke:#34d399,color:#e2e8f0
style Models fill:#111827,stroke:#475569,color:#e2e8f0
There is no separate API gateway — the frontend calls FastAPI directly, with CORS
restricted to the origins listed in api_server.py.
.pdf / .docx / .txt file (or pastes text, or picks
a bundled sample) on /launchPOST /api/extract parses .pdf / .docx files with pypdf /
python-docx and returns plain text (.txt files are read directly in the browser)POST /api/process runs all six modules in one call and returns a single
JSON payloadlocalStorage and rendered across six pages under
/pipeline/*, one per modulePOST /api/qa-ask answers arbitrary follow-up questions
against the same document| # | Module | Model | What it produces |
|---|---|---|---|
| 1 | Preprocessing | spaCy en_core_web_sm | Tokens with lemma/POS/dependency, sentence split, corpus stats |
| 2 | Embeddings | all-MiniLM-L6-v2 | 384-d sentence vectors, cosine similarity matrix, most-similar pairs |
| 3 | NER + IE | dslim/bert-base-NER + spaCy | Person/Org/Location/Misc entities (BERT) plus Date and numeric entities (spaCy — the "Money" bucket also holds cardinals and percentages), subject-verb-object relations |
| 4 | Ambiguity | MiniLM + spaCy parse | PP-attachment and anaphoric ambiguities (at most one per sentence), each with a resolved candidate |
| 5 | QA Engine | deepset/roberta-base-squad2 | Extractive answer spans with character offsets and confidence |
| 6 | Summary | sshleifer/distilbart-cnn-12-6 | Abstractive executive summary, key sentences, date-anchored timeline |
Extractive QA returns a span of your document — it never generates text, so it cannot hallucinate. Getting a correct span requires more than an argmax:
end >= start, and are
capped at 40 tokens.[CLS] position. A span is only returned if
it outscores that null; otherwise the answer is empty. Confidence is the sigmoid of that
margin.DistilBART accepts 1024 tokens (roughly 750 words) and silently truncates anything longer, so every input it sees is sized to fit. Documents up to 400 words are summarized in one pass. Longer documents are split into evenly-sized, sentence-aligned chunks of ~512 tokens (sentences with no punctuation, common in PDF extraction, are broken into word windows). Every sentence goes into exactly one chunk, so the whole document is covered. Each chunk is summarized, near-duplicate sentences are dropped, and the partials are condensed into the executive summary — recursively, if the partials themselves exceed 1024 tokens. There is no cap on the number of chunks, so summarization time grows linearly with document length (a 6,000-word document takes ~50 s on a CPU laptop).
All five model loaders are wrapped in @lru_cache(maxsize=1), so weights load once per
worker process and are reused. benchmark.py measures what that buys:
python benchmark.py
One run on a CPU-only Windows laptop with weights already in ~/.cache/huggingface
(python benchmark.py 100 400):
| Document | Warm request (inference) | Cold request (load + inference) | Ratio |
|---|---|---|---|
| 100 words | 3.3 s | 38.8 s | 11.8× |
| 400 words | 11.3 s | 46.8 s | 4.2× |
Absolute numbers vary a lot between machines and runs (the figures previously quoted here were 7.9 s / 16.8 s warm with ~23 s load), so treat them as illustrative. Two things to know about the method:
lru_cache lookups together
take tens of microseconds.What holds across runs is the shape: the cold/warm ratio is highest on short documents, where load dominates, and falls as inference grows — it is a property of the document, not a single headline number.
A true cold start in deployment is larger than any of these, because the Dockerfile deliberately does not pre-download weights (it blew past the HF Spaces build timeout), so the first request after a container wake also pays a ~2.1 GB network download. That cost is bandwidth-dependent and not reproducible as a fixed figure, which is why it is not quoted here.
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
python -m spacy download en_core_web_sm
uvicorn api_server:app --host 0.0.0.0 --port 8000 --reload
Models download from HuggingFace on first use (~2.1 GB total, most of it DistilBART) and are cached afterwards.
cd client
npm install
npm run dev
Open http://localhost:3000.
| Variable | Service | Purpose |
|---|---|---|
NEXT_PUBLIC_API_URL | Frontend | FastAPI base URL (default http://localhost:8000) |
FRONTEND_URL | Backend | Deployed frontend origin, appended to the CORS whitelist |
QA_MODEL | Backend | Override the QA model (default deepset/roberta-base-squad2) |
SUM_MODEL | Backend | Override the summarization model |
NER_MODEL | Backend | Override the NER model |
EMB_MODEL | Backend | Override the embedding model |
| Endpoint | Method | Body | Returns |
|---|---|---|---|
/health | GET | — | Service status |
/api/extract | POST | multipart/form-data file | { text, chars, words } |
/api/process | POST | { text } | All six module results |
/api/qa-ask | POST | { text, question } | { question, answer, confidence, start, end } |
cadis_project/
├── api_server.py # FastAPI backend — all six modules
├── Dockerfile # HuggingFace Spaces image (CPU torch; models fetched on first use)
├── requirements.txt # Python dependencies
├── benchmark.py # Cold-vs-warm latency measurement for model caching
├── hf_README.md # HF Space card metadata
├── client/ # Next.js 16 frontend
│ ├── app/
│ │ ├── page.tsx # Landing page
│ │ ├── launch/ # Upload / paste / sample + pipeline runner
│ │ └── pipeline/ # One page per module
│ ├── components/ # Landing sections + shadcn/ui primitives
│ └── lib/utils.ts # Tailwind className helper (cn)
└── data/ # Sample datasets
This project is for academic and research purposes.