Skip to main content

ThaiBreak — Fast Thai Word Segmenter & Typographic Line Breaker

CI License Packagist Version Go Reference Go version npm version crates.io PyPI version

ระบบตัดคำและตัดแบ่งบรรทัดภาษาไทยประสิทธิภาพสูงแบบ Multi-Language Engine รองรับ PHP / Laravel, Go, TypeScript / Node.js, Rust Core, C / C++, Python, และ WebAssembly

ใช้อัลกอริทึม Shortest Path Viterbi DAG ร่วมกับ Theeramunkong 30-Rule Thai Character Cluster (TCC) บนพจนานุกรมมาตรฐานภาษาไทย (data/words.txt 25,402 คำ)

🚀 Zero External Corpus Dependency: ไม่พึ่งพาคลังข้อความที่มีข้อจำกัดทางลิขสิทธิ์ เป็น Open Source Apache-2.0 แท้ 100% ใช้งานเชิงพาณิชย์ได้อย่างสบายใจ
⚡ ความเร็วสูงระดับไมโครวินาที: ~30-45 µs ใน Go/Rust, ~0.3 ms ใน PHP/Node.js (~25,000 ประโยค/วินาทีต่อ core)
💾 Ultra-Lightweight & Low Memory: พจนานุกรมบีบอัดแบบ Compact DAWG (167 KB) และ FST (289 KB) ใช้ RAM ต่ำกว่า 0.2–0.5 MB (ลดลง 95%)
📄 Typographic Line Breaker & Soft Wrapping: ตัดแบ่งบรรทัดป้องกันสระลอย/ตกขอบ ตาม Unicode UAX #14 (Unicode 16.0) ครบทุกกฎ ผ่านชุดทดสอบทางการของ Unicode และ W3C tlreq สำหรับ PDF (dompdf, mPDF, TCPDF, Typst) และ Web
🔥 พร้อมใช้งานกับ Laravel: Auto-Discovery, Facade, Blade Directives (@thaibreak, @thaiwrap), Str Macros


คุณสมบัติเด่น

  1. Shortest Path Graph Viterbi Algorithm: อัลกอริทึมค้นหาเส้นทางคำที่เหมาะสมที่สุดบนกราฟ ค้นหาคำที่ยาวและถูกต้องสมบูรณ์ตามธรรมชาติ
  2. Theeramunkong et al. TCC Grammar (30 Rules): คำนวณจุดตัดคลัสเตอร์ภาษาไทยระดับไบต์ออฟเซ็ต ป้องกันการตัดแยกสระ สระบน-ล่าง วรรณยุกต์ หรือพยัญชนะนำ 100%
  3. FST & Compact DAWG Dictionary Architecture (v1.1.0): โครงสร้างข้อมูลพจนานุกรม Finite State Transducer / Minimal Acyclic DFA บีบอัดคลังคำ 25,402 คำเหลือเพียง 167 KB โหลดทันใจระดับไมโครวินาที (0.04 ms ใน Go, 0.7 ms ใน Node.js, 0.00 ms ใน Rust/OPcache) พร้อมรองรับ Dynamic Overlay เมื่อมีการเพิ่มคำใหม่ขณะรันไทม์
  4. Smart OOV & Abbreviation Handling: รู้จักคำย่อภาษาไทย (รพ., พ.ศ., มิ.ย.), ตัวเลขคั่นจุลภาค (10,000), ทศนิยม (3.14), เปอร์เซ็นต์ (40%)
  5. ThaiLineBreaker (UAX #14 & W3C Thai Text Layout): ตัดแบ่งบรรทัดสำหรับทำ PDF หรือเว็บด้วย Unicode Line Breaking Algorithm ครบทุกกฎ (LB1–LB31) ใช้พจนานุกรมตัดคำเฉพาะภายในช่วงอักษรไทย ไม่ตัดกลางคำ ตัวเลข คำย่อ หรืออีเมล ไม่ทิ้งวรรคไว้หน้าบรรทัดใหม่ ป้องกันเครื่องหมายตกค้าง (ๆ, ฯ, วงเล็บ, อัญประกาศ)
  6. HTML / EPUB Safe: รักษาแท็ก HTML (<p>, <b>, <span>) และ HTML Entities (&amp;, &quot;) ให้คงอยู่สมบูรณ์ ไม่แทรกสัญลักษณ์ตัดคำเข้าไปภายในแท็ก

รองรับหลายภาษาโปรแกรม (Multi-Language Architecture)

ThaiBreak ได้รับการออกแบบสถาปัตยกรรมแบบ Monorepo เพื่อรองรับการใช้งานในทุก Stack โดยใช้คลังคำศัพท์มาตรฐาน (data/words.txt: 25,402 คำ) เป็น Single Source of Truth:

thai-break/
├── data/                 # Shared Dictionaries (words.dawg: 167 KB, words.fst: 289 KB, words.php, words.txt)
├── php/                  # Native PHP & Laravel Package (Composer: kamthorn/thai-break)
│   ├── src/              # PHP Source & Laravel Integration
│   ├── tests/            # PHPUnit & Integration Tests
│   └── examples/         # Demo Scripts
├── go/                   # Native Go Package (go get github.com/kamthorn/thai-break/go)
├── typescript/           # Native TypeScript / Node.js Package (npm: thai-break)
├── rust/                 # High-Performance Rust Core (Cargo: thaibreak)
│   ├── include/          # C / C++ Header (thaibreak.h)
│   └── src/              # Core Engine + C FFI + Python (PyO3) + Wasm (wasm-bindgen)
├── python/               # Python Package (pip: thaibreak)
└── tools/                # Dev tools: line-break table generator, CLI segmenter, accuracy benchmark

1. PHP & Laravel

การติดตั้งผ่าน Composer

composer require kamthorn/thai-break

การใช้งานทั่วไป (One-liner Quick Start)

use ThaiBreak\ThaiBreak;

// 1. ตัดคำเป็น Array
$words = ThaiBreak::words('ฉันรักภาษาไทย');
// → ['ฉัน', 'รัก', 'ภาษา', 'ไทย']

// ตำแหน่งขอบเขตคำแบบ BreakIterator (นับไบต์ สำหรับ substr(); ส่ง true เป็นอาร์กิวเมนต์ที่สองเพื่อนับตัวอักษร สำหรับ mb_substr())
$bounds = ThaiBreak::boundaries('ฉันรักภาษาไทย');
// → [0, 9, 18, 30, 39]

// 2. ตัดคำคั่นด้วยเครื่องหมาย
$joined = ThaiBreak::join('สวัสดีครับคุณลูกค้า', '|');
// → "สวัสดี|ครับ|คุณ|ลูกค้า"

// 3. แทรกจุดตัดบรรทัด (Zero-Width Space U+200B) สำหรับ Render PDF/HTML
$lines = ThaiBreak::lines('ข้อความยาวๆ ที่ต้องการจัดหน้าใน PDF');

// 4. ตัดแบ่งบรรทัดสำหรับ HTML (รักษาแท็กและ entities)
$html = ThaiBreak::lines('<p>สวัสดี <b>ประเทศไทย</b> &amp; กรุงเทพมหานคร</p>', isHtml: true);

// 5. Hard Wrap ตัดข้อความขึ้นบรรทัดใหม่ตามความกว้างคอลัมน์ (Display Width)
$wrapped = ThaiBreak::wrap('ข้อความภาษาไทยขนาดยาว...', width: 40);

การใช้งานใน Laravel

ThaiBreak รองรับ Laravel Package Auto-Discovery อัตโนมัติ:

use ThaiBreak; // Facade

// เรียกผ่าน Facade
$words = ThaiBreak::words('ข้อความ');

// หรือเรียกผ่าน Str Macro
$words = Str::thaiWords('ฉันรักภาษาไทย');
$html  = Str::thaiLines('ข้อความในหน้าเว็บ');
$pdf   = Str::thaiWrap($text, 40);

ใน Blade Template:

{{-- แทรก Zero-Width Space เพื่อให้ Browser/PDF ตัดคำได้สวยงาม --}}
@thaibreak($post->content)

{{-- ตัดบรรทัดจำกัดความกว้าง 40 ตัวอักษร --}}
@thaiwrap($report->summary, 40)

การกำหนดพจนานุกรมเพิ่มเติม (Custom Dictionary)

use ThaiBreak\DictionaryLoader;
use ThaiBreak\ThaiTokenizer;

// ตัวเลือกที่ 1: Compact DAWG 167 KB (แนะนำ - โหลดใน 0.3 ms แรม < 0.5 MB)
$trie = DictionaryLoader::fromDawgFile('data/words.dawg');

// ตัวเลือกที่ 2: OPcache Preload (0.00 ms โหลด แรม 0 MB ต่อ worker)
// $trie = DictionaryLoader::fromPhpFile('data/words.php');

// เพิ่มคำศัพท์ใหม่แบบ Dynamic ได้ทันที
$trie->add('คำศัพท์เฉพาะทาง', 10.0);

$tokenizer = new ThaiTokenizer($trie);
$words = $tokenizer->tokenize('ข้อความ...');

2. Go (Golang) — Native Implementation

เขียนด้วย Pure Go 100% ไม่พึ่งพา CGO (CGO_ENABLED=0) ความเร็วสูง ~30-45 µs ต่อประโยค:

go get github.com/kamthorn/thai-break/go
package main

import (
    "fmt"
    tb "github.com/kamthorn/thai-break/go"
)

func main() {
    // ตัดคำ
    words := tb.Words("ฉันรักภาษาไทย")
    fmt.Println(words) // [ฉัน รัก ภาษา ไทย]

    // ตำแหน่งขอบเขตคำแบบ BreakIterator (นับไบต์ ใช้กับ text[b[i]:b[i+1]])
    bounds := tb.Boundaries("ฉันรักภาษาไทย") // [0 9 18 30 39]

    // แทรกจุดตัดบรรทัด (Zero-Width Space U+200B)
    lines := tb.Lines("สวัสดีครับคุณลูกค้า", false)

    // ป้องกันแท็ก HTML และ Entity
    html := tb.Lines("<b>สวัสดี</b> &amp; ประเทศไทย", true)

    // ตัดบรรทัดตามความกว้างหน้าจอ (คำนวณสระ/วรรณยุกต์ไม่คิดความกว้าง)
    wrapped := tb.Wrap("ข้อความภาษาไทยยาวๆ...", 40)
    fmt.Println(wrapped)
}

3. TypeScript & JavaScript (Node.js / Browser) — Native Implementation

เขียนด้วย TypeScript (ES2022 / NodeNext) ทำงานได้ทั้ง Node.js, Bun, Deno และ Browser:

npm install thai-break
import { words, boundaries, lines, wrap, displayWidth } from 'thai-break';

// ตัดคำ
const tokens = words('ฉันรักภาษาไทย');
console.log(tokens); // ['ฉัน', 'รัก', 'ภาษา', 'ไทย']

// ตำแหน่งขอบเขตคำแบบ BreakIterator (UTF-16 ตรงกับ string.slice)
console.log(boundaries('ฉันรักภาษาไทย')); // [0, 3, 6, 10, 13]

// ตัดบรรทัดสำหรับ HTML (รักษาแท็กและ entities ไม่เสียหาย)
const htmlWithZwsp = lines('<div class="header"><b>สวัสดี</b> &amp; ประเทศไทย</div>', true);

// ตัดบรรทัดจำกัดความกว้างคอลัมน์ (Display Width)
const wrapped = wrap('ฉันรักภาษาไทยมากที่สุดในโลก', 12);
console.log(wrapped);

// คำนวณความกว้างตัวอักษรจริง (สระบน-ล่าง/วรรณยุกต์ = 0, CJK = 2)
console.log(displayWidth('ภาษาไทย')); // 7

4. Rust Core Engine (thaibreak)

ประสิทธิภาพสูงสุดระดับ Native Machine Code ผ่าน Cargo:

[dependencies]
thaibreak = "1"

พจนานุกรมพื้นฐาน (words.fst, 289 KB) ฝังอยู่ในไลบรารีแล้ว (feature embedded-dict เปิดเป็นค่าเริ่มต้น) จึงเรียก words() ได้ทันทีโดยไม่ต้องมีไฟล์ หากต้องการใช้พจนานุกรมของตัวเองเท่านั้น ให้ใช้ default-features = false

use thaibreak::{words, lines, wrap, display_width, DEFAULT_BREAK_MARKER};

fn main() {
    let tokens = words("ฉันรักภาษาไทย");
    println!("{:?}", tokens); // ["ฉัน", "รัก", "ภาษา", "ไทย"]

    let html = lines("<p>สวัสดีชาวโลก</p>", DEFAULT_BREAK_MARKER, true);
    println!("{}", html);

    let width = display_width("ภาษาไทย");
    println!("Width: {}", width); // 7
}

5. C & C++ (ผ่าน C-ABI Shared / Static Library)

เชื่อมต่อได้ทั้ง C, C++, Qt, หรือภาษาใดๆ ที่รองรับ C-ABI:

#include <stdio.h>
#include "thaibreak.h"

int main() {
    // โหลดพจนานุกรม FST (เร็วขึ้น 70x และประหยัดแรม) หรือส่ง NULL เพื่อโหลดอัตโนมัติ
    thaibreak_init("data/words.fst", NULL);

    // ตัดคำ
    size_t count = 0;
    char **tokens = thaibreak_tokenize("ฉันรักภาษาไทย", &count);
    for (size_t i = 0; i < count; i++) {
        printf("[%zu] %s\n", i, tokens[i]);
    }
    thaibreak_free_tokens(tokens, count);

    // แทรกจุดตัดบรรทัดใน HTML
    char *broken = thaibreak_lines("<b>สวัสดี</b> ประเทศไทย", NULL, 1);
    printf("%s\n", broken);
    thaibreak_free_string(broken);

    return 0;
}

คอมไพล์ด้วย GCC / Clang:

gcc -I rust/include main.c -L rust/target/release -lthaibreak -o app

6. Python (ผ่าน C-FFI / PyO3)

pip install thaibreak

แพ็กเกจเป็น wheel แยกตามแพลตฟอร์ม (py3-none-<platform>) ที่มีไลบรารี Rust และพจนานุกรมพื้นฐาน (words.fst) ติดมาด้วย ใช้ได้กับ Python 3.9 ขึ้นไป (ทดสอบ 3.9–3.13) โดยไม่ต้องติดตั้ง Rust: Linux x86_64/aarch64 (glibc 2.28+), macOS x86_64/arm64 และ Windows x64 แพลตฟอร์มอื่น (เช่น Alpine/musl) ต้อง build เองตามด้านล่าง

import thaibreak

# ไม่ต้องเรียก init ก็ใช้งานได้ (โหลดพจนานุกรมพื้นฐานที่ติดมากับแพ็กเกจ)
# หรือระบุพจนานุกรมเอง เช่น thaibreak.init("data/words.fst")

# ตัดคำ
tokens = thaibreak.words("ฉันรักภาษาไทย")
print(tokens) # ['ฉัน', 'รัก', 'ภาษา', 'ไทย']

# ตำแหน่งขอบเขตคำแบบ BreakIterator (index ของ str; ช่องว่างและเครื่องหมายเป็น segment ด้วย)
text = "ฉันรักภาษาไทย"
b = thaibreak.boundaries(text)   # [0, 3, 6, 10, 13]
segments = [text[i:j] for i, j in zip(b, b[1:])]

# แทรกจุดตัดบรรทัดสำหรับ HTML
html = thaibreak.lines("<b>สวัสดี</b> &amp; ประเทศไทย", is_html=True)

# ตัดบรรทัดตามความกว้าง
wrapped = thaibreak.wrap("ฉันรักภาษาไทยมากที่สุดในโลก", width=12)
print(wrapped)

Build wheel เอง (ต้องมี Rust และ Python):

tools/build_python_wheel.sh      # ได้ไฟล์ใน python/dist/

GitHub Actions workflow python-wheels.yml build wheel ครบทุกแพลตฟอร์มและอัปโหลดเป็น artifact python-wheels (ไม่ publish ขึ้น PyPI ให้อัตโนมัติ)


7. WebAssembly (Wasm)

คอมไพล์เป็น Wasm สำหรับ Edge/Cloudflare Workers หรือเบราว์เซอร์:

cd rust && wasm-pack build --target web --features wasm
import init, { WasmThaiBreak } from './pkg/thaibreak.js';

await init();
const tb = WasmThaiBreak.withDefault();          // ใช้พจนานุกรมพื้นฐานที่ฝังในโมดูล
// const tb = new WasmThaiBreak(dictTextString); // หรือส่งพจนานุกรมของคุณเอง (TSV)
console.log(tb.words("ฉันรักภาษาไทย"));
console.log(tb.boundaries("ฉันรักภาษาไทย")); // ตำแหน่ง UTF-16 ตาม string index ของ JS

กฎเกณฑ์สำคัญของการตัดบรรทัด (ThaiLineBreaker)

ปัญหาคลาสสิกของการ Render PDF และ EPUB ภาษาไทยคือโปรแกรมตัดคำไทยไม่เป็น ทำให้ข้อความล้นตกขอบ หรือตัดคำแยกกลางสระ/กลางพยางค์

ThaiBreak ใช้ Unicode Line Breaking Algorithm (UAX #14) ของ Unicode 16.0 ครบทุกกฎ (LB1–LB31) โดยอ่านคลาส Line_Break ของทุกอักขระจากฐานข้อมูล Unicode (UCD) และตรวจกับชุดทดสอบทางการ LineBreakTest.txt ผ่านครบทั้ง 16,672 กรณีในทั้ง 4 ภาษา (PHP, Go, Rust, TypeScript; Python ใช้ Rust):

  1. พจนานุกรมเฉพาะในช่วงอักษรไทย (SA, LB1): UAX #14 กำหนดให้ตัดภายในช่วงอักษรไทยด้วยพจนานุกรม ThaiBreak ใช้ผลตัดคำเป็นจุดตัดบรรทัดเฉพาะระหว่างอักษรไทยกับอักษรไทย เมื่ออักษรไทยอยู่ติดกับอักขระอื่นจะถือเป็นตัวอักษร (AL) จึงไม่ตัด ราคา100บาท, ปี๒๕๖๗นะ, ภาษาPHPเป็น, ไทย(สยาม)เป็น, «ไทย»ไทย
  2. ส่วนขยายเฉพาะภาษาไทย (Tailoring): ไม้ยมก (ๆ) และไปยาลน้อย (ฯ, รวมถึง ฯลฯ) ไม่ขึ้นต้นบรรทัดใหม่ แม้มีวรรคคั่นอยู่ข้างหน้า (เด็ก ๆ) ตาม W3C tlreq เป็นกฎเดียวที่เพิ่มเติมจาก UAX #14
  3. ห้ามขึ้นต้นบรรทัด: เครื่องหมายปิดและวรรคตอน (), ], }, 、, 。, !, ?, ,, ., :, ;, /; LB13, LB15d) ยัติภังค์และขีด (-, –, ๚, ๛; LB21)
  4. ห้ามลงท้ายบรรทัด: วงเล็บเปิดแม้มีวรรคตามหลัง (( ไทย ); LB14) อัญประกาศเปิด (LB15a, LB19) และสัญลักษณ์นำหน้า เช่น ฿, $ เมื่อตามด้วยตัวเลขหรือตัวอักษร (LB24, LB25)
  5. ไม่ตัดกลางตัวเลข คำย่อ อีเมล: 1/2/2567, 10:30, 10-20, -5, 40%, พ.ศ.2567, รพ.ศิริราช, e.g., user@example.com (LB23, LB25, LB28, LB29)
  6. จุดตัดภายในคำที่ไม่ใช่ภาษาไทย: ตัดหลังยัติภังค์หรือทับใน URL ได้ตามมาตรฐาน เช่น state-|of-|the-|art, https://|example.com/|a-|b
  7. ป้องกัน Orphan Spaces: ช่องว่าง ( ) เป็นจุดตัดบรรทัดอยู่แล้ว จึงไม่ใส่ break marker ติดกับช่องว่าง ป้องกันไม่ให้เกิดวรรคนำหน้าในบรรทัดใหม่
  8. คงความถูกต้องของ HTML/EPUB: แท็ก HTML (<p>, <b>, <span>), บล็อกสคริปต์/สไตล์ (<script>, <style>, <!-- คอมเมนต์ -->) และ HTML Entities (&amp;, &quot;) จะถูกรักษาไว้อย่างสมบูรณ์ ตรวจว่าเป็น HTML เฉพาะเมื่อพบแท็กจริง (< ตามด้วยตัวอักษร / ! หรือ ?) ข้อความอย่าง x < 5 และ y > 3 จึงไม่ถูกมองเป็นแท็ก (ข้อจำกัด: ข้อความแต่ละช่วงระหว่างแท็กประมวลผลแยกกัน จึงไม่มีจุดตัดตรงรอยต่อแท็ก)
  9. wrap() ใช้จุดตัดชุดเดียวกัน: ตัดบรรทัดเฉพาะจุดที่ insertLineBreaks() อนุญาตหรือหลังช่องว่าง และเมื่อเปิด cutLongWords จะตัดคำที่ยาวเกินบรรทัดตามขอบเขต Thai Character Cluster (TCC) ไม่แยกสระหน้าหรือวรรณยุกต์ออกจากพยัญชนะ
  10. คำนวณความกว้างคอลัมน์ถูกต้อง: สระบน-ล่าง วรรณยุกต์ ไม่นับความกว้างคอลัมน์ (thaiDisplayWidth) ทำให้ตัดบรรทัดได้พอดีความกว้างจริง

