Skip to content

Serving

The serving module is the app contract half of the two-contracts architecture (ADR-0006). It exposes a small, OpenAPI-documented HTTP API on top of the data platform and ranker so application clients — the TypeScript editor, the Streamlit swap-demo, anything else that speaks the contract — can drive the recommender without touching DuckDB directly.

The whole module is also where most of the FastAPI + Python code lives that the other modules anchor to. If you are exploring the repo top-down, tutorial/serving/ is the directory with the most going on.

EndpointWhat it doesSource
GET /articles/{id}Single-article lookuparticles.py
GET /recommendations/{user_id}Generates a candidate set, applies the persisted configuration’s ranker, returns the ranked listrecommendations.py
POST /previewSame ranker, but takes the configuration inline (does not persist). Powers the editor’s live preview.recommendations.py
GET / POST / PUT / DELETE /constraint-configurations*Full CRUD against the constraint_configurations tableconfigurations.py
POST /assistants/change-explainerEditorial AI assistant: explains why a recommendation list changedagents/change-explainer.ts (TS side) + serving glue

The application entry point is app.py. FastAPI generates the OpenAPI spec automatically; the API reference page on this docs site renders that spec for readers, and the TypeScript editor consumes it as auto-generated typed clients (see the editor module).

The OpenAPI file is the swappable boundary

Section titled “The OpenAPI file is the swappable boundary”

The architectural claim (ADR-0006) is that any client speaking the same OpenAPI contract is interchangeable with any other. The TypeScript editor is one client; the Streamlit swap-demo is a deliberately different one (different language, different UI runtime) — and the swap_demo.py script makes the swappability claim falsifiable rather than rhetorical.

A side-by-side integration test feeds the same fake app-contract server to both clients and asserts they produce identical rankings for the same user and configuration. Read serving’s lesson prose for the full walkthrough.

The tests/ directory carries integration tests for every endpoint:

Each test makes the response schema explicit and verifies behaviour against the ranker module without going through the network. The OpenAPI contract is enforced at the boundary.

The editor module is the primary application client. The assistants module hangs its endpoints off the same FastAPI app. The evaluation module reads the same ranker behaviour the serving endpoints expose.