-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Expand file tree
/
Copy pathfeature_store_client_configs_gen.py
More file actions
238 lines (200 loc) · 7.05 KB
/
feature_store_client_configs_gen.py
File metadata and controls
238 lines (200 loc) · 7.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#!/usr/bin/env python3
"""
Script to create feature store YAMLs and feature store objects from client config YAML contents.
Especially made for Workbenches to create feature store YAMLs and objects from client config contents from dashboard
This script:
1. Takes multiple Feast client config YAML contents as input
2. Creates feature_store.yaml files in the current directory for each config
3. Creates FeatureStore objects for each configuration
4. Prints success messages and feature store object names
"""
import os
import yaml
from pathlib import Path
from typing import Dict, Any
from feast import FeatureStore
def create_feature_store_yaml(config_content: str, config_name: str) -> str:
"""
Create a feature_store.yaml file from config content.
Args:
config_content: YAML content as string
config_name: Name identifier for the config (used for filename)
Returns:
Path to the created YAML file
"""
# Parse the YAML content to validate it
try:
config_dict = yaml.safe_load(config_content)
except yaml.YAMLError as e:
raise ValueError(f"Failed to parse YAML content for {config_name}: {e}")
# Ensure required fields are present
required_fields = ["project", "registry", "provider"]
for field in required_fields:
if field not in config_dict:
raise ValueError(
f"Failed to create config {config_name}: missing required field '{field}'"
)
# Create filename
filename = f"feature_store_{config_name}.yaml"
filepath = Path(filename)
# Write the YAML file
with open(filepath, "w") as f:
yaml.dump(config_dict, f, default_flow_style=False, sort_keys=False)
return str(filepath)
def create_feature_store_object(yaml_file_path: str) -> FeatureStore:
"""
Create a FeatureStore object from a YAML file.
Args:
yaml_file_path: Path to the feature_store.yaml file
Returns:
FeatureStore object
"""
try:
# Create FeatureStore from the YAML file
fs = FeatureStore(fs_yaml_file=Path(yaml_file_path))
return fs
except Exception as e:
raise RuntimeError(
f"Failed to create FeatureStore object from {yaml_file_path}: {e}"
)
def process_client_configs(client_configs: Dict[str, str]) -> Dict[str, Dict[str, Any]]:
"""
Process multiple client config YAML contents and create feature stores.
Args:
client_configs: Dictionary mapping config names to YAML content strings
Returns:
Dictionary with results for each config
"""
results = {}
created_yamls = []
feature_stores = {}
print("Creating feature store YAMLs and objects...")
print("=" * 50)
for config_name, config_content in client_configs.items():
try:
print(f"\nProcessing config: {config_name}")
# Create YAML file
yaml_path = create_feature_store_yaml(config_content, config_name)
created_yamls.append(yaml_path)
print(f"✓ Created YAML file: {yaml_path}")
# Create FeatureStore object
fs = create_feature_store_object(yaml_path)
fs_var_name = f"fs_{fs.project}"
globals()[fs_var_name] = fs
feature_stores[config_name] = fs_var_name
print(f"✓ Created FeatureStore object: {fs_var_name}")
results[config_name] = {
"yaml_path": yaml_path,
"feature_store": fs_var_name,
"project_name": fs.project,
"success": True,
"error": None,
}
except Exception as e:
print(f"✗ Failed to process config {config_name}: {e}")
results[config_name] = {
"yaml_path": None,
"feature_store": None,
"project_name": None,
"success": False,
"error": str(e),
}
return results
def print_summary(results: Dict[str, Dict[str, Any]]) -> None:
"""
Print summary of all operations.
Args:
results: Results dictionary from process_client_configs
"""
print("\n" + "=" * 50)
print("SUMMARY")
print("=" * 50)
successful_configs = [name for name, result in results.items() if result["success"]]
failed_configs = [name for name, result in results.items() if not result["success"]]
print(f"\n\n✓✓Feature Store YAML files have been created in: {os.getcwd()}")
print(f"\n✓ Successfully processed {len(successful_configs)} config(s):")
for config_name in successful_configs:
result = results[config_name]
print(
f" - {config_name}: {result['yaml_path']} (Project: {result['project_name']})"
)
if failed_configs:
print(f"\n✗ Failed to process {len(failed_configs)} config(s):")
for config_name in failed_configs:
result = results[config_name]
print(f" - {config_name}: {result['error']}")
print("\n\n✓✓ Feature Store Object(s) details:")
for config_name in successful_configs:
result = results[config_name]
print(
f"> Object Name - {result['feature_store']} ; project name - {result['project_name']} ; yaml path - {result['yaml_path']}"
)
print("\n")
print("=" * 25, "Usage:", "=" * 25)
print(
"You can now use feature store object(s) to access the feature store resources and functions!"
)
print(
"\n// Note: Replace object_name with the actual object name from the list above."
)
print("object_name.list_features()\nobject_name.get_historical_features()")
print("=" * 58)
def main():
"""
Main function to demonstrate usage with example configs.
"""
# Example client config YAML contents
example_configs = {
"local_sqlite": """
project: local_feature_store
registry: data/registry.db
provider: local
online_store:
type: sqlite
path: data/online_store.db
offline_store:
type: file
entity_key_serialization_version: 3
""",
"aws_redshift": """
project: aws_feature_store
registry: data/registry.db
provider: aws
online_store:
type: sqlite
path: data/online_store.db
offline_store:
type: redshift
cluster_id: my-cluster
region: us-west-2
database: my_database
user: my_user
s3_staging_location: s3://my-bucket/staging
iam_role: arn:aws:iam::123456789012:role/RedshiftRole
entity_key_serialization_version: 3
""",
"gcp_bigquery": """
project: gcp_feature_store
registry: data/registry.db
provider: gcp
online_store:
type: sqlite
path: data/online_store.db
offline_store:
type: bigquery
project_id: my-gcp-project
dataset_id: my_dataset
entity_key_serialization_version: 3
""",
}
print("=" * 50)
print(
"This script will create feature store YAMLs and objects from client configs."
)
print(f"Processing {len(example_configs)} example configurations...")
# Process the configs
results = process_client_configs(example_configs)
# Print summary
print_summary(results)
if __name__ == "__main__":
main()