Qwen3.6-27B โ€” FRAME track LoRA adapter (clip-corrected)

LoRA adapter for Qwen3.6-27B, fine-tuned for the ORena SAVE FOCUS Challenge, FRAME track: single-frame visual question answering about surgical foreign objects (clips, sponges, needles, specimen bags, drains) left in the operative field.

Official leaderboard result: pre_evaluation_score = 0.5911 (rank 24). That is the challenge's own held-out evaluation, not a local split.

bucket accuracy
aggregation โ€” in-distribution 55.52%
aggregation โ€” out-of-distribution 60.64%
object_recognition โ€” in-distribution 68.54%
object_recognition โ€” out-of-distribution 51.76%
pre_evaluation_score (unweighted mean) 59.11%

Latency on the challenge hardware (single L40S, FP8 base): 1.38 s/question, 0 forfeited, 0 unanswered.

What is different about this adapter

It is a two-stage adapter. The first stage is ordinary supervised fine-tuning on the challenge data. The second stage corrects a specific, measurable failure.

The base fine-tune had learned an unconditional habit of predicting "clip" โ€” about 40% of the class-list answers in the training data contain one, so the model said clip almost regardless of the image. On the in-distribution procedure this is a good bet (answers containing clip were 78.5% correct). On the out-of-distribution procedure it was fatal: 99 out of 99 answers containing clip were wrong.

A dedicated probe showed the habit was not a perception error. The model said clip on 92.2% of frames with no clamps present and 94.2% of frames with clamps present โ€” essentially independent of what was in the picture. It was a language prior, not a misidentification, and it could not be fixed by telling the model the procedure type (every procedure in the training data is clip-heavy, so that field carries no signal).

The correction stage therefore adds out-of-distribution frames where clips are genuinely absent, forcing the prediction to be grounded in pixels. Frames come from SAR-RARP50 (EndoVis 2022, CC BY-NC-SA 4.0), with foreign-object labels derived from its hand-drawn segmentation masks โ€” suturing needle โ†’ Needle; instruments ignored; ambiguous frames dropped.

Measured on 180 held-out prostatectomy frames, the rate of answers wrongly containing a clip fell from 89.4% to 0.6%, and the official out-of-distribution object-recognition bucket rose +6.58 points.

Known trade-off. This adapter buys that gain partly by collapsing its answer diversity on unfamiliar footage (it answers "needle" on 172 of those 180 frames), which cost โˆ’2.62 points on the in-distribution object-recognition bucket. Net gain over the uncorrected adapter is +1.14 points. A revision that keeps the correction without the collapse is in progress.

Configuration

LoRA r=32, alpha=64, dropout=0.05, 16 target module names resolving to 614 modules: the full vision tower (attention, MLP, patch_embed, and the visionโ†’language merger), and the full language tower โ€” including the 48 Gated DeltaNet layers of this hybrid-attention model (in_proj_qkv, in_proj_z, in_proj_a, in_proj_b, out_proj), which a naive target list silently misses.

Usage

import torch
from transformers import AutoModelForImageTextToText, AutoProcessor
from peft import PeftModel
from PIL import Image

BASE = "Qwen/Qwen3.6-27B"
model = AutoModelForImageTextToText.from_pretrained(
    BASE, dtype=torch.bfloat16, device_map="cuda:0").eval()
model = PeftModel.from_pretrained(model, "Potestates/qwen3.6-27b-frame-lora").eval()
processor = AutoProcessor.from_pretrained(BASE)

image = Image.open("frame.png").convert("RGB")   # native resolution โ€” do not resize
question = "List all foreign objects that are visible in this video frame. " \
           "Please provide the class names or answer with none."

messages = [{"role": "user", "content": [
    {"type": "image", "image": image},
    {"type": "text",  "text": question},
]}]
text = processor.apply_chat_template(
    messages, tokenize=False, add_generation_prompt=True, enable_thinking=False)
inputs = processor(text=[text], images=[image], return_tensors="pt").to(model.device)

with torch.inference_mode():
    out = model.generate(**inputs, max_new_tokens=32, do_sample=False)
print(processor.batch_decode(out[:, inputs["input_ids"].shape[1]:],
                             skip_special_tokens=True)[0].strip().rstrip(" ."))

Things that matter for reproducing the score

  • Raw question only. No system prompt, no foreign-object definitions, no procedure type. The model was fine-tuned this way; prepending anything moves you off distribution.
  • Do not resize the image. Qwen3.6 has no fixed input resolution, so resizing changes the number of vision tokens.
  • enable_thinking=False. Leaving the reasoning trace on burns the token budget.
  • Greedy decoding. Self-consistency sampling was measured and it loses 1.7 points on counting questions.
  • Strip trailing punctuation before scoring; the official parser is strict about exact-match formats.

Known weak point

Counting (answer_format=number) is the weakest category and has resisted every intervention we tried: self-consistency (โˆ’1.7), high-resolution upsampling (โˆ’0.4), count-weighted loss (โˆ’2.1), a weakly-supervised density head (0.000 exact match), enumeration prompting (flat), and an external detector (โˆ’13). Linear probes across layers read counts worse than the model's own generation, which suggests the count is not linearly present in the hidden states at all.

Citation

Base model: Qwen3.6-27B (Apache-2.0). Correction data: SAR-RARP50, EndoVis 2022 (CC BY-NC-SA 4.0) โ€” non-commercial.

Downloads last month
5
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Model tree for Potestates/qwen3.6-27b-frame-lora

Base model

Qwen/Qwen3.6-27B
Adapter
(590)
this model