A full-stack NLP web application that measures the semantic similarity between two sentences using Sentence-BERT (all-MiniLM-L6-v2) and cosine similarity. Built with FastAPI (backend) and Vanilla HTML/CSS/JS (frontend).
- What is Semantic Similarity?
- How Pretrained Embeddings Work
- How the Model is Used
- Project Structure
- How to Run Locally
- π³ Run with Docker
- API Reference
- Score Interpretation
- Technologies Used
Semantic similarity is the measure of how alike two pieces of text are in meaning, not just in the words they use.
For example:
| Sentence 1 | Sentence 2 | Similarity |
|---|---|---|
| "The dog barked loudly." | "The canine made a loud sound." | High β same meaning, different words |
| "I love pizza." | "The stock market crashed." | Low β completely unrelated topics |
Traditional keyword-based methods (like counting shared words) fail to capture this nuance. Deep learning models solve this by learning rich semantic representations of language.
A word/sentence embedding is a dense numerical vector (array of numbers) that represents the meaning of text in a mathematical space. The key idea is:
"Similar meanings β Similar vectors"
- A large language model (like BERT) is trained on billions of sentences from the Internet.
- During training, the model learns to place semantically related sentences close together in a high-dimensional vector space.
- After training, we can encode any new sentence into this space without retraining.
- SBERT is a modification of the original BERT model, fine-tuned using Siamese networks to produce meaningful sentence-level embeddings.
- The model used here β
all-MiniLM-L6-v2β maps sentences to 384-dimensional vectors. - It is compact, fast, and achieves excellent performance on semantic textual similarity (STS) benchmarks.
User Input (2 sentences)
β
βΌ
[FastAPI Backend]
β
βΌ
SentenceTransformer.encode(sentence1) β Vector1 (384 dims)
SentenceTransformer.encode(sentence2) β Vector2 (384 dims)
β
βΌ
cosine_similarity(Vector1, Vector2)
β
βΌ
Score β [0.0, 1.0]
β
βΌ
Interpretation + JSON Response
β
βΌ
[Frontend displays Result]
cosine_similarity(A, B) = (A Β· B) / (||A|| Γ ||B||)
- A value of 1.0 means the vectors point in the exact same direction β identical meaning.
- A value of 0.0 means the vectors are perpendicular β completely unrelated.
nlp project/
β
βββ app/
β βββ __init__.py # Marks 'app' as a Python package
β βββ main.py # FastAPI app setup, static files, template serving
β βββ model.py # Loads the SentenceTransformer model (once)
β βββ similarity.py # Core logic: encode sentences, compute cosine similarity
β βββ routes.py # API route definitions (/similarity endpoint)
β
βββ static/
β βββ style.css # CSS: dark glassmorphism theme, animations
β
βββ templates/
β βββ index.html # Frontend: HTML + Vanilla JS (uses fetch API)
β
βββ Dockerfile # Docker image definition
βββ .dockerignore # Files excluded from the Docker build context
βββ requirements.txt # Python package dependencies
βββ run.bat # One-click startup script (Windows)
βββ README.md # This file
- Python 3.9 or higher
pippackage manager
If you cloned from a repository:
git clone <your-repo-url>
cd "nlp project"Or navigate to the project directory directly.
# Windows
python -m venv venv
venv\Scripts\activate
# macOS / Linux
python3 -m venv venv
source venv/bin/activatepip install -r requirements.txt
β οΈ Note: The first install will download theall-MiniLM-L6-v2model (~90 MB) automatically from Hugging Face. Ensure you have an internet connection.
π‘ For CPU-only PyTorch (smaller download):
pip install torch --index-url https://download.pytorch.org/whl/cpu pip install -r requirements.txt
Windows (one-click script):
.\run.batWindows / Linux / macOS (manual):
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reloadNavigate to: http://localhost:8000
The interactive API documentation (Swagger UI) is also available at:
http://localhost:8000/docs
Docker lets you run the app in an isolated container β no Python installation or virtual environment needed.
- Docker Desktop installed and running.
docker build -t nlp-similarity-app .
β οΈ Note: The first build will download theall-MiniLM-L6-v2model (~90 MB) from Hugging Face inside the container. Ensure you have an internet connection.
docker run -p 8000:8000 nlp-similarity-appThis maps port 8000 on your machine to port 8000 inside the container.
Navigate to: http://localhost:8000
π‘ Tip: To run the container in the background (detached mode), use:
docker run -d -p 8000:8000 --name nlp-app nlp-similarity-appStop it later with:
docker stop nlp-app
| File | Purpose |
|---|---|
Dockerfile |
Defines the image: Python 3.12-slim base, installs deps, copies code, starts Uvicorn |
.dockerignore |
Excludes .venv/, __pycache__/, model binaries, and .git from the build context |
Computes the semantic similarity between two sentences.
Request Body (JSON):
{
"sentence1": "The cat sat on the mat.",
"sentence2": "A cat was resting on a rug."
}Response Body (JSON):
{
"score": 0.8731,
"interpretation": "Highly Similar",
"sentence1": "The cat sat on the mat.",
"sentence2": "A cat was resting on a rug."
}Example using curl:
curl -X POST http://localhost:8000/similarity \
-H "Content-Type: application/json" \
-d '{"sentence1": "I love machine learning", "sentence2": "I enjoy deep learning"}'| Score Range | Label | Meaning |
|---|---|---|
| 0.8 β 1.0 | π’ Highly Similar | Sentences convey the same or very similar meaning |
| 0.5 β 0.8 | π‘ Moderately Similar | Some overlap in meaning or topic |
| 0.0 β 0.5 | π΄ Not Similar | Sentences are largely unrelated |
| Layer | Technology | Purpose |
|---|---|---|
| Backend | FastAPI | REST API framework |
| Server | Uvicorn | ASGI server |
| NLP Model | Sentence Transformers | Sentence embeddings |
| Pretrained Model | all-MiniLM-L6-v2 |
384-dim dense vectors |
| Similarity Metric | scikit-learn | Cosine similarity |
| Templating | Jinja2 | HTML rendering |
| Frontend | HTML5 + CSS3 + Vanilla JS | User interface |
| Validation | Pydantic | Request/response schemas |
| Containerization | Docker | Portable, dependency-free deployment |
This project is designed to be beginner-friendly:
- Every file is heavily commented for clarity.
- The model is loaded only once at startup (not per request), making it efficient.
- The frontend communicates with the backend via the
fetch()API, demonstrating how modern SPAs work without a page reload. - The cosine similarity is computed using scikit-learn, which is a standard, well-tested library.
Built with β€οΈ using Python, FastAPI, and Sentence-BERT.