Skip to content

Commit deeb83d

Browse files
xisen-wpeteryangms
andauthored
refine core to store experiment results and hypothesis feedback (#55)
* Update proposal.py Completed The HypothesisFeedback Class. * refine the core code --------- Co-authored-by: xuyang1 <[email protected]>
1 parent 14de9cf commit deeb83d

File tree

9 files changed

+85
-80
lines changed

9 files changed

+85
-80
lines changed

rdagent/app/qlib_rd_loop/conf.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,22 @@
44
class PropSetting(BaseSettings):
55
""""""
66

7-
scen: str = "rdagent.scenarios.qlib.experiment.factor_experiment.QlibFactorScenario"
8-
hypothesis_gen: str = "rdagent.scenarios.qlib.factor_proposal.QlibFactorHypothesisGen"
9-
hypothesis2experiment: str = "rdagent.scenarios.qlib.factor_proposal.QlibFactorHypothesis2Experiment"
7+
qlib_factor_scen: str = "rdagent.scenarios.qlib.experiment.factor_experiment.QlibFactorScenario"
8+
qlib_factor_hypothesis_gen: str = "rdagent.scenarios.qlib.factor_proposal.QlibFactorHypothesisGen"
9+
qlib_factor_hypothesis2experiment: str = "rdagent.scenarios.qlib.factor_proposal.QlibFactorHypothesis2Experiment"
1010
qlib_factor_coder: str = "rdagent.scenarios.qlib.factor_task_implementation.QlibFactorCoSTEER"
1111
qlib_factor_runner: str = "rdagent.scenarios.qlib.task_generator.data.QlibFactorRunner"
12-
qlib_factor_summarizer: str = "rdagent.scenarios.qlib.task_generator.feedback.QlibFactorExperiment2Feedback"
12+
qlib_factor_summarizer: str = (
13+
"rdagent.scenarios.qlib.task_generator.feedback.QlibFactorHypothesisExperiment2Feedback"
14+
)
15+
16+
# TODO: model part is not finished yet
17+
qlib_model_scen: str = ""
18+
qlib_model_hypothesis_gen: str = ""
19+
qlib_model_hypothesis2experiment: str = ""
20+
qlib_model_coder: str = ""
21+
qlib_model_runner: str = ""
22+
qlib_model_summarizer: str = ""
1323

1424
evolving_n: int = 10
1525

rdagent/app/qlib_rd_loop/factor.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,34 @@
66

77
load_dotenv(override=True)
88

9-
# import_from
109
from rdagent.app.qlib_rd_loop.conf import PROP_SETTING
1110
from rdagent.core.proposal import (
12-
Experiment2Feedback,
1311
Hypothesis2Experiment,
12+
HypothesisExperiment2Feedback,
1413
HypothesisGen,
15-
HypothesisSet,
1614
Trace,
1715
)
1816
from rdagent.core.task_generator import TaskGenerator
1917
from rdagent.core.utils import import_class
2018

21-
scen = import_class(PROP_SETTING.scen)()
19+
scen = import_class(PROP_SETTING.qlib_factor_scen)()
2220

23-
hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.hypothesis_gen)(scen)
21+
hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.qlib_factor_hypothesis_gen)(scen)
2422

25-
hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.hypothesis2experiment)()
23+
hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.qlib_factor_hypothesis2experiment)()
2624

2725
qlib_factor_coder: TaskGenerator = import_class(PROP_SETTING.qlib_factor_coder)(scen)
2826
qlib_factor_runner: TaskGenerator = import_class(PROP_SETTING.qlib_factor_runner)(scen)
2927

30-
qlib_factor_summarizer: Experiment2Feedback = import_class(PROP_SETTING.qlib_factor_summarizer)()
28+
qlib_factor_summarizer: HypothesisExperiment2Feedback = import_class(PROP_SETTING.qlib_factor_summarizer)()
3129

3230

3331
trace = Trace(scen=scen)
34-
hs = HypothesisSet(trace=trace)
3532
for _ in range(PROP_SETTING.evolving_n):
3633
hypothesis = hypothesis_gen.gen(trace)
37-
exp = hypothesis2experiment.convert(hs)
34+
exp = hypothesis2experiment.convert(hypothesis, trace)
3835
exp = qlib_factor_coder.generate(exp)
3936
exp = qlib_factor_runner.generate(exp)
40-
feedback = qlib_factor_summarizer.summarize(exp)
37+
feedback = qlib_factor_summarizer.generateFeedback(exp, hypothesis, trace)
4138

4239
trace.hist.append((hypothesis, exp, feedback))

