Skip to content

Commit 4c8f6ba

Browse files
committed
create better debug report to show more detailed paths and files
1 parent 0b8705e commit 4c8f6ba

File tree

9 files changed

+117
-34
lines changed

9 files changed

+117
-34
lines changed

adalflow/adalflow/core/generator.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,10 +940,18 @@ def __init__(self, **kwargs):
940940
if kwargs is None:
941941
kwargs = {}
942942
kwargs["template"] = FEEDBACK_ENGINE_TEMPLATE
943+
943944
super().__init__(**kwargs)
944945
self.name = "BackwardEngine"
945946
self.teacher_mode = False
946947

948+
def call(self, **kwargs) -> GeneratorOutputType:
949+
r"""Catch the rate limit error and raise it."""
950+
output = super().call(**kwargs)
951+
if output and output.error is not None and "429" in output.error:
952+
raise ValueError(f"Error in the backward engine: {output.error}")
953+
return output
954+
947955
@staticmethod
948956
def failure_message_to_optimizer(
949957
gradient_response: GeneratorOutput,

adalflow/adalflow/optim/parameter.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,9 @@ def get_gradient_and_context_text(self) -> str:
453453
[self.gradients_context[g] for g in self.gradients],
454454
)
455455
)
456+
# set all gradients value to None
457+
for g in self.gradients:
458+
g.data = None
456459

