Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add Keye vl 8b 1.5#41040

Open
Kwai-Keye wants to merge 40 commits into
huggingface:mainfrom
Kwai-Keye:keye-vl-8b-1.5
Open

Add Keye vl 8b 1.5#41040
Kwai-Keye wants to merge 40 commits into
huggingface:mainfrom
Kwai-Keye:keye-vl-8b-1.5

Conversation

@Kwai-Keye

Copy link
Copy Markdown

Model Upgrade: Keye-VL-1.5-8B

Overview

This PR introduces an upgraded version of the visual-language model, transitioning from the previous keye-preview to keye-vl-1.5-8B. The update includes architectural refinements, documentation improvements, code optimizations, and style enhancements.

Key Changes

1. Model Architecture

  • Fine-tuned the model structure for improved performance and efficiency.
  • Enhanced visual-language alignment capabilities.

2. Documentation

  • Updated and optimized relevant documentation for better clarity and usability.
  • Added detailed descriptions of new features and modifications.

3. Code Optimization

  • Streamlined code workflow for enhanced maintainability.
  • Removed redundant parameters and code lines to improve efficiency.
  • Performed code style adaptations to ensure consistency with project standards.

Impact

  • Improved model performance and accuracy.
  • Enhanced code readability and maintainability.
  • Reduced computational overhead by eliminating unnecessary parameters.

Usage

Refer to the updated documentation for detailed instructions on using the new model version.

Notes

  • This upgrade maintains backward compatibility with existing pipelines.
  • Users are encouraged to review the updated docs for optimal utilization of new features.

@Kwai-Keye

Kwai-Keye commented Sep 22, 2025

Copy link
Copy Markdown
Author

@zucchini-nlp Please help take a look at this PR, thanks.

@zucchini-nlp

Copy link
Copy Markdown
Member

Nice, just wondering if it is same or similar to #39292 in terms of architecture? If it is, then imo it makes more sense to push the prev PR and allow 1.5 8B to re-use modules from it. WDYT?

@Kwai-Keye

Copy link
Copy Markdown
Author

@zucchini-nlp
I closed #39292 just now, we won't be submitting #39292 version.
But how do we resolve the failures in the screenshot below? There's a bizarre issue in page where importing the torch library fails.
截屏2025-09-22 16 46 27

@zucchini-nlp

Copy link
Copy Markdown
Member

To resolve the torch issue, you need to import from .image_processing_keye_vl_1_5 import KeyeVL1_5ImageProcessor and from transformers.models.qwen2.tokenization_qwen2_fast import Qwen2TokenizerFast in processing file with safe guards. Both require is_vision_available() and the second one also requires is_torchvision_available()

The other CI issues seem related to np version used, probably you need to find the equivalent of np.long in the version used in CI

@zucchini-nlp

Copy link
Copy Markdown
Member

I will review the PR shortly

@Kwai-Keye

Copy link
Copy Markdown
Author

@zucchini-nlp
Thanks.

@zucchini-nlp zucchini-nlp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, I think we need to clean up a bit since most part of the model are identical to Qwen-VL series. Also, regarding the video processing, let's create a separate video processing class similar to Qwen2-VL

I reviewed most of it, will come back soon to finish reviewing

