soup-cli 0.2.0__tar.gz → 0.2.2__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.
Files changed (67) hide show
  1. {soup_cli-0.2.0 → soup_cli-0.2.2}/PKG-INFO +3 -3
  2. {soup_cli-0.2.0 → soup_cli-0.2.2}/README.md +2 -2
  3. soup_cli-0.2.2/TESTING_GUIDE.md +196 -0
  4. {soup_cli-0.2.0 → soup_cli-0.2.2}/pyproject.toml +1 -1
  5. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/__init__.py +1 -1
  6. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/commands/chat.py +2 -2
  7. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/commands/export.py +1 -1
  8. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/commands/merge.py +2 -2
  9. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/monitoring/callback.py +1 -1
  10. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/trainer/dpo.py +10 -1
  11. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/trainer/sft.py +10 -1
  12. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/utils/gpu.py +1 -1
  13. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_cli.py +2 -1
  14. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_resume.py +2 -2
  15. {soup_cli-0.2.0 → soup_cli-0.2.2}/.claude/settings.json +0 -0
  16. {soup_cli-0.2.0 → soup_cli-0.2.2}/.github/workflows/ci.yml +0 -0
  17. {soup_cli-0.2.0 → soup_cli-0.2.2}/.github/workflows/publish.yml +0 -0
  18. {soup_cli-0.2.0 → soup_cli-0.2.2}/.gitignore +0 -0
  19. {soup_cli-0.2.0 → soup_cli-0.2.2}/CLAUDE.md +0 -0
  20. {soup_cli-0.2.0 → soup_cli-0.2.2}/LICENSE +0 -0
  21. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup.png +0 -0
  22. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/__main__.py +0 -0
  23. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/cli.py +0 -0
  24. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/commands/__init__.py +0 -0
  25. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/commands/data.py +0 -0
  26. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/commands/eval.py +0 -0
  27. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/commands/init.py +0 -0
  28. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/commands/push.py +0 -0
  29. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/commands/runs.py +0 -0
  30. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/commands/train.py +0 -0
  31. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/config/__init__.py +0 -0
  32. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/config/loader.py +0 -0
  33. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/config/schema.py +0 -0
  34. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/data/__init__.py +0 -0
  35. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/data/formats.py +0 -0
  36. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/data/loader.py +0 -0
  37. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/data/validator.py +0 -0
  38. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/experiment/__init__.py +0 -0
  39. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/experiment/tracker.py +0 -0
  40. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/monitoring/__init__.py +0 -0
  41. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/monitoring/display.py +0 -0
  42. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/trainer/__init__.py +0 -0
  43. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/utils/__init__.py +0 -0
  44. {soup_cli-0.2.0 → soup_cli-0.2.2}/soup_cli/utils/constants.py +0 -0
  45. {soup_cli-0.2.0 → soup_cli-0.2.2}/templates/chat.yaml +0 -0
  46. {soup_cli-0.2.0 → soup_cli-0.2.2}/templates/code.yaml +0 -0
  47. {soup_cli-0.2.0 → soup_cli-0.2.2}/templates/medical.yaml +0 -0
  48. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/__init__.py +0 -0
  49. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/conftest.py +0 -0
  50. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_callback.py +0 -0
  51. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_chat.py +0 -0
  52. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_config.py +0 -0
  53. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_data.py +0 -0
  54. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_data_tools.py +0 -0
  55. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_display.py +0 -0
  56. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_eval.py +0 -0
  57. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_export.py +0 -0
  58. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_formats.py +0 -0
  59. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_gpu.py +0 -0
  60. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_init.py +0 -0
  61. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_loader.py +0 -0
  62. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_merge.py +0 -0
  63. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_push.py +0 -0
  64. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_runs.py +0 -0
  65. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_smoke_train.py +0 -0
  66. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_tracker.py +0 -0
  67. {soup_cli-0.2.0 → soup_cli-0.2.2}/tests/test_validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: soup-cli
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Fine-tune LLMs in one command. No SSH, no config hell.
5
5
  Project-URL: Homepage, https://github.com/MakazhanAlpamys/Soup
6
6
  Project-URL: Repository, https://github.com/MakazhanAlpamys/Soup
@@ -67,7 +67,7 @@ Description-Content-Type: text/markdown
67
67
  <a href="https://pypi.org/project/soup-cli/"><img src="https://img.shields.io/pypi/v/soup-cli?color=blue" alt="PyPI"></a>
