| import os
|
| import sys
|
| import atexit
|
| import asyncio
|
| import argparse
|
| import subprocess
|
| from pathlib import Path
|
| import tomli
|
| import uvicorn
|
| from loguru import logger
|
| from upgrade_codes.upgrade_manager import UpgradeManager
|
|
|
| from src.open_llm_vtuber.server import WebSocketServer
|
| from src.open_llm_vtuber.config_manager import Config, read_yaml, validate_config
|
|
|
| os.environ["HF_HOME"] = str(Path(__file__).parent / "models")
|
| os.environ["MODELSCOPE_CACHE"] = str(Path(__file__).parent / "models")
|
|
|
| upgrade_manager = UpgradeManager()
|
|
|
|
|
| def get_version() -> str:
|
| with open("pyproject.toml", "rb") as f:
|
| pyproject = tomli.load(f)
|
| return pyproject["project"]["version"]
|
|
|
|
|
| def init_logger(console_log_level: str = "INFO") -> None:
|
| logger.remove()
|
|
|
| logger.add(
|
| sys.stderr,
|
| level=console_log_level,
|
| format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | {message}",
|
| colorize=True,
|
| )
|
|
|
|
|
| logger.add(
|
| "logs/debug_{time:YYYY-MM-DD}.log",
|
| rotation="10 MB",
|
| retention="30 days",
|
| level="DEBUG",
|
| format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {name}:{function}:{line} | {message} | {extra}",
|
| backtrace=True,
|
| diagnose=True,
|
| )
|
|
|
|
|
| def check_frontend_submodule(lang=None):
|
| """
|
| Check if the frontend submodule is initialized. If not, attempt to initialize it.
|
| If initialization fails, log an error message.
|
| """
|
| if lang is None:
|
| lang = upgrade_manager.lang
|
|
|
| frontend_path = Path(__file__).parent / "frontend" / "index.html"
|
| if not frontend_path.exists():
|
| if lang == "zh":
|
| logger.warning("未找到前端子模块,正在尝试初始化子模块...")
|
| else:
|
| logger.warning(
|
| "Frontend submodule not found, attempting to initialize submodules..."
|
| )
|
|
|
| try:
|
| subprocess.run(
|
| ["git", "submodule", "update", "--init", "--recursive"], check=True
|
| )
|
| if frontend_path.exists():
|
| if lang == "zh":
|
| logger.info("👍 前端子模块(和其他子模块)初始化成功。")
|
| else:
|
| logger.info(
|
| "👍 Frontend submodule (and other submodules) initialized successfully."
|
| )
|
| else:
|
| if lang == "zh":
|
| logger.critical(
|
| '子模块初始化失败。\n你之后可能会在浏览器中看到 {{"detail":"Not Found"}} 的错误提示。请检查我们的快速入门指南和常见问题页面以获取更多信息。'
|
| )
|
| logger.error(
|
| "初始化子模块后,前端文件仍然缺失。\n"
|
| + "你是否手动更改或删除了 `frontend` 文件夹?\n"
|
| + "它是一个 Git 子模块 - 你不应该直接修改它。\n"
|
| + "如果你这样做了,请使用 `git restore frontend` 丢弃你的更改,然后再试一次。\n"
|
| )
|
| else:
|
| logger.critical(
|
| 'Failed to initialize submodules. \nYou might see {{"detail":"Not Found"}} in your browser. Please check our quick start guide and common issues page from our documentation.'
|
| )
|
| logger.error(
|
| "Frontend files are still missing after submodule initialization.\n"
|
| + "Did you manually change or delete the `frontend` folder? \n"
|
| + "It's a Git submodule — you shouldn't modify it directly. \n"
|
| + "If you did, discard your changes with `git restore frontend`, then try again.\n"
|
| )
|
| except Exception as e:
|
| if lang == "zh":
|
| logger.critical(
|
| f'初始化子模块失败: {e}。\n怀疑你跟 GitHub 之间有网络问题。你之后可能会在浏览器中看到 {{"detail":"Not Found"}} 的错误提示。请检查我们的快速入门指南和常见问题页面以获取更多信息。\n'
|
| )
|
| else:
|
| logger.critical(
|
| f'Failed to initialize submodules: {e}. \nYou might see {{"detail":"Not Found"}} in your browser. Please check our quick start guide and common issues page from our documentation.\n'
|
| )
|
|
|
|
|
| def parse_args():
|
| parser = argparse.ArgumentParser(description="Open-LLM-VTuber Server")
|
| parser.add_argument("--verbose", action="store_true", help="Enable verbose logging")
|
| parser.add_argument(
|
| "--hf_mirror", action="store_true", help="Use Hugging Face mirror"
|
| )
|
| return parser.parse_args()
|
|
|
|
|
| @logger.catch
|
| def run(console_log_level: str):
|
| init_logger(console_log_level)
|
| logger.info(f"Open-LLM-VTuber, version v{get_version()}")
|
|
|
|
|
| lang = upgrade_manager.lang
|
|
|
|
|
| check_frontend_submodule(lang)
|
|
|
|
|
| try:
|
| upgrade_manager.sync_user_config()
|
| except Exception as e:
|
| logger.error(f"Error syncing user config: {e}")
|
|
|
| atexit.register(WebSocketServer.clean_cache)
|
|
|
|
|
| config: Config = validate_config(read_yaml("conf.yaml"))
|
| server_config = config.system_config
|
|
|
| if server_config.enable_proxy:
|
| logger.info("Proxy mode enabled - /proxy-ws endpoint will be available")
|
|
|
|
|
| server = WebSocketServer(config=config)
|
|
|
|
|
| logger.info("Initializing server context...")
|
| try:
|
| asyncio.run(server.initialize())
|
| logger.info("Server context initialized successfully.")
|
| except Exception as e:
|
| logger.error(f"Failed to initialize server context: {e}")
|
| sys.exit(1)
|
|
|
|
|
| logger.info(f"Starting server on {server_config.host}:{server_config.port}")
|
| uvicorn.run(
|
| app=server.app,
|
| host=server_config.host,
|
| port=server_config.port,
|
| log_level=console_log_level.lower(),
|
| )
|
|
|
|
|
| if __name__ == "__main__":
|
| args = parse_args()
|
| console_log_level = "DEBUG" if args.verbose else "INFO"
|
| if args.verbose:
|
| logger.info("Running in verbose mode")
|
| else:
|
| logger.info(
|
| "Running in standard mode. For detailed debug logs, use: uv run run_server.py --verbose"
|
| )
|
| if args.hf_mirror:
|
| os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
|
| run(console_log_level=console_log_level)
|
|
|