קופיילוט שנותן רמזים טובים משלך — בעזרת וקטורים, קצת גאומטריה, ואפס מודלי שפה ענקיים. זו הצלילה לעומק: למה זו בכלל בעיית דמיון סמנטי, איך בוחרים את הרמז, ולמה דווקא עברית הקשתה.
ב"שם קוד" רב המרגלים נותן מילה אחת ומספר, והצוות מנחש את הקלפים שלו — בלי לגעת בקלפים של היריב, בניטרליים, ובמיוחד לא במתנקש. ברגע שמפסיקים לחשוב על זה כמשחק מילים ומתחילים לחשוב עליו כקרבה במרחב, הפתרון מתבקש.
כל מילה הופכת לווקטור — נקודה במרחב של 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)שלושת הקנסות הם מדורגים: λₐ ≫ λₒ > λₙ. ככה הקופיילוט "מפחד" מהמתנקש הרבה יותר מאשר
מקלף ניטרלי. הרמז שמנצח הוא לא בהכרח הכי קרוב למילים שלך — אלא זה שמשיג את ההפרדה הנקייה ביותר
בין שלך לכל השאר.
הקנסות למעלה קוראים דמיון מוחלט. אבל מנחש אמיתי לא שואל "כמה הרמז קרוב למתנקש" — הוא בוחר מבין 25
הקלפים. לכן נוסף גם איבר בסגנון RSA (Rational Speech Acts): המנוע ממדל את המנחש כ"מאזין
ליטרלי" — softmax על הדמיון של הרמז לכל 25 מילות הלוח, כלומר התפלגות ההסתברות שינחש כל קלף.
איבר הסכנה הוא מסת ההסתברות שנוחתת על המתנקש (במשקל כפול) ועל קלפי היריב. היתרון: הוא
מודע־תחרות וחסר־יחידות — רמז הקרוב למתנקש עדיין בטוח אם מילות הקבוצה והניטרליות מושכות יותר ממסת המנחש,
ומסוכן רק אם הסכנה באמת "מנצחת" את התחרות.
זה לא היה ניחוש. ערכנו מבחן ראש־בראש: כל אנקודר שיחק רב מרגלים על אותם לוחות ואותו אוצר רמזים, ומדדנו כמה טוב מנחש עצמאי משחזר את המילים שהאנקודר התכוון אליהן (recovery), ועד כמה הרמז שומר מרחק מהמתנקש.
| אנקודר | recovery | margin (הפרדה) | סוג |
|---|---|---|---|
| Blend (fastText+Numberbatch) | 0.444 | 0.252 | וקטורים מותכים ✓ |
| 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 שמקלפת תחיליות (ב/כ/ל/מ/ה/ו) ונטיות; מעליה חתימת־שורש עיצורית שמנטרלת אותיות שימוש (מ/ה/נ בתחילית, אהו״י באמצע, וסיומות) — כך "רכבת/רכב", "שומר/שמירה" וגם "פחד/מפחיד/פחדן" נתפסים כאותו שורש; ולבסוף בדיקת הכלה שתופסת הכפלות והקטנות שהשוואת שורש מפספסת — "כלבלב" ליד "כלב", "חתלתול" ליד "חתול". זו הֵאוריסטיקה דטרמיניסטית, מהירה ואופליין, שמכוּונת לפסול־ביתר ולא להחמיץ (אין מודל מודרני שמחזיר שורש עברי כשדה — בדקנו).
אוצר הרמזים הוא כ‑4,286 מילים שנבחרו בקפידה ממאגר עברי גדול על‑ידי מודל שפה (OpenAI gpt‑5.6‑terra): שמות עצם, שמות תואר, ושמות פרטיים מוכרים (מדינות, ערים, מקומות). כל מילה נשפטה כלמה עברית שלמה, מוכרת ובת‑משחק — פעלים, קיצורים, שברי מילים וטוקנים בני שתי אותיות נפסלים; המילים עצמן אמיתיות ומדורגות‑תדירות מהמאגר (המודל בורר, לא ממציא). מילות הלוח ומילים פוגעניות (רשימת חסימה) מסוננות מראש, כך שרמז לעולם אינו מילה שעל הלוח, וכמעט כל מילה עברית מוכרת נותרת מועמדת לגיטימית — לא רשימה קצרה וקבועה.
מכיוון ש‑fastText בנוי על n‑gramים של אותיות, הוא נותן וקטור הגיוני גם למילה שלא ראה מעולם — הטיה, מילה עם אות יחס, או רמז שהמשתמש הקליד. זה מה ששומר על הכיסוי בעברית בלי טבלת מילים ענקית.
וקטורים בעברית נוטים להצטופף לפי תדירות ואורך, לא רק לפי משמעות — קונוס משותף שמעוות מרחקים. אנחנו מסירים את k=3 הצירים הראשיים (all‑but‑the‑top, Mu & Viswanath) לפני ההקרנה, וזה פותח את המפה חזרה כדי שתראה פיזור סמנטי ולא פיזור־תדירות.
וקטורים סטטיים מוגבלים בגלל מילים רב-משמעיות — "עלה" הוא צמח, מחיר, או פועל, והגאומטריה הסטטית קורסת לוקטור ממוצע מדולל. אבל גילינו שאפשר לפתור את זה ללא LLM: מזינים את מילות האשכול של הרמז **ביחד** כרצף טקסט קצר (בשיטת Bag-of-Words) לתוך מודל הקשר מקומי (כמו NeoDictaBERT). מנגנון ה-Self-Attention של הטרנספורמר מבצע התרת משמעות (WSD) דינמית במקום:
"עלה עץ פרח ירוק", הוקטור של המילה עלה מתקרב ל-עץ (דמיון 0.21 לעומת 0.09 בהקשר פיננסי)."עלה מחיר כסף חנות", הוקטור של עלה מתקרב ל-כסף (דמיון 0.27 לעומת 0.17 בהקשר בוטני).המפה שמתחת ללוח היא ההקרנה ל‑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.3 · 0.7 | רק רמזים בטוחים, מסרב יותר |
| מאוזן | 3 | 2.5 · 0.9 · 0.6 | ברירת המחדל |
| שובב | 4 | 1.8 · 0.7 · 0.4 | מכסה יותר, סובל קרבה ליריב |
בשובב המנוע גם לא קובר רמז מסוכן בתחתית הרשימה — כי זו כל הנקודה של שובב.
ה"מכסה" הוא רק תקרה — המספר בפועל נגזר מגיזום כיסוי (keep): מילת קבוצה נספרת רק אם הדמיון שלה ≥ keep · הדמיון של המילה החזקה ביותר, כך שהמנוע לא "מנפח" מספר. את הסף כיילנו מול מנחש‑LLM כדי שהמספר המוצהר יתאים למה שמנחש אמיתי משחזר (over‑claim ≈ 0), ורמז של מילה בודדת הוא מוצא אחרון. הרשימה הנגללת מגוּונת ב‑MMR כדי שצמד קלפים אחד לא ימלא את כל האפשרויות ברמזים כמעט‑זהים.