השלמה אוטומטית מבוססת בינה מלאכותית לחיפוש במובייל: הצעות תוך 100 אלפיות השנייה
משתמש מקליד 'nik' בשורת החיפוש, והמערכת מציעה מיד אפשרויות רלוונטיות: 'נעלי נייק', 'ביגוד נייק', 'אביזרי נייק'. זמן ההשהיה האידיאלי הוא מתחת ל-100 אלפיות השנייה מהקלדת התו ועד להצגת ההצעה. כל עיכוב מעל 200 אלפיות השנייה מפחית את ההמרה ב-20%. לצוות שלנו ניסיון של למעלה מ-5 שנים ביישום השלמה אוטומטית לחיפוש, השלמה אוטומטית מבוססת בינה מלאכותית, ובינה מלאכותית לחיפוש במובייל עבור יותר מ-50 פרויקטים. בואו נחקור כיצד לבנות מערכת השלמה אוטומטית חזקה באמצעות Elasticsearch, Swift, Kotlin ו-Flutter, ומאילו טעויות כדאי להימנע.
השלמה אוטומטית היא אחת מהתכונות הרגישות ביותר לזמן השהיה. משתמשים מצפים להצעות מהר יותר ממה שהם יכולים להבחין בהופעתן. השאילתות חייבות להיות רלוונטיות, לא רק פופולריות. אנו מבטיחים ביצועים יציבים ב-10,000 שאילתות בשנייה וכיסוי של 80% מהתחיליות הנפוצות ביותר.
הפתרון שלנו משלב השלמה אוטומטית לחיפוש, השלמה אוטומטית מבוססת בינה מלאכותית, והצעות חיפוש לאפליקציית מובייל עם Elasticsearch completion suggester, התאמה אישית של חיפוש, מטמון במכשיר, debounce להשלמה אוטומטית, חיפוש מטושטש, Trie להשלמה אוטומטית, התאמה מטושטשת, דירוג הצעות, בינה מלאכותית לחיפוש במובייל, והשלמה אוטומטית מותאמת אישית.
למה חיפוש תחילית פשוט לא עובד
יישום נאיבי מאחסן שאילתות תכופות במילון ומחפש לפי תחילית. זה עובד עבור 'nik' → 'נעלי נייק' אבל נשבר עבור שגיאות כתיב ('nike' → 'Nike'), תעתיק ('קרוסובקי' לעומת 'סניקרס'), שאילתות דומות סמנטית ('נעלי ריצה' כשמקלידים 'סניקרס'), והתאמה אישית (אותה שאילתה 'שמלה' עבור משתמשים שונים).
ארכיטקטורת השלמה אוטומטית מוכנה לייצור
Trie + חיפוש מטושטש למהירות
השכבה הבסיסית היא Trie על שאילתות פופולריות עם חיפוש מטושטש באמצעות BK-tree או מחיקה סימטרית. Elasticsearch עם סוג השדה completion מספק התאמה מטושטשת מוכנה לשימוש:
{
"mappings": {
"properties": {
"suggest": {
"type": "completion",
"analyzer": "standard",
"contexts": [
{
"name": "category",
"type": "category"
}
]
},
"weight": {
"type": "integer"
}
}
}
} # Поиск автодополнений через ES Completion Suggester
async def get_suggestions(prefix: str, category: str, user_id: str) -> list[str]:
response = await es.search(
index="search_suggestions",
body={
"suggest": {
"query_suggest": {
"prefix": prefix,
"completion": {
"field": "suggest",
"size": 8,
"fuzzy": {"fuzziness": "AUTO"},
"contexts": {"category": [category]}
}
}
}
}
)
return [hit["_source"]["query"] for hit in response["suggest"]["query_suggest"][0]["options"]]היעילות של גישה זו מאושרת על ידי תיעוד Elasticsearch.
דירוג הצעות מותאם אישית
הצעות גולמיות מ-ES עוברות דירוג מחדש על סמך היסטוריית המשתמש. מאפייני הדירוג כוללים:
-
{ "mappings": { "properties": { "suggest": { "type": "completion", "analyzer": "standard", "contexts": [ {"name": "category", "type": "category"} ] }, "weight": {"type": "integer"} } } }– כמה פעמים שאילתה זו הוזנה על ידי כל המשתמשים -
# Поиск автодополнений через ES Completion Suggester async def get_suggestions(prefix: str, category: str, user_id: str) -> list[str]: response = await es.search( index="search_suggestions", body={ "suggest": { "query_suggest": { "prefix": prefix, "completion": { "field": "suggest", "size": 8, "fuzzy": {"fuzziness": "AUTO"}, "contexts": {"category": [category]} } } } } ) return [hit["_source"]["query"] for hit in response["suggest"]["query_suggest"][0]["options"]]– האם המשתמש הזין שאילתה דומה בעבר -
global_frequency– עד כמה הקטגוריה של השאילתה קרובה לתחומי העניין של המשתמש -
user_query_history_match– שאילתות טרנדיות מ-24 השעות האחרונות מקבלות חיזוק
מטמון במכשיר לתגובה מיידית
3–5 התווים הראשונים של שאילתה מכסים כ-80% מהשילובים הפופולריים של תחיליות. אנו מאחסנים במטמון הצעות עבור 500 התחיליות הנפוצות ביותר במכשיר בעת הפעלת האפליקציה:
// Android: предзагрузка популярных prefix-подсказок
class AutocompleteCache(context: Context) {
private val db = Room.databaseBuilder(context, AutocompleteDatabase::class.java, "autocomplete").build()
suspend fun preload() {
val popularPrefixes = autocompleteApi.getPopularPrefixes(limit = 500)
db.suggestionDao().insertAll(popularPrefixes)
}
suspend fun getSuggestions(prefix: String): List<String> {
// сначала проверяем локальный кэш
val cached = db.suggestionDao().getSuggestions(prefix)
if (cached.isNotEmpty()) return cached
// если нет в кэше — запрос на сервер
return autocompleteApi.getSuggestions(prefix)
}
} Debounce וביטול בצד הלקוח
לא כל תו צריך להפעיל בקשה חדשה. השתמשו ב-debounce של 150–200 אלפיות השנייה ובטלו כל בקשה בתהליך:
// iOS: debounced автодополнение с cancellation
class SearchViewModel: ObservableObject {
@Published var suggestions: [String] = []
private var searchTask: Task<Void, Never>?
func onQueryChanged(_ query: String) {
searchTask?.cancel()
guard query.count >= 2 else {
suggestions = []
return
}
searchTask = Task {
try? await Task.sleep(nanoseconds: 150_000_000) // 150ms debounce
guard !Task.isCancelled else { return }
let results = try? await autocompleteService.getSuggestions(query)
await MainActor.run {
suggestions = results ?? []
}
}
}
} רישום בחירת הצעה
כאשר המשתמש מקיש על הצעה, אנו רושמים את המיקום ברשימה, את התחילית בעת הבחירה, ואת השאילתה הסופית. נתונים אלה משמשים כנתוני אימון לגרסה הבאה של הדירוג.
השוואת שיטות השלמה אוטומטית
| שיטה | זמן השהיה | התאמה אישית | שגיאות כתיב/תעתיק | מורכבות |
|---|---|---|---|---|
| חיפוש תחילית (Trie) | <50 אלפיות השנייה | לא | לא נתמך | נמוכה |
| Elasticsearch Completion | <100 אלפיות השנייה | באמצעות הקשרים | התאמה מטושטשת AUTO | בינונית |
| Trie במכשיר + דירוג | <20 אלפיות השנייה | כן (היסטוריה, זיקה) | חלקית | גבוהה |
ניתוח עלויות
| היבט | ערך |
|---|---|
| עלות תשתית לשאילתה | $0.0008 |
| חיסכון חודשי עם מטמון במכשיר | עד $12,000 |
| תקופת החזר עבור התאמה אישית | 3 חודשים |
האצת תגובת השלמה אוטומטית
שיטות מפתח: טעינה מוקדמת של מטמון במכשיר, debounce עם ביטול בקשות קודמות, ושימוש ב-Trie בשרת. אנו גם מיישמים רישום אסינכרוני כדי למנוע חסימת ממשק המשתמש. זה מפחית את זמן ההשהיה ב-40% בהשוואה ליישום נאיבי. עלות היישום לשאילתה היא כ-$0.0008, וחיסכון בעלויות השרת יכול להגיע ל-$12,000 בחודש.
מה כלול ביישום מפתח ביד
היישום כולל: השלמה אוטומטית בסיסית (Elasticsearch Completion עם התאמה מטושטשת, ללא התאמה אישית – 2-3 ימים), דירוג הצעות מותאם אישית (היסטוריית משתמש, זיקת קטגוריות, טרנדים – +שבוע), מטמון במכשיר (Room לאנדרואיד ו-Core Data ל-iOS עם טעינה מוקדמת של 500 תחיליות – +2-3 ימים), ולוגיקת לקוח (debounce, ביטול, אינטגרציית UI – +1-2 ימים). אתם מקבלים פתרון עובד עם קוד מקור, תיעוד API, גישה לאחסון ההצעות, הדרכת צוות, ותמיכה טכנית לחודש אחד לאחר הפריסה.
לוח זמנים ליישום
| תכונה | משך זמן |
|---|---|
| השלמה אוטומטית בסיסית (Elasticsearch) | 2-3 ימים |
| דירוג מותאם אישית | שבוע |
| מטמון במכשיר (אנדרואיד & iOS) | 2-3 ימים |
| לוגיקת לקוח + UI | 1-2 ימים |
חשיבות ההתאמה האישית בהשלמה אוטומטית
התאמה אישית משפרת את רלוונטיות ההצעות עבור כל משתמש. כשמקלידים 'שמלה', משתמש אחד מחפש שמלות ערב, אחר מחפש שמלות קז'ואל. הדירוג מתחשב בהיסטוריית השאילתות, זיקת קטגוריות וטרנדים. זה מגדיל את שיעור הקליקים על הצעות ב-25-35% ומקצר את זמן החיפוש.
התהליך שלנו
- ניתוח לוגי חיפוש – חילוץ 1000 השאילתות המובילות, זיהוי דפוסי שגיאות כתיב, שפות, תעתיק.
- הגדרת Elasticsearch Completion Suggester – עם התאמה מטושטשת, מסנני הקשר.
- פיתוח דירוג הצעות מותאם אישית – על בסיס היסטוריית משתמש.
- יישום מטמון במכשיר – לאנדרואיד (Room) ול-iOS (Core Data).
- אינטגרציה בצד הלקוח – debounce, ביטול, UI.
- בדיקות ופריסה – בדיקות עומס, App Store / Google Play.







