This is a Copier template for bootstrapping machine-learning projects that follow a data-centric state machine with Prefect v2 orchestration. It renders a clean scaffold with typed config (pydantic-settings), optional Pandera, and a CLI plus minimal Prefect flows. The template is designed to be updatable later via copier update without clobbering your project-owned code.
-
Prereqs: Python 3.11+,
pipx install copier(orpip install copier). -
Create a new project:
copier copy gh:your-org/ml-project-template path/to/your_project # or from a local checkout copier copy . path/to/your_project
-
Questions include project name, package name, Python version, and whether to enable Prefect/Pandera.
-
mlcore dependency (optional):
- Projects may include
mlcore[prefect] >=0.1,<0.2, but it’s optional. - To dogfood locally during generation, set
MLCORE_LOCAL_PATHenv var before running Copier. The generated project will use the local path via uv sources.
- Projects may include
Automate the full flow (copy template → create venv → install deps → open shell):
# From the parent folder that contains ml-project-template/ and (optionally) mlcore/
python ml-project-template/scripts/new_project.py --name my-new-project --use-python311Behavior:
- Creates the project as a sibling of
ml-project-template/(no nested folder). - Detects
../mlcoreand installs it editable, or pass--mlcore-path noneto skip. - Creates
.venv, upgrades pip, installs the project editable, and drops you into an activated shell in the new project directory.
Useful flags:
--source local|gh: choose local template or GitHub (default: local)--template-path <path>: path to local template (auto-detected by default)--parent-dir <dir>: parent directory holding siblings (auto-detected)--mlcore-path <path|none>: path to local mlcore ornoneto disable--skip-venv: only generate the project, no venv or installs--enter/--no-enter: open an activated subshell in the project (default: enter)--shell <name>: force shell (e.g., bash, zsh, fish); otherwise detected--clean: start a shell without user rc files (zsh -f, bash --noprofile --norc)
Copier availability:
- If
copierisn’t on PATH, the script bootstraps a tiny venv inml-project-template/.bootstrap, installs Copier there, and uses it automatically.
-
Lint/type-check this template repo:
pre-commit run --all-files
The template renders this structure (verbatim):
your_project_name/
├── pyproject.toml
├── prefect.yaml
├── README.md
│
├── docs/
│ ├── ARCHITECTURE.md
│ └── QUICKSTART.md
│
├── configs/
│ ├── env/
│ │ ├── dev.yaml
│ │ └── prod.yaml
│ ├── data_sources.yaml
│ └── policies/
│ └── thresholds.yaml
│
├── registries/
│ ├── schemas/
│ ├── features/
│ └── prompts/
│
├── src/<your_package_name>/
│ ├── tasks/
│ │ ├── io/
│ │ ├── validation/
│ │ ├── featurization/
│ │ ├── modeling/
│ │ └── evaluation/
│ │
│ └── flows/
│ ├── ingest_validate.py
│ ├── feature_build.py
│ ├── train_eval.py
│ └── deploy.py
│
├── lab/
│ ├── notebooks/
│ ├── playbooks/
│ └── overrides/
│
├── scripts/
│ └── cli.py
│
├── tests/
│ ├── unit/
│ └── integration/
│
└── data/
├── samples/
└── fixtures/
Projects can be updated later. Run:
git switch -c chore/template-update
copier update
# review diffs/prompts
pytest -qSee TEMPLATE_UPDATES.md for the policy on which files are template-owned vs project-owned.
- Source of truth for the generated project’s version is
pyproject.tomlunder[project].version. - In this template the default is set in:
template/{{ project_slug }}/pyproject.toml.j2:7
- Recommended initial versioning (Semantic Versioning):
- Private/prototype:
0.0.1 - First usable/internal release:
0.1.0 - Public/production baseline:
1.0.0
- Private/prototype:
- Tag format on GitHub:
vX.Y.Z(e.g.,v0.1.0), and ensure the tag points to the commit on your default branch that contains the version bump.
- Template plane: this repo defines structure, configs, CI, and example flows/CLI.
- Library plane:
mlcorecontains reusable utilities and abstractions (logging, IO, model cards, etc.). The template pins an upper bound by default to prevent silent breaking changes, and supports a local path override viaMLCORE_LOCAL_PATHwhen generating or developing.
The CI lints this repository and test-generates a sample project using Copier, installs it (pointing mlcore to a local stub in this repo), and runs its tests. This ensures the template stays healthy.
- Run
scripts/e2e_sanity.shto generate two sample projects:- Scenario A: no
mlcoredependency - Scenario B: with local
mlcoreviaMLCORE_LOCAL_PATHIt installs, runs tests, and executes the demo flow in both cases.
- Scenario A: no