chore: remove redundant tag in old scenarios (#917)

* remove state.times in old ui

* remove "r" tag

* remove "d" tag

* remove "ef" tag

* remove "init" tag

* fix CI

* remove old tag in app UI

* fix bugs

* fix CI

* some updates

* filter tags
This commit is contained in:
XianBW
2025-06-13 17:49:58 +08:00
committed by GitHub
parent 77e9f186d5
commit 5a3a2bf2be
7 changed files with 238 additions and 290 deletions
+9 -12
View File
@@ -30,18 +30,15 @@ def extract_models_and_implement(report_file_path: str) -> None:
Returns:
None
"""
with logger.tag("init"):
scenario = GeneralModelScenario()
logger.log_object(scenario, tag="scenario")
with logger.tag("r"):
# Save Relevant Images
img = extract_first_page_screenshot_from_pdf(report_file_path)
logger.log_object(img, tag="pdf_image")
exp = ModelExperimentLoaderFromPDFfiles().load(report_file_path)
logger.log_object(exp, tag="load_experiment")
with logger.tag("d"):
exp = QlibModelCoSTEER(scenario).develop(exp)
logger.log_object(exp, tag="developed_experiment")
scenario = GeneralModelScenario()
logger.log_object(scenario, tag="scenario")
# Save Relevant Images
img = extract_first_page_screenshot_from_pdf(report_file_path)
logger.log_object(img, tag="pdf_image")
exp = ModelExperimentLoaderFromPDFfiles().load(report_file_path)
logger.log_object(exp, tag="load_experiment")
exp = QlibModelCoSTEER(scenario).develop(exp)
logger.log_object(exp, tag="developed_experiment")
if __name__ == "__main__":
+72 -79
View File
@@ -28,90 +28,83 @@ from rdagent.scenarios.kaggle.proposal.proposal import KGTrace
class KaggleRDLoop(RDLoop):
def __init__(self, PROP_SETTING: BasePropSetting):
with logger.tag("init"):
scen: Scenario = import_class(PROP_SETTING.scen)(PROP_SETTING.competition)
logger.log_object(scen, tag="scenario")
knowledge_base = (
import_class(PROP_SETTING.knowledge_base)(PROP_SETTING.knowledge_base_path, scen)
if PROP_SETTING.knowledge_base != ""
else None
)
logger.log_object(knowledge_base, tag="knowledge_base")
self.hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.hypothesis_gen)(scen)
logger.log_object(self.hypothesis_gen, tag="hypothesis generator")
self.hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.hypothesis2experiment)()
logger.log_object(self.hypothesis2experiment, tag="hypothesis2experiment")
self.feature_coder: Developer = import_class(PROP_SETTING.feature_coder)(scen)
logger.log_object(self.feature_coder, tag="feature coder")
self.model_feature_selection_coder: Developer = import_class(PROP_SETTING.model_feature_selection_coder)(
scen
)
logger.log_object(self.model_feature_selection_coder, tag="model feature selection coder")
self.model_coder: Developer = import_class(PROP_SETTING.model_coder)(scen)
logger.log_object(self.model_coder, tag="model coder")
self.feature_runner: Developer = import_class(PROP_SETTING.feature_runner)(scen)
logger.log_object(self.feature_runner, tag="feature runner")
self.model_runner: Developer = import_class(PROP_SETTING.model_runner)(scen)
logger.log_object(self.model_runner, tag="model runner")
self.summarizer: Experiment2Feedback = import_class(PROP_SETTING.summarizer)(scen)
logger.log_object(self.summarizer, tag="summarizer")
self.trace = KGTrace(scen=scen, knowledge_base=knowledge_base)
super(RDLoop, self).__init__()
scen: Scenario = import_class(PROP_SETTING.scen)(PROP_SETTING.competition)
logger.log_object(scen, tag="scenario")
knowledge_base = (
import_class(PROP_SETTING.knowledge_base)(PROP_SETTING.knowledge_base_path, scen)
if PROP_SETTING.knowledge_base != ""
else None
)
logger.log_object(knowledge_base, tag="knowledge_base")
self.hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.hypothesis_gen)(scen)
logger.log_object(self.hypothesis_gen, tag="hypothesis generator")
self.hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.hypothesis2experiment)()
logger.log_object(self.hypothesis2experiment, tag="hypothesis2experiment")
self.feature_coder: Developer = import_class(PROP_SETTING.feature_coder)(scen)
logger.log_object(self.feature_coder, tag="feature coder")
self.model_feature_selection_coder: Developer = import_class(PROP_SETTING.model_feature_selection_coder)(scen)
logger.log_object(self.model_feature_selection_coder, tag="model feature selection coder")
self.model_coder: Developer = import_class(PROP_SETTING.model_coder)(scen)
logger.log_object(self.model_coder, tag="model coder")
self.feature_runner: Developer = import_class(PROP_SETTING.feature_runner)(scen)
logger.log_object(self.feature_runner, tag="feature runner")
self.model_runner: Developer = import_class(PROP_SETTING.model_runner)(scen)
logger.log_object(self.model_runner, tag="model runner")
self.summarizer: Experiment2Feedback = import_class(PROP_SETTING.summarizer)(scen)
logger.log_object(self.summarizer, tag="summarizer")
self.trace = KGTrace(scen=scen, knowledge_base=knowledge_base)
super(RDLoop, self).__init__()
def coding(self, prev_out: dict[str, Any]):
with logger.tag("d"): # develop
if prev_out["direct_exp_gen"]["propose"].action in [
KG_ACTION_FEATURE_ENGINEERING,
KG_ACTION_FEATURE_PROCESSING,
]:
exp = self.feature_coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
elif prev_out["direct_exp_gen"]["propose"].action == KG_ACTION_MODEL_FEATURE_SELECTION:
exp = self.model_feature_selection_coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
else:
exp = self.model_coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
logger.log_object(exp.sub_workspace_list, tag="coder result")
if prev_out["direct_exp_gen"]["propose"].action in [
KG_ACTION_FEATURE_ENGINEERING,
KG_ACTION_FEATURE_PROCESSING,
]:
exp = self.feature_coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
elif prev_out["direct_exp_gen"]["propose"].action == KG_ACTION_MODEL_FEATURE_SELECTION:
exp = self.model_feature_selection_coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
else:
exp = self.model_coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
logger.log_object(exp.sub_workspace_list, tag="coder result")
return exp
def running(self, prev_out: dict[str, Any]):
with logger.tag("ef"): # evaluate and feedback
if prev_out["direct_exp_gen"]["propose"].action in [
KG_ACTION_FEATURE_ENGINEERING,
KG_ACTION_FEATURE_PROCESSING,
]:
exp = self.feature_runner.develop(prev_out["coding"])
else:
exp = self.model_runner.develop(prev_out["coding"])
logger.log_object(exp, tag="runner result")
if KAGGLE_IMPLEMENT_SETTING.competition in [
"optiver-realized-volatility-prediction",
"covid19-global-forecasting-week-1",
]:
try:
python_files_to_notebook(
KAGGLE_IMPLEMENT_SETTING.competition, exp.experiment_workspace.workspace_path
)
except Exception as e:
logger.error(f"Merge python files to one file failed: {e}")
if KAGGLE_IMPLEMENT_SETTING.auto_submit:
csv_path = exp.experiment_workspace.workspace_path / "submission.csv"
try:
subprocess.run(
[
"kaggle",
"competitions",
"submit",
"-f",
str(csv_path.absolute()),
"-m",
str(csv_path.parent.absolute()),
KAGGLE_IMPLEMENT_SETTING.competition,
],
check=True,
)
except subprocess.CalledProcessError as e:
logger.error(f"Auto submission failed: \n{e}")
except Exception as e:
logger.error(f"Other exception when use kaggle api:\n{e}")
if prev_out["direct_exp_gen"]["propose"].action in [
KG_ACTION_FEATURE_ENGINEERING,
KG_ACTION_FEATURE_PROCESSING,
]:
exp = self.feature_runner.develop(prev_out["coding"])
else:
exp = self.model_runner.develop(prev_out["coding"])
logger.log_object(exp, tag="runner result")
if KAGGLE_IMPLEMENT_SETTING.competition in [
"optiver-realized-volatility-prediction",
"covid19-global-forecasting-week-1",
]:
try:
python_files_to_notebook(KAGGLE_IMPLEMENT_SETTING.competition, exp.experiment_workspace.workspace_path)
except Exception as e:
logger.error(f"Merge python files to one file failed: {e}")
if KAGGLE_IMPLEMENT_SETTING.auto_submit:
csv_path = exp.experiment_workspace.workspace_path / "submission.csv"
try:
subprocess.run(
[
"kaggle",
"competitions",
"submit",
"-f",
str(csv_path.absolute()),
"-m",
str(csv_path.parent.absolute()),
KAGGLE_IMPLEMENT_SETTING.competition,
],
check=True,
)
except subprocess.CalledProcessError as e:
logger.error(f"Auto submission failed: \n{e}")
except Exception as e:
logger.error(f"Other exception when use kaggle api:\n{e}")
return exp
+5 -6
View File
@@ -17,12 +17,11 @@ class FactorRDLoop(RDLoop):
skip_loop_error = (FactorEmptyError,)
def running(self, prev_out: dict[str, Any]):
with logger.tag("ef"): # evaluate and feedback
exp = self.runner.develop(prev_out["coding"])
if exp is None:
logger.error(f"Factor extraction failed.")
raise FactorEmptyError("Factor extraction failed.")
logger.log_object(exp, tag="runner result")
exp = self.runner.develop(prev_out["coding"])
if exp is None:
logger.error(f"Factor extraction failed.")
raise FactorEmptyError("Factor extraction failed.")
logger.log_object(exp, tag="runner result")
return exp
+22 -24
View File
@@ -112,27 +112,26 @@ class FactorReportLoop(FactorRDLoop, metaclass=LoopMeta):
self.steps = ["propose_hypo_exp", "propose", "direct_exp_gen", "coding", "running", "feedback"]
def propose_hypo_exp(self, prev_out: dict[str, Any]):
with logger.tag("r"):
while True:
if FACTOR_FROM_REPORT_PROP_SETTING.is_report_limit_enabled and self.valid_pdf_file_count > 15:
break
report_file_path = self.judge_pdf_data_items[self.pdf_file_index]
logger.info(f"Processing number {self.pdf_file_index} report: {report_file_path}")
self.pdf_file_index += 1
exp, hypothesis = extract_hypothesis_and_exp_from_reports(str(report_file_path))
if exp is None:
continue
self.valid_pdf_file_count += 1
exp.based_experiments = [QlibFactorExperiment(sub_tasks=[], hypothesis=hypothesis)] + [
t[0] for t in self.trace.hist if t[1]
]
exp.sub_workspace_list = exp.sub_workspace_list[: FACTOR_FROM_REPORT_PROP_SETTING.max_factors_per_exp]
exp.sub_tasks = exp.sub_tasks[: FACTOR_FROM_REPORT_PROP_SETTING.max_factors_per_exp]
logger.log_object(hypothesis, tag="hypothesis generation")
logger.log_object(exp.sub_tasks, tag="experiment generation")
self.current_loop_hypothesis = hypothesis
self.current_loop_exp = exp
return None
while True:
if FACTOR_FROM_REPORT_PROP_SETTING.is_report_limit_enabled and self.valid_pdf_file_count > 15:
break
report_file_path = self.judge_pdf_data_items[self.pdf_file_index]
logger.info(f"Processing number {self.pdf_file_index} report: {report_file_path}")
self.pdf_file_index += 1
exp, hypothesis = extract_hypothesis_and_exp_from_reports(str(report_file_path))
if exp is None:
continue
self.valid_pdf_file_count += 1
exp.based_experiments = [QlibFactorExperiment(sub_tasks=[], hypothesis=hypothesis)] + [
t[0] for t in self.trace.hist if t[1]
]
exp.sub_workspace_list = exp.sub_workspace_list[: FACTOR_FROM_REPORT_PROP_SETTING.max_factors_per_exp]
exp.sub_tasks = exp.sub_tasks[: FACTOR_FROM_REPORT_PROP_SETTING.max_factors_per_exp]
logger.log_object(hypothesis, tag="hypothesis generation")
logger.log_object(exp.sub_tasks, tag="experiment generation")
self.current_loop_hypothesis = hypothesis
self.current_loop_exp = exp
return None
def propose(self, prev_out: dict[str, Any]):
return self.current_loop_hypothesis
@@ -141,9 +140,8 @@ class FactorReportLoop(FactorRDLoop, metaclass=LoopMeta):
return {"propose": self.current_loop_hypothesis, "exp_gen": self.current_loop_exp}
def coding(self, prev_out: dict[str, Any]):
with logger.tag("d"): # develop
exp = self.coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
logger.log_object(exp.sub_workspace_list, tag="coder result")
exp = self.coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
logger.log_object(exp.sub_workspace_list, tag="coder result")
return exp
+48 -54
View File
@@ -31,70 +31,66 @@ class QuantRDLoop(RDLoop):
)
def __init__(self, PROP_SETTING: BasePropSetting):
with logger.tag("init"):
scen: Scenario = import_class(PROP_SETTING.scen)()
logger.log_object(scen, tag="scenario")
scen: Scenario = import_class(PROP_SETTING.scen)()
logger.log_object(scen, tag="scenario")
self.hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.quant_hypothesis_gen)(scen)
logger.log_object(self.hypothesis_gen, tag="quant hypothesis generator")
self.hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.quant_hypothesis_gen)(scen)
logger.log_object(self.hypothesis_gen, tag="quant hypothesis generator")
self.factor_hypothesis2experiment: Hypothesis2Experiment = import_class(
PROP_SETTING.factor_hypothesis2experiment
)()
logger.log_object(self.factor_hypothesis2experiment, tag="factor hypothesis2experiment")
self.model_hypothesis2experiment: Hypothesis2Experiment = import_class(
PROP_SETTING.model_hypothesis2experiment
)()
logger.log_object(self.model_hypothesis2experiment, tag="model hypothesis2experiment")
self.factor_hypothesis2experiment: Hypothesis2Experiment = import_class(
PROP_SETTING.factor_hypothesis2experiment
)()
logger.log_object(self.factor_hypothesis2experiment, tag="factor hypothesis2experiment")
self.model_hypothesis2experiment: Hypothesis2Experiment = import_class(
PROP_SETTING.model_hypothesis2experiment
)()
logger.log_object(self.model_hypothesis2experiment, tag="model hypothesis2experiment")
self.factor_coder: Developer = import_class(PROP_SETTING.factor_coder)(scen)
logger.log_object(self.factor_coder, tag="factor coder")
self.model_coder: Developer = import_class(PROP_SETTING.model_coder)(scen)
logger.log_object(self.model_coder, tag="model coder")
self.factor_coder: Developer = import_class(PROP_SETTING.factor_coder)(scen)
logger.log_object(self.factor_coder, tag="factor coder")
self.model_coder: Developer = import_class(PROP_SETTING.model_coder)(scen)
logger.log_object(self.model_coder, tag="model coder")
self.factor_runner: Developer = import_class(PROP_SETTING.factor_runner)(scen)
logger.log_object(self.factor_runner, tag="factor runner")
self.model_runner: Developer = import_class(PROP_SETTING.model_runner)(scen)
logger.log_object(self.model_runner, tag="model runner")
self.factor_runner: Developer = import_class(PROP_SETTING.factor_runner)(scen)
logger.log_object(self.factor_runner, tag="factor runner")
self.model_runner: Developer = import_class(PROP_SETTING.model_runner)(scen)
logger.log_object(self.model_runner, tag="model runner")
self.factor_summarizer: Experiment2Feedback = import_class(PROP_SETTING.factor_summarizer)(scen)
logger.log_object(self.factor_summarizer, tag="factor summarizer")
self.model_summarizer: Experiment2Feedback = import_class(PROP_SETTING.model_summarizer)(scen)
logger.log_object(self.model_summarizer, tag="model summarizer")
self.factor_summarizer: Experiment2Feedback = import_class(PROP_SETTING.factor_summarizer)(scen)
logger.log_object(self.factor_summarizer, tag="factor summarizer")
self.model_summarizer: Experiment2Feedback = import_class(PROP_SETTING.model_summarizer)(scen)
logger.log_object(self.model_summarizer, tag="model summarizer")
self.trace = QuantTrace(scen=scen)
super(RDLoop, self).__init__()
self.trace = QuantTrace(scen=scen)
super(RDLoop, self).__init__()
def direct_exp_gen(self, prev_out: dict[str, Any]):
with logger.tag("r"): # research
hypo = self._propose()
assert hypo.action in ["factor", "model"]
if hypo.action == "factor":
exp = self.factor_hypothesis2experiment.convert(hypo, self.trace)
else:
exp = self.model_hypothesis2experiment.convert(hypo, self.trace)
logger.log_object(exp.sub_tasks, tag="experiment generation")
hypo = self._propose()
assert hypo.action in ["factor", "model"]
if hypo.action == "factor":
exp = self.factor_hypothesis2experiment.convert(hypo, self.trace)
else:
exp = self.model_hypothesis2experiment.convert(hypo, self.trace)
logger.log_object(exp.sub_tasks, tag="experiment generation")
return {"propose": hypo, "exp_gen": exp}
def coding(self, prev_out: dict[str, Any]):
with logger.tag("d"): # development
if prev_out["direct_exp_gen"]["propose"].action == "factor":
exp = self.factor_coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
elif prev_out["direct_exp_gen"]["propose"].action == "model":
exp = self.model_coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
logger.log_object(exp, tag="coder result")
if prev_out["direct_exp_gen"]["propose"].action == "factor":
exp = self.factor_coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
elif prev_out["direct_exp_gen"]["propose"].action == "model":
exp = self.model_coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
logger.log_object(exp, tag="coder result")
return exp
def running(self, prev_out: dict[str, Any]):
with logger.tag("ef"):
if prev_out["direct_exp_gen"]["propose"].action == "factor":
exp = self.factor_runner.develop(prev_out["coding"])
if exp is None:
logger.error(f"Factor extraction failed.")
raise FactorEmptyError("Factor extraction failed.")
elif prev_out["direct_exp_gen"]["propose"].action == "model":
exp = self.model_runner.develop(prev_out["coding"])
logger.log_object(exp, tag="runner result")
if prev_out["direct_exp_gen"]["propose"].action == "factor":
exp = self.factor_runner.develop(prev_out["coding"])
if exp is None:
logger.error(f"Factor extraction failed.")
raise FactorEmptyError("Factor extraction failed.")
elif prev_out["direct_exp_gen"]["propose"].action == "model":
exp = self.model_runner.develop(prev_out["coding"])
logger.log_object(exp, tag="runner result")
return exp
def feedback(self, prev_out: dict[str, Any]):
@@ -107,16 +103,14 @@ class QuantRDLoop(RDLoop):
reason="",
decision=False,
)
with logger.tag("ef"): # evaluate and feedback
logger.log_object(feedback, tag="feedback")
logger.log_object(feedback, tag="feedback")
self.trace.hist.append((prev_out["direct_exp_gen"]["exp_gen"], feedback))
else:
if prev_out["direct_exp_gen"]["propose"].action == "factor":
feedback = self.factor_summarizer.generate_feedback(prev_out["running"], self.trace)
elif prev_out["direct_exp_gen"]["propose"].action == "model":
feedback = self.model_summarizer.generate_feedback(prev_out["running"], self.trace)
with logger.tag("ef"):
logger.log_object(feedback, tag="feedback")
logger.log_object(feedback, tag="feedback")
self.trace.hist.append((prev_out["running"], feedback))
+22 -28
View File
@@ -24,25 +24,24 @@ from rdagent.utils.workflow import LoopBase, LoopMeta
class RDLoop(LoopBase, metaclass=LoopMeta):
def __init__(self, PROP_SETTING: BasePropSetting):
with logger.tag("init"):
scen: Scenario = import_class(PROP_SETTING.scen)()
logger.log_object(scen, tag="scenario")
scen: Scenario = import_class(PROP_SETTING.scen)()
logger.log_object(scen, tag="scenario")
self.hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.hypothesis_gen)(scen)
logger.log_object(self.hypothesis_gen, tag="hypothesis generator")
self.hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.hypothesis_gen)(scen)
logger.log_object(self.hypothesis_gen, tag="hypothesis generator")
self.hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.hypothesis2experiment)()
logger.log_object(self.hypothesis2experiment, tag="hypothesis2experiment")
self.hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.hypothesis2experiment)()
logger.log_object(self.hypothesis2experiment, tag="hypothesis2experiment")
self.coder: Developer = import_class(PROP_SETTING.coder)(scen)
logger.log_object(self.coder, tag="coder")
self.runner: Developer = import_class(PROP_SETTING.runner)(scen)
logger.log_object(self.runner, tag="runner")
self.coder: Developer = import_class(PROP_SETTING.coder)(scen)
logger.log_object(self.coder, tag="coder")
self.runner: Developer = import_class(PROP_SETTING.runner)(scen)
logger.log_object(self.runner, tag="runner")
self.summarizer: Experiment2Feedback = import_class(PROP_SETTING.summarizer)(scen)
logger.log_object(self.summarizer, tag="summarizer")
self.trace = Trace(scen=scen)
super().__init__()
self.summarizer: Experiment2Feedback = import_class(PROP_SETTING.summarizer)(scen)
logger.log_object(self.summarizer, tag="summarizer")
self.trace = Trace(scen=scen)
super().__init__()
# excluded steps
def _propose(self):
@@ -57,21 +56,18 @@ class RDLoop(LoopBase, metaclass=LoopMeta):
# included steps
def direct_exp_gen(self, prev_out: dict[str, Any]):
with logger.tag("r"): # research
hypo = self._propose()
exp = self._exp_gen(hypo)
hypo = self._propose()
exp = self._exp_gen(hypo)
return {"propose": hypo, "exp_gen": exp}
def coding(self, prev_out: dict[str, Any]):
with logger.tag("d"): # develop
exp = self.coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
logger.log_object(exp.sub_workspace_list, tag="coder result")
exp = self.coder.develop(prev_out["direct_exp_gen"]["exp_gen"])
logger.log_object(exp.sub_workspace_list, tag="coder result")
return exp
def running(self, prev_out: dict[str, Any]):
with logger.tag("ef"): # evaluate and feedback
exp = self.runner.develop(prev_out["coding"])
logger.log_object(exp, tag="runner result")
exp = self.runner.develop(prev_out["coding"])
logger.log_object(exp, tag="runner result")
return exp
def feedback(self, prev_out: dict[str, Any]):
@@ -84,11 +80,9 @@ class RDLoop(LoopBase, metaclass=LoopMeta):
reason="",
decision=False,
)
with logger.tag("ef"): # evaluate and feedback
logger.log_object(feedback, tag="feedback")
logger.log_object(feedback, tag="feedback")
self.trace.hist.append((prev_out["direct_exp_gen"]["exp_gen"], feedback))
else:
feedback = self.summarizer.generate_feedback(prev_out["running"], self.trace)
with logger.tag("ef"): # evaluate and feedback
logger.log_object(feedback, tag="feedback")
logger.log_object(feedback, tag="feedback")
self.trace.hist.append((prev_out["running"], feedback))
+60 -87
View File
@@ -111,9 +111,6 @@ if "current_tags" not in state:
if "lround" not in state:
state.lround = 0 # RD Loop Round
if "times" not in state:
state.times = defaultdict(lambda: defaultdict(list))
if "erounds" not in state:
state.erounds = defaultdict(int) # Evolving Rounds in each RD Loop
@@ -140,7 +137,7 @@ if "alpha158_metrics" not in state:
def should_display(msg: Message):
for t in state.excluded_tags:
for t in state.excluded_tags + ["debug_tpl", "debug_llm"]:
if t in msg.tag.split("."):
return False
@@ -155,17 +152,24 @@ def get_msgs_until(end_func: Callable[[Message], bool] = lambda _: True):
while True:
try:
msg = next(state.fs)
# new scenario gen this tags, old version UI not have these tags.
msg.tag = re.sub(r"\.evo_loop_\d+", "", msg.tag)
msg.tag = re.sub(r"Loop_\d+\.[^.]+", "", msg.tag)
msg.tag = re.sub(r"\.\.", ".", msg.tag)
msg.tag = msg.tag.strip(".")
if should_display(msg):
tags = msg.tag.split(".")
if "r" not in state.current_tags and "r" in tags:
if "hypothesis generation" in msg.tag:
state.lround += 1
# new scenario gen this tags, old version UI not have these tags.
msg.tag = re.sub(r"\.evo_loop_\d+", "", msg.tag)
msg.tag = re.sub(r"Loop_\d+\.[^.]+", "", msg.tag)
msg.tag = re.sub(r"\.\.", ".", msg.tag)
# remove old redundant tags
msg.tag = re.sub(r"init\.", "", msg.tag)
msg.tag = re.sub(r"r\.", "", msg.tag)
msg.tag = re.sub(r"d\.", "", msg.tag)
msg.tag = re.sub(r"ef\.", "", msg.tag)
msg.tag = msg.tag.strip(".")
if "evolving code" not in state.current_tags and "evolving code" in tags:
state.erounds[state.lround] += 1
@@ -173,7 +177,7 @@ def get_msgs_until(end_func: Callable[[Message], bool] = lambda _: True):
state.last_msg = msg
# Update Summary Info
if "model runner result" in tags or "factor runner result" in tags or "runner result" in tags:
if "runner result" in tags:
# factor baseline exp metrics
if (
isinstance(state.scenario, (QlibFactorScenario, QlibQuantScenario))
@@ -234,37 +238,26 @@ def get_msgs_until(end_func: Callable[[Message], bool] = lambda _: True):
state.all_metric_series.append(sms_all)
elif "hypothesis generation" in tags:
state.hypotheses[state.lround] = msg.content
elif "ef" in tags and "feedback" in tags:
elif "evolving code" in tags:
msg.content = [i for i in msg.content if i]
elif "evolving feedback" in tags:
total_len = len(msg.content)
none_num = total_len - len(msg.content)
right_num = 0
for wsf in msg.content:
if wsf.final_decision:
right_num += 1
wrong_num = len(msg.content) - right_num
state.e_decisions[state.lround][state.erounds[state.lround]] = (
right_num,
wrong_num,
none_num,
)
elif "feedback" in tags and isinstance(msg.content, HypothesisFeedback):
state.h_decisions[state.lround] = msg.content.decision
elif "d" in tags:
if "evolving code" in tags:
msg.content = [i for i in msg.content if i]
if "evolving feedback" in tags:
total_len = len(msg.content)
none_num = total_len - len(msg.content)
right_num = 0
for wsf in msg.content:
if wsf.final_decision:
right_num += 1
wrong_num = len(msg.content) - right_num
state.e_decisions[state.lround][state.erounds[state.lround]] = (
right_num,
wrong_num,
none_num,
)
state.msgs[state.lround][msg.tag].append(msg)
# Update Times
if "init" in tags:
state.times[state.lround]["init"].append(msg.timestamp)
if "r" in tags:
state.times[state.lround]["r"].append(msg.timestamp)
if "d" in tags:
state.times[state.lround]["d"].append(msg.timestamp)
if "ef" in tags:
state.times[state.lround]["ef"].append(msg.timestamp)
# Stop Getting Logs
if end_func(msg):
break
@@ -305,7 +298,6 @@ def refresh(same_trace: bool = False):
state.last_msg = None
state.current_tags = []
state.alpha158_metrics = None
state.times = defaultdict(lambda: defaultdict(list))
def evolving_feedback_window(wsf: FactorSingleFeedback | ModelSingleFeedback):
@@ -471,7 +463,9 @@ def summary_window():
df = pd.DataFrame(state.metric_series)
if show_true_only and len(state.hypotheses) >= len(state.metric_series):
if state.alpha158_metrics is not None:
selected = ["alpha158"] + [i for i in df.index if state.h_decisions[int(i[6:])]]
selected = ["alpha158"] + [
i for i in df.index if i == "Baseline" or state.h_decisions[int(i[6:])]
]
else:
selected = [i for i in df.index if i == "Baseline" or state.h_decisions[int(i[6:])]]
df = df.loc[selected]
@@ -488,9 +482,9 @@ def summary_window():
elif isinstance(state.scenario, GeneralModelScenario):
with st.container(border=True):
st.subheader("Summary📊", divider="rainbow", anchor="_summary")
if len(state.msgs[state.lround]["d.evolving code"]) > 0:
if len(state.msgs[state.lround]["evolving code"]) > 0:
# pass
ws: list[FactorFBWorkspace | ModelFBWorkspace] = state.msgs[state.lround]["d.evolving code"][-1].content
ws: list[FactorFBWorkspace | ModelFBWorkspace] = state.msgs[state.lround]["evolving code"][-1].content
# All Tasks
tab_names = [
@@ -498,7 +492,7 @@ def summary_window():
for w in ws
]
for j in range(len(ws)):
if state.msgs[state.lround]["d.evolving feedback"][-1].content[j].final_decision:
if state.msgs[state.lround]["evolving feedback"][-1].content[j].final_decision:
tab_names[j] += "✔️"
else:
tab_names[j] += ""
@@ -512,7 +506,7 @@ def summary_window():
st.code(v, language="python")
# Evolving Feedback
evolving_feedback_window(state.msgs[state.lround]["d.evolving feedback"][-1].content[j])
evolving_feedback_window(state.msgs[state.lround]["evolving feedback"][-1].content[j])
def tabs_hint():
@@ -570,12 +564,12 @@ def research_window():
st.subheader(title, divider="blue", anchor="_research")
if isinstance(state.scenario, SIMILAR_SCENARIOS):
# pdf image
if pim := state.msgs[round]["r.extract_factors_and_implement.load_pdf_screenshot"]:
if pim := state.msgs[round]["extract_factors_and_implement.load_pdf_screenshot"]:
for i in range(min(2, len(pim))):
st.image(pim[i].content, use_container_width=True)
# Hypothesis
if hg := state.msgs[round]["r.hypothesis generation"]:
if hg := state.msgs[round]["hypothesis generation"]:
st.markdown("**Hypothesis💡**") # 🧠
h: Hypothesis = hg[0].content
st.markdown(
@@ -584,25 +578,20 @@ def research_window():
- **Reason**: {h.reason}"""
)
if eg := state.msgs[round]["r.experiment generation"]:
if eg := state.msgs[round]["experiment generation"]:
tasks_window(eg[0].content)
elif isinstance(state.scenario, GeneralModelScenario):
# pdf image
c1, c2 = st.columns([2, 3])
with c1:
if pim := state.msgs[round]["r.pdf_image"]:
if pim := state.msgs[0]["pdf_image"]:
for i in range(len(pim)):
st.image(pim[i].content, use_container_width=True)
# loaded model exp
with c2:
if mem := state.msgs[round]["d.load_experiment"]:
# 'load_experiment' should in 'r' now, but old version trace may in 'd', so we need to check both
# TODO: modify the way to get one message with a specific tag like 'load_experiment' in the future
me: QlibModelExperiment = mem[0].content
tasks_window(me.sub_tasks)
elif mem := state.msgs[round]["r.load_experiment"]:
if mem := state.msgs[0]["load_experiment"]:
me: QlibModelExperiment = mem[0].content
tasks_window(me.sub_tasks)
@@ -649,7 +638,7 @@ def feedback_window():
state.scenario,
(QlibModelScenario, QlibFactorScenario, QlibFactorFromReportScenario, QlibQuantScenario, KGScenario),
):
if fbr := state.msgs[round]["ef.runner result"]:
if fbr := state.msgs[round]["runner result"]:
try:
st.write("workspace")
st.write(fbr[0].content.experiment_workspace.workspace_path)
@@ -659,11 +648,11 @@ def feedback_window():
with st.expander("**Config⚙️**", expanded=True):
st.markdown(state.scenario.experiment_setting, unsafe_allow_html=True)
if fbr := state.msgs[round]["ef.Quantitative Backtesting Chart"]:
if fbr := state.msgs[round]["Quantitative Backtesting Chart"]:
st.markdown("**Returns📈**")
fig = report_figure(fbr[0].content)
st.plotly_chart(fig)
if fb := state.msgs[round]["ef.feedback"]:
if fb := state.msgs[round]["feedback"]:
st.markdown("**Hypothesis Feedback🔍**")
h: HypothesisFeedback = fb[0].content
st.markdown(
@@ -676,7 +665,7 @@ def feedback_window():
)
if isinstance(state.scenario, KGScenario):
if fbe := state.msgs[round]["ef.runner result"]:
if fbe := state.msgs[round]["runner result"]:
submission_path = fbe[0].content.experiment_workspace.workspace_path / "submission.csv"
st.markdown(
f":green[**Exp Workspace**]: {str(fbe[0].content.experiment_workspace.workspace_path.absolute())}"
@@ -723,17 +712,15 @@ def evolving_window():
else:
evolving_round = 1
ws: list[FactorFBWorkspace | ModelFBWorkspace] = state.msgs[round]["d.evolving code"][
evolving_round - 1
].content
ws: list[FactorFBWorkspace | ModelFBWorkspace] = state.msgs[round]["evolving code"][evolving_round - 1].content
# All Tasks
tab_names = [
w.target_task.factor_name if isinstance(w.target_task, FactorTask) else w.target_task.name for w in ws
]
if len(state.msgs[round]["d.evolving feedback"]) >= evolving_round:
if len(state.msgs[round]["evolving feedback"]) >= evolving_round:
for j in range(len(ws)):
if state.msgs[round]["d.evolving feedback"][evolving_round - 1].content[j].final_decision:
if state.msgs[round]["evolving feedback"][evolving_round - 1].content[j].final_decision:
tab_names[j] += "✔️"
else:
tab_names[j] += ""
@@ -749,8 +736,8 @@ def evolving_window():
st.code(v, language="python")
# Evolving Feedback
if len(state.msgs[round]["d.evolving feedback"]) >= evolving_round:
evolving_feedback_window(state.msgs[round]["d.evolving feedback"][evolving_round - 1].content[j])
if len(state.msgs[round]["evolving feedback"]) >= evolving_round:
evolving_feedback_window(state.msgs[round]["evolving feedback"][evolving_round - 1].content[j])
toc = """
@@ -804,12 +791,12 @@ with st.sidebar:
if st.button(":green[Next Loop]", use_container_width=True):
if not state.fs:
refresh()
get_msgs_until(lambda m: "ef.feedback" in m.tag)
get_msgs_until(lambda m: "feedback" in m.tag and "evolving feedback" not in m.tag)
if st.button("Next Step", use_container_width=True):
if not state.fs:
refresh()
get_msgs_until(lambda m: "d.evolving feedback" in m.tag)
get_msgs_until(lambda m: "evolving feedback" in m.tag)
with st.popover(":orange[**Config⚙️**]", use_container_width=True):
st.multiselect("excluded log tags", ["llm_messages"], ["llm_messages"], key="excluded_tags")
@@ -891,18 +878,6 @@ with st.container():
st.markdown(state.scenario.rich_style_description + css, unsafe_allow_html=True)
def show_times(round: int):
for k, v in state.times[round].items():
if len(v) > 1:
diff = v[-1] - v[0]
else:
diff = v[0] - v[0]
total_seconds = diff.seconds
seconds = total_seconds % 60
minutes = total_seconds // 60
st.markdown(f"**:blue[{k}]**: :red[**{minutes}**] minutes :orange[**{seconds}**] seconds")
def analyze_task_completion():
st.header("Task Completion Analysis", divider="orange")
@@ -924,9 +899,9 @@ def analyze_task_completion():
# For each evolving round in this loop
for e_round in range(1, max_evolving_round + 1):
if len(state.msgs[loop_round]["d.evolving feedback"]) >= e_round:
if len(state.msgs[loop_round]["evolving feedback"]) >= e_round:
# Get feedback for this evolving round
feedback = state.msgs[loop_round]["d.evolving feedback"][e_round - 1].content
feedback = state.msgs[loop_round]["evolving feedback"][e_round - 1].content
# Count passed tasks and track their indices
passed_tasks = set()
@@ -944,7 +919,7 @@ def analyze_task_completion():
}
completion_stats[loop_round] = {
"total_tasks": len(state.msgs[loop_round]["d.evolving feedback"][0].content),
"total_tasks": len(state.msgs[loop_round]["evolving feedback"][0].content),
"rounds": tasks_passed_by_round,
"max_round": max_evolving_round,
}
@@ -1147,14 +1122,12 @@ if state.scenario is not None:
else:
round = 1
show_times(round)
rf_c, d_c = st.columns([2, 2])
elif isinstance(state.scenario, GeneralModelScenario):
show_times(round)
rf_c = st.container()
d_c = st.container()
round = 1
round = 0
else:
st.error("Unknown Scenario!")
st.stop()