Loading repository data…
Loading repository data…
Donovan-Nudrak / repository
Production-oriented e-commerce REST API featuring JWT authentication, Redis caching, PostgreSQL, pgvector semantic search, and Gemini-powered RAG.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
A well-structured, fully tested e-commerce REST API with semantic search powered by RAG (Retrieval-Augmented Generation).
history in the request/response/media| Layer | Technology | Version | Purpose |
|---|
| API framework | FastAPI | 0.136.3 | HTTP API, OpenAPI docs, dependency injection |
| ASGI server | Uvicorn | 0.48.0 | Production/dev server |
| Validation | Pydantic | 2.13.4 | Request/response schemas |
| Configuration | pydantic-settings | 2.14.1 | Environment-based settings |
| ORM | SQLAlchemy | 2.0.50 | Database models and sessions |
| Migrations | Alembic | 1.18.4 | Schema migrations |
| Database | PostgreSQL | 15 | Primary data store |
| Vector search | pgvector | 0.3.6 | Cosine similarity on product embeddings |
| Cache / sessions | Redis (server 7 / client) | 8.0.0 | Refresh tokens and password-reset tokens |
| Auth | python-jose + bcrypt | 3.5.0 / 5.0.0 | JWT signing and password hashing |
| Rate limiting | SlowAPI | 0.1.9 | Per-IP limits on auth routes |
| AI / RAG | google-generativeai | 0.7.2 | Embeddings and answer generation (Gemini) |
| DB driver | psycopg2-binary | 2.9.12 | PostgreSQL connectivity |
| Containers | Docker Compose | 2.x | Local multi-service stack |
| Testing | pytest, pytest-cov, pytest-asyncio | 9.0.3 / 7.1.0 / 1.4.0 | Unit and integration tests |
| Test doubles | fakeredis | 2.36.0 | In-memory Redis for standard test suite |
The application follows a layered design: Router → Service → Repository → Model, with Pydantic schemas at API boundaries.
HTTP Client
│
▼
FastAPI (CORS middleware, SlowAPI rate limiter)
│
▼
API Router (/api/v1/{module})
│
▼
Service (business logic)
│
▼
Repository (SQLAlchemy queries)
│
├──► PostgreSQL (persistent data, pgvector)
└──► Redis (refresh / reset tokens)
POST /api/v1/rag/query { query, history[] }
│
▼
Embed query (Gemini, task_type=retrieval_query)
│
▼
pgvector search: score = 1 - (embedding <=> query_vector)
│ candidates = RAG_TOP_K × RAG_CANDIDATE_MULTIPLIER
│ filter: score >= RAG_SIMILARITY_THRESHOLD
│ sort desc, take RAG_TOP_K
▼
Build product context (enriched documents: category stats, discounts, stock)
│
▼
Build prompt: SYSTEM + Previous conversation (last 6 msgs) + Context + Question
│
▼
Generate answer (Gemini)
│
▼
RAGResponse { answer, sources[], query, history[] }
Inactive products and zero-stock items are excluded from vector retrieval. The client stores history and sends it on the next turn (stateless server; no Redis session for chat).
GEMINI_API_KEY) for RAG featuresgit clone https://github.com/Donovan-Nudrak/E-Commerce_API_RAG.git
cd E-Commerce_API_RAG
cp .env.example .env
Edit .env and set at minimum:
SECRET_KEY — long random string for JWT signing. In production (DEBUG=false), use a secure random value (at least 32 characters). The .env.example placeholder is rejected at startup and will prevent the API from running.POSTGRES_PASSWORD — database passwordGEMINI_API_KEY — your Gemini API keyUse RAG_EMBEDDING_MODEL=models/gemini-embedding-001 (required format for the Gemini embedding API).
docker compose up -d --build
docker compose exec api alembic upgrade head
docker compose exec api python -m app.database.seed
| Service | URL |
|---|---|
| API base | http://localhost:8000 |
| Health check | http://localhost:8000/ |
| Swagger UI | http://localhost:8000/docs |
| ReDoc | http://localhost:8000/redoc |
| Media (uploads) | http://localhost:8000/media |
Email: admin@ecommerce.com
Password: admin1234
These credentials are for local development only. Change them before any public deployment.
TOKEN=$(curl -s -X POST http://localhost:8000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@ecommerce.com","password":"admin1234"}' \
| python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
curl -s -X POST http://localhost:8000/api/v1/rag/index \
-H "Authorization: Bearer $TOKEN"
curl -s -X POST http://localhost:8000/api/v1/rag/index/categories \
-H "Authorization: Bearer $TOKEN"
The RAG module lets customers ask natural-language questions about the catalog. Answers are grounded in retrieved product data; the model is instructed not to invent products or prices.
products.embedding (768 dimensions) via pgvector<=>); similarity score = 1 - distanceRAG_SIMILARITY_THRESHOLDhistory: [{role, content}, ...]; server returns updated history (stateless; no server-side chat session) ┌─────────────────────────────┐
query embedding │ SELECT top (K × multiplier)│
───────────►│ active, stock > 0, │
│ embedding NOT NULL │
└─────────────┬───────────────┘
│
score = 1 - cosine_distance
│
┌─────────────▼───────────────┐
│ score >= THRESHOLD ? │
│ sort by score DESC │
│ take RAG_TOP_K │
└─────────────┬───────────────┘
│
┌─────────────▼───────────────┐
│ Build context + prompt │
│ Generate with Gemini │
└─────────────────────────────┘
| Variable | Description | Default |
|---|---|---|
RAG_TOP_K | Max products in context and sources | 5 |
RAG_SIMILARITY_THRESHOLD | Minimum similarity score (0–1) | 0.5 |
RAG_CANDIDATE_MULTIPLIER | Initial retrieval pool size = TOP_K × multiplier | 3 |
RAG_EMBEDDING_DIM | Vector dimensions (must match model) | 768 |
RAG_EMBEDDING_MODEL | Gemini embedding model | models/gemini-embedding-001 |
RAG_GENERATION_MODEL | Gemini chat model | gemini-2.5-flash |
POST /api/v1/rag/index (admin) — embeds all active products from enriched text documentsPOST /api/v1/rag/index/categories (admin) — embeds per-category summaries and blends into product vectorsExample index responses:
{ "indexed": 6, "errors": 0, "message": "Reindexed active products." }
{ "categories_processed": 5, "products_updated": 6, "errors": 0 }
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/v1/rag/query | Public | Semantic Q&A; supports multi-turn history |
| POST | /api/v1/rag/index | Admin (Bearer) | Reindex product embeddings |
| POST | /api/v1/rag/index/categories | Admin (Bearer) | Apply category context blend to embeddings |
| PUT | /api/v1/rag/products/{product_id}/reindex | Admin (Bearer) | Reindex single product embedding |
Turn 1 — initial question:
curl -s -X POST http://localhost:8000/api/v1/rag/query \
-H "Content-Type: application/json" \
-d '{"query": "what affordable products do you have?", "history": []}'
Example response (abbreviated structure):
{
"answer": "We have several affordable options:\n\n* **Cotton T-Shirt**: $12.50\n* **Organic Coffee 1kg**: $18.90 (24% off)\n* **Bluetooth Headphones**: $19.99 (33% off)",
"sources": [
{
"id": 3,
"name": "Cotton T-Shirt",
"price": "12.50",
"discount_price": null,
"stock": 200,
"category_name": "Clothing",
"similarity_score": 0.745
},
{
"id": 4,
"name": "Organic Coffe 1kg",
"price": "24.90",
"discount_price": "18.90",
"stock": 80,
"category_name": "Food & Beverages",
"similarity_score": 0.741
}
],
"query": "what affordable products do you have?",
"history": [
{ "role": "user", "content": "what affordable products do you have?" },
{ "role": "assistant", "content": "We have several affordable options:..." }
]
}
Turn 2 — follow-up using history from turn 1:
curl -s -X POST http://localhost:8000/api/v1/rag/query \
-H "Content-Type: application/json" \
-d '{
"query": "do any of those have a discount?",
"history": [
{"role": "user", "content": "what affordable products do you have?"},
{"role": "assistant", "content": "We have several affordable options:..."}
]
}'
The assistant can answer in context (e.g. listing discounted items mentioned earlier). history grows by two messages per turn (user + assistant). Only the last 6 messages are injected into the prompt.
RAGResponse fields| Field | Type | Description |
|---|---|---|
answer | string | Natural-language reply from Gemini |
sources | array | Retrieved products with similarity_score (descending) |
query | string | Current user question |
history | array | Full conversation state for the client to persist |
Each sourc