Skip to content

Commit 1491e17

Browse files
committed
iterate with claude
1 parent bafd03c commit 1491e17

File tree

8 files changed

+526
-556
lines changed

8 files changed

+526
-556
lines changed

src/data_designer/cli/commands/list.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def list_command(
5353
if providers_data or models_data:
5454
print_info("Configuration loaded successfully")
5555
else:
56-
print_warning("No configuration files found. Run 'data-designer init' to create them.")
56+
print_warning("No configuration files found. Run 'data-designer config' to see available commands.")
5757

5858

5959
def load_providers(provider_path: Path, as_json: bool) -> dict | None:
@@ -123,7 +123,7 @@ def load_providers(provider_path: Path, as_json: bool) -> dict | None:
123123
except InvalidFilePathError:
124124
if not as_json:
125125
print_warning(f"Provider configuration not found: {provider_path}")
126-
print_info("Run 'data-designer init' to create it")
126+
print_info("Run 'data-designer config providers' to create it")
127127
console.print()
128128
return {"file": str(provider_path), "valid": False, "error": "File not found"} if as_json else None
129129

@@ -220,7 +220,7 @@ def load_models(model_path: Path, as_json: bool) -> dict | None:
220220
except InvalidFilePathError:
221221
if not as_json:
222222
print_warning(f"Model configuration not found: {model_path}")
223-
print_info("Run 'data-designer init' to create it")
223+
print_info("Run 'data-designer config models' to create it")
224224
console.print()
225225
return {"file": str(model_path), "valid": False, "error": "File not found"} if as_json else None
226226

src/data_designer/cli/commands/models.py

Lines changed: 146 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@
77

88
from data_designer.cli.ui import (
99
BACK,
10+
confirm_action,
1011
console,
12+
display_config_preview,
1113
print_error,
1214
print_header,
1315
print_info,
16+
print_navigation_tip,
1417
print_success,
18+
print_warning,
1519
prompt_text_input,
1620
select_with_arrows,
1721
)
@@ -62,14 +66,62 @@ def models_command(
6266
raise typer.Exit(1)
6367

6468
print_info(f"Configuration will be saved to: {config_dir}")
65-
console.print()
69+
print_navigation_tip()
70+
71+
# Check for existing configuration
72+
model_path = get_model_config_path(config_dir)
73+
existing_config = None
74+
mode = "create" # "create", "add", or "rewrite"
75+
76+
if model_path.exists():
77+
try:
78+
existing_config = load_config_file(model_path)
79+
except Exception as e:
80+
print_warning(f"Could not load existing configuration: {e}")
81+
print_info("Starting with new configuration")
82+
else:
83+
# Successfully loaded existing config
84+
print_info(
85+
f"Found existing model configuration with {len(existing_config.get('model_configs', []))} model(s)"
86+
)
87+
console.print()
88+
89+
# Show existing configuration
90+
display_config_preview(existing_config, "Current Configuration")
91+
console.print()
92+
93+
# Ask what to do
94+
action_options = {
95+
"add": "Add more models to existing configuration",
96+
"rewrite": "Rewrite the entire configuration",
97+
"exit": "Exit without making changes",
98+
}
99+
action = select_with_arrows(
100+
action_options,
101+
"What would you like to do?",
102+
default_key="add",
103+
allow_back=False,
104+
)
105+
106+
if action is None or action == "exit":
107+
print_info("No changes made to configuration")
108+
raise typer.Exit(0)
109+
elif action == "add":
110+
mode = "add"
111+
elif action == "rewrite":
112+
mode = "rewrite"
66113

67114
# Run the model configuration wizard
68-
model_config = configure_models(available_providers)
115+
model_config = configure_models(available_providers, existing_config if mode == "add" else None)
69116
if model_config is None:
70117
print_error("Model configuration cancelled")
71118
raise typer.Exit(1)
72119

120+
# Check if config actually changed (when adding to existing)
121+
if mode == "add" and model_config == existing_config:
122+
print_info("No changes made to configuration")
123+
raise typer.Exit(0)
124+
73125
# Save configuration
74126
try:
75127
ensure_config_dir_exists(config_dir)
@@ -81,59 +133,51 @@ def models_command(
81133
raise typer.Exit(1)
82134

83135

84-
def configure_models(available_providers: list[str]) -> dict | None:
136+
def configure_models(available_providers: list[str], existing_config: dict | None = None) -> dict | None:
85137
"""Interactive configuration for model configs with back navigation.
86138
87139
Args:
88140
available_providers: List of available provider names
141+
existing_config: Optional existing configuration to add to
89142
90143
Returns:
91144
Model configuration dictionary, or None if cancelled
92145
"""
93146
# Step-based state machine for back navigation
94-
step = "num_models"
95-
num_models = 1
147+
step = "model_alias"
96148
model_configs: list[dict] = []
97-
model_idx = 0
98149

99-
# Storage for model data as we build it
100-
current_model: dict = {}
150+
# If we have existing config, load the models
151+
num_existing = 0
152+
if existing_config:
153+
model_configs = existing_config.get("model_configs", []).copy()
154+
num_existing = len(model_configs)
155+
print_info(f"Adding to existing {num_existing} model(s)")
156+
console.print()
101157

102-
while True:
103-
if step == "num_models":
104-
# Ask how many models
105-
result = prompt_text_input(
106-
"How many models do you want to configure? (1-10)",
107-
default="1",
108-
validator=lambda x: validate_positive_int(x) if x else (True, None),
109-
allow_back=False, # First step, can't go back
110-
)
158+
# Track how many NEW models we've added (for numbering and back navigation)
159+
new_models_count = 0
111160

112-
if result is None:
113-
return None
161+
# Storage for model data as we build it
162+
current_model: dict = {}
114163

115-
num_models = int(result) if result else 1
116-
num_models = min(max(num_models, 1), 10) # Clamp to 1-10
117-
model_idx = 0
118-
model_configs = []
119-
step = "model_alias"
120-
121-
elif step == "model_alias":
122-
if model_idx >= num_models:
123-
# Done with all models
124-
step = "done"
125-
continue
164+
# History stack for proper back navigation
165+
# Each entry: (step_name, model_data)
166+
history: list[tuple[str, dict]] = []
126167

168+
while True:
169+
if step == "model_alias":
127170
console.print()
128-
print_info(f"Configuring model {model_idx + 1}/{num_models}")
171+
total_count = num_existing + new_models_count + 1
172+
print_info(f"Configuring model {total_count}")
129173

130174
# Get existing model aliases for validation
131175
model_aliases = {m["alias"] for m in model_configs}
132176

133177
# Model alias
134178
result = prompt_text_input(
135179
"Model alias (used in your configs)",
136-
default="llama-3-70b" if model_idx == 0 else current_model.get("alias"),
180+
default="llama-3-70b" if new_models_count == 0 and num_existing == 0 else current_model.get("alias"),
137181
validator=lambda x, aliases=model_aliases: (
138182
(False, "Model alias must not be empty")
139183
if not x
@@ -147,26 +191,40 @@ def configure_models(available_providers: list[str]) -> dict | None:
147191
if result is None:
148192
return None
149193
elif result is BACK:
150-
# Go back to previous model or num_models
151-
if model_idx > 0 and len(model_configs) > 0:
152-
# Go back to previous model
153-
model_idx -= 1
154-
current_model = model_configs.pop()
155-
step = "model_max_tokens" # Go to last step of previous model
194+
# Go back using history if available
195+
if history:
196+
# Pop from history and restore state to edit a completed model
197+
prev_step, prev_model = history.pop()
198+
# Remove the last model from the list so we can re-add it after editing
199+
if len(model_configs) > num_existing:
200+
model_configs.pop()
201+
new_models_count -= 1
202+
current_model = prev_model
203+
step = prev_step
156204
continue
157205
else:
158-
# First model, go back to num_models question
159-
step = "num_models"
160-
continue
206+
# No history - check if there are existing models
207+
if num_existing > 0:
208+
# There are existing models, so canceling is OK
209+
if confirm_action("Discard the new models?", default=False):
210+
return existing_config # Return the original config unchanged
211+
continue
212+
else:
213+
# No existing models, confirm complete cancellation
214+
if confirm_action("Cancel all model configuration?", default=False):
215+
return None
216+
continue
161217

162218
current_model = {"alias": result}
163219
step = "model_id"
164220

165221
elif step == "model_id":
166222
# Model ID
167223
result = prompt_text_input(
168-
"Model ID (e.g., meta/llama-3.3-70b-instruct)",
169-
default="meta/llama-3.3-70b-instruct" if model_idx == 0 else current_model.get("model"),
224+
"Model ID",
225+
default="meta/llama-3.3-70b-instruct"
226+
if new_models_count == 0 and num_existing == 0
227+
else current_model.get("model"),
170228
validator=lambda x: (False, "Model ID is required") if not x else (True, None),
171229
allow_back=True,
172230
)
@@ -216,7 +274,7 @@ def configure_models(available_providers: list[str]) -> dict | None:
216274
print_info("Inference Parameters")
217275

218276
result = prompt_text_input(
219-
f"Temperature ({MIN_TEMPERATURE}-{MAX_TEMPERATURE})",
277+
f"Temperature <dim>({MIN_TEMPERATURE}-{MAX_TEMPERATURE})</dim>",
220278
default="0.7",
221279
validator=lambda x: validate_numeric_range(x, MIN_TEMPERATURE, MAX_TEMPERATURE) if x else (True, None),
222280
allow_back=True,
@@ -235,7 +293,7 @@ def configure_models(available_providers: list[str]) -> dict | None:
235293
elif step == "model_top_p":
236294
# Top P
237295
result = prompt_text_input(
238-
f"Top P ({MIN_TOP_P}-{MAX_TOP_P})",
296+
f"Top P <dim>({MIN_TOP_P}-{MAX_TOP_P})</dim>",
239297
default="0.9",
240298
validator=lambda x: validate_numeric_range(x, MIN_TOP_P, MAX_TOP_P) if x else (True, None),
241299
allow_back=True,
@@ -254,7 +312,7 @@ def configure_models(available_providers: list[str]) -> dict | None:
254312
elif step == "model_max_tokens":
255313
# Max tokens
256314
result = prompt_text_input(
257-
"Max tokens (press Enter for default: 2048)",
315+
"Max tokens",
258316
default="2048",
259317
validator=lambda x: validate_positive_int(x) if x else (True, None),
260318
allow_back=True,
@@ -274,13 +332,53 @@ def configure_models(available_providers: list[str]) -> dict | None:
274332
try:
275333
ModelConfig.model_validate(current_model)
276334
model_configs.append(current_model)
277-
model_idx += 1
335+
new_models_count += 1
336+
# Save to history before moving on
337+
history.append(("model_max_tokens", current_model.copy()))
278338
current_model = {}
279-
step = "model_alias" # Move to next model or finish
339+
step = "add_another" # Ask if they want to add another model
280340
except Exception as e:
281341
print_error(f"Invalid model configuration: {e}")
282342
return None
283343

344+
elif step == "add_another":
345+
# Ask if user wants to add another model
346+
console.print()
347+
348+
# Create options for selection with back support
349+
add_another_options = {
350+
"yes": "Add another model",
351+
"no": "Finish configuring models",
352+
}
353+
result = select_with_arrows(
354+
add_another_options,
355+
"Would you like to add another model?",
356+
default_key="no",
357+
allow_back=True,
358+
)
359+
360+
if result is None:
361+
return None
362+
elif result is BACK:
363+
# Go back to the last model's max_tokens step
364+
if history:
365+
prev_step, prev_model = history.pop()
366+
# Remove the last model so we can re-add it after editing
367+
if len(model_configs) > num_existing:
368+
model_configs.pop()
369+
new_models_count -= 1
370+
current_model = prev_model
371+
step = "model_max_tokens"
372+
continue
373+
elif result == "yes":
374+
step = "model_alias"
375+
else: # "no"
376+
step = "done"
377+
284378
elif step == "done":
379+
if len(model_configs) == 0:
380+
print_error("No models configured")
381+
return None
382+
285383
config = {"model_configs": model_configs}
286384
return config

0 commit comments

Comments
 (0)