How to Contribute to the Soup CLI Project: A Complete Guide for Developers
To contribute to the Soup CLI project, fork the repository, set up a Python 3.10–3.12 virtual environment, install with pip install -e ".[dev]", run tests with pytest, and follow the linting standards enforced by ruff before opening a pull request.
Contributing to the Soup CLI means joining a modular, Typer‑based command‑line application for LLM fine‑tuning, evaluation, and deployment according to the MakazhanAlpamys/Soup source code. This guide walks you through the architecture, setup steps, and submission process so you can make effective, well‑tested contributions.
Understanding the Soup CLI Architecture
Before writing code, familiarize yourself with how components connect. The project uses a centralized command registry with lazy imports to keep startup times fast.
Entry Point and Command Registration
In src/soup_cli/cli.py, the run() function drives the entire Typer application. It handles global options, audit logging, and optional telemetry. The cli.py file also serves as the single registry where all sub‑commands are attached:
# src/soup_cli/cli.py (lines 98–146)
# Commands are registered via app.command() or app.add_typer()
Each sub‑command—train, chat, serve, and others—is imported and bound to the main app. This design makes the CLI extensible: adding a new command requires only a new module and a single registration line.
Lazy Imports for Performance
Heavy ML dependencies (torch, transformers, peft, trl) are imported inside command handlers, not at module load time. See the comment at line 84 in cli.py and the implementation pattern in individual command modules. This keeps soup --help responsive even without GPU libraries installed.
Configuration and Data Handling
| Component | Location | Purpose |
|---|---|---|
| Configuration schema | src/soup_cli/config/schema.py |
Pydantic v2 models defining every YAML field—validation, defaults, and type safety in one place. |
| Data format normalization | src/soup_cli/data/formats.py |
Converts Alpaca, ShareGPT, ChatML, vision, and audio formats into a unified {"messages": [...]} structure. |
| Data loading | src/soup_cli/data/loader.py |
Auto‑detects format and prepares data for trainers. |
Trainer Wrappers
Trainer modules in src/soup_cli/trainer/ (e.g., sft.py, dpo.py) wrap HuggingFace TRL trainers. They automatically apply LoRA, quantization, batch‑size estimation, and Rich progress bars to streamline fine‑tuning workflows.
Setting Up Your Development Environment
Follow these validated steps from CONTRIBUTING.md to prepare your workspace:
# 1. Fork the repository on GitHub and clone your fork locally
git clone https://github.com/<your-username>/Soup.git
cd Soup
# 2. Create an isolated Python environment (Python 3.10–3.12)
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 3. Install the project in editable mode with development dependencies
pip install -e ".[dev]"
# 4. Verify the setup by running the test suite
pytest tests/ -v --tb=short
# 5. Run the linter and automatically fix simple violations
ruff check --fix src/soup_cli/ scripts/ tests/
The pip install -e ".[dev]" command installs the package in editable mode plus development tools like pytest and ruff.
Making and Testing Your Changes
Adding a New Sub‑Command
The Soup CLI follows a predictable pattern for command extensions:
- Create your command module at
src/soup_cli/commands/mycmd.py. - Register it in
src/soup_cli/cli.pyusingapp.command()orapp.add_typer(). - Use lazy imports inside your command handler for any heavy dependencies.
# Example structure for src/soup_cli/commands/mycmd.py
import typer
app = typer.Typer()
@app.command()
def mycmd(
config: str = typer.Option(..., help="Path to config YAML"),
verbose: bool = typer.Option(False, "--verbose", "-v"),
):
"""Brief description of what mycmd does."""
# Lazy import: only load when command is invoked
import torch
# ... implementation ...
Running Targeted Tests
After changes, validate with focused test runs:
# Run tests for your specific command
pytest tests/ -k mycmd -v
# Full test suite before final commit
pytest tests/ -v
The tests/ directory covers CLI commands, trainers, data pipelines, and edge cases according to the repository structure.
Code Quality Standards
The project enforces ruff with specific rules:
- Line length: 100 characters
- Import ordering enforced
- No bare
printstatements (use logging)
Run the linter before every commit:
ruff check --fix src/soup_cli/ scripts/ tests/
Documentation and Pull Request Process
Updating Documentation
All contributions must include documentation updates. The project maintains guides under docs/:
| Document | Content |
|---|---|
docs/commands.md |
Reference for all CLI commands |
docs/training.md |
Training workflows and configuration |
Update both the relevant doc page and the README.md for user‑facing features.
Submitting Your Contribution
# 1. Stage your changes
git add src/soup_cli/commands/mycmd.py src/soup_cli/cli.py docs/commands.md
# 2. Commit with conventional commit format
git commit -m "feat: add mycmd sub‑command for custom model evaluation"
# 3. Push and open a Pull Request
git push origin my-feature-branch
Pull requests are reviewed against:
- Test coverage for new functionality
- ruff compliance with zero warnings
- Documentation accuracy and completeness
- Adherence to lazy import patterns for performance
Key Files for Contributors
| File | When to Modify |
|---|---|
src/soup_cli/cli.py |
Adding or wiring new commands; global option changes |
src/soup_cli/config/schema.py |
New configuration fields or validation rules |
src/soup_cli/data/formats.py |
Additional data format support |
src/soup_cli/commands/ |
New command implementations |
tests/ |
Corresponding test coverage for any change |
CONTRIBUTING.md |
Rarely—only for process improvements |
Summary
- Fork and clone the MakazhanAlpamys/Soup repository, then install with
pip install -e ".[dev]". - Understand the architecture: centralized command registry in
cli.py, lazy imports for performance, Pydantic schemas for configuration. - Extend via
src/soup_cli/commands/, register incli.py, and maintain lazy import patterns. - Validate with
pytestand lint withruffbefore submitting. - Document changes in
docs/andREADME.md, using conventional commits for clear history.
Frequently Asked Questions
What Python versions are supported for contributing to Soup CLI?
The project supports Python 3.10 through 3.12. These are the versions validated in CI and tested against all dependencies including torch, transformers, and trl. Using a version outside this range may cause compatibility issues with the ML stack.
Why does Soup CLI use lazy imports instead of top‑level imports?
Lazy imports keep the CLI fast for lightweight operations like soup --help or soup --version. Heavy ML libraries (torch, transformers, peft, trl) are only loaded when a specific command needs them. This pattern is implemented throughout src/soup_cli/commands/ and noted in the comment at line 84 of cli.py.
How do I add a new configuration option to Soup CLI?
Define the field in src/soup_cli/config/schema.py using Pydantic v2. This file is the single source of truth—all validation, defaults, and type safety derive from here. The rest of the codebase references these models, so changes propagate automatically to command handlers and YAML loading.
What should I do if ruff reports errors I don't understand?
Run ruff check --fix src/soup_cli/ scripts/ tests/ first—this auto‑corrects many issues. For remaining errors, consult the ruff documentation or check existing code in the repository for compliant patterns. The project uses 100‑character line length and prohibits bare print statements in favor of structured logging.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →