|
2 | 2 | import json |
3 | 3 | import shlex |
4 | 4 | import sys |
| 5 | +from pathlib import Path |
5 | 6 | from typing import Optional |
6 | 7 |
|
7 | 8 | import typer |
@@ -344,6 +345,56 @@ def search( |
344 | 345 | typer.echo(f"{idx:<3} {snippet:<60} {uri:<40}") |
345 | 346 |
|
346 | 347 |
|
| 348 | +@app.command("download-model") |
| 349 | +def download_model( |
| 350 | + model_id: str = typer.Argument( |
| 351 | + ..., help="Hugging Face model ID (e.g., Qwen/Qwen3-Embedding-0.6B-GGUF)" |
| 352 | + ), |
| 353 | + gguf_file: str = typer.Argument( |
| 354 | + ..., help="GGUF filename to download (e.g., Qwen3-Embedding-0.6B-Q8_0.gguf)" |
| 355 | + ), |
| 356 | + local_dir: str = typer.Option( |
| 357 | + "./models", "--local-dir", "-d", help="Local directory to download to" |
| 358 | + ), |
| 359 | + revision: str = typer.Option( |
| 360 | + "main", "--revision", "-r", help="Model revision/branch to download from" |
| 361 | + ), |
| 362 | +): |
| 363 | + """Download a GGUF model file from Hugging Face""" |
| 364 | + try: |
| 365 | + from huggingface_hub import hf_hub_download |
| 366 | + except ImportError: |
| 367 | + typer.echo( |
| 368 | + "Error: huggingface_hub not found. Install with: pip install huggingface_hub" |
| 369 | + ) |
| 370 | + raise typer.Exit(1) |
| 371 | + |
| 372 | + # Create local directory structure |
| 373 | + local_path = Path(local_dir) / model_id |
| 374 | + local_path.mkdir(parents=True, exist_ok=True) |
| 375 | + |
| 376 | + typer.echo(f"Downloading {gguf_file} from {model_id}...") |
| 377 | + |
| 378 | + try: |
| 379 | + # Download the specific GGUF file |
| 380 | + downloaded_path = hf_hub_download( |
| 381 | + repo_id=model_id, |
| 382 | + filename=gguf_file, |
| 383 | + local_dir=str(local_path), |
| 384 | + revision=revision, |
| 385 | + ) |
| 386 | + |
| 387 | + final_path = Path(downloaded_path) |
| 388 | + typer.echo(f"Downloaded to: {final_path}") |
| 389 | + |
| 390 | + if final_path.exists(): |
| 391 | + typer.echo(f"File size: {final_path.stat().st_size / (1024*1024):.1f} MB") |
| 392 | + |
| 393 | + except Exception as e: |
| 394 | + typer.echo(f"Error downloading model: {e}") |
| 395 | + raise typer.Exit(1) |
| 396 | + |
| 397 | + |
347 | 398 | def repl_mode(): |
348 | 399 | """Interactive REPL mode""" |
349 | 400 | typer.echo("Entering interactive mode. Type 'help' for commands or 'exit' to quit.") |
|
0 commit comments