modelforge-finetuning 3.0.5__tar.gz → 4.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modelforge_finetuning-4.0.1/MANIFEST.in +6 -0
- modelforge_finetuning-4.0.1/PKG-INFO +144 -0
- modelforge_finetuning-4.0.1/README.md +90 -0
- modelforge_finetuning-4.0.1/cli/display.py +164 -0
- modelforge_finetuning-4.0.1/cli/main.py +169 -0
- modelforge_finetuning-4.0.1/cli/runner.py +5 -0
- modelforge_finetuning-4.0.1/cli/terminal.py +160 -0
- modelforge_finetuning-4.0.1/cli/wizard.py +217 -0
- modelforge_finetuning-4.0.1/dataset_manager/dataset_factory.py +188 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/model_factory.py +58 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/strategies/__init__.py +7 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/strategies/dpo.py +358 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/strategies/grpo.py +295 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/strategies/qa.py +185 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/strategies/sft.py +519 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/strategies/strategy.py +223 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/strategy_factory.py +67 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/tasks/__init__.py +11 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/tasks/causal_language_modeling.py +15 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/tasks/question_answering.py +11 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/tasks/seq2seq_modeling.py +19 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/tasks/task.py +38 -0
- modelforge_finetuning-4.0.1/finetuning_strategies/tasks/token_classification.py +19 -0
- modelforge_finetuning-4.0.1/modelforge_finetuning.egg-info/PKG-INFO +144 -0
- modelforge_finetuning-4.0.1/modelforge_finetuning.egg-info/SOURCES.txt +121 -0
- modelforge_finetuning-4.0.1/modelforge_finetuning.egg-info/entry_points.txt +3 -0
- modelforge_finetuning-4.0.1/modelforge_finetuning.egg-info/requires.txt +31 -0
- modelforge_finetuning-4.0.1/modelforge_finetuning.egg-info/top_level.txt +9 -0
- modelforge_finetuning-4.0.1/notebook_cli/__init__.py +5 -0
- modelforge_finetuning-4.0.1/notebook_cli/main.py +116 -0
- modelforge_finetuning-4.0.1/providers/__init__.py +5 -0
- modelforge_finetuning-4.0.1/providers/huggingface.py +35 -0
- modelforge_finetuning-4.0.1/providers/provider.py +35 -0
- modelforge_finetuning-4.0.1/providers/provider_factory.py +22 -0
- modelforge_finetuning-4.0.1/pyproject.toml +93 -0
- modelforge_finetuning-4.0.1/recommendation_engine/__init__.py +17 -0
- modelforge_finetuning-4.0.1/recommendation_engine/language_use_cases/__init__.py +14 -0
- modelforge_finetuning-4.0.1/recommendation_engine/language_use_cases/extractive_qa.py +31 -0
- modelforge_finetuning-4.0.1/recommendation_engine/language_use_cases/instruction_following.py +56 -0
- modelforge_finetuning-4.0.1/recommendation_engine/language_use_cases/summarization.py +28 -0
- modelforge_finetuning-4.0.1/recommendation_engine/language_use_cases/text_generation.py +56 -0
- modelforge_finetuning-4.0.1/recommendation_engine/language_use_cases/use_case.py +131 -0
- modelforge_finetuning-4.0.1/recommendation_engine/validation_models/__init__.py +7 -0
- modelforge_finetuning-4.0.1/recommendation_engine/validation_models/recommendation.py +107 -0
- modelforge_finetuning-4.0.1/scripts/build_frontend.py +119 -0
- modelforge_finetuning-4.0.1/setup.py +102 -0
- modelforge_finetuning-4.0.1/utilities/chat_format.py +87 -0
- modelforge_finetuning-4.0.1/utilities/database_manager.py +613 -0
- modelforge_finetuning-4.0.1/utilities/fsdp_config.py +40 -0
- modelforge_finetuning-4.0.1/utilities/hardware_detector.py +136 -0
- modelforge_finetuning-4.0.1/utilities/parallelism_strategy.py +6 -0
- modelforge_finetuning-4.0.1/utilities/parallelism_validator.py +17 -0
- modelforge_finetuning-4.0.1/utilities/precision.py +13 -0
- modelforge_finetuning-4.0.1/utilities/qa_inference.py +28 -0
- modelforge_finetuning-4.0.1/utilities/recommendation_engine.py +599 -0
- modelforge_finetuning-4.0.1/utilities/tensorboard.py +36 -0
- modelforge_finetuning-4.0.1/utilities/training_objective.py +7 -0
- modelforge_finetuning-4.0.1/web/__init__.py +1 -0
- modelforge_finetuning-4.0.1/web/app.py +405 -0
- modelforge_finetuning-4.0.1/web/auth.py +32 -0
- modelforge_finetuning-4.0.1/web/frontend/index.html +27 -0
- modelforge_finetuning-4.0.1/web/frontend/package-lock.json +3072 -0
- modelforge_finetuning-4.0.1/web/frontend/package.json +29 -0
- modelforge_finetuning-4.0.1/web/frontend/public/apple-touch-icon.png +0 -0
- modelforge_finetuning-4.0.1/web/frontend/public/favicon.ico +0 -0
- modelforge_finetuning-4.0.1/web/frontend/public/favicon.svg +5 -0
- modelforge_finetuning-4.0.1/web/frontend/public/landing-mock/live-run.html +319 -0
- modelforge_finetuning-4.0.1/web/frontend/public/landing-mock/new-run.html +268 -0
- modelforge_finetuning-4.0.1/web/frontend/public/landing-mock/theme.js +18 -0
- modelforge_finetuning-4.0.1/web/frontend/public/landing-mock/workbench.css +198 -0
- modelforge_finetuning-4.0.1/web/frontend/public/logo.svg +20536 -0
- modelforge_finetuning-4.0.1/web/frontend/src/LandingReference.tsx +62 -0
- modelforge_finetuning-4.0.1/web/frontend/src/docs/DocsSite.tsx +111 -0
- modelforge_finetuning-4.0.1/web/frontend/src/docs/content/advanced.tsx +140 -0
- modelforge_finetuning-4.0.1/web/frontend/src/docs/content/basics.tsx +135 -0
- modelforge_finetuning-4.0.1/web/frontend/src/docs/content/getStarted.tsx +160 -0
- modelforge_finetuning-4.0.1/web/frontend/src/docs/content/intermediate.tsx +167 -0
- modelforge_finetuning-4.0.1/web/frontend/src/docs/content/reference.tsx +185 -0
- modelforge_finetuning-4.0.1/web/frontend/src/docs/diagrams.tsx +110 -0
- modelforge_finetuning-4.0.1/web/frontend/src/docs/docs.css +152 -0
- modelforge_finetuning-4.0.1/web/frontend/src/docs/pages.ts +8 -0
- modelforge_finetuning-4.0.1/web/frontend/src/docs/rtd.ts +31 -0
- modelforge_finetuning-4.0.1/web/frontend/src/docs/ui.tsx +60 -0
- modelforge_finetuning-4.0.1/web/frontend/src/landing-reference.css +340 -0
- modelforge_finetuning-4.0.1/web/frontend/src/landing-reference.html +128 -0
- modelforge_finetuning-4.0.1/web/frontend/src/lib/progress.ts +139 -0
- modelforge_finetuning-4.0.1/web/frontend/src/main.tsx +61 -0
- modelforge_finetuning-4.0.1/web/frontend/src/style.css +3 -0
- modelforge_finetuning-4.0.1/web/frontend/src/vite-env.d.ts +1 -0
- modelforge_finetuning-4.0.1/web/frontend/tests/docs-rtd.test.ts +17 -0
- modelforge_finetuning-4.0.1/web/frontend/tests/progress.test.ts +8 -0
- modelforge_finetuning-4.0.1/web/frontend/tests/routes.test.tsx +13 -0
- modelforge_finetuning-4.0.1/web/frontend/tests/streaming.test.tsx +37 -0
- modelforge_finetuning-4.0.1/web/frontend/tsconfig.json +23 -0
- modelforge_finetuning-4.0.1/web/frontend/tsconfig.node.json +12 -0
- modelforge_finetuning-4.0.1/web/frontend/vite.config.ts +23 -0
- modelforge_finetuning-4.0.1/web/frontend/vitest.config.ts +3 -0
- modelforge_finetuning-4.0.1/web/frontend_dist/apple-touch-icon.png +0 -0
- modelforge_finetuning-4.0.1/web/frontend_dist/assets/index-BaXV8yBa.js +176 -0
- modelforge_finetuning-4.0.1/web/frontend_dist/assets/index-DJCUtHGc.css +1 -0
- modelforge_finetuning-4.0.1/web/frontend_dist/favicon.ico +0 -0
- modelforge_finetuning-4.0.1/web/frontend_dist/favicon.svg +5 -0
- modelforge_finetuning-4.0.1/web/frontend_dist/index.html +28 -0
- modelforge_finetuning-4.0.1/web/frontend_dist/landing-mock/live-run.html +319 -0
- modelforge_finetuning-4.0.1/web/frontend_dist/landing-mock/new-run.html +268 -0
- modelforge_finetuning-4.0.1/web/frontend_dist/landing-mock/theme.js +18 -0
- modelforge_finetuning-4.0.1/web/frontend_dist/landing-mock/workbench.css +198 -0
- modelforge_finetuning-4.0.1/web/frontend_dist/logo.svg +20536 -0
- modelforge_finetuning-4.0.1/web/playground.py +261 -0
- modelforge_finetuning-4.0.1/workflow/__init__.py +9 -0
- modelforge_finetuning-4.0.1/workflow/jobs.py +419 -0
- modelforge_finetuning-4.0.1/workflow/models.py +101 -0
- modelforge_finetuning-4.0.1/workflow/playground.py +329 -0
- modelforge_finetuning-4.0.1/workflow/registries.py +16 -0
- modelforge_finetuning-4.0.1/workflow/service.py +298 -0
- modelforge_finetuning-4.0.1/workflow/training.py +131 -0
- modelforge_finetuning-3.0.5/MANIFEST.in +0 -1
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/asset-manifest.json +0 -15
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/index.html +0 -1
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/logo192.png +0 -0
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/logo512.png +0 -0
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/manifest.json +0 -25
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/robots.txt +0 -3
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/css/main.5a3d6ea1.css +0 -4
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/css/main.5a3d6ea1.css.map +0 -1
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/css/main.9680427d.css +0 -4
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/css/main.9680427d.css.map +0 -1
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/453.6e4f956a.chunk.js +0 -2
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/453.6e4f956a.chunk.js.map +0 -1
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/453.ad6eb26e.chunk.js +0 -2
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/453.ad6eb26e.chunk.js.map +0 -1
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/main.2b0344e0.js +0 -3
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/main.2b0344e0.js.LICENSE.txt +0 -49
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/main.2b0344e0.js.map +0 -1
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/main.9cc9257a.js +0 -3
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/main.9cc9257a.js.LICENSE.txt +0 -60
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/main.9cc9257a.js.map +0 -1
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/main.9df15fbf.js +0 -3
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/main.9df15fbf.js.LICENSE.txt +0 -60
- modelforge_finetuning-3.0.5/ModelForge/Frontend/build/static/js/main.9df15fbf.js.map +0 -1
- modelforge_finetuning-3.0.5/ModelForge/app.py +0 -231
- modelforge_finetuning-3.0.5/ModelForge/cli.py +0 -130
- modelforge_finetuning-3.0.5/ModelForge/database/__init__.py +0 -4
- modelforge_finetuning-3.0.5/ModelForge/database/database_manager.py +0 -272
- modelforge_finetuning-3.0.5/ModelForge/database/models.py +0 -44
- modelforge_finetuning-3.0.5/ModelForge/dependencies.py +0 -160
- modelforge_finetuning-3.0.5/ModelForge/evaluation/__init__.py +0 -4
- modelforge_finetuning-3.0.5/ModelForge/evaluation/dataset_validator.py +0 -127
- modelforge_finetuning-3.0.5/ModelForge/evaluation/metrics.py +0 -172
- modelforge_finetuning-3.0.5/ModelForge/exceptions.py +0 -44
- modelforge_finetuning-3.0.5/ModelForge/formatters/__init__.py +0 -8
- modelforge_finetuning-3.0.5/ModelForge/formatters/formatting_functions.py +0 -166
- modelforge_finetuning-3.0.5/ModelForge/globals/__init__.py +0 -1
- modelforge_finetuning-3.0.5/ModelForge/globals/globals.py +0 -82
- modelforge_finetuning-3.0.5/ModelForge/globals/globals_instance.py +0 -3
- modelforge_finetuning-3.0.5/ModelForge/logging_config.py +0 -49
- modelforge_finetuning-3.0.5/ModelForge/model_configs/high_end.json +0 -35
- modelforge_finetuning-3.0.5/ModelForge/model_configs/low_end.json +0 -35
- modelforge_finetuning-3.0.5/ModelForge/model_configs/mid_range.json +0 -35
- modelforge_finetuning-3.0.5/ModelForge/notebook_cli/__init__.py +0 -20
- modelforge_finetuning-3.0.5/ModelForge/notebook_cli/progress.py +0 -138
- modelforge_finetuning-3.0.5/ModelForge/notebook_cli/prompts.py +0 -445
- modelforge_finetuning-3.0.5/ModelForge/notebook_cli/wizard.py +0 -445
- modelforge_finetuning-3.0.5/ModelForge/providers/__init__.py +0 -75
- modelforge_finetuning-3.0.5/ModelForge/providers/huggingface_provider.py +0 -201
- modelforge_finetuning-3.0.5/ModelForge/providers/provider_factory.py +0 -67
- modelforge_finetuning-3.0.5/ModelForge/providers/unsloth_provider.py +0 -217
- modelforge_finetuning-3.0.5/ModelForge/routers/finetuning_router.py +0 -577
- modelforge_finetuning-3.0.5/ModelForge/routers/hub_management_router.py +0 -79
- modelforge_finetuning-3.0.5/ModelForge/routers/models_router.py +0 -165
- modelforge_finetuning-3.0.5/ModelForge/routers/playground_router.py +0 -64
- modelforge_finetuning-3.0.5/ModelForge/schemas/__init__.py +0 -4
- modelforge_finetuning-3.0.5/ModelForge/schemas/training_schemas.py +0 -212
- modelforge_finetuning-3.0.5/ModelForge/services/__init__.py +0 -4
- modelforge_finetuning-3.0.5/ModelForge/services/hardware_service.py +0 -134
- modelforge_finetuning-3.0.5/ModelForge/services/model_service.py +0 -121
- modelforge_finetuning-3.0.5/ModelForge/services/training_service.py +0 -791
- modelforge_finetuning-3.0.5/ModelForge/strategies/__init__.py +0 -88
- modelforge_finetuning-3.0.5/ModelForge/strategies/dpo_strategy.py +0 -188
- modelforge_finetuning-3.0.5/ModelForge/strategies/qlora_strategy.py +0 -286
- modelforge_finetuning-3.0.5/ModelForge/strategies/rlhf_strategy.py +0 -198
- modelforge_finetuning-3.0.5/ModelForge/strategies/sft_strategy.py +0 -300
- modelforge_finetuning-3.0.5/ModelForge/strategies/strategy_factory.py +0 -89
- modelforge_finetuning-3.0.5/ModelForge/test_datasets/low_qa_train_set.jsonl +0 -310
- modelforge_finetuning-3.0.5/ModelForge/test_datasets/low_summarization_train_set.jsonl +0 -100
- modelforge_finetuning-3.0.5/ModelForge/test_datasets/low_text_generation.jsonl +0 -142
- modelforge_finetuning-3.0.5/ModelForge/test_datasets/med_construction.jsonl +0 -460
- modelforge_finetuning-3.0.5/ModelForge/test_datasets/med_text_generation.jsonl +0 -146
- modelforge_finetuning-3.0.5/ModelForge/test_datasets/question_answer-train-data-sample.jsonl +0 -101
- modelforge_finetuning-3.0.5/ModelForge/test_datasets/test_dataset.json +0 -28
- modelforge_finetuning-3.0.5/ModelForge/test_datasets/test_financial_advisory_generation.jsonl +0 -131
- modelforge_finetuning-3.0.5/ModelForge/test_datasets/test_financial_advisory_generation_bak.jsonl +0 -131
- modelforge_finetuning-3.0.5/ModelForge/utilities/__init__.py +0 -0
- modelforge_finetuning-3.0.5/ModelForge/utilities/chat_playground.py +0 -191
- modelforge_finetuning-3.0.5/ModelForge/utilities/configs/hardware_thresholds.json +0 -34
- modelforge_finetuning-3.0.5/ModelForge/utilities/configs/tasks.json +0 -25
- modelforge_finetuning-3.0.5/ModelForge/utilities/device_utils.py +0 -246
- modelforge_finetuning-3.0.5/ModelForge/utilities/finetuning/__init__.py +0 -0
- modelforge_finetuning-3.0.5/ModelForge/utilities/finetuning/quantization.py +0 -127
- modelforge_finetuning-3.0.5/ModelForge/utilities/finetuning/settings_builder.py +0 -168
- modelforge_finetuning-3.0.5/ModelForge/utilities/hardware_detection/__init__.py +0 -0
- modelforge_finetuning-3.0.5/ModelForge/utilities/hardware_detection/config_manager.py +0 -342
- modelforge_finetuning-3.0.5/ModelForge/utilities/hardware_detection/hardware_detector.py +0 -320
- modelforge_finetuning-3.0.5/ModelForge/utilities/hardware_detection/hardware_detector_factory.py +0 -113
- modelforge_finetuning-3.0.5/ModelForge/utilities/hardware_detection/model_recommendation.py +0 -253
- modelforge_finetuning-3.0.5/ModelForge/utilities/hardware_detection/model_validator.py +0 -178
- modelforge_finetuning-3.0.5/ModelForge/utilities/settings_managers/DBManager.py +0 -164
- modelforge_finetuning-3.0.5/ModelForge/utilities/settings_managers/FileManager.py +0 -67
- modelforge_finetuning-3.0.5/ModelForge/utilities/settings_managers/__init__.py +0 -0
- modelforge_finetuning-3.0.5/PKG-INFO +0 -298
- modelforge_finetuning-3.0.5/README.md +0 -255
- modelforge_finetuning-3.0.5/modelforge_finetuning.egg-info/PKG-INFO +0 -298
- modelforge_finetuning-3.0.5/modelforge_finetuning.egg-info/SOURCES.txt +0 -107
- modelforge_finetuning-3.0.5/modelforge_finetuning.egg-info/entry_points.txt +0 -3
- modelforge_finetuning-3.0.5/modelforge_finetuning.egg-info/requires.txt +0 -33
- modelforge_finetuning-3.0.5/modelforge_finetuning.egg-info/top_level.txt +0 -1
- modelforge_finetuning-3.0.5/pyproject.toml +0 -86
- modelforge_finetuning-3.0.5/tests/test_device_utils.py +0 -70
- {modelforge_finetuning-3.0.5 → modelforge_finetuning-4.0.1}/LICENSE +0 -0
- {modelforge_finetuning-3.0.5/ModelForge → modelforge_finetuning-4.0.1/cli}/__init__.py +0 -0
- {modelforge_finetuning-3.0.5/ModelForge/routers → modelforge_finetuning-4.0.1/finetuning_strategies}/__init__.py +0 -0
- {modelforge_finetuning-3.0.5 → modelforge_finetuning-4.0.1}/modelforge_finetuning.egg-info/dependency_links.txt +0 -0
- {modelforge_finetuning-3.0.5 → modelforge_finetuning-4.0.1}/setup.cfg +0 -0
- /modelforge_finetuning-3.0.5/ModelForge/Frontend/build/favicon.ico → /modelforge_finetuning-4.0.1/web/frontend/public/Logo.jpg +0 -0
- /modelforge_finetuning-3.0.5/ModelForge/Frontend/build/favicon.jpg → /modelforge_finetuning-4.0.1/web/frontend_dist/Logo.jpg +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modelforge-finetuning
|
|
3
|
+
Version: 4.0.1
|
|
4
|
+
Summary: Hardware-aware fine-tuning utility with browser, terminal, and notebook interfaces.
|
|
5
|
+
Author-email: R3tr0 M1ll3r <r3tr0.m1ll3r@gmail.com>
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/ForgeOpus/ModelForge
|
|
8
|
+
Project-URL: Documentation, https://modelforge-finetuning.readthedocs.io
|
|
9
|
+
Project-URL: Repository, https://github.com/ForgeOpus/ModelForge
|
|
10
|
+
Project-URL: Issues, https://github.com/ForgeOpus/ModelForge/issues
|
|
11
|
+
Project-URL: Changelog, https://modelforge-finetuning.readthedocs.io/en/latest/getting-started/whats-new/
|
|
12
|
+
Project-URL: Organization, https://github.com/ForgeOpus
|
|
13
|
+
Keywords: fine-tuning,llm,huggingface,lora,qlora,dpo,grpo,peft,transformers
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Classifier: Environment :: GPU :: NVIDIA CUDA
|
|
16
|
+
Classifier: Environment :: Web Environment
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: Intended Audience :: Science/Research
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
23
|
+
Requires-Python: >=3.13
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: accelerate>=1.13.0
|
|
27
|
+
Requires-Dist: bitsandbytes>=0.49.2
|
|
28
|
+
Requires-Dist: fastapi>=0.124.0
|
|
29
|
+
Requires-Dist: huggingface-hub>=1.14.0
|
|
30
|
+
Requires-Dist: nvidia-ml-py>=13.595.45
|
|
31
|
+
Requires-Dist: peft>=0.19.1
|
|
32
|
+
Requires-Dist: platformdirs>=4.9.6
|
|
33
|
+
Requires-Dist: psutil>=6.0
|
|
34
|
+
Requires-Dist: pydantic>=2.13.4
|
|
35
|
+
Requires-Dist: uvicorn>=0.38.0
|
|
36
|
+
Requires-Dist: websockets>=13.0
|
|
37
|
+
Requires-Dist: tensorboard>=2.20.0
|
|
38
|
+
Requires-Dist: tqdm>=4.67.3
|
|
39
|
+
Requires-Dist: transformers>=5.8.0
|
|
40
|
+
Requires-Dist: trl>=1.4.0
|
|
41
|
+
Requires-Dist: setuptools>=81.0.0
|
|
42
|
+
Provides-Extra: cli
|
|
43
|
+
Requires-Dist: click>=8.1; extra == "cli"
|
|
44
|
+
Requires-Dist: rich>=13.0; extra == "cli"
|
|
45
|
+
Provides-Extra: notebook
|
|
46
|
+
Provides-Extra: gpu
|
|
47
|
+
Requires-Dist: liger-kernel>=0.5.0; extra == "gpu"
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: click>=8.1; extra == "dev"
|
|
50
|
+
Requires-Dist: httpx>=0.28.0; extra == "dev"
|
|
51
|
+
Requires-Dist: pytest>=9.0.3; extra == "dev"
|
|
52
|
+
Requires-Dist: rich>=13.0; extra == "dev"
|
|
53
|
+
Dynamic: license-file
|
|
54
|
+
|
|
55
|
+
# ModelForge
|
|
56
|
+
|
|
57
|
+
[](https://pypi.org/project/modelforge-finetuning/)
|
|
58
|
+
[](https://pypi.org/project/modelforge-finetuning/)
|
|
59
|
+
[](https://modelforge-finetuning.readthedocs.io)
|
|
60
|
+
[](https://github.com/ForgeOpus/ModelForge/blob/main/LICENSE)
|
|
61
|
+
[](https://pepy.tech/projects/modelforge-finetuning)
|
|
62
|
+
|
|
63
|
+
<a href="https://www.producthunt.com/products/forgeopus?embed=true&utm_source=badge-featured&utm_medium=badge&utm_campaign=badge-forgeopus" target="_blank" rel="noopener noreferrer"><img alt="ForgeOpus - Where AI masterpieces are forged. Your work, your opus. | Product Hunt" width="250" height="54" src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1080450&theme=light&t=1771311433851"></a>
|
|
64
|
+
|
|
65
|
+

|
|
66
|
+
|
|
67
|
+
Hardware-aware fine-tuning for open models from the Hugging Face Hub, with browser, terminal and notebook interfaces.
|
|
68
|
+
|
|
69
|
+
ModelForge reads your GPUs, works out how large a model fits, picks a training recipe for your goal, and runs it while you watch the loss come down. It shows its reasoning before anything starts, so you don't find out at step 40 that the run doesn't fit in memory.
|
|
70
|
+
|
|
71
|
+
## Features
|
|
72
|
+
|
|
73
|
+
- **Hardware-aware planning.** Total VRAM, the strategy's memory overhead and a per-parameter cost set a ceiling on model size. ModelForge picks full fine-tuning, LoRA or QLoRA (8-bit or 4-bit) to match.
|
|
74
|
+
- **A recipe for each goal.** Supervised fine-tuning (SFT), preference training (DPO) and reinforcement training (GRPO), plus native trainers for summarization and extractive QA.
|
|
75
|
+
- **Model recommendations.** Searches the Hub for popular models of the right type that fit your hardware, or validates any model ID you enter.
|
|
76
|
+
- **Multi-GPU.** Data parallel by default, switching to FSDP automatically when a full fine-tune is too large for one card.
|
|
77
|
+
- **Live runs.** Streamed training logs, checkpoints you can resume from, and TensorBoard logging.
|
|
78
|
+
- **Playground.** Chat with a finished model or any checkpoint in the browser, even while another run is training.
|
|
79
|
+
|
|
80
|
+
## Install
|
|
81
|
+
|
|
82
|
+
ModelForge needs Python 3.13 or newer. Real training needs an NVIDIA GPU with CUDA. Apple Silicon (MPS) and CPU-only machines work, but only with small models.
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pip install modelforge-finetuning
|
|
86
|
+
|
|
87
|
+
# Optional extras: the terminal wizard, and Liger kernels for CUDA
|
|
88
|
+
pip install "modelforge-finetuning[cli,gpu]"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Per-OS instructions, including PyTorch with CUDA, are in the [installation guides](https://modelforge-finetuning.readthedocs.io/en/latest/installation/linux/).
|
|
92
|
+
|
|
93
|
+
## Quick start
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
modelforge run
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
This starts the server and opens the browser console. The link it prints includes a one-time token that connects your browser. On a remote machine, use `modelforge run --no-browser --host 127.0.0.1` and connect through an SSH tunnel.
|
|
100
|
+
|
|
101
|
+
For gated models such as Llama, accept the licence on the model's Hub page, then log in once with `hf auth login`.
|
|
102
|
+
|
|
103
|
+
| Interface | Command | Best for |
|
|
104
|
+
|---|---|---|
|
|
105
|
+
| Browser console | `modelforge run` | Most people |
|
|
106
|
+
| Terminal wizard | `modelforge cli` | Headless servers over SSH (needs `[cli]`) |
|
|
107
|
+
| Notebook | `modelforge-nb` | Jupyter and Colab |
|
|
108
|
+
|
|
109
|
+
The [Quick Start guide](https://modelforge-finetuning.readthedocs.io/en/latest/getting-started/quickstart/) walks through a first run.
|
|
110
|
+
|
|
111
|
+
## Documentation
|
|
112
|
+
|
|
113
|
+
Full documentation is at **[modelforge-finetuning.readthedocs.io](https://modelforge-finetuning.readthedocs.io)**. A shorter version ships inside the app at `/app/docs`.
|
|
114
|
+
|
|
115
|
+
- [What's new in v4 and migrating from v3](https://modelforge-finetuning.readthedocs.io/en/latest/getting-started/whats-new/)
|
|
116
|
+
- [Dataset formats](https://modelforge-finetuning.readthedocs.io/en/latest/configuration/dataset-formats/)
|
|
117
|
+
- [How planning works](https://modelforge-finetuning.readthedocs.io/en/latest/configuration/configuration-guide/)
|
|
118
|
+
- [Training strategies](https://modelforge-finetuning.readthedocs.io/en/latest/strategies/overview/)
|
|
119
|
+
- [REST API](https://modelforge-finetuning.readthedocs.io/en/latest/api-reference/rest-api/)
|
|
120
|
+
- [Troubleshooting](https://modelforge-finetuning.readthedocs.io/en/latest/troubleshooting/common-issues/)
|
|
121
|
+
|
|
122
|
+
## Running from source
|
|
123
|
+
|
|
124
|
+
Building or installing from a source checkout needs Node.js and npm, because the browser UI is compiled into `web/frontend_dist/`. That directory isn't committed.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
git clone https://github.com/ForgeOpus/ModelForge.git
|
|
128
|
+
cd ModelForge
|
|
129
|
+
uv sync --extra dev
|
|
130
|
+
python scripts/build_frontend.py # or, from web/frontend: npm ci && npm run build
|
|
131
|
+
uv run modelforge run --no-browser
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`pip wheel .`, `python -m build` and `uv build` run the frontend build automatically, and fail if Node.js is missing, so a wheel is never published without a UI. Installing an already-built wheel doesn't need Node.
|
|
135
|
+
|
|
136
|
+
See the [development guide](https://modelforge-finetuning.readthedocs.io/en/latest/contributing/development/) and [DEVELOPER_GUIDE.md](https://github.com/ForgeOpus/ModelForge/blob/main/DEVELOPER_GUIDE.md) for the codebase tour, tests and the release process.
|
|
137
|
+
|
|
138
|
+
## Contributing
|
|
139
|
+
|
|
140
|
+
Contributions are welcome. Read the [contributing guide](https://modelforge-finetuning.readthedocs.io/en/latest/contributing/contributing/) and the [code of conduct](https://github.com/ForgeOpus/ModelForge/blob/main/CODE_OF_CONDUCT.md), and report bugs or request features through [GitHub issues](https://github.com/ForgeOpus/ModelForge/issues).
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
ModelForge is released under the [BSD 3-Clause License](https://github.com/ForgeOpus/ModelForge/blob/main/LICENSE).
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# ModelForge
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/modelforge-finetuning/)
|
|
4
|
+
[](https://pypi.org/project/modelforge-finetuning/)
|
|
5
|
+
[](https://modelforge-finetuning.readthedocs.io)
|
|
6
|
+
[](https://github.com/ForgeOpus/ModelForge/blob/main/LICENSE)
|
|
7
|
+
[](https://pepy.tech/projects/modelforge-finetuning)
|
|
8
|
+
|
|
9
|
+
<a href="https://www.producthunt.com/products/forgeopus?embed=true&utm_source=badge-featured&utm_medium=badge&utm_campaign=badge-forgeopus" target="_blank" rel="noopener noreferrer"><img alt="ForgeOpus - Where AI masterpieces are forged. Your work, your opus. | Product Hunt" width="250" height="54" src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1080450&theme=light&t=1771311433851"></a>
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
Hardware-aware fine-tuning for open models from the Hugging Face Hub, with browser, terminal and notebook interfaces.
|
|
14
|
+
|
|
15
|
+
ModelForge reads your GPUs, works out how large a model fits, picks a training recipe for your goal, and runs it while you watch the loss come down. It shows its reasoning before anything starts, so you don't find out at step 40 that the run doesn't fit in memory.
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- **Hardware-aware planning.** Total VRAM, the strategy's memory overhead and a per-parameter cost set a ceiling on model size. ModelForge picks full fine-tuning, LoRA or QLoRA (8-bit or 4-bit) to match.
|
|
20
|
+
- **A recipe for each goal.** Supervised fine-tuning (SFT), preference training (DPO) and reinforcement training (GRPO), plus native trainers for summarization and extractive QA.
|
|
21
|
+
- **Model recommendations.** Searches the Hub for popular models of the right type that fit your hardware, or validates any model ID you enter.
|
|
22
|
+
- **Multi-GPU.** Data parallel by default, switching to FSDP automatically when a full fine-tune is too large for one card.
|
|
23
|
+
- **Live runs.** Streamed training logs, checkpoints you can resume from, and TensorBoard logging.
|
|
24
|
+
- **Playground.** Chat with a finished model or any checkpoint in the browser, even while another run is training.
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
ModelForge needs Python 3.13 or newer. Real training needs an NVIDIA GPU with CUDA. Apple Silicon (MPS) and CPU-only machines work, but only with small models.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install modelforge-finetuning
|
|
32
|
+
|
|
33
|
+
# Optional extras: the terminal wizard, and Liger kernels for CUDA
|
|
34
|
+
pip install "modelforge-finetuning[cli,gpu]"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Per-OS instructions, including PyTorch with CUDA, are in the [installation guides](https://modelforge-finetuning.readthedocs.io/en/latest/installation/linux/).
|
|
38
|
+
|
|
39
|
+
## Quick start
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
modelforge run
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This starts the server and opens the browser console. The link it prints includes a one-time token that connects your browser. On a remote machine, use `modelforge run --no-browser --host 127.0.0.1` and connect through an SSH tunnel.
|
|
46
|
+
|
|
47
|
+
For gated models such as Llama, accept the licence on the model's Hub page, then log in once with `hf auth login`.
|
|
48
|
+
|
|
49
|
+
| Interface | Command | Best for |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| Browser console | `modelforge run` | Most people |
|
|
52
|
+
| Terminal wizard | `modelforge cli` | Headless servers over SSH (needs `[cli]`) |
|
|
53
|
+
| Notebook | `modelforge-nb` | Jupyter and Colab |
|
|
54
|
+
|
|
55
|
+
The [Quick Start guide](https://modelforge-finetuning.readthedocs.io/en/latest/getting-started/quickstart/) walks through a first run.
|
|
56
|
+
|
|
57
|
+
## Documentation
|
|
58
|
+
|
|
59
|
+
Full documentation is at **[modelforge-finetuning.readthedocs.io](https://modelforge-finetuning.readthedocs.io)**. A shorter version ships inside the app at `/app/docs`.
|
|
60
|
+
|
|
61
|
+
- [What's new in v4 and migrating from v3](https://modelforge-finetuning.readthedocs.io/en/latest/getting-started/whats-new/)
|
|
62
|
+
- [Dataset formats](https://modelforge-finetuning.readthedocs.io/en/latest/configuration/dataset-formats/)
|
|
63
|
+
- [How planning works](https://modelforge-finetuning.readthedocs.io/en/latest/configuration/configuration-guide/)
|
|
64
|
+
- [Training strategies](https://modelforge-finetuning.readthedocs.io/en/latest/strategies/overview/)
|
|
65
|
+
- [REST API](https://modelforge-finetuning.readthedocs.io/en/latest/api-reference/rest-api/)
|
|
66
|
+
- [Troubleshooting](https://modelforge-finetuning.readthedocs.io/en/latest/troubleshooting/common-issues/)
|
|
67
|
+
|
|
68
|
+
## Running from source
|
|
69
|
+
|
|
70
|
+
Building or installing from a source checkout needs Node.js and npm, because the browser UI is compiled into `web/frontend_dist/`. That directory isn't committed.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
git clone https://github.com/ForgeOpus/ModelForge.git
|
|
74
|
+
cd ModelForge
|
|
75
|
+
uv sync --extra dev
|
|
76
|
+
python scripts/build_frontend.py # or, from web/frontend: npm ci && npm run build
|
|
77
|
+
uv run modelforge run --no-browser
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`pip wheel .`, `python -m build` and `uv build` run the frontend build automatically, and fail if Node.js is missing, so a wheel is never published without a UI. Installing an already-built wheel doesn't need Node.
|
|
81
|
+
|
|
82
|
+
See the [development guide](https://modelforge-finetuning.readthedocs.io/en/latest/contributing/development/) and [DEVELOPER_GUIDE.md](https://github.com/ForgeOpus/ModelForge/blob/main/DEVELOPER_GUIDE.md) for the codebase tour, tests and the release process.
|
|
83
|
+
|
|
84
|
+
## Contributing
|
|
85
|
+
|
|
86
|
+
Contributions are welcome. Read the [contributing guide](https://modelforge-finetuning.readthedocs.io/en/latest/contributing/contributing/) and the [code of conduct](https://github.com/ForgeOpus/ModelForge/blob/main/CODE_OF_CONDUCT.md), and report bugs or request features through [GitHub issues](https://github.com/ForgeOpus/ModelForge/issues).
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
ModelForge is released under the [BSD 3-Clause License](https://github.com/ForgeOpus/ModelForge/blob/main/LICENSE).
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
from transformers import TrainerCallback
|
|
2
|
+
from rich.progress import Progress, BarColumn, TimeElapsedColumn, MofNCompleteColumn
|
|
3
|
+
from rich.console import Console
|
|
4
|
+
from rich.panel import Panel
|
|
5
|
+
from rich.table import Table, box
|
|
6
|
+
from rich.text import Text
|
|
7
|
+
from rich.rule import Rule
|
|
8
|
+
from rich import print as rprint
|
|
9
|
+
from utilities.hardware_detector import HardwareDetector
|
|
10
|
+
from recommendation_engine.validation_models.recommendation import Recommendation
|
|
11
|
+
|
|
12
|
+
console = Console()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def print_header() -> None:
|
|
16
|
+
banner_lines = [
|
|
17
|
+
(" __ __ _ _ _____", "bold red"),
|
|
18
|
+
("| \\/ | ___ __| | ___| || ___|__ _ __ __ _ ___", "bold yellow"),
|
|
19
|
+
("| |\\/| |/ _ \\ / _` |/ _ \\ || |_ / _ \\| '__/ _` |/ _ \\", "bold green"),
|
|
20
|
+
("| | | | (_) | (_| | __/ || _| (_) | | | (_| | __/", "bold cyan"),
|
|
21
|
+
("|_| |_|\\___/ \\__,_|\\___|_||_| \\___/|_| \\__, |\\___|", "bold blue"),
|
|
22
|
+
(" |___/", "bold magenta"),
|
|
23
|
+
]
|
|
24
|
+
banner_text = Text()
|
|
25
|
+
for line, color in banner_lines:
|
|
26
|
+
banner_text.append(line + "\n", style=color)
|
|
27
|
+
console.print(banner_text)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def print_hardware(hardware: HardwareDetector.HardwareSpecs) -> None:
|
|
31
|
+
table = Table(title="Detected Hardware", show_header=True)
|
|
32
|
+
table.add_column("Component", style="bold")
|
|
33
|
+
table.add_column("Details")
|
|
34
|
+
|
|
35
|
+
table.add_row("CPU", f"{hardware.physical_core_count} cores")
|
|
36
|
+
table.add_row("RAM", f"{hardware.ram_gb:.1f} GB")
|
|
37
|
+
table.add_row(
|
|
38
|
+
"Disk (free)",
|
|
39
|
+
f"{hardware.available_disk_storage_gb:.1f} / {hardware.disk_storage_gb:.1f} GB",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
for i, gpu in enumerate(hardware.gpus):
|
|
43
|
+
if gpu["total_memory_gb"] == "N/A":
|
|
44
|
+
detail = "Apple MPS — shared"
|
|
45
|
+
else:
|
|
46
|
+
detail = f"{gpu['name']} — {gpu['total_memory_gb']} GB VRAM"
|
|
47
|
+
table.add_row(f"GPU {i}", detail)
|
|
48
|
+
|
|
49
|
+
console.print(table)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
_PEFT_COLORS = {
|
|
53
|
+
"full_finetune": "bold green",
|
|
54
|
+
"lora_bf16": "bold cyan",
|
|
55
|
+
"qlora_8bit": "bold yellow",
|
|
56
|
+
"qlora_4bit": "bold orange1",
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def print_recommendation(recommendation: Recommendation) -> None:
|
|
61
|
+
r = recommendation
|
|
62
|
+
|
|
63
|
+
# ── Summary strip ──────────────────────────────────────────────────────────
|
|
64
|
+
peft_color = _PEFT_COLORS.get(r.peft_approach, "bold white")
|
|
65
|
+
summary = Table(box=box.SIMPLE, show_header=False, padding=(0, 2))
|
|
66
|
+
summary.add_column(style="bold dim", no_wrap=True)
|
|
67
|
+
summary.add_column()
|
|
68
|
+
summary.add_row("Strategy", r.strategy_slug)
|
|
69
|
+
summary.add_row("PEFT tier", Text(r.peft_approach, style=peft_color))
|
|
70
|
+
summary.add_row("Task", r.task_slug)
|
|
71
|
+
summary.add_row("Provider", r.provider_slug)
|
|
72
|
+
console.print(Panel(summary, title="[bold green]Recommendation[/bold green]", expand=False))
|
|
73
|
+
|
|
74
|
+
# ── Candidate models ───────────────────────────────────────────────────────
|
|
75
|
+
console.print(Rule("[bold]Candidate Models[/bold]", style="green"))
|
|
76
|
+
models_table = Table(box=box.ROUNDED, show_header=True, header_style="bold")
|
|
77
|
+
models_table.add_column("#", justify="right", style="dim", no_wrap=True)
|
|
78
|
+
models_table.add_column("Model ID", style="cyan", no_wrap=True)
|
|
79
|
+
models_table.add_column("Parameters", justify="right", no_wrap=True)
|
|
80
|
+
models_table.add_column("Downloads", justify="right", style="dim green", no_wrap=True)
|
|
81
|
+
for rank, m in enumerate(r.recommended_models, start=1):
|
|
82
|
+
models_table.add_row(
|
|
83
|
+
str(rank),
|
|
84
|
+
m.model_id,
|
|
85
|
+
f"{m.num_parameters / 1e9:.2f}B",
|
|
86
|
+
f"{m.downloads:,}",
|
|
87
|
+
)
|
|
88
|
+
console.print(models_table)
|
|
89
|
+
|
|
90
|
+
# ── Decision rationale ────────────────────────────────────────────────────
|
|
91
|
+
console.print(Rule("[bold]Decision Rationale[/bold]", style="dim"))
|
|
92
|
+
rationale = Table(box=box.SIMPLE, show_header=False, padding=(0, 2))
|
|
93
|
+
rationale.add_column(style="bold dim", no_wrap=True, width=14)
|
|
94
|
+
rationale.add_column(overflow="fold")
|
|
95
|
+
rationale.add_row("Hardware", r.rationale.vram_summary)
|
|
96
|
+
rationale.add_row("Use Case", r.rationale.use_case_resolution)
|
|
97
|
+
rationale.add_row("PEFT", r.rationale.peft_decision)
|
|
98
|
+
rationale.add_row("Model Filter", r.rationale.model_filter)
|
|
99
|
+
console.print(rationale)
|
|
100
|
+
|
|
101
|
+
# ── Warnings (only if present) ────────────────────────────────────────────
|
|
102
|
+
if r.rationale.warnings:
|
|
103
|
+
warn_text = "\n".join(f"[yellow]⚠[/yellow] {w}" for w in r.rationale.warnings)
|
|
104
|
+
console.print(Panel(warn_text, title="[bold yellow]Warnings[/bold yellow]", border_style="yellow", expand=False))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def print_training_summary(
|
|
108
|
+
model_id: str,
|
|
109
|
+
dataset_desc: str,
|
|
110
|
+
output_dir: str,
|
|
111
|
+
recommendation: Recommendation,
|
|
112
|
+
tensorboard_log_dir: str | None = None,
|
|
113
|
+
) -> None:
|
|
114
|
+
body = (
|
|
115
|
+
f"Model: {model_id}\n"
|
|
116
|
+
f"Dataset: {dataset_desc}\n"
|
|
117
|
+
f"Task: {recommendation.task_slug}\n"
|
|
118
|
+
f"Strategy: {recommendation.strategy_slug}\n"
|
|
119
|
+
f"PEFT approach: {recommendation.peft_approach}\n"
|
|
120
|
+
f"Output Dir: {output_dir}"
|
|
121
|
+
)
|
|
122
|
+
if tensorboard_log_dir:
|
|
123
|
+
body += f"\nTensorBoard: {tensorboard_log_dir}"
|
|
124
|
+
rprint(Panel(body, title="[bold blue]Training Summary[/bold blue]"))
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class RichTrainingCallback(TrainerCallback):
|
|
128
|
+
|
|
129
|
+
def __init__(self):
|
|
130
|
+
self.progress = None
|
|
131
|
+
self.task_id = None
|
|
132
|
+
self.current_step = 0
|
|
133
|
+
|
|
134
|
+
def on_train_begin(self, args, state, control, **kwargs):
|
|
135
|
+
self.current_step = 0
|
|
136
|
+
self.progress = Progress(
|
|
137
|
+
"[progress.description]{task.description}",
|
|
138
|
+
BarColumn(),
|
|
139
|
+
"[progress.percentage]{task.percentage:>3.0f}%",
|
|
140
|
+
TimeElapsedColumn(),
|
|
141
|
+
"•",
|
|
142
|
+
MofNCompleteColumn(),
|
|
143
|
+
)
|
|
144
|
+
self.progress.start()
|
|
145
|
+
self.task_id = self.progress.add_task("Training", total=state.max_steps)
|
|
146
|
+
|
|
147
|
+
def on_log(self, args, state, control, logs=None, **kwargs):
|
|
148
|
+
if logs is None:
|
|
149
|
+
return
|
|
150
|
+
step = logs.get("step", self.current_step + 1)
|
|
151
|
+
advance = step - self.current_step
|
|
152
|
+
self.current_step = step
|
|
153
|
+
loss = logs.get("loss", "N/A")
|
|
154
|
+
epoch = logs.get("epoch", "N/A")
|
|
155
|
+
self.progress.update(
|
|
156
|
+
self.task_id,
|
|
157
|
+
advance=advance,
|
|
158
|
+
description=f"Training loss={loss} epoch={epoch}",
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
def on_train_end(self, args, state, control, **kwargs):
|
|
162
|
+
if self.progress is not None:
|
|
163
|
+
self.progress.stop()
|
|
164
|
+
rprint("[bold green]Training complete![/bold green]")
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import sys
|
|
5
|
+
import webbrowser
|
|
6
|
+
|
|
7
|
+
from utilities.database_manager import FinetuneLedger, WebRunLedger
|
|
8
|
+
from utilities.hardware_detector import HardwareDetector
|
|
9
|
+
from utilities.recommendation_engine import RecommendationEngine
|
|
10
|
+
from utilities.tensorboard import DEFAULT_TENSORBOARD_HOST, DEFAULT_TENSORBOARD_PORT
|
|
11
|
+
from utilities.training_objective import TrainingObjective
|
|
12
|
+
from workflow.registries import load_core_registries
|
|
13
|
+
from workflow.service import WorkflowService
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def cli(argv: list[str] | None = None) -> None:
|
|
17
|
+
parser = build_parser()
|
|
18
|
+
args = parser.parse_args(argv)
|
|
19
|
+
if args.command is None:
|
|
20
|
+
parser.print_help()
|
|
21
|
+
return
|
|
22
|
+
args.func(args)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
26
|
+
parser = argparse.ArgumentParser(prog="modelforge")
|
|
27
|
+
subcommands = parser.add_subparsers(dest="command")
|
|
28
|
+
|
|
29
|
+
run = subcommands.add_parser("run", help="Start the browser UI.")
|
|
30
|
+
run.add_argument("--host", default="0.0.0.0", help="Host to bind. Defaults to 0.0.0.0.")
|
|
31
|
+
run.add_argument("--port", default=8000, type=int, help="Port to bind.")
|
|
32
|
+
run.add_argument("--no-browser", action="store_true", help="Do not open the UI in a browser.")
|
|
33
|
+
run.add_argument("--token", default=None, help="Use a fixed startup token instead of generating one.")
|
|
34
|
+
run.set_defaults(func=run_web)
|
|
35
|
+
|
|
36
|
+
terminal = subcommands.add_parser("cli", help="Start the optional terminal wizard.")
|
|
37
|
+
terminal.add_argument("--no-tensorboard", action="store_true", help="Disable TensorBoard logging.")
|
|
38
|
+
terminal.add_argument("--tensorboard-logdir", default=None, help="Directory for TensorBoard event logs.")
|
|
39
|
+
terminal.set_defaults(func=run_terminal)
|
|
40
|
+
|
|
41
|
+
recommend = subcommands.add_parser("recommend", help="Print hardware-aware model recommendations.")
|
|
42
|
+
recommend.add_argument("--use-case", default=None, help="Use case slug.")
|
|
43
|
+
recommend.add_argument("--objective", default="supervised", choices=[item.value for item in TrainingObjective])
|
|
44
|
+
recommend.add_argument("--n", default=5, type=int)
|
|
45
|
+
recommend.set_defaults(func=run_recommend)
|
|
46
|
+
|
|
47
|
+
history = subcommands.add_parser("history", help="Print run history.")
|
|
48
|
+
history.add_argument("--legacy", action="store_true", help="Show the legacy terminal finetune ledger.")
|
|
49
|
+
history.set_defaults(func=run_history)
|
|
50
|
+
|
|
51
|
+
list_tasks = subcommands.add_parser("list-tasks", help="List available use cases.")
|
|
52
|
+
list_tasks.set_defaults(func=run_list_tasks)
|
|
53
|
+
|
|
54
|
+
tensorboard = subcommands.add_parser("tensorboard", help="Launch TensorBoard for a log directory.")
|
|
55
|
+
tensorboard.add_argument("logdir", nargs="?", default=None)
|
|
56
|
+
tensorboard.add_argument("--host", default=DEFAULT_TENSORBOARD_HOST)
|
|
57
|
+
tensorboard.add_argument("--port", default=DEFAULT_TENSORBOARD_PORT, type=int)
|
|
58
|
+
tensorboard.set_defaults(func=run_tensorboard)
|
|
59
|
+
|
|
60
|
+
return parser
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def run_web(args: argparse.Namespace) -> None:
|
|
64
|
+
import uvicorn
|
|
65
|
+
from web.app import create_app
|
|
66
|
+
from web.auth import TokenAuth
|
|
67
|
+
|
|
68
|
+
auth = TokenAuth(args.token)
|
|
69
|
+
url = auth.public_url(args.host, args.port)
|
|
70
|
+
print("ModelForge v4 browser UI")
|
|
71
|
+
print(f"Serving on: http://{args.host}:{args.port}")
|
|
72
|
+
print(f"Open: {url}")
|
|
73
|
+
print("The startup token is required for API and WebSocket access.")
|
|
74
|
+
if not args.no_browser:
|
|
75
|
+
webbrowser.open(url)
|
|
76
|
+
app = create_app(auth=auth)
|
|
77
|
+
uvicorn.run(app, host=args.host, port=args.port)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def run_terminal(args: argparse.Namespace) -> None:
|
|
81
|
+
try:
|
|
82
|
+
from cli.terminal import run_terminal_wizard
|
|
83
|
+
except ImportError as exc:
|
|
84
|
+
raise SystemExit(
|
|
85
|
+
"The terminal UI requires optional dependencies. "
|
|
86
|
+
"Install with: pip install \"modelforge-finetuning[cli]\""
|
|
87
|
+
) from exc
|
|
88
|
+
run_terminal_wizard(
|
|
89
|
+
tensorboard=not args.no_tensorboard,
|
|
90
|
+
tensorboard_logdir=args.tensorboard_logdir,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def run_recommend(args: argparse.Namespace) -> None:
|
|
95
|
+
load_core_registries()
|
|
96
|
+
service = WorkflowService()
|
|
97
|
+
use_case = args.use_case or _prompt_use_case(service)
|
|
98
|
+
hardware = HardwareDetector.detect_hardware()
|
|
99
|
+
recommendation = RecommendationEngine.recommend(
|
|
100
|
+
use_case,
|
|
101
|
+
TrainingObjective(args.objective),
|
|
102
|
+
hardware,
|
|
103
|
+
n=args.n,
|
|
104
|
+
)
|
|
105
|
+
print(f"Task: {recommendation.task_slug}")
|
|
106
|
+
print(f"Strategy: {recommendation.strategy_slug}")
|
|
107
|
+
print(f"PEFT: {recommendation.peft_approach}")
|
|
108
|
+
print("Models:")
|
|
109
|
+
for model in recommendation.recommended_models:
|
|
110
|
+
print(f" - {model.model_id} ({model.num_parameters:,} params, {model.downloads:,} downloads)")
|
|
111
|
+
if recommendation.rationale.warnings:
|
|
112
|
+
print("Warnings:")
|
|
113
|
+
for warning in recommendation.rationale.warnings:
|
|
114
|
+
print(f" - {warning}")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def run_history(args: argparse.Namespace) -> None:
|
|
118
|
+
if args.legacy:
|
|
119
|
+
runs = FinetuneLedger().list_runs()
|
|
120
|
+
for run in runs:
|
|
121
|
+
print(f"{run['id']}: {run['timestamp']} {run['model_id']} ({run['peft']}) -> {run['output_dir']}")
|
|
122
|
+
if not runs:
|
|
123
|
+
print("No legacy finetune runs recorded yet.")
|
|
124
|
+
return
|
|
125
|
+
runs = WebRunLedger().list_runs()
|
|
126
|
+
for run in runs:
|
|
127
|
+
print(f"{run['id']}: {run['status']} {run['model_id']} -> {run['output_dir']}")
|
|
128
|
+
if not runs:
|
|
129
|
+
print("No runs recorded yet.")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def run_list_tasks(args: argparse.Namespace) -> None:
|
|
133
|
+
service = WorkflowService()
|
|
134
|
+
for use_case in service.list_use_cases():
|
|
135
|
+
objectives = ", ".join(use_case["compatible_objectives"])
|
|
136
|
+
print(f"{use_case['slug']}: {use_case['name']} [{objectives}]")
|
|
137
|
+
print(f" {use_case['description']}")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def run_tensorboard(args: argparse.Namespace) -> None:
|
|
141
|
+
try:
|
|
142
|
+
from cli.terminal import tensorboard_cmd
|
|
143
|
+
except ImportError as exc:
|
|
144
|
+
raise SystemExit(
|
|
145
|
+
"The TensorBoard terminal helper requires optional dependencies. "
|
|
146
|
+
"Install with: pip install \"modelforge-finetuning[cli]\""
|
|
147
|
+
) from exc
|
|
148
|
+
tensorboard_cmd(args.logdir, args.host, args.port)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _prompt_use_case(service: WorkflowService) -> str:
|
|
152
|
+
use_cases = service.list_use_cases()
|
|
153
|
+
print("Available use cases:")
|
|
154
|
+
for index, use_case in enumerate(use_cases, start=1):
|
|
155
|
+
print(f" {index}. {use_case['name']} ({use_case['slug']})")
|
|
156
|
+
while True:
|
|
157
|
+
raw = input("Select use case: ").strip()
|
|
158
|
+
try:
|
|
159
|
+
choice = int(raw)
|
|
160
|
+
if 1 <= choice <= len(use_cases):
|
|
161
|
+
return use_cases[choice - 1]["slug"]
|
|
162
|
+
except ValueError:
|
|
163
|
+
if any(use_case["slug"] == raw for use_case in use_cases):
|
|
164
|
+
return raw
|
|
165
|
+
print("Enter a number from the list or a use case slug.")
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
if __name__ == "__main__":
|
|
169
|
+
cli(sys.argv[1:])
|