Bayan AI commited on
Commit ·
d7619b9
1
Parent(s): 8fcecea
Fix: Prevent conditional sentences rule from overcorrecting 'إن' and 'من' by requiring the subsequent word to be a verb
Browse files- src/nlp/grammar/grammar_rules.py +50 -0
- test_grammar_only.py +30 -0
src/nlp/grammar/grammar_rules.py
CHANGED
|
@@ -358,6 +358,55 @@ class ArabicGrammarGuard:
|
|
| 358 |
|
| 359 |
return text
|
| 360 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 361 |
|
| 362 |
def process(self, original_text, generated_text):
|
| 363 |
"""Apply all grammar rules to model output."""
|
|
@@ -372,6 +421,7 @@ class ArabicGrammarGuard:
|
|
| 372 |
('fix_gender_agreement', self.fix_gender_agreement),
|
| 373 |
('fix_prepositions_advanced', self.fix_prepositions_advanced),
|
| 374 |
('fix_subject_verb_agreement', self.fix_subject_verb_agreement),
|
|
|
|
| 375 |
('regex_rules_fallback', self.regex_rules_fallback),
|
| 376 |
]:
|
| 377 |
try:
|
|
|
|
| 358 |
|
| 359 |
return text
|
| 360 |
|
| 361 |
+
def fix_conditional_sentences(self, text):
|
| 362 |
+
conditional_particles = {'إن', 'من', 'ما', 'متى', 'مهما', 'أينما', 'حيثما', 'أيان', 'كيفما', 'أنى'}
|
| 363 |
+
tokens = simple_word_tokenize(text)
|
| 364 |
+
disambig_tokens = self.mle.disambiguate(tokens)
|
| 365 |
+
corrected_tokens = list(tokens)
|
| 366 |
+
|
| 367 |
+
# Lookahead for 2nd person context
|
| 368 |
+
has_2nd_person_context = any(t.endswith('كم') or t.endswith('كمو') or t.startswith('ت') for t in tokens)
|
| 369 |
+
|
| 370 |
+
in_cond = False
|
| 371 |
+
verbs_jazmed = 0
|
| 372 |
+
|
| 373 |
+
for i, token_info in enumerate(disambig_tokens):
|
| 374 |
+
word = corrected_tokens[i]
|
| 375 |
+
pos_tag = token_info.analyses[0].analysis.get('pos', 'unknown') if token_info.analyses else 'unknown'
|
| 376 |
+
|
| 377 |
+
if word in conditional_particles:
|
| 378 |
+
# To prevent overcorrection (e.g. 'إن الأطباء' treating 'إن' as conditional),
|
| 379 |
+
# ensure the immediately following word is a verb.
|
| 380 |
+
next_pos = 'unknown'
|
| 381 |
+
if i + 1 < len(disambig_tokens):
|
| 382 |
+
if disambig_tokens[i+1].analyses:
|
| 383 |
+
next_pos = disambig_tokens[i+1].analyses[0].analysis.get('pos', 'unknown')
|
| 384 |
+
|
| 385 |
+
if next_pos == 'verb':
|
| 386 |
+
in_cond = True
|
| 387 |
+
verbs_jazmed = 0
|
| 388 |
+
continue
|
| 389 |
+
|
| 390 |
+
if in_cond and pos_tag == 'verb':
|
| 391 |
+
# Apply jazm to present tense verbs ending in ون, ان, ين
|
| 392 |
+
if word.endswith('ون'):
|
| 393 |
+
word = word[:-2] + 'وا'
|
| 394 |
+
elif word.endswith('ان'):
|
| 395 |
+
word = word[:-2] + 'ا'
|
| 396 |
+
elif word.endswith('ين'):
|
| 397 |
+
word = word[:-2] + 'ي'
|
| 398 |
+
|
| 399 |
+
# Fix pronoun mismatch if 2nd person context exists
|
| 400 |
+
if has_2nd_person_context and word.startswith('ي') and (word.endswith('وا') or word.endswith('ا') or word.endswith('ي')):
|
| 401 |
+
word = 'ت' + word[1:]
|
| 402 |
+
|
| 403 |
+
corrected_tokens[i] = word
|
| 404 |
+
verbs_jazmed += 1
|
| 405 |
+
if verbs_jazmed >= 2:
|
| 406 |
+
in_cond = False
|
| 407 |
+
|
| 408 |
+
return " ".join(corrected_tokens)
|
| 409 |
+
|
| 410 |
|
| 411 |
def process(self, original_text, generated_text):
|
| 412 |
"""Apply all grammar rules to model output."""
|
|
|
|
| 421 |
('fix_gender_agreement', self.fix_gender_agreement),
|
| 422 |
('fix_prepositions_advanced', self.fix_prepositions_advanced),
|
| 423 |
('fix_subject_verb_agreement', self.fix_subject_verb_agreement),
|
| 424 |
+
('fix_conditional_sentences', self.fix_conditional_sentences),
|
| 425 |
('regex_rules_fallback', self.regex_rules_fallback),
|
| 426 |
]:
|
| 427 |
try:
|
test_grammar_only.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
import io
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
|
| 5 |
+
# Force UTF-8 encoding for standard output
|
| 6 |
+
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
| 7 |
+
|
| 8 |
+
# Add src to python path
|
| 9 |
+
sys.path.insert(0, str(Path(r'c:\Users\dell\PycharmProjects\JupyterProject1\PythonProject\BAYAN\src')))
|
| 10 |
+
|
| 11 |
+
from src.nlp.grammar.grammar_service import get_grammar_model
|
| 12 |
+
|
| 13 |
+
def test_grammar():
|
| 14 |
+
print("Initializing Grammar Service (No other heavy models loaded)...")
|
| 15 |
+
grammar_checker = get_grammar_model()
|
| 16 |
+
|
| 17 |
+
test_cases = [
|
| 18 |
+
"يذهبون المهندسون الى الشركة",
|
| 19 |
+
"يذهبون المهندسون الى الشركة، أليس كذلك؟",
|
| 20 |
+
"مرحبا، يا عالم الطيور!",
|
| 21 |
+
"متى يسعون في تطوير مهاراتكم بجد واخلاص تجدون ثمرة ذلك قريبا"
|
| 22 |
+
]
|
| 23 |
+
|
| 24 |
+
for text in test_cases:
|
| 25 |
+
print(f"\n[INPUT]: {text}")
|
| 26 |
+
corrected = grammar_checker.correct(text)
|
| 27 |
+
print(f"[OUTPUT]: {corrected}")
|
| 28 |
+
|
| 29 |
+
if __name__ == "__main__":
|
| 30 |
+
test_grammar()
|