Generation problems with Holo-3.1-9B

#1
by Charles-ALaurin - opened

The model Holo-3.1-9B generation looks kinda broken right now. Here's an exemple of the code I'm running and the generation from the model :

from transformers import AutoModelForImageTextToText, AutoProcessor
from transformers.models.qwen2_vl.image_processing_qwen2_vl import smart_resize

### Loading model
holo_model = "Hcompany/Holo-3.1-9B"
model = AutoModelForImageTextToText.from_pretrained(
    holo_model,
    # torch_dtype="auto",
    # attn_implementation="flash_attention_2",
    device_map="auto",
)
model.eval()
processor = AutoProcessor.from_pretrained(holo_model)

### Resizing image
from PIL import ImageDraw
original_image = Image.fromarray(video[0])
min_pixels = 56 * 56
max_pixels = 28 * 28 * 1280

image_processor = processor.image_processor
resized_height, resized_width = smart_resize(
    original_image.height,
    original_image.width,
    factor=image_processor.patch_size * image_processor.merge_size,
    min_pixels=min_pixels,
    max_pixels=max_pixels,
)
frame_questionned = original_image.resize(size=(resized_width, resized_height), resample=None)  # type: ignore

### Generating prompt
guidelines = "Localize an element on the GUI image according to my instructions and output a click position as Click(x, y) with x num pixels from the left edge and y num pixels from the top edge."
new_messages = [{
    "role": "user",
    "content": [
        {"type": "image", "image": frame_questionned},
        {"type": "text", "text": f"{guidelines}\nLocalize the cursor."},
    ],
}]

text = processor.apply_chat_template(
    new_messages, 
    tokenize=False, 
    add_generation_prompt=True,
    enable_thinking=True
)

inputs = processor(
    text=[text],
    images=[frame_questionned],
    padding=True,
    return_tensors="pt",
)
inputs = inputs.to("cuda")

### Generating answer 
generated_ids = model.generate(
    **inputs, 
    temperature=0.6,
    max_new_tokens=512,
    do_sample=True,
    top_p=0.95,
    top_k=20,
    num_return_sequences=10
)
generated_ids_trimmed = generated_ids[:, inputs.input_ids.shape[-1]:]
res = processor.batch_decode(generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False)

This is the output I get :

'The9\n\n=").\n\n\n"),即。\n\n、 5 works"(),或者\n\n。\n=").\n\n和ch"。\n")\n\n>").>").\n=").\n .").\n\n\n\n").\n\n=").\n。=").\n=").\n=").\n=").\n [。")\n\n\n\n),\n=").\n".\n="). ,,\n</think>\n\n\n".\n}")\n\n。\n\n\n ", ,,\n</think>。)=").\n".\n}.\n",\n",\n)".\n").\n".\n ",=").\n=").\n "。\n" " "\n", ").\n " " "\n",")\n\n。\n "。", "", " ".", "", "。 "。 " ,,\n</think>)。\n " " ".\n",完璧。\n", " " "\n", " " " "\n", " ", " ",\n".").\n " " "\n " (。"),\n".\n " "。 " " "\n ".\n ".\n " " "\n ").\n " " "\n " "\n",").",\n".")\n=").\n "。\n "。\n " " ".\n ",".\n " "。", "", " " "\n " "\n ", " "\n " "\n ").\n " " "\n " "\n " "\n " "\n ", " "\n ".\n " " "\n " "\n \\", " " "\n ", ".", " " "\n " " "\n \\", " " "\n " "\n \\",需要山体"。" " ", "", "。 "。\n " "\n " "\n " "\n ". "", " "。\n".", " " "\n " "\n \\x amministr "[。",".", " "。 "e过程和\n\n。。 "。 "". "。 "。 " " ".\n " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "',

The same code works fine for previous models (Holo-2) and for Holo-3.1-4B

Hi Charles, and thanks for the interest your showing for our models.
After checking that the weights weren't corrupted, I've managed to reproduce your bug.

What I believe is happening : You load in float32 with device_map="auto". fp32 9B is roughly 36 GB, so if it doesn't fit on your GPU, device_map="auto" silently offloads layers to CPU. Holo-3.1 is a hybrid linear-attention (Mamba-style) model that passes a recurrent state between layers, and that state gets corrupted when layers span GPU and CPU, giving you the corrupted output.
That's why the 4B works with the same code (fp32 4B fits on one device) but the 9B doesn't.

Suggested fix that worked on my end : keep it on one device by loading in bf16 so it fits:

model = AutoModelForImageTextToText.from_pretrained(
    "Hcompany/Holo-3.1-9B", dtype=torch.bfloat16, device_map={"": 0})

I don't expect much degradation due to the lowered precision.
Let me know if it works on your end!

PS : If it still doesn't fit on a single GPU, consider using vLLM

Sign up or log in to comment