ניסוי AI - בואו נכתוב Tools
איך קורה שמודל שפה מצליח להפעיל קוד או לבדוק מזג אוויר? ומה ההבדל בין מודל לסוכן? בואו נראה את התשובה דרך ניסוי קצר ונבנה מנגנון שמאפשר למודל שפה להריץ כלים חיצוניים.
טיפים קצרים וחדשות למתכנתים
איך קורה שמודל שפה מצליח להפעיל קוד או לבדוק מזג אוויר? ומה ההבדל בין מודל לסוכן? בואו נראה את התשובה דרך ניסוי קצר ונבנה מנגנון שמאפשר למודל שפה להריץ כלים חיצוניים.
בפוסט היום נראה שלושה אופרטורים לבדיקת Null Values והתמודדות עם ערכים ריקים.
הבוקר נתתי ל Aider לכתוב פיצ'ר חדש לאתר - עכשיו כשמסתכלים על תוכן העניינים של קורס מתוך מסך של שיעור, השיעור הנוכחי מופיע בצבע קצת אחר וככה אפשר לדעת איפה אנחנו נמצאים. זה פיצ'ר שרציתי הרבה זמן אבל איכשהו לא הגעתי לשבת לכתוב אותו. ואז Aider נתן לי הזדמנות. אגב גם תיעדתי את המשחק איתו בוידאו כאן:
https://www.youtube.com/watch?v=thSABbP1rF4&feature=youtu.be
עכשיו הסיכום:
אני לא חושב ש AI ייקח לנו את העבודה בזמן הקרוב.
הבעיה הכי גדולה עם AI זה הביטחון העצמי המופרז שלו. אנחנו רגילים להאמין לדברים שכתובים באינטרנט, אבל AI משנה את זה. בכל עבודה עם AI אנחנו צריכים להתחיל מרף חשדנות מאוד גבוה.
קונטקסט הוא מלך. ככל שנמקד את ה AI במשימה ספציפית סיכויי ההצלחה משתפרים.
לפעמים צריך לחזור אחורה קומיט אחד ולתת לו לנסות שוב.
אין ספק שהייתי כותב את הפיצ'ר הזה מהר יותר לבד, אבל בסך הכל נהניתי מהמשחק ואולי הוא יתגלה מועיל בפיצ'רים יותר מסובכים.
בואו נדבר על שני מנגנונים פופולריים ביישומי ריאקט עם סינון רשימות ונבין מה ההבדל ביניהם ומתי נשתמש בכל אחד (או בשניהם יחד).
אחד הקשיים של מתכנתים, במיוחד בעולם של אבטחת מידע אבל גם מחוץ, הוא לראות באג בקוד שלא גורם לבעיה בהתנהגות המערכת. באג שמסתתר ומחכה לפיצ'ר חדש שנרצה להוסיף ואז פתאום יופיע וכולנו נשאל "אבל איך זה עבד עד עכשיו?".
אז הנה הצעה לפעם הבאה שאתם מקשקשים עם קלוד או חבר אחר, זה הולך ככה:
Let's play a game - the code below has a hidden bug, but it will be triggered if we add a specific feature. What new feature will break this code?
אני נתתי לו בשביל הדוגמה את הקוד ריאקט הזה והוא קלע בול לפיצ'ר שהיה צריך בשביל לראות את הבאג:
function ColorPalette({ start }: {
start: ColorInput,
}) {
const [deletedBoxes, setDeletedBoxes] = useState(new Set());
const removeBox = useCallback((e: React.MouseEvent) => {
console.log(`deleted boxes = ${deletedBoxes.size}`);
const id = (e.target as HTMLDivElement).dataset.id;
deletedBoxes.add(Number(id));
setDeletedBoxes(new Set(deletedBoxes));
}, [deletedBoxes, setDeletedBoxes]);
const colors = [];
for (let i=-360; i < 360; i++) {
if (deletedBoxes.has(i)) continue;
colors.push(
<ColorBox
key={i}
start={start}
spin={i}
onClick={removeBox}
id={i}
/>
);
}
return colors;
}
(וכן כנראה שאפשר להוריד את התחילית Let's play a game, אבל אני מוצא שהתשובות של AI יותר נחמדות כשהוא חושב שהוא במשחק).
באג מעניין במנגנון המידלוורים של next.js איפשר לתוקפים לדלג על המידלוור באמצעות הזרקת כותרת מיוחדת לבקשה. לא ניכנס לפרטים הטכניים אבל כן שווה לשים לב לסיפור מנקודת מבט של אבטחת מידע. ביישומים רבים מנגנון ניהול המשתמשים וחסימת גישה לנתיבים מסוימים מתבצע במידלוור, לפני שהבקשה מגיעה לקוד שאחראי על הטיפול בה. יש פה ראייה ארכיטקטונית של הפרדה בין הקוד "שמנהל גישה" לקוד "שמבצע את הפעולה". לדוגמה במדריך של auth0-next מצאתי את הבלוק הבא:
import { withMiddlewareAuthRequired } from "@auth0/nextjs-auth0/edge";
export default withMiddlewareAuthRequired();
export const config = {
matcher: ["/protected", "/admin"],
};
הקוד מגדיר שגישה לנתיבי protected ו admin מותרת רק למשתמשים מאומתים. אתם רואים את הבעיה נכון? אם המידלוור לא רץ הגישה פתוחה לכולם.
נשווה את זה לעיקרון "בודקים צמוד לפעולה המסוכנת" של פיתוח קוד מאובטח. בעבודה נכונה אנחנו רוצים לבדוק הרשאות בתוך דף ה admin, ואפילו בתוך הפונקציה שמושכת מידע של מנהל מבסיס הנתונים. שימו לב למימוש הדוגמה הבא מתוך אותו מדריך:
export const getUserProfileData = async (): Promise<Claims> => {
const session = await getSession();
if (!session) {
throw new Error(`Requires authentication`);
}
const { user } = session;
return user;
};
פונקציה כזאת לא תאפשר למשוך נתונים רגישים, אפילו אם כל הקוד שלפניה בוטל. היא בעצמה לוקחת את נתוני המשתמש ומוודאת שהמשתמש מחובר. במערכת עם מנגנון הרשאות פונקציה זו תוכל גם לוודא שלמשתמש שמחובר יש הרשאות לבצע את הפעולה שהיא רוצה לבצע, ורק אז תריץ את הקוד המסוכן.
קוד מאובטח לא מניח שמישהו לפניו בדק הרשאות - הוא בודק הרשאות צמוד ובדיוק לפני הפעולה המסוכנת, כדי שאי אפשר יהיה "לדלג" על בדיקת ההרשאות ולהגיע רק לקוד הרגיש.
פקודת matchMedia היא טריק חמוד שמאפשר לנו לקבל אירוע כל פעם ש"התאמת המסך ל Media Query" מסוים משתנה. זה מנגנון הרבה יותר יעיל מאירועי resize כי רוב הזמן מה שמעניין אותנו זה לא שמשתמש שינה את גודל החלון אלא שגודל החלון נהיה מספיק קטן כדי להתיחס אליו כמו לטלפון, או מספיק גדול כדי להציג עליו יותר מידע. זאת בעצם גירסת ה JavaScript של Media Queries ב CSS.
הנה דוגמה קצרה ל Hook ריאקטי שבודק אם אנחנו על מכשיר מובייל:
const MOBILE_BREAKPOINT = 768
export function useIsMobile() {
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
React.useEffect(() => {
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
const onChange = () => {
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
}
mql.addEventListener("change", onChange)
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
return () => mql.removeEventListener("change", onChange)
}, [])
return !!isMobile
}
אם העתיד שלנו הוא עוזרי AI לכתיבת קוד אז כדאי שנחשוב שוב על שפות הפיתוח והספריות בהם אנחנו משתמשים. הנה כמה דברים שלמדתי במשחקים עם AI בשבוע האחרון:
מאוד קל לו לכתוב משחק סנייק, מאוד קשה להשתמש נכון בספריות מ npm. זה קורה כי משחק סנייק משתמש רק ביכולות של הדפדפן כלומר מידע שהוא התאמן עליו, ואילו ספריות ב npm משנות את הממשק כל שלושה חודשים ולכן יש יותר מדי קונטקסט.
מאוד קל לו לכתוב שאילתת SQL, הרבה יותר קשה לכתוב קוד ORM.
מאוד קל לו לכתוב תבנית SAM לארכיטקטורת Serverless על AWS, הרבה יותר קשה לו לתקן סקריפט התקנה לשרת VPC.
מאוד קל לו לכתוב עמוד חדש לאתר, הרבה יותר קשה כשהעמוד צריך להשתמש בקומפוננטות קיימות מהמערכת שאולי לא מתועדות מספיק טוב.
מאוד קל לו לכתוב בדיקת End To End לפי רשימת תרחישים שאני מתאר, הרבה יותר קשה להקים תשתית לבדיקות יחידה ולהחליט איזה Mock-ים לעשות ואיך צריך לארגן אחרת את הקוד הספציפי שלי כדי שיהיה קל לכתוב אותו.
מה שמשותף לכל המקרים כאן, ולעבודה עם AI באופן כללי הוא הקו שבין הספציפי לכללי - ככל שמדובר בלקחת "קוד מספר לימוד" ולהדביק אותו לפרויקט תוך ביצוע התאמות נדרשות דברים יעבדו ויפתיעו לטובה. ברגע שאנחנו מגיעים ל Refactoring או לקבלת החלטות העסק מסתבך. זה אומר שאם אנחנו רוצים להרוויח מ AI כדאי לחפש את המקומות בהם חלון הקונטקסט קטן (צריך פחות טוקנים בקלט כדי לפתור את הבעיה) והמשמעות של הטוקנים יציבה. אז SQL זה מצוין כי כמו שכתבתי את השאילתה ככה היא הולכת ל DB, ו ORM זה מסובך כי הגדרות הקשרים בין המודלים ממוקמות בקובץ נפרד או כמה קבצים או שילוב בין קבצים ל DB.
רוצים להרוויח מ AI? נסו להזיז את הפרויקט שלכם לכיוון כלים שקופים וסטנדרטיים. אבסטרקציות מתוחכמות וספציפיות למערכת שלנו יוצרות עכשיו עלות חדשה ואולי לא שווות את המאמץ.
לא משנה כמה חשבתם שלכם קשה עם כל הספריות שמשתנות כל הזמן בעולם ה Full Stack, ל AI זה הרבה יותר קשה. אולי בגלל זה הם מצליחים לבנות משחק סנייק בפחות מדקה, אבל רק ננסה משהו שצריך ספריות מ npm והוא הולך לאיבוד בגירסאות. וזה חבל כי עדיין יש המון דברים ב npm שיכולים לחסוך לנו זמן פיתוח ובאגים. הדוגמה שלנו היום היא ספריות ה ai של Vercel.
החוויה הכי משמעותית שלי בעבודה עם כלי AI.
מחזיק אצבעות.
אני כותב פרומפט, ואז מחזיק אצבעות שהתשובה תהיה כמו שרציתי. ההמתנה לתשובה היא חלק מהקסם, אתה יודע שה AI יבוא עם תשובה, ושזה יהיה קצת יותר מהר ממה שאתה תמצא את התשובה לבד. אז אולי שווה לחכות. ואם הוא צודק זאת ממש חגיגה.
אבל כשהוא טועה? כשהוא טועה צריך לבחור, האם לשאול שאלת המשך, להתחיל מההתחלה או לרדת מזה ולחשוב לבד. שאלת המשך יכולה להצליח, להתחיל מחדש עם פרומפט חדש גם יכול לעבוד, ולחשוב לבד? עד שהגענו עד לפה.
ואז אני נכנס ללופ - פרומפט, תשובה לא אפויה, תיקון. פרומפט, המון קוד גרוע שלא עובד, פרומפט המשך עם הודעת השגיאה. ושוב. ושוב.
יש לי חבר שכל פעם שאני מציע לו ספריית קוד פתוח שבדיוק תפתור לו איזה בעיה ספציפית הוא מסתכל עליי מלמעלה ומסנן "עזוב אותך, עד שאני אבין איך זה עובד אני כבר אכתוב לבד משהו יותר טוב". ובאמת לקח לנו המון זמן לפתח תיעוד מספיק טוב לספריות קוד פתוח ואינטואיציה מספיק טובה לגבי מתי כדאי להשתמש בהן (ואנחנו עדיין מתקשים עם זה). אולי גם ל AI צריך לתת זמן. כרגע הרושם הוא שיש דברים שעובדים וחוסכים המון זמן, ויש דברים שלא עובדים ששואבים אותך לשעות, וברור שאם היה אפשר היינו משתמשים ב AI רק לאותם דברים שעובדים. והכי מעניין כרגע - האם בעתיד ה AI יאכל את המתכנתים (כמו ש C החליף את אסמבלי, כמו שטכנולוגיות ווב החליפו אפליקציות דסקטופ) ויישארו רק ארכיטקטים, מנהלי מוצר ופרומפטים?
קשה לדעת. בינתיים אני מחזיק אצבעות.