קופיילוט שנותן רמזים טובים משלך — בעזרת וקטורים, קצת גאומטריה, ואפס מודלי שפה ענקיים. זו הצלילה לעומק: למה זו בכלל בעיית דמיון סמנטי, איך בוחרים את הרמז, ולמה דווקא עברית הקשתה.
ב"שם קוד" רב המרגלים נותן מילה אחת ומספר, והצוות מנחש את הקלפים שלו — בלי לגעת בקלפים של היריב, בניטרליים, ובמיוחד לא במתנקש. ברגע שמפסיקים לחשוב על זה כמשחק מילים ומתחילים לחשוב עליו כקרבה במרחב, הפתרון מתבקש.
כל מילה הופכת לווקטור — נקודה במרחב של 300 ממדים. "קרבה במשמעות" היא פשוט מרחק בין נקודות. רמז מצוין צריך לקיים תנאי אחד: להיות הכי קרוב למילים שלך, והכי רחוק מכל השאר. המילה שממקסמת את התנאי הזה — היא הרמז.
הקופיילוט מדרג כל מילה־מועמדת מאוצר הרמזים לפי ציון מדורג: בונוס על קרבה למילים שלך, וקנס הולך וגדל ככל שמתקרבים ליריב, לניטרלי, ובעיקר למתנקש. זה הניסוח (s′ היא קוסינוס ממורכז סביב 25 מילות הלוח — תיקון אניזוטרופיה כך שמילים נפוצות "קרובות לכולם" לא מנצחות):
g(c) = Σ s′(c, b) // top-m of your words — reward
− λₐ · max(0, s′(c, assassin)) // the black card — avoid hardest
− λₒ · max(0, max s′(c, opp)) // rival team — avoid strongly
− λₙ · max(0, max s′(c, neutral))// bystanders — avoid mildly
+ λ_f · FREQ(c) // prefer mid-frequency words
where s′(c, w) = cos(c, w) − mean_b cos(c, b)שלושת הקנסות הם מדורגים: λₐ ≫ λₒ > λₙ. ככה הקופיילוט "מפחד" מהמתנקש הרבה יותר מאשר
מקלף ניטרלי. הרמז שמנצח הוא לא בהכרח הכי קרוב למילים שלך — אלא זה שמשיג את ההפרדה הנקייה ביותר
בין שלך לכל השאר.
זה לא היה ניחוש. ערכנו מבחן ראש־בראש: כל אנקודר שיחק רב מרגלים על אותם לוחות ואותו אוצר רמזים, ומדדנו כמה טוב מנחש עצמאי משחזר את המילים שהאנקודר התכוון אליהן (recovery), ועד כמה הרמז שומר מרחק מהמתנקש.
| אנקודר | recovery | margin (הפרדה) | סוג |
|---|---|---|---|
| fastText | 0.375 | 0.194 | וקטורים סטטיים |
| EmbeddingGemma‑300m | 0.292 | 0.131 | SOTA‑small 2025 |
| Qwen3‑Embedding‑0.6B | 0.125 | 0.112 | סנטנס‑אמבדינג |
למה דווקא הסטטי? כי "שם קוד" דורש אסוציאטיביות (מלך→כתר→טירה), לא נרדפוּת. וקטורים סטטיים מבוססי הופעה־משותפת לוכדים בדיוק את זה — וזו הסיבה שספרות ה‑AI של המשחק משתמשת בהם. מודלי סנטנס־אמבדינג מאומנים על דמיון משפטים, ולמילה בודדת הם דוחסים את כל הקוסינוסים לטווח צר וגבוה (qwen בקושי הבדיל בין "מלך·מלכה" ל"מלך·ים"). ועל הלוח אין הקשר — בדיוק היתרון היחיד של מודל קונטקסטואלי מתבטל.
בנוסף: fastText חינם תפעולית — רץ על CPU, אופליין, מחשבים את כל אוצר הרמזים פעם אחת. גם אם טרנספורמר כבד היה מנצח בנקודה־שתיים, הוא הבחירה הלא־נכונה לדמו ציבורי תמידי. תיקו באיכות + ניצחון מוחץ בעלות.
חוקי המשחק אוסרים רמז שחולק שורש עם מילה על הלוח. בעברית השוואת מחרוזות לא מספיקה — "קסם" ו"קוסם" חולקים שורש אבל נראים שונים, ו"בבית" הוא בכלל "בית". הפתרון בנוי בשכבות: למטיזציה מבוססת DictaBERT שמקלפת תחיליות (ב/כ/ל/מ/ה/ו) ונטיות; מעליה חתימת־שורש עיצורית שמנטרלת אותיות שימוש (מ/ה/נ בתחילית, אהו״י באמצע, וסיומות) — כך "רכבת/רכב", "שומר/שמירה" וגם "פחד/מפחיד/פחדן" נתפסים כאותו שורש; ולבסוף בדיקת הכלה שתופסת הכפלות והקטנות שהשוואת שורש מפספסת — "כלבלב" ליד "כלב", "חתלתול" ליד "חתול". זו הֵאוריסטיקה דטרמיניסטית, מהירה ואופליין, שמכוּונת לפסול־ביתר ולא להחמיץ (אין מודל מודרני שמחזיר שורש עברי כשדה — בדקנו).
אוצר הרמזים הוא כ‑5,260 שמות עצם ותארים בתדירות בינונית (לא מילות תפקוד, לא זבל נדיר) — כך שכמעט כל מילה עברית מוכרת היא מועמדת לגיטימית, לא רשימה קצרה וקבועה. מילים פוגעניות מסוננות מראש מהאוצר באמצעות רשימת חסימה.
מכיוון ש‑fastText בנוי על n‑gramים של אותיות, הוא נותן וקטור הגיוני גם למילה שלא ראה מעולם — הטיה, מילה עם אות יחס, או רמז שהמשתמש הקליד. זה מה ששומר על הכיסוי בעברית בלי טבלת מילים ענקית.
וקטורים בעברית נוטים להצטופף לפי תדירות ואורך, לא רק לפי משמעות — קונוס משותף שמעוות מרחקים. אנחנו מסירים את k=3 הצירים הראשיים (all‑but‑the‑top, Mu & Viswanath) לפני ההקרנה, וזה פותח את המפה חזרה כדי שתראה פיזור סמנטי ולא פיזור־תדירות.
המפה שמתחת ללוח היא ההקרנה ל‑2D של אותו מרחב. בונים מטריצת מרחקי קוסינוס בין כל המילים והרמז, ומקרינים אותה עם MDS קלאסי (Torgerson) — מירכוז כפול של מטריצת המרחקים בריבוע, ושני הווקטורים העצמיים הגדולים. הכול ב‑numpy טהור, בלי תלות נוספת.
התוצאה היא התמונה שמסבירה הכול במבט אחד: רמז טוב נוחת במרכז המסה של המילים שלך, ורחוק מהאשכול של היריב.
המודל המלא של fastText שוקל 7.2GB — רובו מטריצת אימון שמיותרת בהסקה, ומיליוני מילים שלעולם לא נשתמש בהן. דחסנו אותו עם compress‑fasttext (גיזום אוצר־מילים + n‑gramים + fp16), ובדקנו שזה לא פוגע: על 12 לוחות, המודל הדחוס בחר בדיוק את אותו רמז ב‑12 מתוך 12, עם recovery ו‑margin זהים לחלוטין.
| וריאנט | גודל | קורלציה | אותו רמז | recovery |
|---|---|---|---|---|
| מלא | 7.2GB | 1.000 | — | 0.375 |
| ברירת־מחדל | 14MB | 0.64 | 5/12 | 0.250 |
| PQ גדול | 107MB | 0.96 | 6/12 | 0.250 |
| fp16 ✓ | 369MB | 0.9985 | 12/12 | 0.375 |
"סיכון" ב"שם קוד" הוא שני כפתורים: כמה מילים לכסות בבת אחת (m), וכמה חזק להימנע מהקלפים של האחרים (הקנסות λ). החוגה פשוט מזיזה את שניהם:
| מצב | מכסה | קנס מתנקש/יריב/ניטרלי | התנהגות |
|---|---|---|---|
| זהיר | 2 | 3.0 · 1.5 · 0.5 | רק רמזים בטוחים, מסרב יותר |
| מאוזן | 2 | 2.0 · 1.0 · 0.3 | ברירת המחדל |
| נועז | 3 | 1.5 · 0.7 · 0.2 | מכסה יותר, סובל קרבה ליריב |
בנועז המנוע גם לא קובר רמז מסוכן בתחתית הרשימה — כי זו כל הנקודה של נועז.