OpenSearch மற்றும் CJK மூலம் எழுத்துப் பிழைகளைத் தாங்கும் தேடலை நான் எவ்வாறு சேர்த்தேன்
தேடல் முடிவுகள் ஏதும் வராத நிலை (Zero-result queries) எங்களது watch time-ஐப் பாதித்தது.
ஒரு வருடமாக, TopVideoHub தேடலுக்காக SQLite FTS5-ஐப் பயன்படுத்தியது. இது துல்லியமானத் தேடல்களுக்கு (exact matches) நன்றாக வேலை செய்தது. ஆனால் பயனர்கள் எழுத்துப் பிழைகளைச் செய்யும்போது இது தோல்வியடைந்தது.
மக்கள் "demon slayer" என்பதற்குப் பதிலாக "demon slyer" என்று தேடினர். ஜப்பானிய அல்லது கொரியத் தலைப்புகளில் தேவையற்ற இடைவெளிகளைச் சேர்த்தனர். FTS5 துல்லியமான டோக்கன்களை (exact tokens) மட்டுமே பொருத்துவதால், ஒரு சிறிய எழுத்துப் பிழை கூட முடிவுகள் ஏதும் வராத நிலையை (zero results) உருவாக்கியது. பயனர்கள் மீண்டும் தேடவில்லை; அவர்கள் வெளியேறிவிட்டனர்.
எங்களது தலைப்புத் தேடலை (title search) நான் OpenSearch-க்கு மாற்றினேன். பன்மொழிப் பார்வையாளர்களுக்கு (multilingual audience) இதை நான் எவ்வாறு தீர்த்தேன் என்பது இதோ.
நிலையான Fuzziness-ல் உள்ள சிக்கல்
எழுத்துப் பிழைகளைச் சரிசெய்ய "fuzziness"-ஐப் பயன்படுத்துமாறு பெரும்பாலான பயிற்சிகள் (tutorials) கூறுகின்றன. இது ஆங்கிலத்திற்கு வேலை செய்யும், ஆனால் சீன, ஜப்பானிய மற்றும் கொரிய (CJK) உரைகளுக்கு இது தோல்வியடையும்.
- CJK-க்கு Edit distance சரியானது அல்ல. CJK-வில் ஒரு எழுத்துப் பிழை என்பது பெரும்பாலும் முற்றிலும் தவறான எழுத்தைப் பயன்படுத்துவதைக் குறிக்கும்.
- நிலையான fuzziness அர்த்தமற்ற முடிவுகளை (semantic garbage) உருவாக்கும். "fire" மற்றும் "water" ஆகியவற்றுக்கு இடையே ஒரு மாற்றம் மட்டுமே இருப்பதால், அது இரண்டையும் பொருத்தக்கூடும்.
- Tokenization செய்வது கடினம். CJK மொழிகளில் சொற்களுக்கு இடையே இடைவெளிகள் பயன்படுத்தப்படுவதில்லை.
தீர்வு: ஒரு மல்டி-ஃபீல்ட் அணுகுமுறை (A Multi-Field Approach)
நான் அனைத்து உரைகளையும் ஒரே மாதிரியாகக் கருதுவதை நிறுத்தினேன். மூன்று வெவ்வேறு வழிகளில் குறியீடாக்கம் (index) செய்யும் ஒரு தர்க்கரீதியான தலைப்புப் புலத்தை (logical title field) உருவாக்கினேன்:
- Latin மற்றும் Romaji: fuzziness வசதியுடன் கூடிய நிலையான tokenization-ஐப் பயன்படுத்தினேன். இதன் prefix length-ஐ 1 என அமைத்தேன். இது "demon" என்பது "demn"-உடன் பொருந்தும், ஆனால் "lemon" என்பது "demon"-உடன் பொருந்தாது என்பதை உறுதி செய்கிறது.
- CJK Text: நான் ஒரு CJK bigram analyzer மற்றும் ICU normalizer-ஐப் பயன்படுத்தினேன். fuzziness வசதியை அணைத்துவிட்டேன் (OFF). அதற்குப் பதிலாக, 70% குறைந்தபட்ச பொருத்தம் (minimum match threshold) என்ற அளவைப் பயன்படுத்தினேன்.
- Autocomplete: search-as-you-type முடிவுகளை வழங்க ஒரு edge-ngram புலத்தைப் பயன்படுத்தினேன்.
கட்டமைப்பு மற்றும் தரவுப் பாதுகாப்பு (Architecture and Data Safety)
நான் SQLite-ஐத் தரவின் ஒரே ஆதாரமாக (single source of truth) வைத்திருந்தேன். OpenSearch ஒரு வேகமான, மீண்டும் உருவாக்கக்கூடிய குறியீடாக (rebuildable index) செயல்படுகிறது.
- OpenSearch-க்குத் தரவுகளைப் பெரிய தொகுதிகளாக (bulk batches) அனுப்ப PHP-ஐப் பயன்படுத்துகிறேன்.
- பயனர் கோரிக்கையின் (user request) போது நான் ஒருபோதும் indexing செய்வதில்லை.
- "drift"-ஐச் சரிபார்க்க ஒரு Python ஸ்கிரிப்டை இயக்குகிறேன். இது OpenSearch எண்ணிக்கையானது SQLite எண்ணிக்கையுடன் ஒத்துப்போவதை உறுதி செய்கிறது.
முடிவுகள்
இந்த மாற்றம் மிகப்பெரியது:
- முடிவுகள் ஏதும் வராத தேடல்கள் (Zero-result queries) 14%-லிருந்து 3%-க்கும் குறைவாகக் குறைந்தது.
- பயனர்கள் தாங்கள் விரும்புவதைத் உடனடியாகக் கண்டறிந்ததால், தேடல் அமர்வுகள் (Search sessions) நீளமானது.
- Latency சுமார் 40ms என்ற அளவில் குறைவாகவே உள்ளது.
நீங்கள் பன்மொழிப் பார்வையாளர்களுக்குச் சேவை செய்கிறீர்கள் என்றால், இதை நினைவில் கொள்ளுங்கள்: எழுத்துப் பிழைத் தாங்குதலும் (typo tolerance) CJK பொருத்தலும் இரண்டு வெவ்வேறு சிக்கல்கள். உங்களுக்கு இரண்டு வெவ்வேறு தீர்வுகள் தேவை.
