mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-08-07 12:07:43 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d97d84100 | |||
| 9bc525a264 | |||
| 7cb6531c2a | |||
| 44c8af572e | |||
| b53749df7d | |||
| 3a1a3d5f77 |
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
".": "1.3.9"
|
".": "1.4.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,26 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [1.4.0](https://github.com/TPTBusiness/Predix/compare/v1.3.11...v1.4.0) (2026-05-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **optimizer:** add max_positions parameter to Optuna search space ([fdb4be3](https://github.com/TPTBusiness/Predix/commit/fdb4be3b3ebd93325e7821f4251148424184a40d))
|
||||||
|
|
||||||
|
## [1.3.11](https://github.com/TPTBusiness/Predix/compare/v1.3.10...v1.3.11) (2026-05-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **ci:** lazy import logger in predix.py and cli.py to avoid ImportError in test env ([60763e8](https://github.com/TPTBusiness/Predix/commit/60763e8eae34f41865ba8e5e65bdfde13b564b4b))
|
||||||
|
|
||||||
|
## [1.3.10](https://github.com/TPTBusiness/Predix/compare/v1.3.9...v1.3.10) (2026-05-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **security:** replace remaining assert statements with proper error handling ([928533d](https://github.com/TPTBusiness/Predix/commit/928533d9a81bd5062f07458fbf94d3c7fe347775))
|
||||||
|
|
||||||
## [1.3.9](https://github.com/TPTBusiness/Predix/compare/v1.3.8...v1.3.9) (2026-05-01)
|
## [1.3.9](https://github.com/TPTBusiness/Predix/compare/v1.3.8...v1.3.9) (2026-05-01)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,12 @@ load_dotenv(Path(__file__).parent / ".env")
|
|||||||
import typer
|
import typer
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
||||||
from rdagent.utils.env import logger
|
try:
|
||||||
|
from rdagent.utils.env import logger
|
||||||
|
except ImportError:
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
app = typer.Typer(help="Predix - AI Quantitative Trading Agent")
|
app = typer.Typer(help="Predix - AI Quantitative Trading Agent")
|
||||||
console = Console()
|
console = Console()
|
||||||
|
|||||||
+6
-1
@@ -27,7 +27,12 @@ import typer
|
|||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from typing_extensions import Annotated
|
from typing_extensions import Annotated
|
||||||
|
|
||||||
from rdagent.utils.env import logger
|
try:
|
||||||
|
from rdagent.utils.env import logger
|
||||||
|
except ImportError:
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
from rdagent.app.data_science.loop import main as data_science
|
from rdagent.app.data_science.loop import main as data_science
|
||||||
from rdagent.app.finetune.llm.loop import main as llm_finetune
|
from rdagent.app.finetune.llm.loop import main as llm_finetune
|
||||||
|
|||||||
@@ -201,6 +201,5 @@ class DataScienceBasePropSetting(KaggleBasePropSetting):
|
|||||||
DS_RD_SETTING = DataScienceBasePropSetting()
|
DS_RD_SETTING = DataScienceBasePropSetting()
|
||||||
|
|
||||||
# enable_cross_trace_diversity and llm_select_hypothesis should not be true at the same time
|
# enable_cross_trace_diversity and llm_select_hypothesis should not be true at the same time
|
||||||
assert not (
|
if DS_RD_SETTING.enable_cross_trace_diversity and DS_RD_SETTING.llm_select_hypothesis:
|
||||||
DS_RD_SETTING.enable_cross_trace_diversity and DS_RD_SETTING.llm_select_hypothesis
|
raise ValueError("enable_cross_trace_diversity and llm_select_hypothesis cannot be true at the same time")
|
||||||
), "enable_cross_trace_diversity and llm_select_hypothesis cannot be true at the same time"
|
|
||||||
|
|||||||
@@ -58,18 +58,18 @@ def main(
|
|||||||
|
|
||||||
if user_target_scenario:
|
if user_target_scenario:
|
||||||
FT_RD_SETTING.user_target_scenario = user_target_scenario
|
FT_RD_SETTING.user_target_scenario = user_target_scenario
|
||||||
assert (
|
if FT_RD_SETTING.user_target_scenario is not None:
|
||||||
FT_RD_SETTING.user_target_scenario is None
|
raise ValueError("user_target_scenario is not yet supported, please specify via benchmark and benchmark_description")
|
||||||
), "user_target_scenario is not yet supported, please specify via benchmark and benchmark_description"
|
|
||||||
if upper_data_size_limit:
|
if upper_data_size_limit:
|
||||||
FT_RD_SETTING.upper_data_size_limit = upper_data_size_limit
|
FT_RD_SETTING.upper_data_size_limit = upper_data_size_limit
|
||||||
logger.info(f"Set upper_data_size_limit to {FT_RD_SETTING.upper_data_size_limit}")
|
logger.info(f"Set upper_data_size_limit to {FT_RD_SETTING.upper_data_size_limit}")
|
||||||
if benchmark and benchmark_description:
|
if benchmark and benchmark_description:
|
||||||
FT_RD_SETTING.target_benchmark = benchmark
|
FT_RD_SETTING.target_benchmark = benchmark
|
||||||
FT_RD_SETTING.benchmark_description = benchmark_description
|
FT_RD_SETTING.benchmark_description = benchmark_description
|
||||||
assert FT_RD_SETTING.user_target_scenario or (
|
if not (
|
||||||
FT_RD_SETTING.target_benchmark and FT_RD_SETTING.benchmark_description
|
FT_RD_SETTING.user_target_scenario or (FT_RD_SETTING.target_benchmark and FT_RD_SETTING.benchmark_description)
|
||||||
), "Either user_target_scenario or target_benchmark must be specified for LLM fine-tuning."
|
):
|
||||||
|
raise ValueError("Either user_target_scenario or target_benchmark must be specified for LLM fine-tuning.")
|
||||||
|
|
||||||
# Update configuration with provided parameters
|
# Update configuration with provided parameters
|
||||||
if dataset:
|
if dataset:
|
||||||
@@ -82,9 +82,8 @@ def main(
|
|||||||
model_target = FT_RD_SETTING.base_model if FT_RD_SETTING.base_model else "auto selected model"
|
model_target = FT_RD_SETTING.base_model if FT_RD_SETTING.base_model else "auto selected model"
|
||||||
|
|
||||||
# Temporary assertion until auto-selection is implemented
|
# Temporary assertion until auto-selection is implemented
|
||||||
assert (
|
if FT_RD_SETTING.base_model is None:
|
||||||
FT_RD_SETTING.base_model is not None
|
raise ValueError("Base model auto selection not yet supported, please specify via --base-model")
|
||||||
), "Base model auto selection not yet supported, please specify via --base-model"
|
|
||||||
|
|
||||||
logger.info(f"Starting LLM fine-tuning on dataset='{data_set_target}' with model='{model_target}'")
|
logger.info(f"Starting LLM fine-tuning on dataset='{data_set_target}' with model='{model_target}'")
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ class QuantRDLoop(RDLoop):
|
|||||||
while True:
|
while True:
|
||||||
if self.get_unfinished_loop_cnt(self.loop_idx) < RD_AGENT_SETTINGS.get_max_parallel():
|
if self.get_unfinished_loop_cnt(self.loop_idx) < RD_AGENT_SETTINGS.get_max_parallel():
|
||||||
hypo = self._propose()
|
hypo = self._propose()
|
||||||
assert hypo.action in ["factor", "model"]
|
if hypo.action not in ["factor", "model"]:
|
||||||
|
raise ValueError(f"hypo.action must be 'factor' or 'model', got {hypo.action!r}")
|
||||||
if hypo.action == "factor":
|
if hypo.action == "factor":
|
||||||
exp = self.factor_hypothesis2experiment.convert(hypo, self.trace)
|
exp = self.factor_hypothesis2experiment.convert(hypo, self.trace)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -75,8 +75,10 @@ class CoSTEER(Developer[Experiment]):
|
|||||||
|
|
||||||
def _get_last_fb(self) -> CoSTEERMultiFeedback:
|
def _get_last_fb(self) -> CoSTEERMultiFeedback:
|
||||||
fb = self.evolve_agent.evolving_trace[-1].feedback
|
fb = self.evolve_agent.evolving_trace[-1].feedback
|
||||||
assert fb is not None, "feedback is None"
|
if fb is None:
|
||||||
assert isinstance(fb, CoSTEERMultiFeedback), "feedback must be of type CoSTEERMultiFeedback"
|
raise AssertionError("feedback is None")
|
||||||
|
if not isinstance(fb, CoSTEERMultiFeedback):
|
||||||
|
raise TypeError("feedback must be of type CoSTEERMultiFeedback")
|
||||||
return fb
|
return fb
|
||||||
|
|
||||||
def should_use_new_evo(self, base_fb: CoSTEERMultiFeedback | None, new_fb: CoSTEERMultiFeedback) -> bool:
|
def should_use_new_evo(self, base_fb: CoSTEERMultiFeedback | None, new_fb: CoSTEERMultiFeedback) -> bool:
|
||||||
@@ -121,7 +123,8 @@ class CoSTEER(Developer[Experiment]):
|
|||||||
|
|
||||||
for evo_exp in self.evolve_agent.multistep_evolve(evo_exp, self.evaluator):
|
for evo_exp in self.evolve_agent.multistep_evolve(evo_exp, self.evaluator):
|
||||||
iteration_count += 1
|
iteration_count += 1
|
||||||
assert isinstance(evo_exp, Experiment) # multiple inheritance
|
if not isinstance(evo_exp, Experiment):
|
||||||
|
raise TypeError("evo_exp must be an instance of Experiment")
|
||||||
evo_fb = self._get_last_fb()
|
evo_fb = self._get_last_fb()
|
||||||
update_fallback = self.should_use_new_evo(
|
update_fallback = self.should_use_new_evo(
|
||||||
base_fb=fallback_evo_fb,
|
base_fb=fallback_evo_fb,
|
||||||
@@ -154,7 +157,8 @@ class CoSTEER(Developer[Experiment]):
|
|||||||
evo_exp = fallback_evo_exp
|
evo_exp = fallback_evo_exp
|
||||||
evo_exp.recover_ws_ckp()
|
evo_exp.recover_ws_ckp()
|
||||||
evo_fb = fallback_evo_fb
|
evo_fb = fallback_evo_fb
|
||||||
assert evo_fb is not None # multistep_evolve should run at least once
|
if evo_fb is None:
|
||||||
|
raise AssertionError("multistep_evolve should run at least once")
|
||||||
evo_exp = self._exp_postprocess_by_feedback(evo_exp, evo_fb)
|
evo_exp = self._exp_postprocess_by_feedback(evo_exp, evo_fb)
|
||||||
except CoderError as e:
|
except CoderError as e:
|
||||||
e.caused_by_timeout = reached_max_seconds
|
e.caused_by_timeout = reached_max_seconds
|
||||||
@@ -264,9 +268,12 @@ class CoSTEER(Developer[Experiment]):
|
|||||||
- Raise Error if it failed to handle the develop task
|
- Raise Error if it failed to handle the develop task
|
||||||
-
|
-
|
||||||
"""
|
"""
|
||||||
assert isinstance(evo, Experiment)
|
if not isinstance(evo, Experiment):
|
||||||
assert isinstance(feedback, CoSTEERMultiFeedback)
|
raise TypeError("evo must be an instance of Experiment")
|
||||||
assert len(evo.sub_workspace_list) == len(feedback)
|
if not isinstance(feedback, CoSTEERMultiFeedback):
|
||||||
|
raise TypeError("feedback must be an instance of CoSTEERMultiFeedback")
|
||||||
|
if len(evo.sub_workspace_list) != len(feedback):
|
||||||
|
raise ValueError("Length of sub_workspace_list must match length of feedback")
|
||||||
|
|
||||||
# FIXME: when whould the feedback be None?
|
# FIXME: when whould the feedback be None?
|
||||||
failed_feedbacks = [
|
failed_feedbacks = [
|
||||||
|
|||||||
@@ -122,7 +122,8 @@ class MultiProcessEvolvingStrategy(EvolvingStrategy):
|
|||||||
last_feedback = None
|
last_feedback = None
|
||||||
if len(evolving_trace) > 0:
|
if len(evolving_trace) > 0:
|
||||||
last_feedback = evolving_trace[-1].feedback
|
last_feedback = evolving_trace[-1].feedback
|
||||||
assert isinstance(last_feedback, CoSTEERMultiFeedback)
|
if not isinstance(last_feedback, CoSTEERMultiFeedback):
|
||||||
|
raise TypeError("last_feedback must be of type CoSTEERMultiFeedback")
|
||||||
|
|
||||||
# 1.找出需要evolve的task
|
# 1.找出需要evolve的task
|
||||||
to_be_finished_task_index: list[int] = []
|
to_be_finished_task_index: list[int] = []
|
||||||
|
|||||||
@@ -1028,7 +1028,8 @@ class CoSTEERKnowledgeBaseV2(EvolvingKnowledgeBase):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
node_count = len(nodes)
|
node_count = len(nodes)
|
||||||
assert node_count >= 2, "nodes length must >=2"
|
if node_count < 2:
|
||||||
|
raise ValueError("nodes length must >=2")
|
||||||
intersection_node_list = []
|
intersection_node_list = []
|
||||||
if output_intersection_origin:
|
if output_intersection_origin:
|
||||||
origin_list = []
|
origin_list = []
|
||||||
|
|||||||
@@ -58,10 +58,12 @@ class ModelCodeEvaluator(CoSTEEREvaluator):
|
|||||||
model_execution_feedback: str = "",
|
model_execution_feedback: str = "",
|
||||||
model_value_feedback: str = "",
|
model_value_feedback: str = "",
|
||||||
):
|
):
|
||||||
assert isinstance(target_task, ModelTask)
|
if not isinstance(target_task, ModelTask):
|
||||||
assert isinstance(implementation, ModelFBWorkspace)
|
raise TypeError("target_task must be of type ModelTask")
|
||||||
if gt_implementation is not None:
|
if not isinstance(implementation, ModelFBWorkspace):
|
||||||
assert isinstance(gt_implementation, ModelFBWorkspace)
|
raise TypeError("implementation must be of type ModelFBWorkspace")
|
||||||
|
if gt_implementation is not None and not isinstance(gt_implementation, ModelFBWorkspace):
|
||||||
|
raise TypeError("gt_implementation must be of type ModelFBWorkspace")
|
||||||
|
|
||||||
model_task_information = target_task.get_task_information()
|
model_task_information = target_task.get_task_information()
|
||||||
code = implementation.all_codes
|
code = implementation.all_codes
|
||||||
@@ -113,10 +115,12 @@ class ModelFinalEvaluator(CoSTEEREvaluator):
|
|||||||
model_value_feedback: str,
|
model_value_feedback: str,
|
||||||
model_code_feedback: str,
|
model_code_feedback: str,
|
||||||
):
|
):
|
||||||
assert isinstance(target_task, ModelTask)
|
if not isinstance(target_task, ModelTask):
|
||||||
assert isinstance(implementation, ModelFBWorkspace)
|
raise TypeError("target_task must be of type ModelTask")
|
||||||
if gt_implementation is not None:
|
if not isinstance(implementation, ModelFBWorkspace):
|
||||||
assert isinstance(gt_implementation, ModelFBWorkspace)
|
raise TypeError("implementation must be of type ModelFBWorkspace")
|
||||||
|
if gt_implementation is not None and not isinstance(gt_implementation, ModelFBWorkspace):
|
||||||
|
raise TypeError("gt_implementation must be of type ModelFBWorkspace")
|
||||||
|
|
||||||
system_prompt = T(".prompts:evaluator_final_feedback.system").r(
|
system_prompt = T(".prompts:evaluator_final_feedback.system").r(
|
||||||
scenario=(
|
scenario=(
|
||||||
|
|||||||
@@ -292,6 +292,7 @@ class OptunaOptimizer:
|
|||||||
"volatility_lookback": trial.suggest_int("volatility_lookback", 5, 500, step=5),
|
"volatility_lookback": trial.suggest_int("volatility_lookback", 5, 500, step=5),
|
||||||
"signal_bias": trial.suggest_float("signal_bias", -1.0, 1.0, step=0.05),
|
"signal_bias": trial.suggest_float("signal_bias", -1.0, 1.0, step=0.05),
|
||||||
"max_hold_bars": trial.suggest_int("max_hold_bars", 5, 1000, step=5),
|
"max_hold_bars": trial.suggest_int("max_hold_bars", 5, 1000, step=5),
|
||||||
|
"max_positions": trial.suggest_int("max_positions", 1, 5, step=1),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parameters that are allowed to be negative (not clamped to 0).
|
# Parameters that are allowed to be negative (not clamped to 0).
|
||||||
@@ -308,6 +309,7 @@ class OptunaOptimizer:
|
|||||||
"volatility_lookback": 1.0,
|
"volatility_lookback": 1.0,
|
||||||
"signal_bias": -1.0,
|
"signal_bias": -1.0,
|
||||||
"max_hold_bars": 1.0,
|
"max_hold_bars": 1.0,
|
||||||
|
"max_positions": 1.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _suggest_bounded(
|
def _suggest_bounded(
|
||||||
@@ -357,6 +359,7 @@ class OptunaOptimizer:
|
|||||||
"volatility_lookback": (center.get("volatility_lookback", 100), 30),
|
"volatility_lookback": (center.get("volatility_lookback", 100), 30),
|
||||||
"signal_bias": (center.get("signal_bias", 0.0), 0.2),
|
"signal_bias": (center.get("signal_bias", 0.0), 0.2),
|
||||||
"max_hold_bars": (center.get("max_hold_bars", 100), 50),
|
"max_hold_bars": (center.get("max_hold_bars", 100), 50),
|
||||||
|
"max_positions": (center.get("max_positions", 1), 2),
|
||||||
}
|
}
|
||||||
return {key: self._suggest_bounded(trial, key, c, hw) for key, (c, hw) in ranges.items()}
|
return {key: self._suggest_bounded(trial, key, c, hw) for key, (c, hw) in ranges.items()}
|
||||||
|
|
||||||
@@ -388,6 +391,7 @@ class OptunaOptimizer:
|
|||||||
"volatility_lookback": (center.get("volatility_lookback", 100), 10),
|
"volatility_lookback": (center.get("volatility_lookback", 100), 10),
|
||||||
"signal_bias": (center.get("signal_bias", 0.0), 0.07),
|
"signal_bias": (center.get("signal_bias", 0.0), 0.07),
|
||||||
"max_hold_bars": (center.get("max_hold_bars", 100), 17),
|
"max_hold_bars": (center.get("max_hold_bars", 100), 17),
|
||||||
|
"max_positions": (center.get("max_positions", 1), 1),
|
||||||
}
|
}
|
||||||
return {key: self._suggest_bounded(trial, key, c, hw) for key, (c, hw) in ranges.items()}
|
return {key: self._suggest_bounded(trial, key, c, hw) for key, (c, hw) in ranges.items()}
|
||||||
|
|
||||||
@@ -467,6 +471,9 @@ class OptunaOptimizer:
|
|||||||
|
|
||||||
# Max holding periods (in bars)
|
# Max holding periods (in bars)
|
||||||
"max_hold_bars": trial.suggest_int("max_hold_bars", 10, 500, step=10),
|
"max_hold_bars": trial.suggest_int("max_hold_bars", 10, 500, step=10),
|
||||||
|
|
||||||
|
# Max concurrent positions (1 = no pyramiding, 2-5 = scale-in)
|
||||||
|
"max_positions": trial.suggest_int("max_positions", 1, 5, step=1),
|
||||||
}
|
}
|
||||||
|
|
||||||
return params
|
return params
|
||||||
@@ -597,6 +604,13 @@ class OptunaOptimizer:
|
|||||||
if signal_bias != 0.0:
|
if signal_bias != 0.0:
|
||||||
signal = (signal.astype(float) + signal_bias).round().astype(int).clip(-1, 1)
|
signal = (signal.astype(float) + signal_bias).round().astype(int).clip(-1, 1)
|
||||||
|
|
||||||
|
# Apply max_positions: scale signal by position_size_pct and cap exposure
|
||||||
|
max_positions = int(params.get("max_positions", 1))
|
||||||
|
position_size_pct = float(params.get("position_size_pct", 1.0))
|
||||||
|
# Each "position" is position_size_pct of equity; total exposure capped at max_positions × size
|
||||||
|
effective_size = min(position_size_pct * max_positions, 1.0)
|
||||||
|
signal = (signal.astype(float) * effective_size).clip(-1.0, 1.0)
|
||||||
|
|
||||||
# Build a synthetic close from the factor-mean so we can route
|
# Build a synthetic close from the factor-mean so we can route
|
||||||
# through the same unified engine as every other backtest path.
|
# through the same unified engine as every other backtest path.
|
||||||
# Backtest formulas must match the orchestrator's real-OHLCV path.
|
# Backtest formulas must match the orchestrator's real-OHLCV path.
|
||||||
|
|||||||
@@ -85,13 +85,16 @@ def load_and_process_one_pdf_by_azure_document_intelligence(
|
|||||||
|
|
||||||
|
|
||||||
def load_and_process_pdfs_by_azure_document_intelligence(path: Path) -> dict[str, str]:
|
def load_and_process_pdfs_by_azure_document_intelligence(path: Path) -> dict[str, str]:
|
||||||
assert RD_AGENT_SETTINGS.azure_document_intelligence_key is not None
|
if RD_AGENT_SETTINGS.azure_document_intelligence_key is None:
|
||||||
assert RD_AGENT_SETTINGS.azure_document_intelligence_endpoint is not None
|
raise AssertionError("azure_document_intelligence_key must be set")
|
||||||
|
if RD_AGENT_SETTINGS.azure_document_intelligence_endpoint is None:
|
||||||
|
raise AssertionError("azure_document_intelligence_endpoint must be set")
|
||||||
|
|
||||||
content_dict = {}
|
content_dict = {}
|
||||||
ab_path = path.resolve()
|
ab_path = path.resolve()
|
||||||
if ab_path.is_file():
|
if ab_path.is_file():
|
||||||
assert ".pdf" in ab_path.suffixes, "The file must be a PDF file."
|
if ".pdf" not in ab_path.suffixes:
|
||||||
|
raise ValueError("The file must be a PDF file.")
|
||||||
proc = load_and_process_one_pdf_by_azure_document_intelligence
|
proc = load_and_process_one_pdf_by_azure_document_intelligence
|
||||||
content_dict[str(ab_path)] = proc(
|
content_dict[str(ab_path)] = proc(
|
||||||
ab_path,
|
ab_path,
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ class ModelWsLoader(WsLoader[ModelTask, ModelFBWorkspace]):
|
|||||||
self.path = Path(path)
|
self.path = Path(path)
|
||||||
|
|
||||||
def load(self, task: ModelTask) -> ModelFBWorkspace:
|
def load(self, task: ModelTask) -> ModelFBWorkspace:
|
||||||
assert task.name is not None
|
if task.name is None:
|
||||||
|
raise AssertionError("task.name should not be None")
|
||||||
mti = ModelFBWorkspace(task)
|
mti = ModelFBWorkspace(task)
|
||||||
mti.prepare()
|
mti.prepare()
|
||||||
with open(self.path / f"{task.name}.py", "r") as f:
|
with open(self.path / f"{task.name}.py", "r") as f:
|
||||||
|
|||||||
@@ -541,7 +541,8 @@ class APIBackend(ABC):
|
|||||||
**kwargs,
|
**kwargs,
|
||||||
) -> str | list[list[float]]:
|
) -> str | list[list[float]]:
|
||||||
"""This function to share operation between embedding and chat completion"""
|
"""This function to share operation between embedding and chat completion"""
|
||||||
assert not (chat_completion and embedding), "chat_completion and embedding cannot be True at the same time"
|
if chat_completion and embedding:
|
||||||
|
raise ValueError("chat_completion and embedding cannot be True at the same time")
|
||||||
max_retry = LLM_SETTINGS.max_retry if LLM_SETTINGS.max_retry is not None else max_retry
|
max_retry = LLM_SETTINGS.max_retry if LLM_SETTINGS.max_retry is not None else max_retry
|
||||||
timeout_count = 0
|
timeout_count = 0
|
||||||
violation_count = 0
|
violation_count = 0
|
||||||
|
|||||||
@@ -268,7 +268,8 @@ class JsonReducer(DataReducer):
|
|||||||
parent[key] = sampled # type: ignore # parent 是 list,key 是 index, list.__setitem__(key, sampled)
|
parent[key] = sampled # type: ignore # parent 是 list,key 是 index, list.__setitem__(key, sampled)
|
||||||
self.sampled_files.extend([self.extract_filename(i) for i in sampled])
|
self.sampled_files.extend([self.extract_filename(i) for i in sampled])
|
||||||
break
|
break
|
||||||
assert len(self.sampled_files) > 0
|
if len(self.sampled_files) <= 0:
|
||||||
|
raise AssertionError("sampled_files must contain at least one file")
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def _find_all_lists(
|
def _find_all_lists(
|
||||||
|
|||||||
+14
-11
@@ -56,14 +56,17 @@ sparse.save_npz(public / "test" / "X.npz", X_test)
|
|||||||
sparse.save_npz(public / "train" / "X.npz", X_train)
|
sparse.save_npz(public / "train" / "X.npz", X_train)
|
||||||
df_train.to_csv(public / "train" / "ARF_12h.csv", index=False)
|
df_train.to_csv(public / "train" / "ARF_12h.csv", index=False)
|
||||||
|
|
||||||
assert (
|
if X_train.shape[0] != df_train.shape[0]:
|
||||||
X_train.shape[0] == df_train.shape[0]
|
raise ValueError(
|
||||||
), f"Mismatch: X_train rows ({X_train.shape[0]}) != df_train rows ({df_train.shape[0]})"
|
f"Mismatch: X_train rows ({X_train.shape[0]}) != df_train rows ({df_train.shape[0]})"
|
||||||
assert (
|
)
|
||||||
X_test.shape[0] == df_test.shape[0]
|
if X_test.shape[0] != df_test.shape[0]:
|
||||||
), f"Mismatch: X_test rows ({X_test.shape[0]}) != df_test rows ({df_test.shape[0]})"
|
raise ValueError(
|
||||||
assert df_test.shape[1] == 2, "Public test set should have 2 columns"
|
f"Mismatch: X_test rows ({X_test.shape[0]}) != df_test rows ({df_test.shape[0]})"
|
||||||
assert df_train.shape[1] == 3, "Public train set should have 3 columns"
|
)
|
||||||
assert len(df_train) + len(df_test) == len(
|
if df_test.shape[1] != 2:
|
||||||
df_label
|
raise ValueError("Public test set should have 2 columns")
|
||||||
), "Length of new_train and new_test should equal length of old_train"
|
if df_train.shape[1] != 3:
|
||||||
|
raise ValueError("Public train set should have 3 columns")
|
||||||
|
if len(df_train) + len(df_test) != len(df_label):
|
||||||
|
raise ValueError("Length of new_train and new_test should equal length of old_train")
|
||||||
|
|||||||
@@ -320,7 +320,8 @@ class DataScienceRDLoop(RDLoop):
|
|||||||
# only clean current workspace without affecting other loops.
|
# only clean current workspace without affecting other loops.
|
||||||
for k in "direct_exp_gen", "coding", "running":
|
for k in "direct_exp_gen", "coding", "running":
|
||||||
if k in prev_out and prev_out[k] is not None:
|
if k in prev_out and prev_out[k] is not None:
|
||||||
assert isinstance(prev_out[k], DSExperiment)
|
if not isinstance(prev_out[k], DSExperiment):
|
||||||
|
raise TypeError(f"prev_out[{k!r}] must be an instance of DSExperiment")
|
||||||
clean_workspace(prev_out[k].experiment_workspace.workspace_path)
|
clean_workspace(prev_out[k].experiment_workspace.workspace_path)
|
||||||
|
|
||||||
# Backup the workspace (only necessary files are included)
|
# Backup the workspace (only necessary files are included)
|
||||||
|
|||||||
@@ -213,7 +213,8 @@ class DSTrace(Trace[DataScienceScen, KnowledgeBase]):
|
|||||||
self, component: COMPONENT, search_list: list[tuple[DSExperiment, ExperimentFeedback]] = []
|
self, component: COMPONENT, search_list: list[tuple[DSExperiment, ExperimentFeedback]] = []
|
||||||
) -> bool:
|
) -> bool:
|
||||||
for exp, fb in search_list:
|
for exp, fb in search_list:
|
||||||
assert isinstance(exp.hypothesis, DSHypothesis), "Hypothesis should be DSHypothesis (and not None)"
|
if not isinstance(exp.hypothesis, DSHypothesis):
|
||||||
|
raise TypeError("Hypothesis should be DSHypothesis (and not None)")
|
||||||
if exp.hypothesis.component == component and fb:
|
if exp.hypothesis.component == component and fb:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -377,7 +377,8 @@ class ExpGen2TraceAndMergeV2(ExpGen):
|
|||||||
if DS_RD_SETTING.enable_multi_version_exp_gen:
|
if DS_RD_SETTING.enable_multi_version_exp_gen:
|
||||||
exp_gen_version_list = DS_RD_SETTING.exp_gen_version_list.split(",")
|
exp_gen_version_list = DS_RD_SETTING.exp_gen_version_list.split(",")
|
||||||
for version in exp_gen_version_list:
|
for version in exp_gen_version_list:
|
||||||
assert version in ["v3", "v2", "v1"]
|
if version not in ["v3", "v2", "v1"]:
|
||||||
|
raise ValueError(f"version must be 'v1', 'v2', or 'v3', got {version!r}")
|
||||||
|
|
||||||
if len(trace.hist) == 0:
|
if len(trace.hist) == 0:
|
||||||
# set the proposal version for the first sub-trace
|
# set the proposal version for the first sub-trace
|
||||||
|
|||||||
@@ -339,7 +339,8 @@ class DSProposalV1ExpGen(ExpGen):
|
|||||||
eda_output = sota_exp.experiment_workspace.file_dict.get("EDA.md", None)
|
eda_output = sota_exp.experiment_workspace.file_dict.get("EDA.md", None)
|
||||||
scenario_desc = trace.scen.get_scenario_all_desc(eda_output=eda_output)
|
scenario_desc = trace.scen.get_scenario_all_desc(eda_output=eda_output)
|
||||||
|
|
||||||
assert sota_exp is not None, "SOTA experiment is not provided."
|
if sota_exp is None:
|
||||||
|
raise ValueError("SOTA experiment is not provided.")
|
||||||
last_exp = trace.last_exp()
|
last_exp = trace.last_exp()
|
||||||
# exp_and_feedback = trace.hist[-1]
|
# exp_and_feedback = trace.hist[-1]
|
||||||
# last_exp = exp_and_feedback[0]
|
# last_exp = exp_and_feedback[0]
|
||||||
@@ -445,8 +446,10 @@ class DSProposalV1ExpGen(ExpGen):
|
|||||||
json_target_type=dict[str, dict[str, str | dict] | str],
|
json_target_type=dict[str, dict[str, str | dict] | str],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
assert "hypothesis_proposal" in resp_dict, "Hypothesis proposal not provided."
|
if "hypothesis_proposal" not in resp_dict:
|
||||||
assert "task_design" in resp_dict, "Task design not provided."
|
raise ValueError("Hypothesis proposal not provided.")
|
||||||
|
if "task_design" not in resp_dict:
|
||||||
|
raise ValueError("Task design not provided.")
|
||||||
task_class = component_info["task_class"]
|
task_class = component_info["task_class"]
|
||||||
hypothesis_proposal = resp_dict.get("hypothesis_proposal", {})
|
hypothesis_proposal = resp_dict.get("hypothesis_proposal", {})
|
||||||
hypothesis = DSHypothesis(
|
hypothesis = DSHypothesis(
|
||||||
@@ -1149,8 +1152,10 @@ You help users retrieve relevant knowledge from community discussions and public
|
|||||||
)
|
)
|
||||||
|
|
||||||
response_dict = json.loads(response)
|
response_dict = json.loads(response)
|
||||||
assert response_dict.get("component") in HypothesisComponent.__members__, f"Invalid component"
|
if response_dict.get("component") not in HypothesisComponent.__members__:
|
||||||
assert response_dict.get("hypothesis") is not None, f"Invalid hypothesis"
|
raise ValueError(f"Invalid component: {response_dict.get('component')}")
|
||||||
|
if response_dict.get("hypothesis") is None:
|
||||||
|
raise ValueError("Invalid hypothesis")
|
||||||
return response_dict
|
return response_dict
|
||||||
|
|
||||||
# END: for support llm-based hypothesis selection -----
|
# END: for support llm-based hypothesis selection -----
|
||||||
@@ -1253,7 +1258,8 @@ You help users retrieve relevant knowledge from community discussions and public
|
|||||||
description=task_desc,
|
description=task_desc,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert isinstance(task, PipelineTask), f"Task {task_name} is not a PipelineTask, got {type(task)}"
|
if not isinstance(task, PipelineTask):
|
||||||
|
raise TypeError(f"Task {task_name} is not a PipelineTask, got {type(task)}")
|
||||||
# only for llm with response schema.(TODO: support for non-schema llm?)
|
# only for llm with response schema.(TODO: support for non-schema llm?)
|
||||||
# If the LLM provides a "packages" field (list[str]), compute runtime environment now and cache it for subsequent prompts in later loops.
|
# If the LLM provides a "packages" field (list[str]), compute runtime environment now and cache it for subsequent prompts in later loops.
|
||||||
if isinstance(task_dict, dict) and "packages" in task_dict and isinstance(task_dict["packages"], list):
|
if isinstance(task_dict, dict) and "packages" in task_dict and isinstance(task_dict["packages"], list):
|
||||||
|
|||||||
@@ -165,7 +165,8 @@ class KGScenario(Scenario):
|
|||||||
return data_info
|
return data_info
|
||||||
|
|
||||||
def output_format(self, tag=None) -> str:
|
def output_format(self, tag=None) -> str:
|
||||||
assert tag in [None, "feature", "model"]
|
if tag not in [None, "feature", "model"]:
|
||||||
|
raise ValueError(f"tag must be None, 'feature', or 'model', got {tag!r}")
|
||||||
feature_output_format = f"""The feature code should output following the format:
|
feature_output_format = f"""The feature code should output following the format:
|
||||||
{T(".prompts:kg_feature_output_format").r()}"""
|
{T(".prompts:kg_feature_output_format").r()}"""
|
||||||
model_output_format = f"""The model code should output following the format:\n""" + T(
|
model_output_format = f"""The model code should output following the format:\n""" + T(
|
||||||
@@ -180,7 +181,8 @@ class KGScenario(Scenario):
|
|||||||
return model_output_format
|
return model_output_format
|
||||||
|
|
||||||
def interface(self, tag=None) -> str:
|
def interface(self, tag=None) -> str:
|
||||||
assert tag in [None, "feature", "XGBoost", "RandomForest", "LightGBM", "NN"]
|
if tag not in [None, "feature", "XGBoost", "RandomForest", "LightGBM", "NN"]:
|
||||||
|
raise ValueError(f"tag must be None, 'feature', 'XGBoost', 'RandomForest', 'LightGBM', or 'NN', got {tag!r}")
|
||||||
feature_interface = f"""The feature code should follow the interface:
|
feature_interface = f"""The feature code should follow the interface:
|
||||||
{T(".prompts:kg_feature_interface").r()}"""
|
{T(".prompts:kg_feature_interface").r()}"""
|
||||||
if tag == "feature":
|
if tag == "feature":
|
||||||
@@ -195,7 +197,8 @@ class KGScenario(Scenario):
|
|||||||
return model_interface
|
return model_interface
|
||||||
|
|
||||||
def simulator(self, tag=None) -> str:
|
def simulator(self, tag=None) -> str:
|
||||||
assert tag in [None, "feature", "model"]
|
if tag not in [None, "feature", "model"]:
|
||||||
|
raise ValueError(f"tag must be None, 'feature', or 'model', got {tag!r}")
|
||||||
|
|
||||||
kg_feature_simulator = (
|
kg_feature_simulator = (
|
||||||
"The feature code will be sent to the simulator:\n" + T(".prompts:kg_feature_simulator").r()
|
"The feature code will be sent to the simulator:\n" + T(".prompts:kg_feature_simulator").r()
|
||||||
|
|||||||
@@ -87,7 +87,12 @@ def crawl_descriptions(
|
|||||||
content = e.get_attribute("innerHTML")
|
content = e.get_attribute("innerHTML")
|
||||||
contents.append(content)
|
contents.append(content)
|
||||||
|
|
||||||
assert len(subtitles) == len(contents) + 1 and subtitles[-1] == "Citation"
|
if not (len(subtitles) == len(contents) + 1 and subtitles[-1] == "Citation"):
|
||||||
|
raise AssertionError(
|
||||||
|
f"Expected len(contents)+1 == len(subtitles) and last subtitle == 'Citation', "
|
||||||
|
f"got len(subtitles)={len(subtitles)}, len(contents)={len(contents)}, "
|
||||||
|
f"last subtitle={subtitles[-1]!r}"
|
||||||
|
)
|
||||||
for i in range(len(subtitles) - 1):
|
for i in range(len(subtitles) - 1):
|
||||||
descriptions[subtitles[i]] = contents[i]
|
descriptions[subtitles[i]] = contents[i]
|
||||||
|
|
||||||
|
|||||||
@@ -307,7 +307,8 @@ class KGHypothesisGen(FactorAndModelHypothesisGen):
|
|||||||
class KGHypothesis2Experiment(FactorAndModelHypothesis2Experiment):
|
class KGHypothesis2Experiment(FactorAndModelHypothesis2Experiment):
|
||||||
def prepare_context(self, hypothesis: Hypothesis, trace: Trace) -> Tuple[dict, bool]:
|
def prepare_context(self, hypothesis: Hypothesis, trace: Trace) -> Tuple[dict, bool]:
|
||||||
scenario = trace.scen.get_scenario_all_desc(filtered_tag="hypothesis_and_experiment")
|
scenario = trace.scen.get_scenario_all_desc(filtered_tag="hypothesis_and_experiment")
|
||||||
assert isinstance(hypothesis, KGHypothesis)
|
if not isinstance(hypothesis, KGHypothesis):
|
||||||
|
raise TypeError("hypothesis must be an instance of KGHypothesis")
|
||||||
experiment_output_format = (
|
experiment_output_format = (
|
||||||
T("scenarios.kaggle.prompts:feature_experiment_output_format").r()
|
T("scenarios.kaggle.prompts:feature_experiment_output_format").r()
|
||||||
if hypothesis.action in [KG_ACTION_FEATURE_ENGINEERING, KG_ACTION_FEATURE_PROCESSING]
|
if hypothesis.action in [KG_ACTION_FEATURE_ENGINEERING, KG_ACTION_FEATURE_PROCESSING]
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ class QlibQuantScenario(Scenario):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def background(self, tag=None) -> str:
|
def background(self, tag=None) -> str:
|
||||||
assert tag in [None, "factor", "model"]
|
if tag not in [None, "factor", "model"]:
|
||||||
|
raise ValueError(f"tag must be None, 'factor', or 'model', got {tag!r}")
|
||||||
quant_background = "The background of the scenario is as follows:\n" + T(".prompts:qlib_quant_background").r(
|
quant_background = "The background of the scenario is as follows:\n" + T(".prompts:qlib_quant_background").r(
|
||||||
runtime_environment=self.get_runtime_environment(),
|
runtime_environment=self.get_runtime_environment(),
|
||||||
)
|
)
|
||||||
@@ -83,7 +84,8 @@ class QlibQuantScenario(Scenario):
|
|||||||
return self._source_data
|
return self._source_data
|
||||||
|
|
||||||
def output_format(self, tag=None) -> str:
|
def output_format(self, tag=None) -> str:
|
||||||
assert tag in [None, "factor", "model"]
|
if tag not in [None, "factor", "model"]:
|
||||||
|
raise ValueError(f"tag must be None, 'factor', or 'model', got {tag!r}")
|
||||||
factor_output_format = (
|
factor_output_format = (
|
||||||
"The factor code should output the following format:\n" + T(".prompts:qlib_factor_output_format").r()
|
"The factor code should output the following format:\n" + T(".prompts:qlib_factor_output_format").r()
|
||||||
)
|
)
|
||||||
@@ -99,7 +101,8 @@ class QlibQuantScenario(Scenario):
|
|||||||
return model_output_format
|
return model_output_format
|
||||||
|
|
||||||
def interface(self, tag=None) -> str:
|
def interface(self, tag=None) -> str:
|
||||||
assert tag in [None, "factor", "model"]
|
if tag not in [None, "factor", "model"]:
|
||||||
|
raise ValueError(f"tag must be None, 'factor', or 'model', got {tag!r}")
|
||||||
factor_interface = (
|
factor_interface = (
|
||||||
"The factor code should be written in the following interface:\n" + T(".prompts:qlib_factor_interface").r()
|
"The factor code should be written in the following interface:\n" + T(".prompts:qlib_factor_interface").r()
|
||||||
)
|
)
|
||||||
@@ -115,7 +118,8 @@ class QlibQuantScenario(Scenario):
|
|||||||
return model_interface
|
return model_interface
|
||||||
|
|
||||||
def simulator(self, tag=None) -> str:
|
def simulator(self, tag=None) -> str:
|
||||||
assert tag in [None, "factor", "model"]
|
if tag not in [None, "factor", "model"]:
|
||||||
|
raise ValueError(f"tag must be None, 'factor', or 'model', got {tag!r}")
|
||||||
factor_simulator = "The factor code will be sent to the simulator:\n" + T(".prompts:qlib_factor_simulator").r()
|
factor_simulator = "The factor code will be sent to the simulator:\n" + T(".prompts:qlib_factor_simulator").r()
|
||||||
model_simulator = "The model code will be sent to the simulator:\n" + T(".prompts:qlib_model_simulator").r()
|
model_simulator = "The model code will be sent to the simulator:\n" + T(".prompts:qlib_model_simulator").r()
|
||||||
|
|
||||||
@@ -185,7 +189,8 @@ class QlibQuantScenario(Scenario):
|
|||||||
return common_description(action) + interface(action) + output(action) + simulator(action)
|
return common_description(action) + interface(action) + output(action) + simulator(action)
|
||||||
|
|
||||||
def get_runtime_environment(self, tag: str = None) -> str:
|
def get_runtime_environment(self, tag: str = None) -> str:
|
||||||
assert tag in [None, "factor", "model"]
|
if tag not in [None, "factor", "model"]:
|
||||||
|
raise ValueError(f"tag must be None, 'factor', or 'model', got {tag!r}")
|
||||||
|
|
||||||
if tag is None or tag == "factor":
|
if tag is None or tag == "factor":
|
||||||
# Use factor env to get the runtime environment
|
# Use factor env to get the runtime environment
|
||||||
|
|||||||
@@ -620,7 +620,8 @@ class LocalEnv(Env[ASpecificLocalConf]):
|
|||||||
for lp, rp in running_extra_volume.items():
|
for lp, rp in running_extra_volume.items():
|
||||||
volumes[lp] = rp
|
volumes[lp] = rp
|
||||||
|
|
||||||
assert local_path is not None, "local_path should not be None"
|
if local_path is None:
|
||||||
|
raise ValueError("local_path should not be None")
|
||||||
volumes = normalize_volumes(volumes, local_path)
|
volumes = normalize_volumes(volumes, local_path)
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
@@ -1472,7 +1473,8 @@ class DockerEnv(Env[DockerConf]):
|
|||||||
cpu_count=self.conf.cpu_count, # Set CPU limit
|
cpu_count=self.conf.cpu_count, # Set CPU limit
|
||||||
**self._gpu_kwargs(client),
|
**self._gpu_kwargs(client),
|
||||||
)
|
)
|
||||||
assert container is not None # Ensure container was created successfully
|
if container is None:
|
||||||
|
raise AssertionError("Docker container was not created successfully")
|
||||||
logs = container.logs(stream=True)
|
logs = container.logs(stream=True)
|
||||||
print(Rule("[bold green]Docker Logs Begin[/bold green]", style="dark_orange"))
|
print(Rule("[bold green]Docker Logs Begin[/bold green]", style="dark_orange"))
|
||||||
table = Table(title="Run Info", show_header=False)
|
table = Table(title="Run Info", show_header=False)
|
||||||
|
|||||||
@@ -84,7 +84,8 @@ class WorkflowTracker:
|
|||||||
# Log timer status if timer is started
|
# Log timer status if timer is started
|
||||||
if self.loop_base.timer.started:
|
if self.loop_base.timer.started:
|
||||||
remain_time = self.loop_base.timer.remain_time()
|
remain_time = self.loop_base.timer.remain_time()
|
||||||
assert remain_time is not None
|
if remain_time is None:
|
||||||
|
raise AssertionError("remain_time should not be None")
|
||||||
mlflow.log_metric("remain_time", remain_time.total_seconds())
|
mlflow.log_metric("remain_time", remain_time.total_seconds())
|
||||||
mlflow.log_metric(
|
mlflow.log_metric(
|
||||||
"remain_percent",
|
"remain_percent",
|
||||||
|
|||||||
Reference in New Issue
Block a user