2024-07-10 15:45:43 +08:00
import pickle
import site
2024-07-30 19:38:37 +08:00
import traceback
2024-06-28 11:45:23 +08:00
from pathlib import Path
2024-09-11 15:26:52 +08:00
from typing import Dict , Optional
2024-06-28 11:45:23 +08:00
2024-11-25 16:27:34 +08:00
from rdagent.components.coder.CoSTEER.task import CoSTEERTask
from rdagent.core.experiment import Experiment , FBWorkspace
2024-10-14 17:34:09 +08:00
from rdagent.core.utils import cache_with_pickle
2024-07-10 15:45:43 +08:00
from rdagent.oai.llm_utils import md5_hash
2024-09-11 15:26:52 +08:00
from rdagent.utils.env import KGDockerEnv , QTDockerEnv
2024-06-21 16:41:34 +08:00
2024-11-25 16:27:34 +08:00
class ModelTask ( CoSTEERTask ):
2024-06-28 11:45:23 +08:00
def __init__ (
2024-07-26 12:12:16 +08:00
self ,
name : str ,
description : str ,
architecture : str ,
2024-09-11 15:26:52 +08:00
* args ,
2024-07-26 12:12:16 +08:00
hyperparameters : Dict [ str , str ],
2024-09-11 15:26:52 +08:00
formulation : str = None ,
variables : Dict [ str , str ] = None ,
2024-07-26 12:12:16 +08:00
model_type : Optional [ str ] = None ,
2024-09-11 15:26:52 +08:00
** kwargs ,
2024-06-28 11:45:23 +08:00
) -> None :
2024-07-10 15:45:43 +08:00
self . formulation : str = formulation
2024-07-24 09:14:20 +00:00
self . architecture : str = architecture
2024-07-10 15:45:43 +08:00
self . variables : str = variables
2024-07-24 11:33:04 +00:00
self . hyperparameters : str = hyperparameters
2024-10-24 20:38:13 +08:00
self . model_type : str = (
model_type # Tabular for tabular model, TimesSeries for time series model, Graph for graph model, XGBoost for XGBoost model
)
2025-01-17 22:53:05 +08:00
super () . __init__ ( name = name , description = description , * args , ** kwargs )
2024-07-02 17:58:37 +08:00
2024-07-15 08:28:34 +00:00
def get_task_information ( self ):
2024-09-11 15:26:52 +08:00
task_desc = f """name: { self . name }
2024-06-30 23:31:00 +08:00
description: { self . description }
"""
2024-09-11 15:26:52 +08:00
task_desc += f "formulation: { self . formulation } \n " if self . formulation else ""
task_desc += f "architecture: { self . architecture } \n "
task_desc += f "variables: { self . variables } \n " if self . variables else ""
task_desc += f "hyperparameters: { self . hyperparameters } \n "
task_desc += f "model_type: { self . model_type } \n "
return task_desc
2024-07-02 17:58:37 +08:00
2024-06-30 23:31:00 +08:00
@staticmethod
def from_dict ( dict ):
2024-07-03 17:42:07 +08:00
return ModelTask ( ** dict )
2024-07-02 17:58:37 +08:00
2024-06-30 23:31:00 +08:00
def __repr__ ( self ) -> str :
return f "< { self . __class__ . __name__ } { self . name } >"
2024-06-21 16:41:34 +08:00
2024-07-17 15:00:13 +08:00
class ModelFBWorkspace ( FBWorkspace ):
2024-06-21 16:41:34 +08:00
"""
It is a Pytorch model implementation task;
All the things are placed in a folder.
Folder
- data source and documents prepared by `prepare`
- Please note that new data may be passed in dynamically in `execute`
- code (file `model.py` ) injected by `inject_code`
- the `model.py` that contains a variable named `model_cls` which indicates the implemented model structure
- `model_cls` is a instance of `torch.nn.Module`;
2024-09-11 15:26:52 +08:00
We support two ways of interface:
(version 1) for qlib we'll make a script to import the model in the implementation in file `model.py` after setting the cwd into the directory
- from model import model_cls
- initialize the model by initializing it `model_cls(input_dim=INPUT_DIM)`
- And then verify the model.
2024-06-28 11:45:23 +08:00
2024-09-11 15:26:52 +08:00
(version 2) for kaggle we'll make a script to call the fit and predict function in the implementation in file `model.py` after setting the cwd into the directory
2024-06-21 16:41:34 +08:00
"""
2024-06-28 11:45:23 +08:00
2024-10-14 17:34:09 +08:00
def hash_func (
self ,
batch_size : int = 8 ,
num_features : int = 10 ,
num_timesteps : int = 4 ,
num_edges : int = 20 ,
input_value : float = 1.0 ,
param_init_value : float = 1.0 ,
) -> str :
target_file_name = f " { batch_size } _ { num_features } _ { num_timesteps } _ { input_value } _ { param_init_value } "
2025-01-17 22:53:05 +08:00
for code_file_name in sorted ( list ( self . file_dict . keys ())):
target_file_name = f " { target_file_name } _ { self . file_dict [ code_file_name ] } "
2024-10-14 17:34:09 +08:00
return md5_hash ( target_file_name )
@cache_with_pickle ( hash_func )
2024-07-10 15:45:43 +08:00
def execute (
self ,
batch_size : int = 8 ,
num_features : int = 10 ,
num_timesteps : int = 4 ,
2024-07-30 19:38:37 +08:00
num_edges : int = 20 ,
2024-07-10 15:45:43 +08:00
input_value : float = 1.0 ,
param_init_value : float = 1.0 ,
):
2025-02-25 12:06:07 +08:00
self . before_execute ()
2024-06-21 16:41:34 +08:00
try :
2024-09-11 15:26:52 +08:00
qtde = QTDockerEnv () if self . target_task . version == 1 else KGDockerEnv ()
qtde . prepare ()
if self . target_task . version == 1 :
dump_code = f """
MODEL_TYPE = " { self . target_task . model_type } "
BATCH_SIZE = { batch_size }
NUM_FEATURES = { num_features }
NUM_TIMESTEPS = { num_timesteps }
NUM_EDGES = { num_edges }
INPUT_VALUE = { input_value }
PARAM_INIT_VALUE = { param_init_value }
{ ( Path ( __file__ ) . parent / 'model_execute_template_v1.txt' ) . read_text () }
"""
elif self . target_task . version == 2 :
dump_code = ( Path ( __file__ ) . parent / "model_execute_template_v2.txt" ) . read_text ()
log , results = qtde . dump_python_code_run_and_get_results (
code = dump_code ,
dump_file_names = [ "execution_feedback_str.pkl" , "execution_model_output.pkl" ],
local_path = str ( self . workspace_path ),
env = {},
2024-09-24 14:50:01 +08:00
code_dump_file_py_name = "model_test" ,
2024-09-11 15:26:52 +08:00
)
2025-01-17 22:53:05 +08:00
if len ( results ) == 0 :
2024-09-11 15:26:52 +08:00
raise RuntimeError ( f "Error in running the model code: { log } " )
[ execution_feedback_str , execution_model_output ] = results
2024-07-26 12:12:16 +08:00
2024-07-10 15:45:43 +08:00
except Exception as e :
2024-07-30 19:38:37 +08:00
execution_feedback_str = f "Execution error: { e } \n Traceback: { traceback . format_exc () } "
execution_model_output = None
if len ( execution_feedback_str ) > 2000 :
execution_feedback_str = (
execution_feedback_str [: 1000 ] + "....hidden long error message...." + execution_feedback_str [ - 1000 :]
)
return execution_feedback_str , execution_model_output
2024-07-10 15:45:43 +08:00
2024-07-17 15:00:13 +08:00
ModelExperiment = Experiment