Skip to content

Serving lesson prose

This lesson prose turns ADR-0006’s claim into something runnable: the editor interface is not special because it is TypeScript, it is special because it is a client of the app contract. The Streamlit page is the swappability proof: a different language, a different UI runtime, and the same FastAPI contract.

Run it beside the FastAPI service:

Terminal window
uv run --package tutorial-serving streamlit run tutorial/serving/swap_demo.py

The page calls GET /constraint-configurations to populate the configuration picker, GET /recommendations/{user_id} to show the saved ranking, and POST /preview to show the selected configuration’s preview ranking. The side-by-side test feeds the same fake app-contract server to the TypeScript editor client and the Streamlit client, then asserts that both preserve the same ranked article order for the same user and configuration.

The preview contract now forwards all soft editorial weights: diversity, recency, recency half-life, sentiment weight, and target sentiment. Sentiment balance uses EB-NeRD’s article-level sentiment_score; Adressa and MIND do not publish equivalent scores, so the ranker degrades gracefully by treating the sentiment term as zero instead of inventing a score or failing the request.