troy-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.
- {troy_cli-0.2.0 → troy_cli-0.2.2}/PKG-INFO +4 -2
- {troy_cli-0.2.0 → troy_cli-0.2.2}/README.md +3 -1
- {troy_cli-0.2.0 → troy_cli-0.2.2}/pyproject.toml +1 -1
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/__init__.py +1 -1
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/cli.py +7 -2
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/hardware.py +2 -1
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/templates.py +27 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/.gitignore +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/chat.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/config.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/data.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/evaluate.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/export.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/push.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/serve.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/train_dpo.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/train_orpo.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/src/troy/train_sft.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/tests/test_config.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/tests/test_data.py +0 -0
- {troy_cli-0.2.0 → troy_cli-0.2.2}/tests/test_hardware.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: troy-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Fine-tune LLMs on your MacBook with one YAML file. Built for Apple Silicon.
|
|
5
5
|
Author: Troy
|
|
6
6
|
License: Apache-2.0
|
|
@@ -46,8 +46,10 @@ troy doctor # check your Mac: chip, memory, MLX, what you can train
|
|
|
46
46
|
troy init # create troy.yaml + sample data
|
|
47
47
|
troy train # fine-tune (LoRA/QLoRA via MLX)
|
|
48
48
|
troy chat # talk to the result
|
|
49
|
+
troy eval # did it work? base-vs-tuned loss + samples
|
|
49
50
|
troy serve # OpenAI-compatible API at localhost:8080/v1
|
|
50
51
|
troy export -f gguf # ship it to llama.cpp / Ollama / LM Studio
|
|
52
|
+
troy push you/model # upload to the Hugging Face Hub
|
|
51
53
|
```
|
|
52
54
|
|
|
53
55
|
## The config is the interface
|
|
@@ -75,7 +77,7 @@ output: ./output
|
|
|
75
77
|
|
|
76
78
|
| Command | Purpose |
|
|
77
79
|
|---|---|
|
|
78
|
-
| `troy init` | Create a config from a template (`chat`, `dpo`) |
|
|
80
|
+
| `troy init` | Create a config from a template (`chat`, `dpo`, `orpo`) |
|
|
79
81
|
| `troy doctor` | Hardware + dependency check, with model-size guidance |
|
|
80
82
|
| `troy train` | LoRA fine-tuning: SFT, DPO, or ORPO |
|
|
81
83
|
| `troy chat` | Interactive REPL (or `-p` for one-shot) with your adapter |
|
|
@@ -31,8 +31,10 @@ troy doctor # check your Mac: chip, memory, MLX, what you can train
|
|
|
31
31
|
troy init # create troy.yaml + sample data
|
|
32
32
|
troy train # fine-tune (LoRA/QLoRA via MLX)
|
|
33
33
|
troy chat # talk to the result
|
|
34
|
+
troy eval # did it work? base-vs-tuned loss + samples
|
|
34
35
|
troy serve # OpenAI-compatible API at localhost:8080/v1
|
|
35
36
|
troy export -f gguf # ship it to llama.cpp / Ollama / LM Studio
|
|
37
|
+
troy push you/model # upload to the Hugging Face Hub
|
|
36
38
|
```
|
|
37
39
|
|
|
38
40
|
## The config is the interface
|
|
@@ -60,7 +62,7 @@ output: ./output
|
|
|
60
62
|
|
|
61
63
|
| Command | Purpose |
|
|
62
64
|
|---|---|
|
|
63
|
-
| `troy init` | Create a config from a template (`chat`, `dpo`) |
|
|
65
|
+
| `troy init` | Create a config from a template (`chat`, `dpo`, `orpo`) |
|
|
64
66
|
| `troy doctor` | Hardware + dependency check, with model-size guidance |
|
|
65
67
|
| `troy train` | LoRA fine-tuning: SFT, DPO, or ORPO |
|
|
66
68
|
| `troy chat` | Interactive REPL (or `-p` for one-shot) with your adapter |
|
|
@@ -51,7 +51,7 @@ def _main(
|
|
|
51
51
|
@app.command()
|
|
52
52
|
def init(
|
|
53
53
|
template: str = typer.Option(
|
|
54
|
-
"chat", help="Template: chat (SFT) or
|
|
54
|
+
"chat", help="Template: chat (SFT), dpo, or orpo (preference tuning)."
|
|
55
55
|
),
|
|
56
56
|
path: Path = typer.Option(Path("troy.yaml"), help="Where to write the config."),
|
|
57
57
|
force: bool = typer.Option(False, "--force", help="Overwrite an existing config."),
|
|
@@ -120,7 +120,12 @@ def doctor() -> None:
|
|
|
120
120
|
except ImportError:
|
|
121
121
|
table.add_row("mlx-lm", f"{fail} (not installed)")
|
|
122
122
|
|
|
123
|
-
table.add_row("
|
|
123
|
+
table.add_row("Comfortable size", model_guidance(hw.memory_gb))
|
|
124
|
+
table.add_row(
|
|
125
|
+
"Supported models",
|
|
126
|
+
"any mlx-lm architecture (Llama, Qwen, Gemma, Phi, Mistral, ...)\n"
|
|
127
|
+
"thousands of ready conversions: hf.co/mlx-community",
|
|
128
|
+
)
|
|
124
129
|
console.print(table)
|
|
125
130
|
|
|
126
131
|
if not hw.is_apple_silicon:
|
|
@@ -42,7 +42,8 @@ def detect() -> Hardware:
|
|
|
42
42
|
)
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
# (min unified memory GB, guidance) — QLoRA 4-bit
|
|
45
|
+
# (min unified memory GB, guidance) — QLoRA 4-bit sizing EXAMPLES, not a
|
|
46
|
+
# whitelist: any mlx-lm-supported architecture trains.
|
|
46
47
|
MODEL_GUIDANCE = [
|
|
47
48
|
(128, "up to ~70B (4-bit QLoRA), e.g. Llama-3.3-70B, Qwen2.5-72B"),
|
|
48
49
|
(64, "up to ~32B (4-bit QLoRA), e.g. Qwen2.5-32B, Gemma-2-27B"),
|
|
@@ -50,6 +50,32 @@ training:
|
|
|
50
50
|
output: ./output
|
|
51
51
|
"""
|
|
52
52
|
|
|
53
|
+
ORPO_TEMPLATE = """\
|
|
54
|
+
# Troy config — preference tuning (ORPO: no reference model, ~2x DPO speed)
|
|
55
|
+
# Run with: troy train
|
|
56
|
+
|
|
57
|
+
base: mlx-community/Qwen3-0.6B-4bit
|
|
58
|
+
task: orpo
|
|
59
|
+
|
|
60
|
+
data:
|
|
61
|
+
train: ./data/preferences.jsonl # {"prompt": ..., "chosen": ..., "rejected": ...}
|
|
62
|
+
format: preference
|
|
63
|
+
val_split: 0.05
|
|
64
|
+
|
|
65
|
+
training:
|
|
66
|
+
epochs: 1
|
|
67
|
+
lr: 2e-5
|
|
68
|
+
batch_size: auto
|
|
69
|
+
seq_len: 2048
|
|
70
|
+
lora:
|
|
71
|
+
r: 8
|
|
72
|
+
alpha: 16
|
|
73
|
+
orpo:
|
|
74
|
+
lambda: 0.2
|
|
75
|
+
|
|
76
|
+
output: ./output
|
|
77
|
+
"""
|
|
78
|
+
|
|
53
79
|
SAMPLE_SFT_DATA = [
|
|
54
80
|
{
|
|
55
81
|
"instruction": "What is the capital of France?",
|
|
@@ -81,4 +107,5 @@ SAMPLE_DPO_DATA = [
|
|
|
81
107
|
TEMPLATES = {
|
|
82
108
|
"chat": (CHAT_TEMPLATE, "train.jsonl", SAMPLE_SFT_DATA),
|
|
83
109
|
"dpo": (DPO_TEMPLATE, "preferences.jsonl", SAMPLE_DPO_DATA),
|
|
110
|
+
"orpo": (ORPO_TEMPLATE, "preferences.jsonl", SAMPLE_DPO_DATA),
|
|
84
111
|
}
|
|
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
|