import gradio as gr import time import os import torch import json import math import soundfile as sf from argparse import Namespace from transformers import Qwen2_5OmniModel, AutoTokenizer, AutoProcessor, BitsAndBytesConfig from src.llamafactory.model.loader import patch_processor from src.llamafactory.data.template import get_template_and_fix_tokenizer # ================= Configuration ================= MODEL_PATH = os.environ.get("ROMA_MODEL_PATH", "whole_model/model") FIXED_VIDEO_PATH = os.environ.get("ROMA_VIDEO", "videos/XzxRMH7G8Lk_360.0_510.0.mp4") FIXED_AUDIO_PATH = os.environ.get("ROMA_AUDIO", "audio/pa_audio/154.wav") DEVICE = "cuda" if torch.cuda.is_available() else "cpu" THRESHOLD = 0.6 print(f"Loading model from {MODEL_PATH} on {DEVICE}...") # ================= Model Loading ================= # Hardware-agnostic, env-driven loader. Defaults are Turing-safe (Quadro RTX 6000, sm_75): # ROMA_DTYPE=float16 (bf16 is not accelerated on Turing) # ROMA_ATTN=sdpa (FlashAttention-2 is unsupported on Turing; use eager if sdpa fails) # ROMA_LOAD_8BIT=0 (fp16 sharded across all visible GPUs via device_map=auto; set 1 for 1-GPU) _DTYPE = {"float16": torch.float16, "bfloat16": torch.bfloat16, "auto": "auto"}[os.environ.get("ROMA_DTYPE", "float16")] _load_kwargs = dict( torch_dtype=_DTYPE, device_map="auto", attn_implementation=os.environ.get("ROMA_ATTN", "sdpa"), trust_remote_code=True, ) if os.environ.get("ROMA_LOAD_8BIT", "0") == "1": _load_kwargs["quantization_config"] = BitsAndBytesConfig( load_in_8bit=True, # keep encoders, the gate (Speak Head) and the talker in fp16 for quality/correctness llm_int8_skip_modules=["talker", "token2wav", "visual", "audio_tower", "gate_head", "gate_mixer", "gate_head_pro_fc1", "gate_head_pro_fc2"], ) model = Qwen2_5OmniModel.from_pretrained(MODEL_PATH, **_load_kwargs) try: model.disable_talker() # demos only use model.thinker; frees memory. Best-effort (fork API may vary) except Exception: pass tokenizer = AutoTokenizer.from_pretrained( MODEL_PATH, use_fast=True, split_special_tokens=False, padding_side="left", trust_remote_code=True, cache_dir=None, revision='main', token=None ) processor_args_dict = { "image_max_pixels": 262144, "image_min_pixels": 1024, "image_do_pan_and_scan": False, "crop_to_patches": False, "video_max_pixels": 65536, "video_min_pixels": 256, "video_fps": 2.0, "video_maxlen": 14400, "audio_sampling_rate": 16000, "use_audio_in_video": True } processor_args = Namespace(**processor_args_dict) processor = AutoProcessor.from_pretrained(MODEL_PATH, trust_remote_code=True) patch_processor(processor, tokenizer, processor_args) template_args = Namespace(**{"template": "streaming_turn", "train_on_prompt": False, "tool_format": None}) template = get_template_and_fix_tokenizer(tokenizer, template_args) print("Model Loaded Successfully!") # ================= Helper Functions ================= def transform_example_format(example: dict) -> dict: return { "_prompt": example.get("query", []), "_response": example.get("ans", []), "_system": "", "_tools": example.get("tools", "") if example.get("tools") else "", "_images": example.get("images") if len(example.get("images"))!=0 else None, "_videos": example.get("videos") if len(example.get("videos"))!=0 else None, "_audios": [] } def get_multimodal_input_ids(prompt, response, system, tools, images, videos, audios): messages = template.mm_plugin.process_messages( [[prompt, response]], images, videos, audios, processor, mode="infer" ) encoded_pairs = template.encode_multiturn(tokenizer, messages, system, tools) inputs_list = [] for input_multimodal, _ in encoded_pairs: inputs_list.append(input_multimodal) return inputs_list # ================= Core Logic ================= def run_detection_stream(): """ 1. 预处理 2. 倒计时 3. 同步推理 """ if not os.path.exists(FIXED_VIDEO_PATH) or not os.path.exists(FIXED_AUDIO_PATH): yield "❌ 错误:找不到指定的视频或音频文件。" return # --- 阶段 1: 数据预处理 --- # 为了让前端看到状态,这里必须 yield log_text log_text = "" yield log_text print("⚙️ 正在后台加载视频与预处理数据,请稍候...\n") data = { "task": "action_prediction", "id": "3", "videos": [[FIXED_VIDEO_PATH]], # 使用配置的路径 "query": [ { "text": "