ko-hand-ocr-vl โ ํ๊ธ ์๊ธ์จ OCR ์ ์ฉ VL ๋ชจ๋ธ (0.8B)
์ฌ์ง์ ๊ทธ๋๋ก ๋ฃ์ผ๋ฉด ์๊ธ์จ๋ฅผ ๊ธ์๋ก ๋๋ ค์ฃผ๋ ์คํ ์จ์ดํธ ๋ชจ๋ธ์ ๋๋ค. Qwen3.5-0.8B ๋ฅผ ํ๊ธ ์๊ธ์จ๋ก ๋ฏธ์ธ์กฐ์ ํ๊ณ ๊ตฌ์กฐ๋ ํ ์นธ๋ ์ ๋ฐ๊ฟจ์ต๋๋ค. ๊ทธ๋์ Qwen3.5 ๋ฅผ ์ฌ๋ฆฌ๋ ๊ณณ โ Ollama, LM Studio, llama.cpp, vLLM, transformers โ ์ ์ ์ฝ๋ ์์ด ๊ทธ๋๋ก ์ฌ๋ผ๊ฐ๋๋ค.
GGUF(LM Studioยทllama.cppยทOllama)๋ localdeel/ko-hand-ocr-vl-GGUF ์ ์์ต๋๋ค.
๊ฐ์ ์ ์ฅ์ ๊ณ์ด์ ko-hand-ocr(41M)๋ ์๋ผ ๋ ํ ์ค๋ง ์ฝ๋ ์๊ณ ๋น ๋ฅธ ๋ชจ๋ธ์ด๊ณ , ์ด๊ฒ์ ์ฌ์ง ํต์งธ๋ฅผ ์ฝ์ต๋๋ค. ์๋ผ ๋ ์ค ํ๋๋ง ์ฝ์ ๋๋ ๋์ด ๋น์ทํฉ๋๋ค โ ์ํ ๊ธ์จ์ฒด๋ ์ด๊ฒ์ด, ์ฌ์ง ์ค ์นธ์ 41M ์ด ์กฐ๊ธ ๋์ต๋๋ค. 41M ์ ๋ฐ๋ ํฌ๊ธฐ๊ฐ 17๋ถ์ 1์ด๊ณ GPU ์์ ์ค์ 3.9๋ฐฐ ๋นจ๋ฆฌ ์ฝ์ต๋๋ค(์๋ ํ, ๊ฐ์ ํ์์ ์ฐ ๊ฐ).
2026-10-12 โ ์ดํ๋ฅผ ์๋ผ ๊ฐ๋ฒผ์์ก์ต๋๋ค. ์๋ณธ Qwen3.5 ์ ์ดํ 248,077๊ฐ ๊ฐ์ด๋ฐ ํ๊ธยท์๋ชจยท์ซ์ยท๊ธฐํธยท์งง์ ์๋ฌธ ์กฐ๊ฐ๊ณผ ํ์ตยท์ํ์ ์ฐ์ธ ํ ํฐ๋ง ๋จ๊ฒจ 59,453๊ฐ๋ก ์ค์์ต๋๋ค(ํ๋ผ๋ฏธํฐ 853M -> 660M). ๋ค์ ํ์ตํ์ง ์์ ๊ฐ์ ํ์ด๊ณ , ์ํ ๊ธ์จ์ฒดยท์ฒ์ ๋ณด๋ ๊ธ์จ์ฒดยท์ฌ์ง ์ค ์นธยท์ฌ์ง ํต์งธ์์ ๋ต์ด ๊ธ์ ํ๋๊น์ง ๊ฐ์์ต๋๋ค โ transformers ๋ก๋, llama-server (Q8_0, ํ ์ค์ฉ) ๋ก๋. ๋ฐ๋ ํฌ๊ธฐ๋ safetensors 1.63GB -> 1.27GB, Q8_0 774MB -> 570MB, Q4_K_M 505MB -> 345MB ์ด๊ณ , llama.cpp ์์ ๊ธ์๋ฅผ ๋ด๋ ๋น ๋ฅด๊ธฐ๊ฐ 26~36% ์ฌ๋์ต๋๋ค(์ด PC, llama-bench). ์ดํ์์ ๋บ ๊ธด ์์ด ๋ฑ๋ง๋ก๋ง ์ง์ ์ค 200๊ฐ์์๋ 173๊ฐ๊ฐ ๊ฐ์๊ณ ์๋ชจ ๋ฎ์์ด 98.34 -> 98.01 ๋ก ์กฐ๊ธ ๋ด๋ ค๊ฐ์ต๋๋ค. ์ค ๊ฒฌ์คํ์ ๋น ๋ฅด๊ธฐ๋ ์๋ฅธ ํ์ผ๋ก ๋ค์ ์ฐ ๊ฐ์ด๊ณ , ์ฌ์ง ํต์งธ์ ใ์ด๋์ ๋๋ ค๋ ๊ฐ์๊ฐใ ํ๋ ์๋ฅด๊ธฐ ์ ์ ์ฐ ๊ฐ์ ๋๋ค(๋ต์ด ๊ฐ์ ๊ทธ๋๋ก ๋ก๋๋ค). ์๋ฅด๊ธฐ ์ ํ์ ์ด ์ ์ฅ์์ ํ๊ทธ
full-vocab์ ์์ต๋๋ค.
์ผ๋ง๋ ์ฝ๋
๋ชจ๋ ๊ฐ์ ์ํ์ง, ๊ฐ์ PC(RTX 5060 Laptop 8GB)์์ ์ฐ ๊ฐ์ ๋๋ค. ์ํ ๊ธ์จ์ฒด๋ ํ์ต์์ ๋บ ๊ธ๊ผด์ด๊ณ , ์ฌ์ง 11์ฅ์ ์ฌ๋์ด ์ค์ ๋ก ์ด ์๊ธ์จ์ด๋ฉฐ ํ์ต์ ํ ์ฅ๋ ์ฐ์ง ์์์ต๋๋ค(๊ณต๊ฐํ์ง ์์ต๋๋ค). ์๋ชจ ๋ฎ์์ ๋์์๋ก, CER(๊ธ์ ์ค๋ฅ์จ)์ ๋ฎ์์๋ก ์ข์ต๋๋ค.
์ค ํ๋์ฉ โ ๋ค๋ฅธ OCR ๊ณผ ๊ฐ์ ์๋ก
| ๋ชจ๋ธ | ํฌ๊ธฐ | ์ํ ๊ธ์จ์ฒด 6๋ฒ (์๋ชจ ๋ฎ์ / CER) | ์ฒ์ ๋ณด๋ ๊ธ์จ์ฒด 24๋ฒ | ์ฌ์ง 11์ฅ ์ค ์นธ (์๋ชจ ๋ฎ์ / CER) | GPU ์ค/์ด |
|---|---|---|---|---|---|
| ko-hand-ocr-vl (์ด๊ฒ, 660M) | 1.27GB | 97.0 / 5.8 | 97.4 | 93.4 / 15.8 | 10.8 |
| Qwen3.5-0.8B (๋ฏธ์ธ์กฐ์ ์ ์๋ณธ) | 1.63GB | 53.0 / 161.8 | 51.4 | 54.2 / 115.3 | 9.6 |
| ko-hand-ocr ๋จ์ผ ๋ชจ๋ธ (41M, ์ค ์ ์ฉ) | 78MB | 96.8 / 7.2 | 97.3 | 94.2 / 13.4 | 42.0 |
| ko-hand-ocr ์์๋ธ (๋ชจ๋ธ 3๊ฐ) | 225MB | 97.1 / 6.7 | 97.7 | 96.5 / 8.6 | 8.3 |
| Qwen/Qwen3-VL-2B-Instruct | 3.96GB | 66.6 / 79.1 | 68.0 | 69.9 / 38.3 | 7.3 |
| PaddlePaddle/PaddleOCR-VL-1.6 | 1.79GB | 63.6 / 62.9 | 66.5 | 61.7 / 44.0 | 1.2 |
| ddobokki/ko-trocr | 408MB | 78.2 / 42.3 | 80.4 | 78.5 / 39.2 | 6.1 |
| PaddleOCR PP-OCRv5 (korean) | 13MB | 72.7 / 40.5 | 75.3 | 71.8 / 39.7 | 397.4 |
| EasyOCR (korean) | 15MB | 56.6 / 64.3 | 64.6 | 66.9 / 55.0 | 81.3 |
| Tesseract 5 (kor+eng) | 6MB | 17.7 / 97.3 | 19.7 | 13.2 / 98.6 | โ |
2026-10-13 ์ ์ด ๋ชจ๋ธ์ ๊ฐ์ PC ์์ ํ ๋ฒ์ ์์ต๋๋ค. ์ํ ๊ธ์จ์ฒด๋ 6๋ฒ ํฉ์ณ 640์ค, ์ค ์นธ์ ko-hand-ocr ์ ์ค ์๋ฅด๊ธฐ๋ก ์๋ผ ๋ชจ๋์๊ฒ ๊ฐ์ ์นธ์ ์ค๋๋ค. ์๋์๊ฒ๋ ๋ชจ๋ธ ์นด๋์ ์ฌ์ฉ๋ฒ ๊ทธ๋๋ก, ์์ฌ ๋ฝ๊ธฐ(greedy)๋ก ๋ฌป์ต๋๋ค. ๋ฌผ์์ Qwen ๊ณ์ด์ด ใ์ด ์ด๋ฏธ์ง์ ์ฐ์ธ ๊ธ์๋ฅผ ๊ทธ๋๋ก ์ฝ์ด ์ ์ผ์ธ์. ๊ธ์๋ง ์ถ๋ ฅํ์ธ์.ใ, PaddleOCR-VL ์ด ใOCR:ใ ์ ๋๋ค.
์ฌ์ง ํต์งธ
์ฌ์ง ํ ์ฅ์ ์๋ณธ ๊ทธ๋๋ก ์ค๋๋ค. ๊ทธ๋ฆผ์ 4,096ํ ํฐ๊น์ง๋ก ์ค์ฌ ๋ค์ด๊ฐ๋๋ค(llama.cppยทOllama ์ ๊ฐ์ ์ํ). ์ชฝ ์ ์ชฝ์ ๊ธ์๋ฅผ ๋ค ์ด์ด ๋ถ์ฌ ๊ฒฌ์ค ๊ฐ(ํต์งธ OCR ์ ์ฌ๋ ํํ ์)์ด๊ณ , ์ค ์ง ์ ์ฝ์ ์ค์ ์ ๋ต ์ค๊ณผ ์ง์ง์ด ์ฐ ๊ฐ์ ๋๋ค. ์ ๋ตํ๊ฐ ํ ์ค์ ๋๋ํ ์ด ใ๋ถ์: โฆ ์ฑ๋ช : โฆใ ์ ๋ ์ค๋ก ๋๋ ์ ์ด ๋์ด์, ํ ์ค๋ก ๋ฐ๋ฅด๊ฒ ์ฝ์ด๋ ์ค ์ง์ผ๋ก๋ ๊น์ ๋๋ค. ์๋ VL ๋์ ์ฐ๋ฆฌ ์ํ์ ์์ฐ์ง ์๊ณ ๊ทธ์ชฝ ๊ธฐ๋ณธ ๊ทธ๋ฆผ ํฌ๊ธฐ ๊ทธ๋๋ก ์ค๋๋ค.
| ๋ชจ๋ธ | ์ชฝ ์๋ชจ ๋ฎ์ | ์ชฝ CER | ๊ฐ์ฅ ๋ฎ์ ์ฌ์ง(์ชฝ) | ์ค ์ง ์๋ชจ ๋ฎ์ |
|---|---|---|---|---|
| ko-hand-ocr-vl (์ด๊ฒ) | 94.3 | 15.3 | 78.3 | 95.6 |
| Qwen3.5-0.8B (์๋ณธ) | 72.7 | 42.1 | 55.3 | 62.1 |
| Qwen3-VL-2B-Instruct | 76.9 | 41.1 | 47.6 | 72.5 |
| PaddleOCR-VL-1.6 | 79.9 | 37.3 | 54.5 | 57.3 |
์ด๋์ ๋๋ ค๋ ๊ฐ์๊ฐ
๊ฐ์ ๋ชจ๋ธ์ ๋ฐ๋ ๊ธธ๋ง๋ค ๋ค์ ์์ต๋๋ค. ์์ํ๋ ๊ทธ๋ฆผ ํฌ๊ธฐ ๋ง์ถ๊ธฐ๊ฐ ๊ธธ๋ง๋ค ๋ฌ๋ผ์ ๊ทธ๋๋ก ๋ฏฟ์ง ์๊ณ ์์ต๋๋ค(์ด ํ๋ ๊ธ์จ์ฒด ๋ฒ๋ง๋ค 100์ค). llama.cpp ์ชฝ(LM StudioยทOllama ํฌํจ)์ด ์ฌ์ง์์ ๋ฎ์ ๊ฒ์ ์์ํ ํ์ด ์๋๋๋ค โ ์์ํ ์ ํ F16 GGUF ๋ ๊ฐ์ ๊ฐ์ด ๋์ต๋๋ค. ๊ทธ๋ฆผ ํฌ๊ธฐ๋ฅผ ๋ง์ถ๋ ๋ฒ์ด transformers ์ ๋ฌ๋ผ์์ ๋๋ค. llama.cpp ๋ ๊ฐ๋ก์ธ๋ก ๋น๋ฅผ ์งํค๋ฉฐ ์ค์ด๊ณ ๋จ๋ ๊ฐ์ฅ์๋ฆฌ๋ฅผ ๊ฒ์ ์ผ๋ก ์ฑ์ฐ๋ฉฐ, ์์ ๊ทธ๋ฆผ์ 8ํ ํฐ๊น์ง ์ค์ ๋๋ค(์ด ๋ชจ๋ธ์ 64ํ ํฐ๋ถํฐ ๋ฐฐ์ ์ต๋๋ค).
๊ทธ๋์ ๊ทธ๋ฆผ ์ต์ยท์ต๋ ํฌ๊ธฐ(64~4,096ํ ํฐ)๋ฅผ mmproj ํ์ผ ์์ ์ ์ด ๋์์ต๋๋ค(2026-10-09). llama.cpp ์ LM Studio ๋ ๋ฐ๊ธฐ๋ง ํ๋ฉด ์ด ๊ฐ์ ์๋๋ค โ ๊ฐ์ LM Studio ์์ ์ฌ์ง ์ค ์นธ์ด 90.8 -> 92.5, llama-server ์์ 90.9 -> 92.0 ์ผ๋ก ์ฌ๋์ต๋๋ค. Ollama 0.34.4 ๋ ์์ง ์ด ๊ฐ์ ์ฝ์ง ์์ ๊ทธ๋๋ก์
๋๋ค. ๊ฒ์ ์ฌ๋ฐฑ์ ํ์ผ๋ก ๋ฐ๊ฟ ์ ์์ต๋๋ค.
| ๋๋ฆฌ๋ ๊ธธ | ์ํ ๊ธ์จ์ฒด 6๋ฒ | ์ฌ์ง ์ค ์นธ | ์ฌ์ง ํต์งธ |
|---|---|---|---|
| transformers (bf16, safetensors) | 96.9 | 93.3 | 94.3 |
llama.cpp llama-server โ Q8_0 |
96.7 | 92.0 | 91.8 |
| LM Studio โ Q8_0, ๋ฐ์ ๊ทธ๋๋ก (์ค์ ์ ๊ฑด๋๋ฆผ) | 96.4 | 92.5 | 91.8 |
Ollama โ hf.co/โฆ:Q8_0, ๋ฐ์ ๊ทธ๋๋ก |
96.2 | 90.9 | 91.8 |
์ด๋ค ์ค์ ํ๋ฆฌ๋
์ค ์์ ๋ฌด์์ด ๋ค์๋์ง์ ๋ฐ๋ผ ๋๋ ๊ธ์ ์ค๋ฅ์จ(CER)์ ๋๋ค. ๋ฎ์์๋ก ์ข์ต๋๋ค.
๋น ๋ฅด๊ธฐ์ ๋ฉ์น
๋ฒค์น๋งํฌ๋ ์ด๋ ๊ฒ ์์ต๋๋ค
์ ์ซ์๊ฐ ์ด๋์ ๋์๋์ง ๋ค ์ ์ต๋๋ค. ๊ฐ์ ์ํ์ง๋ฅผ ๊ฐ์ PC ์์, ์ด ๋ชจ๋ธ์ ํ ๋ฒ์ ๋๋ ธ๊ณ (2026-10-13 14:59) ์ฌ์ง์ ํ์ต์ ํ ์ฅ๋ ์ฐ์ง ์์์ต๋๋ค.
์ํ์ง
| ์ํ์ง | ๋ฌด์์ธ๊ฐ | ํฌ๊ธฐ | ํ์ต์ ์ผ๋ |
|---|---|---|---|
| ์ํ ๊ธ์จ์ฒด 6๋ฒ | ๋ฌด๋ฃ ์๊ธ์จ ๊ธ๊ผด ์ฌ์ฏ ๋ฒ(OFL)๋ก ์ค์ ๊ทธ๋ฆฐ ๊ทธ๋ฆผ. ํ์ต ๊ทธ๋ฆผ๊ณผ ๊ฐ์ ๊ทธ๋ฆฌ๊ฐ๋ก ์ข ์ด ๊ฒฐยท๊ธฐ์ธ๊ธฐยท์ง์ด ์๊ตญ ๊ฐ์ ํ๋ค๊ธฐ๋ฅผ ์ ํ๊ณ , ์จ์์ ํ์ต์ ์ ์ฐ๋ ๊ณ ์ ๊ฐ์ ๋๋ค | 640์ค 4,448์ | ์ ์. ํ์ต ๊ธ๊ผด 450๋ฒ ๊ฐ์ด๋ฐ ์ด ์ฌ์ฏ๊ณผ ์๊น์๊ฐ ๋ฎ์ ๊ฒ(๋ฎ์ 0.7 ์ด์)๋ ๋บ์ต๋๋ค |
| ์ฒ์ ๋ณด๋ ๊ธ์จ์ฒด 24๋ฒ | ๋๋์๊ธ์จ 6 ยท ๊ทธ ๋ฐ 17 ยท ๊ตฌ๊ธ 1 (์๋ ๋ชฉ๋ก). ๊ฐ์ ๋ฐฉ์์ผ๋ก ๊ทธ๋ฆผ | 634์ค 3,614์ | ์ ์. ๋ชจ๋ธ์ ๊ณ ๋ฅด๋ ๋ฐ๋ ์ ์ โ ๊ทธ๋์ ใ๋๋ฃจ ์ฝ๋ใ๋ฅผ ๋ฌป๋ ์์ ๋๋ค |
| ์ฌ์ง 11์ฅ โ ์ค ์นธ | ์ฌ๋์ด ์ค์ ์์ ์ข ์ด์ ์์ผ๋ก ์จ์ ์ฐ์ ์ฌ์ง. ko-hand-ocr ์ ์ค ์๋ฅด๊ธฐ๋ก ์๋ผ ๋ชจ๋์๊ฒ ๊ฐ์ ์นธ์ ์ค๋๋ค | 34์ค 209์ | ์ ์. ์ฌ๋ ์๋ฃ๋ผ ๊ณต๊ฐํ์ง ์์ต๋๋ค |
| ์ฌ์ง 11์ฅ โ ํต์งธ | ๊ฐ์ ์ฌ์ง์ ์๋ฅด์ง ์๊ณ ํ ์ฅ ๊ทธ๋๋ก | 11์ฅ | ใ |
์ํ ๊ธ์จ์ฒด ์ค์ ์์์์ ์ค์ ๋ก ๋ณด๋ ๊ผด์ ์์ด ๋ง๋ญ๋๋ค. ๋๋ต ์ ์ ํ๋๊ฐ ๋ป ์๋ ์์ ์ ์ด์ด ๋ถ์ธ ์ค(์ด๋ฆยท์ํธ์ฒ๋ผ ์ธ์ด ์ง์์ด ์ ํตํ๋ ์ค โ ํ๋ง ๋ณด๊ณ ์ฝ๋ ํ์ ์ฝ๋๋ค), ์ ์ ํ๋๊ฐ ์์ ์นธ(ใ์ฑ๋ช : โฆใ, ใ์ผ์ : 2026.03.17ใ), ๋ค์ฏ์ ํ๋๊ฐ ์ ๋ชฉยท๋ผ๋ฒจ, ๋๋จธ์ง๊ฐ ๋ฌธ์ฅ์ ๋๋ค. ์ซ์ยท๋ ์งยท์๋ฌธ ์ฝ์ดยท๊ธฐํธ๊ฐ ์์ ๋๋ค. ํ์๋ชจ ์ค๊ณผ ๊ทธ ๊ธ๊ผด์ด ๋ชป ๊ทธ๋ฆฌ๋ ๊ธ์๊ฐ ๋ ์ค์ ๋บ๋๋ค โ ์๋ฌด๋ ๋งํ ์ ์๋ ์ค์ด๋ผ์์ ๋๋ค(2026-10-08 ์ ๊ณ ์น ์. ๊ทธ ์ ์ซ์์ ์์ด ๊ฒฌ์ฃผ์ง ์์ต๋๋ค).
์ฌ์ง ์ชฝ 12๋ฒ์งธ ์ฅ(์ ํด์๋ ์ธ์ ์์ + ์๋ช )์ ์๊ธ์จ ํ๋ ์ ๋ชฉํ๊ฐ ์๋๋ผ์ ์ฌ๊ธฐ๋ง ํ๊ณ ์ ์์์๋ ๋บ๋๋ค. ์ด ๋ชจ๋ธ์ ๊ทธ ์ฅ์์ 61.3% ์ ๋๋ค.
์ฒ์ ๋ณด๋ ๊ธ์จ์ฒด 24๋ฒ ๋ชฉ๋ก๋๋๋ธ๋ฌ์์คํฌ๋ฆฝํธ, KCC ๋๋ด๋๋ด์ฒด, ๊ฐ๋น์ ๋ด๋ฐ๋์ฒด, ๊ทธ๋ฆฌ์ด ๊ท์์ฒด, ๊ทธ๋ฆฌ์ด ํ๋กฌ์, ๋ ์๋์ด์ฒด, ์ธ๊ตฌ์ธ๊ตฌ์ฒด, ์ด๋น ๊น๋น ๋ฅธ์ฒด, ์ด๋น ๋ง์ธ ์ฝ์ฒด, ์ด๋น ์ค์์ฒด, ์ด๋น ์๋์ฒด, ์ด๋น ํธ์ ์ด์ฒด, ์จ๊ธ์ ๊ณต๋ถ์ํ์๋, ์จ๊ธ์ ์ธ์ฆ์ฒด, ์ค์ด๋ก์ฐ์ฐ์ด๋ฆฐ์ด ๋ฏผ๊ตญ, ์นดํ24 ๋๋, ํ๊ต์์ฌ ๊พธ๋ฌ๊ธฐ, ํ๊ต์์ฌ ์น ํ์ง์ฐ๊ฐ, ๋๋์๊ธ์จ ๊ธฐ์จ๋ฐ์, ๋๋์๊ธ์จ ๋ฐ๋ปํ ์๋ณ, ๋๋์๊ธ์จ ๋ถ์ฅ๋ ๋์น์ฒด, ๋๋์๊ธ์จ ์๋น ๊ธ์จ, ๋๋์๊ธ์จ ์ธํ ๋จธ๋๊ธ์จ, ๋๋์๊ธ์จ ํ๋์ฒด
์ ์
| ์ ์ | ์ด๋ป๊ฒ ์ ํ๋ |
|---|---|
| ์๋ชจ ๋ฎ์ | ์ฝ์ ๊ฒ๊ณผ ์ ๋ต์ ์๋ชจ(ใฑ ใ
ใ
โฆ)๋ก ํ๊ณ ๋์ด์ฐ๊ธฐ๋ฅผ ์ง์ด ๋ค ์ผ๋ง๋ ๋ฎ์๋(ํ์ด์ฌ difflib ๋น์จ). ใํใ์ ใํใ์ผ๋ก ์ฝ์ผ๋ฉด ์๋ชจ ์
๊ฐ์ด๋ฐ ํ๋๋ง ํ๋ ค 0.67 ์
๋๋ค. ์ค๋ง๋ค ๋ด์ ํ๊ท ํฉ๋๋ค |
| CER(๊ธ์ ์ค๋ฅ์จ) | ์ ๋ต์ด ๋๋๋ก ๊ณ ์ณ์ผ ํ๋ ๊ธ์ ์(ํธ์ง ๊ฑฐ๋ฆฌ) รท ์ ๋ต ๊ธ์ ์, ๋์ด์ฐ๊ธฐ๋ ์ง์ฐ๊ณ . ์ค๋ง๋ค ํ๊ท ๋ด์ง ์๊ณ ๊ธ์๋ฅผ ๋ค ๋ชจ์ ๋๋๋๋ค. ์ ๋ต๋ณด๋ค ๊ธธ๊ฒ ์ง์ด๋ด๋ฉด 100% ๋ฅผ ๋์ต๋๋ค(์๋ณธ Qwen3.5 ์ 161.8% ๊ฐ ๊ทธ ๊ฒฝ์ฐ) |
| ๊ฐ์ฅ ๋ฎ์ ๋ฒ / ์ฌ์ง | ํ๊ท ์ด ๊ฐ๋ฆฌ๋ ๋ฐ๋ฅ. ์ฌ์ฏ ๋ฒ ์ฌ์ด๊ฐ ๋ช ์ ์ฉ ๋ฒ์ด์ง๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ์ ์ต๋๋ค |
| ์ฌ์ง ํต์งธ โ ์ชฝ | ์ฝ์ ๊ธ์๋ฅผ ์ชฝ ์ ์ฒด๋ก ์ด์ด ๋ถ์ฌ ์ ๋ต ์ ์ฒด์ ๊ฒฌ์ค๋๋ค(ํต์งธ OCR ์ ์ฌ๋ ํํ ์) |
| ์ฌ์ง ํต์งธ โ ์ค ์ง | ์ฝ์ ์ค๊ณผ ์ ๋ต ์ค์ ๊ฐ์ฅ ๋ฎ์ ๊ฒ๋ผ๋ฆฌ ์ง์ง์ด ์ฝ๋๋ค. ์ ๋ตํ๊ฐ ํ ์ค์ ๋๋ํ ์ด ๋ ์นธ์ ๋ ์ค๋ก ์ ์ด ๋์ด์, ํ ์ค๋ก ๋ฐ๋ฅด๊ฒ ์ฝ์ด๋ ๊น์ ๋๋ค |
์ฅ๋น์ ํ
| GPU | NVIDIA GeForce RTX 5060 Laptop GPU (8GB) |
| CPU | AMD Ryzen 7 260 (๋ ธํธ๋ถ, 8์ฝ์ด 16์ค๋ ๋) |
| ์ด์์ฒด์ | Windows 11 Pro |
| PyTorch | 2.14.0+cu130 |
| ์ด ๋ชจ๋ธ (transformers) | transformers 5.16.1, bfloat16, ์์ฌ ๋ฝ๊ธฐ(greedy), ์ค ํ๋์ ์ต๋ 64ํ ํฐ. ์ฌ์ง ํต์งธ๋ ๊ทธ๋ฆผ์ 4,096ํ ํฐ๊น์ง๋ก ์ค์ฌ ๋ฃ์ |
| ๋ฌผ์ | ใ์ด ์ด๋ฏธ์ง์ ์ฐ์ธ ๊ธ์๋ฅผ ๊ทธ๋๋ก ์ฝ์ด ์ ์ผ์ธ์. ๊ธ์๋ง ์ถ๋ ฅํ์ธ์.ใ |
| llama.cpp | llama.cpp llama-server build 11474 (b9acf138a), CUDA |
| LM Studio | LM Studio โ ์์ง llama.cpp CUDA 12 2.55.0, ๋ฐ์ ์ค์ ๊ทธ๋๋ก |
| Ollama | Ollama 0.34.4, ๋ฐ์ ์ค์ ๊ทธ๋๋ก |
๋ชจ๋ธ๋ง๋ค ์ด๋ป๊ฒ ๋๋ ธ๋
์๋๋ ๋ชจ๋ ๋ชจ๋ธ ์นด๋์ ์ฌ์ฉ๋ฒ ๊ทธ๋๋ก ๋๋ ธ์ต๋๋ค. ์์ง๋ง๋ค ๋ฐ๋ก ๊น ํ๊ฒฝ์์ ๋๋ฆฌ๊ณ , ์๊ฐ์ ์์ง ์์์ ์ฐ ๊ฐ๋ง ์ ๋๋ค(๊ทธ๋ฆผ์ ๋๊ธฐ๋ ๊ฐ์ ๋บ๋๋ค).
| ๋ชจ๋ธ | ์ด๋ป๊ฒ |
|---|---|
| ko-hand-ocr ์์๋ธ | ๋ชจ๋ธ 3๊ฐ x ํ๋ค๊ธฐ ์ ์ ์ฝ๊ณ ์๋ก ๊ฐ์ฅ ๋ฎ์ ๋ต(๊ฐ์ด๋ฐ ๋ต) |
| ko-hand-ocr ๋จ์ผ ๋ชจ๋ธ | ko-hand-ocr 0.4.1 Reader, float32, ๋น 5, ํ๋ค๊ธฐ ์
|
| ddobokki/ko-trocr | transformers, float32, ๋น 5, ๊ธธ์ด ์ํ 16 -> 64 ๋ก ํ์ด ์ค |
| PaddleOCR PP-OCRv5 (korean) | paddleocr TextRecognition(korean_PP-OCRv5_mobile_rec) (paddleocr 3.7.0 / paddle 3.4.0) |
| EasyOCR (korean) | easyocr korean_g2 (ko+en), recognize() ์ ์ค ๊ทธ๋ฆผ ์ ์ฒด๋ฅผ ํ ์นธ์ผ๋ก (1.7.2) |
| Tesseract 5 (kor+eng) | tesseract 5.5.3, --oem 1 --psm 7 -l kor+eng |
| PaddlePaddle/PaddleOCR-VL-1.6 | transformers 5.16.1, bfloat16, ๋ฌผ์ 'OCR:', ์์ฌ ๋ฝ๊ธฐ, ์ต๋ 64ํ ํฐ |
| Qwen/Qwen3-VL-2B-Instruct | transformers 5.16.1, bfloat16, ๋ฌผ์ '์ด ์ด๋ฏธ์ง์ ์ฐ์ธ ๊ธ์๋ฅผ ๊ทธ๋๋ก ์ฝ์ด ์ ์ผ์ธ์. ๊ธ์๋ง ์ถ๋ ฅํ์ธ์.', ์์ฌ ๋ฝ๊ธฐ, ์ต๋ 64ํ ํฐ |
| ko-hand-ocr-vl (Qwen3.5-0.8B ๋ฏธ์ธ์กฐ์ ) | transformers 5.16.1, bfloat16, ๋ฌผ์ '์ด ์ด๋ฏธ์ง์ ์ฐ์ธ ๊ธ์๋ฅผ ๊ทธ๋๋ก ์ฝ์ด ์ ์ผ์ธ์. ๊ธ์๋ง ์ถ๋ ฅํ์ธ์.', ์์ฌ ๋ฝ๊ธฐ, ์ต๋ 64ํ ํฐ |
| Qwen/Qwen3.5-0.8B | transformers 5.16.1, bfloat16, ๋ฌผ์ '์ด ์ด๋ฏธ์ง์ ์ฐ์ธ ๊ธ์๋ฅผ ๊ทธ๋๋ก ์ฝ์ด ์ ์ผ์ธ์. ๊ธ์๋ง ์ถ๋ ฅํ์ธ์.', ์์ฌ ๋ฝ๊ธฐ, ์ต๋ 64ํ ํฐ |
๊ธ์จ์ฒด๋ง๋ค
ํฉ๊ณ ํ๋๋ง ๋ณด๋ฉด ๋ฌด๋์ง๋ ๊ธ์จ์ฒด๊ฐ ๊ฐ๋ ค์ง๋๋ค. ๋ฒ๋ง๋ค ์ค ์๊ฐ ๋ค๋ฅธ ๊ฒ์ ๋ชป ๊ทธ๋ฆฌ๋ ์ค์ ๋บ๊ธฐ ๋๋ฌธ์ ๋๋ค.
| ๊ธ์จ์ฒด | ์ค | ์ด ๋ชจ๋ธ | 41M ๋จ์ผ ๋ชจ๋ธ | 41M ์์๋ธ | ko-trocr (์๋ ๊ฐ์ด๋ฐ 1๋ฑ) |
|---|---|---|---|---|---|
| ๋๋ํ์คํฌ๋ฆฝํธ (NanumPenScript) | 112 | 95.4 | 95.4 | 96.2 | 69.1 |
| ๊ฐ์๊ฝ (GamjaFlower) | 112 | 97.2 | 97.9 | 97.9 | 82.1 |
| ํ์ด๋ฉ๋ก๋ (HiMelody) | 112 | 97.3 | 97.2 | 97.3 | 75.3 |
| ์ฑ๊ธ๋ฐ์ด (SingleDay) | 112 | 98.2 | 99.0 | 98.9 | 88.9 |
| ๋ํด๋ ๋ (EastSeaDokdo) | 97 | 95.0 | 93.1 | 94.1 | 65.9 |
| ๊ธฐ๋ํด๋ (KirangHaerang) | 95 | 99.0 | 97.9 | 97.8 | 87.9 |
์ฌ์ง๋ง๋ค (์ค ์นธ, ์๋ชจ ๋ฎ์)
| 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| ์ด ๋ชจ๋ธ | 94 | 100 | 98 | 82 | 100 | 94 | 89 | 100 | 88 | 91 | 93 |
| 41M ๋จ์ผ ๋ชจ๋ธ | 94 | 100 | 100 | 96 | 93 | 83 | 94 | 100 | 89 | 87 | 100 |
| 41M ์์๋ธ | 100 | 100 | 100 | 98 | 100 | 90 | 95 | 97 | 91 | 93 | 98 |
์ฌ์ง์ ์ฅ๋ง๋ค ์๋ ์ค๋ฟ์ด๋ผ ํ ์ค์ด ํ ์ฅ ์ ์๋ฅผ 10์ ๋๊ฒ ์์ง์ ๋๋ค. ๊ทธ๋์ ์ฌ์ง ์ชฝ ์ฐจ์ด๋ ๊ธ์จ์ฒด ์ชฝ๋ณด๋ค ํจ์ฌ ๋ ๋ฏฟ์ ๋งํฉ๋๋ค.
๋น ๋ฅด๊ธฐ๋ ์ด๋ ๊ฒ ์์ต๋๋ค
- ์๋ฅธ ์ค์ง๋ฆฌ ์๋ฅ ํ ์ชฝ์ ๊ธฐ์ค์ผ๋ก ์ฝ๋๋ค. ์ค ์๋ฅด๊ธฐ(CPU, ๋ชจ๋ ๊ฐ์ 0.40์ด) + ์ฝ๊ธฐ์ ๋๋ค.
- GPU ๋ ๋ฌถ์์ 1ยท4ยท8ยท16ยท32์ค๋ก ๋ฐ๊ฟ ๊ฐ๋ฉฐ ์ธ ๋ฒ์ฉ ์ฌ๊ณ , ์นด๋(8GB) ๋ฐ์ผ๋ก ๋์น์ง ์์ ๊ฒ ๊ฐ์ด๋ฐ ์ค๋น ๊ฐ์ฅ ์ผ ๋ฌถ์์ ์๋๋ค. ์ด ๋ชจ๋ธ์ 16์ค ๋ฌถ์์ด ๊ฐ์ฅ ์ธ๊ณ , ๊ทธ๋ VRAM ๊ผญ๋๊ธฐ๋ 2.2GB ์ ๋๋ค.
- CPU ๋ 1ยท8์ค ๋ฌถ์, ํฐ VL ๋ชจ๋ธ์ ์ค๋น 1์ด ์ํ์ด๋ผ 1์ค๋ง ์ฝ๋๋ค.
- CPU ๊ฐ์ ์ด ๋ ธํธ๋ถ์ ๊ทธ๋ ์ํ๋ฅผ ํฌ๊ฒ ํ๋๋ค. ์ค/์ด ์์ฒด๋ณด๋ค ๊ฐ์ ํ ์์ ์์๋ฅผ ๋ด ์ฃผ์ธ์.
๊ฐ์ง ์์ ๊ฒ โ ๋๊ตฌ์๊ฒ ์ ๋ฆฌํ์ง๊น์ง
| ๋ฌด์์ด | ์ด๋ป๊ฒ | ๋๊ตฌ์๊ฒ ์ ๋ฆฌ |
|---|---|---|
| ์ํ ๊ธ๊ผด | ์ฐ๋ฆฌ ํ์ต์์๋ง ๋บ์ต๋๋ค. ์๋๊ฐ ๋ฌด์์ ๋ณด๊ณ ๋ฐฐ์ ๋์ง๋ ๋ชจ๋ฆ ๋๋ค | ์๋ |
| ์ค ์๋ฅด๊ธฐ | ์ค ์ธ์๊ธฐ๋ค์๊ฒ ์ฐ๋ฆฌ ์ค ์๋ฅด๊ธฐ๋ฅผ ๋น๋ ค์ฃผ์์ต๋๋ค | ์๋ |
| ๋ฌผ์ | Qwen3-VL-2B ๋ ์ ํด ๋ OCR ๋ฌผ์์ด ์์ด ์ ์ ๋ ๋ณด๊ณ ๊ฐ์ฅ ์ ์ฝ๋ ๊ฒ์ ์ฃผ์์ต๋๋ค | ์๋ |
| ์ฌ์ง ํต์งธ ๊ทธ๋ฆผ ํฌ๊ธฐ | ์ฐ๋ฆฌ์ ์๋ณธ์ 4,096ํ ํฐ๊น์ง๋ก ์ค์ด๊ณ , ์๋ VL ๋์ ๊ทธ์ชฝ ๊ธฐ๋ณธ ํฌ๊ธฐ ๊ทธ๋๋ก | ์๋ |
| ๊ธธ์ด ์ํ | ko-trocr ์ ๊ธฐ๋ณธ 16๊ธ์๋ฅผ 64๋ก ํ์ด ์ฃผ์์ต๋๋ค | ์๋ |
| ๊ทธ๋ฆฌ๊ฐ | ์ฐ๋ฆฌ๋ ์ํ์ง์ ๊ฐ์ ๊ทธ๋ฆฌ๊ฐ๋ก ๋ง๋ ํฉ์ฑ ๊ทธ๋ฆผ์ผ๋ก ๋ฐฐ์ ์ต๋๋ค(๊ธ๊ผด์ ๋ค๋ฆ). ์ํ ๊ธ์จ์ฒด ์ชฝ์ ์ฐ๋ฆฌ์๊ฒ ๋ฏ์ต์ ๊ผด์ ๋๋ค โ ๊ทธ๋์ ์ฌ์ง ์ชฝ์ด ๊ฐ์ฅ ๊นจ๋ํ ๊ฒฌ์ค์ ๋๋ค | ์ฐ๋ฆฌ |
| ๋ง๋ ๋ชฉ์ | ์๋ VL ์ ๋ฌธ์ ์ ์ฒดยท์ฌ๋ฌ ์ธ์ด์ฉ์ ๋๋ค. ์ด๊ฒ์ ํ๊ธ ์๊ธ์จ ํ๋๋ง ๋ ธ๋ ธ์ต๋๋ค | ์ฐ๋ฆฌ |
์๋๋ค์ด ๋์ ๋ชจ๋ธ์ด๋ผ๋ ๋ป์ด ์๋๋๋ค. ์ธ์ ๋ฌธ์ยทํยท์ฅ๋ฉด ๊ธ์๋ฅผ ์ฝ์ผ๋ผ๊ณ ๋ง๋ ๋ชจ๋ธ์ ์๊ธ์จ๋ฅผ ์ค ๊ฒ์ด๊ณ , ๊ทธ ๋ฐ๋(์ธ์ ๋ฌธ์ ์ ์ฒด, ํ)๋ ์ฌ์ง ์์์ต๋๋ค. ์ฌ๋ฉด ์ด ๋ชจ๋ธ์ด ์ง ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
LM StudioยทOllamaยทllama.cpp ์ค์ ๊ฐ์ Q8_0 ํ์ผ์ ๋ฐ์ ์ค์ ๊ทธ๋๋ก ๋์ฐ๊ณ , ๊ฐ์ ์ํ์ง(๊ธ์จ์ฒด ๋ฒ๋ง๋ค 100์ค)์ ๊ฐ์ ์ฌ์ง์ผ๋ก OpenAI ๊ผด API ์ ๋ฌผ์ด ์ฐ ๊ฐ์ ๋๋ค. LM StudioยทOllama ๊ฐ ์ด ์ ์ฅ์์์ ๋ฐ์ Q8_0 ๊ณผ ๊ทธ๋ฆผ ํ์ผ(mmproj)์ ์ฌ๋ฆฐ ํ์ผ๊ณผ sha256 ์ด ๊ฐ์ต๋๋ค.
์ฐ๋ ๋ฒ
๋ฌผ์์ ๋ฌด์์ด๋ ๋ฉ๋๋ค(ใOCRใ, ใ๊ธ์ ์ฝ์ด ์คใ, ์์ด, ๋น ๋ฌผ์). ๋๋ต์ ๊ธ์๋ง ์ค๋ง๋ค ํ ์ค๋ก ๋์ต๋๋ค. ์๊ฐ ์นธ์ ๋ํ ํ์์ ๋ ๋ซํ ์์ด์ ์๊ฐํ๋ ๋ฐ ์๊ฐ์ ์ฐ์ง ์์ต๋๋ค. temperature ๋ 0 ์ผ๋ก ๋์ญ์์ค(OCR ์ ๊ณ ๋ฅด๊ฒ ๋ฝ์ผ๋ฉด ํ๋ฆฝ๋๋ค).
Ollama
ollama run hf.co/localdeel/ko-hand-ocr-vl-GGUF:Q8_0
๊ทธ๋ฆผ ์ฝ๋ ๋ชซ๊ณผ ์ค์ (temperature 0, top_k 1, ๋งฅ๋ฝ 8192)์ด ๊ฐ์ด ๋ฐ์์ง๋๋ค(์ ์ฅ์์ params).
API ๋ก๋ ๊ทธ๋ฆผ์ base64 ๋ก ๋ฃ์ต๋๋ค.
curl http://localhost:11434/api/chat -d '{"model": "hf.co/localdeel/ko-hand-ocr-vl-GGUF:Q8_0", "stream": false,
"messages": [{"role": "user", "content": "OCR", "images": ["<base64>"]}]}'
LM Studio
๊ฒ์์์ ko-hand-ocr-vl ์ ์ฐพ์ Q8_0 ์ ๋ฐ๊ฑฐ๋, ๋ช
๋ น์ค๋ก ๋ฐ์ต๋๋ค.
lms get https://huggingface.co/localdeel/ko-hand-ocr-vl-GGUF@q8_0
๊ทธ๋ฆผ ์ฝ๋ ๋ชซ(mmproj)์ด ๊ฐ์ด ๋ฐ์์ง๊ณ (ํฉ์ณ 765MB), ์ค์ ์ ํ๋๋ ์ ๋ฐ๊ฟ๋ ๋ง๊ฒ ๋๋๋ค โ
์๊ฐ ์นธ์ ๋ํ ํ์์ ๋ซํ ์๊ณ , ๊ฐ์ฅ ๊ทธ๋ด๋ฏํ ๊ธ์ ํ๋๋ง ๊ณ ๋ฅด๋ ์ค์ (top_k 1)์ด ํ์ผ์ ๋ค์ด
์์ต๋๋ค. ์ ํ์ LM Studio ์ค์ด ๊ทธ๋ ๊ฒ ๋ฐ์ ๊ทธ๋๋ก ์ฐ ๊ฐ์
๋๋ค. ๋ํ์ฐฝ์ ์ฌ์ง์ ๋์ด ๋๊ฑฐ๋,
์๋ฒ๋ฅผ ์ผ๊ณ OpenAI ๊ผด๋ก ๋ถ๋ฆ
๋๋ค.
llama.cpp
llama-server -hf localdeel/ko-hand-ocr-vl-GGUF:Q8_0 --temp 0
vLLM
vllm serve localdeel/ko-hand-ocr-vl --max-model-len 8192 --limit-mm-per-prompt '{"image": 1}'
๊ตฌ์กฐ๊ฐ Qwen3.5-0.8B ๊ทธ๋๋ก๋ผ vLLM ์ Qwen3.5 ์ง์์ผ๋ก ์ฌ๋ผ๊ฐ๋๋ค. ์ด ๋ชจ๋ธ์ ๋ง๋ PC ์์๋ vLLM ์ด ๋์ง ์์(Windows) ์ง์ ๋์ ๋ณด์ง๋ ๋ชปํ์ต๋๋ค.
transformers
from transformers import AutoModelForImageTextToText, AutoProcessor
from PIL import Image
proc = AutoProcessor.from_pretrained("localdeel/ko-hand-ocr-vl")
model = AutoModelForImageTextToText.from_pretrained("localdeel/ko-hand-ocr-vl", dtype="auto", device_map="auto")
talk = [{"role": "user", "content": [{"type": "image"}, {"type": "text", "text": "OCR"}]}]
text = proc.apply_chat_template(talk, add_generation_prompt=True)
ask = proc(text=[text], images=[Image.open("photo.jpg")], return_tensors="pt").to(model.device)
out = model.generate(**ask, max_new_tokens=512)
print(proc.batch_decode(out[:, ask["input_ids"].shape[1]:], skip_special_tokens=True)[0])
OpenAI ๊ผด ์๋ฒ(LM Studioยทllama-serverยทOllamaยทvLLM)์๋ ๋ชจ๋ ๊ฐ์ ๊ผด๋ก ๋ฌป์ต๋๋ค.
import base64
from openai import OpenAI
client = OpenAI(base_url="http://localhost:1234/v1", api_key="none") # ์๋ฒ ์ฃผ์๋ง ๋ฐ๊พผ๋ค
data = base64.b64encode(open("photo.jpg", "rb").read()).decode()
got = client.chat.completions.create(model="ko-hand-ocr-vl", temperature=0, messages=[{
"role": "user", "content": [
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64," + data}},
{"type": "text", "text": "OCR"}]}])
print(got.choices[0].message.content)
์ด๋ป๊ฒ ๋ง๋ค์๋
- ์๋ณธ: Qwen3.5-0.8B (Gated DeltaNet 18์ธต + ์ฃผ์ 6์ธต, ๊ทธ๋ฆผ ์ธ์ฝ๋ 1์ต ๊ฐ)
- LoRA(r=64, ๋ชจ๋ ์ ํ ์ธต โ ๊ทธ๋ฆผ ์ธ์ฝ๋ ํฌํจ), ๋๋ต ์๋ฆฌ์์๋ง ์์ค, ํ์ต๋ฅ 5e-5. ๋์ 46,000๊ฑธ์(ํ ๊ฑธ์ = ์ค 6๊ฐ ๋๋ ์ฌ์ง 1์ฅ)์ ์ฌ๋ฌ ์ฐจ๋ก ์ด์ด ๋๋ ธ๊ณ , ๊ธด ๋ ์ฐจ๋ก(20,000๊ฑธ์์ฉ) ๋๋ง๋ค ๋ง์ง๋ง ์ ์ฅ ๋ท์ ํ๊ท ํ์ต๋๋ค. ๋ น์ฌ์ ๋ด๋ณด๋
- ํ์ต ๊ทธ๋ฆผ์ ์ ๋ถ ํฉ์ฑ: ์๊ธ์จ ๊ธ๊ผด 450๋ฒ๋ก ๊ทธ๋ฆฐ ํ ์ค(55%), ํ ์ฌ๋์ด ์ข
์ด์ ์ด 1
10์ค์ ์ฑ ์ ์์์ ์ฐ์ ๊ฒ์ฒ๋ผ ๋ง๋ ์ฌ์ง(35%, ๊ธด ๋ณ 6402,400px), ์ธ์์ฒด ์ค(10%) - ์ง์ด ์๊ตญยทํ ํ๊ธฐยท๊ธฐ์ธ์ยท๊ทธ๋ยทํ๋ฆผยทJPEG ๋ฅผ ์์์ต๋๋ค. ์ํ ๊ธ์จ์ฒด 30๋ฒ๊ณผ ์ฌ์ง์ ํ์ต์์ ๋บ์ต๋๋ค
- ์ฌ์ง์ฒ๋ผ ๋ง๋ ์ชฝ์ ํ ๊ฐ๋ก์ค์ ๋์ธ ๋ฉ์ด๋ฅผ ๋๋ํ ์ฐ๊ธฐ๋ ํฉ๋๋ค(ใํ: โฆใ ์ผ์ชฝ, ใ์ด๋ฆ: โฆใ ์ค๋ฅธ์ชฝ). ์ค์ ์์์ด ๊ทธ๋ ๊ฒ ์ฐ์ฌ์, ์ ๊ทธ๋ฌ๋ฉด ์ค๋ฅธ์ชฝ ๋ฉ์ด๋ฅผ ๋น ๋จ๋ ธ์ต๋๋ค
- ๊ธ๊ผด์ด ๋ชป ๊ทธ๋ฆฌ๋ ๊ธ์(โกยท๋น์นธ)๊ฐ ๋ ์ค์ ๊ทธ ๊ธ๊ผด๋ก ๊ทธ๋ฆฌ์ง ์์ต๋๋ค. ๋ค๋ชจ๋ฅผ ๊ทธ๋ ค ๋๊ณ ์ ๋ต์ ์ ๊ธ์๋ฅผ ์ ์ผ๋ฉด ๋ชป ์ฝ๋ ์๋ฆฌ๋ฅผ ์ง์ด๋ด๋ผ๊ณ ๊ฐ๋ฅด์น๋ ๊ผด์ด๋ผ์์ ๋๋ค
- ๋์งธ ์ฐจ๋ก(20,000๊ฑธ์)์๋ ๋ป ์๋ ๊ธ์ ์ค์ 15% ์์์ต๋๋ค. ํ๋ฆฐ ๊ธ์๋ฅผ ํํ ๋ฑ๋ง๋ก ๊ณ ์ณ ์ฝ๋ ๋ฒ๋ฆ(์ธ์ฌํโ์ธ์ฌํ)์ ์ค์ด๋ ค๋ ๊ฒ์ ๋๋ค
- ๋ฐ๊พผ ์ค์ : ๋ํ ํ์ ์๊ฐ ์นธ์ ๋ ๋ซ์, ๊ทธ๋ฆผ ์ํ 4,096ํ ํฐ,
top_k: 1
ํ๊ณ
- ์ฌ๋ ์๊ธ์จ๋ก๋ ํ์ตํ์ง ์์์ต๋๋ค. ๊ธ๊ผด๋ก ๊ทธ๋ฆฐ ์๊ธ์จ๋ง ๋ดค์ต๋๋ค. ํ๋ ค ์ด ๊ธ์จ, ๊ฒน์ณ ์ด ๊ธ์จ๋ ์ฝํฉ๋๋ค.
- ์ํ ์ฌ์ง์ด 11์ฅ๋ฟ์ด๋ผ ์ฌ์ง ์ ์์ ํญ์ด ํฝ๋๋ค(ํ ์ฅ์ด 9%p).
- ํยท๋์ฅยท์๋ช ๊ฐ์ ์์ ๊ตฌ์กฐ๋ ์ฝ์ง ์์ต๋๋ค. ๊ธ์๋ง ์ค๋ง๋ค ๋ ๋๋ค.
- safetensors ์
mtp.*(์ฌ๋ฌ ํ ํฐ ๋ฏธ๋ฆฌ ์ง์) ๋จธ๋ฆฌ๋ ์๋ณธ ๊ทธ๋๋ก๋ผ ๋ฏธ์ธ์กฐ์ ๋์ง ์์์ต๋๋ค. ๋ต์ ์ ๋ฐ๋์ง๋ง ์ง์์ด ๋ ๋ง์ ์ ์์ต๋๋ค. GGUF ์๋ ์์ต๋๋ค. - safetensors ๋ฅผ ์์ GGUF ๋ก ๋ฐ๊ฟ ๋ llama.cpp
convert_hf_to_gguf.py๊ฐ ํ ํฌ๋์ด์ ๋ฅผ ๋ชป ์์๋ด ๋๋ค โ ์ดํ๋ฅผ ์๋ผ ์ง๋ฌธ์ด ๋ฌ๋ผ์ก๊ธฐ ๋๋ฌธ์ ๋๋ค. ์๋ณธ๊ณผ ๊ฐ์qwen35๋ก ์ ํด ์ฃผ๊ณ ๋ฐ๊พธ๊ฑฐ๋ GGUF ํ์ ๋ฐ์ต๋๋ค.
๋ผ์ด์ ์ค
Apache-2.0. ์๋ณธ Qwen3.5-0.8B ๋ Apache-2.0 ์
๋๋ค. ์์ธํ ๊ฒ์ NOTICE.
English
An open-weight Korean handwriting OCR model: give it a photo, get the text back. It is Qwen3.5-0.8B fine-tuned on Korean handwriting with the architecture unchanged, so anything that runs Qwen3.5 โ Ollama, LM Studio, llama.cpp, vLLM, transformers โ runs it with no new code.
2026-10-12 โ vocabulary cut, same answers. Of the base Qwen3.5 vocabulary (248,077 tokens) we kept Hangul, jamo, digits, symbols, short Latin pieces and every token our training and test text uses: 59,453 tokens (853M -> 660M parameters). The weights were not retrained, and on the test fonts, the held-out fonts, the photo line crops and the whole photos every answer came out identical, character for character โ through transformers and through llama-server (Q8_0, one request at a time). Downloads shrink: safetensors 1.63GB -> 1.27GB, Q8_0 774MB -> 570MB, Q4_K_M 505MB -> 345MB, and llama.cpp generates 26โ36% faster (this PC, llama-bench). On 200 lines built only from long English words that left the vocabulary, 173 came out the same and jamo similarity went 98.34 -> 98.01. The line table and the speeds were re-measured on the cut model; the whole-photo and runtime tables were measured before the cut (the answers are the same, so they stand). The uncut model is at this repo's tag
full-vocab.
All numbers below are measured on the same test sheets on the same PC. Test fonts were held out of training; the 11 photos are real handwriting, never used for training, and not published.
| Model | Size | Test fonts 6 (char. sim. / CER) | Unseen fonts 24 | Photos 11, line crops (sim. / CER) | GPU lines/s |
|---|---|---|---|---|---|
| ko-hand-ocr-vl (this, 660M) | 1.27GB | 97.0 / 5.8 | 97.4 | 93.4 / 15.8 | 10.8 |
| Qwen3.5-0.8B (base, before fine-tuning) | 1.63GB | 53.0 / 161.8 | 51.4 | 54.2 / 115.3 | 9.6 |
| ko-hand-ocr single model (41M, lines only) | 78MB | 96.8 / 7.2 | 97.3 | 94.2 / 13.4 | 42.0 |
| ko-hand-ocr ensemble (3 models) | 225MB | 97.1 / 6.7 | 97.7 | 96.5 / 8.6 | 8.3 |
| Qwen/Qwen3-VL-2B-Instruct | 3.96GB | 66.6 / 79.1 | 68.0 | 69.9 / 38.3 | 7.3 |
| PaddlePaddle/PaddleOCR-VL-1.6 | 1.79GB | 63.6 / 62.9 | 66.5 | 61.7 / 44.0 | 1.2 |
| ddobokki/ko-trocr | 408MB | 78.2 / 42.3 | 80.4 | 78.5 / 39.2 | 6.1 |
| PaddleOCR PP-OCRv5 (korean) | 13MB | 72.7 / 40.5 | 75.3 | 71.8 / 39.7 | 397.4 |
| EasyOCR (korean) | 15MB | 56.6 / 64.3 | 64.6 | 66.9 / 55.0 | 81.3 |
| Tesseract 5 (kor+eng) | 6MB | 17.7 / 97.3 | 19.7 | 13.2 / 98.6 | โ |
Whole photos (original size, capped at 4,096 image tokens). Page compares the whole page's text joined together (the usual page-level CER); line-paired matches each line read to a label line. The two rival VLMs get their own default image size, not our cap:
| Model | Page char. similarity | Page CER | Worst photo (page) | Line-paired similarity |
|---|---|---|---|---|
| ko-hand-ocr-vl (this) | 94.3 | 15.3 | 78.3 | 95.6 |
| Qwen3.5-0.8B (base) | 72.7 | 42.1 | 55.3 | 62.1 |
| Qwen3-VL-2B-Instruct | 76.9 | 41.1 | 47.6 | 72.5 |
| PaddleOCR-VL-1.6 | 79.9 | 37.3 | 54.5 | 57.3 |
Same model, different runtimes (100 lines per font). The llama.cpp family is lower on photos because of image preprocessing, not quantization (the unquantized F16 GGUF scores the same): llama.cpp keeps the aspect ratio and pads the edge with black, and shrinks small images down to 8 tokens, while this model was trained from 64. The mmproj now carries the 64-4,096 token limits (2026-10-09), which llama.cpp and LM Studio read on load: photo line crops went 90.8 -> 92.5 in the same LM Studio and 90.9 -> 92.0 in llama-server. Ollama 0.34.4 does not read them yet. The black padding cannot be changed from the file.
| How it runs | Test fonts 6 | Photos, line crops | Photos, whole |
|---|---|---|---|
| transformers (bf16, safetensors) | 96.9 | 93.3 | 94.3 |
llama.cpp llama-server โ Q8_0 |
96.7 | 92.0 | 91.8 |
| LM Studio โ Q8_0, ๋ฐ์ ๊ทธ๋๋ก (์ค์ ์ ๊ฑด๋๋ฆผ) | 96.4 | 92.5 | 91.8 |
Ollama โ hf.co/โฆ:Q8_0, ๋ฐ์ ๊ทธ๋๋ก |
96.2 | 90.9 | 91.8 |
How the benchmark was run
- Same test sheets, same PC, all ten models in one run (2026-10-13 14:59). GPU: NVIDIA GeForce RTX 5060 Laptop GPU (8GB); CPU: AMD Ryzen 7 260 (laptop, 8 cores); Windows 11; PyTorch 2.14.0+cu130.
- Test fonts (6): 640 lines / 4,448 characters drawn with six free handwriting fonts (OFL) held out of training, with paper texture, tilt and strike-through marks; fixed seed never used in training. About a third of the lines are meaningless syllable strings (no language prior to lean on), a third are form fields, the rest titles and sentences, with digits, dates, Latin abbreviations and symbols mixed in. Lines a font cannot draw are dropped.
- Unseen fonts (24): 634 lines, never used for training or for picking models.
- Photos (11): real handwriting on real forms, 34 lines / 209 characters, never used for training and not published. Line crops come from the ko-hand-ocr line cutter, so every model gets the same crops. A 12th photo (low-res printed form + signatures) is measured but not scored.
- Scores: character similarity =
difflibratio over jamo with spaces removed, averaged per line; CER = edit distance / reference characters, pooled over all characters (can exceed 100% when a model rambles). - Rivals run exactly as their model cards say, in their own environments; timing counts only time inside the engine. Qwen3-VL-2B got the best of three prompts; ko-trocr's 16-char length cap was raised to 64; the rival VLMs read whole photos at their own default size. Our training images come from the same renderer as the font sheets (different fonts), so the photo set is the cleanest comparison.
- Runtimes: llama.cpp build 11474, LM Studio (llama.cpp CUDA 12 engine 2.55.0) and Ollama 0.34.4, each with the downloaded Q8_0 file and default settings, 100 lines per font. The Q8_0 and mmproj files LM Studio and Ollama downloaded from this repo match the upload by sha256.
Usage
Any prompt works ("OCR", "Read the text", Korean, or empty). The answer is only the text, one line per line. The thinking block is always closed by the chat template, so no time is spent thinking. Use temperature 0 (sampling makes OCR worse).
- Ollama:
ollama run hf.co/localdeel/ko-hand-ocr-vl-GGUF:Q8_0 - LM Studio: search
ko-hand-ocr-vlorlms get https://huggingface.co/localdeel/ko-hand-ocr-vl-GGUF@q8_0. Themmprojvision file comes with it and it works with no settings changed (thinking is closed in the template;top_k 1is in the file). - llama.cpp:
llama-server -hf localdeel/ko-hand-ocr-vl-GGUF:Q8_0 --temp 0 - vLLM:
vllm serve localdeel/ko-hand-ocr-vl --max-model-len 8192โ same architecture as Qwen3.5-0.8B, so vLLM's Qwen3.5 support loads it. Not run by us (the build machine is Windows). - transformers:
AutoModelForImageTextToText+AutoProcessor, as in the Korean section.
Limits. Trained on synthetic handwriting only (450 fonts), no real handwriting samples. Only 11 test photos, so the photo scores are noisy. Reads text line by line; does not parse tables or forms. To convert the safetensors to GGUF yourself, set the pre-tokenizer to qwen35 (the cut vocabulary changes the fingerprint convert_hf_to_gguf.py checks); the GGUF repo already has it. License: Apache-2.0 (same as the base model).