SPARC-LLM framework with sklearn-inspired object API
Project description
SPARC-LLM Framework
SPARC-LLM is now organized as a reusable Python framework (scikit-learn inspired) with object-oriented APIs, typed configs, service layers, and a stable CLI.
Functional overview (what it does)
This framework helps you run continual learning for LLMs in a clean, reusable way:
- decompose a base model in SVD space,
- train an SVF policy to preserve important capabilities,
- inject new knowledge with orthogonal LoRA,
- evaluate base/SVF/LoRA/hybrid variants on knowledge + downstream tasks.
Typical user scenarios
- Research iteration: quickly test a new knowledge dataset while tracking skill retention.
- Benchmarking: compare
nonevssvf_onlyvslora_onlyvsboth. - Pipeline integration: call framework objects from another Python project.
- Progressive industrialization: keep research code, but expose a clean API for tests and automation.
End-to-end functional flow
flowchart LR
A[Base model] --> B[SVD decomposition]
B --> C[SVF training]
C --> D[Orthogonal LoRA training]
D --> E[Merge modes: none/svf/lora/both]
E --> F[Knowledge + downstream evaluation]
Quick execution paths
- Python-first: use
SPARCExperiment.run(...)for orchestration. - CLI-first: use
sparcllm run ...for end-to-end execution. - Stage-by-stage: use
sparcllm decompose,train-svf,train-orthogonal,evaluate.
Explainability first (non-technical)
If you are not deeply technical, think about this framework as a way to teach new knowledge to an AI model without making it forget what it already knows.
Intuition of each method
-
SVD (decomposition)
The model is split into reusable building blocks, like separating a recipe into ingredients.
Why: it makes later updates more controlled and easier to analyze. -
SVF (stability policy training)
The framework learns which internal directions are important to keep stable.
Why: this protects useful existing skills (reasoning, coding patterns, etc.). -
Orthogonal LoRA (knowledge injection)
LoRA adds new knowledge through lightweight adapters. “Orthogonal” means the update is guided to avoid conflicting with protected directions.
Why: inject new facts while reducing catastrophic forgetting. -
Merge + evaluation
You can compare multiple versions of the model:- base only,
- SVF only,
- LoRA only,
- SVF + LoRA together.
Why: measure what really works before deployment.
What happens when you run one full command
When you launch:
sparcllm run \
--with-svd \
--with-svf \
--with-orthogonal \
--with-eval \
--model-id meta-llama/Llama-3.1-8B-Instruct \
--base-model-key llama3i8b \
--svf-checkpoint-path svf_adapters/gsm_131224_policy_params.pt \
--knowledge-dataset-file knowledge_injection_data/500UK_3rHK.csv \
--svf-params-path svf_adapters/gsm_131224_policy_params.pt \
--svd-params-path svd_parameters/llama3.1_decomposed_params.pt \
--lora-adapter-path results_orthogonal/<run>/lora_epoch_10 \
--eval-mode both \
--task-names gsm8k arc
the framework does this, in order:
- decomposes the base model (
--with-svd), - trains/uses SVF to mark stability directions (
--with-svf), - trains orthogonal LoRA for new knowledge (
--with-orthogonal), - evaluates the final setup (
--with-eval) on selected tasks.
Human explanation of key flags
-
--model-id ...
Which foundation model you start from. -
--base-model-key llama3i8b
Which internal preset/config to use for training defaults. -
--svf-checkpoint-path ...
Previously learned SVF stability knowledge (what should be preserved). -
--knowledge-dataset-file ...
The file containing new knowledge you want to teach. -
--svf-params-path ...and--svd-params-path ...
Technical files needed to rebuild and apply stability-aware modifications. -
--lora-adapter-path ...
The LoRA adapter produced by orthogonal training (the “new knowledge module”). -
--eval-mode both
Evaluate the combined model (SVF + LoRA).
Other modes let you compare components separately. -
--task-names gsm8k arc
Which benchmarks to run for quality checks.
How to read results simply
- If knowledge metrics improve and baseline skills stay stable, your run is successful.
- If knowledge improves but old skills drop strongly, increase preservation constraints (SVF/orthogonal settings).
- If everything drops, reduce training aggressiveness (learning rate, epochs, adapter rank, batch size).
What you get
- clean Python objects for each stage (
fit,evaluate,run) - typed configs with dataclasses
- layered architecture (
datasets,models,trainers,evaluators) - one orchestrator object for full experiments
- installable package with CLI (
sparcllm) - tests + pre-commit baseline for quality
Installation
python3.11 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
cd evaluation/fishfarm && pip install -e . && cd ../..
pip install -e .
Install from PyPI
pip install sparcllm
The wheel includes the sparcllm.tasks package (downstream benchmarks wired through fishfarm). For ModelMergerEvaluator, Hydra research configs, and anything that runs vLLM-backed evaluation, install the optional extra:
pip install "sparcllm[eval]"
That pulls fishfarm, vllm, and datasets (Hugging Face). Without it, you can still import configs and estimators; evaluation fails at runtime with a clear missing-dependency error once tasks or vLLM are needed.
Auth + env:
hf auth login --token YOURTOKEN
export HF_TOKEN=YOURTOKEN
export CUDA_VISIBLE_DEVICES=0
Python API examples
1) Full workflow with SPARCExperiment
from sparcllm import (
MergeConfig,
OrthogonalTrainingConfig,
SPARCExperiment,
SVDConfig,
SVFTrainingConfig,
)
exp = SPARCExperiment(project_root=".")
report = exp.run(
svd_cfg=SVDConfig(
model_id="meta-llama/Llama-3.1-8B-Instruct",
output_file="svd_parameters/llama3.1_decomposed_params.pt",
),
svf_cfg=SVFTrainingConfig(
base_model_key="llama3i8b",
mode="training",
optimization="reinforce",
),
orthogonal_cfg=OrthogonalTrainingConfig(
base_model_key="llama3i8b",
svf_checkpoint_path="svf_adapters/gsm_131224_policy_params.pt",
knowledge_dataset_file="knowledge_injection_data/500UK_3rHK.csv",
run_name="exp_v2",
),
merge_cfg=MergeConfig(
base_model_id="meta-llama/Llama-3.1-8B-Instruct",
lora_adapter_path="results_orthogonal/<run>/lora_epoch_10",
svf_params_path="svf_adapters/gsm_131224_policy_params.pt",
svd_params_path="svd_parameters/llama3.1_decomposed_params.pt",
mode="both",
task_names=["gsm8k", "arc"],
),
)
print(report.executed_stages, report.metrics)
2) Estimator-style partial execution
from sparcllm import MergeConfig, ModelMergerEvaluator
metrics = ModelMergerEvaluator(
MergeConfig(
base_model_id="meta-llama/Llama-3.1-8B-Instruct",
mode="none",
task_names=["gsm8k"],
skip_knowledge_eval=True,
)
).evaluate()
print(metrics)
CLI usage
Stage-by-stage
sparcllm decompose \
--model-id meta-llama/Llama-3.1-8B-Instruct \
--output-file svd_parameters/llama3.1_decomposed_params.pt
sparcllm train-svf \
--base-model-key llama3i8b \
--mode training \
--optimization reinforce
sparcllm train-orthogonal \
--base-model-key llama3i8b \
--svf-checkpoint-path svf_adapters/gsm_131224_policy_params.pt \
--knowledge-dataset-file knowledge_injection_data/500UK_3rHK.csv \
--num-epochs 10 \
--batch-size 8 \
--lr 2e-4 \
--lambda-ip 0 \
--lambda-ortho 100
sparcllm evaluate \
--base-model-id meta-llama/Llama-3.1-8B-Instruct \
--mode both \
--lora-adapter-path results_orthogonal/<run>/lora_epoch_10 \
--svf-params-path svf_adapters/gsm_131224_policy_params.pt \
--svd-params-path svd_parameters/llama3.1_decomposed_params.pt \
--knowledge-dataset-file knowledge_injection_data/500UK_3rHK.csv \
--task-names gsm8k arc
One command orchestration
sparcllm run \
--with-svd \
--with-svf \
--with-orthogonal \
--with-eval \
--model-id meta-llama/Llama-3.1-8B-Instruct \
--base-model-key llama3i8b \
--svf-checkpoint-path svf_adapters/gsm_131224_policy_params.pt \
--knowledge-dataset-file knowledge_injection_data/500UK_3rHK.csv \
--svf-params-path svf_adapters/gsm_131224_policy_params.pt \
--svd-params-path svd_parameters/llama3.1_decomposed_params.pt \
--lora-adapter-path results_orthogonal/<run>/lora_epoch_10 \
--eval-mode both \
--task-names gsm8k arc
Plot and visualize results
You can now generate plots directly from output files with the framework CLI.
1) Plot orthogonal training losses
Input file: training_history.json generated by orthogonal training.
sparcllm plot \
--kind orthogonal_history \
--input-file results_orthogonal/<run>/training_history.json \
--output-dir plots
2) Plot LoRA training curves (Unknown/HighlyKnown/Loss)
Input file: training_log.json (JSONL or concatenated JSON objects).
sparcllm plot \
--kind lora_training_log \
--input-file results_sft/<run>/training_log.json \
--output-dir plots
3) Plot merge/evaluation metrics
Input file: results.json from merge/eval runs.
sparcllm plot \
--kind merge_results \
--input-file results_merge_adapters/<timestamp>/results.json \
--output-dir plots
The command prints the output image path(s), so you can open them directly.
Internal architecture
flowchart LR
A[Config objects] --> B[Workflow object]
B --> C[Training services]
B --> D[Model composition service]
B --> E[Evaluation engine]
C --> F[Hydra research entrypoints]
D --> G[Base/SVF/LoRA merged model]
E --> H[Task metrics + report]
Package map
sparcllm/
__init__.py
base.py # BaseEstimator
config.py # dataclass configs
runner.py # command execution utility
pipeline.py # sklearn-like stage estimators
workflows.py # SPARCExperiment + ExperimentReport
cli.py # `sparcllm` command line
datasets/registry.py # task registry/factory
models/composer.py # base/SVF/LoRA composition
trainers/stages.py # SVD/SVF/Orthogonal services
evaluators/engine.py # knowledge + downstream evaluation engine
tasks/ # downstream + knowledge task wrappers (fishfarm / vLLM)
examples/
framework_quickstart.py
tests/
test_base_estimator.py
test_config_and_pipeline.py
Main objects and what they do
Config objects (sparcllm.config)
SVDConfig: controls decomposition stage.SVFTrainingConfig: controls SVF policy training.OrthogonalTrainingConfig: controls orthogonal LoRA training.MergeConfig: controls merge + evaluation stage.ComposeRequest: internal model-composition request.
Estimator objects (sparcllm.pipeline)
SVDDecomposer.fit()SVFTrainer.fit()OrthogonalLoRATrainer.fit()ModelMergerEvaluator.evaluate()SPARCPipeline.run(...)(compose multiple stages)
Workflow object (sparcllm.workflows)
SPARCExperiment.run(...)returns anExperimentReport:executed_stagesnotesmetrics
This is the recommended object for production orchestration.
Object interaction diagram
flowchart TD
C1[SVDConfig]
C2[SVFTrainingConfig]
C3[OrthogonalTrainingConfig]
C4[MergeConfig]
E[SPARCExperiment]
R[CommandRunner]
S1[SVDService]
S2[SVFTrainingService]
S3[OrthogonalTrainingService]
M[ModelComposer]
EV[EvaluationEngine]
TR[TaskRegistry]
REP[ExperimentReport]
C1 --> E
C2 --> E
C3 --> E
C4 --> E
E --> R
E --> S1
E --> S2
E --> S3
E --> EV
S1 --> R
S2 --> R
S3 --> R
EV --> M
EV --> TR
EV --> REP
E --> REP
How to read this diagram
SPARCExperimentis the top-level orchestrator.- Config objects define what each stage should do.
- Training services execute stage logic (currently through managed command calls).
EvaluationEnginecomposes models viaModelComposer, resolves tasks viaTaskRegistry, and returns metrics.ExperimentReportis the final structured output for executed stages, notes, and results.
About scripts in scripts/
Legacy shell scripts are still present for reproducibility of older runs.
For new integrations, prefer:
- Python API via
sparcllmobjects - CLI via
sparcllm ...
This keeps your codebase cleaner and easier to test.
Local quality gates
pip install -e ".[dev]"
# optional: fishfarm + vLLM + datasets (matches PyPI `sparcllm[eval]`)
pip install -e ".[eval]"
pre-commit install
pre-commit run --all-files
pytest
Hydra configs under cfgs/ use _target_: sparcllm.tasks.... (task implementations live in the sparcllm.tasks package).
CI/CD and Python artifact publishing
This repository now includes GitHub Actions workflows to validate quality and prepare package publishing.
Workflows added
.github/workflows/ci.yml- runs lint (
ruff) and unit tests (pytest) on PRs and key branches
- runs lint (
.github/workflows/release.yml- resolves version bump from labels (or manual input),
- bumps package version in
pyproject.toml, - builds wheel/sdist (
python -m build), - uploads build artifacts,
- supports controlled publishing target:
none,pypi,artifactory,both, - uses Trusted Publisher (OIDC) for PyPI publication.
Versioning strategy (x.y.z)
The release workflow uses semantic versioning:
- x = major (breaking change)
- y = minor (new backward-compatible features)
- z = patch (bug fixes)
Label mapping used by the workflow:
- major:
x,major,semver:major - minor:
y,minor,semver:minor - patch:
z,bug,bugfix,patch,semver:patch
If no label is detected, default bump is patch.
Branch strategy for now (before main)
The release workflow is configured to run on:
- push to
code_refactoring - push to
main/master - manual
workflow_dispatch
Recommended while preparing:
- trigger manual runs with
publish_target=noneto validate build/versioning only, - then use
publish_target=pypiwhen you are ready to publish.
Important: on push, the workflow has no publish_target input, so it always stays none. The PyPI and Artifactory steps are skipped on purpose (only build, artifact upload, and version commit run). That is why you may see a “skipped” icon on those steps after a push. To actually upload to PyPI, run Release Package manually and set publish_target to pypi (or both).
Trigger release from code_refactoring (no merge to main)
The GitHub UI Run workflow only appears reliably when the workflow file is on the default branch. To publish from the integration branch without merging to main first, use the GitHub CLI (gh):
# macOS: brew install gh then: gh auth login
gh workflow run release.yml \
--ref code_refactoring \
-f bump=patch \
-f publish_target=pypi
Adjust bump (patch, minor, major) and publish_target (none, pypi, artifactory, both) as needed. The job runs on the workflow revision present on code_refactoring.
Required secrets for publishing
To publish to your Python artifact repository (Artifactory), set:
ARTIFACTORY_PYPI_URLARTIFACTORY_PYPI_USERNAMEARTIFACTORY_PYPI_PASSWORD
For public PyPI (Trusted Publisher), no API token secret is required when OIDC is configured in PyPI.
If publishing target is none, workflow still builds and stores artifacts in GitHub Actions.
The commit version bump step runs only on push and uses the identity github-actions[bot] so git commit works on the runner (no extra secrets needed for that).
Install after publication
Once published in your artifact repository, you can install with:
pip install sparcllm
If your registry is private, configure pip index/auth first (according to your Artifactory or private PyPI setup).
Cleanup performed
- framework now uses explicit service layers for datasets/models/trainers/evaluators
- reusable workflow object added (
SPARCExperiment) - CLI expanded to cover stage-by-stage and end-to-end runs
- legacy shell scripts kept for reproducibility, framework API prioritized for new usage
This is now a solid base for next steps (deeper tests and artifact publishing pipeline).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sparcllm-2.0.1.tar.gz.
File metadata
- Download URL: sparcllm-2.0.1.tar.gz
- Upload date:
- Size: 35.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d1f1dfea6ed2f933046d10712b76e3615d4ab448af2e9ad4b78011bebc18c89
|
|
| MD5 |
05c96e59ed9e9952de7683add5686515
|
|
| BLAKE2b-256 |
1808b06e65113c5e4b7a412cf3f2bcbcc4b917e70bf185b7f4bdfc946f44e74c
|
Provenance
The following attestation bundles were made for sparcllm-2.0.1.tar.gz:
Publisher:
release.yml on mustashot/adaptive-llms
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sparcllm-2.0.1.tar.gz -
Subject digest:
9d1f1dfea6ed2f933046d10712b76e3615d4ab448af2e9ad4b78011bebc18c89 - Sigstore transparency entry: 1258388896
- Sigstore integration time:
-
Permalink:
mustashot/adaptive-llms@4cb26ed85306b1638d40ea3465adcd234b39721b -
Branch / Tag:
refs/heads/code_refactoring - Owner: https://github.com/mustashot
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4cb26ed85306b1638d40ea3465adcd234b39721b -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file sparcllm-2.0.1-py3-none-any.whl.
File metadata
- Download URL: sparcllm-2.0.1-py3-none-any.whl
- Upload date:
- Size: 39.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1cb758abc3846fd7b5b9c0ade605c16a317cffcd393e6b26a92587b3ac88ccbf
|
|
| MD5 |
43e2a6cbf21507425db084448225174c
|
|
| BLAKE2b-256 |
3f62f81e311dc7510ebcf757e17aaec650c6d25fd015ba2c768aa8a75de7f5e0
|
Provenance
The following attestation bundles were made for sparcllm-2.0.1-py3-none-any.whl:
Publisher:
release.yml on mustashot/adaptive-llms
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sparcllm-2.0.1-py3-none-any.whl -
Subject digest:
1cb758abc3846fd7b5b9c0ade605c16a317cffcd393e6b26a92587b3ac88ccbf - Sigstore transparency entry: 1258388913
- Sigstore integration time:
-
Permalink:
mustashot/adaptive-llms@4cb26ed85306b1638d40ea3465adcd234b39721b -
Branch / Tag:
refs/heads/code_refactoring - Owner: https://github.com/mustashot
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4cb26ed85306b1638d40ea3465adcd234b39721b -
Trigger Event:
workflow_dispatch
-
Statement type: