mkd-hika/keural-mid-vlm-bilingual
Keural Mid VLM — Bilingual (EN / KO)
<img alt="encoder" src="https://img.shields.io/badge/encoder-183.6M%20frozen-blue"> <img alt="trainable" src="https://img.shields.io/badge/trainable-14.0M-success"> <img alt="languages" src="https://img.shields.io/badge/languages-EN%20%2B%20KO-blueviolet"> <img alt="decoder" src="https://img.shields.io/badge/decoder-Qwen2.5--7B--Instruct-informational"> <img alt="precision" src="https://img.shields.io/badge/precision-bfloat16-informational"> <img alt="pope" src="https://img.shields.io/badge/POPE%20vs%20blind-%2B25.95-brightgreen"> <img alt="mme" src="https://img.shields.io/badge/MME%20vs%20blind-%2B446.9-brightgreen"> <img alt="status" src="https://img.shields.io/badge/status-training%20complete-success">
Developed by MKD Co., Ltd. · Encoder: [keural-vision-encoder-mid](https://huggingface.co/mkd-hika/keural-vision-encoder-mid) · Code: [github.com/mkd-hika/Keural-VLM-Mid-level](https://github.com/mkd-hika/Keural-VLM-Mid-level)
A bilingual vision-language model built on Keural Mid, a 183.6M-parameter vision encoder trained from random initialization — not a CLIP, ViT or DINO derivative.
This repository contains the trained bridge only: a projector and LoRA adapters, 37 MB total. The encoder and decoder load from their own repositories.
Measured vision contribution
A vision-language model can post respectable scores while barely using the image — "what colour is the banana?" is answerable from language priors alone. Every benchmark below was therefore run twice: once normally, once with the visual tokens removed and everything else held constant.
The delta is the encoder's contribution. It is the one number a language model cannot manufacture.
Two figures qualify the headline numbers and are reported because they are what a careful reader will check:
POPE yes-ratio is 0.492 against a gold ratio of 0.500. The model discriminates on object existence rather than defaulting to one answer. A model replying "yes" indiscriminately scores ~50% accuracy while being useless, so accuracy without the yes-ratio is uninterpretable.
The blind VQAv2 score of 39.83% lands where language-prior performance is expected. That the baseline behaves as theory predicts is corroborating evidence that the measurement itself is sound.
Composition
14.0M trainable parameters against 7.8B frozen. The encoder is never fine-tuned at any learning rate, so every result above is attributable to the Stage 1 representation plus a trained bridge.
Usage
import torch, torchvision.transforms as T
from PIL import Image
from transformers import AutoModel, AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
from huggingface_hub import hf_hub_download
from alignment.projectors import LevelAwareProjector # github.com/mkd-hika/Keural-VLM-Mid-level
DT = torch.bfloat16
REPO = "mkd-hika/keural-mid-vlm-bilingual"
vision = AutoModel.from_pretrained(
"mkd-hika/keural-vision-encoder-mid", trust_remote_code=True, dtype=DT).cuda().eval()
tok = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
llm = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-7B-Instruct", dtype=DT, device_map="auto")
llm = PeftModel.from_pretrained(llm, REPO).eval()
proj = LevelAwareProjector(encoder_dim=768, llm_dim=3584, hidden_dim=2048).cuda().to(DT)
proj.load_state_dict(torch.load(hf_hub_download(REPO, "projector.pt")))
proj.eval()
tf = T.Compose([T.Resize((512, 512)), T.ToTensor(),
T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
@torch.no_grad()
def ask(image_path: str, question: str) -> str:
px = tf(Image.open(image_path).convert("RGB")).unsqueeze(0).cuda().to(DT)
vis = proj(vision(px, token_budget=512)) # (1, 512, 3584)
emb = llm.get_input_embeddings()
ids = tok.apply_chat_template([{"role": "user", "content": question}],
tokenize=True, add_generation_prompt=True,
return_tensors="pt").to(vis.device)
inp = torch.cat([vis, emb(ids).to(DT)], dim=1)
out = llm.generate(
inputs_embeds=inp,
attention_mask=torch.ones(inp.shape[:2], dtype=torch.long, device=vis.device),
max_new_tokens=128, do_sample=False, pad_token_id=tok.pad_token_id)
return tok.decode(out[0], skip_special_tokens=True)
ask("photo.jpg", "What is in this image?")
ask("photo.jpg", "이 이미지에 무엇이 있나요?")Inference must run at 512×512 with a 512-token budget. Both are what Stage 2 trained at, neither is auto-detected, and a mismatch degrades output silently with no error raised.
Training
2× NVIDIA H200 · DistributedDataParallel · bfloat16 · effective batch 64 · seed 42. Label masking supervises assistant turns only, so the model learns to answer rather than to reproduce the question.
On the bilingual mixture. It is 60% Korean / 40% English, rebalanced from an original 70/30 in response to a measured failure rather than a hunch. The English-only model scored 1.73% strict against 48.60% lenient on VQAv2 — a 47-point divergence caused by answer format, not perception. Asked "Is this rice noodle soup?" with gold answer "yes", it replied "Yes, this is a bowl of rice noodle soup", which exact-match scoring credits as zero. The mixture carried only verbose conversational data and no English short-answer supervision. Adding 84,590 short-answer records raised strict accuracy to 53.04%, and strict and lenient now agree to within 0.54 points.
Scope and limitations
- Long-form generation fabricates detail. Asked for a detailed description the model invents plausible objects that are not present. Short answers are substantially more reliable, so answer length functions as a reliability control rather than a stylistic one.
- Text recognition is partial. No OCR data was used in training. The model scores 110.0 on the MME OCR category against a blind 50.0 and reads large, high-contrast signage, but not documents or small text.
- Output is sensitive to prompt phrasing. On POPE, the instruction "Answer yes or no only" — absent from training — collapsed the yes-ratio to 0.050, while the trained phrasing gave 0.492. Prompts resembling the training format behave materially differently from those that do not.
- The encoder bounds everything downstream. At 37.2% zero-shot ImageNet it is undertrained relative to CLIP ViT-L/14 (~75%), and its Stage 1 loss was still declining when the run ended.
- Single images only. No temporal modelling.
Citation
@misc{keural_mid_vlm_2026,
title = {Keural Mid VLM: A Bilingual Vision-Language Model on an
Adaptive-Tokenization Encoder},
author = {Barki, Hika},
year = {2026},
url = {https://huggingface.co/mkd-hika/keural-mid-vlm-bilingual},
note = {MKD Co., Ltd.}
}License — Proprietary, MKD Co., Ltd. Qwen2.5-7B-Instruct (Apache-2.0) is used as the decoder and is not redistributed here.
