Skip to main content

Plug-in recommendation engine router for FastAPI

Project description

SearchRec

PyPI CI

A recommendation engine that mounts directly into any FastAPI app. Tracks click sessions, learns what gets browsed together, and serves "you may also like" recommendations with an admin dashboard to visualise the model.

Install into any FastAPI app in under a minute.

Install

pip install searchrec

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 passed 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 scores are cached so serving is a single database lookup with 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 and 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
  • Native integrations for Next.js, Express, and NestJS

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.1.tar.gz (29.6 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.1-py3-none-any.whl (30.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: searchrec-0.1.1.tar.gz
  • Upload date:
  • Size: 29.6 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.1.tar.gz
Algorithm Hash digest
SHA256 f12768e05446dccee61ace74cffca6cefb9225e25f9a5ea934e89f70deeadcd4
MD5 f6cfb02af7d7cca4d3d14b8b74933234
BLAKE2b-256 5d6ca4accfc9f10a40775be69ec6129531b52b7768b7abb3dfc1dbf25c12ade0

See more details on using hashes here.

File details

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

File metadata

  • Download URL: searchrec-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 30.3 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 35910643d6bfafea19daa5ea2cbe9f63feeda8e13d63a44e19292f3160d38b5f
MD5 93eaaeb7bdc5e1ee42a27687cc65bf9c
BLAKE2b-256 24a79b573c7198e49c479a2172aa09cf0b4ab816895cdf18ec29f595ca5bf8b3

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