Comment thread docs/source/en/model_doc/keye_vl_1_5.md Outdated
@@ -0,0 +1,252 @@
<!--Copyright 2025 The Kuai Keye Team and The HuggingFace Inc. team. All rights reserved.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to make sure, is Kuai correct or should it be Kwai?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment thread docs/source/en/model_doc/keye_vl_1_5.md Outdated
Comment on lines +64 to +69
# Keye-VL-Preview
[Keye-VL-Preview](https://huggingface.co/papers/2507.01949) is an 8-billion-parameter multimodal foundation model, excels in short-video understanding while maintaining robust general-purpose vision-language abilities through a comprehensive pre- and post-training process, including reinforcement learning and alignment.

The abstract from the paper is the following:

*While Multimodal Large Language Models (MLLMs) demonstrate remarkable capabilities on static images, they often fall short in comprehending dynamic, information-dense short-form videos, a dominant medium in today’s digital landscape. To bridge this gap, we introduce Kwai Keye-VL, an 8-billion-parameter multimodal foundation model engineered for leading-edge performance in short-video understanding while maintaining robust general-purpose vision-language abilities. The development of Keye-VL rests on two core pillars: a massive, high-quality dataset exceeding 600 billion tokens with a strong emphasis on video, and an innovative training recipe. This recipe features a four-stage pre-training process for solid vision-language alignment, followed by a meticulous two-phase post-training process. The first post-training stage enhances foundational capabilities like instruction following, while the second phase focuses on stimulating advanced reasoning. In this second phase, a key innovation is our five-mode “cold-start” data mixture, which includes “thinking”, “non-thinking”, “auto-think”, “think with image”, and high-quality video data. This mixture teaches the model to decide when and how to reason. Subsequent reinforcement learning (RL) and alignment steps further enhance these reasoning capabilities and correct abnormal model behaviors, such as repetitive outputs. To validate our approach, we conduct extensive evaluations, showing that Keye-VL achieves state-of-the-art results on public video benchmarks and remains highly competitive on general image-based tasks (Figure 1). Furthermore, we develop and release the KC-MMBench, a new benchmark tailored for real-world short-video scenarios, where Keye-VL shows a significant advantage. Comprehensive human evaluations also confirm that our model provides a superior user experience compared to other leading models of a similar scale. This paper details the architecture, data construction strategy, and training methodology of Keye-VL, offering valuable insights for building the next generation of MLLMs for the video era.*

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

preview is not available anymore, can delete

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment thread src/transformers/modeling_utils.py Outdated
"qwen2_5_vl",
"videollava",
"vipllava",
"keyevl1_5",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to delete as well, instead we should change the checkpoint keys before release. This list is reserved for models we cannot change because they are released in the past

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment thread src/transformers/models/keye_vl_1_5/modular_keye_vl_1_5.py Outdated
Comment on lines +554 to +556
image_token_id: int = None,
video_token_id: int = None,
attention_bias: bool = False,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The special image/video tokens also go in KeyeVL1_5Config. Then we can copy the text config from any existing LM's and reduce LOC :)

spatial_merge_size = config.vision_config.spatial_merge_size
self.merge_kernel_size = (spatial_merge_size, spatial_merge_size)

self.hidden_size = self.vision_config.hidden_size * self.merge_kernel_size[0] * self.merge_kernel_size[1]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't used in forward, we can keep as hidden_size = my-value-here

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment on lines +2897 to +2898
m1, m2 = self.merge_kernel_size
h_kernel, w_kernel = self.merge_kernel_size

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment thread utils/check_docstrings.py Outdated
"InformerConfig",
"JukeboxPriorConfig",
"JukeboxTokenizer",
"KeyeImageProcessor",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has to be fixed, we can't skip image processor docs

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment on lines +115 to +123
# text_config={
# "vocab_size": 99,
# "hidden_size": 32,
# "intermediate_size": 37,
# "num_hidden_layers": 4,
# "num_attention_heads": 4,
# "num_key_value_heads": 2,
# "hidden_act": "silu",
# "max_position_embeddings": 512,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uncomment?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

@@ -0,0 +1,533 @@
# Copyright 2025 The Keye Team and The HuggingFace Inc. team. All rights reserved.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need test for processing, image processing and video processing classes as well

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment on lines +3408 to +3412
_checkpoint_conversion_mapping = {
"^visual": "model.visual",
"^mlp_AR": "model.mm_projector",
r"^model(?!\.(language_model|visual|mm_projector))": "model.language_model",
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to remove and set to {}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment on lines +3248 to +3266
device = pixel_values.device
pixel_values = pixel_values.type(self.visual.dtype)
pixel_values = pixel_values.unsqueeze(0)
assert torch.all(image_grid_thw[:, 0] == 1)
image_grid_thw = image_grid_thw.to(device)

total_patches = image_grid_thw.prod(dim=1)
width = torch.repeat_interleave(image_grid_thw[:, 2], total_patches)
cu_seqlens = total_patches.cumsum(0)

arange = torch.arange(cu_seqlens[-1], dtype=torch.long, device=device)
image_position_ids = arange - torch.repeat_interleave(cu_seqlens.to(device) - total_patches, total_patches)

width_position_ids = torch.remainder(image_position_ids, width)
height_position_ids = torch.div(image_position_ids, width, rounding_mode="floor")
cu_seqlens = F.pad(cu_seqlens, (1, 0), value=0).to(dtype=torch.int32, device=device)
width_position_ids = width_position_ids.to(device)
height_position_ids = height_position_ids.to(device)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to call self.get_image_features()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment on lines +3303 to +3314
device = pixel_values_videos.device
pixel_values_videos = pixel_values_videos.type(self.visual.dtype)
pixel_values_videos = pixel_values_videos.unsqueeze(0)
video_grid_thw = split_thw(video_grid_thw.squeeze(0)).to(device)

assert torch.all(video_grid_thw[:, 0] == 1)

total_patches = video_grid_thw.prod(dim=1)
width = torch.repeat_interleave(video_grid_thw[:, 2], total_patches)
cu_seqlens = total_patches.cumsum(0)
arange = torch.arange(cu_seqlens[-1], dtype=torch.long, device=device)
video_position_ids = arange - torch.repeat_interleave(cu_seqlens.to(device) - total_patches, total_patches)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, we need to call self.get_video_features()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment on lines +3280 to +3287
if input_ids is None:
image_mask = inputs_embeds == self.get_input_embeddings()(
torch.tensor(self.config.image_token_id, dtype=torch.long, device=inputs_embeds.device)
)
image_mask = image_mask.all(-1)
else:
image_mask = input_ids == self.config.image_token_id

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is obtained from self.get_placeholder_mask similar to other VLMs (e,g. Qwen-VL)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment on lines +3333 to +3342
if input_ids is None:
video_mask = inputs_embeds == self.get_input_embeddings()(
torch.tensor(self.config.video_token_id, dtype=torch.long, device=inputs_embeds.device)
)
video_mask = video_mask.all(-1)
else:
video_mask = input_ids == self.config.video_token_id

n_video_tokens = video_mask.sum().item()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, from self.get_placeholder_mask similar to other VLMs (e,g. Qwen-VL)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment on lines +3178 to +3179
assert torch.all(image_grid_thw[:, 0] == 1)
image_grid_thw = image_grid_thw.to(device)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can delete these two lines

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment on lines +3137 to +3148
total_patches = video_grid_thw.prod(dim=1)
width = torch.repeat_interleave(video_grid_thw[:, 2], total_patches)
cu_seqlens = total_patches.cumsum(0)
arange = torch.arange(cu_seqlens[-1], dtype=torch.long, device=device)
video_position_ids = arange - torch.repeat_interleave(cu_seqlens.to(device) - total_patches, total_patches)

width_position_ids = torch.remainder(video_position_ids, width)
height_position_ids = torch.div(video_position_ids, width, rounding_mode="floor")
cu_seqlens = F.pad(cu_seqlens, (1, 0), value=0).to(dtype=torch.int32, device=device)
width_position_ids = width_position_ids.to(device)
height_position_ids = height_position_ids.to(device)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these lines are identical for video and image. I think we can move it under VisionModel.forward so that users can pass directly the image pixels and let the model handle the rest

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

Comment on lines +2958 to +2973
Examples:
Temporal (Time): 3 patches, representing different segments of the video in time.
Height: 2 patches, dividing each frame vertically.
Width: 2 patches, dividing each frame horizontally.
We also have some important parameters:
fps (Frames Per Second): The video's frame rate, set to 1. This means one frame is processed each second.
tokens_per_second: This is a crucial parameter. It dictates how many "time-steps" or "temporal tokens" are conceptually packed into a one-second interval of the video. In this case, we have 25 tokens per second. So each second of the video will be represented with 25 separate time points. It essentially defines the temporal granularity.
temporal_patch_size: The number of frames that compose one temporal patch. Here, it's 2 frames.
interval: The step size for the temporal position IDs, calculated as tokens_per_second * temporal_patch_size / fps. In this case, 25 * 2 / 1 = 50. This means that each temporal patch will be have a difference of 50 in the temporal position IDs.
input_ids: [V V V V V V V V V V V V T T T T T], here V is for vision.
vision temporal position_ids: [0, 0, 0, 0, 2, 2, 2, 2, 4, 4, 4, 4]
vision height position_ids: [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
vision width position_ids: [0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 4, 5]
text temporal position_ids: [101, 102, 103, 104, 105]
text height position_ids: [101, 102, 103, 104, 105]
text width position_ids: [101, 102, 103, 104, 105]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you comment what is the diff from qwen2-vl and update the docs?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done.

@zucchini-nlp

Copy link
Copy Markdown
Member

Ping me again when it is ready for review, I will unsubscribe myself from notifications

@Kwai-Keye

Copy link
Copy Markdown
Author

@zucchini-nlp
Hi, Could you please take a look now? We've revised most of the code issues you pointed out, but some didn't quite fit our model, so we didn't make those changes.

@github-actions

Copy link
Copy Markdown
Contributor

[For maintainers] Suggested jobs to run (before merge)

run-slow: auto, keye_vl_1_5

@Kwai-Keye

Copy link
Copy Markdown
Author

@zucchini-nlp

@zucchini-nlp

Copy link
Copy Markdown
Member

@Kwai-Keye oke, today or tomorrow I will try to take a look. I'll also be on vacation starting Thursday until November, so the review process will be a bit slower

In the meantime, can you take a look at failing tests?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants