Serving lesson prose
L07 — Streamlit Swappability Proof
Section titled “L07 — Streamlit Swappability Proof”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:
uv run --package tutorial-serving streamlit run tutorial/serving/swap_demo.pyThe 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.