-
-
Notifications
You must be signed in to change notification settings - Fork 301
Add Thai profanity detection utilities with custom words support #1183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
1a9da7c
Initial plan
Copilot faa4dd6
Add Thai profanity detection feature
Copilot 9bce902
Remove trailing empty line from profanity_th.txt
Copilot 10c1413
Add custom_words parameter and improve tokenization with merged dict
Copilot 1af6b48
Update type hints to use lowercase built-in types (Python 3.9+)
Copilot a8b17f7
Merge dev branch - Resolve conflicts and align with latest codebase
Copilot ce0abc4
Merge branch 'dev' into copilot/add-profanity-detection-thai
wannaphong 7dd940d
Add documentation for profanity detection functions to docs/api/util.rst
Copilot 0906103
Update tests/core/test_profanity.py
bact b8ab5f8
Update pythainlp/corpus/profanity_th.txt
bact 448ffb3
Update pythainlp/util/profanity.py
bact a8d48c4
Remove unused imports, remove trailing whitespaces
bact f440490
Fix type violation: change custom_words type from set[str] to set[str…
Copilot 5d82c22
Update pythainlp/util/profanity.py
bact File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| # SPDX-FileCopyrightText: 2026 PyThaiNLP Project | ||
| # SPDX-FileType: OTHER | ||
| # SPDX-FileType: TEXT | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Thai profanity words | ||
| # | ||
| # This list contains common Thai profanity words for filtering/detection purposes | ||
| # Words are stored without tone marks or variations for broader matching | ||
| ควย | ||
| สัส | ||
| เหี้ย | ||
| ไอ้เหี้ย | ||
| ไอ้สัส | ||
| ระยำ | ||
| เย็ด | ||
| มึง | ||
| ไอ้มึง | ||
| กู | ||
| ไอ้กู | ||
| เชี่ย | ||
| ดอกทอง | ||
| สัตว์ | ||
| ไอ้สัตว์ | ||
| ชาติหมา | ||
| ตาย | ||
| ไอ้ตาย | ||
| บ้า | ||
| ไอ้บ้า | ||
| เวร | ||
| ไอ้เวร | ||
| เหี้ยน |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| # SPDX-FileCopyrightText: 2026 PyThaiNLP Project | ||
| # SPDX-FileType: SOURCE | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| """ | ||
| Profanity detection for Thai language | ||
| """ | ||
| from __future__ import annotations | ||
|
|
||
| from pythainlp.corpus.common import thai_profanity_words, thai_words | ||
| from pythainlp.tokenize import word_tokenize | ||
| from pythainlp.util.trie import dict_trie | ||
|
|
||
|
|
||
| def contains_profanity( | ||
| text: str, custom_words: set[str] | None = None, engine: str = "newmm" | ||
| ) -> bool: | ||
| """ | ||
| Check if the given text contains profanity words. | ||
|
|
||
| :param str text: Thai text to check | ||
| :param set custom_words: additional profanity words to check (default: None) | ||
| :param str engine: tokenization engine (default: "newmm") | ||
| :return: True if text contains profanity, False otherwise | ||
| :rtype: bool | ||
|
|
||
| :Example: | ||
| :: | ||
|
|
||
| from pythainlp.util import contains_profanity | ||
|
|
||
| print(contains_profanity("สวัสดีครับ")) | ||
| # output: False | ||
|
|
||
| print(contains_profanity("คำหยาบคาย")) | ||
| # output: True if the word is in the profanity list | ||
|
|
||
| # Add custom profanity words | ||
| print(contains_profanity("คำใหม่", custom_words={"คำใหม่"})) | ||
| # output: True | ||
| """ | ||
| if not text: | ||
| return False | ||
|
|
||
| profanity_set = set(thai_profanity_words()) | ||
| if custom_words: | ||
| profanity_set.update(custom_words) | ||
|
|
||
| # Create custom dictionary that merges thai_words and profanity_set | ||
| # for better tokenization | ||
| custom_dict_set = set(thai_words()) | ||
| custom_dict_set.update(profanity_set) | ||
| custom_dict = dict_trie(dict_source=custom_dict_set) | ||
|
|
||
| tokens = word_tokenize(text, custom_dict=custom_dict, engine=engine) | ||
|
|
||
| for token in tokens: | ||
| if token in profanity_set: | ||
| return True | ||
|
|
||
| return False | ||
|
|
||
|
|
||
| def find_profanity( | ||
| text: str, custom_words: set[str] | None = None, engine: str = "newmm" | ||
| ) -> list[str]: | ||
| """ | ||
| Find all profanity words in the given text. | ||
|
|
||
| :param str text: Thai text to check | ||
| :param set custom_words: additional profanity words to check (default: None) | ||
| :param str engine: tokenization engine (default: "newmm") | ||
| :return: list of profanity words found in the text | ||
| :rtype: list[str] | ||
|
|
||
| :Example: | ||
| :: | ||
|
|
||
| from pythainlp.util import find_profanity | ||
|
|
||
| print(find_profanity("สวัสดีครับ")) | ||
| # output: [] | ||
|
|
||
| print(find_profanity("text with profanity words")) | ||
| # output: ['profanity_word1', 'profanity_word2'] | ||
|
|
||
| # Add custom profanity words | ||
| print(find_profanity("คำใหม่", custom_words={"คำใหม่"})) | ||
| # output: ['คำใหม่'] | ||
| """ | ||
| if not text: | ||
| return [] | ||
|
|
||
| profanity_set = set(thai_profanity_words()) | ||
| if custom_words: | ||
| profanity_set.update(custom_words) | ||
|
|
||
| # Create custom dictionary that merges thai_words and profanity_set | ||
| # for better tokenization | ||
| custom_dict_set = set(thai_words()) | ||
| custom_dict_set.update(profanity_set) | ||
| custom_dict = dict_trie(dict_source=custom_dict_set) | ||
|
|
||
| tokens = word_tokenize(text, custom_dict=custom_dict, engine=engine) | ||
|
|
||
| found_profanity = [] | ||
| for token in tokens: | ||
| if token in profanity_set: | ||
| found_profanity.append(token) | ||
|
|
||
| return found_profanity | ||
|
|
||
|
|
||
| def censor_profanity( | ||
| text: str, | ||
| replacement: str = "*", | ||
| custom_words: set[str] | None = None, | ||
| engine: str = "newmm", | ||
| ) -> str: | ||
| """ | ||
| Replace profanity words in the text with a replacement character. | ||
|
|
||
| :param str text: Thai text to censor | ||
| :param str replacement: character to replace profanity with (default: "*") | ||
| :param set custom_words: additional profanity words to censor (default: None) | ||
| :param str engine: tokenization engine (default: "newmm") | ||
| :return: Text with profanity words censored | ||
| :rtype: str | ||
|
|
||
| :Example: | ||
| :: | ||
|
|
||
| from pythainlp.util import censor_profanity | ||
|
|
||
| print(censor_profanity("สวัสดีครับ")) | ||
| # output: สวัสดีครับ | ||
|
|
||
| print(censor_profanity("text with profanity word")) | ||
| # output: text with *** word | ||
|
|
||
| # Add custom profanity words | ||
| print(censor_profanity("คำใหม่", custom_words={"คำใหม่"})) | ||
| # output: ****** | ||
| """ | ||
| if not text: | ||
| return text | ||
|
|
||
| profanity_set = set(thai_profanity_words()) | ||
| if custom_words: | ||
| profanity_set.update(custom_words) | ||
|
|
||
| # Create custom dictionary that merges thai_words and profanity_set | ||
| # for better tokenization | ||
| custom_dict_set = set(thai_words()) | ||
| custom_dict_set.update(profanity_set) | ||
| custom_dict = dict_trie(dict_source=custom_dict_set) | ||
|
|
||
| tokens = word_tokenize( | ||
| text, custom_dict=custom_dict, engine=engine, keep_whitespace=True | ||
| ) | ||
|
|
||
| censored_tokens = [] | ||
| for token in tokens: | ||
| if token in profanity_set: | ||
| censored_tokens.append(replacement * len(token)) | ||
| else: | ||
| censored_tokens.append(token) | ||
|
|
||
| return "".join(censored_tokens) | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.