Skip to content

Commit 22f2447

Browse files
authored
Merge branch 'dev' into main
2 parents 38195b0 + fd089d9 commit 22f2447

25 files changed

Lines changed: 1064 additions & 145 deletions

CHANGELOG.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ and this project adheres to
1717
- Full release notes: <https://github.com/PyThaiNLP/pythainlp/releases>
1818
- Commit history: <https://github.com/PyThaiNLP/pythainlp/compare/v5.3.3...v5.3.4>
1919

20+
## [Unreleased]
21+
22+
## Changed
23+
24+
- Improve guardrails in `check_sara()` and `nighit()`
25+
2026
## [5.3.5] - 2026-07-30
2127

2228
### Fixed
@@ -26,7 +32,6 @@ and this project adheres to
2632
- Fix: CodeQL ReDoS vulnerability in ULMFiT replace_url #1400
2733
- fix: remove unconditional overwrite that disables teacher forcing in Seq2Seq #1380
2834

29-
3035
## [5.3.4] - 2026-04-02
3136

3237
### Fixed
@@ -36,6 +41,18 @@ and this project adheres to
3641
- Build WSD Trie after populating dictionary (#1388).
3742
- Doctests across all modules (#1392).
3843

44+
## [Unreleased]
45+
46+
### Changed
47+
48+
- `pythainlp.tokenize.deepcut`: migrated from the TensorFlow-based `deepcut`
49+
package to a built-in ONNX inference engine, removing the TensorFlow
50+
dependency. The `deepcut.onnx` model (ported from
51+
[LEKCut](https://github.com/PyThaiNLP/LEKCut)) is now bundled with PyThaiNLP.
52+
The `segment()` API is unchanged; the `custom_dict` parameter is kept for
53+
backward compatibility but is no longer applied to the model inference.
54+
Deepcut tests moved from `tests/noauto_tensorflow/` to `tests/noauto_onnx/`.
55+
3956
## [5.3.3] - 2026-03-26
4057

4158
Security fixes and thai2rom_onnx bug fixes.

docs/api/transliterate.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,25 @@ Modules
1717

1818
The `transliterate` function serves as a versatile transliteration tool, offering a range of transliteration engines to choose from. It provides flexibility and customization for your transliteration needs.
1919

20+
.. autofunction:: transliterate_wiktionary
21+
:noindex:
22+
2023
.. autofunction:: pronunciate
2124
:noindex:
2225

2326
This function provides assistance in generating phonetic representations of Thai words, which is particularly useful for language learning and pronunciation practice.
2427

28+
.. autofunction:: pronunciate_pali
29+
:noindex:
30+
2531
.. autofunction:: puan
2632
:noindex:
2733

2834
The `puan` function offers a unique transliteration feature known as "Puan." It provides a specialized transliteration method for Thai text and is an additional option for rendering Thai text into English characters.
2935

36+
.. autofunction:: get_word_dict
37+
:noindex:
38+
3039
.. autoclass:: pythainlp.transliterate.wunsen.WunsenTransliterate
3140
:members:
3241

pyproject.toml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ noauto-torch = [
219219

220220
# TensorFlow-based dependencies - for tests.noauto_tensorflow
221221
noauto-tensorflow = [
222-
"deepcut>=0.7.0",
223222
"numpy>=1.26.0",
224223
]
225224

@@ -247,10 +246,8 @@ full = [
247246
"attacut==1.0.6",
248247
"attaparse==1.0.0",
249248
"bpemb>=0.3.6,<0.4",
250-
"budoux==0.8.4",
251-
"deepcut==0.7.0.0",
252-
"emoji>=0.6.0,<1",
253-
"epitran==1.35.2",
249+
"budoux==0.7.0",
250+
"epitran==1.26.0",
254251
"esupar>=1.3.9,<2",
255252
'fairseq>=0.10.0,<0.13;python_version<"3.11"',
256253
'fairseq-fixed==0.12.3.1,<0.13;python_version>="3.11"',
@@ -455,7 +452,6 @@ module = [
455452
"attaparse.*",
456453
"bpemb.*",
457454
"budoux.*",
458-
"deepcut.*",
459455
"emoji.*",
460456
"epitran.*",
461457
"esupar.*",

pythainlp/corpus/deepcut.onnx

2.08 MB
Binary file not shown.

pythainlp/corpus/default_db.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,29 @@
11
{
2+
"deepcut_onnx": {
3+
"name": "deepcut_onnx",
4+
"latest_version": "1.0.0",
5+
"description": "DeepCut ONNX model",
6+
"long_description": "DeepCut Thai word segmentation model in ONNX format, ported from the original TensorFlow model",
7+
"url": "https://github.com/PyThaiNLP/LEKCut",
8+
"authors": [
9+
"Rakpong Kittinaradorn",
10+
"Titipat Achakulvisut",
11+
"Korakot Chaovavanich",
12+
"Kittinan Srithaworn",
13+
"Pattarawat Chormai",
14+
"Chanwit Kaewkasi",
15+
"Tulakan Ruangrong",
16+
"Krichkorn Oparad"
17+
],
18+
"license": "MIT",
19+
"versions": {
20+
"1.0.0": {
21+
"filename": "deepcut.onnx",
22+
"md5": "f4662560dd9a706bfb1d7790ad6c667f",
23+
"pythainlp_version": ">=5.4.0"
24+
}
25+
}
26+
},
227
"thainer": {
328
"name": "thainer",
429
"latest_version": "1.5.1",

pythainlp/corpus/words_th.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11552,6 +11552,7 @@
1155211552
เค
1155311553
แคเฟ
1155411554
แคแกล
11555+
แคคตัส
1155511556
แคชเชียร์
1155611557
แคชเมียร์
1155711558
แคช
@@ -18381,6 +18382,7 @@
1838118382
โดกเดก
1838218383
โด่งดัง
1838318384
โด่ง
18385+
โดจิน
1838418386
โดซีแท็กเซล
1838518387
โดด ๆ
1838618388
โดดเด่น
@@ -20307,6 +20309,7 @@
2030720309
ตาลุก
2030820310
ตาลุชะ
2030920311
ตาลุ
20312+
ตาลโตนด
2031020313
ตาเล็กตาน้อย
2031120314
ต๋าว
2031220315
ตาว
@@ -38600,6 +38603,7 @@
3860038603
มั่ง
3860138604
มั้ง
3860238605
มัง
38606+
มังงะ
3860338607
มั่งมีในใจ แล่นใบบนบก
3860438608
มั่งมี
3860538609
มังราย
@@ -45834,6 +45838,7 @@
4583445838
ลิงหลอกเจ้า
4583545839
ลิงอุรังอุตัง
4583645840
ลิจฉวี
45841+
ลิซ่า
4583745842
ลิดตีนปู
4583845843
ลิดรอน
4583945844
ลิด

pythainlp/khavee/core.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,15 @@ def check_sara(self, word: str) -> str:
5353
sara = []
5454
countoa = 0
5555

56+
if not word:
57+
return ""
58+
5659
# In case of การันย์
5760
if "์" in word[-1]:
5861
word = word[:-2]
62+
# After removing the karun, the word may become empty (e.g. "ก์")
63+
if not word:
64+
return ""
5965

6066
# In case of สระเดี่ยว
6167
for i in word:
@@ -217,7 +223,7 @@ def check_sara(self, word: str) -> str:
217223
sara.append("เอือ")
218224

219225
if not sara:
220-
return "Can't find Sara in this word"
226+
return ""
221227

222228
return sara[0]
223229

@@ -251,6 +257,9 @@ def check_marttra(self, word: str) -> str:
251257
word = self.handle_karun_sound_silence(word)
252258
word = remove_tonemark(word)
253259

260+
if not word:
261+
return ""
262+
254263
# Check for ำ at the end (represents "am" sound, ends with m)
255264
if word[-1] == "ำ":
256265
return "กม"

pythainlp/morpheme/word_formation.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,28 @@ def nighit(w1: str, w2: str) -> str:
3535
>>> nighit("สํ", "โยค")
3636
'สังโยค'
3737
"""
38+
if not isinstance(w1, str) or not isinstance(w2, str):
39+
raise TypeError("Both w1 and w2 must be strings.")
40+
w1 = w1.strip()
41+
w2 = w2.strip()
42+
if not w1:
43+
return w2
44+
if not w2:
45+
return w1
3846
if not str(w1).endswith("ํ") and len(w1) != 2:
3947
raise NotImplementedError(f"The function doesn't support {w1}.")
4048
list_w1 = list(w1)
4149
list_w2 = list(w2)
4250
newword = []
4351
newword.append(list_w1[0])
4452
newword.append("ั")
45-
consonant_start = [i for i in list_w2 if i in set(thai_consonants)][0]
53+
_consonants = set(thai_consonants)
54+
consonants_in_w2 = [i for i in list_w2 if i in _consonants]
55+
if not consonants_in_w2:
56+
raise ValueError(
57+
f"w2 {w2!r} contains no Thai consonants."
58+
)
59+
consonant_start = consonants_in_w2[0]
4660
if consonant_start in ["ก", "ช", "ค", "ข", "ง"]:
4761
newword.append("ง")
4862
elif consonant_start in ["จ", "ฉ", "ช", "ฌ"]:

pythainlp/soundex/metasound.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
_CONS_THANTHAKHAT: str = "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ์"
1717
_THANTHAKHAT: str = "์" # \u0e4c
1818
_C1: str = "กขฃคฆฅ" # sound K -> coded letter 1
19-
_C2: str = "จฉชฌซฐทฒดฎตสศษ" # D -> 2
19+
_C2: str = "จฉชฌซฐฏทฑฒถธดฎตสศษ" # D -> 2
2020
_C3: str = "ฟฝพผภบป" # B -> 3
2121
_C4: str = "ง" # NG -> 4
2222
_C5: str = "ลฬรนณฦญ" # N -> 5
@@ -71,7 +71,8 @@ def metasound(text: str, length: int = 4) -> str:
7171
chars[i] = " "
7272
i += 1
7373

74-
# retain first consonant, encode the rest
74+
# filter out spaces left by karan removal, then truncate
75+
chars = [c for c in chars if c != " "]
7576
chars = chars[:length]
7677
i = 1
7778
while i < len(chars):

pythainlp/soundex/prayut_and_somchaip.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
_C0: str = "AEIOUHWYอ"
2020
_C1: str = "BFPVบฝฟปผพภว"
21-
_C2: str = "CGJKQSXZขฃคฅฆฉขฌกจซศษส"
21+
_C2: str = "CGJKQSXZขฃคฅฆฉฌกจซศษส"
2222
_C3: str = "DTฎดฏตฐฑฒถทธ"
2323
_C4: str = "Lลฬ"
2424
_C5: str = "MNมณน"

0 commit comments

Comments
 (0)