457460
gradient_context_combined_str = Prompt(
458461
template=COMBINED_GRADIENTS_TEMPLATE,

adalflow/adalflow/optim/text_grad/tgd_optimizer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,8 @@ def propose(self):
386386
if self.proposing:
387387
raise ValueError("Already proposing a value.")
388388

389+
print("Proposing a new value.")
390+
389391
# no cache so that new proposal can be made
390392
no_cache = True
391393
# print("Proposing a new value.")

adalflow/adalflow/optim/trainer/adal.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -249,13 +249,18 @@ def evaluate_samples(
249249
)
250250

251251
for future in concurrent.futures.as_completed(futures):
252-
i = futures[future]
253-
acc_list[i] = (
254-
future.result()
255-
) # Place the result in the correct position
256-
progress_bar.update(
257-
1
258-
) # Update progress bar after each result is collected
252+
try:
253+
i = futures[future]
254+
acc_list[i] = (
255+
future.result()
256+
) # Place the result in the correct position
257+
progress_bar.update(
258+
1
259+
) # Update progress bar after each result is collected
260+
except Exception as e:
261+
262+
progress_bar.close()
263+
raise ValueError(f"Exception in task {i}: {e}")
259264

260265
avg_score = float(np.mean(np.array(acc_list)))
261266
return EvaluationResult(avg_score=avg_score, per_item_scores=acc_list)

adalflow/adalflow/optim/trainer/trainer.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,8 @@ def diagnose_report(
317317

318318
def debug_report(
319319
self,
320-
text_grad_debug_path: Optional[str] = None,
321-
few_shot_demo_debug_path: Optional[str] = None,
320+
text_grad_debug_path: Optional[Dict[str, object]] = None,
321+
few_shot_demo_debug_path: Optional[Dict[str, object]] = None,
322322
):
323323
import colorama
324324
from colorama import Fore
@@ -361,9 +361,12 @@ def fit(
361361
resume_from_ckpt: Optional[
362362
str
363363
] = None, # TODO: have a more comprehensive ckpt loading in the future
364-
):
364+
) -> Tuple[str, TrainerResult]:
365365
r"""
366366
train_loader: An iterable or collection of iterables specifying training samples.
367+
368+
Returns:
369+
Tuple[str, TrainerResult]: Checkpoint file and the TrainerResult object
367370
"""
368371
start_time = time.time()
369372

@@ -491,7 +494,7 @@ def fit(
491494
train_loader, train_dataset, val_dataset, test_dataset
492495
)
493496
self.debug_report(text_grad_debug_path, few_shot_demo_debug_path)
494-
return
497+
return self.ckpt_file, trainer_results
495498

496499
########Run text_optimizers and demo optimizers in sequential order ########
497500
if (
@@ -557,6 +560,7 @@ def fit(
557560
end_time = time.time()
558561
print(f"Training time: {end_time - start_time}s")
559562
print(f"ckpt_file: {self.ckpt_file}")
563+
return self.ckpt_file, trainer_results
560564

561565
@staticmethod
562566
def _estimate_num_epochs(train_loader: Any, max_steps: int):
@@ -684,7 +688,7 @@ def _pre_fit(self, val_dataset: Any, test_dataset: Any) -> TrainerResult:
684688

685689
def _fit_demos_one_step_for_debug(
686690
self, train_loader, train_dataset: Any, val_dataset: Any, test_dataset: Any
687-
) -> str:
691+
) -> Dict[str, object]:
688692
"""Trace both the teacher and the student demos with scores and for sampling.
689693
For demos: we need to run both the teacher mode and the student mode."""
690694

@@ -760,6 +764,8 @@ def _fit_demos_one_step_for_debug(
760764

761765
# 2. run student mode
762766

767+
demo_debug_result_path = None
768+
763769
for batch_idx, batch in enumerate(train_loader):
764770
print(f"Training step: {batch_idx}")
765771
if batch_idx > 0:
@@ -820,7 +826,9 @@ def _fit_demos_one_step_for_debug(
820826
self._demo_optimizers_propose()
821827
graph_path = os.path.join(debug_path, "student_graph")
822828

823-
paths = losses_student[0].draw_graph(filepath=graph_path) # noqa F841
829+
demo_debug_result_path = losses_student[0].draw_graph(
830+
filepath=graph_path
831+
) # noqa F841
824832

825833
# test step
826834
self._demo_optimizers_step()
@@ -851,9 +859,9 @@ def _fit_demos_one_step_for_debug(
851859
if len(param._demos) == 0:
852860
raise ValueError(f"No demos found, param: {param}")
853861

854-
return debug_path
862+
return demo_debug_result_path
855863

856-
def _fit_text_grads_one_step_for_debug(self, train_loader: Any) -> str:
864+
def _fit_text_grads_one_step_for_debug(self, train_loader: Any) -> Dict[str, str]:
857865
printc(
858866
"Debugging fitting one step with batch size 2 for text optimizer", "blue"
859867
)
@@ -901,8 +909,8 @@ def _fit_text_grads_one_step_for_debug(self, train_loader: Any) -> str:
901909
# test optimizer
902910
self._propose_text_optimizers()
903911

904-
total_loss.draw_graph(filepath=debug_path, full_trace=True)
905-
return debug_path
912+
debug_files = total_loss.draw_graph(filepath=debug_path, full_trace=True)
913+
return debug_files
906914

907915
def _set_demo_optimizers_dataset(self, train_dataset: Any):
908916
# init the dataset
@@ -1701,6 +1709,9 @@ def _text_grad_constraint_propose_step(
17011709
all_y_preds,
17021710
include_demo_optimizers: bool = False,
17031711
):
1712+
"""Handles both the mixed training and the separate training.
1713+
When include_demo_optimizers is True, the demo optimizers are included in the training
1714+
"""
17041715
# comptute moving batch acc
17051716
from adalflow.optim.parameter import Parameter
17061717

@@ -1894,6 +1905,7 @@ def _fit_text_grad_constraint(
18941905
trainer_results.prompts[-1],
18951906
total_steps,
18961907
)
1908+
self._add_failed_proposals_text_optimizers()
18971909
continue
18981910

18991911
# prune the correct sample size if its too big, same with error samples

use_cases/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
gpt_4o_model = {
4242
"model_client": OpenAIClient(),
4343
"model_kwargs": {
44-
"model": "gpt-4o",
44+
"model": "gpt-4o-mini",
4545
"temperature": 1,
4646
"top_p": 0.99,
4747
"max_tokens": 1000,

use_cases/question_answering/bbh/object_count/task.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ def call(
6060
self, question: str, id: str = None
6161
) -> Union[adal.GeneratorOutput, adal.Parameter]:
6262
output = self.llm_counter(prompt_kwargs={"input_str": question}, id=id)
63+
print(f"output: {output}, training: {self.training}")
64+
if self.training:
65+
if output.full_response.error and "429" in output.full_response.error:
66+
raise ValueError("Rate limit exceeded")
67+
else:
68+
if output.error and "429" in output.error:
69+
print("rate limit exceeded:")
70+
raise ValueError("Rate limit exceeded")
6371
return output
6472

6573

use_cases/question_answering/bbh/object_count/train_new.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,22 +130,33 @@ def train(
130130
print(trainer)
131131

132132
train_dataset, val_dataset, test_dataset = load_datasets()
133-
trainer.fit(
133+
ckpt, _ = trainer.fit(
134134
train_dataset=train_dataset,
135135
val_dataset=val_dataset,
136136
test_dataset=test_dataset,
137137
resume_from_ckpt=resume_from_ckpt,
138138
)
139+
return ckpt
139140

140141

141142
if __name__ == "__main__":
143+
import sys
144+
import json
142145

143-
train(
146+
ckpt = train(
144147
debug=True,
145-
max_steps=12,
148+
max_steps=1,
146149
strategy="constrained",
147150
exclude_input_fields_from_bootstrap_demos=True,
148151
)
152+
print(f"ckpt: {ckpt}")
153+
# Save ckpt to a file passed as an argument
154+
if len(sys.argv) > 1: # Check if a file path is provided
155+
with open(sys.argv[1], "w") as f:
156+
json.dump({"ckpt": ckpt}, f)
149157

150158
# train_diagnose(**gpt_3_model)
151-
# train_diagnose_teacher(**gpt_4o_model)
159+
# train_diagnose_teacher(**gpt_4o_model) # 4omini works well as an optimizer too
160+
# /Users/liyin/.adalflow/ckpt/ObjectCountAdalComponent/constrained_max_steps_12_49c63_run_1.json
161+
# 0.72 -> 0.9 val
162+
# 0.79 -> 0.92 test

use_cases/text_grad_2.0_train.py

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,58 @@
11
import subprocess
2+
import tempfile
3+
import json
24

35
# List of experiments to run
6+
object_count = "use_cases/question_answering/bbh/object_count/train_new.py"
7+
hotpot_qa_multi_hop_rag = "benchmarks/hotpot_qa/adal_exp/train_multi_hop_rag.py"
8+
9+
ckpt_values = []
410
experiments = [
5-
"experiment1.py",
6-
"experiment2.py",
7-
"experiment3.py",
11+
object_count,
12+
# hotpot_qa_multi_hop_rag,
813
]
914

1015
# Optional: Arguments for each experiment (if needed)
1116
experiment_args = {
12-
"experiment1.py": "",
13-
"experiment2.py": "",
14-
"experiment3.py": "",
17+
object_count: "",
18+
# hotpot_qa_multi_hop_rag: "",
1519
}
20+
ckpt_values = {}
21+
1622

17-
# Loop through experiments and run them
18-
for experiment in experiments:
19-
args = experiment_args.get(experiment, "")
23+
def run_experiment(script, args):
2024
try:
21-
print(f"Running {experiment} with args: {args}")
22-
subprocess.run(f"python {experiment} {args}", check=True, shell=True)
25+
# Use a temporary file to store the ckpt
26+
with tempfile.NamedTemporaryFile(suffix=".json", delete=False) as temp_file:
27+
temp_path = temp_file.name
28+
29+
print(f"Running {script} with args: {args}")
30+
subprocess.run(
31+
f"python {script} {temp_path} {args}",
32+
check=True,
33+
shell=True,
34+
text=True,
35+
)
36+
37+
# Read the ckpt value from the temporary file
38+
with open(temp_path, "r") as f:
39+
data = json.load(f)
40+
ckpt = data.get("ckpt")
41+
print(f"Checkpoint from {script}: {ckpt}")
42+
return ckpt
43+
2344
except subprocess.CalledProcessError as e:
24-
print(f"Experiment {experiment} failed with error: {e}")
45+
print(f"Experiment {script} failed with error: {e}")
46+
return None
47+
48+
49+
if __name__ == "__main__":
50+
for experiment in experiments:
51+
args = experiment_args.get(experiment, "")
52+
ckpt = run_experiment(experiment, args)
53+
if ckpt:
54+
ckpt_values[experiment] = ckpt
55+
56+
print("\nAll Checkpoints:")
57+
for experiment, ckpt in ckpt_values.items():
58+
print(f"{experiment}: {ckpt}")

0 commit comments

Comments
 (0)