rdagent/app/qlib_rd_loop/model.py

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,33 @@
44
"""
55

66
# import_from
7-
from rdagent.app.model_proposal.conf import MODEL_PROP_SETTING
87

8+
from rdagent.app.qlib_rd_loop.conf import PROP_SETTING
99
from rdagent.core.proposal import (
10-
Experiment2Feedback,
1110
Hypothesis2Experiment,
12-
HypothesisSet,
11+
HypothesisExperiment2Feedback,
1312
Trace,
1413
)
1514
from rdagent.core.task_generator import TaskGenerator
15+
from rdagent.core.utils import import_class
1616

17-
# load_from_cls_uri
17+
scen = import_class(PROP_SETTING.qlib_model_scen)()
1818

19+
hypothesis_gen = import_class(PROP_SETTING.qlib_model_hypothesis_gen)(scen)
1920

20-
scen = load_from_cls_uri(MODEL_PROP_SETTING.scen)()
21+
hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.qlib_model_hypothesis2experiment)()
2122

22-
hypothesis_gen = load_from_cls_uri(MODEL_PROP_SETTING.hypothesis_gen)(scen)
23+
qlib_model_coder: TaskGenerator = import_class(PROP_SETTING.qlib_model_coder)(scen)
24+
qlib_model_runner: TaskGenerator = import_class(PROP_SETTING.qlib_model_runner)(scen)
2325

24-
hypothesis2task: Hypothesis2Experiment = load_from_cls_uri(MODEL_PROP_SETTING.hypothesis2task)()
26+
qlib_model_summarizer: HypothesisExperiment2Feedback = import_class(PROP_SETTING.qlib_model_hypothesis2experiment)(scen)
2527

26-
task_gen: TaskGenerator = load_from_cls_uri(MODEL_PROP_SETTING.task_gen)(scen) # for implementation
27-
28-
imp2feedback: Experiment2Feedback = load_from_cls_uri(MODEL_PROP_SETTING.imp2feedback)(scen) # for implementation
29-
30-
31-
iter_n = MODEL_PROP_SETTING.iter_n
32-
33-
trace = Trace()
34-
35-
hypothesis_set = HypothesisSet()
36-
for _ in range(iter_n):
28+
trace = Trace(scen=scen)
29+
for _ in range(PROP_SETTING.evolving_n):
3730
hypothesis = hypothesis_gen.gen(trace)
38-
task = hypothesis2task.convert(hypothesis)
39-
imp = task_gen.gen(task)
40-
imp.execute()
41-
feedback = imp2feedback.summarize(imp)
42-
trace.hist.append((hypothesis, feedback))
31+
exp = hypothesis2experiment.convert(hypothesis, trace)
32+
exp = qlib_model_coder.generate(exp)
33+
exp = qlib_model_runner.generate(exp)
34+
feedback = qlib_model_summarizer.generateFeedback(exp, hypothesis, trace)
35+
36+
trace.hist.append((hypothesis, exp, feedback))

rdagent/components/proposal/factor_proposal.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
Hypothesis,
1111
Hypothesis2Experiment,
1212
HypothesisGen,
13-
HypothesisSet,
1413
Scenario,
1514
Trace,
1615
)
@@ -28,12 +27,10 @@ def __init__(self, scen: Scenario):
2827

2928
# The following methods are scenario related so they should be implemented in the subclass
3029
@abstractmethod
31-
def prepare_context(self, trace: Trace) -> Tuple[dict, bool]:
32-
...
30+
def prepare_context(self, trace: Trace) -> Tuple[dict, bool]: ...
3331

3432
@abstractmethod
35-
def convert_response(self, response: str) -> FactorHypothesis:
36-
...
33+
def convert_response(self, response: str) -> FactorHypothesis: ...
3734

3835
def gen(self, trace: Trace) -> FactorHypothesis:
3936
context_dict, json_flag = self.prepare_context(trace)
@@ -67,27 +64,26 @@ def __init__(self) -> None:
6764
super().__init__()
6865

6966
@abstractmethod
70-
def prepare_context(self, hs: HypothesisSet) -> Tuple[dict, bool]:
71-
...
67+
def prepare_context(self, hypothesis: Hypothesis, trace: Trace) -> Tuple[dict, bool]: ...
7268

7369
@abstractmethod
74-
def convert_response(self, response: str) -> FactorExperiment:
75-
...
70+
def convert_response(self, response: str, trace: Trace) -> FactorExperiment: ...
7671

77-
def convert(self, hs: HypothesisSet) -> FactorExperiment:
78-
context, json_flag = self.prepare_context(hs)
72+
def convert(self, hypothesis: Hypothesis, trace: Trace) -> FactorExperiment:
73+
context, json_flag = self.prepare_context(hypothesis, trace)
7974
system_prompt = (
8075
Environment(undefined=StrictUndefined)
8176
.from_string(prompt_dict["factor_hypothesis2experiment"]["system_prompt"])
8277
.render(
83-
scenario=hs.trace.scen.get_scenario_all_desc(),
78+
scenario=trace.scen.get_scenario_all_desc(),
8479
experiment_output_format=context["experiment_output_format"],
8580
)
8681
)
8782
user_prompt = (
8883
Environment(undefined=StrictUndefined)
8984
.from_string(prompt_dict["factor_hypothesis2experiment"]["user_prompt"])
9085
.render(
86+
target_hypothesis=context["target_hypothesis"],
9187
hypothesis_and_feedback=context["hypothesis_and_feedback"],
9288
factor_list=context["factor_list"],
9389
RAG=context["RAG"],
@@ -96,4 +92,4 @@ def convert(self, hs: HypothesisSet) -> FactorExperiment:
9692

9793
resp = APIBackend().build_messages_and_create_chat_completion(user_prompt, system_prompt, json_mode=json_flag)
9894

99-
return self.convert_response(resp)
95+
return self.convert_response(resp, trace)

rdagent/components/proposal/prompts.yaml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,17 @@ factor_hypothesis2experiment:
2121
The factors are used in certain scenario, the scenario is as follows:
2222
{{ scenario }}
2323
The user will use the factors generated to do some experiments. The user will provide this information to you:
24-
1. The hypothesis generated in the previous steps and their corresponding feedbacks.
25-
2. Former proposed factors on similar hypothesis.
26-
3. Some additional information to help you generate new factors.
24+
1. The target hypothesis you are targeting to generate factors for.
25+
2. The hypothesis generated in the previous steps and their corresponding feedbacks.
26+
3. Former proposed factors on similar hypothesis.
27+
4. Some additional information to help you generate new factors.
2728
Please generate the output following the format below:
2829
{{ experiment_output_format }}
2930
3031
user_prompt: |-
3132
The user has made several hypothesis on this scenario and did several evaluation on them.
33+
The target hypothesis you are targeting to generate factors for is as follows:
34+
{{ target_hypothesis }}
3235
The former hypothesis and the corresponding feedbacks are as follows:
3336
{{ hypothesis_and_feedback }}
3437
The former proposed factors on similar hypothesis are as follows:

rdagent/core/experiment.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ class Experiment(ABC, Generic[ASpecificTask, ASpecificImp]):
122122
def __init__(self, sub_tasks: Sequence[ASpecificTask]) -> None:
123123
self.sub_tasks = sub_tasks
124124
self.sub_implementations: Sequence[ASpecificImp] = [None for _ in self.sub_tasks]
125+
self.based_experiments: Sequence[Experiment] = []
126+
self.result: object = None # The result of the experiment, can be different types in different scenarios.
125127

126128

127129
TaskOrExperiment = TypeVar("TaskOrExperiment", Task, Experiment)

rdagent/core/proposal.py

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,27 @@ class Hypothesis:
2323
def __init__(self, hypothesis: str, reason: str) -> None:
2424
self.hypothesis: str = hypothesis
2525
self.reason: str = reason
26+
27+
def __str__(self) -> str:
28+
return f"""Hypothesis: {self.hypothesis}
29+
Reason: {self.reason}"""
2630

2731
# source: data_ana | model_nan = None
2832

2933

3034
# Origin(path of repo/data/feedback) => view/summarization => generated Hypothesis
3135

3236

33-
class HypothesisFeedback(Feedback): ...
37+
class HypothesisFeedback(Feedback):
38+
def __init__(self, observations: str, hypothesis_evaluation: str, new_hypothesis: str, reason: str, decision: bool):
39+
self.observations = observations
40+
self.hypothesis_evaluation = hypothesis_evaluation
41+
self.new_hypothesis = new_hypothesis
42+
self.reason = reason
43+
self.decision = decision
44+
45+
def __bool__(self):
46+
return self.decision
3447

3548

3649
ASpecificScen = TypeVar("ASpecificScen", bound=Scenario)
@@ -59,19 +72,6 @@ def gen(self, trace: Trace) -> Hypothesis:
5972
"""
6073

