Files
2026-07-13 13:16:54 +08:00

1232 lines
57 KiB
Python

# Copyright (c) 2025 ByteDance Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# coding: utf-8
import json
import os
from typing import Any, Dict, List
import sys
import numpy as np
import torch
from torch.utils.data import Dataset
import decord
from decord import VideoReader
from PIL import Image
from data.video.sampler.utils import FRAME_SAMPLER_TYPES
from data.video.sampler.frames import FrameSamplerOutput
from data.transforms import VideoTransform
from data.data_utils import (
get_flattened_position_ids_extrapolate_video,
len2weight,
patchify_video_with_merge,
)
from data.system_prompt_render import render_qwenvl_prompt, expand_and_index_by_token_ids_new
from data.common import generate_system_prompt
from modeling.qwen2 import Qwen2Tokenizer
from config.config_factory import ModelArguments, DataArguments, TrainingArguments
sample_task_map = {
't2v': 0,
'idip': 1,
'edit': 2,
'refedit': 3,
}
modality_map = {
'system_prompt': -1,
'text': 0,
'noise': 1,
'ref_source': 2,
'ref_image': 3,
'ref_vit': 4
}
class ValidationDataset(Dataset):
def __init__(
self,
jsonl_path: str,
tokenizer: Qwen2Tokenizer,
data_args: DataArguments,
model_args: ModelArguments,
training_args: TrainingArguments,
new_token_ids: Dict[str, int],
dataset_config: None,
local_rank: int = 0,
world_size: int = 1,
):
"""
Initialize the validation dataset.
Args:
jsonl_path: Path to the JSONL file.
tokenizer: Tokenizer instance.
"""
self.jsonl_path = jsonl_path
self.tokenizer = tokenizer
self.new_token_ids = new_token_ids
try:
full_data = self._read_jsonl()
except:
with open(jsonl_path, 'r', encoding='utf-8') as f:
full_data = json.load(f)
if isinstance(full_data, dict):
full_data = [{"index": self.pro_index(index), "data": prompt} for index, prompt in full_data.items()]
if world_size > 1:
self.data = full_data[local_rank::world_size]
print(f"Rank {local_rank}/{world_size} will process {len(self.data)} samples")
else:
self.data = full_data
self.data_config = dataset_config
self.bos_token_id = self.new_token_ids["bos_token_id"]
self.eos_token_id = self.new_token_ids["eos_token_id"]
self.start_of_image = self.new_token_ids["start_of_image"]
self.end_of_image = self.new_token_ids["end_of_image"]
self.image_token_id = self.new_token_ids["image_token_id"]
try:
max_duration = self.data_config.max_duration
except:
max_duration = 6.0
video_frame_sampler_params = {"temporal": 4, "sample_fps": 12, "max_duration": max_duration, "assert_seconds": False, "truncate": False}
self.frame_sampler = FRAME_SAMPLER_TYPES["multi_clips"](**video_frame_sampler_params)
self.cpu_count = os.cpu_count() or 1
if self.data_config.resolution in ["video_192p", "image_256res"]:
resolution_vae = 256
resolution_vit = 224
elif self.data_config.resolution == "image_512res":
resolution_vae = 512
resolution_vit = 448
elif self.data_config.resolution == "image_768res":
resolution_vae = 768
resolution_vit = 672
elif self.data_config.resolution == "video_360p":
resolution_vae = 480
resolution_vit = 476
elif self.data_config.resolution == "video_480p":
resolution_vae = 640
resolution_vit = 616
else:
raise ValueError(f"Unknown resolution: {self.data_config.resolution}")
video_transform_args = {
"resolution": resolution_vae,
"mode": "bucket",
"divisible_crop_size": 16,
"stride_spatial": 16,
"stride_temporal": 4,
"aspect_ratios": ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"],
"mean": 0.5,
"std": 0.5,
}
self.transform = VideoTransform(**video_transform_args)
vit_video_transform_args = {
"resolution": resolution_vit,
"mode": "bucket",
"divisible_crop_size": 28,
"aspect_ratios": ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"],
"mean": [0.48145466, 0.4578275, 0.40821073],
"std": [0.26862954, 0.26130258, 0.27577711],
}
self.vit_transform = VideoTransform(**vit_video_transform_args)
self.sample = self.set_sequence_status()
self.frame_condition_idx = []
if hasattr(self.data_config, 'system_prompt_type'):
self.system_prompt_type = self.data_config.system_prompt_type
else:
self.system_prompt_type = 'SP0'
def pro_index(self, index: int):
if isinstance(index, str):
for x in ['.mp4', '.jpg', '.png', '.jpeg']:
index = index.replace(x, "")
return int(index)
def set_sequence_status(self):
sequence_status = dict(
curr=0,
sample_lens=[],
sample_type=[],
sample_N_target=[],
packed_position_ids=[],
nested_attention_masks=[],
split_lens=[],
attn_modes=[],
packed_text_ids=[],
packed_text_indexes=[],
packed_label_ids=[],
ce_loss_indexes=[],
ce_loss_weights=[],
vae_image_tensors=[],
vae_video_tensors=[],
packed_latent_position_ids=[],
vae_latent_shapes=[],
packed_vae_token_indexes=[],
packed_timesteps=[],
mse_loss_indexes=[],
packed_vit_tokens=[],
vit_token_seqlens=[],
packed_vit_position_ids=[],
packed_vit_token_indexes=[],
vit_video_grid_thw=[],
vae_video_grid_thw=[],
video_grid_thw=[],
vit_video_tensors=[],
vae_video_latent=[],
vae_data_mode=[],
vit_data_mode=[],
sample_task=[],
sample_modality=[],
save_fps=12,
)
return sequence_status
def _read_jsonl(self) -> List[Dict[str, Any]]:
"""Read the JSONL file."""
data = []
with open(self.jsonl_path, "r", encoding="utf-8") as f:
for line in f:
data.append(json.loads(line.strip()))
return data
def _maybe_enhance_t2v_prompt(self, prompt: str) -> str:
if self.data_config.task != "t2v":
return prompt
if not getattr(self.data_config, "enhance_prompt", False):
return prompt
from common.utils.caption_rewrite import has_rewrite_api_key, rewrite_prompt
if not has_rewrite_api_key():
return prompt
try:
enhanced_prompt = rewrite_prompt(prompt)
except Exception as exc:
print(f"[enhance_prompt][t2v][warning] prompt rewrite failed, use original prompt. error={exc}")
return prompt
print(f"[enhance_prompt][t2v][original] {prompt}")
print(f"[enhance_prompt][t2v][rewritten] {enhanced_prompt}")
return enhanced_prompt
def _maybe_enhance_i2v_prompt(self, prompt: str, image_path: str) -> str:
if "i2v" not in self.data_config.task:
return prompt
if not getattr(self.data_config, "enhance_prompt", False):
return prompt
from common.utils.caption_rewrite import has_rewrite_api_key, rewrite_i2v_prompt
if not has_rewrite_api_key():
return prompt
try:
enhanced_prompt = rewrite_i2v_prompt(prompt, image_path=image_path)
except Exception as exc:
print(f"[enhance_prompt][i2v][warning] prompt rewrite failed, use original prompt. error={exc}")
return prompt
print(f"[enhance_prompt][i2v][image] {image_path}")
print(f"[enhance_prompt][i2v][original] {prompt}")
print(f"[enhance_prompt][i2v][rewritten] {enhanced_prompt}")
return enhanced_prompt
def __len__(self) -> int:
return len(self.data)
@staticmethod
def _read_decord(video: VideoReader, frame_idx: List[int]) -> List[Image.Image]:
frames_np = video.get_batch(frame_idx).asnumpy()
return [Image.fromarray(frame) for frame in frames_np]
def get_video_tensor_online(self, media_url, vision_stream, worker_id=0, element_dtype="image") -> torch.Tensor:
self.vision_stream = vision_stream
video_stream = media_url
if element_dtype == "image":
image = Image.open(video_stream)
if image.mode == "P":
image = image.convert("RGBA")
if image.mode == "RGBA":
bg = Image.new("RGB", image.size, (255, 255, 255))
bg.paste(image, mask=image.split()[3])
image = bg
else:
image = image.convert("RGB")
video_frames = [image]
else:
video_reader = VideoReader(video_stream, ctx=decord.cpu(worker_id % self.cpu_count))
total_frames = len(video_reader)
try:
fps = int(round(float(video_reader.get_avg_fps())))
except Exception:
fps = 24
frames_info = {
"clip_indices": [(0, total_frames)],
"fps": fps,
}
frames_sampler_output: FrameSamplerOutput = self.frame_sampler(frames_info)
video_frames = self._read_decord(video_reader, frames_sampler_output.indices)
if vision_stream == "vae_video":
video_tensor = self.transform(video_frames)
elif vision_stream == "vit_video":
video_tensor = self.vit_transform(video_frames)
if element_dtype == "image":
video_tensor = video_tensor.repeat(1, 2, 1, 1)
if video_tensor.shape[1] % 2 == 1:
last_frame = video_tensor[:, -1:, :, :]
video_tensor = torch.cat([video_tensor, last_frame], dim=1)
else:
raise ValueError(f"Unknown vision_stream: {vision_stream}")
return video_tensor
def process_vit_video(self, video_tensor, curr: int, curr_rope_id: int, curr_split_len: int, curr_video_grid_thw: None, item_loss=0):
if not self.data_config.text_template:
self.sample["packed_text_ids"].append(self.start_of_image)
self.sample["packed_text_indexes"].append(curr)
curr += 1
curr_split_len += 1
if isinstance(video_tensor, torch.Tensor):
self.sample["vit_video_tensors"].append(video_tensor)
vit_tokens = patchify_video_with_merge(
video_tensor, self.data_config.vit_patch_size, self.data_config.vit_patch_size_temporal
)
num_video_tokens = vit_tokens.shape[0] // 4
t, h, w = video_tensor.size(1), video_tensor.size(2), video_tensor.size(3)
self.sample["packed_vit_tokens"].append(vit_tokens)
self.sample["vit_data_mode"].append("online")
if t is not None:
vit_video_grid_thw = [
t // self.data_config.vit_patch_size_temporal,
h // self.data_config.vit_patch_size,
w // self.data_config.vit_patch_size,
]
self.sample["vit_video_grid_thw"].append(vit_video_grid_thw)
curr_video_grid_thw.append(vit_video_grid_thw)
self.sample["vit_token_seqlens"].append(num_video_tokens)
self.sample["packed_vit_position_ids"].append(
torch.zeros(num_video_tokens)
)
if not self.data_config.text_template:
self.sample["packed_vit_token_indexes"].extend(range(curr, curr + num_video_tokens))
curr += num_video_tokens
curr_split_len += num_video_tokens
self.sample["packed_text_ids"].extend([self.image_token_id] * num_video_tokens)
self.sample["packed_text_ids"].append(self.end_of_image)
self.sample["packed_text_indexes"].append(curr)
curr += 1
curr_split_len += 1
self.sample["packed_position_ids"].extend([curr_rope_id] * curr_split_len)
curr_rope_id += 1
self.sample["attn_modes"].append("full")
self.sample["split_lens"].append(curr_split_len)
return self.sample, curr, curr_rope_id, curr_split_len, curr_video_grid_thw, num_video_tokens
def process_text(self, caption: str, curr: int, curr_rope_id: int, curr_split_len: int, item_loss=0):
"""Process text and append special tokens."""
text_ids = self.tokenizer.encode(caption)
shifted_text_ids = [self.bos_token_id] + text_ids
self.sample["packed_text_ids"].extend(shifted_text_ids)
self.sample["packed_text_indexes"].extend(range(curr, curr + len(shifted_text_ids)))
if item_loss == 1:
loss_token_shift = 0
self.sample["ce_loss_indexes"].extend(range(curr - loss_token_shift, curr + len(shifted_text_ids)))
self.sample["ce_loss_weights"].extend([len2weight(len(shifted_text_ids) + loss_token_shift)] * (len(shifted_text_ids) + loss_token_shift))
self.sample["packed_label_ids"].extend(text_ids + [self.eos_token_id])
curr += len(shifted_text_ids)
curr_split_len += len(shifted_text_ids)
# Append the <|im_end|> end token.
self.sample["packed_text_ids"].append(self.eos_token_id)
self.sample["packed_text_indexes"].append(curr)
curr += 1
curr_split_len += 1
self.sample["attn_modes"].append("causal")
self.sample["packed_position_ids"].extend(range(curr_rope_id, curr_rope_id + curr_split_len))
curr_rope_id += curr_split_len
self.sample["split_lens"].append(curr_split_len)
return self.sample, curr, curr_rope_id, curr_split_len
def process_vae_video(self, video_tensor, curr: int, curr_rope_id: int, curr_split_len: int, curr_video_grid_thw: None, video_sizes: list, item_loss=0):
if not self.data_config.text_template:
num_special_tokens = 0
self.sample["packed_text_ids"].append(self.start_of_image)
self.sample["packed_text_indexes"].append(curr)
curr += 1
curr_split_len += 1
num_special_tokens += 1
if isinstance(video_tensor, torch.Tensor):
self.sample["vae_video_tensors"].append(video_tensor)
_, T, H, W = video_tensor.shape
_T, _H, _W = self.data_config.vae_downsample
t = (T - 1) // _T + 1
h = H // _H
w = W // _W
self.sample["vae_data_mode"].append("online")
spatial_merge_size = 2
vae_video_grid_thw = [
t,
h * spatial_merge_size,
w * spatial_merge_size,
]
self.sample["vae_video_grid_thw"].append(vae_video_grid_thw)
curr_video_grid_thw.append(vae_video_grid_thw)
self.sample["vae_latent_shapes"].append((t, h, w))
packed_latent_position_ids = get_flattened_position_ids_extrapolate_video(t, h, w, max_latent_size=self.data_config.max_latent_size)
self.sample["packed_latent_position_ids"].append(packed_latent_position_ids)
num_vid_tokens = t * h * w
if not self.data_config.text_template:
self.sample["packed_vae_token_indexes"].extend(range(curr, curr + num_vid_tokens))
if item_loss == 1:
timestep = np.random.randn()
frame_condition_idx = self.frame_condition_idx
packed_timesteps = [timestep] * num_vid_tokens
mse_loss_indexes = list(range(curr, curr + num_vid_tokens))
frame_condition_indexes = []
for idx in frame_condition_idx:
if idx == -1:
idx = t - 1
if idx == 1:
continue
frame_condition_indexes.extend(mse_loss_indexes[idx * h * w : (idx + 1) * h * w])
packed_timesteps[idx * h * w : (idx + 1) * h * w] = [-sys.float_info.max] * (h * w)
if frame_condition_idx:
mse_loss_indexes = sorted(list(set(mse_loss_indexes) - set(frame_condition_indexes)))
if not self.data_config.text_template:
self.sample["mse_loss_indexes"].extend(mse_loss_indexes)
else:
timestep = float("-inf")
packed_timesteps = [timestep] * num_vid_tokens
self.sample["packed_timesteps"].extend(packed_timesteps)
if not self.data_config.text_template:
curr += num_vid_tokens
curr_split_len += num_vid_tokens
self.sample["packed_text_ids"].extend([self.image_token_id] * num_vid_tokens)
# Append the <|endofimage|> image end token.
self.sample["packed_text_ids"].append(self.end_of_image)
self.sample["packed_text_indexes"].append(curr)
curr += 1
curr_split_len += 1
num_special_tokens += 1
# Update sequence state.
if item_loss == 1:
self.sample["attn_modes"].append("noise")
else:
self.sample["attn_modes"].append("full_noise")
self.sample["packed_position_ids"].extend([curr_rope_id] * (num_vid_tokens + num_special_tokens))
curr_rope_id += 1
self.sample["split_lens"].append(curr_split_len)
video_sizes.append([T, H, W])
return self.sample, curr, curr_rope_id, curr_split_len, curr_video_grid_thw, video_sizes, num_vid_tokens
def process_text_template(
self,
text_ids,
spans_index,
tgt_index,
caption_index,
video_types: list[str],
curr: int,
curr_rope_id: int,
curr_split_len: int,
item_loss=0,
):
self.sample["packed_text_ids"].extend(text_ids)
self.sample["sample_lens"] = len(text_ids)
curr_split_idx = curr
for video_id, span_index in enumerate(spans_index):
vision_start, vision_end = curr_split_idx + span_index[0], curr_split_idx + span_index[-1]
self.sample["packed_text_indexes"].extend(range(curr, vision_start))
if (vision_start - 1) - curr != 0:
curr_split_len = (vision_start - 1) - curr
self.sample["packed_position_ids"].extend(
range(curr_rope_id, curr_rope_id + curr_split_len)
)
curr_rope_id += curr_split_len
self.sample["sample_modality"].extend([modality_map["system_prompt"]] * curr_split_len)
if caption_index != [] and caption_index[0] in range(curr, curr + curr_split_len):
split_len_1 = caption_index[0] - curr
split_len_2 = len(caption_index)
split_len_3 = curr_split_len - split_len_1 - split_len_2
split_len_text = [split_len_1, split_len_2, split_len_3]
split_len_text = [x for x in split_len_text if x != 0]
self.sample["attn_modes"].extend(["causal"] * len(split_len_text))
self.sample["split_lens"].extend(split_len_text)
else:
self.sample["attn_modes"].append("causal")
self.sample["split_lens"].append(curr_split_len)
curr_split_len = len(span_index) + 2
if video_types[video_id] == "vit_video":
self.sample["packed_vit_token_indexes"].extend(range(vision_start, vision_end + 1))
self.sample["attn_modes"].append("full")
self.sample["sample_modality"].extend([modality_map["ref_vit"]] * curr_split_len)
elif "vae_video" in video_types[video_id]:
self.sample["packed_vae_token_indexes"].extend(range(vision_start, vision_end + 1))
if "cond" in video_types[video_id]:
self.sample["attn_modes"].append("full_noise")
if self.sample_task == "edit":
self.sample["sample_modality"].extend([modality_map["ref_source"]] * curr_split_len)
elif self.sample_task == "idip":
self.sample["sample_modality"].extend([modality_map["ref_image"]] * curr_split_len)
elif "target" in video_types[video_id]:
self.sample["mse_loss_indexes"].extend(range(vision_start, vision_end + 1))
self.sample["attn_modes"].append("noise")
self.sample["sample_modality"].extend([modality_map["noise"]] * curr_split_len)
else:
raise ValueError(f"video_types {video_types[video_id]} not supported")
self.sample["packed_position_ids"].extend([curr_rope_id] * curr_split_len)
self.sample["split_lens"].append(len(span_index) + 2)
curr = vision_end + 1
curr_rope_id += 1
self.sample["packed_text_indexes"].append(curr)
curr += 1
len_split_last = self.sample["sample_lens"] - (curr - curr_split_idx) if spans_index != [] else len(text_ids)
if len_split_last != 0:
self.sample["split_lens"].append(len_split_last)
self.sample["packed_text_indexes"].extend(range(curr, curr + len_split_last))
self.sample["packed_position_ids"].extend(range(curr_rope_id, curr_rope_id + len_split_last))
self.sample["attn_modes"].append("causal")
self.sample["sample_modality"].extend([modality_map["system_prompt"]] * len_split_last)
if item_loss == 1:
packed_label_index = tgt_index
self.sample["packed_label_ids"].extend(text_ids[packed_label_index[0] :])
packed_label_index = np.asarray(packed_label_index, dtype=np.int64) + curr_split_idx
ce_loss_indexes = (packed_label_index - 1).tolist()
self.sample["ce_loss_indexes"].extend(ce_loss_indexes)
self.sample["ce_loss_weights"].extend([len2weight(len(packed_label_index))] * (len(packed_label_index)))
if caption_index != []:
self.sample["sample_modality"][caption_index[0] : caption_index[-1] + 1] = [modality_map["text"]] * (caption_index[-1] - caption_index[0] + 1)
curr_split_idx += len(text_ids)
curr = curr_split_idx
return self.sample, curr, curr_rope_id, curr_split_len
def process_und_template(self, system_prompt, user_prompt, answer, vit_video_tensor):
curr = 0
sample_lens = 0
curr_rope_id = 0
curr_video_grid_thw = []
prompt_prefix = "<|im_start|>" + "system\n" + system_prompt + "<|im_end|>" + "\n" + "<|im_start|>" + "user\n"
text_ids_prompt_prefix = self.tokenizer.encode(prompt_prefix)
self.sample["packed_text_ids"].extend(text_ids_prompt_prefix)
self.sample["packed_text_indexes"].extend(range(curr, curr + len(text_ids_prompt_prefix)))
curr += len(text_ids_prompt_prefix)
split_len_prefix = len(text_ids_prompt_prefix)
# Update sequence state.
self.sample["attn_modes"].append("causal")
self.sample["packed_position_ids"].extend(range(curr_rope_id, curr_rope_id + split_len_prefix))
self.sample["split_lens"].append(split_len_prefix)
curr_rope_id += split_len_prefix
self.sample["packed_text_ids"].append(self.start_of_image)
self.sample["packed_text_indexes"].append(curr)
curr += 1
split_len_vision_token = 1
if isinstance(vit_video_tensor, torch.Tensor):
self.sample["vit_video_tensors"].append(vit_video_tensor)
# Preprocess the video.
vit_tokens = patchify_video_with_merge(
vit_video_tensor, self.data_config.vit_patch_size, self.data_config.vit_patch_size_temporal
)
num_video_tokens = vit_tokens.shape[0] // 4
t, h, w = vit_video_tensor.size(1), vit_video_tensor.size(2), vit_video_tensor.size(3)
self.sample["packed_vit_tokens"].append(vit_tokens)
self.sample["vit_data_mode"].append("online")
if t is not None:
vit_video_grid_thw = [
t // self.data_config.vit_patch_size_temporal,
h // self.data_config.vit_patch_size,
w // self.data_config.vit_patch_size,
]
self.sample["vit_video_grid_thw"].append(vit_video_grid_thw)
curr_video_grid_thw.append(vit_video_grid_thw)
self.sample["vit_token_seqlens"].append(num_video_tokens)
self.sample["packed_vit_position_ids"].append(
torch.zeros(num_video_tokens)
)
self.sample["packed_vit_token_indexes"].extend(range(curr, curr + num_video_tokens))
curr += num_video_tokens
split_len_vision_token += num_video_tokens
# Fill placeholder position_ids.
self.sample["packed_text_ids"].extend([self.image_token_id] * num_video_tokens)
# Append the <|endofimage|> image end token.
self.sample["packed_text_ids"].append(self.end_of_image)
self.sample["packed_text_indexes"].append(curr)
curr += 1
split_len_vision_token += 1
# Update sequence state.
self.sample["attn_modes"].append("full")
self.sample["packed_position_ids"].extend([curr_rope_id] * split_len_vision_token)
self.sample["split_lens"].append(split_len_vision_token)
curr_rope_id += 1
prompt_postfix = user_prompt + "<|im_end|>" + "\n" + "<|im_start|>" + "assistant"
text_ids_prompt_postfix = self.tokenizer.encode(prompt_postfix)
self.sample["packed_text_ids"].extend(text_ids_prompt_postfix)
self.sample["packed_text_indexes"].extend(range(curr, curr + len(text_ids_prompt_postfix)))
curr += len(text_ids_prompt_postfix)
split_len_postfix = len(text_ids_prompt_postfix)
self.sample["attn_modes"].append("causal")
self.sample["packed_position_ids"].extend(range(curr_rope_id, curr_rope_id + split_len_postfix))
self.sample["split_lens"].append(split_len_postfix)
curr_rope_id += split_len_postfix
answer = "\n" + answer
answer_ids = self.tokenizer.encode(answer)
shifted_text_ids_answer = answer_ids + [self.eos_token_id]
self.sample["packed_text_ids"].extend(shifted_text_ids_answer)
self.sample["packed_text_indexes"].extend(range(curr, curr + len(shifted_text_ids_answer)))
self.sample["ce_loss_indexes"].extend(range(curr, curr + len(shifted_text_ids_answer)))
self.sample["ce_loss_weights"].extend([len2weight(len(shifted_text_ids_answer))] * (len(shifted_text_ids_answer)))
self.sample["packed_label_ids"].extend(shifted_text_ids_answer)
curr += len(shifted_text_ids_answer)
split_len_answer = len(shifted_text_ids_answer)
self.sample["attn_modes"].append("causal")
self.sample["packed_position_ids"].extend(range(curr_rope_id, curr_rope_id + split_len_answer))
self.sample["split_lens"].append(split_len_answer)
curr_rope_id += split_len_answer
sample_lens = len(self.sample["packed_text_ids"])
return sample_lens, curr_video_grid_thw
def _finalize_sample(self, sample_lens, curr_video_grid_thw, sample_type, sample=None, additional_fields=None, video_sizes=None):
self.sample["sample_lens"] = [sample_lens]
self.sample["video_grid_thw"] = torch.tensor([curr_video_grid_thw])
self.sample["packed_text_ids"] = torch.tensor(self.sample["packed_text_ids"])
self.sample["packed_text_indexes"] = torch.tensor(self.sample["packed_text_indexes"])
self.sample["packed_vae_token_indexes"] = torch.tensor(self.sample["packed_vae_token_indexes"])
self.sample["packed_position_ids"] = torch.tensor(self.sample["packed_position_ids"])
self.sample["vae_video_grid_thw"] = torch.tensor(self.sample["vae_video_grid_thw"])
self.sample["vit_video_grid_thw"] = torch.tensor(self.sample["vit_video_grid_thw"])
self.sample["packed_vit_token_indexes"] = torch.tensor(self.sample["packed_vit_token_indexes"])
self.sample["sample_N_target"] = torch.tensor([[1]])
self.sample["sample_type"] = [sample_type]
self.sample["padded_videos"] = self.sample["vae_video_tensors"]
if "ce_loss_indexes" in self.sample and len(self.sample["ce_loss_indexes"]) > 0:
self.sample["ce_loss_indexes"] = torch.tensor(self.sample["ce_loss_indexes"])
self.sample["mse_loss_indexes"] = torch.tensor(self.sample["mse_loss_indexes"])
if video_sizes is not None:
self.sample["video_sizes"] = torch.tensor(video_sizes)
elif "video_sizes" in self.sample:
self.sample["video_sizes"] = torch.tensor(self.sample["video_sizes"])
if "sample_modality" in self.sample and len(self.sample["sample_modality"]) > 0:
self.sample["sample_modality"] = torch.tensor(self.sample["sample_modality"])
if sample is not None:
for key in ["index", "category", "question", "gt"]:
if key in sample:
self.sample[key] = sample[key]
if additional_fields is not None:
for key, value in additional_fields.items():
self.sample[key] = value
return self.sample
def ti2t_sample(self, idx: int) -> Dict[str, Any]:
self.sample = self.set_sequence_status()
sample = self.data[idx]
system_prompt = sample["system_prompt"]
user_prompt = sample["user_prompt"]
answer = sample["gt"]
image_path = sample["image_path"]
vit_image_tensor = self.get_video_tensor_online(image_path, vision_stream="vit_video", element_dtype="image")
sample_lens, curr_video_grid_thw = self.process_und_template(
system_prompt=system_prompt,
user_prompt=user_prompt,
answer=answer,
vit_video_tensor=vit_image_tensor,
)
self.sample["system_prompt"] = system_prompt
self.sample["user_prompt"] = user_prompt
self.sample["image_path"] = image_path
self.sample["instruction"] = user_prompt
return self._finalize_sample(
sample_lens, curr_video_grid_thw,
sample_type="und",
sample=sample
)
def t2v_sample(self, idx: int) -> Dict[str, Any]:
"""Get a single sample."""
thw_video, thw_downsample = self.get_thw()
t, h, w = thw_downsample
num_vid_tokens = t * h * w
spatial_merge_size = 2
self.sample = self.set_sequence_status()
packed_text_indexes, packed_position_ids, sample_modality = [], [], []
sample = self.data[idx]
if "prompt_en" in sample.keys():
user_prompt = "".join(sample["prompt_en"][0])
else:
user_prompt = sample["data"]
user_prompt = self._maybe_enhance_t2v_prompt(user_prompt)
if self.data_config.text_template:
caption_instruction = generate_system_prompt(system_prompt_type=self.data_config.task, vision_type=self.data_config.target_modality)
text_template_user, text_template_assistant, vit_num_tokens, video_types = [], [], [], []
if self.system_prompt_type == 'SP2':
user_prompt = caption_instruction + " " + user_prompt
caption_instruction = "You are a helpful assistant. "
elif self.system_prompt_type == 'SP1':
caption_instruction = "You are a helpful assistant. " + caption_instruction
text_template_user.append({"type": "text", "text": user_prompt})
else:
text_ids = self.tokenizer.encode(user_prompt)
text_ids = [self.new_token_ids["bos_token_id"]] + text_ids + [self.new_token_ids["eos_token_id"]]
text_split_len = len(text_ids)
packed_text_indexes.extend(range(0, text_split_len))
packed_position_ids.extend(range(0, text_split_len))
sample_modality.extend([modality_map['text']] * text_split_len)
if self.data_config.text_template:
text_template_assistant.append({"type":self.data_config.target_modality})
else:
text_ids.append(self.new_token_ids["start_of_image"])
packed_text_indexes.append(text_split_len)
packed_vae_token_indexes = torch.tensor(range(len(text_ids), len(text_ids) + num_vid_tokens))
text_ids.extend([self.image_token_id] * num_vid_tokens)
text_ids.append(self.new_token_ids["end_of_image"])
packed_text_indexes.append(len(text_ids) - 1)
video_split_len = num_vid_tokens + 2
packed_position_ids.extend([text_split_len] * video_split_len)
sample_modality.extend([modality_map['noise']] * video_split_len)
if self.data_config.text_template:
all_token_id, spans_index, tgt_index, search_index = self.render_template(caption_instruction, text_template_assistant, text_template_user, [num_vid_tokens], search_text=user_prompt)
self.sample, curr, curr_rope_id, curr_split_len = self.process_text_template(
all_token_id,
spans_index,
tgt_index,
search_index,
video_types=['target_vae_video'],
curr=0,
curr_rope_id=0,
curr_split_len=0,
item_loss=0,
)
return {
"packed_text_ids": torch.tensor(text_ids) if not self.data_config.text_template else torch.tensor(self.sample["packed_text_ids"]),
"packed_text_indexes": torch.tensor(packed_text_indexes) if not self.data_config.text_template else torch.tensor(self.sample["packed_text_indexes"]),
"packed_vae_token_indexes": packed_vae_token_indexes if not self.data_config.text_template else torch.tensor(self.sample["packed_vae_token_indexes"]),
"vae_video_grid_thw": torch.tensor([[t, h * spatial_merge_size, w * spatial_merge_size]]),
"video_grid_thw": torch.tensor([[[t, h * spatial_merge_size, w * spatial_merge_size]]]),
"sample_N_target": torch.tensor([[1]]),
"split_lens": [text_split_len, video_split_len] if not self.data_config.text_template else self.sample["split_lens"],
"attn_modes": ["causal", "noise"] if not self.data_config.text_template else self.sample["attn_modes"],
"sample_lens": [text_split_len + video_split_len] if not self.data_config.text_template else [self.sample["sample_lens"]],
"val_sample_type": ["gen"],
"padded_latent": None,
"mse_loss_indexes": packed_vae_token_indexes if not self.data_config.text_template else torch.tensor(self.sample["mse_loss_indexes"]),
"video_sizes": torch.tensor([thw_video]),
"packed_position_ids": torch.tensor(packed_position_ids) if not self.data_config.text_template else torch.tensor(self.sample["packed_position_ids"]),
"caption": user_prompt,
"sample_type": ["gen"],
"index": sample["index"],
"caption_cn": user_prompt,
"original_prompt_en": sample["original_prompt_en"] if "original_prompt_en" in sample.keys() else user_prompt,
"sample_task": torch.zeros(text_split_len + video_split_len) if not self.data_config.text_template else torch.zeros(self.sample["sample_lens"]),
"sample_modality": torch.tensor(sample_modality) if not self.data_config.text_template else torch.tensor(self.sample["sample_modality"]),
"additional_info": sample["additional_info"] if "additional_info" in sample.keys() else None,
}
def get_thw(self):
_T, _H, _W = self.data_config.vae_downsample
if self.data_config.target_modality == "image":
t = 1
t_ = 1
elif self.data_config.target_modality == "video":
t = (self.data_config.num_frames - 1) // _T + 1
t_ = self.data_config.num_frames
h = self.data_config.H // _H
w = self.data_config.W // _W
return [t_, self.data_config.H, self.data_config.W], [t, h, w] # Original video size and downsampled size.
def gen_timesteps(self, t, h, w, curr, num_vid_tokens):
timestep = np.random.randn()
frame_condition_idx = self.frame_condition_idx
packed_timesteps = [timestep] * num_vid_tokens
mse_loss_indexes = list(range(curr, curr + num_vid_tokens))
frame_condition_indexes = []
for idx in frame_condition_idx:
frame_condition_indexes.extend(mse_loss_indexes[idx * h * w : (idx + 1) * h * w])
packed_timesteps[idx * h * w : (idx + 1) * h * w] = [-sys.float_info.max] * (h * w)
if frame_condition_idx:
mse_loss_indexes = sorted(list(set(mse_loss_indexes) - set(frame_condition_indexes)))
return packed_timesteps, mse_loss_indexes
def tiv2v_sample(self, idx: int) -> Dict[str, Any]:
sample_modality, text_template_user, text_template_assistant, vit_num_tokens, video_types = [], [], [], [], []
self.sample = self.set_sequence_status()
sample_lens = 0
sample = self.data[idx]
index = sample["index"]
data_sample = sample["data"]
additional_info = sample["data"]["additional_info"] if "additional_info" in sample["data"] else []
interleave_array, element_dtype_array, istarget_in_interleave = data_sample["interleave_array"], data_sample["element_dtype_array"], data_sample["istarget_in_interleave"]
curr, curr_rope_id, curr_split_len, curr_video_grid_thw, video_sizes, caption_all = 0, 0, 0, [], [], ''
for element, element_dtype, is_target in zip(interleave_array, element_dtype_array, istarget_in_interleave):
if element_dtype == "text":
caption_all += element
if self.data_config.text_template:
text_template_user.append({"type": "text", "text": element})
search_text = element
else:
self.sample, curr, curr_rope_id, curr_split_len = self.process_text(element, curr=curr, curr_rope_id=curr_rope_id, curr_split_len=0, item_loss=is_target)
sample_lens += curr_split_len
sample_modality.extend([modality_map['text']] * curr_split_len)
elif element_dtype in ["image", "video"]:
if is_target == 0:
vit_image_tensor = self.get_video_tensor_online(element, vision_stream="vit_video", element_dtype=element_dtype)
self.sample, curr, curr_rope_id, curr_split_len, curr_video_grid_thw, num_tokens_ = self.process_vit_video(
vit_image_tensor, curr=curr, curr_rope_id=curr_rope_id, curr_split_len=0, curr_video_grid_thw=curr_video_grid_thw, item_loss=0
)
if self.data_config.text_template:
text_template_user.append({"type": element_dtype})
vit_num_tokens.append(num_tokens_)
video_types.append("vit_video")
else:
sample_lens += curr_split_len
sample_modality.extend([modality_map['ref_vit']] * curr_split_len)
# Process VAE conditioning input.
vae_image_tensor = self.get_video_tensor_online(element, vision_stream="vae_video", element_dtype=element_dtype)
self.sample, curr, curr_rope_id, curr_split_len, curr_video_grid_thw, video_sizes, num_tokens_ = self.process_vae_video(
vae_image_tensor, curr=curr, curr_rope_id=curr_rope_id, curr_split_len=0, curr_video_grid_thw=curr_video_grid_thw, video_sizes=video_sizes, item_loss=is_target
)
vit_num_tokens.append(num_tokens_)
text_template_user.append({"type": element_dtype})
video_types.append("cond_vae_video")
if self.sample_task == 'edit':
self.data_config.num_frames, self.data_config.H, self.data_config.W = vae_image_tensor.shape[1], vae_image_tensor.shape[2], vae_image_tensor.shape[3]
# Process the VAE target input.
thw_video, thw_downsample = self.get_thw()
video_sizes.append(thw_video)
t, h, w = thw_downsample
num_vid_tokens = t * h * w
self.sample["vae_data_mode"].append("online")
spatial_merge_size = 2
vae_video_grid_thw = [
t,
h * spatial_merge_size,
w * spatial_merge_size,
]
curr_video_grid_thw.append(vae_video_grid_thw)
self.sample["vae_video_grid_thw"].append(vae_video_grid_thw)
self.sample["vae_latent_shapes"].append((t, h, w))
# Use 3D-aware extrapolated position encoding.
packed_latent_position_ids = get_flattened_position_ids_extrapolate_video(t, h, w, max_latent_size=self.data_config.max_latent_size)
self.sample["packed_latent_position_ids"].append(packed_latent_position_ids)
packed_timesteps, mse_loss_indexes = self.gen_timesteps(t, h, w, curr, num_vid_tokens)
self.sample["packed_timesteps"].extend(packed_timesteps)
vae_tensor = torch.randn([3, thw_video[0], thw_video[1], thw_video[2]], dtype=torch.float32) # Raw CTHW video, not latent.
self.sample["vae_video_tensors"].append(vae_tensor)
if self.data_config.text_template:
vit_num_tokens.append(num_vid_tokens)
text_template_assistant.append({"type": self.data_config.target_modality})
video_types.append("target_vae_video")
if text_template_user[0]['type']=='text':
text_template_user = text_template_user[1:] + text_template_user[:1]
caption_instruction = generate_system_prompt(system_prompt_type=self.data_config.task, vision_type=element_dtype)
all_token_id, spans_index, tgt_index, search_index = self.render_template(caption_instruction, text_template_assistant, text_template_user, vit_num_tokens, search_text=search_text)
self.sample, curr, curr_rope_id, curr_split_len = self.process_text_template(
all_token_id,
spans_index,
tgt_index,
search_index,
video_types=video_types,
curr=0,
curr_rope_id=0,
curr_split_len=0,
item_loss=0,
)
sample_lens = len(all_token_id)
sample_modality = self.sample["sample_modality"]
additional_fields = {
"caption": caption_all,
"caption_cn": caption_all,
"index": sample["index"],
"additional_info": additional_info
}
if self.sample_task == 'edit':
self.sample["sample_task"] = torch.ones(sample_lens) * sample_task_map['edit']
elif self.sample_task == 'idip':
self.sample["sample_task"] = torch.ones(sample_lens) * sample_task_map['idip']
return self._finalize_sample(
sample_lens, curr_video_grid_thw,
sample_type="gen",
sample=sample,
additional_fields=additional_fields,
video_sizes=video_sizes
)
def ff2v_sample(self, idx: int) -> Dict[str, Any]:
"""Get a single sample."""
sample_modality, text_template_user, text_template_assistant, vit_num_tokens, video_types, search_text = [], [], [], [], [], ''
self.sample = self.set_sequence_status()
sample_lens = 0
sample = self.data[idx]
index = sample["index"]
data_sample = sample["data"]
additional_info = sample["data"]["additional_info"] if "additional_info" in sample["data"] else []
interleave_array, element_dtype_array, istarget_in_interleave = data_sample["interleave_array"], data_sample["element_dtype_array"], data_sample["istarget_in_interleave"]
interleave_array = list(interleave_array)
text_idx = next((i for i, dtype in enumerate(element_dtype_array) if dtype == "text"), None)
image_idx = next(
(
i
for i, (dtype, is_target) in enumerate(zip(element_dtype_array, istarget_in_interleave))
if dtype == "image" and is_target == 0
),
None,
)
if text_idx is not None and image_idx is not None:
interleave_array[text_idx] = self._maybe_enhance_i2v_prompt(
interleave_array[text_idx],
image_path=interleave_array[image_idx],
)
curr, curr_rope_id, curr_split_len, curr_video_grid_thw, video_sizes, caption_all, vae_image_tensor = 0, 0, 0, [], [], '', None
for element, element_dtype, is_target in zip(interleave_array, element_dtype_array, istarget_in_interleave):
if element_dtype == "text":
caption_all += element
if self.data_config.text_template:
text_template_user.append({"type": "text", "text": element})
search_text = element
else:
self.sample, curr, curr_rope_id, curr_split_len = self.process_text(element, curr=curr, curr_rope_id=curr_rope_id, curr_split_len=0, item_loss=is_target)
sample_lens += curr_split_len
sample_modality.extend([modality_map['text']] * curr_split_len)
elif element_dtype in ["image", "video"]:
if is_target == 0:
vae_image_tensor = self.get_video_tensor_online(element, vision_stream="vae_video", element_dtype=element_dtype)
self.data_config.H, self.data_config.W = vae_image_tensor.shape[2], vae_image_tensor.shape[3]
self.frame_condition_idx = [0]
# Add the target VAE latent.
thw_video, thw_downsample = self.get_thw()
video_sizes.append(thw_video)
t, h, w = thw_downsample
num_vid_tokens = t * h * w
self.sample["vae_data_mode"].append("online")
spatial_merge_size = 2
vae_video_grid_thw = [
t,
h * spatial_merge_size,
w * spatial_merge_size,
]
curr_video_grid_thw.append(vae_video_grid_thw)
self.sample["vae_video_grid_thw"].append(vae_video_grid_thw)
self.sample["vae_latent_shapes"].append((t, h, w))
packed_latent_position_ids = get_flattened_position_ids_extrapolate_video(t, h, w, max_latent_size=self.data_config.max_latent_size)
self.sample["packed_latent_position_ids"].append(packed_latent_position_ids)
packed_timesteps, mse_loss_indexes = self.gen_timesteps(t, h, w, curr, num_vid_tokens)
self.sample["packed_timesteps"].extend(packed_timesteps)
vae_tensor = torch.randn([3, thw_video[0], thw_video[1], thw_video[2]], dtype=torch.float32)
if vae_image_tensor is not None: # Fill in the first frame.
vae_tensor[:, :4, :, :] = vae_image_tensor[:, 0:1, :, :].repeat(1, 4, 1, 1)
else:
raise ValueError("vae_image_tensor of first frame is None")
self.sample["vae_video_tensors"].append(vae_tensor)
if self.data_config.text_template:
vit_num_tokens.append(num_vid_tokens)
text_template_assistant.append({"type": self.data_config.target_modality})
video_types.append("target_vae_video")
if len(text_template_user) > 0 and text_template_user[0]['type'] == 'text':
text_template_user = text_template_user[1:] + text_template_user[:1]
caption_instruction = generate_system_prompt(system_prompt_type=self.data_config.task, vision_type=self.data_config.target_modality)
all_token_id, spans_index, tgt_index, search_index = self.render_template(caption_instruction, text_template_assistant, text_template_user, vit_num_tokens, search_text=search_text)
self.sample, curr, curr_rope_id, curr_split_len = self.process_text_template(
all_token_id,
spans_index,
tgt_index,
search_index,
video_types=video_types,
curr=0,
curr_rope_id=0,
curr_split_len=0,
item_loss=0,
)
sample_lens = len(all_token_id)
sample_modality = self.sample["sample_modality"]
self.sample["sample_task"] = torch.ones(sample_lens) * sample_task_map[self.sample_task]
self.sample["sample_modality"] = sample_modality
has_vit_video_grid = self.sample["vit_video_grid_thw"] != []
has_packed_vit_token_indexes = self.sample["packed_vit_token_indexes"] != []
if self.frame_condition_idx != []:
mse_loss_indexes_first = self.sample["mse_loss_indexes"][0]
self.sample["mse_loss_indexes"] = [idx + mse_loss_indexes_first for idx in mse_loss_indexes]
finalized_sample = self._finalize_sample(
sample_lens,
curr_video_grid_thw,
sample_type="gen",
sample=sample,
additional_fields={
"caption": caption_all,
"caption_cn": caption_all,
"additional_info": additional_info,
},
video_sizes=video_sizes,
)
if not has_vit_video_grid:
finalized_sample["vit_video_grid_thw"] = None
if not has_packed_vit_token_indexes:
finalized_sample["packed_vit_token_indexes"] = None
return finalized_sample
def render_template(self, instruction, text_template_assistant, text_template_user, vit_num_tokens, search_text=""):
messages = [
{
"role": "user",
"content": text_template_user,
},
{
"role": "assistant",
"content": text_template_assistant,
},
]
caption_all = render_qwenvl_prompt(messages, default_system=instruction, include_assistant_content=True)
all_token_id, spans_index, tgt_index, search_index = expand_and_index_by_token_ids_new(
rendered_text=caption_all.strip(), tokens=vit_num_tokens, target_text=f"assistant\n", tokenizer=self.tokenizer, search_text=search_text
)
assert len(all_token_id[tgt_index[0] :]) == len(tgt_index)
return all_token_id, spans_index, tgt_index, search_index
def x2t_sample(self, idx: int) -> Dict[str, Any]:
sample_modality = []
self.sample = self.set_sequence_status()
sample_lens = 0
sample = self.data[idx]
index = sample["index"]
data_sample = sample["data"]
interleave_array, element_dtype_array, istarget_in_interleave = data_sample["interleave_array"], data_sample["element_dtype_array"], data_sample["istarget_in_interleave"]
curr, curr_rope_id, curr_split_len, curr_video_grid_thw, video_sizes, caption_all = 0, 0, 0, [], [], ""
if self.data_config.text_template:
text_template_user, text_template_assistant, vit_num_tokens, video_types = [], [], [], []
for element, element_dtype, is_target in zip(interleave_array, element_dtype_array, istarget_in_interleave):
if element_dtype == "text":
if is_target == 1:
if self.data_config.text_template:
if isinstance(element, str):
caption_a = element
caption_i = generate_system_prompt(system_prompt_type="caption", vision_type=element_dtype_array[0])
caption_q = ""
element = [caption_i, caption_q, caption_a]
caption_i, caption_q, caption_a = element[0], element[1], element[2]
if self.system_prompt_type == 'SP2':
caption_q = caption_i + " " + caption_q
caption_i = "You are a helpful assistant. "
elif self.system_prompt_type == 'SP1':
caption_i = "You are a helpful assistant. " + caption_i
element = [caption_i, caption_q, caption_a]
caption_i, caption_q, caption_a = element[0], element[1], element[2]
text_template_assistant.append({"type": "text", "text": caption_a})
if caption_q != "":
text_template_user.append({"type": "text", "text": caption_q})
all_token_id, spans_index, tgt_index, search_index = self.render_template(caption_i, text_template_assistant, text_template_user, vit_num_tokens)
self.sample, curr, curr_rope_id, curr_split_len = self.process_text_template(
all_token_id,
spans_index,
tgt_index,
search_index,
video_types,
curr=curr,
curr_rope_id=curr_rope_id,
curr_split_len=0,
item_loss=is_target,
)
sample_lens += curr_split_len
caption_all += "\n".join(element)
caption_answer = element[-1]
else:
if isinstance(element, list):
element = element[-1]
self.sample, curr, curr_rope_id, curr_split_len = self.process_text(
element, curr=curr, curr_rope_id=curr_rope_id, curr_split_len=0, item_loss=is_target
)
sample_lens += curr_split_len
sample_modality.extend([modality_map["text"]] * curr_split_len)
caption_all += element
caption_answer = element
elif element_dtype in ["image", "video"]:
vit_image_tensor = self.get_video_tensor_online(element, vision_stream="vit_video", element_dtype=element_dtype)
self.sample, curr, curr_rope_id, curr_split_len, curr_video_grid_thw, num_tokens_ = self.process_vit_video(
vit_image_tensor, curr=curr, curr_rope_id=curr_rope_id, curr_split_len=0, curr_video_grid_thw=curr_video_grid_thw, item_loss=0
)
sample_lens += curr_split_len
sample_modality.extend([modality_map["ref_vit"]] * curr_split_len)
index_video_path_name = element.split("/")[-1]
if self.data_config.text_template:
text_template_user.append({"type": element_dtype})
vit_num_tokens.append(num_tokens_)
video_types.append("vit_video")
if self.sample["sample_lens"] != []:
sample_lens = self.sample["sample_lens"]
if self.sample["sample_modality"] != []:
sample_modality = self.sample["sample_modality"]
self.sample["sample_modality"] = sample_modality
self.sample["sample_task"] = torch.ones(self.sample["sample_lens"]) * sample_task_map["t2v"]
additional_fields = {
"caption": caption_all,
"caption_cn": caption_all,
"caption_answer": caption_answer,
"index_item": index,
"index": index_video_path_name,
"additional_information": data_sample["additional_information"] if "additional_information" in data_sample.keys() else {},
"visual_path": data_sample["interleave_array"][0],
"question": data_sample["interleave_array"][1][1] if isinstance(data_sample["interleave_array"][1], list) and len(data_sample["interleave_array"][1]) > 1 else None,
"answer": data_sample["interleave_array"][1][2] if isinstance(data_sample["interleave_array"][1], list) and len(data_sample["interleave_array"][1]) > 2 else None
}
return self._finalize_sample(
sample_lens, curr_video_grid_thw,
sample_type="und",
additional_fields=additional_fields
)
def __getitem__(self, idx: int) -> Dict[str, Any]:
task = self.data_config.task
# Get target modality
if '_t' in task:
self.data_config.target_modality = 'text'
elif '2i' in task or 'image' in task:
self.data_config.target_modality = 'image'
else:
self.data_config.target_modality = 'video'
# Get sample
if task in ["t2i", "t2v"]: # Text-to-image or text-to-video
return self.t2v_sample(idx)
elif 'edit' in task: # Video Editing or Image Editing
self.sample_task = 'edit'
return self.tiv2v_sample(idx)
elif 'idip' in task: # Video IDIP, Image IDIP
self.sample_task = 'idip'
return self.tiv2v_sample(idx)
elif "i2v" in task: # Text-Image-to-Video
self.sample_task = 't2v'
return self.ff2v_sample(idx)
elif task in ["x2t", "x2t_image", "x2t_video"]: # Multi-modal Understanding
return self.x2t_sample(idx)
else:
raise ValueError(f"Unknown task: {task}")