modelforge-finetuning 3.0.3__tar.gz → 3.0.5__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-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/cli.py +2 -2
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/evaluation/metrics.py +10 -18
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/notebook_cli/__init__.py +2 -1
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/notebook_cli/progress.py +11 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/notebook_cli/prompts.py +57 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/notebook_cli/wizard.py +145 -37
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/services/training_service.py +10 -1
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/strategies/qlora_strategy.py +9 -3
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/strategies/sft_strategy.py +39 -2
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/strategies/strategy_factory.py +34 -14
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/chat_playground.py +1 -1
- {modelforge_finetuning-3.0.3/modelforge_finetuning.egg-info → modelforge_finetuning-3.0.5}/PKG-INFO +4 -1
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5/modelforge_finetuning.egg-info}/PKG-INFO +4 -1
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/modelforge_finetuning.egg-info/requires.txt +4 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/pyproject.toml +5 -1
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/LICENSE +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/MANIFEST.in +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/asset-manifest.json +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/favicon.ico +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/favicon.jpg +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/index.html +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/logo192.png +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/logo512.png +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/manifest.json +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/robots.txt +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/css/main.5a3d6ea1.css +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/css/main.5a3d6ea1.css.map +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/css/main.9680427d.css +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/css/main.9680427d.css.map +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/453.6e4f956a.chunk.js +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/453.6e4f956a.chunk.js.map +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/453.ad6eb26e.chunk.js +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/453.ad6eb26e.chunk.js.map +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/main.2b0344e0.js +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/main.2b0344e0.js.LICENSE.txt +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/main.2b0344e0.js.map +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/main.9cc9257a.js +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/main.9cc9257a.js.LICENSE.txt +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/main.9cc9257a.js.map +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/main.9df15fbf.js +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/main.9df15fbf.js.LICENSE.txt +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/static/js/main.9df15fbf.js.map +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/app.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/database/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/database/database_manager.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/database/models.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/dependencies.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/evaluation/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/evaluation/dataset_validator.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/exceptions.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/formatters/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/formatters/formatting_functions.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/globals/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/globals/globals.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/globals/globals_instance.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/logging_config.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/model_configs/high_end.json +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/model_configs/low_end.json +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/model_configs/mid_range.json +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/providers/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/providers/huggingface_provider.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/providers/provider_factory.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/providers/unsloth_provider.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/routers/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/routers/finetuning_router.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/routers/hub_management_router.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/routers/models_router.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/routers/playground_router.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/schemas/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/schemas/training_schemas.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/services/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/services/hardware_service.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/services/model_service.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/strategies/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/strategies/dpo_strategy.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/strategies/rlhf_strategy.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/test_datasets/low_qa_train_set.jsonl +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/test_datasets/low_summarization_train_set.jsonl +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/test_datasets/low_text_generation.jsonl +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/test_datasets/med_construction.jsonl +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/test_datasets/med_text_generation.jsonl +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/test_datasets/question_answer-train-data-sample.jsonl +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/test_datasets/test_dataset.json +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/test_datasets/test_financial_advisory_generation.jsonl +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/test_datasets/test_financial_advisory_generation_bak.jsonl +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/configs/hardware_thresholds.json +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/configs/tasks.json +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/device_utils.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/finetuning/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/finetuning/quantization.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/finetuning/settings_builder.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/hardware_detection/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/hardware_detection/config_manager.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/hardware_detection/hardware_detector.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/hardware_detection/hardware_detector_factory.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/hardware_detection/model_recommendation.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/hardware_detection/model_validator.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/settings_managers/DBManager.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/settings_managers/FileManager.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/settings_managers/__init__.py +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/README.md +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/modelforge_finetuning.egg-info/SOURCES.txt +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/modelforge_finetuning.egg-info/dependency_links.txt +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/modelforge_finetuning.egg-info/entry_points.txt +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/modelforge_finetuning.egg-info/top_level.txt +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/setup.cfg +0 -0
- {modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/tests/test_device_utils.py +0 -0
|
@@ -65,14 +65,14 @@ def main():
|
|
|
65
65
|
subcommand = sys.argv[1]
|
|
66
66
|
if subcommand == "cli":
|
|
67
67
|
try:
|
|
68
|
-
from .notebook_cli.wizard import
|
|
68
|
+
from .notebook_cli.wizard import ModelForgeWizard
|
|
69
69
|
except ImportError as e:
|
|
70
70
|
logger.error(f"Failed to import CLI wizard or its dependencies: {e}")
|
|
71
71
|
print("\nThe interactive CLI requires optional dependencies that are not installed.")
|
|
72
72
|
print("Please install the CLI extras and try again, for example:")
|
|
73
73
|
print(" pip install \"modelforge-finetuning[cli]\"")
|
|
74
74
|
sys.exit(1)
|
|
75
|
-
|
|
75
|
+
ModelForgeWizard(notebook=False).run()
|
|
76
76
|
return
|
|
77
77
|
else:
|
|
78
78
|
print(f"Unknown subcommand: '{subcommand}'")
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/evaluation/metrics.py
RENAMED
|
@@ -21,6 +21,10 @@ class MetricsCalculator:
|
|
|
21
21
|
- Perplexity: exp(loss)
|
|
22
22
|
- Loss: Cross-entropy loss
|
|
23
23
|
|
|
24
|
+
Note: When preprocess_logits_for_metrics is used, predictions contain
|
|
25
|
+
pre-computed scalar losses (one per eval batch) instead of full logit tensors.
|
|
26
|
+
This prevents RAM exhaustion during evaluation.
|
|
27
|
+
|
|
24
28
|
Args:
|
|
25
29
|
eval_pred: Evaluation prediction with predictions and labels
|
|
26
30
|
|
|
@@ -29,28 +33,16 @@ class MetricsCalculator:
|
|
|
29
33
|
"""
|
|
30
34
|
logger.info("Computing causal LM metrics")
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
import torch.nn.functional as F
|
|
34
|
-
|
|
35
|
-
predictions, labels = eval_pred.predictions, eval_pred.label_ids
|
|
36
|
-
|
|
37
|
-
logits = torch.from_numpy(np.array(predictions)).float()
|
|
38
|
-
lbl = torch.from_numpy(np.array(labels))
|
|
39
|
-
|
|
40
|
-
shift_logits = logits[..., :-1, :].contiguous()
|
|
41
|
-
shift_labels = lbl[..., 1:].contiguous()
|
|
36
|
+
predictions = eval_pred.predictions
|
|
42
37
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
reduction="mean",
|
|
48
|
-
)
|
|
49
|
-
perplexity = float(torch.exp(loss))
|
|
38
|
+
# predictions is shape (num_eval_batches, 1) of pre-computed scalar losses
|
|
39
|
+
# (from _preprocess_logits_for_metrics in sft_strategy.py)
|
|
40
|
+
mean_loss = float(np.mean(predictions))
|
|
41
|
+
perplexity = float(np.exp(mean_loss))
|
|
50
42
|
|
|
51
43
|
metrics = {
|
|
52
44
|
"perplexity": perplexity,
|
|
53
|
-
"eval_loss":
|
|
45
|
+
"eval_loss": mean_loss,
|
|
54
46
|
}
|
|
55
47
|
|
|
56
48
|
logger.info(f"Causal LM metrics: {metrics}")
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/notebook_cli/__init__.py
RENAMED
|
@@ -12,7 +12,8 @@ Usage from a notebook cell:
|
|
|
12
12
|
run_cli()
|
|
13
13
|
|
|
14
14
|
Usage from a terminal:
|
|
15
|
-
modelforge-nb
|
|
15
|
+
modelforge-nb (notebook-safe input() prompts)
|
|
16
|
+
modelforge cli (interactive terminal with questionary)
|
|
16
17
|
"""
|
|
17
18
|
from .wizard import ModelForgeWizard, main as run_cli
|
|
18
19
|
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/notebook_cli/progress.py
RENAMED
|
@@ -7,8 +7,13 @@ notebook environment, and falls back to tqdm for plain terminal use.
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
_NOTEBOOK_OVERRIDE: bool | None = None
|
|
11
|
+
|
|
12
|
+
|
|
10
13
|
def _is_notebook() -> bool:
|
|
11
14
|
"""Return True if running inside a Jupyter-compatible notebook kernel."""
|
|
15
|
+
if _NOTEBOOK_OVERRIDE is not None:
|
|
16
|
+
return _NOTEBOOK_OVERRIDE
|
|
12
17
|
try:
|
|
13
18
|
from IPython import get_ipython
|
|
14
19
|
shell = get_ipython()
|
|
@@ -19,6 +24,12 @@ def _is_notebook() -> bool:
|
|
|
19
24
|
return False
|
|
20
25
|
|
|
21
26
|
|
|
27
|
+
def set_notebook_mode(mode: bool) -> None:
|
|
28
|
+
"""Override the auto-detected notebook mode."""
|
|
29
|
+
global _NOTEBOOK_OVERRIDE
|
|
30
|
+
_NOTEBOOK_OVERRIDE = mode
|
|
31
|
+
|
|
32
|
+
|
|
22
33
|
class ProgressDisplay:
|
|
23
34
|
"""
|
|
24
35
|
Unified progress display that works in notebooks and terminals.
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/notebook_cli/prompts.py
RENAMED
|
@@ -33,6 +33,12 @@ def _is_notebook() -> bool:
|
|
|
33
33
|
_IN_NOTEBOOK = _is_notebook()
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
def set_notebook_mode(mode: bool) -> None:
|
|
37
|
+
"""Override the auto-detected notebook mode."""
|
|
38
|
+
global _IN_NOTEBOOK
|
|
39
|
+
_IN_NOTEBOOK = mode
|
|
40
|
+
|
|
41
|
+
|
|
36
42
|
# ── Notebook-safe input() fallbacks ──────────────────────────────────────────
|
|
37
43
|
|
|
38
44
|
def _nb_select(message: str, choices: list) -> str:
|
|
@@ -83,6 +89,14 @@ def _nb_confirm(message: str, default: bool = True) -> bool:
|
|
|
83
89
|
|
|
84
90
|
# ── Choices ────────────────────────────────────────────────────────────────
|
|
85
91
|
|
|
92
|
+
_MAIN_MENU_CHOICES = [
|
|
93
|
+
questionary.Choice("Fine-tune a model", value="train"),
|
|
94
|
+
questionary.Choice("List past models", value="list"),
|
|
95
|
+
questionary.Choice("Test a fine-tuned model", value="test"),
|
|
96
|
+
questionary.Choice("Exit", value="exit"),
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
|
|
86
100
|
_TASK_CHOICES = [
|
|
87
101
|
questionary.Choice("Text Generation (causal LM fine-tuning)", value="text-generation"),
|
|
88
102
|
questionary.Choice("Summarization (seq-to-seq fine-tuning)", value="summarization"),
|
|
@@ -342,6 +356,49 @@ def prompt_hyperparams(defaults: dict) -> dict:
|
|
|
342
356
|
return params
|
|
343
357
|
|
|
344
358
|
|
|
359
|
+
def prompt_main_menu() -> str:
|
|
360
|
+
"""Ask the user what they want to do."""
|
|
361
|
+
if _IN_NOTEBOOK:
|
|
362
|
+
return _nb_select("What would you like to do?", _MAIN_MENU_CHOICES)
|
|
363
|
+
return questionary.select(
|
|
364
|
+
"What would you like to do?",
|
|
365
|
+
choices=_MAIN_MENU_CHOICES,
|
|
366
|
+
style=questionary.Style([("selected", "fg:cyan bold")]),
|
|
367
|
+
).ask()
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def prompt_select_model(models: list[dict]) -> dict | None:
|
|
371
|
+
"""
|
|
372
|
+
Ask the user to select a model from a list.
|
|
373
|
+
|
|
374
|
+
Args:
|
|
375
|
+
models: List of model dictionaries from the database.
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
Selected model dict, or None if cancelled.
|
|
379
|
+
"""
|
|
380
|
+
choices = []
|
|
381
|
+
for m in models:
|
|
382
|
+
label = (
|
|
383
|
+
f"{m.get('name', 'unknown')} "
|
|
384
|
+
f"[{m.get('task', '?')} / {m.get('strategy', '?')}]"
|
|
385
|
+
)
|
|
386
|
+
choices.append(questionary.Choice(label, value=m["id"]))
|
|
387
|
+
|
|
388
|
+
if _IN_NOTEBOOK:
|
|
389
|
+
model_id = _nb_select("Select a model:", choices)
|
|
390
|
+
else:
|
|
391
|
+
model_id = questionary.select(
|
|
392
|
+
"Select a model:",
|
|
393
|
+
choices=choices,
|
|
394
|
+
style=questionary.Style([("selected", "fg:cyan bold")]),
|
|
395
|
+
).ask()
|
|
396
|
+
|
|
397
|
+
if model_id is None:
|
|
398
|
+
return None
|
|
399
|
+
return next((m for m in models if m["id"] == model_id), None)
|
|
400
|
+
|
|
401
|
+
|
|
345
402
|
def prompt_confirm_config(config: dict) -> bool:
|
|
346
403
|
"""
|
|
347
404
|
Show a summary table of the final config and ask for confirmation.
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/notebook_cli/wizard.py
RENAMED
|
@@ -30,57 +30,165 @@ class ModelForgeWizard:
|
|
|
30
30
|
Uses existing Python service classes directly — no REST API calls.
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
|
-
def __init__(self):
|
|
33
|
+
def __init__(self, notebook: bool | None = None):
|
|
34
34
|
from rich.console import Console
|
|
35
35
|
|
|
36
36
|
self.console = Console()
|
|
37
37
|
|
|
38
|
+
if notebook is not None:
|
|
39
|
+
from . import prompts, progress
|
|
40
|
+
prompts.set_notebook_mode(notebook)
|
|
41
|
+
progress.set_notebook_mode(notebook)
|
|
42
|
+
|
|
38
43
|
# ── Public ─────────────────────────────────────────────────────────────
|
|
39
44
|
|
|
40
45
|
def run(self) -> None:
|
|
41
|
-
"""
|
|
42
|
-
from
|
|
43
|
-
|
|
44
|
-
from ..schemas.training_schemas import TrainingConfig
|
|
45
|
-
from .prompts import prompt_confirm_config
|
|
46
|
+
"""Show main menu in a loop, dispatching until the user exits."""
|
|
47
|
+
from .prompts import prompt_main_menu
|
|
46
48
|
|
|
47
49
|
try:
|
|
48
50
|
self._print_banner()
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
strategy=strategy,
|
|
61
|
-
dataset=dataset_path,
|
|
62
|
-
compute_specs=hardware_info.get("compute_profile", "low_end"),
|
|
63
|
-
hyperparams=hyperparams,
|
|
64
|
-
)
|
|
65
|
-
try:
|
|
66
|
-
TrainingConfig(**config)
|
|
67
|
-
except ValidationError as exc:
|
|
68
|
-
errors = "; ".join(e["msg"] for e in exc.errors())
|
|
69
|
-
self.console.print(
|
|
70
|
-
f"\n[red bold]Invalid configuration:[/red bold] {errors}"
|
|
71
|
-
)
|
|
72
|
-
return
|
|
73
|
-
confirmed = prompt_confirm_config(config)
|
|
74
|
-
if not confirmed:
|
|
75
|
-
self.console.print("\n[yellow]Training cancelled.[/yellow]")
|
|
76
|
-
return
|
|
77
|
-
self._run_training(config)
|
|
51
|
+
while True:
|
|
52
|
+
action = prompt_main_menu()
|
|
53
|
+
if action is None or action == "exit":
|
|
54
|
+
self.console.print("\n[dim]Goodbye![/dim]")
|
|
55
|
+
return
|
|
56
|
+
if action == "train":
|
|
57
|
+
self._run_train_wizard()
|
|
58
|
+
elif action == "list":
|
|
59
|
+
self._list_models()
|
|
60
|
+
elif action == "test":
|
|
61
|
+
self._test_model()
|
|
78
62
|
except KeyboardInterrupt:
|
|
79
63
|
self.console.print("\n\n[yellow]Interrupted — goodbye.[/yellow]")
|
|
80
64
|
except Exception as exc:
|
|
81
65
|
self.console.print(f"\n[red bold]Error:[/red bold] {exc}")
|
|
82
66
|
raise
|
|
83
67
|
|
|
68
|
+
def _run_train_wizard(self) -> None:
|
|
69
|
+
"""Execute the full training wizard flow."""
|
|
70
|
+
from pydantic import ValidationError
|
|
71
|
+
|
|
72
|
+
from ..schemas.training_schemas import TrainingConfig
|
|
73
|
+
from .prompts import prompt_confirm_config
|
|
74
|
+
|
|
75
|
+
hardware_info = self._detect_hardware()
|
|
76
|
+
task = self._select_task()
|
|
77
|
+
model_name = self._select_model(task, hardware_info)
|
|
78
|
+
provider = self._select_provider()
|
|
79
|
+
strategy = self._select_strategy()
|
|
80
|
+
dataset_path = self._select_dataset(task, strategy)
|
|
81
|
+
hyperparams = self._configure_hyperparams(hardware_info, strategy)
|
|
82
|
+
config = self._build_config(
|
|
83
|
+
task=task,
|
|
84
|
+
model_name=model_name,
|
|
85
|
+
provider=provider,
|
|
86
|
+
strategy=strategy,
|
|
87
|
+
dataset=dataset_path,
|
|
88
|
+
compute_specs=hardware_info.get("compute_profile", "low_end"),
|
|
89
|
+
hyperparams=hyperparams,
|
|
90
|
+
)
|
|
91
|
+
try:
|
|
92
|
+
TrainingConfig(**config)
|
|
93
|
+
except ValidationError as exc:
|
|
94
|
+
errors = "; ".join(e["msg"] for e in exc.errors())
|
|
95
|
+
self.console.print(
|
|
96
|
+
f"\n[red bold]Invalid configuration:[/red bold] {errors}"
|
|
97
|
+
)
|
|
98
|
+
return
|
|
99
|
+
confirmed = prompt_confirm_config(config)
|
|
100
|
+
if not confirmed:
|
|
101
|
+
self.console.print("\n[yellow]Training cancelled.[/yellow]")
|
|
102
|
+
return
|
|
103
|
+
self._run_training(config)
|
|
104
|
+
|
|
105
|
+
# ── List & Test ────────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
def _list_models(self) -> None:
|
|
108
|
+
"""Display a table of all fine-tuned models."""
|
|
109
|
+
from rich.table import Table
|
|
110
|
+
|
|
111
|
+
from ..dependencies import get_model_service
|
|
112
|
+
|
|
113
|
+
self.console.print("\n[bold]Past Fine-Tuned Models[/bold]\n")
|
|
114
|
+
model_service = get_model_service()
|
|
115
|
+
models = model_service.get_all_models()
|
|
116
|
+
|
|
117
|
+
if not models:
|
|
118
|
+
self.console.print(" [dim]No models found.[/dim]")
|
|
119
|
+
return
|
|
120
|
+
|
|
121
|
+
table = Table(show_header=True, header_style="bold cyan")
|
|
122
|
+
table.add_column("#", style="dim", width=3)
|
|
123
|
+
table.add_column("Name")
|
|
124
|
+
table.add_column("Base Model")
|
|
125
|
+
table.add_column("Task")
|
|
126
|
+
table.add_column("Strategy")
|
|
127
|
+
table.add_column("Provider")
|
|
128
|
+
table.add_column("Created")
|
|
129
|
+
table.add_column("Path", style="dim")
|
|
130
|
+
|
|
131
|
+
for i, m in enumerate(models, 1):
|
|
132
|
+
created = m.get("created_at", "")
|
|
133
|
+
if created:
|
|
134
|
+
created = created[:16].replace("T", " ")
|
|
135
|
+
table.add_row(
|
|
136
|
+
str(i),
|
|
137
|
+
m.get("name", "—"),
|
|
138
|
+
m.get("base_model", "—"),
|
|
139
|
+
m.get("task", "—"),
|
|
140
|
+
m.get("strategy", "—"),
|
|
141
|
+
m.get("provider", "—"),
|
|
142
|
+
created,
|
|
143
|
+
m.get("path", "—"),
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
self.console.print(table)
|
|
147
|
+
|
|
148
|
+
def _test_model(self) -> None:
|
|
149
|
+
"""Let the user pick a fine-tuned model and launch the playground."""
|
|
150
|
+
import os
|
|
151
|
+
|
|
152
|
+
from rich.panel import Panel
|
|
153
|
+
|
|
154
|
+
from ..dependencies import get_model_service
|
|
155
|
+
from .prompts import prompt_select_model
|
|
156
|
+
|
|
157
|
+
self.console.print("\n[bold]Test a Fine-Tuned Model[/bold]\n")
|
|
158
|
+
model_service = get_model_service()
|
|
159
|
+
models = model_service.get_all_models()
|
|
160
|
+
|
|
161
|
+
if not models:
|
|
162
|
+
self.console.print(" [dim]No models found. Fine-tune a model first.[/dim]")
|
|
163
|
+
return
|
|
164
|
+
|
|
165
|
+
selected = prompt_select_model(models)
|
|
166
|
+
if selected is None:
|
|
167
|
+
return
|
|
168
|
+
|
|
169
|
+
model_path = selected.get("path", "")
|
|
170
|
+
if not model_path or not os.path.isdir(model_path):
|
|
171
|
+
self.console.print(
|
|
172
|
+
f"\n[red]Model path not found:[/red] {model_path}"
|
|
173
|
+
)
|
|
174
|
+
return
|
|
175
|
+
|
|
176
|
+
self.console.print(
|
|
177
|
+
Panel(
|
|
178
|
+
f"[bold]Model:[/bold] {selected.get('name', '—')}\n"
|
|
179
|
+
f"[bold]Path:[/bold] {model_path}\n\n"
|
|
180
|
+
"[dim]Type /bye to exit, /view_settings to inspect the model.[/dim]",
|
|
181
|
+
title="Playground",
|
|
182
|
+
border_style="cyan",
|
|
183
|
+
expand=False,
|
|
184
|
+
)
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
from ..utilities.chat_playground import PlaygroundModel
|
|
188
|
+
|
|
189
|
+
bot = PlaygroundModel(model_path=model_path)
|
|
190
|
+
bot.chat()
|
|
191
|
+
|
|
84
192
|
# ── Steps ───────────────────────────────────────────────────────────────
|
|
85
193
|
|
|
86
194
|
def _print_banner(self) -> None:
|
|
@@ -317,7 +425,7 @@ class ModelForgeWizard:
|
|
|
317
425
|
# ── Entry point ──────────────────────────────────────────────────────────────
|
|
318
426
|
|
|
319
427
|
def main() -> None:
|
|
320
|
-
"""Entry point for the ``modelforge-nb`` console script."""
|
|
428
|
+
"""Entry point for the ``modelforge-nb`` console script (notebook mode)."""
|
|
321
429
|
try:
|
|
322
430
|
import questionary # noqa: F401
|
|
323
431
|
import rich # noqa: F401
|
|
@@ -330,7 +438,7 @@ def main() -> None:
|
|
|
330
438
|
' pip install "modelforge-finetuning[cli]"\n'
|
|
331
439
|
)
|
|
332
440
|
sys.exit(1)
|
|
333
|
-
ModelForgeWizard().run()
|
|
441
|
+
ModelForgeWizard(notebook=True).run()
|
|
334
442
|
|
|
335
443
|
|
|
336
444
|
if __name__ == "__main__":
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/services/training_service.py
RENAMED
|
@@ -432,7 +432,16 @@ class TrainingService:
|
|
|
432
432
|
|
|
433
433
|
# Train
|
|
434
434
|
self.training_status["message"] = "Training in progress..."
|
|
435
|
-
|
|
435
|
+
provider_name = config.get("provider", "")
|
|
436
|
+
if provider_name == "unsloth":
|
|
437
|
+
try:
|
|
438
|
+
from unsloth import unsloth_train
|
|
439
|
+
unsloth_train(trainer)
|
|
440
|
+
except ImportError:
|
|
441
|
+
logger.warning("unsloth_train not available, falling back to trainer.train()")
|
|
442
|
+
trainer.train()
|
|
443
|
+
else:
|
|
444
|
+
trainer.train()
|
|
436
445
|
|
|
437
446
|
# Save model
|
|
438
447
|
self.training_status["message"] = "Saving model..."
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/strategies/qlora_strategy.py
RENAMED
|
@@ -22,6 +22,7 @@ except ImportError:
|
|
|
22
22
|
from trl import SFTTrainer, SFTConfig
|
|
23
23
|
|
|
24
24
|
from ..logging_config import logger
|
|
25
|
+
from .sft_strategy import _preprocess_logits_for_metrics
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
class QLoRAStrategy:
|
|
@@ -211,7 +212,7 @@ class QLoRAStrategy:
|
|
|
211
212
|
max_seq_length = 2048
|
|
212
213
|
|
|
213
214
|
# QLoRA-optimized training arguments
|
|
214
|
-
|
|
215
|
+
sft_kwargs = dict(
|
|
215
216
|
output_dir=config.get("output_dir", "./checkpoints"),
|
|
216
217
|
num_train_epochs=config.get("num_train_epochs", 1),
|
|
217
218
|
per_device_train_batch_size=config.get("per_device_train_batch_size", 4),
|
|
@@ -227,7 +228,6 @@ class QLoRAStrategy:
|
|
|
227
228
|
bf16=config.get("bf16", True), # Default True for CUDA; MPS overrides to False in training_service
|
|
228
229
|
max_grad_norm=config.get("max_grad_norm", 0.3),
|
|
229
230
|
max_steps=config.get("max_steps", -1),
|
|
230
|
-
group_by_length=config.get("group_by_length", True),
|
|
231
231
|
lr_scheduler_type=config.get("lr_scheduler_type", "cosine"),
|
|
232
232
|
report_to="tensorboard",
|
|
233
233
|
logging_dir=config.get("logging_dir", "./training_logs"),
|
|
@@ -245,12 +245,17 @@ class QLoRAStrategy:
|
|
|
245
245
|
load_best_model_at_end=True if eval_dataset else False,
|
|
246
246
|
metric_for_best_model="eval_loss" if eval_dataset else None,
|
|
247
247
|
ddp_find_unused_parameters=False,
|
|
248
|
-
use_cache=False,
|
|
249
248
|
# Dataloader settings (MPS sets these to avoid multiprocessing issues)
|
|
250
249
|
dataloader_num_workers=config.get("dataloader_num_workers", 0),
|
|
251
250
|
dataloader_pin_memory=config.get("dataloader_pin_memory", True),
|
|
252
251
|
)
|
|
253
252
|
|
|
253
|
+
# Unsloth's patched SFTConfig doesn't support group_by_length
|
|
254
|
+
if not config.get("_peft_already_applied"):
|
|
255
|
+
sft_kwargs["group_by_length"] = config.get("group_by_length", True)
|
|
256
|
+
|
|
257
|
+
training_args = SFTConfig(**sft_kwargs)
|
|
258
|
+
|
|
254
259
|
# Build the PEFT config for SFTTrainer to apply LoRA
|
|
255
260
|
# Skip if PEFT was already applied (e.g. by Unsloth provider)
|
|
256
261
|
peft_config = None if config.get("_peft_already_applied") else self.get_peft_config(config)
|
|
@@ -265,6 +270,7 @@ class QLoRAStrategy:
|
|
|
265
270
|
peft_config=peft_config,
|
|
266
271
|
callbacks=callbacks or [],
|
|
267
272
|
compute_metrics=compute_metrics,
|
|
273
|
+
preprocess_logits_for_metrics=_preprocess_logits_for_metrics,
|
|
268
274
|
)
|
|
269
275
|
|
|
270
276
|
logger.info("QLoRA SFTTrainer created successfully")
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/strategies/sft_strategy.py
RENAMED
|
@@ -23,6 +23,37 @@ from trl import SFTTrainer, SFTConfig
|
|
|
23
23
|
from ..logging_config import logger
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
def _preprocess_logits_for_metrics(logits, labels):
|
|
27
|
+
"""
|
|
28
|
+
Reduce logit tensors to scalar loss per batch before CPU accumulation.
|
|
29
|
+
|
|
30
|
+
This prevents RAM exhaustion when the Trainer accumulates eval predictions.
|
|
31
|
+
Instead of storing full logit tensors (batch × seq_len × vocab_size),
|
|
32
|
+
we compute the loss on GPU and return only a scalar, reducing memory by
|
|
33
|
+
orders of magnitude (e.g., 19.7 GB/batch → bytes/batch).
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
logits: Model logits (batch, seq_len, vocab_size)
|
|
37
|
+
labels: Token labels (batch, seq_len)
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Scalar loss tensor for this batch, shape (1,)
|
|
41
|
+
"""
|
|
42
|
+
import torch.nn.functional as F
|
|
43
|
+
|
|
44
|
+
shift_logits = logits[..., :-1, :].contiguous()
|
|
45
|
+
shift_labels = labels[..., 1:].contiguous()
|
|
46
|
+
|
|
47
|
+
loss = F.cross_entropy(
|
|
48
|
+
shift_logits.view(-1, shift_logits.size(-1)),
|
|
49
|
+
shift_labels.view(-1).long(),
|
|
50
|
+
ignore_index=-100,
|
|
51
|
+
reduction="mean",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
return loss.unsqueeze(0)
|
|
55
|
+
|
|
56
|
+
|
|
26
57
|
class SFTStrategy:
|
|
27
58
|
"""Supervised Fine-Tuning strategy using TRL's SFTTrainer."""
|
|
28
59
|
|
|
@@ -193,7 +224,7 @@ class SFTStrategy:
|
|
|
193
224
|
max_seq_length = 2048
|
|
194
225
|
|
|
195
226
|
# Create SFTConfig with training arguments
|
|
196
|
-
|
|
227
|
+
sft_kwargs = dict(
|
|
197
228
|
output_dir=config.get("output_dir", "./checkpoints"),
|
|
198
229
|
num_train_epochs=config.get("num_train_epochs", 1),
|
|
199
230
|
per_device_train_batch_size=config.get("per_device_train_batch_size", 1),
|
|
@@ -209,7 +240,6 @@ class SFTStrategy:
|
|
|
209
240
|
bf16=config.get("bf16", False),
|
|
210
241
|
max_grad_norm=config.get("max_grad_norm", 0.3),
|
|
211
242
|
max_steps=config.get("max_steps", -1),
|
|
212
|
-
group_by_length=config.get("group_by_length", True),
|
|
213
243
|
lr_scheduler_type=config.get("lr_scheduler_type", "cosine"),
|
|
214
244
|
report_to="tensorboard",
|
|
215
245
|
logging_dir=config.get("logging_dir", "./training_logs"),
|
|
@@ -229,6 +259,12 @@ class SFTStrategy:
|
|
|
229
259
|
dataloader_pin_memory=config.get("dataloader_pin_memory", True),
|
|
230
260
|
)
|
|
231
261
|
|
|
262
|
+
# Unsloth's patched SFTConfig doesn't support group_by_length
|
|
263
|
+
if not config.get("_peft_already_applied"):
|
|
264
|
+
sft_kwargs["group_by_length"] = config.get("group_by_length", True)
|
|
265
|
+
|
|
266
|
+
training_args = SFTConfig(**sft_kwargs)
|
|
267
|
+
|
|
232
268
|
# Build the PEFT config for SFTTrainer to apply LoRA
|
|
233
269
|
# Skip if PEFT was already applied (e.g. by Unsloth provider)
|
|
234
270
|
peft_config = None if config.get("_peft_already_applied") else self.get_peft_config(config)
|
|
@@ -243,6 +279,7 @@ class SFTStrategy:
|
|
|
243
279
|
peft_config=peft_config,
|
|
244
280
|
callbacks=callbacks or [],
|
|
245
281
|
compute_metrics=compute_metrics,
|
|
282
|
+
preprocess_logits_for_metrics=_preprocess_logits_for_metrics,
|
|
246
283
|
)
|
|
247
284
|
|
|
248
285
|
logger.info("SFTTrainer created successfully")
|
|
@@ -1,22 +1,42 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Strategy factory for creating training strategy instances.
|
|
3
|
+
|
|
4
|
+
Strategy imports are deferred to avoid pulling in heavy dependencies (trl, wandb)
|
|
5
|
+
at module load time — which would break lightweight entry points like the notebook
|
|
6
|
+
CLI wizard that only need HardwareService.
|
|
3
7
|
"""
|
|
4
|
-
from .sft_strategy import SFTStrategy
|
|
5
|
-
from .rlhf_strategy import RLHFStrategy
|
|
6
|
-
from .dpo_strategy import DPOStrategy
|
|
7
|
-
from .qlora_strategy import QLoRAStrategy
|
|
8
8
|
from ..exceptions import ConfigurationError
|
|
9
9
|
from ..logging_config import logger
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
def _import_sft():
|
|
13
|
+
from .sft_strategy import SFTStrategy
|
|
14
|
+
return SFTStrategy
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _import_rlhf():
|
|
18
|
+
from .rlhf_strategy import RLHFStrategy
|
|
19
|
+
return RLHFStrategy
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _import_dpo():
|
|
23
|
+
from .dpo_strategy import DPOStrategy
|
|
24
|
+
return DPOStrategy
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _import_qlora():
|
|
28
|
+
from .qlora_strategy import QLoRAStrategy
|
|
29
|
+
return QLoRAStrategy
|
|
30
|
+
|
|
31
|
+
|
|
12
32
|
class StrategyFactory:
|
|
13
33
|
"""Factory for creating training strategy instances."""
|
|
14
34
|
|
|
15
|
-
|
|
16
|
-
"sft":
|
|
17
|
-
"rlhf":
|
|
18
|
-
"dpo":
|
|
19
|
-
"qlora":
|
|
35
|
+
_strategy_loaders = {
|
|
36
|
+
"sft": _import_sft,
|
|
37
|
+
"rlhf": _import_rlhf,
|
|
38
|
+
"dpo": _import_dpo,
|
|
39
|
+
"qlora": _import_qlora,
|
|
20
40
|
}
|
|
21
41
|
|
|
22
42
|
@classmethod
|
|
@@ -37,13 +57,13 @@ class StrategyFactory:
|
|
|
37
57
|
|
|
38
58
|
strategy_name = strategy_name.lower()
|
|
39
59
|
|
|
40
|
-
if strategy_name not in cls.
|
|
60
|
+
if strategy_name not in cls._strategy_loaders:
|
|
41
61
|
raise ConfigurationError(
|
|
42
62
|
f"Unknown training strategy: {strategy_name}. "
|
|
43
|
-
f"Available strategies: {list(cls.
|
|
63
|
+
f"Available strategies: {list(cls._strategy_loaders.keys())}"
|
|
44
64
|
)
|
|
45
65
|
|
|
46
|
-
strategy_class = cls.
|
|
66
|
+
strategy_class = cls._strategy_loaders[strategy_name]()
|
|
47
67
|
return strategy_class()
|
|
48
68
|
|
|
49
69
|
@classmethod
|
|
@@ -54,7 +74,7 @@ class StrategyFactory:
|
|
|
54
74
|
Returns:
|
|
55
75
|
List of strategy names
|
|
56
76
|
"""
|
|
57
|
-
return list(cls.
|
|
77
|
+
return list(cls._strategy_loaders.keys())
|
|
58
78
|
|
|
59
79
|
@classmethod
|
|
60
80
|
def register_strategy(cls, name: str, strategy_class):
|
|
@@ -66,4 +86,4 @@ class StrategyFactory:
|
|
|
66
86
|
strategy_class: Strategy class
|
|
67
87
|
"""
|
|
68
88
|
logger.info(f"Registering strategy: {name}")
|
|
69
|
-
cls.
|
|
89
|
+
cls._strategy_loaders[name.lower()] = lambda _cls=strategy_class: _cls
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/chat_playground.py
RENAMED
|
@@ -78,7 +78,7 @@ class PlaygroundModel:
|
|
|
78
78
|
input("\nPress Enter to exit...")
|
|
79
79
|
exit(1)
|
|
80
80
|
except KeyError:
|
|
81
|
-
print(
|
|
81
|
+
print(traceback.format_exc())
|
|
82
82
|
input("\nPress Enter to exit...")
|
|
83
83
|
exit(1)
|
|
84
84
|
except Exception as e:
|
{modelforge_finetuning-3.0.3/modelforge_finetuning.egg-info → modelforge_finetuning-3.0.5}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modelforge-finetuning
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.5
|
|
4
4
|
Summary: ModelForge: A no-code toolkit for fine-tuning HuggingFace models
|
|
5
5
|
Author-email: R3tr0 M1ll3r <r3tr0.m1ll3r@gmail.com>
|
|
6
6
|
Project-URL: Documentation, https://modelforge-finetuning.readthedocs.io
|
|
@@ -36,6 +36,9 @@ Requires-Dist: questionary>=2.0.1; extra == "cli"
|
|
|
36
36
|
Requires-Dist: rich>=13.0.0; extra == "cli"
|
|
37
37
|
Requires-Dist: ipywidgets>=8.0.0; extra == "cli"
|
|
38
38
|
Requires-Dist: ipython>=8.0.0; extra == "cli"
|
|
39
|
+
Provides-Extra: unsloth
|
|
40
|
+
Requires-Dist: unsloth; extra == "unsloth"
|
|
41
|
+
Requires-Dist: bitsandbytes==0.45.3; extra == "unsloth"
|
|
39
42
|
Dynamic: license-file
|
|
40
43
|
|
|
41
44
|
# ModelForge 🔧⚡
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5/modelforge_finetuning.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modelforge-finetuning
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.5
|
|
4
4
|
Summary: ModelForge: A no-code toolkit for fine-tuning HuggingFace models
|
|
5
5
|
Author-email: R3tr0 M1ll3r <r3tr0.m1ll3r@gmail.com>
|
|
6
6
|
Project-URL: Documentation, https://modelforge-finetuning.readthedocs.io
|
|
@@ -36,6 +36,9 @@ Requires-Dist: questionary>=2.0.1; extra == "cli"
|
|
|
36
36
|
Requires-Dist: rich>=13.0.0; extra == "cli"
|
|
37
37
|
Requires-Dist: ipywidgets>=8.0.0; extra == "cli"
|
|
38
38
|
Requires-Dist: ipython>=8.0.0; extra == "cli"
|
|
39
|
+
Provides-Extra: unsloth
|
|
40
|
+
Requires-Dist: unsloth; extra == "unsloth"
|
|
41
|
+
Requires-Dist: bitsandbytes==0.45.3; extra == "unsloth"
|
|
39
42
|
Dynamic: license-file
|
|
40
43
|
|
|
41
44
|
# ModelForge 🔧⚡
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "modelforge-finetuning"
|
|
3
|
-
version = "3.0.
|
|
3
|
+
version = "3.0.5"
|
|
4
4
|
description = "ModelForge: A no-code toolkit for fine-tuning HuggingFace models"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "R3tr0 M1ll3r", email = "r3tr0.m1ll3r@gmail.com"},
|
|
@@ -40,6 +40,10 @@ cli = [
|
|
|
40
40
|
"ipywidgets>=8.0.0",
|
|
41
41
|
"ipython>=8.0.0",
|
|
42
42
|
]
|
|
43
|
+
unsloth = [
|
|
44
|
+
"unsloth",
|
|
45
|
+
"bitsandbytes==0.45.3",
|
|
46
|
+
]
|
|
43
47
|
|
|
44
48
|
[tool.setuptools.packages.find]
|
|
45
49
|
where = ["."]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/favicon.ico
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/favicon.jpg
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/index.html
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/logo192.png
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/logo512.png
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/manifest.json
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/Frontend/build/robots.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/database/database_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/evaluation/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/formatters/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/globals/globals_instance.py
RENAMED
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/model_configs/high_end.json
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/model_configs/low_end.json
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/model_configs/mid_range.json
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/providers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/providers/provider_factory.py
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/providers/unsloth_provider.py
RENAMED
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/routers/finetuning_router.py
RENAMED
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/routers/models_router.py
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/routers/playground_router.py
RENAMED
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/schemas/training_schemas.py
RENAMED
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/services/hardware_service.py
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/services/model_service.py
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/strategies/__init__.py
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/strategies/dpo_strategy.py
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/strategies/rlhf_strategy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/configs/tasks.json
RENAMED
|
File without changes
|
{modelforge_finetuning-3.0.3 → modelforge_finetuning-3.0.5}/ModelForge/utilities/device_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|