Video-Text-to-Text
Transformers
Safetensors
English
Chinese
moss_vl
feature-extraction
Realtime
Streaming
Video-Understanding
Image-Understanding
MOSS-VL
OpenMOSS
multimodal
video
vision-language
custom_code
Instructions to use OpenMOSS-Team/MOSS-VL-Realtime with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use OpenMOSS-Team/MOSS-VL-Realtime with Transformers:
# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("OpenMOSS-Team/MOSS-VL-Realtime", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Ascend NPU support: device-aware cache release, GIL-friendly idle wait, <=8-D vision processing, BICUBIC declaration
#3
by Joiin0392 - opened
- modeling_moss_vl.py +22 -5
- processing_moss_vl.py +6 -1
- video_processing_moss_vl.py +6 -1
modeling_moss_vl.py
CHANGED
|
@@ -2874,8 +2874,13 @@ class MossVLForConditionalGeneration(MossVLPreTrainedModel, GenerationMixin):
|
|
| 2874 |
|
| 2875 |
def stop_real_time_generate(self):
|
| 2876 |
gc.collect()
|
| 2877 |
-
|
| 2878 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2879 |
self.continue_generating = False
|
| 2880 |
|
| 2881 |
@staticmethod
|
|
@@ -3099,8 +3104,11 @@ class MossVLForConditionalGeneration(MossVLPreTrainedModel, GenerationMixin):
|
|
| 3099 |
break
|
| 3100 |
|
| 3101 |
if self.continue_generating and should_wait_for_new_input and not frames_to_process and not prompts_to_process:
|
| 3102 |
-
#
|
| 3103 |
-
#
|
|
|
|
|
|
|
|
|
|
| 3104 |
continue
|
| 3105 |
break
|
| 3106 |
|
|
@@ -3596,7 +3604,16 @@ class MossVLForConditionalGeneration(MossVLPreTrainedModel, GenerationMixin):
|
|
| 3596 |
and buf_list[-1] == invalid_token_id
|
| 3597 |
)
|
| 3598 |
if is_silence_or_ellipsis or is_complete_text or is_invalid_complete:
|
| 3599 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3600 |
token_buffer.clear()
|
| 3601 |
|
| 3602 |
input_ids = torch.cat([input_ids, next_tokens[:, None]], dim=-1)
|
|
|
|
| 2874 |
|
| 2875 |
def stop_real_time_generate(self):
|
| 2876 |
gc.collect()
|
| 2877 |
+
try:
|
| 2878 |
+
import torch_npu # noqa: F401
|
| 2879 |
+
if torch.npu.is_available():
|
| 2880 |
+
torch.npu.empty_cache()
|
| 2881 |
+
except ImportError:
|
| 2882 |
+
if torch.cuda.is_available():
|
| 2883 |
+
torch.cuda.empty_cache()
|
| 2884 |
self.continue_generating = False
|
| 2885 |
|
| 2886 |
@staticmethod
|
|
|
|
| 3104 |
break
|
| 3105 |
|
| 3106 |
if self.continue_generating and should_wait_for_new_input and not frames_to_process and not prompts_to_process:
|
| 3107 |
+
# GIL-friendly wait: a bare `continue` busy-spin monopolizes the GIL
|
| 3108 |
+
# and starves in-process siblings (in-process ASR decode inflates
|
| 3109 |
+
# ~150ms -> 40-80s while a realtime session idles in <|silence|>).
|
| 3110 |
+
# 20ms poll keeps input-detection latency negligible.
|
| 3111 |
+
time.sleep(0.02)
|
| 3112 |
continue
|
| 3113 |
break
|
| 3114 |
|
|
|
|
| 3604 |
and buf_list[-1] == invalid_token_id
|
| 3605 |
)
|
| 3606 |
if is_silence_or_ellipsis or is_complete_text or is_invalid_complete:
|
| 3607 |
+
# The end-of-buffer guard above only catches an INCOMPLETE
|
| 3608 |
+
# trailing char. Under sampling, a multi-byte char can also
|
| 3609 |
+
# break MID-string (the next token completes a different
|
| 3610 |
+
# char, orphaning the first char's tail bytes) — the
|
| 3611 |
+
# replacement char then stays in the text forever. Those
|
| 3612 |
+
# bytes are unrecoverable at this point: drop the broken
|
| 3613 |
+
# character instead of emitting mojibake.
|
| 3614 |
+
clean_text = decoded_text.replace("\ufffd", "")
|
| 3615 |
+
if clean_text:
|
| 3616 |
+
output_text_queue.put(clean_text)
|
| 3617 |
token_buffer.clear()
|
| 3618 |
|
| 3619 |
input_ids = torch.cat([input_ids, next_tokens[:, None]], dim=-1)
|
processing_moss_vl.py
CHANGED
|
@@ -164,12 +164,17 @@ class MossVLImageProcessorFast(Qwen2VLImageProcessorFast):
|
|
| 164 |
)
|
| 165 |
# Reorder dimensions to group grid and patch information for subsequent flattening.
|
| 166 |
# (batch, grid_t, grid_h, grid_w, merge_h, merge_w, channel, temp_patch_size, patch_h, patch_w)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
patches = patches.permute(0, 1, 4, 7, 5, 8, 3, 2, 6, 9)
|
| 168 |
flatten_patches = patches.reshape(
|
| 169 |
batch_size,
|
| 170 |
grid_t * grid_h * grid_w,
|
| 171 |
channel * temporal_patch_size * patch_size * patch_size,
|
| 172 |
-
)
|
| 173 |
|
| 174 |
processed_images_grouped[shape] = flatten_patches
|
| 175 |
processed_grids[shape] = [[grid_t, grid_h, grid_w]] * batch_size
|
|
|
|
| 164 |
)
|
| 165 |
# Reorder dimensions to group grid and patch information for subsequent flattening.
|
| 166 |
# (batch, grid_t, grid_h, grid_w, merge_h, merge_w, channel, temp_patch_size, patch_h, patch_w)
|
| 167 |
+
# NPU ops support at most 8-D tensors; route the 10-D permute+reshape
|
| 168 |
+
# through CPU there. CUDA handles 10-D natively — keep it on-device.
|
| 169 |
+
patches_device = patches.device
|
| 170 |
+
if patches_device.type == "npu":
|
| 171 |
+
patches = patches.cpu()
|
| 172 |
patches = patches.permute(0, 1, 4, 7, 5, 8, 3, 2, 6, 9)
|
| 173 |
flatten_patches = patches.reshape(
|
| 174 |
batch_size,
|
| 175 |
grid_t * grid_h * grid_w,
|
| 176 |
channel * temporal_patch_size * patch_size * patch_size,
|
| 177 |
+
).to(patches_device)
|
| 178 |
|
| 179 |
processed_images_grouped[shape] = flatten_patches
|
| 180 |
processed_grids[shape] = [[grid_t, grid_h, grid_w]] * batch_size
|
video_processing_moss_vl.py
CHANGED
|
@@ -1147,12 +1147,17 @@ class MossVLVideoProcessor(BaseVideoProcessor):
|
|
| 1147 |
merge_size,
|
| 1148 |
patch_size,
|
| 1149 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1150 |
patches = patches.permute(0, 1, 4, 7, 5, 8, 3, 2, 6, 9)
|
| 1151 |
flatten_patches = patches.reshape(
|
| 1152 |
batch_size,
|
| 1153 |
grid_t * grid_h * grid_w,
|
| 1154 |
channel * temporal_patch_size * patch_size * patch_size,
|
| 1155 |
-
)
|
| 1156 |
|
| 1157 |
processed_videos_grouped[shape] = flatten_patches
|
| 1158 |
processed_grids[shape] = [[grid_t, grid_h, grid_w]] * batch_size
|
|
|
|
| 1147 |
merge_size,
|
| 1148 |
patch_size,
|
| 1149 |
)
|
| 1150 |
+
patches_device = patches.device
|
| 1151 |
+
# NPU: max 8D tensors — route the 10D permute+reshape through CPU.
|
| 1152 |
+
# CUDA handles 10D natively — keep it on-device.
|
| 1153 |
+
if patches_device.type == "npu":
|
| 1154 |
+
patches = patches.cpu()
|
| 1155 |
patches = patches.permute(0, 1, 4, 7, 5, 8, 3, 2, 6, 9)
|
| 1156 |
flatten_patches = patches.reshape(
|
| 1157 |
batch_size,
|
| 1158 |
grid_t * grid_h * grid_w,
|
| 1159 |
channel * temporal_patch_size * patch_size * patch_size,
|
| 1160 |
+
).to(patches_device)
|
| 1161 |
|
| 1162 |
processed_videos_grouped[shape] = flatten_patches
|
| 1163 |
processed_grids[shape] = [[grid_t, grid_h, grid_w]] * batch_size
|