ตาราง Line_Break สร้างจาก UCD ด้วย php tools/generate-linebreak-data.php <UNICODE_VERSION> ซึ่งเขียนไฟล์ตารางของทั้ง 4 ภาษาพร้อมกัน


ผลการประเมินความแม่นยำและประสิทธิภาพ (Accuracy & Performance Benchmarks)

ThaiBreak ได้รับการออกแบบให้มีความสมดุลสูงสุดระหว่าง ความแม่นยำทางภาษาศาสตร์ (Linguistic Accuracy), ความเร็วระดับไมโครวินาที (High Throughput), และ ความปลอดภัยทางลิขสิทธิ์ (Commercial Clean Data)

1. ความแม่นยำในการตัดคำ (Accuracy Benchmark)

วัดด้วย tools/benchmark.py ในโปรเจกต์นี้ เทียบกับคำตอบที่ตัดคำไว้แล้ว (Gold Standard) สองชุดพจนานุกรม: ฐานอย่างเดียว (data/words.txt 25,411 คำ พร้อมน้ำหนักคำจาก data/word-weights.tsv ซึ่งเป็นค่าเริ่มต้นของไลบรารี) และ ฐาน + dict-extra (38,483 คำ รวมพจนานุกรมเสริม thai-break-dict-extra ชุดตัดคำ 14,331 คำ ซึ่งเป็นชุดเดียวกับที่ OpenSearch plugin และตัวอย่าง service ใช้ โดยคำของฐานใช้น้ำหนักชุดเดียวกัน):