68
68
  <img src="https://img.shields.io/badge/python-3.9%2B-blue" alt="Python 3.9+">
69
69
  <img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License">
70
- <img src="https://img.shields.io/badge/tests-184%20passed-brightgreen" alt="Tests">
70
+ <img src="https://img.shields.io/badge/tests-186%20passed-brightgreen" alt="Tests">
71
71
  <a href="https://github.com/MakazhanAlpamys/Soup/actions"><img src="https://github.com/MakazhanAlpamys/Soup/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
72
72
  </p>
73
73
 
@@ -418,7 +418,7 @@ pip install -e ".[dev]"
418
418
  # Lint
419
419
  ruff check soup_cli/ tests/
420
420
 
421
- # Run unit tests (fast, no GPU needed — 184 tests)
421
+ # Run unit tests (fast, no GPU needed — 186 tests)
422
422
  pytest tests/ -v
423
423
 
424
424
  # Run smoke tests (downloads tiny model, runs real training)
@@ -21,7 +21,7 @@
21
21
  <a href="https://pypi.org/project/soup-cli/"><img src="https://img.shields.io/pypi/v/soup-cli?color=blue" alt="PyPI"></a>
22
22
  <img src="https://img.shields.io/badge/python-3.9%2B-blue" alt="Python 3.9+">
23
23
  <img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License">
24
- <img src="https://img.shields.io/badge/tests-184%20passed-brightgreen" alt="Tests">
24
+ <img src="https://img.shields.io/badge/tests-186%20passed-brightgreen" alt="Tests">
25
25
  <a href="https://github.com/MakazhanAlpamys/Soup/actions"><img src="https://github.com/MakazhanAlpamys/Soup/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
26
26
  </p>
27
27
 
@@ -372,7 +372,7 @@ pip install -e ".[dev]"
372
372
  # Lint
373
373
  ruff check soup_cli/ tests/
374
374
 
375
- # Run unit tests (fast, no GPU needed — 184 tests)
375
+ # Run unit tests (fast, no GPU needed — 186 tests)
376
376
  pytest tests/ -v
377
377
 
378
378
  # Run smoke tests (downloads tiny model, runs real training)
