איך Copilot "חושב"?
כדי לנצל נכון כלי AI כמו Copilot, כדאי להבין באופן כללי כיצד הוא פועל "מאחורי הקלעים". Copilot מבוסס על מודל שפה גדול (LLM) שמיומן על כמויות עצומות של קוד ממאגרי קוד ציבוריים (ובעיקר על המודל OpenAI Codex, גרסה של GPT שיועדה להשלמת קוד). בפועל, GitHub Copilot משתמש בממשקי API של OpenAI – עבור השלמות קוד בזמן אמת הוא עושה שימוש במודל GPT-3.5 Turbo המהיר, בעוד שבמצב שיחה (Copilot Chat) הוא נעזר במודל המתקדם GPT-4 blog.quastor.org. מודל GPT-4 אמנם איטי יותר, אך "חכם" יותר ומסוגל להבין בקשות מורכבות ומפורטות יותר – ולכן מתאים לאינטראקציות של שאלות/תשובות, ניתוח קוד וכדומה.
תהליך הפקת ההצעות
Copilot מנטר באופן רציף את הקוד שאתם כותבים ואת ההקשר סביב סמן הטקסט (cursor) שלכם. בשלב הראשון, הוא אוסף מידע מהקובץ הפעיל – שורות הקוד שלפני הסמן, ההגדרות בתוך הפונקציה/מחלקה הנוכחית, וכדומהblog.quastor.org . המערכת מנסה להבין "לאן הרוח נושבת" – מה אתם מנסים לממש כעת – מתוך ההקשר הזה. בנוסף, Copilot מסוגל להתחשב גם בקבצים פתוחים אחרים במידה והם רלוונטיים. לדוגמה, אם יש לכם קובץ כותרת (Header) ב-C או ממשק ב-Java פתוח בטאב אחד, וקובץ מימוש בטאב שני, הוא עשוי לקשר בין ההכרזות בממשק לבין הקוד שאתם כותבים ולנחש את המימוש. לצורך זה Copilot מפעיל אלגוריתמים שמשווים הבדלים בין טקסט בקבצים פתוחים (כפי שצוין ע"י צוות הפיתוח, הם אף משתמשים ב-"Jacobian difference" למציאת חלקים רלוונטיים) blog.quastor.orgblog.quastor.org. בצורה כזו, ה"הנחיה" (Prompt) שהמודל רואה אינה רק השורה הנוכחית, אלא תמצית של ההקשר הרחב: החתימה של הפונקציה, הערות שכתבתם, קוד דומה בקרבת מקום, ואפילו חלקים מקבצים אחרים שיכולים לסייע.
לאחר איסוף ההקשר, Copilot שולח את המידע הזה לשרת backend ב-GitHub, ששם מתבצע "טיהור" ההנחיה לפני שליחתה למודל השפה. שלב זה כולל סינון תוכן בעייתי (כגון תכנים פוגעניים), הסרת מידע לא רלוונטי (למשל אם משום מה התווספו חלקי טקסט שאינם קשורים לתכנות), והגנה מפני "הזרקות פקודות" זדוניות שעלולות לשנות את התנהגות המודלblog.quastor.org . רק לאחר מכן ההנחיה המנוקה נשלחת למודל ה-LLM (בענן של OpenAI), והמנוע מייצר השלמה – בין אם זה כמה שורות קוד, פונקציה שלמה, או תשובה מילולית בבוט הצ'אט, בהתאם למצב השימוש.
בדיקה וסינון בצד השרת של GitHub
כעת מתרחש שלב חשוב נוסף: לפני שההצעה נשלחת בחזרה אליכם, היא עוברת בדיקה וסינון בצד השרת של GitHub. מנגנון אוטומטי בודק את הקוד שהוצע ומנסה לזהות בעיות אבטחה נפוצות או באגים אפשריים. למשל, אם מוצע קוד עם תבנית ידועה של חולשת אבטחה (כגון שימוש לא בטוח בהצפנה, SQL Injection, קריאות לא מאובטחות וכד'), Copilot עשוי לסנן או לשנות את ההצעה. למעשה, בתחילת 2023 דווח ש-GitHub שילב ב-Copilot מסנן AI ייעודי להפחתת חולשות אבטחה בהשלמות – כולל זיהוי סיסמאות גלויות, דפוסי SQL Injection ועודcircle.cloudsecurityalliance.org . בנוסף, כאן גם מתבצעת בדיקת התאמה לקוד ציבורי: אם ההצעה מכילה מקטע ארוך (150 תווים ומעלה), המערכת תשווה אותו למאגר ענק של כל הקוד הציבורי ב-GitHub, כדי לוודא שלא מדובר בהעתק מדויק של קוד קייםblog.quastor.org . אם יימצא שההצעה זהה למשל לקוד ממאגר פומבי מסוים, Copilot ימנע מלהציג אותה לכם כברירת מחדל (אלא אם ביטלתם את סינון הקוד הפומבי בהגדרות, כמוסבר לעיל) blog.quastor.orgdocs.github.com. רק אחרי כל אלו, ההצעה "הנקייה" נשלחת חזרה לעורך שלכם ומוצגת כטקסט רפאים אפור להשלמה בלחיצת Tab.
מה המשמעות עבור המשתמש?
תהליך זה מסביר מדוע לפעמים Copilot "מהסס" או לא מציע מיד תשובה – ייתכן שההקשר מורכב והוא אוסף מידע, או שהייתה הצעה שסוננה עקב חיקוי קוד מוכר. כמו כן, מאחר והמודל הסטטיסטי נבנה מלמידה על דוגמאות, הוא בעיקר "משלים תבניות" ולא בהכרח מבין באופן עמוק את מטרת הקוד. כלומר, Copilot מנחש את ההמשך הסביר לקוד שלכם על סמך דמיון לדוגמאות שראה באימון. לכן ייתכן שיופיעו הצעות שנראות הגיוניות תחבירית אך אינן נכונות לוגית. למשל, הוא עשוי לקרוא לפונקציה שלא קיימת במערכת שלכם, רק כי במקרים דומים במאגרי קוד אחרים הייתה פונקציה בשם הזה. הבנת אופן הפעולה הזה מסייעת למפתח: יש להתייחס ל-Copilot כאל כלי שמציע השערות מושכלות, אך לא כמקור אמת בלתי מעורער. חשוב לעבור על ההצעות בביקורתיות, במיוחד כשמדובר בקוד קריטי.
הקשר רחב ו-Context Window
כדאי לדעת שלמודלים יש מגבלה על כמות ההקשר שהם יכולים לקבל (Context Window). Copilot יכול "לראות" כמה מאות שורות (או אלפי טוקנים) מהקוד סביבכם. בשנים האחרונות חל שיפור, והגרסאות החדשות (במיוחד בצ'אט) תומכות בהקשר גדול יותר, אך עדיין לא כל הפרויקט טעון בזיכרון בבת אחת. לכן, אם אתם עובדים על קובץ גדול מאוד, Copilot אולי לא "יזכור" פונקציה שהגדרתם בתחילת הקובץ כשאתם כותבים בסופו. במקרים כאלה, ייתכן שתרצו להזכיר לו בהערות (comments) מידע רלוונטי, או פשוט להיות מודעים שייתכן צורך לעזור לו עם הקשר נוסף. אגב, צוות GitHub עובד על שיטות להרחיב הקשר – למשל שימוש בגישת RAG (Retrieval Augmented Generation), שבה חלקי מידע (כמו דוקומנטציה של הפרויקט, מבנה הספריות, פלט טרמינל וכד') מאוחסנים במסד נתונים חיצוני ומוצאות דינמית לפי הצורך כדי להזין למודל blog.quastor.orgblog.quastor.org. חלק מהרעיונות הללו צפויים להתממש בדורות הבאים של Copilot, ויאפשרו לכלי "להבין" את הפרויקט כולו לעומק רב יותר.
תירגול מוצע
נסו לערוך ניסוי קצר כדי לראות איך אופן הניסוח שלכם משפיע על הצעות Copilot. למשל, כתבו בפונקציה חדשה הערת TODO עמומה כמו # TODO: חשב את התוצאה והמתינו להצעה. לאחר מכן, מחקו את ההצעה ונסחו את אותה הערה בצורה מפורטת יותר, למשל: # TODO: חשב את הממוצע של רשימת מספרים, והתעלם מערכים שליליים. השוו בין ההצעות שקיבלתם בשני המקרים. תרגיל זה ידגים כיצד Copilot "חושב" וכמה הוא רגיש להקשר ולהנחיה שהמשתמש מספק – הנחיה מפורשת וממוקדת תניב בדרך כלל תוצאה מדויקת ושימושית יותר.