Spaces:
Sleeping
Sleeping
| # app.py | |
| """ | |
| Точка входа для Hugging Face Spaces. | |
| Выполняет загрузку ассетов, вызывает штатный скрипт запуска vLLM | |
| и инициализирует Gradio-интерфейс. | |
| """ | |
| import sys | |
| import os | |
| import logging | |
| import subprocess | |
| from pathlib import Path | |
| from huggingface_hub import snapshot_download | |
| # Настройка логирования | |
| logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s") | |
| logger: logging.Logger = logging.getLogger(__name__) | |
| def download_assets(repo_id: str, local_dir: Path, repo_type: str = "dataset") -> None: | |
| """Скачивает ассеты из указанного репозитория Hugging Face.""" | |
| if not local_dir.exists() or not any(local_dir.iterdir()): | |
| logger.info(f"📥 Начинаем загрузку ассетов из {repo_id}...") | |
| local_dir.mkdir(parents=True, exist_ok=True) | |
| try: | |
| snapshot_download( | |
| repo_id=repo_id, | |
| repo_type=repo_type, | |
| local_dir=str(local_dir), | |
| allow_patterns=["*.glb", "*.gltf", "*fake*"], | |
| local_dir_use_symlinks=False | |
| ) | |
| logger.info("✅ Ассеты успешно скачаны!") | |
| except Exception as e: | |
| logger.error(f"❌ Ошибка при скачивании ассетов: {e}") | |
| raise | |
| else: | |
| logger.info("⚡ Ассеты уже существуют локально, скачивание не требуется.") | |
| def init_space() -> None: | |
| """Инициализирует пути проекта, подготавливает ассеты и запускает сервисы.""" | |
| project_root: Path = Path(__file__).resolve().parent | |
| # 1. НАСТРАИВАЕМ ПУТИ | |
| if str(project_root) not in sys.path: | |
| sys.path.append(str(project_root)) | |
| src_dir: Path = project_root / "src" | |
| if str(src_dir) not in sys.path: | |
| sys.path.append(str(src_dir)) | |
| # 2. СКАЧИВАЕМ АССЕТЫ | |
| assets_dir: Path = project_root / "assets" | |
| download_assets( | |
| repo_id="emb-ai/RoboBenchMart_assets", | |
| local_dir=assets_dir, | |
| repo_type="dataset" | |
| ) | |
| # 3. ЗАПУСКАЕМ vLLM ЧЕРЕЗ ШТАТНЫЙ СКРИПТ | |
| logger.info("🚀 Запуск фонового сервера vLLM через launch_llm_server.py...") | |
| launcher_path = project_root / "scripts" / "launch_llm_server.py" | |
| if launcher_path.exists(): | |
| try: | |
| # subprocess.run заблокирует выполнение app.py, пока лаунчер не сделает exit() | |
| # Так как лаунчер ждет статуса 200 OK от health-эндпоинта, UI не запустится раньше времени. | |
| subprocess.run([sys.executable, str(launcher_path)], check=True) | |
| logger.info("✅ Лаунчер отработал успешно, бэкенд готов!") | |
| except subprocess.CalledProcessError as e: | |
| logger.error(f"❌ Ошибка при запуске сервера vLLM. Код возврата: {e.returncode}") | |
| sys.exit(1) | |
| else: | |
| logger.error(f"❌ Скрипт лаунчера не найден по пути: {launcher_path}") | |
| sys.exit(1) | |
| # 4. ЗАПУСКАЕМ UI | |
| from scripts.launch_ui import main | |
| logger.info("🎨 Запуск основного интерфейса Gradio...") | |
| main() | |
| if __name__ == "__main__": | |
| init_space() |