Lab Information
The xFusionCorp Industries ML team uses uv and lockfiles to keep Python dependencies reproducible across machines. A teammate has left behind a requirements.in specification that does not match the team's standard. Correct it and compile it into a pinned lockfile.
A high-level dependency specification exists at /root/code/fraud-detection/requirements.in. uv is already installed.
The corrected specification must meet the following requirements:
it lists exactly these four top-level packages: scikit-learn, mlflow, pandas, and numpy;
every package carries a version constraint that uv can actually satisfy against PyPI.
Review the existing requirements.in, and correct everything that does not match the requirements above.
From the project directory, compile the corrected specification into a pinned lockfile:
uv pip compile requirements.in -o requirements.txt
The resulting requirements.txt must pin each of the four top-level packages to an exact version using ==, and must also include the transitive dependencies that uv resolved.
Lab Solutions
🧭 Part 1: Lab Step-by-Step Guidelines
Run the following commands on the controlplane host.
Step 1 — Move to the project directory
cd /root/code/fraud-detection
Step 2 — Inspect the existing requirements.in
cat requirements.in
Look for:
wrong package names
missing packages
extra packages
invalid version constraints
Step 3 — Edit requirements.in
Open the file:
vi requirements.in
Replace the contents with valid package constraints such as:
scikit-learn>=1.4
mlflow>=2.12
pandas>=2.2
numpy>=1.26
The file must contain:
exactly 4 top-level packages
all valid PyPI-installable constraints
Step 4 — Compile the lockfile using uv
Run:
uv pip compile requirements.in -o requirements.txt
This generates:
requirements.txt
with:
exact pinned versions (==)
all transitive dependencies
Step 5 — Verify the generated lockfile
Check the file:
cat requirements.txt
You should see entries like:
Resolved 90 packages in 626ms
# This file was autogenerated by uv via the following command:
# uv pip compile requirements.in -o requirements.txt
aiohappyeyeballs==2.6.2
# via aiohttp
aiohttp==3.14.0
# via mlflow
aiosignal==1.4.0
# via aiohttp
alembic==1.18.4
# via mlflow
annotated-doc==0.0.4
# via fastapi
annotated-types==0.7.0
# via pydantic
anyio==4.13.0
# via starlette
attrs==26.1.0
# via aiohttp
blinker==1.9.0
# via flask
cachetools==7.1.4
# via
# mlflow-skinny
# mlflow-tracing
certifi==2026.5.20
# via requests
cffi==2.0.0
# via cryptography
charset-normalizer==3.4.7
# via requests
click==8.4.1
# via
# flask
# mlflow-skinny
# uvicorn
cloudpickle==3.1.2
# via mlflow-skinny
contourpy==1.3.3
# via matplotlib
cryptography==48.0.0
# via
# google-auth
# mlflow
cycler==0.12.1
# via matplotlib
databricks-sdk==0.114.0
# via
# mlflow-skinny
# mlflow-tracing
docker==7.1.0
# via mlflow
fastapi==0.136.3
# via mlflow-skinny
flask==3.1.3
# via
# flask-cors
# mlflow
flask-cors==6.0.2
# via mlflow
fonttools==4.63.0
# via matplotlib
frozenlist==1.8.0
# via
# aiohttp
# aiosignal
gitdb==4.0.12
# via gitpython
gitpython==3.1.50
# via mlflow-skinny
google-auth==2.53.0
# via databricks-sdk
graphene==3.4.3
# via mlflow
graphql-core==3.2.8
# via
# graphene
# graphql-relay
graphql-relay==3.2.0
# via graphene
greenlet==3.5.1
# via sqlalchemy
gunicorn==26.0.0
# via mlflow
h11==0.16.0
# via uvicorn
huey==3.0.1
# via mlflow
idna==3.17
# via
# anyio
# requests
# yarl
importlib-metadata==9.0.0
# via mlflow-skinny
itsdangerous==2.2.0
# via flask
jinja2==3.1.6
# via flask
joblib==1.5.3
# via scikit-learn
kiwisolver==1.5.0
# via matplotlib
mako==1.3.12
# via alembic
markupsafe==3.0.3
# via
# flask
# jinja2
# mako
# werkzeug
matplotlib==3.10.9
# via mlflow
mlflow==3.13.0
# via -r requirements.in
mlflow-skinny==3.13.0
# via mlflow
mlflow-tracing==3.13.0
# via mlflow
multidict==6.7.1
# via
# aiohttp
# yarl
narwhals==2.22.0
# via scikit-learn
numpy==2.4.6
# via
# -r requirements.in
# contourpy
# matplotlib
# mlflow
# pandas
# scikit-learn
# scipy
# skops
opentelemetry-api==1.42.1
# via
# mlflow-skinny
# mlflow-tracing
# opentelemetry-sdk
# opentelemetry-semantic-conventions
opentelemetry-proto==1.42.1
# via
# mlflow-skinny
# mlflow-tracing
opentelemetry-sdk==1.42.1
# via
# mlflow-skinny
# mlflow-tracing
opentelemetry-semantic-conventions==0.63b1
# via opentelemetry-sdk
packaging==26.2
# via
# gunicorn
# matplotlib
# mlflow-skinny
# mlflow-tracing
# skops
pandas==2.3.3
# via
# -r requirements.in
# mlflow
pillow==12.2.0
# via matplotlib
prettytable==3.17.0
# via skops
propcache==0.5.2
# via
# aiohttp
# yarl
protobuf==6.33.6
# via
# databricks-sdk
# mlflow-skinny
# mlflow-tracing
# opentelemetry-proto
pyarrow==24.0.0
# via mlflow
pyasn1==0.6.3
# via pyasn1-modules
pyasn1-modules==0.4.2
# via google-auth
pycparser==3.0
# via cffi
pydantic==2.13.4
# via
# fastapi
# mlflow-skinny
# mlflow-tracing
pydantic-core==2.46.4
# via pydantic
pyparsing==3.3.2
# via matplotlib
python-dateutil==2.9.0.post0
# via
# graphene
# matplotlib
# pandas
python-dotenv==1.2.2
# via mlflow-skinny
pytz==2026.2
# via pandas
pyyaml==6.0.3
# via mlflow-skinny
requests==2.34.2
# via
# databricks-sdk
# docker
# mlflow-skinny
scikit-learn==1.9.0
# via
# -r requirements.in
# mlflow
# skops
scipy==1.17.1
# via
# mlflow
# scikit-learn
# skops
six==1.17.0
# via python-dateutil
skops==0.14.0
# via mlflow
smmap==5.0.3
# via gitdb
sqlalchemy==2.0.50
# via
# alembic
# mlflow
sqlparse==0.5.5
# via mlflow-skinny
starlette==1.2.1
# via
# fastapi
# mlflow-skinny
threadpoolctl==3.6.0
# via scikit-learn
typing-extensions==4.15.0
# via
# aiohttp
# aiosignal
# alembic
# anyio
# fastapi
# graphene
# mlflow-skinny
# opentelemetry-api
# opentelemetry-sdk
# opentelemetry-semantic-conventions
# pydantic
# pydantic-core
# sqlalchemy
# starlette
# typing-inspection
typing-inspection==0.4.2
# via
# fastapi
# pydantic
tzdata==2026.2
# via pandas
urllib3==2.7.0
# via
# docker
# requests
uvicorn==0.48.0
# via mlflow-skinny
wcwidth==0.7.0
# via prettytable
werkzeug==3.1.8
# via
# flask
# flask-cors
yarl==1.24.2
# via aiohttp
zipp==4.1.0
# via importlib-metadata
🧠 Part 2: Simple Beginner-Friendly Explanation
What is requirements.in?
requirements.in is a high-level dependency file.
It describes:
“These are the packages my project needs.”
Example:
numpy>=1.26
This means:
install numpy
any compatible version newer than 1.26
What is a Lockfile?
The generated:
requirements.txt
is a fully pinned dependency lockfile.
It contains:
exact package versions
every dependency required underneath
Example:
numpy==1.26.4
This guarantees:
reproducible installs
same environment on every machine
Why Use uv pip compile?
Command:
uv pip compile requirements.in -o requirements.txt
does the following:
reads requirements.in
resolves compatible versions
locks exact versions
includes transitive dependencies
Difference Between Top-Level and Transitive Dependencies
Top-Level Dependencies
Packages you explicitly request:
numpy
pandas
mlflow
scikit-learn
Transitive Dependencies
Packages automatically required by those libraries.
Example:
pandas may require:
python-dateutil
pytz
mlflow may require many extra libraries
These appear automatically in:
requirements.txt
Why Exact == Versions Matter
Example:
numpy==1.26.4
This prevents:
unexpected upgrades
dependency conflicts
“works on my machine” problems
It ensures all developers use identical versions.
Top comments (0)