How to use from the
Use from the
Transformers library
# Use a pipeline as a high-level helper
from transformers import pipeline

pipe = pipeline("image-text-to-text", model="KORMo-VL/KORMo-Web-10B")
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"},
            {"type": "text", "text": "What animal is on the candy?"}
        ]
    },
]
pipe(text=messages)
# pip install -U transformers accelerate
# Load model directly
from transformers import AutoProcessor, AutoModelForMultimodalLM

processor = AutoProcessor.from_pretrained("KORMo-VL/KORMo-Web-10B")
model = AutoModelForMultimodalLM.from_pretrained("KORMo-VL/KORMo-Web-10B", device_map="auto")
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"},
            {"type": "text", "text": "What animal is on the candy?"}
        ]
    },
]
inputs = processor.apply_chat_template(
	messages,
	add_generation_prompt=True,
	tokenize=True,
	return_dict=True,
	return_tensors="pt",
).to(model.device)

outputs = model.generate(**inputs, max_new_tokens=256)
print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:]))
Quick Links

KORMo-Web-10B

KORMo-Web-10B is a Korean-first web agent built entirely on the KORMo model family, which KAIST MLP Lab trains from scratch. It reads a screenshot, thinks, and takes one browser action at a time (click, type, scroll, move between tabs and sites) until the task is done.

Among the open web agents we compared, it scores the highest in Korean (30.1%) on Online-Mind2Web, and 29.0% in English.

From a Korean LLM to a Korean web agent

KORMo-Web-10B is the third step of one Korean lineage, not a fine-tune of a foreign base model:

Step Model What it adds
1 KORMo-10B Koreanโ€“English LLM trained from scratch, with its own Korean tokenizer
2 KORMo-VL Vision: SigLIP encoder + KORMo-10B, trained on Korean document and UI images
3 KORMo-Web-10B Web agent: large-scale web understanding data and browser trajectories, in Korean and English

Because every stage was trained with Korean as a first language, the model handles Korean pages, Korean UI terms and natural Korean requests directly.

Performance

All models below ran the same 612 live-website tasks (300 English, 312 Korean), each with its own prompt and action format, and were scored by the same LLM judge.

Model Size Online-Mind2Web EN Online-Mind2Web KO
Qwen3.5-9B (base, no fine-tuning) 9B 24.7 16.7
Fara-1.5-4B 4B 20.7 7.7
UI-TARS-1.5-7B 7B 22.3 20.2
OpenWebRL-4B 4B 32.7 15.4
KORMo-Web-10B (ours) 11B 29.0 30.1
GPT-6-luna (proprietary) โ€“ 63.0 65.7
Gemini-3.8-flash (proprietary) โ€“ 74.0 80.1

Success rate (%). The denominator is always the full task count, so crashed or empty runs count as failures.

KORMo-Web-10B has the best Korean score among the open web agents above, by about 10 points.

Why KORMo-Web-10B

  • Korean from the ground up. Built on a Korean LLM trained from scratch, not adapted from an English-first model.
  • Korean and English, natural requests. Handles short commands as well as long, conversational instructions in either language.
  • Screenshot-only. It needs no DOM or accessibility tree; it acts on what is on screen and checks each action's result on the next screenshot.
  • Thinks, then acts. A short reasoning step precedes every action, so its behaviour is easy to inspect.
  • Open and ready to run. Weights, model code for transformers 5, a vLLM path, a reference browser harness and the exact inference settings are all included.

Quickstart

Tested with transformers 5.12.1 and vLLM 0.23.0. The model runs on a single GPU.

transformers does not ship the KORMo text model, so this repo includes it (_modeling_kormo.py) together with a small loader, kormo_load.py:

  • kormo_load.register(path) registers the KORMo text model. Call it before loading the processor or the model.
  • kormo_load.patch_vision(model) feeds the SigLIP features after post-layernorm to the projector, as in training. Without it the model still runs but misreads screenshots.

Inference example (one step, transformers)

pip install -U "transformers>=5.12" torch pillow huggingface_hub
huggingface-cli download KORMo-VL/KORMo-Web-10B --local-dir KORMo-Web-10B
import json, sys, torch
from PIL import Image
from transformers import AutoModelForImageTextToText, AutoProcessor

M = "KORMo-Web-10B"
sys.path.insert(0, M)
import kormo_load
kormo_load.register(M)
processor = AutoProcessor.from_pretrained(M)
model = AutoModelForImageTextToText.from_pretrained(M, dtype=torch.bfloat16, device_map="cuda").eval()
kormo_load.patch_vision(model)

SYSTEM = open(f"{M}/system_prompt.md").read().strip()
TOOLS = json.load(open(f"{M}/tools.json"))
obs = ("<observation>\nscreen size: 1280 x 720\nCurrent tab: 0\nAvailable tabs:\n"
       "- Tab 0 (active): https://www.google.com/\n\nurl: https://www.google.com/\nscreenshot:\n")
messages = [
    {"role": "system", "content": SYSTEM},
    {"role": "user", "content": [
        {"type": "text", "text": "<user_request>\n๊ตฌ๊ธ€์—์„œ KAIST ๋ฅผ ๊ฒ€์ƒ‰ํ•ด์„œ ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€๋ฅผ ์—ด์–ด์ค˜.\n</user_request>\n" + obs},
        {"type": "image", "image": Image.open("screen.png").convert("RGB")},
        {"type": "text", "text": "\n</observation>"},
    ]},
]
inputs = processor.apply_chat_template(messages, tools=TOOLS, add_generation_prompt=True,
                                       tokenize=True, return_dict=True, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=16384, do_sample=True, temperature=0.6, top_p=0.95, top_k=20)