ชุดทดสอบ ฐานอย่างเดียว Word F1 Boundary F1 ฐาน + dict-extra Word F1 Boundary F1
LST20 test (NECTEC, ข่าว) 86.9% 93.8% 83.7% 92.2%
LST20 eval 83.5% 91.3% 80.6% 90.1%
Blackboard Treebank (ระดับคำย่อย, ไม่รวมประโยคที่ซ้ำกับ LST20 train) 86.6% 94.0% 84.2% 93.0%
Wisesight-1000 (โซเชียลมีเดีย, CC0) 84.5% 91.1% 82.7%† 90.3%†
  • Word F1: นับคำที่ตำแหน่งต้นและท้ายตรงกับคำตอบ Boundary F1: เทียบตำแหน่งจุดตัดระหว่างคำ ข้อความแบ่งเป็นท่อนที่ช่องว่างและขอบเขตประโยค และไม่นับช่องว่าง
  • ทำไมสองคอลัมน์: gold ของ LST20 และ Blackboard แยกคำประสมและชื่อเป็นหน่วยย่อย ส่วน dict-extra เก็บคำประสมและชื่อเฉพาะไว้เป็นคำเดียวโดยตั้งใจ เพื่อให้การค้นหาด้วยคำประสมตรงตัวได้น้ำหนักมากขึ้น (ค้นด้วยคำย่อยได้ผ่านโหมด decompound ของ plugin) คะแนนระดับคำจึงต่ำลงเมื่อใช้ dict-extra: บน LST20 test จุดตัดที่ทำนายแม่นขึ้น (precision 90.1% → 90.8%) แต่พบจุดตัดของ gold ได้น้อยลง (recall 97.7% → 93.7%) ตัวเลขนี้วัดการตัดคำเทียบ gold เท่านั้น ไม่ได้วัดคุณภาพการค้นหา ถ้าจะใช้ตัดคำให้ตรงกับแนวทางของคลังข้อความแบบ LST20 ให้ใช้ฐานอย่างเดียว ส่วนการตัดบรรทัดใช้ชุด words-extra-lines ที่ตัดชื่อเฉพาะและคำประสมออกแล้ว
  • † dict-extra มีคำสแลงที่สกัดจาก Wisesight Sentiment ซึ่งอาจซ้อนกับข้อความของ Wisesight-1000 คอลัมน์นี้จึงไม่ใช่การทดสอบกับข้อมูลที่ไม่เคยเห็น (แต่คะแนนก็ไม่ได้สูงขึ้น)
  • คำที่ตัดผิดส่วนใหญ่ไม่มีในพจนานุกรม: บน LST20 eval ประมาณสองในสามของคำที่ตัดผิด เช่นคำประสมภาษาข่าวตามแนวทางของ LST20 (มีการ, วันที่, ดังกล่าว) การเพิ่มคำด้วย addCustomWords() หรือพจนานุกรมเสริมจึงเป็นทางปรับแต่งหลัก แต่ผลขึ้นกับว่าคำที่เพิ่มตรงกับแนวทางตัดคำของงานของคุณหรือไม่ (ดูตารางด้านบน) พจนานุกรมแบบ TSV ที่มีน้ำหนักความถี่ของคำจะถูกใช้เป็นความน่าจะเป็นของคำ (unigram) โดยตรง
  • คลังข้อมูลไม่ได้รวมอยู่ในโปรเจกต์: LST20 ต้องขอจาก NECTEC และใช้ได้ตามข้อตกลงการใช้งาน (งานวิจัย ไม่ใช่เชิงพาณิชย์ และโอเพนซอร์ส ห้ามแจกจ่ายต่อ) Blackboard Treebank มาจากแหล่งข่าวเดียวกัน ส่วน Wisesight-1000 มาจาก PyThaiNLP/wisesight-sentiment — วางไว้เป็นโฟลเดอร์ข้าง thai-break/ (เช่น ../LST20_Corpus)
