Skip to content

Commit ead4ec2

Browse files
committed
chore: Refactor CLI using cyclopts
1 parent 4b1c6a5 commit ead4ec2

66 files changed

Lines changed: 3066 additions & 3759 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.9.18
1+
3.10

cli_demo.py

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Demo script showcasing the CLI style guide with brand colors.
4+
Run this to see all the styled components in action.
5+
"""
6+
7+
import time
8+
9+
from rich.box import ROUNDED
10+
from rich.panel import Panel
11+
from rich.table import Table
12+
from rich.theme import Theme
13+
from rich.columns import Columns
14+
from rich.console import Console
15+
from rich.progress import Progress, BarColumn, TextColumn, SpinnerColumn, TaskProgressColumn
16+
17+
# Custom theme with brand colors (using only core starred colors)
18+
custom_theme = Theme(
19+
{
20+
# Text styles
21+
"primary": "#caaef5", # Purple 300 ⭐ (lighter when bold)
22+
"secondary": "dim #caaef5", # Purple 500 ⭐ (mid-tone without bold)
23+
"accent": "#ff68d4", # Pink 500 ⭐
24+
"muted": "#98a0b3", # Grey 400 ⭐
25+
"dim": "dim #626b84", # Grey 600 ⭐
26+
# Semantic styles
27+
"success": "bold #0dce74", # Green 400 ⭐
28+
"info": "#64afff", # Blue 500 ⭐
29+
"warning": "bold #ff815d", # Red 500 ⭐
30+
"error": "bold #c63800", # Red 700 ⭐
31+
# UI elements
32+
"prompt": "#ba92ff", # Purple 500 ⭐ (no bold)
33+
"prompt.choices": "#caaef5", # Purple 300 ⭐
34+
"prompt.default": "dim #98a0b3", # Grey 400 ⭐
35+
# Table styles
36+
"table.header": "#414858", # Purple 300 ⭐ (lighter when bold)
37+
"table.border": "#626b84", # Grey 600 ⭐
38+
"table.row": "#c4c9d4", # Grey 300 ⭐
39+
# Progress/Loading
40+
"progress.description": "#caaef5", # Purple 300 ⭐
41+
"progress.percentage": "bold #caaef5", # Purple 300 ⭐ (lighter when bold)
42+
"bar.complete": "#ba92ff", # Purple 500 ⭐ (no bold)
43+
"bar.finished": "#0dce74", # Green 400 ⭐
44+
"bar.pulse": "#ff68d4", # Pink 500 ⭐
45+
}
46+
)
47+
48+
console = Console(theme=custom_theme)
49+
50+
51+
def demo_tables():
52+
"""Demonstrate table styles."""
53+
console.print()
54+
console.print("[primary]═══ Tables Demo ═══[/primary]")
55+
console.print()
56+
57+
# Create a data table with generous spacing
58+
table = Table(
59+
title="[primary]Available Models[/primary]",
60+
header_style="table.header",
61+
border_style="table.border",
62+
show_header=True,
63+
box=ROUNDED,
64+
padding=(0, 2), # Generous horizontal padding
65+
# title_style="bold #caaef5",
66+
# title_justify="left",
67+
)
68+
69+
table.add_column("Model", style="primary")
70+
table.add_column("Type", style="secondary")
71+
table.add_column("Status", style="success", justify="center")
72+
table.add_column("Context", style="muted", justify="right")
73+
table.add_column("Created", style="muted")
74+
75+
# Add sample data
76+
models = [
77+
("meta-llama/Llama-3-70b", "chat", "✓ active", "8k", "2024-01-15"),
78+
("mistralai/Mistral-7B-v0.1", "completion", "✓ active", "32k", "2024-01-14"),
79+
("Qwen/Qwen2-72B", "chat", "✓ active", "4k", "2024-01-13"),
80+
("togethercomputer/GPT-NeoXT", "completion", "[error]⊘ inactive[error]", "2k", "2024-01-10"),
81+
]
82+
83+
for row in models:
84+
table.add_row(*row)
85+
86+
console.print(table)
87+
console.print()
88+
89+
90+
def demo_status_messages():
91+
"""Demonstrate status message styles."""
92+
console.print()
93+
console.print("[primary]═══ Status Messages Demo ═══[/primary]")
94+
console.print()
95+
96+
console.print("[success]✓[/success] Model deployed to production")
97+
console.print("[info]ℹ[/info] Using default configuration")
98+
console.print("[warning]⚠[/warning] Rate limit approaching")
99+
console.print("[error]✗[/error] API key required")
100+
console.print()
101+
102+
103+
def demo_panels():
104+
"""Demonstrate panel styles (card-based design)."""
105+
console.print()
106+
console.print("[primary]═══ Panels & Cards Demo ═══[/primary]")
107+
console.print()
108+
109+
# Welcome/header panel
110+
console.print(
111+
Panel(
112+
"[primary]Together AI - Model Training[/primary]\n[secondary]Train custom models on your data[/secondary]",
113+
border_style="primary",
114+
padding=(1, 2),
115+
)
116+
)
117+
118+
console.print()
119+
120+
# Info panel with cleaner messaging
121+
console.print(
122+
Panel(
123+
"Set your API key to get started:\n\n[dim]export TOGETHER_API_KEY='your-key-here'[/dim]",
124+
title="[info]Setup Required[/info]",
125+
border_style="info",
126+
padding=(1, 3),
127+
)
128+
)
129+
130+
console.print()
131+
132+
# Configuration card
133+
console.print(
134+
Panel(
135+
"[info]Endpoint:[/info] https://api.together.xyz\n"
136+
"[info]Model:[/info] meta-llama/Llama-3-70b\n"
137+
"[info]Context:[/info] 8k tokens",
138+
title="[primary]Configuration[/primary]",
139+
border_style="table.border",
140+
padding=(1, 2),
141+
)
142+
)
143+
144+
console.print()
145+
146+
147+
def demo_prompts():
148+
"""Demonstrate prompt styles (non-interactive demo)."""
149+
console.print()
150+
console.print("[primary]═══ Create Flow Demo ═══[/primary]")
151+
console.print()
152+
153+
console.print(
154+
Panel(
155+
"[primary]Fine-Tune Setup[/primary]\n[secondary]Let's configure your training job[/secondary]",
156+
border_style="primary",
157+
padding=(1, 2),
158+
)
159+
)
160+
161+
console.print()
162+
console.print("[dim]Step 1 of 3[/dim]")
163+
console.print("[prompt]Select base model:[/prompt] [prompt.choices](llama-3/mistral-7b/qwen-72b)[/prompt.choices]")
164+
console.print("[muted]→ llama-3[/muted]")
165+
166+
console.print()
167+
console.print("[dim]Step 2 of 3[/dim]")
168+
console.print("[prompt]Training dataset:[/prompt] [prompt.default][./data/train.jsonl][/prompt.default]")
169+
console.print("[muted]→ ./data/train.jsonl[/muted]")
170+
171+
console.print()
172+
console.print("[dim]Step 3 of 3[/dim]")
173+
console.print("[accent]Ready to start training? (Y/n)[/accent]")
174+
console.print("[muted]→ y[/muted]")
175+
176+
console.print()
177+
console.print("[success]✓[/success] Training job created")
178+
console.print()
179+
180+
181+
def demo_loading():
182+
"""Demonstrate loading indicators."""
183+
console.print()
184+
console.print("[primary]═══ Loading Indicators Demo ═══[/primary]")
185+
console.print()
186+
187+
# Spinner
188+
with console.status(
189+
"[progress.description]Loading models...[/progress.description]",
190+
spinner="dots",
191+
spinner_style="bar.pulse",
192+
) as _:
193+
time.sleep(1.5)
194+
195+
console.print("[success]✓[/success] Models loaded")
196+
console.print()
197+
198+
# Progress bar
199+
with Progress(
200+
SpinnerColumn(spinner_name="dots", style="bar.pulse"),
201+
TextColumn("[progress.description]{task.description}"),
202+
BarColumn(
203+
complete_style="bar.complete",
204+
finished_style="bar.finished",
205+
),
206+
TaskProgressColumn(style="progress.percentage"),
207+
console=console,
208+
) as progress:
209+
task = progress.add_task("[progress.description]Uploading training data...", total=100)
210+
211+
for _ in range(100):
212+
time.sleep(0.02)
213+
progress.update(task, advance=1)
214+
215+
progress.update(task, description="[success]Upload complete[/success]")
216+
time.sleep(0.5)
217+
218+
console.print()
219+
220+
221+
def demo_columns():
222+
"""Demonstrate column layout (dashboard cards)."""
223+
console.print()
224+
console.print("[primary]═══ Dashboard Demo ═══[/primary]")
225+
console.print()
226+
227+
panels = [
228+
Panel(
229+
"[success]125[/success] models\n[secondary]Available[/secondary]",
230+
title="[primary]Catalog[/primary]",
231+
border_style="table.border",
232+
padding=(1, 2),
233+
),
234+
Panel(
235+
"[accent]3[/accent] active\n[secondary]Training[/secondary]",
236+
title="[primary]Jobs[/primary]",
237+
border_style="table.border",
238+
padding=(1, 2),
239+
),
240+
Panel(
241+
"[info]5000[/info] credits\n[secondary]Remaining[/secondary]",
242+
title="[primary]Balance[/primary]",
243+
border_style="table.border",
244+
padding=(1, 2),
245+
),
246+
]
247+
248+
console.print(Columns(panels, equal=True, expand=True))
249+
console.print()
250+
251+
252+
def main():
253+
"""Run all demos."""
254+
console.clear()
255+
256+
# Header
257+
console.print(
258+
Panel(
259+
"[primary]Together AI CLI - Style Guide Demo[/primary]\n"
260+
"[secondary]Showcasing brand colors with Rich library[/secondary]",
261+
border_style="primary",
262+
padding=(1, 2),
263+
)
264+
)
265+
266+
demo_tables()
267+
demo_status_messages()
268+
demo_panels()
269+
demo_prompts()
270+
demo_loading()
271+
demo_columns()
272+
273+
# Footer
274+
console.print(
275+
Panel(
276+
"[dim]End of demo - See CLI_STYLE_GUIDE.md for implementation details[/dim]",
277+
border_style="dim",
278+
)
279+
)
280+
281+
282+
if __name__ == "__main__":
283+
main()

pyproject.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ dependencies = [
1515
"anyio>=3.5.0, <5",
1616
"distro>=1.7.0, <2",
1717
"sniffio",
18-
"click>=8.1.7",
18+
"cyclopts>=4.6.0",
1919
"rich>=13.7.1",
2020
"tabulate>=0.9.0",
2121
"pillow>=10.4.0",
@@ -25,9 +25,11 @@ dependencies = [
2525
"filelock>=3.13.1",
2626
"types-pyyaml>=6.0.12.20250915",
2727
"tomli>=2.0.0; python_version < '3.11'",
28+
"questionary>=2.1.1",
29+
"detect-agent>=0.1.1",
2830
]
2931

30-
requires-python = ">= 3.9"
32+
requires-python = ">= 3.10"
3133
classifiers = [
3234
"Typing :: Typed",
3335
"Intended Audience :: Developers",
@@ -60,6 +62,7 @@ cli = ["PyYAML"]
6062

6163
[project.scripts]
6264
together = "together.lib.cli:main"
65+
tg = "together.lib.cli:main"
6366

6467
[tool.uv]
6568
managed = true

0 commit comments

Comments
 (0)