Files
Traffic-Intersection-Monito…/qt_app_pyside1/vlm_backend/model_downloader.py
2025-08-26 13:24:53 -07:00

175 lines
5.8 KiB
Python

import os
import sys
import logging
import time
import argparse
import json
from pathlib import Path
import subprocess
import shutil
import requests
import zipfile
import io
import tempfile
from tqdm import tqdm
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="[%(levelname)s] %(asctime)s.%(msecs)03d [%(name)s]: %(message)s",
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger('model_downloader')
def download_file(url, output_path, chunk_size=8192):
"""
Download a file from URL with progress bar.
Args:
url: URL to download from
output_path: Path to save the file
chunk_size: Size of chunks to download
Returns:
Path to the downloaded file
"""
try:
response = requests.get(url, stream=True)
response.raise_for_status()
# Get file size for progress bar
total_size = int(response.headers.get('content-length', 0))
# Show download progress
desc = f"Downloading {os.path.basename(url)}"
with open(output_path, 'wb') as f, tqdm(
desc=desc,
total=total_size,
unit='B',
unit_scale=True,
unit_divisor=1024,
) as bar:
for chunk in response.iter_content(chunk_size=chunk_size):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
bar.update(len(chunk))
return output_path
except Exception as e:
logger.error(f"Error downloading file: {str(e)}")
if os.path.exists(output_path):
os.remove(output_path)
raise e
def download_openvino_model(repo_id="ezelanza/llava-next-video-openvino", output_dir="./models"):
"""
Download pre-converted OpenVINO model from Hugging Face.
Args:
repo_id: Hugging Face repository ID
output_dir: Directory to save the downloaded model
Returns:
Path to the downloaded model directory
"""
# Create a model-specific output directory
model_id = repo_id.split('/')[-1].replace("-openvino", "")
output_path = Path(output_dir) / f"{model_id}_openvino_model"
output_path.mkdir(parents=True, exist_ok=True)
# Check if model already exists (look for XML and BIN files)
if list(output_path.glob("*.xml")) and list(output_path.glob("*.bin")):
logger.info(f"OpenVINO model already exists at {output_path}")
return output_path
try:
# Define files to download
files_to_download = [
"openvino_model.xml",
"openvino_model.bin",
"config.json",
"tokenizer_config.json",
"special_tokens_map.json",
"tokenizer.model"
]
# Base URL for raw files on Hugging Face
base_url = f"https://huggingface.co/{repo_id}/resolve/main"
# Download each file
for filename in files_to_download:
file_url = f"{base_url}/{filename}"
output_file = output_path / filename
try:
download_file(file_url, output_file)
logger.info(f"Successfully downloaded {filename}")
except Exception as e:
logger.warning(f"Could not download {filename}: {str(e)}")
# Continue with other files even if one fails
continue
# Create a model info file
model_info = {
"model_name": repo_id,
"download_date": time.strftime("%Y-%m-%d %H:%M:%S"),
"files": [f.name for f in output_path.glob("*") if f.is_file()]
}
with open(output_path / "model_info.json", "w") as f:
json.dump(model_info, f, indent=2)
logger.info(f"Model files downloaded to {output_path}")
return output_path
except Exception as e:
logger.error(f"Error downloading model: {str(e)}")
raise e
def download_vl_model(model_name="ezelanza/llava-next-video-openvino", output_dir="./models", precision=None):
"""
Download a Vision-Language model.
Args:
model_name: Name of the model identifier on Hugging Face
output_dir: Directory to save the model
precision: Not used in this implementation but kept for API compatibility
Returns:
Path to the downloaded model
"""
start_time = time.time()
logger.info(f"Starting download of {model_name}...")
# Create output directory if it doesn't exist
Path(output_dir).mkdir(parents=True, exist_ok=True)
# Download the OpenVINO model
model_path = download_openvino_model(model_name, output_dir)
total_time = time.time() - start_time
logger.info(f"Completed in {total_time:.2f} seconds. Model saved at {model_path}")
return model_path
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Download pre-converted Vision-Language models in OpenVINO format")
parser.add_argument("--model_name", type=str, default="ezelanza/llava-next-video-openvino",
help="Name of the model repository on Hugging Face Hub")
parser.add_argument("--output_dir", type=str, default="./models",
help="Directory to save the OpenVINO model")
args = parser.parse_args()
try:
model_path = download_vl_model(args.model_name, args.output_dir)
print(f"\nModel successfully downloaded to: {model_path}")
print(f"Files downloaded:")
for file in sorted(os.listdir(model_path)):
file_path = os.path.join(model_path, file)
size_mb = os.path.getsize(file_path) / (1024 * 1024)
print(f" - {file} ({size_mb:.2f} MB)")
except Exception as e:
print(f"\nError downloading model: {e}")
sys.exit(1)