Skip to content

Commit cc7368f

Browse files
committed
Improved UX of HF token
1 parent 8a9302c commit cc7368f

File tree

4 files changed

+48
-12
lines changed

4 files changed

+48
-12
lines changed

locallab/cli/interactive.py

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -269,30 +269,49 @@ def prompt_for_config(use_ngrok: bool = None, port: int = None, ngrok_auth_token
269269
os.environ["LOCALLAB_LOG_FILE"] = log_file
270270
config["log_file"] = log_file
271271

272-
# Ask about HuggingFace token
272+
# Ask about HuggingFace token with improved UX
273273
hf_token = config.get("huggingface_token") or os.environ.get("HUGGINGFACE_TOKEN")
274274
if not hf_token or force_reconfigure:
275-
click.echo("\n🔑 Enter your HuggingFace token (optional)")
276-
click.echo(" Get your token from: https://huggingface.co/settings/tokens")
277-
click.echo(" Press Enter to skip or paste your token (it will be hidden): ", nl=False)
275+
click.echo("\n�� HuggingFace Token Configuration")
276+
click.echo("───────────────────────────────")
277+
click.echo("A token is required to download models like microsoft/phi-2")
278+
click.echo("Get your token from: https://huggingface.co/settings/tokens")
278279

279-
# Read token character by character
280+
if hf_token:
281+
click.echo(f"\nCurrent token: {hf_token[:4]}...{hf_token[-4:]}")
282+
if not click.confirm("Would you like to update your token?", default=False):
283+
click.echo("Keeping existing token...")
284+
return config
285+
286+
click.echo("\nEnter your HuggingFace token (press Enter to skip): ", nl=False)
287+
288+
# Read token character by character for secure input
280289
chars = []
281290
while True:
282291
char = click.getchar()
283292
if char in ('\r', '\n'):
284293
break
285294
chars.append(char)
286-
click.echo('*', nl=False) # Show * for each character
295+
click.echo('*', nl=False)
287296

288297
hf_token = ''.join(chars)
289298

290299
if hf_token:
291-
click.echo("\n✅ Token saved!")
300+
# Validate token format
301+
if len(hf_token) < 20: # Basic validation
302+
click.echo("\n❌ Invalid token format. Token should be longer than 20 characters.")
303+
click.echo("Please check your token and try again.")
304+
return config
305+
306+
click.echo("\n✅ Token saved successfully!")
292307
os.environ["HUGGINGFACE_TOKEN"] = hf_token
293308
config["huggingface_token"] = hf_token
309+
310+
# Save immediately to ensure it's persisted
311+
from .config import save_config
312+
save_config(config)
294313
else:
295-
click.echo("\nSkipping HuggingFace token...")
296-
314+
click.echo("\n⚠️ No token provided. Some models may not be accessible.")
315+
297316
click.echo("\n✅ Configuration complete!\n")
298317
return config

locallab/config.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ def get_hf_token(interactive: bool = False) -> Optional[str]:
531531
# If interactive and still no token, prompt user
532532
if not token and interactive:
533533
try:
534-
click.echo("\n🔑 HuggingFace token is recommended for better model access.")
534+
click.echo("\n🔑 HuggingFace token is required for accessing this model.")
535535
click.echo("Get your token from: https://huggingface.co/settings/tokens")
536536
click.echo("Enter token (press Enter to skip): ", nl=False)
537537

@@ -546,8 +546,16 @@ def get_hf_token(interactive: bool = False) -> Optional[str]:
546546

547547
token = ''.join(chars)
548548
if token:
549+
if len(token) < 20: # Basic validation
550+
click.echo("\n❌ Invalid token format. Please check your token.")
551+
return None
552+
549553
click.echo("\n✅ Token saved!")
550554
os.environ["HUGGINGFACE_TOKEN"] = token
555+
556+
# Save to config
557+
from .cli.config import set_config_value
558+
set_config_value("huggingface_token", token)
551559
else:
552560
click.echo("\nSkipping token...")
553561
except:

locallab/model_manager.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,17 @@ async def load_model(self, model_id: str) -> bool:
255255
start_time = time.time()
256256
logger.info(f"\n{Fore.CYAN}Loading model: {model_id}{Style.RESET_ALL}")
257257

258+
# Get and validate HuggingFace token
258259
from .config import get_hf_token
259-
hf_token = get_hf_token(interactive=True)
260+
hf_token = get_hf_token(interactive=False) # Don't prompt during model loading
261+
262+
if not hf_token and model_id in ["microsoft/phi-2"]: # Add other gated models here
263+
logger.error(f"{Fore.RED}This model requires authentication. Please configure your HuggingFace token first.{Style.RESET_ALL}")
264+
logger.info(f"{Fore.YELLOW}You can set your token by running: locallab config{Style.RESET_ALL}")
265+
raise HTTPException(
266+
status_code=401,
267+
detail="HuggingFace token required for this model. Run 'locallab config' to set up."
268+
)
260269

261270
if self.model is not None:
262271
prev_model = self.current_model

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setup(
77
name="locallab",
8-
version="0.4.29",
8+
version="0.4.30",
99
packages=find_packages(include=["locallab", "locallab.*"]),
1010
install_requires=[
1111
"fastapi>=0.95.0,<1.0.0",

0 commit comments

Comments
 (0)