Image-Text-to-Text
Transformers
Safetensors
Korean
English
llava_onevision
gui-agent
web-agent
computer-use
browser
korean
conversational
Instructions to use KORMo-VL/KORMo-Web-10B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use KORMo-VL/KORMo-Web-10B with Transformers:
# 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]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use KORMo-VL/KORMo-Web-10B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "KORMo-VL/KORMo-Web-10B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "KORMo-VL/KORMo-Web-10B", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/KORMo-VL/KORMo-Web-10B
- SGLang
How to use KORMo-VL/KORMo-Web-10B with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "KORMo-VL/KORMo-Web-10B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "KORMo-VL/KORMo-Web-10B", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "KORMo-VL/KORMo-Web-10B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "KORMo-VL/KORMo-Web-10B", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use KORMo-VL/KORMo-Web-10B with Docker Model Runner:
docker model run hf.co/KORMo-VL/KORMo-Web-10B
|
Download README.md from KORMo-VL/KORMo-Web-10B: direct link, hf CLI and curl.
- Browser
- Download file 11.2 kB
-
https://huggingface.co/KORMo-VL/KORMo-Web-10B/resolve/main/README.md
- Command line
-
hf download hf://KORMo-VL/KORMo-Web-10B/README.md
-
curl -L -o README.md https://huggingface.co/KORMo-VL/KORMo-Web-10B/resolve/main/README.md
11.2 kB
| license: apache-2.0 | |
| base_model: | |
| - KORMo-VL/KORMo-VL | |
| language: | |
| - ko | |
| - en | |
| pipeline_tag: image-text-to-text | |
| library_name: transformers | |
| tags: | |
| - gui-agent | |
| - web-agent | |
| - computer-use | |
| - browser | |
| - korean | |
| <style> | |
| #kormo-web-card { font-size: 16px; line-height: 1.6; overflow-wrap: break-word; } | |
| #kormo-web-card h1 { margin: 0 0 12px; font-size: 30px; line-height: 1.25; letter-spacing: -0.018em; } | |
| #kormo-web-card h2 { margin: 30px 0 10px; font-size: 22px; line-height: 1.3; letter-spacing: -0.012em; } | |
| #kormo-web-card h3 { margin: 22px 0 8px; font-size: 17px; font-weight: 700; line-height: 1.4; } | |
| #kormo-web-card h2 + h3 { margin-top: 14px; } | |
| #kormo-web-card p { margin: 0 0 10px; } | |
| #kormo-web-card ul, #kormo-web-card ol { margin: 6px 0 12px; padding-left: 22px; } | |
| #kormo-web-card li { margin: 4px 0; line-height: 1.55; } | |
| #kormo-web-card table { width: 100%; margin: 6px 0 14px; border-collapse: collapse; font-size: 14px; line-height: 1.45; font-variant-numeric: tabular-nums; } | |
| #kormo-web-card th, #kormo-web-card td { padding: 7px 10px; vertical-align: middle; } | |
| #kormo-web-card blockquote { margin: 12px 0 16px; padding: 0 0 0 14px; font-size: 15px; } | |
| #kormo-web-card blockquote p { margin: 0; } | |
| #kormo-web-card pre { margin: 10px 0 14px; padding: 14px 16px; overflow-x: auto; line-height: 1.5; } | |
| #kormo-web-card pre code { font-size: 13px; } | |
| #kormo-web-card > p:has(> em:only-child) { margin: 4px 0 14px; font-size: 13px; } | |
| #kormo-web-card .pills { margin: 4px 0 18px; } | |
| #kormo-web-card .pill { display: inline-block; margin: 0 6px 6px 0; padding: 3px 10px; border-radius: 999px; border: 1px solid rgba(127,127,127,.35); font-size: 13px; } | |
| @media (max-width: 640px) { | |
| #kormo-web-card h1 { font-size: 26px; } | |
| #kormo-web-card table { font-size: 13px; } | |
| #kormo-web-card th, #kormo-web-card td { padding: 7px 6px; } | |
| } | |
| </style> | |
| <div id="kormo-web-card"> | |
| # 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](https://huggingface.co/KORMo-Team/KORMo-10B-sft) | KoreanโEnglish LLM trained from scratch, with its own Korean tokenizer | | |
| | 2 | [KORMo-VL](https://huggingface.co/KORMo-VL/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) | |
| ```bash | |
| pip install -U "transformers>=5.12" torch pillow huggingface_hub | |
| huggingface-cli download KORMo-VL/KORMo-Web-10B --local-dir KORMo-Web-10B | |
| ``` | |
| ```python | |
| 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).to("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.aladin.co.kr/\n\nurl: https://www.aladin.co.kr/\nscreenshot:\n") | |
| messages = [ | |
| {"role": "system", "content": SYSTEM}, | |
| {"role": "user", "content": [ | |
| {"type": "text", "text": "<user_request>\n์๋ผ๋ ์ฌ์ดํธ์์ 'ํด์ปค์ค ํ ์ต RC'๋ฅผ ๊ฒ์ํ ๋ค ๊ฐ์ฅ ๋จผ์ ํ์๋๋ ๋์์ ์ถ๊ฐ์ผ์ ์๋ ค์ค.\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)) | |
| ``` | |
| A real first step from our Online-Mind2Web run (Aladin home page): | |
| ```text | |
| <think>I see the Aladin homepage, with the search field labeled โํตํฉ๊ฒ์โ near the top. I have not yet searched for the book, so I still need to enter โํด์ปค์ค ํ ์ต RC,โ inspect the first resultโs publication date, and report that date. My plan: | |
| 1. Click the search field | |
| 2. Enter โํด์ปค์ค ํ ์ต RCโ and submit the search | |
| 3. Read the publication date of the first listed book | |
| This click targets the visible search field and is a safe, relevant first action. | |
| </think> | |
| <tool_call> | |
| <function=click> | |
| <parameter=x> | |
| 482 | |
| </parameter> | |
| <parameter=y> | |
| 212 | |
| </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)** | |
| ```bash | |
| 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** | |
| ```bash | |
| 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** | |
| ```bash | |
| 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`](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](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](https://huggingface.co/KORMo-VL/KORMo-VL)** and **[KORMo-10B](https://huggingface.co/KORMo-Team/KORMo-10B-sft)** by KAIST MLP Lab. Evaluated on **Online-Mind2Web** and its Korean counterpart. | |
| </div> | |