# รันจากโฟลเดอร์รากของ thai-break
# ค่าเริ่มต้นของไลบรารี: รายการคำฐานพร้อมน้ำหนักคำ
python3 tools/benchmark.py --corpus lst20 --corpus-dir ../LST20_Corpus/test \
    --dict data/words.txt --weights data/word-weights.tsv

# ภาษาอื่นที่อ่านบรรทัดจาก stdin เช่น PHP
python3 tools/benchmark.py --corpus lst20 --corpus-dir ../LST20_Corpus/test \
    --dict data/words.txt --weights data/word-weights.tsv --segmenter-cmd "php tools/segment.php {dict}"

# ฐาน + dict-extra (ใส่ --dict ซ้ำเพื่อรวมพจนานุกรม)
python3 tools/benchmark.py --corpus lst20 --corpus-dir ../LST20_Corpus/test \
    --dict data/words.txt --dict ../thai-break-dict-extra/dist/words-extra.tsv --weights data/word-weights.tsv

2. ประสิทธิภาพและการใช้ทรัพยากร (Performance & Resource Benchmarks)

ทดสอบการประมวลผลจริงบน PHP 8.4 (Native In-Memory) ด้วยการรันข้อความซ้ำ 1,000 รอบ:

ก. การใช้หน่วยความจำและเวลาเตรียมระบบ (Footprint & Startup per Language)

