| 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) |
|
|