Appendix A — Appendix
This appendix brings together the commands, interfaces, and diagnostic checks used throughout the guide. It is a reference for repeating the workflow; the explanations and design decisions remain in the main chapters.
What this guide establishes
The completed workflow demonstrates that one fitted preprocessing-and-model pipeline can be:
- trained reproducibly;
- saved and loaded as a single artifact;
- called through a reliable inference function;
- exposed through a validated HTTP API;
- tested with valid and invalid requests;
- packaged and run in a container; and
- checked for basic service health and prediction correctness.
This is the boundary of Model Deployment in the CDI Data Science pathway. A successful JSON request proves the complete prediction pathway, but it does not by itself prove production readiness. CI/CD, infrastructure provisioning, secrets, production observability, scaling, rollback, feedback loops, retraining, governance, and human decision systems belong to the next guide, From Models to Systems.
Repository conventions
| Path | Purpose |
|---|---|
app/ |
FastAPI application, schemas, and inference code |
data/raw/ |
Original input data retained without modification |
data/processed/ |
Reproducible training or testing data derived from raw inputs |
models/ |
Serialized model pipelines and associated metadata |
results/ |
Machine-readable test and validation outputs |
reports/ |
Human-readable summaries or rendered supporting material |
scripts/python/ |
Executable Python programs, prefixed by chapter number |
scripts/bash/ |
Repeatable shell entry points, prefixed by chapter number |
tests/ |
Automated application and API tests |
docs/ |
Rendered Quarto book |
Generated artifacts should not be edited manually. Change the source data or program, then rerun the responsible script.
Environment commands
Create and activate the repository-specific environment:
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txtConfirm that the active interpreter belongs to this repository:
which python
python --version
python -m pip --versionDeactivate it before moving to another project:
deactivatePython’s venv module creates an isolated environment whose installed packages are separate from the base interpreter (Python Software Foundation n.d.).
Application commands
Start the API for local development:
python -m uvicorn app.main:app --reloadUseful local endpoints are:
| Endpoint | Purpose |
|---|---|
http://127.0.0.1:8000/health |
Service and model-readiness check |
http://127.0.0.1:8000/predict |
Prediction request |
http://127.0.0.1:8000/docs |
Interactive OpenAPI documentation |
http://127.0.0.1:8000/openapi.json |
Machine-readable API specification |
FastAPI derives request handling and interactive documentation from declared routes and typed schemas (Ramírez n.d.a, n.d.b).
Run the automated tests:
python -m pytest -qUsing python -m pytest makes the selected Python interpreter explicit. Pytest discovers test modules and reports passing, failing, and erroring tests (pytest developers n.d.).
Request and response contracts
The request body is a contract, not merely an example. Field names, data types, required values, and numeric boundaries must agree with the schema defined in the application. Pydantic field constraints make those requirements explicit (Pydantic n.d.).
A prediction request has this general form:
{
"feature_1": 12.5,
"feature_2": 3,
"feature_3": "category_a"
}Use the exact feature names and valid values defined by the project schema. Test with the chapter’s maintained request fixture rather than copying this generic structure into the running application.
A successful response should expose a stable response schema, for example:
{
"prediction": 1,
"probability": 0.83,
"model_version": "1.0.0"
}The actual fields are determined by the application’s response model. Declaring a response model allows FastAPI to validate, document, and filter returned data (Ramírez n.d.c).
HTTP outcomes
| Status | Meaning in this workflow | First check |
|---|---|---|
200 |
Request completed successfully | Inspect the returned prediction and metadata |
404 |
Route was not found | Confirm the path and HTTP method |
405 |
Method is not allowed | Use POST for the prediction endpoint |
422 |
Request failed schema validation | Compare JSON fields, types, and constraints with the schema |
500 |
Application failed during processing | Inspect server logs and the traceback |
503 |
Service is running but not ready | Check model loading and required files |
Validation failures should be tested deliberately. A 422 response for a malformed request is evidence that the boundary is rejecting invalid input, not that the API is broken.
Command-line API checks
Check health:
curl --silent --show-error --fail \
http://127.0.0.1:8000/healthSend a prediction request using the maintained JSON fixture:
curl --silent --show-error --fail \
--request POST \
--header "Content-Type: application/json" \
--data @data/reference/prediction-request.json \
http://127.0.0.1:8000/predictThe curl options used here suppress progress output, preserve useful error messages, and return a failure exit status for unsuccessful HTTP responses (curl project n.d.).
Container commands
Build the image from the repository root:
docker build --tag model-deployment:latest .Run it and map the container port to the host:
docker run --rm \
--name model-deployment-api \
--publish 8000:8000 \
model-deployment:latestInspect running containers and logs from another terminal:
docker ps
docker logs model-deployment-apiStop the container when --rm is not being used interactively:
docker stop model-deployment-apiA Dockerfile defines how the image is assembled, while docker run creates and starts a container from that image (Docker n.d.a, n.d.b).
Artifact safety and compatibility
The serialized artifact contains the fitted preprocessing and model pipeline. Keep preprocessing inside the pipeline so training and inference apply the same transformations (scikit-learn developers n.d.b).
pickle-based formats, including joblib, must be loaded only from trusted sources. They can execute arbitrary code during loading, and loading an artifact with different dependency versions is unsupported. Record the training code, dependency versions, data reference, and evaluation results needed to reproduce the artifact (scikit-learn developers n.d.a).
At minimum, retain:
- the artifact filename and version;
- the feature schema and target definition;
- the training-data reference or immutable snapshot identifier;
- the Python and package versions;
- the training script or source commit;
- the evaluation metrics; and
- the creation date.
Troubleshooting sequence
Diagnose failures from the inside out:
- Environment: Is the repository-specific
.venvactive and are dependencies installed? - Artifact: Does the expected model file exist, and can it be loaded by the current environment?
- Inference: Does a direct Python call return a prediction for a known valid record?
- Schema: Does the JSON body match the declared field names, types, and constraints?
- Application: Does
/healthreport that the service and model are ready? - HTTP: Does the maintained valid request return
200, while invalid cases return the expected422responses? - Container: Does the image contain the artifact and application files, expose the correct port, and start the correct command?
Common failures
| Symptom | Likely cause | Corrective action |
|---|---|---|
ModuleNotFoundError |
Wrong environment or missing dependency | Activate .venv; reinstall requirements.txt |
| Model file not found | Wrong working directory or image copy path | Verify the configured path and Docker build context |
| Artifact load warning or failure | Dependency-version mismatch | Recreate the recorded environment or rebuild the artifact |
Valid-looking request returns 422 |
Field name, type, or boundary differs from schema | Compare the body with /docs or openapi.json |
| Direct inference works but API fails | Request-to-dataframe conversion or response serialization issue | Test the inference adapter separately |
| Local API works but container fails | Missing copied file, wrong command, host binding, or port mapping | Inspect the Dockerfile, image contents, and container logs |
| Connection refused | Server is stopped or the wrong port is used | Start the service and verify host/container port mapping |
Completion checklist
The guide is complete when all of the following are true:
Passing this checklist establishes a packaged, validated, tested, and containerized model service. Broader production operation begins in From Models to Systems.