ภาษา / รูปแบบพจนานุกรม ไฟล์จัดเก็บ ขนาดไฟล์ เวลาโหลด (Startup) RAM Heap ต่อ Worker Throughput ค้นหาคำ
Rust (Native FST) data/words.fst 289.8 KB ~0.00 ms (Zero-copy) 0 Bytes (Buffer) 17.8 ล้าน lookups/s
Go (Compact DAWG) data/words.dawg 167.4 KB 0.04 ms (48 µs) < 0.2 MB 24.5 ล้าน lookups/s
TypeScript / Node (Compact DAWG) data/words.dawg 167.4 KB 0.70 ms < 0.3 MB 31.8 ล้าน lookups/s
PHP (Compact DAWG) data/words.dawg 167.4 KB 0.30 ms < 0.5 MB 1.75 ล้าน lookups/s
PHP (OPcache Preload Array) data/words.php 2.5 MB 0.00 ms (Preload) 0 MB (Shared Memory) 6.5 ล้าน lookups/s
PHP (Flat TSV Fallback) data/words.txt 492.5 KB 21.6 ms ~7.0 MB 6.5 ล้าน lookups/s
  • การติดตั้งเสริมใน PHP: ไม่ต้องใช้ APCu หรือ C-Extension เสริมใดๆ ทำงานบน Pure PHP ได้ทันทีผ่าน Compact DAWG หรือ OPcache Preloading

