Skip to main content

Plug-in recommendation engine router for FastAPI

Project description

SearchRec

An e-commerce recommendation engine built on item-item collaborative filtering. Tracks user click sessions, learns what gets browsed together, and serves "you may also like" recommendations — with an admin dashboard to visualize the model.

Install into any FastAPI app in under a minute.

Install

pip install git+https://github.com/dariu5-dev/searchrec.git

Integration

from fastapi import FastAPI
from searchrec import create_router, SearchRec, searchrec_lifespan
from contextlib import asynccontextmanager

@asynccontextmanager
async def lifespan(app):
    async with searchrec_lifespan("./rec.db"):
        yield

app = FastAPI(lifespan=lifespan)
app.include_router(
    create_router(db_path="./rec.db", frontend_prefix="/rec"),
    prefix="/rec",
)

Then push your product catalogue once (e.g. at startup or via a management command):

rec = SearchRec(db_path="./rec.db")
await rec.sync_products([
    {"item_id": "shirt_001", "name": "Blue Tee", "category": "Clothing", "price": 29.99},
    {"item_id": "shoe_001",  "name": "Runner X",  "category": "Shoes",    "price": 89.99},
    # ...
])

After users have browsed the store, train the model:

POST /rec/api/retrain

Then recommendations are live:

GET /rec/api/recommend/shirt_001

frontend_prefix must match prefix=

The bundled frontend injects window.REC_BASE via a /config.js endpoint so all API calls resolve correctly when the router is mounted at a sub-path. The value of frontend_prefix must be identical to the prefix= argument you pass to include_router.

# Mounted at /rec — both must say "/rec"
app.include_router(create_router(frontend_prefix="/rec"), prefix="/rec")

# Mounted at root — omit both (default is "")
app.include_router(create_router())

Composable lifespan

If your app already has a lifespan, compose with searchrec_lifespan:

from searchrec import searchrec_lifespan

@asynccontextmanager
async def lifespan(app):
    async with searchrec_lifespan("./rec.db"):
        # your own startup work here
        yield
        # your own shutdown work here

Alternatively, create_router registers a @router.on_event("startup") handler as a fallback for apps that don't use a lifespan.

How it works

Every time a user clicks items in the same session, those items get a +1 in a co-click matrix. After enough sessions, cosine similarity is computed over the matrix to produce ranked recommendations. Similarity is cached to a database so serving is just a lookup — no ML at request time.

User clicks → /api/track (batched)
                  ↓
           click_events table
                  ↓
        POST /api/retrain (offline)
        load sessions → co-click matrix → cosine similarity → cache
                  ↓
        GET /api/recommend/{item_id} → DB lookup → top-N items

Configuration

Pass keyword arguments to create_router, or build a SearchRecConfig object:

from searchrec import create_router, SearchRecConfig

config = SearchRecConfig(
    db_path="./rec.db",
    min_sessions_to_retrain=10,  # minimum sessions before retrain proceeds
    min_coclick=2,               # minimum co-clicks for a pair to count
    top_n=10,                    # recommendations cached per item
    recommend_limit_default=10,  # default ?limit= on /api/recommend
    recommend_limit_max=50,      # maximum ?limit= allowed
    serve_frontend=True,         # set False to disable bundled UI routes
    frontend_prefix="/rec",      # must match prefix= in include_router
)

app.include_router(create_router(config=config), prefix="/rec")

API

Method Endpoint Description
GET /health Health check
POST /api/track Ingest a batch of click events (max 100)
POST /api/retrain Run the full recommendation pipeline
GET /api/recommend/{item_id} Top similar items for an item
PUT/POST /api/items Upsert a batch of products
DELETE /api/items/{item_id} Remove a product
GET /api/items/search?q= Search the product catalogue
GET /api/items/{item_id} Single item detail
GET /api/admin/stats Summary stats (clicks, coverage, avg score)
GET /api/admin/clicks/top Top items by click count
GET /api/admin/clicks/timeseries Daily click volume (last N days)
GET /api/admin/matrix Co-click matrix for top N items
GET /api/admin/export Download all recommendations as JSON
GET /api/admin/export/csv Download all recommendations as CSV

Bundled UI

When serve_frontend=True (the default), the router also serves:

Route Description
/ Store — search products, click to see recommendations
/admin Admin dashboard
/style.css Shared stylesheet
/tracker.js Click event tracker (auto-loaded by the store UI)
/config.js Injects window.REC_BASE for correct API prefixing

Admin dashboard

  • Stats — total clicks, recommendation coverage, avg similarity score, last retrain time
  • Click volume — 14-day line chart
  • Co-click matrix — heatmap of the top 20 most-clicked items, hover for exact counts
  • Top items — horizontal bar chart ranked by click count
  • Item inspector — search any product and inspect its recommendations with similarity scores

Stack

Layer Tech
Backend Python · FastAPI · aiosqlite
ML numpy · scikit-learn (cosine similarity)
Database SQLite (WAL mode)
Frontend Vanilla JS · HTML/CSS
Charts Chart.js

Demo app

ecommerce-rec/ contains a standalone demo with a seed script to populate sample products and click sessions:

cd ecommerce-rec/backend
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
python seed.py
uvicorn main:app --reload

Roadmap

  • Phase 2 — Word2Vec embeddings on click sequences + FAISS approximate nearest-neighbour search
  • Nightly automated retrain (cron)
  • User authentication on the admin dashboard

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

searchrec-0.1.0.tar.gz (28.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

searchrec-0.1.0-py3-none-any.whl (30.2 kB view details)

Uploaded Python 3

File details

Details for the file searchrec-0.1.0.tar.gz.

File metadata

  • Download URL: searchrec-0.1.0.tar.gz
  • Upload date:
  • Size: 28.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for searchrec-0.1.0.tar.gz
Algorithm Hash digest
SHA256 270f350864822a2f952a7b38e6ce6bf7259d915155d5b3d1c1cc9cb064b2c8f6
MD5 d6f253d320da731cf1bf711c2916221b
BLAKE2b-256 bf45772fd813924343926cb43dd2e8c2edbb142e0c0c7d5bbd40b6d3f5363b34

See more details on using hashes here.

File details

Details for the file searchrec-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: searchrec-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 30.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for searchrec-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2fe181fe185b0706bacf3f2ac7fc2131d9e38938540aa1a8f95d84c5f4a90b08
MD5 54b677ff0ca06d26022a412a4e3f9b8f
BLAKE2b-256 c11236e2f18eb2842355044bf49e3f8bcd113b0f92b96e6c605b85de74511097

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page