1111from intugle .link_predictor .predictor import LinkPredictor
1212from intugle .semantic_search import SemanticSearch
1313from intugle .utils .files import update_relationship_file_mtime
14+ from pathlib import Path
1415
1516if TYPE_CHECKING :
1617 from intugle .adapters .adapter import Adapter
2021
2122
2223class SemanticModel :
23- def __init__ (self , data_input : Dict [str , Any ] | List [DataSet ], domain : str = "" ):
24+ def __init__ (self , data_input : Dict [str , Any ] | List [DataSet ] | str , domain : str = "" ):
2425 """
2526 Initialize a SemanticModel to build a semantic layer over your data.
2627
@@ -57,13 +58,15 @@ def __init__(self, data_input: Dict[str, Any] | List[DataSet], domain: str = "")
5758 self .domain = domain
5859 self ._semantic_search_initialized = False
5960
60- if isinstance (data_input , dict ):
61+ if isinstance (data_input , str ):
62+ self ._initialize_from_folder (data_input )
63+ elif isinstance (data_input , dict ):
6164 self ._initialize_from_dict (data_input )
6265 elif isinstance (data_input , list ):
6366 self ._initialize_from_list (data_input )
6467 else :
6568 raise TypeError (
66- "Input must be a dictionary of named dataframes or a list of DataSet objects ."
69+ "Input must be a dictionary, a list of DataSet objects, or a folder path string ."
6770 )
6871
6972 def _initialize_from_dict (self , data_dict : Dict [str , Any ]):
@@ -80,6 +83,56 @@ def _initialize_from_list(self, data_list: List[DataSet]):
8083 "DataSet objects provided in a list must have a 'name' attribute."
8184 )
8285 self .datasets [dataset .name ] = dataset
86+ def _initialize_from_folder (self , folder_path : str ):
87+ """
88+ Initialize datasets by scanning a folder (recursively) for supported data files.
89+ Supported formats: CSV, Parquet, Excel.
90+ """
91+ path = Path (folder_path )
92+
93+ if not path .exists ():
94+ raise ValueError (f"Provided path does not exist: { folder_path } " )
95+
96+ if not path .is_dir ():
97+ raise ValueError (f"Provided path is not a directory: { folder_path } " )
98+
99+ extension_mapping = {
100+ ".csv" : "csv" ,
101+ ".parquet" : "parquet" ,
102+ ".xlsx" : "xlsx" ,
103+ }
104+
105+ found = False
106+
107+ for file_path in path .rglob ("*" ): # Recursive
108+ if not file_path .is_file ():
109+ continue
110+
111+ ext = file_path .suffix .lower ()
112+ if ext not in extension_mapping :
113+ continue
114+
115+ dataset_name = file_path .stem
116+
117+ if dataset_name in self .datasets :
118+ raise ValueError (
119+ f"Duplicate dataset name '{ dataset_name } ' found while scanning { folder_path } "
120+ )
121+
122+ config = {
123+ "path" : str (file_path .resolve ()),
124+ "type" : extension_mapping [ext ],
125+ }
126+
127+ dataset = DataSet (config , name = dataset_name )
128+ self .datasets [dataset_name ] = dataset
129+ found = True
130+
131+ if not found :
132+ raise ValueError (
133+ f"No supported data files (.csv, .parquet, .xlsx) found in directory: { folder_path } "
134+ )
135+
83136
84137 def profile (self , force_recreate : bool = False ):
85138 """
0 commit comments