@@ -0,0 +1,196 @@
1
+ # Soup CLI — Quick Local Test Guide (Windows)
2
+
3
+ **Hardware:** RTX 3050 (4GB VRAM), i5
4
+ **Model:** `TinyLlama/TinyLlama-1.1B-Chat-v1.0` (~1.1B params, ~600MB in 4-bit)
5
+ **OS:** Windows (CMD/PowerShell)
6
+
7
+ ---
8
+
9
+ ## 0. Install
10
+
11
+ ```cmd
12
+ pip install soup-cli
13
+ pip install datasketch
14
+ ```
15
+
16
+ > Unit tests (`pytest tests/`) only work from the repo clone (`pip install -e ".[dev]"`), not from pip install.
17
+
18
+ ## 1. Version & Help
19
+
20
+ ```cmd
21
+ soup version
22
+ soup --help
23
+ soup train --help
24
+ soup data --help
25
+ ```
26
+
27
+ ## 2. Init Config from Templates
28
+
29
+ ```cmd
30
+ soup init -t chat -o test_chat.yaml
31
+ soup init -t code -o test_code.yaml
32
+ ```
33
+
34
+ > `soup init` without `-t` opens interactive wizard (requires terminal input).
35
+
36
+ ## 3. Create Test Dataset
37
+
38
+ Create file `test_data.jsonl` with this content (copy-paste into any text editor, save as `test_data.jsonl`):
39
+
40
+ ```jsonl
41
+ {"instruction": "What is Python?", "input": "", "output": "Python is a high-level programming language known for its simplicity."}
42
+ {"instruction": "Explain recursion", "input": "", "output": "Recursion is when a function calls itself to solve smaller subproblems."}
43
+ {"instruction": "What is a list?", "input": "", "output": "A list is an ordered, mutable collection of elements in Python."}
44
+ {"instruction": "What is a dictionary?", "input": "", "output": "A dictionary is a key-value data structure in Python."}
45
+ {"instruction": "What is OOP?", "input": "", "output": "OOP is a programming paradigm based on objects and classes."}
46
+ {"instruction": "What is an API?", "input": "", "output": "An API is an interface that allows software systems to communicate."}
47
+ {"instruction": "What is Git?", "input": "", "output": "Git is a distributed version control system for tracking code changes."}
48
+ {"instruction": "What is Docker?", "input": "", "output": "Docker is a platform for containerizing applications."}
49
+ {"instruction": "What is SQL?", "input": "", "output": "SQL is a language for managing and querying relational databases."}
50
+ {"instruction": "What is REST?", "input": "", "output": "REST is an architectural style for designing networked APIs using HTTP methods."}
51
+ ```
52
+
53
+ Or create it with Python one-liner:
54
+
55
+ ```cmd
56
+ python -c "import json; data=[{'instruction':q,'input':'','output':a} for q,a in [('What is Python?','A high-level programming language.'),('Explain recursion','A function calling itself.'),('What is a list?','An ordered mutable collection.'),('What is OOP?','Programming with objects and classes.'),('What is Git?','A version control system.'),('What is Docker?','A containerization platform.'),('What is SQL?','A database query language.'),('What is REST?','An API architectural style.'),('What is an API?','An interface for software communication.'),('What is CSS?','A stylesheet language for web pages.')]]; f=open('test_data.jsonl','w'); [f.write(json.dumps(d)+'\n') for d in data]; f.close(); print('Created test_data.jsonl')"
57
+ ```
58
+
59
+ ## 4. Data Tools
60
+
61
+ ```cmd
62
+ soup data inspect test_data.jsonl
63
+
64
+ soup data validate test_data.jsonl --format alpaca
65
+
66
+ soup data stats test_data.jsonl
67
+
68
+ soup data convert test_data.jsonl --to sharegpt -o test_sharegpt.jsonl
69
+
70
+ soup data convert test_data.jsonl --to chatml -o test_chatml.jsonl
71
+
72
+ soup data inspect test_sharegpt.jsonl
73
+
74
+ soup data inspect test_chatml.jsonl
75
+
76
+ soup data merge test_data.jsonl test_sharegpt.jsonl -o test_merged.jsonl --shuffle
77
+
78
+ soup data dedup test_merged.jsonl -o test_deduped.jsonl --threshold 0.8
79
+ ```
80
+
81
+ ## 5. Create Config for Training
82
+
83
+ Create file `test_soup.yaml` (copy-paste into text editor):
84
+
85
+ ```yaml
86
+ base: TinyLlama/TinyLlama-1.1B-Chat-v1.0
87
+
88
+ data:
89
+ train: test_data.jsonl
90
+ format: alpaca
91
+ max_length: 256
92
+
93
+ training:
94
+ epochs: 2
95
+ lr: 2e-4
96
+ batch_size: 2
97
+ quantization: 4bit
98
+ logging_steps: 1
99
+ save_steps: 50
100
+ lora:
101
+ r: 8
102
+ alpha: 16
103
+ dropout: 0.05
104
+
105
+ output: ./test_output
106
+ ```
107
+
108
+ ## 6. Dry Run (validate without training)
109
+
110
+ ```cmd
111
+ soup train -c test_soup.yaml --dry-run
112
+ ```
113
+
114
+ ## 7. Train
115
+
116
+ ```cmd
117
+ soup train -c test_soup.yaml --name "local-test"
118
+ ```
119
+
120
+ Training should take ~1-3 minutes on 3050 with this tiny dataset.
121
+
122
+ ## 8. Experiment Tracking
123
+
124
+ ```cmd
125
+ soup runs
126
+ ```
127
+
128
+ Copy the Run ID from the output, then:
129
+
130
+ ```cmd
131
+ soup runs show RUN_ID_HERE
132
+ ```
133
+
134
+ Example: `soup runs show run_20260304_004948_983f284d`
135
+
136
+ ## 9. Chat with Fine-Tuned Model
137
+
138
+ ```cmd
139
+ soup chat -m ./test_output
140
+ ```
141
+
142
+ Type questions, then type `exit` to quit.
143
+
144
+ ## 10. Merge LoRA
145
+
146
+ ```cmd
147
+ soup merge -a ./test_output -o ./test_merged_model
148
+ ```
149
+
150
+ ## 11. Export to GGUF (optional, needs llama.cpp + cmake)
151
+
152
+ ```cmd
153
+ soup export -m ./test_merged_model -q q4_k_m -o test_model.gguf
154
+ ```
155
+
156
+ ## 12. Eval (optional, slow)
157
+
158
+ ```cmd
159
+ pip install lm-eval
160
+ soup eval -m ./test_output --benchmarks hellaswag --batch-size 4
161
+ ```
162
+
163
+ ---
164
+
165
+ ## Cleanup (Windows)
166
+
167
+ ```cmd
168
+ rmdir /s /q test_output test_merged_model
169
+ del test_data.jsonl test_sharegpt.jsonl test_chatml.jsonl test_merged.jsonl test_deduped.jsonl
170
+ del test_soup.yaml test_chat.yaml test_code.yaml test_model.gguf
171
+ ```
172
+
173
+ Or in PowerShell:
174
+
175
+ ```powershell
176
+ Remove-Item -Recurse -Force test_output, test_merged_model -ErrorAction SilentlyContinue
177
+ Remove-Item test_data.jsonl, test_sharegpt.jsonl, test_chatml.jsonl, test_merged.jsonl, test_deduped.jsonl, test_soup.yaml, test_chat.yaml, test_code.yaml, test_model.gguf -ErrorAction SilentlyContinue
178
+ ```
179
+
180
+ ## Expected Results
181
+
182
+ | Step | Expected |
183
+ |------|----------|
184
+ | Version | `soup v0.2.1` |
185
+ | Init templates | Creates yaml files |
186
+ | Data inspect | Table with stats + sample rows |
187
+ | Data validate | "20/20 rows valid" |
188
+ | Data stats | Length distribution + histogram |
189
+ | Data convert | Creates sharegpt/chatml jsonl files |
190
+ | Data merge | Merges into single file |
191
+ | Data dedup | Removes near-duplicates |
192
+ | Dry run | "Config valid" or similar |
193
+ | Train | Loss decreasing, ~1-3 min |
194
+ | Runs | Shows run with metrics |
195
+ | Chat | Model responds (quality low with 10 samples — that's OK) |
196
+ | Merge | Creates full model in test_merged_model/ |
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "soup-cli"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "Fine-tune LLMs in one command. No SSH, no config hell."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,3 +1,3 @@
1
1
  """Soup CLI — Fine-tune LLMs in one command."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.2.2"
@@ -179,7 +179,7 @@ def _load_model(
179
179
  base_model,
180
180
  trust_remote_code=True,
181
181
  device_map="auto",
182
- torch_dtype=torch.float16,
182
+ dtype=torch.float16,
183
183
  )
184
184
  console.print(f"[dim]Loading LoRA adapter: {model_path}...[/]")
185
185
  model_obj = PeftModel.from_pretrained(base, model_path)
@@ -189,7 +189,7 @@ def _load_model(
189
189
  model_path,
190
190
  trust_remote_code=True,
191
191
  device_map="auto",
192
- torch_dtype=torch.float16,
192
+ dtype=torch.float16,
193
193
  )
194
194
 
195
195
  model_obj.eval()
@@ -194,7 +194,7 @@ def _merge_adapter(adapter_path: str, base_model: str, output_dir: str):
194
194
  console.print(f"[dim]Loading base model: {base_model}...[/]")
195
195
  model = AutoModelForCausalLM.from_pretrained(
196
196
  base_model,
197
- torch_dtype=torch.float16,
197
+ dtype=torch.float16,
198
198
  trust_remote_code=True,
199
199
  device_map="cpu",
200
200
  )
@@ -91,12 +91,12 @@ def merge(
91
91
  "bfloat16": torch.bfloat16,
92
92
  "float32": torch.float32,
93
93
  }
94
- torch_dtype = dtype_map[dtype]
94
+ model_dtype = dtype_map[dtype]
95
95
 
96
96
  console.print(f"[dim]Loading base model: {base}...[/]")
97
97
  model = AutoModelForCausalLM.from_pretrained(
98
98
  base,
99
- torch_dtype=torch_dtype,
99
+ dtype=model_dtype,
100
100
  trust_remote_code=True,
101
101
  device_map="cpu",
102
102
  )
@@ -47,7 +47,7 @@ class SoupTrainerCallback(TrainerCallback):
47
47
 
48
48
  if torch.cuda.is_available():
49
49
  used = torch.cuda.memory_allocated() / (1024**3)
50
- total = torch.cuda.get_device_properties(0).total_mem / (1024**3)
50
+ total = torch.cuda.get_device_properties(0).total_memory / (1024**3)
51
51
  gpu_mem = f"{used:.1f}/{total:.1f} GB"
52
52
  except Exception:
53
53
  pass
@@ -127,6 +127,15 @@ class DPOTrainerWrapper:
127
127
  output_dir = output_dir / cfg.experiment_name
128
128
  output_dir.mkdir(parents=True, exist_ok=True)
129
129
 
130
+ # --- Calculate warmup steps from ratio ---
131
+ import math
132
+
133
+ total_steps = (
134
+ math.ceil(len(train_ds) / batch_size / tcfg.gradient_accumulation_steps)
135
+ * tcfg.epochs
136
+ )
137
+ warmup_steps = int(total_steps * tcfg.warmup_ratio)
138
+
130
139
  # --- DPO config ---
131
140
  dpo_config = DPOConfig(
132
141
  output_dir=str(output_dir),
@@ -134,7 +143,7 @@ class DPOTrainerWrapper:
134
143
  per_device_train_batch_size=batch_size,
135
144
  gradient_accumulation_steps=tcfg.gradient_accumulation_steps,
136
145
  learning_rate=tcfg.lr,
137
- warmup_ratio=tcfg.warmup_ratio,
146
+ warmup_steps=warmup_steps,
138
147
  weight_decay=tcfg.weight_decay,
139
148
  max_grad_norm=tcfg.max_grad_norm,
140
149
  optim=tcfg.optimizer,
@@ -137,6 +137,15 @@ class SFTTrainerWrapper:
137
137
  output_dir = output_dir / cfg.experiment_name
138
138
  output_dir.mkdir(parents=True, exist_ok=True)
139
139
 
140
+ # --- Calculate warmup steps from ratio ---
141
+ import math
142
+
143
+ total_steps = (
144
+ math.ceil(len(train_ds) / batch_size / tcfg.gradient_accumulation_steps)
145
+ * tcfg.epochs
146
+ )
147
+ warmup_steps = int(total_steps * tcfg.warmup_ratio)
148
+
140
149
  # --- Training args ---
141
150
  training_args = TrainingArguments(
142
151
  output_dir=str(output_dir),
@@ -144,7 +153,7 @@ class SFTTrainerWrapper:
144
153
  per_device_train_batch_size=batch_size,
145
154
  gradient_accumulation_steps=tcfg.gradient_accumulation_steps,
146
155
  learning_rate=tcfg.lr,
147
- warmup_ratio=tcfg.warmup_ratio,
156
+ warmup_steps=warmup_steps,
148
157
  weight_decay=tcfg.weight_decay,
149
158
  max_grad_norm=tcfg.max_grad_norm,
150
159
  optim=tcfg.optimizer,
@@ -25,7 +25,7 @@ def get_gpu_info() -> dict:
25
25
  import torch
26
26
 
27
27
  if torch.cuda.is_available():
28
- total = torch.cuda.get_device_properties(0).total_mem
28
+ total = torch.cuda.get_device_properties(0).total_memory
29
29
  total_gb = total / (1024**3)
30
30
  return {
31
31
  "memory_total": f"{total_gb:.1f} GB",
@@ -2,6 +2,7 @@
2
2
 
3
3
  from typer.testing import CliRunner
4
4
 
5
+ from soup_cli import __version__
5
6
  from soup_cli.cli import app
6
7
 
7
8
  runner = CliRunner()
@@ -10,7 +11,7 @@ runner = CliRunner()
10
11
  def test_version():
11
12
  result = runner.invoke(app, ["version"])
12
13
  assert result.exit_code == 0
13
- assert "0.2.0" in result.output
14
+ assert __version__ in result.output
14
15
 
15
16
 
16
17
  def test_help():
@@ -83,13 +83,13 @@ def test_resolve_checkpoint_auto_ignores_non_checkpoint_dirs(tmp_path: Path):
83
83
  def test_train_resume_flag_in_help():
84
84
  result = runner.invoke(app, ["train", "--help"])
85
85
  assert result.exit_code == 0
86
- assert "--resume" in result.output
86
+ assert "resume" in result.output.lower()
87
87
 
88
88
 
89
89
  def test_train_wandb_flag_in_help():
90
90
  result = runner.invoke(app, ["train", "--help"])
91
91
  assert result.exit_code == 0
92
- assert "--wandb" in result.output
92
+ assert "wandb" in result.output.lower()
93
93
 
94
94
 
95
95
  def test_train_resume_nonexistent_checkpoint(tmp_path: Path):
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
File without changes
File without changes
File without changes
File without changes