Spaces:
Runtime error
Runtime error
File size: 6,952 Bytes
ffcf62f |
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 |
import json
import os
import time
from typing import Dict
from swarms.utils.loguru_logger import initialize_logger
from swarms.telemetry.capture_sys_data import (
capture_system_data,
log_agent_data,
)
logger = initialize_logger(log_folder="onboarding_process")
class OnboardingProcess:
"""
This class handles the onboarding process for users. It collects user data including their
full name, first name, email, Swarms API key, and system data, then autosaves it in both a
main JSON file and a cache file for reliability. It supports loading previously saved or cached data.
"""
def __init__(
self,
auto_save_path: str = "user_data.json",
cache_save_path: str = "user_data_cache.json",
) -> None:
"""
Initializes the OnboardingProcess with an autosave file path and a cache path.
Args:
auto_save_path (str): The path where user data is automatically saved.
cache_save_path (str): The path where user data is cached for reliability.
"""
self.user_data: Dict[str, str] = {}
self.system_data: Dict[str, str] = capture_system_data()
self.auto_save_path = auto_save_path
self.cache_save_path = cache_save_path
self.load_existing_data()
def load_existing_data(self) -> None:
"""
Loads existing user data from the auto-save file or cache if available.
"""
if os.path.exists(self.auto_save_path):
try:
with open(self.auto_save_path, "r") as f:
self.user_data = json.load(f)
logger.info(
"Existing user data loaded from {}",
self.auto_save_path,
)
return
except json.JSONDecodeError as e:
logger.error(
"Failed to load user data from main file: {}", e
)
# Fallback to cache if main file fails
if os.path.exists(self.cache_save_path):
try:
with open(self.cache_save_path, "r") as f:
self.user_data = json.load(f)
logger.info(
"User data loaded from cache: {}",
self.cache_save_path,
)
except json.JSONDecodeError as e:
logger.error(
"Failed to load user data from cache: {}", e
)
def save_data(self, retry_attempts: int = 3) -> None:
"""
Saves the current user data to both the auto-save file and the cache file. If the main
save fails, the cache is updated instead. Implements retry logic with exponential backoff
in case both save attempts fail.
Args:
retry_attempts (int): The number of retries if saving fails.
"""
attempt = 0
backoff_time = 1 # Starting backoff time (in seconds)
while attempt < retry_attempts:
try:
combined_data = {**self.user_data, **self.system_data}
log_agent_data(combined_data)
return # Exit the function if saving was successful
except Exception as e:
logger.error(
"Error saving user data (Attempt {}): {}",
attempt + 1,
e,
)
# Retry after a short delay (exponential backoff)
time.sleep(backoff_time)
attempt += 1
backoff_time *= (
2 # Double the backoff time for each retry
)
logger.error(
"Failed to save user data after {} attempts.",
retry_attempts,
)
def ask_input(self, prompt: str, key: str) -> None:
"""
Asks the user for input, validates it, and saves it in the user_data dictionary.
Autosaves and caches after each valid input.
Args:
prompt (str): The prompt message to display to the user.
key (str): The key under which the input will be saved in user_data.
Raises:
ValueError: If the input is empty or only contains whitespace.
"""
try:
response = input(prompt)
if response.strip().lower() == "quit":
logger.info(
"User chose to quit the onboarding process."
)
exit(0)
if not response.strip():
raise ValueError(
f"{key.capitalize()} cannot be empty."
)
self.user_data[key] = response.strip()
self.save_data()
return response
except ValueError as e:
logger.warning(e)
self.ask_input(prompt, key)
except KeyboardInterrupt:
logger.warning(
"Onboarding process interrupted by the user."
)
exit(1)
def collect_user_info(self) -> None:
"""
Initiates the onboarding process by collecting the user's full name, first name, email,
Swarms API key, and system data. Additionally, it reminds the user to set their WORKSPACE_DIR environment variable.
"""
logger.info("Initiating swarms cloud onboarding process...")
self.ask_input(
"Enter your first name (or type 'quit' to exit): ",
"first_name",
)
self.ask_input(
"Enter your Last Name (or type 'quit' to exit): ",
"last_name",
)
self.ask_input(
"Enter your email (or type 'quit' to exit): ", "email"
)
workspace = self.ask_input(
"Enter your WORKSPACE_DIR: This is where logs, errors, and agent configurations will be stored (or type 'quit' to exit). Remember to set this as an environment variable: https://docs.swarms.world/en/latest/swarms/install/quickstart/ || ",
"workspace_dir",
)
os.environ["WORKSPACE_DIR"] = workspace
logger.info(
"Important: Please ensure you have set your WORKSPACE_DIR environment variable as per the instructions provided."
)
logger.info(
"Additionally, remember to add your API keys for your respective models in your .env file."
)
logger.success("Onboarding process completed successfully!")
def run(self) -> None:
"""
Main method to run the onboarding process. It handles unexpected errors and ensures
proper finalization.
"""
try:
self.collect_user_info()
except Exception as e:
logger.error("An unexpected error occurred: {}", e)
finally:
logger.info("Finalizing the onboarding process.")
# if __name__ == "__main__":
# onboarding = OnboardingProcess()
# onboarding.run()
|