Skip to content

Add check_khuap_klam to pythainlp.util for Thai consonant cluster detection - #1308

Merged
wannaphong merged 6 commits into
devfrom
copilot/add-thai-consonant-clusters
Mar 8, 2026
Merged

Add check_khuap_klam to pythainlp.util for Thai consonant cluster detection#1308
wannaphong merged 6 commits into
devfrom
copilot/add-thai-consonant-clusters

Conversation

Copilot AI commented Mar 7, 2026

Copy link
Copy Markdown
Contributor

What do these changes do

Adds check_khuap_klam(word) to pythainlp.util — a function that classifies Thai words by consonant cluster (Kham Khuap Klam, คำควบกล้ำ) type.

from pythainlp.util import check_khuap_klam

check_khuap_klam("กราบ")   # True  — true cluster (คำควบกล้ำแท้)
check_khuap_klam("ปลา")    # True
check_khuap_klam("จริง")   # False — false cluster (คำควบกล้ำไม่แท้)
check_khuap_klam("ทราย")   # False
check_khuap_klam("แม่")    # None  — not a cluster
check_khuap_klam("ตา")     # None

Return values:

  • True — true consonant cluster (คำควบกล้ำแท้): pronunciation merges two consonants (initial ก ข ค ต ป ผ พ ฟ บ + ร ล ว)
  • False — false consonant cluster (คำควบกล้ำไม่แท้): written as cluster (ทร จร ศร สร ซร) but not pronounced as one
  • None — not a consonant cluster

What was wrong

No utility existed in PyThaiNLP to programmatically identify Thai consonant clusters or distinguish true clusters from false ones.

How this fixes it

  • pythainlp/util/khuap_klam.py — new module; uses pronunciate(word, engine="w2p") (lazy import to avoid circular imports) to get the phonemic reading, then applies regex checks on both the written form and the pronunciation to classify the cluster type.
  • pythainlp/util/__init__.py — exports check_khuap_klam (added to __all__ and import block, both in alphabetical order).
  • tests/compact/testc_util.py — covers all three return values and the empty-string edge case (placed in the compact test suite as it requires the w2p transliteration engine).
  • CHANGELOG.md — entry added under the current dev version (line-length fixed to comply with MD013).
  • docs/api/util.rst — API documentation entry added in alphabetical order.

Your checklist for this pull request

  • Passed code styles and structures
  • Passed code linting checks and unit test
Original prompt

This section details on the original issue you should resolve

<issue_title>Add Thai Consonant Clusters</issue_title>
<issue_description>I write function to check Thai word is khuap klam (คำควบกล้ำ) or Thai Consonant Clusters.

import re
from pythainlp.transliterate import pronunciate

def check_khuap_klam(word):
    """
    Check Kham Khuap Klam (คำควบกล้ำ) or Thai Consonant Clusters

    The function is used to check Thai word is Kham Khuap Klam (คำควบกล้ำแท้ or คำควบกล้ำไม่แท้) or not is Kham Khuap Klam.

    Output: True - The word is Kham Khuap Klam and is The True Kham Khuap Klam (คำควบกล้ำแท้)
    False - The word is Kham Khuap Klam but is not The True Kham Khuap Klam (คำควบกล้ำไม่แท้)
    None - The word is not Kham Khuap Klam
    """
    # 1. แปลงคำเป็นเสียงอ่าน (engine "w2p" จะคืนค่าคำอ่านที่คั่นพยางค์ด้วยขีด "-")
    reading = pronunciate(word, engine="w2p").replace('ฺ',"")
    
    # 2. ดึงพยางค์แรกมาทดสอบ (หากต้องการประยุกต์ สามารถทำลูปเช็กทุกพยางค์ได้)
    first_syll_written = word
    first_syll_reading = reading.split('-')[0]
    
    # ฟังก์ชันช่วยตัด "สระหน้า" (เ แ โ ใ ไ) ออกก่อน เพื่อให้พยัญชนะต้นมาอยู่หน้าสุดเวลาดึงไปเทียบ Regex
    def strip_front_vowels(text):
        return re.sub(r'^[เแโใไ]+', '', text)
    
    written_core = strip_front_vowels(first_syll_written)
    reading_core = strip_front_vowels(first_syll_reading)
    
    # 3. กำหนดรูปแบบ Regex
    # พยัญชนะที่สามารถเป็นควบแท้ได้ (ก ข ค ต ป ผ พ ฟ บ + ร ล ว)
    true_cluster_pattern = re.compile(r'^([กขคตปผพฟบ][รลว])')
    # พยัญชนะที่มักเป็นควบไม่แท้ (ทร, จร, ศร, สร, ซร)
    false_cluster_pattern = re.compile(r'^(ทร|จร|ศร|สร|ซร)')
    
    # 4. ตรวจสอบสถานะจากรูปและเสียง
    is_true_sound = bool(true_cluster_pattern.match(reading_core))
    is_false_form = bool(false_cluster_pattern.match(written_core))
    
    # 5. สรุปผลลัพธ์
    if is_true_sound:
        return True
    elif is_false_form and not is_true_sound:
        return False
    else:
        return None

