mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-07-27 23:47:46 +00:00
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 <xuyang1@microsoft.com>
This commit is contained in:
@@ -4,12 +4,22 @@ from pydantic_settings import BaseSettings
|
||||
class PropSetting(BaseSettings):
|
||||
""""""
|
||||
|
||||
scen: str = "rdagent.scenarios.qlib.experiment.factor_experiment.QlibFactorScenario"
|
||||
hypothesis_gen: str = "rdagent.scenarios.qlib.factor_proposal.QlibFactorHypothesisGen"
|
||||
hypothesis2experiment: str = "rdagent.scenarios.qlib.factor_proposal.QlibFactorHypothesis2Experiment"
|
||||
qlib_factor_scen: str = "rdagent.scenarios.qlib.experiment.factor_experiment.QlibFactorScenario"
|
||||
qlib_factor_hypothesis_gen: str = "rdagent.scenarios.qlib.factor_proposal.QlibFactorHypothesisGen"
|
||||
qlib_factor_hypothesis2experiment: str = "rdagent.scenarios.qlib.factor_proposal.QlibFactorHypothesis2Experiment"
|
||||
qlib_factor_coder: str = "rdagent.scenarios.qlib.factor_task_implementation.QlibFactorCoSTEER"
|
||||
qlib_factor_runner: str = "rdagent.scenarios.qlib.task_generator.data.QlibFactorRunner"
|
||||
qlib_factor_summarizer: str = "rdagent.scenarios.qlib.task_generator.feedback.QlibFactorExperiment2Feedback"
|
||||
qlib_factor_summarizer: str = (
|
||||
"rdagent.scenarios.qlib.task_generator.feedback.QlibFactorHypothesisExperiment2Feedback"
|
||||
)
|
||||
|
||||
# TODO: model part is not finished yet
|
||||
qlib_model_scen: str = ""
|
||||
qlib_model_hypothesis_gen: str = ""
|
||||
qlib_model_hypothesis2experiment: str = ""
|
||||
qlib_model_coder: str = ""
|
||||
qlib_model_runner: str = ""
|
||||
qlib_model_summarizer: str = ""
|
||||
|
||||
evolving_n: int = 10
|
||||
|
||||
|
||||
@@ -6,37 +6,34 @@ from dotenv import load_dotenv
|
||||
|
||||
load_dotenv(override=True)
|
||||
|
||||
# import_from
|
||||
from rdagent.app.qlib_rd_loop.conf import PROP_SETTING
|
||||
from rdagent.core.proposal import (
|
||||
Experiment2Feedback,
|
||||
Hypothesis2Experiment,
|
||||
HypothesisExperiment2Feedback,
|
||||
HypothesisGen,
|
||||
HypothesisSet,
|
||||
Trace,
|
||||
)
|
||||
from rdagent.core.task_generator import TaskGenerator
|
||||
from rdagent.core.utils import import_class
|
||||
|
||||
scen = import_class(PROP_SETTING.scen)()
|
||||
scen = import_class(PROP_SETTING.qlib_factor_scen)()
|
||||
|
||||
hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.hypothesis_gen)(scen)
|
||||
hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.qlib_factor_hypothesis_gen)(scen)
|
||||
|
||||
hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.hypothesis2experiment)()
|
||||
hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.qlib_factor_hypothesis2experiment)()
|
||||
|
||||
qlib_factor_coder: TaskGenerator = import_class(PROP_SETTING.qlib_factor_coder)(scen)
|
||||
qlib_factor_runner: TaskGenerator = import_class(PROP_SETTING.qlib_factor_runner)(scen)
|
||||
|
||||
qlib_factor_summarizer: Experiment2Feedback = import_class(PROP_SETTING.qlib_factor_summarizer)()
|
||||
qlib_factor_summarizer: HypothesisExperiment2Feedback = import_class(PROP_SETTING.qlib_factor_summarizer)()
|
||||
|
||||
|
||||
trace = Trace(scen=scen)
|
||||
hs = HypothesisSet(trace=trace)
|
||||
for _ in range(PROP_SETTING.evolving_n):
|
||||
hypothesis = hypothesis_gen.gen(trace)
|
||||
exp = hypothesis2experiment.convert(hs)
|
||||
exp = hypothesis2experiment.convert(hypothesis, trace)
|
||||
exp = qlib_factor_coder.generate(exp)
|
||||
exp = qlib_factor_runner.generate(exp)
|
||||
feedback = qlib_factor_summarizer.summarize(exp)
|
||||
feedback = qlib_factor_summarizer.generateFeedback(exp, hypothesis, trace)
|
||||
|
||||
trace.hist.append((hypothesis, exp, feedback))
|
||||
|
||||
@@ -4,39 +4,33 @@ TODO: move the following code to a new class: Model_RD_Agent
|
||||
"""
|
||||
|
||||
# import_from
|
||||
from rdagent.app.model_proposal.conf import MODEL_PROP_SETTING
|
||||
|
||||
from rdagent.app.qlib_rd_loop.conf import PROP_SETTING
|
||||
from rdagent.core.proposal import (
|
||||
Experiment2Feedback,
|
||||
Hypothesis2Experiment,
|
||||
HypothesisSet,
|
||||
HypothesisExperiment2Feedback,
|
||||
Trace,
|
||||
)
|
||||
from rdagent.core.task_generator import TaskGenerator
|
||||
from rdagent.core.utils import import_class
|
||||
|
||||
# load_from_cls_uri
|
||||
scen = import_class(PROP_SETTING.qlib_model_scen)()
|
||||
|
||||
hypothesis_gen = import_class(PROP_SETTING.qlib_model_hypothesis_gen)(scen)
|
||||
|
||||
scen = load_from_cls_uri(MODEL_PROP_SETTING.scen)()
|
||||
hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.qlib_model_hypothesis2experiment)()
|
||||
|
||||
hypothesis_gen = load_from_cls_uri(MODEL_PROP_SETTING.hypothesis_gen)(scen)
|
||||
qlib_model_coder: TaskGenerator = import_class(PROP_SETTING.qlib_model_coder)(scen)
|
||||
qlib_model_runner: TaskGenerator = import_class(PROP_SETTING.qlib_model_runner)(scen)
|
||||
|
||||
hypothesis2task: Hypothesis2Experiment = load_from_cls_uri(MODEL_PROP_SETTING.hypothesis2task)()
|
||||
qlib_model_summarizer: HypothesisExperiment2Feedback = import_class(PROP_SETTING.qlib_model_hypothesis2experiment)(scen)
|
||||
|
||||
task_gen: TaskGenerator = load_from_cls_uri(MODEL_PROP_SETTING.task_gen)(scen) # for implementation
|
||||
|
||||
imp2feedback: Experiment2Feedback = load_from_cls_uri(MODEL_PROP_SETTING.imp2feedback)(scen) # for implementation
|
||||
|
||||
|
||||
iter_n = MODEL_PROP_SETTING.iter_n
|
||||
|
||||
trace = Trace()
|
||||
|
||||
hypothesis_set = HypothesisSet()
|
||||
for _ in range(iter_n):
|
||||
trace = Trace(scen=scen)
|
||||
for _ in range(PROP_SETTING.evolving_n):
|
||||
hypothesis = hypothesis_gen.gen(trace)
|
||||
task = hypothesis2task.convert(hypothesis)
|
||||
imp = task_gen.gen(task)
|
||||
imp.execute()
|
||||
feedback = imp2feedback.summarize(imp)
|
||||
trace.hist.append((hypothesis, feedback))
|
||||
exp = hypothesis2experiment.convert(hypothesis, trace)
|
||||
exp = qlib_model_coder.generate(exp)
|
||||
exp = qlib_model_runner.generate(exp)
|
||||
feedback = qlib_model_summarizer.generateFeedback(exp, hypothesis, trace)
|
||||
|
||||
trace.hist.append((hypothesis, exp, feedback))
|
||||
|
||||
@@ -10,7 +10,6 @@ from rdagent.core.proposal import (
|
||||
Hypothesis,
|
||||
Hypothesis2Experiment,
|
||||
HypothesisGen,
|
||||
HypothesisSet,
|
||||
Scenario,
|
||||
Trace,
|
||||
)
|
||||
@@ -28,12 +27,10 @@ class FactorHypothesisGen(HypothesisGen):
|
||||
|
||||
# The following methods are scenario related so they should be implemented in the subclass
|
||||
@abstractmethod
|
||||
def prepare_context(self, trace: Trace) -> Tuple[dict, bool]:
|
||||
...
|
||||
def prepare_context(self, trace: Trace) -> Tuple[dict, bool]: ...
|
||||
|
||||
@abstractmethod
|
||||
def convert_response(self, response: str) -> FactorHypothesis:
|
||||
...
|
||||
def convert_response(self, response: str) -> FactorHypothesis: ...
|
||||
|
||||
def gen(self, trace: Trace) -> FactorHypothesis:
|
||||
context_dict, json_flag = self.prepare_context(trace)
|
||||
@@ -67,20 +64,18 @@ class FactorHypothesis2Experiment(Hypothesis2Experiment[FactorExperiment]):
|
||||
super().__init__()
|
||||
|
||||
@abstractmethod
|
||||
def prepare_context(self, hs: HypothesisSet) -> Tuple[dict, bool]:
|
||||
...
|
||||
def prepare_context(self, hypothesis: Hypothesis, trace: Trace) -> Tuple[dict, bool]: ...
|
||||
|
||||
@abstractmethod
|
||||
def convert_response(self, response: str) -> FactorExperiment:
|
||||
...
|
||||
def convert_response(self, response: str, trace: Trace) -> FactorExperiment: ...
|
||||
|
||||
def convert(self, hs: HypothesisSet) -> FactorExperiment:
|
||||
context, json_flag = self.prepare_context(hs)
|
||||
def convert(self, hypothesis: Hypothesis, trace: Trace) -> FactorExperiment:
|
||||
context, json_flag = self.prepare_context(hypothesis, trace)
|
||||
system_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["factor_hypothesis2experiment"]["system_prompt"])
|
||||
.render(
|
||||
scenario=hs.trace.scen.get_scenario_all_desc(),
|
||||
scenario=trace.scen.get_scenario_all_desc(),
|
||||
experiment_output_format=context["experiment_output_format"],
|
||||
)
|
||||
)
|
||||
@@ -88,6 +83,7 @@ class FactorHypothesis2Experiment(Hypothesis2Experiment[FactorExperiment]):
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["factor_hypothesis2experiment"]["user_prompt"])
|
||||
.render(
|
||||
target_hypothesis=context["target_hypothesis"],
|
||||
hypothesis_and_feedback=context["hypothesis_and_feedback"],
|
||||
factor_list=context["factor_list"],
|
||||
RAG=context["RAG"],
|
||||
@@ -96,4 +92,4 @@ class FactorHypothesis2Experiment(Hypothesis2Experiment[FactorExperiment]):
|
||||
|
||||
resp = APIBackend().build_messages_and_create_chat_completion(user_prompt, system_prompt, json_mode=json_flag)
|
||||
|
||||
return self.convert_response(resp)
|
||||
return self.convert_response(resp, trace)
|
||||
|
||||
@@ -21,14 +21,17 @@ factor_hypothesis2experiment:
|
||||
The factors are used in certain scenario, the scenario is as follows:
|
||||
{{ scenario }}
|
||||
The user will use the factors generated to do some experiments. The user will provide this information to you:
|
||||
1. The hypothesis generated in the previous steps and their corresponding feedbacks.
|
||||
2. Former proposed factors on similar hypothesis.
|
||||
3. Some additional information to help you generate new factors.
|
||||
1. The target hypothesis you are targeting to generate factors for.
|
||||
2. The hypothesis generated in the previous steps and their corresponding feedbacks.
|
||||
3. Former proposed factors on similar hypothesis.
|
||||
4. Some additional information to help you generate new factors.
|
||||
Please generate the output following the format below:
|
||||
{{ experiment_output_format }}
|
||||
|
||||
user_prompt: |-
|
||||
The user has made several hypothesis on this scenario and did several evaluation on them.
|
||||
The target hypothesis you are targeting to generate factors for is as follows:
|
||||
{{ target_hypothesis }}
|
||||
The former hypothesis and the corresponding feedbacks are as follows:
|
||||
{{ hypothesis_and_feedback }}
|
||||
The former proposed factors on similar hypothesis are as follows:
|
||||
|
||||
@@ -122,6 +122,8 @@ class Experiment(ABC, Generic[ASpecificTask, ASpecificImp]):
|
||||
def __init__(self, sub_tasks: Sequence[ASpecificTask]) -> None:
|
||||
self.sub_tasks = sub_tasks
|
||||
self.sub_implementations: Sequence[ASpecificImp] = [None for _ in self.sub_tasks]
|
||||
self.based_experiments: Sequence[Experiment] = []
|
||||
self.result: object = None # The result of the experiment, can be different types in different scenarios.
|
||||
|
||||
|
||||
TaskOrExperiment = TypeVar("TaskOrExperiment", Task, Experiment)
|
||||
|
||||
+18
-17
@@ -23,6 +23,10 @@ class Hypothesis:
|
||||
def __init__(self, hypothesis: str, reason: str) -> None:
|
||||
self.hypothesis: str = hypothesis
|
||||
self.reason: str = reason
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"""Hypothesis: {self.hypothesis}
|
||||
Reason: {self.reason}"""
|
||||
|
||||
# source: data_ana | model_nan = None
|
||||
|
||||
@@ -30,7 +34,16 @@ class Hypothesis:
|
||||
# Origin(path of repo/data/feedback) => view/summarization => generated Hypothesis
|
||||
|
||||
|
||||
class HypothesisFeedback(Feedback): ...
|
||||
class HypothesisFeedback(Feedback):
|
||||
def __init__(self, observations: str, hypothesis_evaluation: str, new_hypothesis: str, reason: str, decision: bool):
|
||||
self.observations = observations
|
||||
self.hypothesis_evaluation = hypothesis_evaluation
|
||||
self.new_hypothesis = new_hypothesis
|
||||
self.reason = reason
|
||||
self.decision = decision
|
||||
|
||||
def __bool__(self):
|
||||
return self.decision
|
||||
|
||||
|
||||
ASpecificScen = TypeVar("ASpecificScen", bound=Scenario)
|
||||
@@ -59,19 +72,6 @@ class HypothesisGen:
|
||||
"""
|
||||
|
||||
|
||||
class HypothesisSet:
|
||||
"""
|
||||
# drop, append
|
||||
|
||||
hypothesis_imp: list[float] | None # importance of each hypothesis
|
||||
true_hypothesis or false_hypothesis
|
||||
"""
|
||||
|
||||
def __init__(self, trace: Trace, hypothesis_list: list[Hypothesis] = []) -> None:
|
||||
self.hypothesis_list: list[Hypothesis] = hypothesis_list
|
||||
self.trace: Trace = trace
|
||||
|
||||
|
||||
ASpecificExp = TypeVar("ASpecificExp", bound=Experiment)
|
||||
|
||||
|
||||
@@ -81,21 +81,22 @@ class Hypothesis2Experiment(ABC, Generic[ASpecificExp]):
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def convert(self, hs: HypothesisSet) -> ASpecificExp:
|
||||
def convert(self, hypothesis: Hypothesis, trace: Trace) -> ASpecificExp:
|
||||
"""Connect the idea proposal to implementation"""
|
||||
...
|
||||
|
||||
|
||||
# Boolean, Reason, Confidence, etc.
|
||||
|
||||
|
||||
class HypothesisExperiment2Feedback:
|
||||
""" "Generated feedbacks on the hypothesis from **Executed** Implementations of different tasks & their comparisons with previous performances"""
|
||||
|
||||
def generateFeedback(self, ti: Experiment, hypothesis: Hypothesis, trace: Trace) -> HypothesisFeedback:
|
||||
"""
|
||||
The `ti` should be executed and the results should be included, as well as the comparison between previous results (done by LLM).
|
||||
The `ti` should be executed and the results should be included, as well as the comparison between previous results (done by LLM).
|
||||
For example: `mlflow` of Qlib will be included.
|
||||
"""
|
||||
return HypothesisFeedback()
|
||||
raise NotImplementedError("generateFeedback method is not implemented.")
|
||||
|
||||
# def generateResultComparison()
|
||||
|
||||
@@ -12,7 +12,7 @@ from rdagent.components.proposal.factor_proposal import (
|
||||
FactorHypothesisGen,
|
||||
)
|
||||
from rdagent.core.prompts import Prompts
|
||||
from rdagent.core.proposal import HypothesisSet, Scenario, Trace
|
||||
from rdagent.core.proposal import Hypothesis, Scenario, Trace
|
||||
|
||||
prompt_dict = Prompts(file_path=Path(__file__).parent / "prompts.yaml")
|
||||
|
||||
@@ -43,23 +43,24 @@ class QlibFactorHypothesisGen(FactorHypothesisGen):
|
||||
|
||||
|
||||
class QlibFactorHypothesis2Experiment(FactorHypothesis2Experiment):
|
||||
def prepare_context(self, hs: HypothesisSet) -> Tuple[dict | bool]:
|
||||
scenario = hs.trace.scen.get_scenario_all_desc()
|
||||
def prepare_context(self, hypothesis: Hypothesis, trace: Trace) -> Tuple[dict | bool]:
|
||||
scenario = trace.scen.get_scenario_all_desc()
|
||||
experiment_output_format = prompt_dict["experiment_output_format"]
|
||||
|
||||
hypothesis_and_feedback = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["hypothesis_and_feedback"])
|
||||
.render(trace=hs.trace)
|
||||
.render(trace=trace)
|
||||
)
|
||||
|
||||
experiment_list: List[FactorExperiment] = [t[1] for t in hs.trace.hist]
|
||||
experiment_list: List[FactorExperiment] = [t[1] for t in trace.hist]
|
||||
|
||||
factor_list = []
|
||||
for experiment in experiment_list:
|
||||
factor_list.extend(experiment.sub_tasks)
|
||||
|
||||
return {
|
||||
"target_hypothesis": str(hypothesis),
|
||||
"scenario": scenario,
|
||||
"hypothesis_and_feedback": hypothesis_and_feedback,
|
||||
"experiment_output_format": experiment_output_format,
|
||||
@@ -67,7 +68,7 @@ class QlibFactorHypothesis2Experiment(FactorHypothesis2Experiment):
|
||||
"RAG": ...,
|
||||
}, True
|
||||
|
||||
def convert_response(self, response: str) -> FactorExperiment:
|
||||
def convert_response(self, response: str, trace: Trace) -> FactorExperiment:
|
||||
response_dict = json.loads(response)
|
||||
tasks = []
|
||||
for factor_name in response_dict:
|
||||
@@ -75,4 +76,6 @@ class QlibFactorHypothesis2Experiment(FactorHypothesis2Experiment):
|
||||
formulation = response_dict[factor_name]["formulation"]
|
||||
variables = response_dict[factor_name]["variables"]
|
||||
tasks.append(FactorTask(factor_name, description, formulation, variables))
|
||||
return FactorExperiment(tasks)
|
||||
exp = FactorExperiment(tasks)
|
||||
exp.based_experiments = [t[1] for t in trace.hist if t[2]]
|
||||
return exp
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
# TODO:
|
||||
# Implement to feedback.
|
||||
|
||||
from rdagent.core.proposal import Experiment2Feedback
|
||||
from rdagent.core.proposal import HypothesisExperiment2Feedback
|
||||
|
||||
|
||||
class QlibFactorExperiment2Feedback(Experiment2Feedback):
|
||||
...
|
||||
class QlibFactorHypothesisExperiment2Feedback(HypothesisExperiment2Feedback): ...
|
||||
|
||||
Reference in New Issue
Block a user