print(processor.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=False))

The output is a short <think> block followed by one tool call:

<think>
I can see the Google home page with an empty search box. I have not searched yet.
My plan: 1. Click the search box. 2. Type "KAIST". 3. Press Enter and open the official site.
</think>

<tool_call>
<function=click>
<parameter=x>
500
</parameter>
<parameter=y>
427
</parameter>
</function>
</tool_call>

Coordinates are normalized to 0โ€“1000. Convert them to pixels with x / 1000 ร— width and y / 1000 ร— height.

Run the agent (vLLM)

vLLM does not include the KORMo architecture either. The KORMo text layers have the Llama structure, so vllm/convert_to_vllm.py renames two parameter names and writes a folder vLLM loads natively. vllm/sitecustomize.py turns SigLIP post-layernorm back on inside vLLM.

1. Convert (once)

pip install -U "vllm>=0.23.0" openai playwright safetensors
playwright install chromium
python KORMo-Web-10B/vllm/convert_to_vllm.py KORMo-Web-10B KORMo-Web-10B-vllm

2. Start the model server

PYTHONPATH=$PWD/KORMo-Web-10B/vllm vllm serve ./KORMo-Web-10B-vllm --served-model-name KORMo-Web-10B \
  --max-model-len 65536 --limit-mm-per-prompt '{"image":1,"video":0}'

Check that the server log prints [kormo-vllm] SigLIP post_layernorm enabled.

3. Run a browser task

python KORMo-Web-10B/examples/agent_playwright.py --model KORMo-Web-10B \
  --task "๋‹ค๋‚˜์™€์—์„œ 50๋งŒ ์› ์ดํ•˜, 10์ธ์น˜ ์ด์ƒ ํƒœ๋ธ”๋ฆฟ 3๊ฐœ๋ฅผ ์ฐพ์•„์„œ ๊ฐ€๊ฒฉ์„ ์•Œ๋ ค์ค˜"

The agent opens Chromium, prints each action as it goes, and finishes with the model's answer.

How It Works

user       <user_request> task </user_request>  + observation (tabs, url, screenshot)
assistant  <think> what I see ยท what is done ยท plan </think>  <tool_call> one action </tool_call>
tool       action result  + new observation (newest screenshot only)
โ€ฆ          repeat until finished(answer)
  • Action space: 22 browser tools: click, type, hotkey, scroll, drag, goto, tab control, finished, and others (tools.json).
  • Memory: the full text history of thoughts, actions and observations is kept. Only the current screenshot is sent.
  • Recommended settings: temperature 0.6, top_p 0.95, top_k 20, thinking on, up to 16k tokens per step and 50 steps. These are already set in generation_config.json.

The exact message format, parsing rules and feedback strings are in HARNESS.md. Follow it if you build your own harness.

Evaluation Details

Tasks Online-Mind2Web: 300 English, 312 Korean
Judge GPT-6

Files

File Description
model.safetensors ยท config.json Weights and config (LLaVA-OneVision: SigLIP + KORMo-10B text model)
_configuration_kormo.py ยท _modeling_kormo.py KORMo text model code for transformers 5
kormo_load.py register() and patch_vision()
chat_template.jinja Chat template (XML tool calls, thinking on)
system_prompt.md ยท tools.json System prompt and 22-tool schema
HARNESS.md Full harness specification
examples/agent_playwright.py Reference browser agent (Playwright + OpenAI-compatible API). It does not execute upload.
vllm/convert_to_vllm.py ยท vllm/sitecustomize.py Convert for vLLM and the post-layernorm fix
generation_config.json ยท *processor_config.json ยท tokenizer*.json ยท special_tokens_map.json Sampling, processor and tokenizer configs

ํ•œ๊ตญ์–ด ์š”์•ฝ

KORMo-Web-10B๋Š” KAIST MLP ์—ฐ๊ตฌ์‹ค์ด ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•™์Šตํ•œ ํ•œ๊ตญ์–ด ๋ชจ๋ธ KORMo-10B โ†’ KORMo-VL์„ ์ด์–ด ๋งŒ๋“  ํ•œ๊ตญ์–ด ์šฐ์„  ์›น ์—์ด์ „ํŠธ์ž…๋‹ˆ๋‹ค. ์Šคํฌ๋ฆฐ์ƒท๋งŒ ๋ณด๊ณ  ํ•œ๊ตญ์–ดยท์˜์–ด ์›น ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • Online-Mind2Web: EN 29.0, KO 30.1
  • ๋น„๊ตํ•œ ๊ณต๊ฐœ ์›น ์—์ด์ „ํŠธ ์ค‘ ํ•œ๊ตญ์–ด ์ ์ˆ˜๊ฐ€ ๊ฐ€์žฅ ๋†’์Šต๋‹ˆ๋‹ค.

Acknowledgements

Built on KORMo-VL and KORMo-10B by KAIST MLP Lab. Evaluated on Online-Mind2Web and its Korean counterpart.

Downloads last month
-
Safetensors
Model size
11B params
Tensor type
BF16
ยท
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Model tree for KORMo-VL/KORMo-Web-10B

Finetuned
(1)
this model

Collection including KORMo-VL/KORMo-Web-10B