Test:

# --- ทดสอบการใช้งาน ---
test_words = ["กราบ","ปลา", "เพราะ","ตรง"] # คำควบกล้ำแท้
test_words+=["จริง","ไซร้","ทราย","เศร้า"] # คำควบกล้ำไม่แท้
test_words+=["แม่","ตา","มา","นา"] # ไม่ใช่คำควบกล้ำ

for w in test_words:
    print(check_khuap_klam(w))
```</issue_description>

<agent_instructions>Add this function to pythainlp.util, write the testset, and add docs</agent_instructions>

## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

…ection

Co-authored-by: wannaphong <8536487+wannaphong@users.noreply.github.com>
Copilot AI changed the title [WIP] Add function to check Thai consonant clusters Add check_khuap_klam to pythainlp.util for Thai consonant cluster detection Mar 7, 2026
@wannaphong

Copy link
Copy Markdown
Member

@copilot Add docs to docs/api/util.rst

Co-authored-by: wannaphong <8536487+wannaphong@users.noreply.github.com>

Copilot AI commented Mar 7, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Add docs to docs/api/util.rst

Added check_khuap_klam to docs/api/util.rst in alphabetical order (between bahttext and censor_profanity), following the existing entry format in that file. Commit: ca09669.

@wannaphong
wannaphong marked this pull request as ready for review March 7, 2026 06:50
Comment thread CHANGELOG.md Outdated
- Reorganize noauto test suite by dependency groups
(torch, tensorflow, onnx, cython, network) #1290
- Add BLEU, ROUGE, WER, and CER metrics to pythainlp.benchmarks #1295
- Add `check_khuap_klam` to `pythainlp.util` for checking Thai consonant clusters #1308

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Fix Line length
Check failure: Line length
CHANGELOG.md:41:81 MD013/line-length Line length [Expected: 80; Actual: 87]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c4482ea — wrapped the line to keep it within 80 characters.

Co-authored-by: wannaphong <8536487+wannaphong@users.noreply.github.com>
@wannaphong

Copy link
Copy Markdown
Member

@copilot Move the testset to tests/compact. It is not core testset.

Co-authored-by: wannaphong <8536487+wannaphong@users.noreply.github.com>

Copilot AI commented Mar 7, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Move the testset to tests/compact. It is not core testset.

Done in e59334d — moved test_check_khuap_klam to tests/compact/testc_util.py (new KhuapKlamTestCaseC class) and removed it from tests/core/test_util.py.

@sonarqubecloud

sonarqubecloud Bot commented Mar 7, 2026

Copy link
Copy Markdown

@wannaphong
wannaphong merged commit c6d19d6 into dev Mar 8, 2026
27 checks passed
@bact bact added this to the 5.3 milestone Mar 8, 2026
@wannaphong
wannaphong deleted the copilot/add-thai-consonant-clusters branch March 8, 2026 17:45
@bact bact added the enhancement enhance functionalities label Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement enhance functionalities

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Add Thai Consonant Clusters

3 participants