6174

62-
class HypothesisSet:
63-
"""
64-
# drop, append
65-
66-
hypothesis_imp: list[float] | None # importance of each hypothesis
67-
true_hypothesis or false_hypothesis
68-
"""
69-
70-
def __init__(self, trace: Trace, hypothesis_list: list[Hypothesis] = []) -> None:
71-
self.hypothesis_list: list[Hypothesis] = hypothesis_list
72-
self.trace: Trace = trace
73-
74-
7575
ASpecificExp = TypeVar("ASpecificExp", bound=Experiment)
7676

7777

@@ -81,21 +81,22 @@ class Hypothesis2Experiment(ABC, Generic[ASpecificExp]):
8181
"""
8282

8383
@abstractmethod
84-
def convert(self, hs: HypothesisSet) -> ASpecificExp:
84+
def convert(self, hypothesis: Hypothesis, trace: Trace) -> ASpecificExp:
8585
"""Connect the idea proposal to implementation"""
8686
...
8787

8888

8989
# Boolean, Reason, Confidence, etc.
9090

91+
9192
class HypothesisExperiment2Feedback:
9293
""" "Generated feedbacks on the hypothesis from **Executed** Implementations of different tasks & their comparisons with previous performances"""
9394

9495
def generateFeedback(self, ti: Experiment, hypothesis: Hypothesis, trace: Trace) -> HypothesisFeedback:
9596
"""
96-
The `ti` should be executed and the results should be included, as well as the comparison between previous results (done by LLM).
97+
The `ti` should be executed and the results should be included, as well as the comparison between previous results (done by LLM).
9798
For example: `mlflow` of Qlib will be included.
9899
"""
99-
return HypothesisFeedback()
100+
raise NotImplementedError("generateFeedback method is not implemented.")
100101

