Wrap up and what to build next

You have a four-stage recommender that runs end to end. Retrieval, filtering, ranking, optional LLM rerank. Served by FastAPI. Backed by Postgres, Qdrant, and MLflow. The Streamlit UI just calls the API and renders article images, so you can sanity check by clicking through.

recsys/ui/streamlit_app.py
python
def render():
    samples = _api_get("/customers/sample", {"limit": 25}).get("customers", [])
    options = {f"{c['customer_id'][:12]} (age {c.get('age', '?')})": c["customer_id"] for c in samples}
    customer_id = options[st.selectbox("Pick a customer", list(options.keys()))]
    top_k = st.slider("Top-K", min_value=4, max_value=40, value=12, step=4)
    use_llm = st.toggle("LLM rerank", value=False)

    if st.button("Get recommendations", type="primary"):
        result = _api_post("/recommend", {"customer_id": customer_id, "top_k": top_k, "use_llm": use_llm})
        for i, item in enumerate(result.get("items", [])):
            with st.columns(4)[i % 4]:
                if item.get("image_url"):
                    st.image(item["image_url"], use_container_width=True)
                st.markdown(item.get("prod_name") or item["article_id"])

The UI is intentionally thin. All it does is call the API and render cards.

Upgrades that pay off in the order I would tackle them: switch to hard negatives in ranking, add a real-time feature for time-since-last-purchase, swap the embedded Qdrant for a server-mode deployment, and stand up an A/B framework that splits traffic deterministically by customer id.

AI prompt: Try it: extend the project

Loading practice…