13
13
def get_env_var (key : str , * , default : Any = None , var_type : Type = str ) -> Any :
14
14
"""Get environment variable with type conversion and validation."""
15
15
value = os .environ .get (key )
16
-
16
+
17
17
if value is None :
18
18
try :
19
19
from .cli .config import get_config_value
@@ -22,13 +22,13 @@ def get_env_var(key: str, *, default: Any = None, var_type: Type = str) -> Any:
22
22
config_key = "ngrok_auth_token"
23
23
elif key == HF_TOKEN_ENV :
24
24
config_key = "huggingface_token"
25
-
25
+
26
26
config_value = get_config_value (config_key )
27
27
if config_value is not None :
28
28
value = config_value
29
29
except :
30
30
pass
31
-
31
+
32
32
if value is None :
33
33
return default
34
34
@@ -61,20 +61,20 @@ def get_ngrok_token() -> Optional[str]:
61
61
def save_config (config : Dict [str , Any ]):
62
62
"""Save configuration to file"""
63
63
from .cli .config import ensure_config_dir , CONFIG_FILE
64
-
64
+
65
65
ensure_config_dir ()
66
-
66
+
67
67
# Ensure tokens are stored as proper strings
68
68
if "ngrok_auth_token" in config :
69
69
token = str (config ["ngrok_auth_token" ]).strip ()
70
70
config ["ngrok_auth_token" ] = token
71
71
set_env_var (NGROK_TOKEN_ENV , token )
72
-
72
+
73
73
if "huggingface_token" in config :
74
74
token = str (config ["huggingface_token" ]).strip ()
75
75
config ["huggingface_token" ] = token
76
76
set_env_var (HF_TOKEN_ENV , token )
77
-
77
+
78
78
try :
79
79
with open (CONFIG_FILE , "w" ) as f :
80
80
json .dump (config , f , indent = 2 )
@@ -159,18 +159,18 @@ def can_run_model(model_id: str) -> bool:
159
159
160
160
# Get available memory with a buffer
161
161
available_ram = (psutil .virtual_memory ().available / (1024 ** 3 )) * 0.8 # 80% of available RAM in GB
162
-
162
+
163
163
# Adjust requirements based on optimizations
164
164
if get_env_var ("LOCALLAB_ENABLE_QUANTIZATION" , default = False , var_type = bool ):
165
165
# Quantization reduces memory usage
166
166
requirements ["min_ram" ] *= 0.5
167
167
if "min_vram" in requirements :
168
168
requirements ["min_vram" ] *= 0.5
169
-
169
+
170
170
if get_env_var ("LOCALLAB_ENABLE_CPU_OFFLOADING" , default = False , var_type = bool ):
171
171
# CPU offloading allows running with less RAM
172
172
requirements ["min_ram" ] *= 0.7
173
-
173
+
174
174
# Check RAM
175
175
if available_ram < requirements ["min_ram" ]:
176
176
logger .warning (f"Insufficient RAM. Available: { available_ram :.1f} GB, Required: { requirements ['min_ram' ]} GB" )
@@ -324,18 +324,26 @@ def estimate_model_requirements(model_id: str) -> Dict[str, float]:
324
324
ENABLE_FILE_LOGGING = get_env_var (
325
325
"LOCALLAB_ENABLE_FILE_LOGGING" , default = False , var_type = bool )
326
326
327
- # Configure logging
328
- logging . basicConfig (
329
- level = getattr ( logging , LOG_LEVEL . upper ()),
330
- format = LOG_FORMAT ,
331
- handlers = [
332
- logging . StreamHandler () if ENABLE_CONSOLE_LOGGING else logging . NullHandler (),
333
- logging . FileHandler (
334
- LOG_FILE ) if ENABLE_FILE_LOGGING and LOG_FILE else logging .NullHandler ( )
335
- ]
336
- )
327
+ # Import our logger instead of using basicConfig
328
+ # This prevents duplicate logging configuration
329
+ from . logger import get_logger
330
+
331
+ # Set up file logging if enabled
332
+ if ENABLE_FILE_LOGGING and LOG_FILE :
333
+ # Add file handler to root logger
334
+ file_handler = logging .FileHandler ( LOG_FILE )
335
+ file_formatter = logging . Formatter ( LOG_FORMAT )
336
+ file_handler . setFormatter ( file_formatter )
337
337
338
- logger = logging .getLogger ("locallab" )
338
+ # Add to root logger
339
+ root_logger = logging .getLogger ()
340
+ root_logger .addHandler (file_handler )
341
+
342
+ # Set log level
343
+ root_logger .setLevel (getattr (logging , LOG_LEVEL .upper ()))
344
+
345
+ # Get the logger for this module
346
+ logger = get_logger ("locallab" )
339
347
340
348
341
349
def get_system_resources () -> Dict [str , Any ]:
@@ -563,7 +571,7 @@ def get_env_var(key: str, *, default: Any = None, var_type: Type = str) -> Any:
563
571
"""
564
572
# First check environment variables
565
573
value = os .environ .get (key )
566
-
574
+
567
575
# If not found in environment, try the config file
568
576
if value is None :
569
577
try :
@@ -574,14 +582,14 @@ def get_env_var(key: str, *, default: Any = None, var_type: Type = str) -> Any:
574
582
config_key = key [9 :].lower ()
575
583
else :
576
584
config_key = key .lower ()
577
-
585
+
578
586
config_value = get_config_value (config_key )
579
587
if config_value is not None :
580
588
value = config_value
581
589
except (ImportError , ModuleNotFoundError ):
582
590
# If the config module isn't available yet, just use the environment variable
583
591
pass
584
-
592
+
585
593
# If still not found, use default
586
594
if value is None :
587
595
return default
@@ -602,7 +610,7 @@ def get_hf_token(interactive: bool = False) -> Optional[str]:
602
610
"""Get HuggingFace token from environment or config"""
603
611
# First check environment
604
612
token = os .environ .get ("HUGGINGFACE_TOKEN" , "" ).strip ()
605
-
613
+
606
614
# Then check config
607
615
if not token :
608
616
try :
@@ -613,43 +621,43 @@ def get_hf_token(interactive: bool = False) -> Optional[str]:
613
621
os .environ ["HUGGINGFACE_TOKEN" ] = token
614
622
except :
615
623
pass
616
-
624
+
617
625
# If interactive and still no token, prompt user
618
626
if not token and interactive :
619
627
try :
620
628
click .echo ("\n 🔑 HuggingFace token is required for accessing this model." )
621
629
click .echo ("Get your token from: https://huggingface.co/settings/tokens" )
622
-
630
+
623
631
token = click .prompt (
624
632
"Enter your HuggingFace token" ,
625
633
type = str ,
626
634
default = "" ,
627
635
show_default = False
628
636
).strip ()
629
-
637
+
630
638
if token :
631
639
if len (token ) < 20 :
632
640
click .echo ("\n ❌ Invalid token format. Please check your token." )
633
641
return None
634
-
642
+
635
643
click .echo (f"\n ✅ Token saved: { token } " )
636
644
os .environ ["HUGGINGFACE_TOKEN" ] = token
637
-
645
+
638
646
# Save to config
639
647
from .cli .config import set_config_value
640
648
set_config_value ("huggingface_token" , token )
641
649
else :
642
650
click .echo ("\n Skipping token..." )
643
651
except :
644
652
pass
645
-
653
+
646
654
return token
647
655
648
656
def get_ngrok_token () -> Optional [str ]:
649
657
"""Get ngrok token from environment or config"""
650
658
# First check environment
651
659
token = os .environ .get ("NGROK_AUTHTOKEN" , "" ).strip ()
652
-
660
+
653
661
# Then check config
654
662
if not token :
655
663
try :
@@ -660,26 +668,26 @@ def get_ngrok_token() -> Optional[str]:
660
668
os .environ ["NGROK_AUTHTOKEN" ] = token
661
669
except :
662
670
pass
663
-
671
+
664
672
return token
665
673
666
674
def save_config (config : Dict [str , Any ]):
667
675
"""Save configuration to file"""
668
676
from .cli .config import ensure_config_dir , CONFIG_FILE
669
-
677
+
670
678
ensure_config_dir ()
671
-
679
+
672
680
# Ensure tokens are stored as proper strings
673
681
if "ngrok_auth_token" in config :
674
682
token = str (config ["ngrok_auth_token" ]).strip ()
675
683
config ["ngrok_auth_token" ] = token
676
684
set_env_var (NGROK_TOKEN_ENV , token )
677
-
685
+
678
686
if "huggingface_token" in config :
679
687
token = str (config ["huggingface_token" ]).strip ()
680
688
config ["huggingface_token" ] = token
681
689
set_env_var (HF_TOKEN_ENV , token )
682
-
690
+
683
691
try :
684
692
with open (CONFIG_FILE , "w" ) as f :
685
693
json .dump (config , f , indent = 2 )
0 commit comments