101102
# def generateResultComparison()

rdagent/scenarios/qlib/factor_proposal.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
FactorHypothesisGen,
1313
)
1414
from rdagent.core.prompts import Prompts
15-
from rdagent.core.proposal import HypothesisSet, Scenario, Trace
15+
from rdagent.core.proposal import Hypothesis, Scenario, Trace
1616

1717
prompt_dict = Prompts(file_path=Path(__file__).parent / "prompts.yaml")
1818

@@ -43,36 +43,39 @@ def convert_response(self, response: str) -> FactorHypothesis:
4343

4444

4545
class QlibFactorHypothesis2Experiment(FactorHypothesis2Experiment):
46-
def prepare_context(self, hs: HypothesisSet) -> Tuple[dict | bool]:
47-
scenario = hs.trace.scen.get_scenario_all_desc()
46+
def prepare_context(self, hypothesis: Hypothesis, trace: Trace) -> Tuple[dict | bool]:
47+
scenario = trace.scen.get_scenario_all_desc()
4848
experiment_output_format = prompt_dict["experiment_output_format"]
4949

5050
hypothesis_and_feedback = (
5151
Environment(undefined=StrictUndefined)
5252
.from_string(prompt_dict["hypothesis_and_feedback"])
53-
.render(trace=hs.trace)
53+
.render(trace=trace)
5454
)
5555

56-
experiment_list: List[FactorExperiment] = [t[1] for t in hs.trace.hist]
56+
experiment_list: List[FactorExperiment] = [t[1] for t in trace.hist]
5757

5858
factor_list = []
5959
for experiment in experiment_list:
6060
factor_list.extend(experiment.sub_tasks)
6161

6262
return {
63+
"target_hypothesis": str(hypothesis),
6364
"scenario": scenario,
6465
"hypothesis_and_feedback": hypothesis_and_feedback,
6566
"experiment_output_format": experiment_output_format,
6667
"factor_list": factor_list,
6768
"RAG": ...,
6869
}, True
6970

70-
def convert_response(self, response: str) -> FactorExperiment:
71+
def convert_response(self, response: str, trace: Trace) -> FactorExperiment:
7172
response_dict = json.loads(response)
7273
tasks = []
7374
for factor_name in response_dict:
7475
description = response_dict[factor_name]["description"]
7576
formulation = response_dict[factor_name]["formulation"]
7677
variables = response_dict[factor_name]["variables"]
7778
tasks.append(FactorTask(factor_name, description, formulation, variables))
78-
return FactorExperiment(tasks)
79+
exp = FactorExperiment(tasks)
80+
exp.based_experiments = [t[1] for t in trace.hist if t[2]]
81+
return exp
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
# TODO:
22
# Implement to feedback.
33

4-
from rdagent.core.proposal import Experiment2Feedback
4+
from rdagent.core.proposal import HypothesisExperiment2Feedback
55

66

7-
class QlibFactorExperiment2Feedback(Experiment2Feedback):
8-
...
7+
class QlibFactorHypothesisExperiment2Feedback(HypothesisExperiment2Feedback): ...

0 commit comments

Comments
 (0)