ข. ความเร็วในการตัดคำและตัดบรรทัด (Throughput & Latency)

ขนาดข้อความทดสอบ ความยาว คำที่ได้ เวลาประมวลผล (Latency) ความเร็ว (Throughput)
ประโยคสั้น (ข้อความแชท/ค้นหา) 16 ตัวอักษร 5 คำ 0.011 ms (11 ไมโครวินาที) ~1,440,000 chars/s
ประโยคทั่วไป (ข้อความเอกสาร/ข่าว) 67 ตัวอักษร 15 คำ 0.044 ms (44 ไมโครวินาที) ~1,530,000 chars/s
ย่อหน้ายาว (บทความ 1 พารากราฟ) 351 ตัวอักษร 78 คำ 0.213 ms (0.2 มิลลิวินาที) ~1,650,000 chars/s
บทความเต็มหน้า (ข้อความขนาดยาว) 3,520 ตัวอักษร 780 คำ 2.630 ms (2.6 มิลลิวินาที) ~1,340,000 chars/s
HTML Typographic Line Breaking (แทรก ZWSP ตาม UAX #14) 210 ตัวอักษร - 0.170 ms ~1,240,000 chars/s

การรันชุดทดสอบ (Tests Across All Languages)

# 1. PHP & Laravel Tests (รวม Unicode LineBreakTest conformance จาก testdata/)
./vendor/bin/phpunit
php php/tests/TokenizerTest.php

# 2. Go Tests & Benchmarks
cd go && go test -v ./... && go test -bench=. ./...

# 3. TypeScript / Node.js Tests
cd typescript && npm run build && npm test

# 4. Rust Core Tests & Build
cd rust && cargo test && cargo build --release

# 5. Python Tests
cd python && python3 -m unittest tests/test_thaibreak.py

# 6. Benchmark Tool Tests (synthetic data only, no corpus needed)
python3 -m unittest discover tools/tests

การจัดทำโค้ดและการเปิดเผยบทบาทของ AI (AI Disclosure & Attribution)

โครงการ ThaiBreak ได้รับการพัฒนา วางสถาปัตยกรรม และกำกับดูแลทิศทางโดยมนุษย์ (Kamthorn Krairaksa) โดยมีการใช้เทคโนโลยีปัญญาประดิษฐ์ (Generative AI) ในรูปแบบ Pair Programming & Multi-Agent Engineering ร่วมจัดทำโค้ดอย่างโปร่งใส ดังนี้:

  • Claude Sonnet 4.6 (Anthropic): ร่วมออกแบบโครงสร้างอัลกอริทึมหลัก (Thai Character Cluster: TCC, DAG Word Graph, Viterbi Forward/Backward Dynamic Programming, W3C/Unicode Typographic Line Breaking Rules) และการพัฒนาโค้ด Native ในภาษา PHP, Go, TypeScript รวมถึง Rust Core Engine
  • Gemini 3.8 Flash (Google DeepMind): ร่วมวิเคราะห์ประสิทธิภาพ (Performance Optimization), การตรวจสอบความถูกต้องข้ามภาษา (Cross-language Verification), การจัดทำชุดทดสอบรอบด้าน (Test Suites across all 5+ languages), การตรวจสอบความปลอดภัยและการจัดการหน่วยความจำ (Memory Safety & C-FFI Hardening) และการคัดกรองฐานข้อมูลพจนานุกรมให้เป็น Public Domain 100%

โค้ดทุกโมดูลได้รับการออกแบบ ตรวจทาน ปรับแก้สถาปัตยกรรม และผ่านการทดสอบอัตโนมัติ (Automated Unit & Integration Tests) ครบถ้วนทุกภาษา ทั้ง PHP, Go, TypeScript, Rust, C/C++ และ Python เพื่อความมั่นใจในคุณภาพ ความปลอดภัย และความถูกต้องตามหลักภาษาศาสตร์


OpenSearch / Elasticsearch Integration

สำหรับการใช้งาน ThaiBreak engine บน OpenSearch หรือ Elasticsearch ผ่าน Plugin สำเร็จรูป ดูที่:

opensearch-analysis-thaibreak v1.0.0

Release

Plugin OpenSearch ที่ใช้ Viterbi+TCC engine เดียวกัน พร้อม Token Filters ครบชุด:

Token Filter คำอธิบาย
thai_tone ลบวรรณยุกต์และไม้ไต่คู้เพื่อค้นหาแบบ Loose
thai_soundex Phonetic matching ด้วย Udom83 Algorithm
thai_keyboard แปลง Kedmanee ↔ QWERTY สำหรับ mis-type
thai_number แปลงเลขไทย (๐-๙) และคำอ่านตัวเลขเป็นอารบิก
# ติดตั้งสำหรับ OpenSearch 2.18.0
bin/opensearch-plugin install \
  https://github.com/kamthorn/opensearch-analysis-thaibreak/releases/download/v1.0.0/analysis-thaibreak-2.18.0.0.zip

รองรับ OpenSearch: 2.11.1 · 2.15.0 · 2.17.1 · 2.18.0 · 2.19.0 · 3.8.0

🔗 github.com/kamthorn/opensearch-analysis-thaibreak


เอกสารอ้างอิง

  • Royal Institute Dictionary: พจนานุกรมฉบับราชบัณฑิตยสถาน (Public Domain Standard Thai Wordlist)
  • Prachathai-67k: คลังข่าวประชาไท 67,000 บทความ (wannaphong/prachathai67k, Apache-2.0) ใช้นับน้ำหนักความถี่ของคำ
  • Thai Character Cluster (TCC): Theeramunkong et al., Multi-segmentation for Thai word extraction, 2000
  • Unicode Line Breaking Algorithm: Unicode Standard Annex #14 (UAX #14)
  • W3C Requirements for Thai Text Layout: W3C Working Group Note (tlreq)
  • License: Apache-2.0

Metadata

Release files for thaibreak 1.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for thaibreak 1.4.0
File
thaibreak-1.4.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
thaibreak-1.4.0-py3-none-manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64 Details
thaibreak-1.4.0-py3-none-manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.28+ ARM64 Details
thaibreak-1.4.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
thaibreak-1.4.0-py3-none-macosx_10_13_x86_64.whl Python 3 none macOS 10.13+ x86-64 Details

Total release size: 4.3 MB

Release files / thaibreak-1.4.0-py3-none-win_amd64.whl

Download URL thaibreak-1.4.0-py3-none-win_amd64.whl
Size 766.1 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
e99040636aea65c820b2496ba6907543f6ebce9c4b2997100f72200af20529d3
BLAKE2b-256 checksum
How to use checksums
acdee2d1a167d1778cdff0acd047bad6edf46c63098020d4524820bbf5742ef3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.5

Release files / thaibreak-1.4.0-py3-none-manylinux_2_28_x86_64.whl

Download URL thaibreak-1.4.0-py3-none-manylinux_2_28_x86_64.whl
Size 930.3 kB
Tags Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
a0a6e17c258a3109a689994d48e679512a98fd02871efcf18e1534d9424937f9
BLAKE2b-256 checksum
How to use checksums
d88fa9abdf6a0286e9ce962e3e457cf5bb937be2a19142f230a9f5ac84458ed5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.5

Release files / thaibreak-1.4.0-py3-none-manylinux_2_28_aarch64.whl

Download URL thaibreak-1.4.0-py3-none-manylinux_2_28_aarch64.whl
Size 925.2 kB
Tags Linux glibc 2.28+ ARM64 Python 3
SHA-256 checksum
How to use checksums
245e00da7fe2dca33adc7f797495682c5fe17f164451094f7ee70ddeb3999896
BLAKE2b-256 checksum
How to use checksums
6863331a13e055e62226fc2726035251751f341a8185d9101488f5c994ca8e30
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.5

Release files / thaibreak-1.4.0-py3-none-macosx_11_0_arm64.whl

Download URL thaibreak-1.4.0-py3-none-macosx_11_0_arm64.whl
Size 847.3 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
55dd9a61c20a5eb8ad96e2106e76e686a7a46399363f60b66e60769eed4b5f11
BLAKE2b-256 checksum
How to use checksums
b614b7be3b3cd4262a2e535e2abbc94cecb0b1722b5f744c5fac3d223a65fdc1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.5

Release files / thaibreak-1.4.0-py3-none-macosx_10_13_x86_64.whl

Download URL thaibreak-1.4.0-py3-none-macosx_10_13_x86_64.whl
Size 862.8 kB
Tags Python 3 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
c400e371f3159c07841277886518554d73d8844c4df1935a33e4748f9941312a
BLAKE2b-256 checksum
How to use checksums
d3c3340badf5ac80de75b5b019073acacad63bcd8ef10ca959da13a69723e58c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.5

Release history Release notifications | RSS feed

1.4.1

5 release files

This release

1.4.0 This release

5 release files

1.3.0

5 release files

1.2.0

5 release files

1.1.2

5 release files

1.0.3

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page