mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-07-27 23:47:46 +00:00
model proposal first version (#61)
* init code * first version of model proposal
This commit is contained in:
@@ -14,12 +14,12 @@ class PropSetting(BaseSettings):
|
||||
)
|
||||
|
||||
# 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 = ""
|
||||
qlib_model_scen: str = "rdagent.scenarios.qlib.experiment.model_experiment.QlibModelScenario"
|
||||
qlib_model_hypothesis_gen: str = "rdagent.scenarios.qlib.model_proposal.QlibModelHypothesisGen"
|
||||
qlib_model_hypothesis2experiment: str = "rdagent.scenarios.qlib.model_proposal.QlibModelHypothesis2Experiment"
|
||||
qlib_model_coder: str = "rdagent.scenarios.qlib.model_task_implementation.QlibModelCoSTEER"
|
||||
qlib_model_runner: str = "rdagent.scenarios.qlib.task_generator.model.QlibModelRunner"
|
||||
qlib_model_summarizer: str = "rdagent.scenarios.qlib.task_generator.feedback.QlibModelHypothesisExperiment2Feedback"
|
||||
|
||||
evolving_n: int = 10
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ TODO: Factor Structure RD-Loop
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from rdagent.core.scenario import Scenario
|
||||
|
||||
load_dotenv(override=True)
|
||||
|
||||
from rdagent.app.qlib_rd_loop.conf import PROP_SETTING
|
||||
@@ -16,7 +18,7 @@ from rdagent.core.proposal import (
|
||||
from rdagent.core.task_generator import TaskGenerator
|
||||
from rdagent.core.utils import import_class
|
||||
|
||||
scen = import_class(PROP_SETTING.qlib_factor_scen)()
|
||||
scen: Scenario = import_class(PROP_SETTING.qlib_factor_scen)()
|
||||
|
||||
hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.qlib_factor_hypothesis_gen)(scen)
|
||||
|
||||
|
||||
@@ -9,21 +9,23 @@ from rdagent.app.qlib_rd_loop.conf import PROP_SETTING
|
||||
from rdagent.core.proposal import (
|
||||
Hypothesis2Experiment,
|
||||
HypothesisExperiment2Feedback,
|
||||
HypothesisGen,
|
||||
Trace,
|
||||
)
|
||||
from rdagent.core.scenario import Scenario
|
||||
from rdagent.core.task_generator import TaskGenerator
|
||||
from rdagent.core.utils import import_class
|
||||
|
||||
scen = import_class(PROP_SETTING.qlib_model_scen)()
|
||||
scen: Scenario = import_class(PROP_SETTING.qlib_model_scen)()
|
||||
|
||||
hypothesis_gen = import_class(PROP_SETTING.qlib_model_hypothesis_gen)(scen)
|
||||
hypothesis_gen: HypothesisGen = import_class(PROP_SETTING.qlib_model_hypothesis_gen)(scen)
|
||||
|
||||
hypothesis2experiment: Hypothesis2Experiment = import_class(PROP_SETTING.qlib_model_hypothesis2experiment)()
|
||||
|
||||
qlib_model_coder: TaskGenerator = import_class(PROP_SETTING.qlib_model_coder)(scen)
|
||||
qlib_model_runner: TaskGenerator = import_class(PROP_SETTING.qlib_model_runner)(scen)
|
||||
|
||||
qlib_model_summarizer: HypothesisExperiment2Feedback = import_class(PROP_SETTING.qlib_model_hypothesis2experiment)(scen)
|
||||
qlib_model_summarizer: HypothesisExperiment2Feedback = import_class(PROP_SETTING.qlib_model_hypothesis2experiment)()
|
||||
|
||||
trace = Trace(scen=scen)
|
||||
for _ in range(PROP_SETTING.evolving_n):
|
||||
|
||||
@@ -15,12 +15,6 @@ from rdagent.utils import get_module_by_module_path
|
||||
|
||||
|
||||
class ModelTask(Task):
|
||||
# TODO: it should change when the Task changes.
|
||||
name: str
|
||||
description: str
|
||||
formulation: str
|
||||
variables: Dict[str, str] # map the variable name to the variable description
|
||||
|
||||
def __init__(
|
||||
self, name: str, description: str, formulation: str, variables: Dict[str, str], model_type: Optional[str] = None
|
||||
) -> None:
|
||||
|
||||
@@ -37,16 +37,18 @@ class FactorHypothesisGen(HypothesisGen):
|
||||
|
||||
system_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["factor_hypothesis_gen"]["system_prompt"])
|
||||
.from_string(prompt_dict["hypothesis_gen"]["system_prompt"])
|
||||
.render(
|
||||
targets="factors",
|
||||
scenario=self.scen.get_scenario_all_desc(),
|
||||
hypothesis_output_format=context_dict["hypothesis_output_format"],
|
||||
)
|
||||
)
|
||||
user_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["factor_hypothesis_gen"]["user_prompt"])
|
||||
.from_string(prompt_dict["hypothesis_gen"]["user_prompt"])
|
||||
.render(
|
||||
targets="factors",
|
||||
hypothesis_and_feedback=context_dict["hypothesis_and_feedback"],
|
||||
RAG=context_dict["RAG"],
|
||||
)
|
||||
@@ -60,8 +62,6 @@ class FactorHypothesisGen(HypothesisGen):
|
||||
|
||||
|
||||
class FactorHypothesis2Experiment(Hypothesis2Experiment[FactorExperiment]):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
@abstractmethod
|
||||
def prepare_context(self, hypothesis: Hypothesis, trace: Trace) -> Tuple[dict, bool]: ...
|
||||
@@ -73,19 +73,21 @@ class FactorHypothesis2Experiment(Hypothesis2Experiment[FactorExperiment]):
|
||||
context, json_flag = self.prepare_context(hypothesis, trace)
|
||||
system_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["factor_hypothesis2experiment"]["system_prompt"])
|
||||
.from_string(prompt_dict["hypothesis2experiment"]["system_prompt"])
|
||||
.render(
|
||||
targets="factors",
|
||||
scenario=trace.scen.get_scenario_all_desc(),
|
||||
experiment_output_format=context["experiment_output_format"],
|
||||
)
|
||||
)
|
||||
user_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["factor_hypothesis2experiment"]["user_prompt"])
|
||||
.from_string(prompt_dict["hypothesis2experiment"]["user_prompt"])
|
||||
.render(
|
||||
targets="factors",
|
||||
target_hypothesis=context["target_hypothesis"],
|
||||
hypothesis_and_feedback=context["hypothesis_and_feedback"],
|
||||
factor_list=context["factor_list"],
|
||||
target_list=context["target_list"],
|
||||
RAG=context["RAG"],
|
||||
)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
from abc import abstractmethod
|
||||
from pathlib import Path
|
||||
from typing import Tuple
|
||||
|
||||
from jinja2 import Environment, StrictUndefined
|
||||
|
||||
from rdagent.components.coder.model_coder.model import ModelExperiment
|
||||
from rdagent.core.prompts import Prompts
|
||||
from rdagent.core.proposal import (
|
||||
Hypothesis,
|
||||
Hypothesis2Experiment,
|
||||
HypothesisGen,
|
||||
Scenario,
|
||||
Trace,
|
||||
)
|
||||
from rdagent.oai.llm_utils import APIBackend
|
||||
|
||||
prompt_dict = Prompts(file_path=Path(__file__).parent / "prompts.yaml")
|
||||
|
||||
ModelHypothesis = Hypothesis
|
||||
|
||||
|
||||
class ModelHypothesisGen(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]: ...
|
||||
|
||||
@abstractmethod
|
||||
def convert_response(self, response: str) -> ModelHypothesis: ...
|
||||
|
||||
def gen(self, trace: Trace) -> ModelHypothesis:
|
||||
context_dict, json_flag = self.prepare_context(trace)
|
||||
|
||||
system_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["hypothesis_gen"]["system_prompt"])
|
||||
.render(
|
||||
targets="factors",
|
||||
scenario=self.scen.get_scenario_all_desc(),
|
||||
hypothesis_output_format=context_dict["hypothesis_output_format"],
|
||||
)
|
||||
)
|
||||
user_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["hypothesis_gen"]["user_prompt"])
|
||||
.render(
|
||||
targets="factors",
|
||||
hypothesis_and_feedback=context_dict["hypothesis_and_feedback"],
|
||||
RAG=context_dict["RAG"],
|
||||
)
|
||||
)
|
||||
|
||||
resp = APIBackend().build_messages_and_create_chat_completion(user_prompt, system_prompt, json_mode=json_flag)
|
||||
|
||||
hypothesis = self.convert_response(resp)
|
||||
|
||||
return hypothesis
|
||||
|
||||
|
||||
class ModelHypothesis2Experiment(Hypothesis2Experiment[ModelExperiment]):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
@abstractmethod
|
||||
def prepare_context(self, hypothesis: Hypothesis, trace: Trace) -> Tuple[dict, bool]: ...
|
||||
|
||||
@abstractmethod
|
||||
def convert_response(self, response: str, trace: Trace) -> ModelExperiment: ...
|
||||
|
||||
def convert(self, hypothesis: Hypothesis, trace: Trace) -> ModelExperiment:
|
||||
context, json_flag = self.prepare_context(hypothesis, trace)
|
||||
system_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["hypothesis2experiment"]["system_prompt"])
|
||||
.render(
|
||||
targets="factors",
|
||||
scenario=trace.scen.get_scenario_all_desc(),
|
||||
experiment_output_format=context["experiment_output_format"],
|
||||
)
|
||||
)
|
||||
user_prompt = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["hypothesis2experiment"]["user_prompt"])
|
||||
.render(
|
||||
targets="factors",
|
||||
target_hypothesis=context["target_hypothesis"],
|
||||
hypothesis_and_feedback=context["hypothesis_and_feedback"],
|
||||
target_list=context["target_list"],
|
||||
RAG=context["RAG"],
|
||||
)
|
||||
)
|
||||
|
||||
resp = APIBackend().build_messages_and_create_chat_completion(user_prompt, system_prompt, json_mode=json_flag)
|
||||
|
||||
return self.convert_response(resp, trace)
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
factor_hypothesis_gen:
|
||||
hypothesis_gen:
|
||||
system_prompt: |-
|
||||
The user is trying to generate new hypothesis on the factors in data-driven research and development.
|
||||
The factors are used in a certain scenario, the scenario is as follows:
|
||||
The user is trying to generate new hypothesis on the {{targets}} in data-driven research and development.
|
||||
The {{targets}} are used in a certain scenario, the scenario is as follows:
|
||||
{{ scenario }}
|
||||
The user has made several hypothesis on this scenario and did several evaluation on them. The user will provide this information to you.
|
||||
To help you generate new hypothesis, the user has prepared some additional information for you. You should use this information to help generate new factors.
|
||||
To help you generate new hypothesis, the user has prepared some additional information for you. You should use this information to help generate new {{targets}}.
|
||||
Please generate the output following the format below:
|
||||
{{ hypothesis_output_format }}
|
||||
user_prompt: |-
|
||||
The user has made several hypothesis on this scenario and did several evaluation on them.
|
||||
The former hypothesis and the corresponding feedbacks are as follows:
|
||||
{{ hypothesis_and_feedback }}
|
||||
To help you generate new factors, we have prepared the following information for you:
|
||||
To help you generate new {{targets}}, we have prepared the following information for you:
|
||||
{{ RAG }}
|
||||
Please generate the new hypothesis based on the information above.
|
||||
|
||||
factor_hypothesis2experiment:
|
||||
hypothesis2experiment:
|
||||
system_prompt: |-
|
||||
The user is trying to generate new factors based on the hypothesis generated in the previous step.
|
||||
The factors are used in certain scenario, the scenario is as follows:
|
||||
The user is trying to generate new {{targets}} based on the hypothesis generated in the previous step.
|
||||
The {{targets}} 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 target hypothesis you are targeting to generate factors for.
|
||||
The user will use the {{targets}} generated to do some experiments. The user will provide this information to you:
|
||||
1. The target hypothesis you are targeting to generate {{targets}} 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.
|
||||
3. Former proposed {{targets}} on similar hypothesis.
|
||||
4. Some additional information to help you generate new {{targets}}.
|
||||
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:
|
||||
The target hypothesis you are targeting to generate {{targets}} 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:
|
||||
{{ factor_list }}
|
||||
To help you generate new factors, we have prepared the following information for you:
|
||||
The former proposed {{targets}} on similar hypothesis are as follows:
|
||||
{{ target_list }}
|
||||
To help you generate new {{targets}}, we have prepared the following information for you:
|
||||
{{ RAG }}
|
||||
Please generate the new factors based on the information above.
|
||||
Please generate the new {{targets}} based on the information above.
|
||||
@@ -92,6 +92,8 @@ qlib_model_interface: |-
|
||||
|
||||
Don't write any try-except block in your python code. The user will catch the exception message and provide the feedback to you. Also, don't write main function in your python code. The user will call the forward method in the model_cls to get the output tensor.
|
||||
|
||||
Please notice that your model should only use current features as input. The user will provide the input tensor to the model's forward function.
|
||||
|
||||
|
||||
qlib_model_output_format: |-
|
||||
Your output should be a tensor with shape (batch_size, 1).
|
||||
|
||||
@@ -5,7 +5,6 @@ from typing import List, Tuple
|
||||
from jinja2 import Environment, StrictUndefined
|
||||
|
||||
from rdagent.components.coder.factor_coder.factor import FactorExperiment, FactorTask
|
||||
from rdagent.components.coder.factor_coder.utils import get_data_folder_intro
|
||||
from rdagent.components.proposal.factor_proposal import (
|
||||
FactorHypothesis,
|
||||
FactorHypothesis2Experiment,
|
||||
@@ -23,7 +22,7 @@ class QlibFactorHypothesisGen(FactorHypothesisGen):
|
||||
def __init__(self, scen: Scenario) -> Tuple[dict, bool]:
|
||||
super().__init__(scen)
|
||||
|
||||
def prepare_context(self, trace: Trace) -> None:
|
||||
def prepare_context(self, trace: Trace) -> Tuple[dict, bool]:
|
||||
hypothesis_feedback = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["hypothesis_and_feedback"])
|
||||
@@ -45,7 +44,7 @@ class QlibFactorHypothesisGen(FactorHypothesisGen):
|
||||
class QlibFactorHypothesis2Experiment(FactorHypothesis2Experiment):
|
||||
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"]
|
||||
experiment_output_format = prompt_dict["factor_experiment_output_format"]
|
||||
|
||||
hypothesis_and_feedback = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
@@ -64,7 +63,7 @@ class QlibFactorHypothesis2Experiment(FactorHypothesis2Experiment):
|
||||
"scenario": scenario,
|
||||
"hypothesis_and_feedback": hypothesis_and_feedback,
|
||||
"experiment_output_format": experiment_output_format,
|
||||
"factor_list": factor_list,
|
||||
"target_list": factor_list,
|
||||
"RAG": ...,
|
||||
}, True
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple
|
||||
|
||||
from jinja2 import Environment, StrictUndefined
|
||||
|
||||
from rdagent.components.coder.model_coder.model import ModelExperiment, ModelTask
|
||||
from rdagent.components.proposal.model_proposal import (
|
||||
ModelHypothesis,
|
||||
ModelHypothesis2Experiment,
|
||||
ModelHypothesisGen,
|
||||
)
|
||||
from rdagent.core.prompts import Prompts
|
||||
from rdagent.core.proposal import Hypothesis, Scenario, Trace
|
||||
|
||||
prompt_dict = Prompts(file_path=Path(__file__).parent / "prompts.yaml")
|
||||
|
||||
QlibModelHypothesis = ModelHypothesis
|
||||
|
||||
|
||||
class QlibModelHypothesisGen(ModelHypothesisGen):
|
||||
def __init__(self, scen: Scenario) -> Tuple[dict, bool]:
|
||||
super().__init__(scen)
|
||||
|
||||
def prepare_context(self, trace: Trace) -> Tuple[dict, bool]:
|
||||
hypothesis_feedback = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["hypothesis_and_feedback"])
|
||||
.render(trace=trace)
|
||||
)
|
||||
context_dict = {
|
||||
"hypothesis_and_feedback": hypothesis_feedback,
|
||||
"RAG": ...,
|
||||
"hypothesis_output_format": prompt_dict["hypothesis_output_format"],
|
||||
}
|
||||
return context_dict, True
|
||||
|
||||
def convert_response(self, response: str) -> ModelHypothesis:
|
||||
response_dict = json.loads(response)
|
||||
hypothesis = QlibModelHypothesis(hypothesis=response_dict["hypothesis"], reason=response_dict["reason"])
|
||||
return hypothesis
|
||||
|
||||
|
||||
class QlibModelHypothesis2Experiment(ModelHypothesis2Experiment):
|
||||
def prepare_context(self, hypothesis: Hypothesis, trace: Trace) -> Tuple[dict, bool]:
|
||||
scenario = trace.scen.get_scenario_all_desc()
|
||||
experiment_output_format = prompt_dict["model_experiment_output_format"]
|
||||
|
||||
hypothesis_and_feedback = (
|
||||
Environment(undefined=StrictUndefined)
|
||||
.from_string(prompt_dict["hypothesis_and_feedback"])
|
||||
.render(trace=trace)
|
||||
)
|
||||
|
||||
experiment_list: List[ModelExperiment] = [t[1] for t in trace.hist]
|
||||
|
||||
model_list = []
|
||||
for experiment in experiment_list:
|
||||
model_list.extend(experiment.sub_tasks)
|
||||
|
||||
return {
|
||||
"target_hypothesis": str(hypothesis),
|
||||
"scenario": scenario,
|
||||
"hypothesis_and_feedback": hypothesis_and_feedback,
|
||||
"experiment_output_format": experiment_output_format,
|
||||
"target_list": model_list,
|
||||
"RAG": ...,
|
||||
}, True
|
||||
|
||||
def convert_response(self, response: str, trace: Trace) -> ModelExperiment:
|
||||
response_dict = json.loads(response)
|
||||
tasks = []
|
||||
for model_name in response_dict:
|
||||
description = response_dict[model_name]["description"]
|
||||
formulation = response_dict[model_name]["formulation"]
|
||||
variables = response_dict[model_name]["variables"]
|
||||
model_type = response_dict[model_name]["model_type"]
|
||||
tasks.append(ModelTask(model_name, description, formulation, variables, model_type))
|
||||
exp = ModelExperiment(tasks)
|
||||
exp.based_experiments = [t[1] for t in trace.hist if t[2]]
|
||||
return exp
|
||||
@@ -1,5 +1,3 @@
|
||||
from rdagent.components.coder.model_coder.one_shot import ModelCodeWriter
|
||||
from rdagent.components.coder.model_coder.CoSTEER import ModelCoSTEER
|
||||
|
||||
|
||||
class QlibModelCodeWriter(ModelCodeWriter):
|
||||
...
|
||||
QlibModelCoSTEER = ModelCoSTEER
|
||||
|
||||
@@ -11,7 +11,7 @@ hypothesis_output_format: |-
|
||||
"reason": "The reason why you generate this hypothesis."
|
||||
}
|
||||
|
||||
experiment_output_format: |-
|
||||
factor_experiment_output_format: |-
|
||||
The output should follow JSON format. The schema is as follows:
|
||||
{
|
||||
"factor name 1": {
|
||||
@@ -32,3 +32,19 @@ experiment_output_format: |-
|
||||
}
|
||||
# Don't add ellipsis (...) or any filler text that might cause JSON parsing errors here!
|
||||
}
|
||||
|
||||
model_experiment_output_format: |-
|
||||
So far please only design one model to test the hypothesis!
|
||||
The output should follow JSON format. The schema is as follows:
|
||||
{
|
||||
"model name 1": {
|
||||
"description": "detailed description of model 1",
|
||||
"formulation": "latex formulation of model 1",
|
||||
"variables": {
|
||||
"variable or function name 1": "description of variable or function 1",
|
||||
"variable or function name 2": "description of variable or function 2"
|
||||
}
|
||||
"model_type": "type of model 1, Tabular or TimesSeries"
|
||||
}
|
||||
# Don't add ellipsis (...) or any filler text that might cause JSON parsing errors here!
|
||||
}
|
||||
@@ -5,3 +5,6 @@ from rdagent.core.proposal import HypothesisExperiment2Feedback
|
||||
|
||||
|
||||
class QlibFactorHypothesisExperiment2Feedback(HypothesisExperiment2Feedback): ...
|
||||
|
||||
|
||||
class QlibModelHypothesisExperiment2Feedback(HypothesisExperiment2Feedback): ...
|
||||
|
||||
@@ -2,7 +2,7 @@ from rdagent.components.coder.model_coder.model import ModelImplementation
|
||||
from rdagent.core.task_generator import TaskGenerator
|
||||
|
||||
|
||||
class QlibModelImplementation(TaskGenerator[ModelImplementation]):
|
||||
class QlibModelRunner(TaskGenerator[ModelImplementation]):
|
||||
"""
|
||||
Docker run
|
||||
Everything in a folder
|
||||
@@ -14,3 +14,6 @@ class QlibModelImplementation(TaskGenerator[ModelImplementation]):
|
||||
- pt_model_uri: hard-code `model.py:Net` in the config
|
||||
- let LLM modify model.py
|
||||
"""
|
||||
|
||||
def generate(self, exp: ModelImplementation) -> ModelImplementation:
|
||||
return exp # TODO IMPLEMENT THIS
|
||||
|
||||
Reference in New Issue
Block a user