ar
Feedback
ToCode

ToCode

الذهاب إلى القناة على Telegram

טיפים קצרים למתכנתים מאת ינון פרק

إظهار المزيد
1 419
المشتركون
لا توجد بيانات24 ساعات
لا توجد بيانات7 أيام
-430 أيام
أرشيف المشاركات
ToCode
1 419
אז כבר לא צריך CSRF Token? פריימוורקס לפיתוח ווב באופן מסורתי הוסיפו לטפסים שדה נסתר מיוחד כדי לוודא שהטופס הוגש רק מהאתר בו הטופס נכתב. לדוגמה טופס שיוצר בדוטנט הכיל את השדה:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">
טופס שיוצר בריילס הכיל את השדה:
<input type="hidden" name="authenticity_token" value="Y1OeREmhWaEzt4AVJJFzquSrJjHvZ-3rkxMde4IOzLznve33Dx3lYkXpkVkChj-VLIKUQK-ff_6hG9jPs9DTFA" autocomplete="off" />
וכך גם ב Laravel ופריימוורקס דומים. הסיבה היא שפרטי הגישה לאתר שמורים ב Cookie בדפדפן של הגולש והדפדפן בעבר שלח את כל ה Cookies בכל כניסה לאתר. לכן אם לדוגמה יש לכם באתר של הבנק טופס להעברת כסף לחשבון אחר מישהו באתר אחר היה יכול להעתיק את כל הטופס ולשנות את הטקסטים כדי שיראה כמו טופס להשארת הודעה. אתם חושבים שאתם משאירים הודעה באתר אחד אבל בפועל אתם מגישים טופס שפונה לבצע פעולה באתר אחר. אתר הבנק לא יודע שמילאתם את הטופס באתר זדוני ומבצע את פעולת ההעברה. מנגנון CSRF Protection נועד להגן על אתר הבנק ועל החשבון שלכם מפני מתקפות מסוג זה. הטוקן הנסתר מוגרל מחדש כל פעם שאתם נכנסים לדף הטופס באתר של הבנק, וכך מי שינסה להעתיק את הטופס לעולם לא יוכל להעתיק את הטוקן. כשמגישים את הטופס בלי הטוקן הנכון אתר הבנק יכול לזהות שהטופס הגיע מאתר אחר ולהתעלם מהבקשה. החל מכרום גירסה 80 ופיירפוקס גירסה 79 (שינוי שקרה כבר ב 2020) ברירת המחדל של דפדפנים השתנתה. היום ברירת המחדל היא לא לשלוח Cookies בבקשות POST ולכן כל עוד לא ביטלתם את מנגנון ההגנה הזה עם הגדרת SameSite שונה לעוגיות שלכם אתם לכאורה מוגנים ממתקפות CSRF כבר ברמת הדפדפן. למה לכאורה? יש שניים וחצי מצבים עם פוטנציאל בעייתי: 1. אם הטופס שלכם משתמש בבקשה מסוג GET בטעות, העוגיות עדיין יישלחו גם מאתרים אחרים שמגישים את הטופס. 2. אם תוקף השתלט על סאבדומיין שלכם ויצר שם את הטופס המזויף (גם בברירת המחדל החדשה עוגיות יישלחו מסאב דומיין). 3. אם שדרוג עתידי של הדפדפן יגרום לבאג שישלח בטעות את העוגיות גם מטופס מזויף מאתר אחר. לכן ההמלצה היום היא להישאר עם שני המנגנונים מופעלים. לא לוותר על הגנת ה CSRF המובנית בפריימוורק ובמקביל לא לבטל את הגנת ה SameSite המובנית בדפדפן.

ToCode
1 419
למה קשה ללמוד תכנות מ AI הייתי רוצה להיות מסוגל להגיד "הי לאבבל תבנה לי אפליקציה X". אחרי זה לפתוח את הקוד של האפליקציה, לפענח מה לאבבל עשה וככה ללמוד מה צריך לעשות. יש עם זה עדיין כמה בעיות: 1. טמפלייט ההתחלה של לאבבל (או כל AI Builder) עבר אופטימיזציה להיות בסיס טוב לסוכן קידוד מבוסס AI. זה לא תמיד בסיס טוב ללמידה. הטמפלייט מכיל המון קונספטים שכל אחד מהם דורש עבודת למידה. 2. ללמוד מ AI זה ללמוד את מה שעובד לא את מה שנכון. אם AI כתב באותה תוכנית את אותו מנגנון 3 פעמים ורק אחת מהפעמים עובדת (שני המימושים האחרים לא עובדים אבל במקרה גם לא שוברים כלום) אז מי שינסה ללמוד מה AI עלול ללמוד שיטה שבורה. 3. ללמוד מ AI זה ללמוד משהו שמהר מאוד לא יהיה העבודה שלנו. אם AI יודע לכתוב את זה לבן אדם יש דברים יותר טובים לעשות. איך בכל זאת אני חושב שלימוד מ AI יכול להיות אפקטיבי? מתחילים עם "הי לאבבל תבנה לי אפליקציה X", ואז נכנסים לקוד במטרה לשכתב ולשפר אותו. נרצה להבין: איזה מנגנונים ה AI יצר בקוד, עבור כל מנגנון מה המטרה שלו, למה הוא שם, האם אפשר לכתוב אותו במקום אחר או בדרך אחרת, מה היתרונות והחסרונות של כל מימוש. לדוגמה נניח ש AI כתב לי פונקציה כזאת בתוך קומפוננטת ריאקט:
const formatTime = (seconds: number) => {
  const mins = Math.floor(seconds / 60);
  const secs = Math.floor(seconds % 60);
  return \${mins}:${secs.toString().padStart(2, '0')}\;
};
זאת יכולה להיות הזדמנות למידה מצוינת. אני רואה את הקוד, עוצר ומחפש ללמוד: 1. מה זה בכלל פונקציה? האם יש עוד דרכים להגדיר פונקציה בטייפסקריפט? למה הפונקציה מוגדרת דווקא במקום בו היא מוגדרת (בתוך הקומפוננטה)? האם אני יכול להגדיר אותה במקום אחר? מה היתרונות והחסרונות של הגדרת הפונקציה במקום אחר? 2. מה זה אומר שהפונקציה מקבל פרמטר יחיד מסוג מספר? מה אם אנסה להפעיל אותה עם ערך שאינו מספר? מתי זה יישבר? איך זה יישבר? 3. מה זה Math. ? יש עוד דברים שאפשר לכתוב אחריו חוץ מ floor? 4. מה משמעות השורה האחרונה בפונקציה? האם יש דרכים נוספות לכתוב אותה? מה זה אומר שכותבים נקודה ו toString אחרי משתנה? יש דברים נוספים שאפשר לכתוב במקום toString באותו הקשר? לימוד תכנות מספר הוא לימוד דרך כתיבה. אנחנו קוראים מה הדרך הנכונה לכתוב קוד ומנסים לחזור עליה עבור המקרה שלנו בצורה שתעבוד. לימוד תכנות מ AI הוא לימוד דרך קריאה. אנחנו קוראים את המימוש של ה AI ודרכו מגלים מה עלינו ללמוד כדי להתקדם.

ToCode
1 419
תוכניות לשנה החדשה ראש השנה הוא תמיד הזדמנות מצוינת לעצור לחשוב, להתבונן ולתכנן. אלה הנקודות המרכזיות שאני מתכנן לקדם בשנה הקרובה: לימוד תכנות מהפכת ה AI שאנחנו נמצאים בתוכה מכריחה אותנו לחשוב מחדש על עולם לימודי התכנות. ה AI גם מקל על לימודי תכנות וגם מאוד מקשה עליהם כשהקושי העיקרי הוא המוטיבציה. בפרויקט לימודי אנחנו בונים משהו שמישהו כבר בנה (במקום אחר, בזמן אחר). הפרויקט הלימודי הוא לא מסובך במיוחד כי הוא נועד לתרגל את הדברים שאנחנו לומדים לפני שנוכל להגיע לעבוד על אתגרים חדשים בעולם האמיתי. זה נותן לבינה מלאכותית ייתרון לא הוגן על מתכנתים אנושיים - הבינה המלאכותית מסוגלת לכתוב כל פרויקט לימודי יותר טוב מכל סטודנט. איך אתה מוצא את המוטיבציה להתאמץ ולכתוב פרויקט כשבלחיצת כפתור אתה יכול לקבל את הפיתרון? איך אתה משכנע את עצמך שאתה מתרגל מיומנות חשובה בתנאים האלה? מה שאני רואה סביבי זה שהמוטיבציה משתנה. מתכנתים לעתיד יודעים להשתמש בכלי פיתוח מבוססי AI ויודעים לייצר לעצמם פרויקטים קטנים ונקודת ההתחלה שלהם היא לכאורה מאוד מתקדמת. ואז מגיע הרגע שה AI נתקע ואנחנו תקועים עם הקוד. אותה נקודה היא נקודת ההתחלה של הלמידה, היא הנקודה שבה אנשים מתחילים לנסות להבין מה קרה פה, מה ה AI כתב ואיך אני יכול להתקדם עם זה. לימוד תכנות בעידן ה AI יהיה חייב לקבל את כלי הבניה מבוססי AI וללמד תכנות מתוך התוצרים שלהם. להשתמש ב Lovable או Base44 בתור נקודת התחלה לחוויה הלימודית. אני לא בטוח עדיין איך לעשות את זה, אבל זה יצטרך להיות המבנה של קורסי תכנות בשנים הקרובות. אני מקווה השנה כבר להרים קורס ראשון בסגנון זה. לימוד AI מהפכת ה AI מכריחה אותנו גם ללמוד שפה חדשה - שפת ה AI. והשפה הזאת דורשת תרגול. לדבר עם מכונה שמתנהגת כמו בן אדם יכול להיות מבלבל ולשלב מכונה כזאת בקוד כולל אינסוף אתגרים חדשים. הרבה רעש היום בעולם ה AI מגיע מחברות שמנסות לתקן או להקל על האתגרים והרבה מהבלבול של מתכנתים מגיע מלראות מוצר בלי להבין עד הסוף את האתגר שאותו מוצר מנסה לפתור. פרויקט "מדברים AI" שהתחלתי ואני מתכנן להמשיך מגיע מתוך ההבנה שקשה ללמוד AI רק דרך וידאו. שיש פה באמת שיטת עבודה חדשה ותפיסת עולם חדשה, ולימוד אפקטיבי שלה דורש דיאלוג והשקעה לאורך זמן. בקבוצת מדברים AI אנחנו נפגשים פעם בשבוע בזום בימי חמישי בבוקר כל פעם לראות נושא אחר שקשור ל AI ולפעמים גם לעבור פעם נוספת על נושאים שכבר ראינו. המטרה היא לדבר, לתרגל ולהתרגל לכלי החדש הזה שילווה אותנו בשנים הקרובות ואולי יותר. השנה התחלתי גם להעביר קורסי AI למפתחים בחברות תוכנה ולעזור לצוותי פיתוח להטמיע עבודה עם AI עבור פיתוח. הדגש הוא על איך לקבל האצה משמעותית בקצב הפיתוח בלי להתפשר על איכות המוצר. הסיפור שם הוא לא איזה כפתור בקופיילוט עושה מה או איך כותבים קובץ הוראות אלא מה כדאי לכתוב בקובץ הוראות כדי לקבל את התוצאות הטובות ביותר ואיך בכלל מודדים את התוצאות של AI ואיזה מבנה פרויקט צריך שיהיה לי כדי ש AI יוכל לתת את הערך הטוב ביותר לצוות הפיתוח. הפרויקט הזה מרתק, כל צוות מגיע עם סיפור משלו ואתגרים משלו. ככל שיותר חברות ישלבו AI בצורה מקצועית בתהליך הפיתוח אני מאמין ששנה הבאה אמשיך לראות עשייה מסוג זה. פה גם המקום להזכיר שאם אתם כבר עובדים עם קופיילוט או קרסר או כלי AI אחרים בפיתוח ורוצים עזרה לקבל מהם תוצאות טובות יותר דברו איתי - יש עולם שלם של טכניקות שאפשר ורצוי להטמיע. השנה האחרונה היתה כמו רכבת הרים טכנולוגית. עושה רושם שאנחנו נכנסים להתייצבות מסוימת מבחינת הכלים והיכולות שלהם. עכשיו הזמן לעבוד ולבנות ערך סביב אותן יכולות חדשות. שנה טובה לכולם

ToCode
1 419
לא שוב, קלוד אני מודה אני אשם. אני נתתי לקלוד לכתוב את הקוד הזה. אני לא קראתי אותו מספיק. אני לא לקחתי ברצינות את ה include שהוא כתב שם. אני חשבתי שזה חמוד שקלוד הצליח למשוך את כל הנתונים בשאילתה אחת. זה מה שהוא כתב שם:
@lessons = @course.lessons
          .includes(:activities, :lesson_users, activities: :activity_users)
          .with_progress_data(current_user)
          .order(:order)
קצר, קסום ומהר מאוד גומר את הזיכרון של המכונה. רק בגלל שזה עובד לא אומר שצריך להשאיר קוד במערכת. ורק בגלל שקלוד כתב קוד לא אומר שהקוד הזה נכון. גם אם קלוד יודע הרבה דברים שאנחנו לא יודעים, לקבל החלטות זה עדיין מחוץ לליגה שלו.

ToCode
1 419
עם או בלי היסטוריה כותבי ספריות סוכנים צריכים להחליט מה עושים עם היסטוריית הודעות, איך מנהלים אותה ואיך שומרים אותה. אנחנו חייבים להכיר את ההתנהגות הזאת ולשים לב להתאים את הקוד שאנחנו כותבים לכל מקרה. תכף דוגמה לבאג אבל קודם שתי הגישות. קוד ראשון מ OpenAI Agents SDK שולח שאלה לסוכן:
from agents import Agent, Runner

agent = Agent(name="Assistant", instructions="You are a helpful assistant")

result = Runner.run_sync(agent, "Write a haiku about recursion in programming.")
print(result.final_output)
השאלה הבאה שתישלח לאותו סוכן לא תכיל את היסטוריית ההודעות, לא את בקשת ההייקו ולא את ההייקו שנוצר. כל הפעלה של Runner.run היא עצמאית. בשביל לשמור את היסטוריית ההודעות יש להם מבנה אחר שנקרא Session שצריך ליצור בנפרד. והנה דוגמה שניה מ RubyLLM:
chat = RubyLLM.chat
chat.ask "What's the best way to learn Ruby?"
chat.ask "Send me some resources"
פה כל היסטוריית ההודעות נשמרת בתוך אוביקט ה chat אוטומטית ונשלחת למודל עם כל שאלה חדשה. כך המודל יכול לענות על השאלה השניה. ואיך זה נראה כשמתבלבלים? הנה באג שמצאתי היום:
chat = TracedChat.new(span_name: "add_token_translations", model: 'gpt-5-mini')

long_text.lines.each_slice(12) do |block|
  chat.with_instructions(instructions).add_message role: :user, content: block.join

  response = chat.complete
  data["result"] += response.content.strip + "\n\n"
  save!
end
הקוד לוקח טקסט ארוך, שובר אותו לבלוקים של 12 שורות ושולח כל בלוק ל AI. החלוקה לבלוקים עוזרת לקבל תוצאות טובות יותר מה AI, אבל שימו לב לטעות - אוביקט chat נוצר לפני הלולאה. לכן כל פניה עבור בלוק מכילה גם את כל ההודעות הקודמות (כל הבלוקים הקודמים והתוצאות שלהם). התוצאה היא ירידה באיכות התוצאות ככל שהטקסט מתארך. מרגע שראינו את זה התיקון פשוט - צריך רק להעביר את יצירת ה chat לתוך הלולאה:
long_text.lines.each_slice(12) do |block|
  chat = TracedChat.new(span_name: "add_token_translations", model: 'gpt-5-mini')
  chat.with_instructions(instructions).add_message role: :user, content: block.join

  response = chat.complete
  data["result"] += response.content.strip + "\n\n"
  save!
end
האתגר בעבודה עם LLM-ים הוא לשים לב שבכלל יש בעיה. בגלל זה חשוב תמיד לעקוב אחרי הלוגים ולוודא שהשיחות שלכם עם ה AI נראות כמו שאתם מצפים.

ToCode
1 419
מצב לא חוקי מצב לא חוקי במערכת הוא מצב שהמערכת "תקועה". הדרך היחידה החוצה היא לנקות את המצב הלא חוקי - למשל על ידי מחיקת הקבצים, ניקוי השורה הבעייתית מבסיס הנתונים, ניקוי עוגיות, או כיבוי המחשב. כל מי שעבד על מערכת מחשב נתקל מתישהו בתוכנה שנקלעה למצב לא חוקי למרות כל המאמץ שלנו המפתחים שזה לא יקרה. בפיתוח מערכת שווה לשים לב לשני תהליכים חשובים שצריך לבצע במקביל: 1. עלינו למנוע ממשתמשים להכניס את המערכת למצב לא חוקי. 2. עלינו לצמצם את המצבים הלא חוקיים של המערכות שאנחנו בונים. הראשון קל יותר, השני חשוב ונכון יותר. למרות הפיתוח, בהינתן שזיהיתם מצב לא חוקי של המערכת שלכם תמיד העדיפו לשלב פיתרונות משני הסוגים ובכל מקרה היו מאוד זהירים כשמוותרים על החלק השני בפיתרון. "אני רק אוסיף פה וולידציה ב UI" אולי ישמח את אנשי הפרודקט. מפתחים טובים ידאגו להוסיף גם וולידציה בצד שרת ובבסיס הנתונים.

ToCode
1 419
מה שלא היה באסיפת הורים הייתי באסיפת הורים בבית ספר השבוע. לא יודע איך המצב אצלכם אבל על כל השאלות האלה לא דיברו בכלל: 1. מה המטרה של בית הספר? 2. למה התלמידים הולכים לשם? איזה תהליכים לימודיים, חינוכיים ומחשבתיים הם יעברו השנה? 3. איזה מיומנויות חדשות התלמידים יקבלו השנה? 4. מה הרמה של התלמידים היום בכיתה? מה הם יודעים? מה מעניין אותם? מה הם רוצים לדעת? מערכת חינוכית היא מערכת שמעבירה אנשים תהליך. מערכת חינוכית צריכה לענות מתוך שינה על שלוש השאלות: איפה אנחנו עכשיו, לאן אנחנו רוצים להגיע, איך נראה המסלול. אני יודע לענות על השאלות האלה לכל קורס פה באתר ולכל קורס שאי פעם לימדתי. בלי הבנה ברורה של נקודת המוצא, היעד והמסלול קשה לראות את הערך שאותה חוויה לימודית מספקת.

ToCode
1 419
שי חלוד מתקפת שרשרת האספקה האחרונה ממשיכה להפיל קורבנות ולגנוב מפתחות גישה של מפתחים ברחבי העולם. חמש עשרה שנים אחרי יצירתו אנחנו עדיין לא בטוחים איך לחשוב על npm והחבילות שמגיעות ממנו. בגלל הכמות העצומה של חבילות ותלויות של כל חבילה ומבנה האקוסיסטם כמעט בלתי אפשרי לעבור על הקוד של כל חבילה שרצה אצלנו על המחשב. במקביל התוכניות האלה מקבלות גישה למכונה שלנו כאילו היו קבצי exe שהורדנו מהרשת. אנחנו מקווים שמישהו יצעק ויוריד מהרשת חבילות זדוניות לפני שנגיע להתקין אותן למרות שאנחנו רואים שוב ושוב שזה לא קורה. אותי הסיפור החזיר להרצאה האחרונה של DHH ב RailsWorld. הקיטור המרכזי שלו שם נגד הצעירים היום היה שספריות קוד פתוח מודרניות מנסות לפתור בעיה אחת קטנה ותמיד בונות על זה שבעולם האמיתי נשלב אותן עם הרבה ספריות נוספות. הניגוד היה כמובן ריילס שמנסה להשתלט על העולם ולפתור את כל הבעיות של פיתוח ווב. ומצד שני אי אפשר בכלל להשוות את הפופולריות של npm מול rubygems. לא מפתיע ששחקנים זדוניים לא מנסים להשתלט על ריילס במתקפות נגד שרשרת האספקה באותה עוצמה וכמות כמו שתוקפים את npm. גם אליקסיר, php, קלוז'ר וכלים לא פופולריים רבים נוספים "נהנים" מהיותם מטרה פחות מלהיבה. קצת כמו ש Desktop Linux די חסין לוירוסים, פשוט בגלל שהוא לא מטרה מספיק מלהיבה. לקחים מעשיים מהסיפור? כמו במקרים דומים כדאי לשים לב ל Best Practices של פיתוח מאובטח: 1. לא להתקין גירסאות חדשות של ספריות חיצוניות מיד כשעולות לאוויר. 2. להוריד הרשאה על מפתחות גישה, לא לערבב בין מפתחות גישה של פיתוח ושל פרודקשן. 3. להפריד בין רכיבים במערכת ובין מערכות שונות, כולל משתמשים שונים לכל מערכת. 4. לנטר בקשות שיוצאות מהמחשב שלכם (כן גם ממחשב הפיתוח, כמובן שמסביבת סטייג'ינג ובמיוחד ממחשבי הפרודקשן). 5. לתחזק פרוטוקול החלפת מפתחות למקרה שסיסמה או מפתח דולפים. לדעת איפה ומה צריך לשנות בשביל להחליף מפתח שדלף. לשמור גיבויים רחוק במקום שאי אפשר להתחבר אליו בצורה אוטומטית מהמחשב שלכם. 6. להתקין פחות ספריות JavaScript. הרבה דברים אפשר לפתור היום לבד או עם מימוש קטן של AI.

ToCode
1 419
תקציר דוגמאות הוובינר מחר הי חברים מה קורה? השבוע במפגש של מדברים AI אני אציג את הספריה OpenAI Agents ואראה איך להתקין אותה, מה הקשר שלה לספריות סוכנים מתחרות או מקבילות ומה המנגנונים והעקרונות המרכזיים של כתיבת סוכנים. אלה 5 דוגמאות שאני מתכנן להציג. הסוכן הראשון שלי סוכן הוא בסך הכל תוכנית רגילה שחלק מהעבודה שלה נעשה באמצעות מודל שפה גדול. דוגמה ראשונה עם OpenAI Agents היא התוכנית:
from agents import Agent, Runner

agent = Agent(name="Assistant", instructions="You are a helpful assistant")

result = Runner.run_sync(agent, "Write a haiku about recursion in programming.")
print(result.final_output)
בשביל להריץ את התוכנית יש להתקין את הספריה עם:
pip install openai-agents
ולהגדיר משתנה סביבה בשם OPENAI_API_KEY שמחזיק את מפתח ה API שלכם מ openai. התוכנית בדוגמה משתמשת במודל שפה דרך API כדי לכתוב שיר הייקו. כל פעם שמפעילים אותה מקבלים שיר קצת אחר על אותו נושא. גיוון סוכנים עם בדיחות אבא דוגמה שניה היא בחירת המודל. כל מודל נותן תשובות אחרות והרבה פעמים מודלים מסוימים יותר מתאימים לענות על שאלות מסוימות מאחרים. אין "מודל הכי טוב" יש מודל שמתאים בצורה הכי טובה לפרומפט שכתבתי ולמשימה שאני צריך לבצע. עם openai agents יש לי שתי אפשרויות לבחור מודל. אופציה ראשונה אם אני רוצה להישאר בעולם של OpenAI אפשר להעביר את המפתח model לבנאי של Agents לדוגמה:
agent = Agent(
    name="Assistant",
    instructions="You are a mighty creator of dad jokes",
    model="gpt-5-mini",
)
אופציה שניה אם אני רוצה מודל מספק אחר, למשל בשביל לעבוד עם ג'מיני, אני צריך להתקין גירסה של ספריית הסוכנים עם תוסף בשם LiteLLM עם הפקודה:
pip install "openai-agents[litellm]"
ואז אני יכול בקוד לכתוב:
gemini = Agent(
    name="Assistant",
    instructions="You are a mighty creator of dad jokes",
    model=LitellmModel(model="gemini/gemini-2.5-flash", api_key="...")
)

result = Runner.run_sync(gemini, "Write a random dad joke")
print(result.final_output)
בדיקת סוכנים דרך ה REPL ספריית OpenAI Agents מגיעה עם כלי שורת פקודה לבדיקת סוכנים. הכלי מאפשר לי לכתוב שורת Instructions ואז להמשיך ולדבר עם הסוכן שמוגדר על ידי המודל וה Instructions. תוכנית כזו מפעילה לולאה שמחכה לשורה מהמשתמש, שולחת את ההודעה למודל השפה, שומרת את ההודעה ואת תשובת המודל ומדפיסה אותה חזרה למשתמש בהזרמה. זה הקוד וזה מאוד נוח כדי לבדוק איך סוכנים שונים שאנחנו בונים יתנהגו:
import asyncio
from agents import Agent, run_demo_loop

async def main() -> None:
    agent = Agent(
        name="Assistant",
        instructions="You are a mighty creator of dad jokes",
        model="gpt-4.1-mini",
    )

    await run_demo_loop(agent)

if __name__ == "__main__":
    asyncio.run(main())
ניהול Session בעצמנו מה בעצם עושה הפונקציה run_demo_loop? היא פותחת אוביקט שנקרא session. מודל השפה לא "זוכר" הודעות ישנות, אין לו State, לכן בשביל לייצר שיחה כל הודעה נשלחת עם כל ההודעות הקודמות באותה השיחה. אוביקט session שומר רשימות של הודעות כדי שיהיה אפשר להמשיך שיחות. ה session יכולה להישמר בזיכרון אבל יהיה לנו נוח לשמור אותה בבסיס נתונים. הקוד הזה מריץ לולאה של שיחה עם מודל ושומר את כל ההודעות לבסיס נתונים מסוג SQLite. אחרי הרצה הסתכלו בבסיס הנתונים כדי לראות את מבנה הטבלאות וההודעות:
import asyncio
from agents import Agent, SQLiteSession, Runner

async def main() -> None:
    agent = Agent(
        name="Assistant",
        instructions="You are a mighty creator of dad jokes",
        model="gpt-4.1-mini",
    )
    session = SQLiteSession("user_123", "conversations.db")

    while True:
        next_line = input('> ')
        result = await Runner.run(
            agent,
            next_line,
            session=session
        )
        print(result.final_output)



if __name__ == "__main__":
    asyncio.run(main())
הפעלת כלים

ToCode
1 419
רק AI היה יכול לחשוב על זה, חלק 2 מאחר ול AI אין בעיה להקליד הרבה אנחנו הרבה פעמים מקבלים PR-ים עם המון קוד שבמבט ראשון לא נראה נורא ואולי אפילו נותן הרגשה של "וואו איזה כיף שיש AI כי לי היה לוקח המון זמן להקליד את כל זה" אבל במבט יותר מעמיק אנחנו מבינים שבני אדם מראש לא היו מקלידים את הכל. דוגמה? בטח. כתבתי קוד שיוצר מבנה נתונים של רשימה בה לכל פריט יש מזהה וגם כל פריט צריך להחזיק את המזהים של הפריטים שהיו לפניו ואחריו, ככה בערך זה נראה:
items = [
    { id: 'a', name: 'one', next: 'b' },
    { id: 'b', name: 'two', prev: 'a', next: 'c' },
    { id: 'c', name: 'three', prev: 'b', next: 'd' },
    { id: 'd', name: 'four', prev: 'c' }
]
וביקשתי מ AI לכתוב בדיקות ללוגיקה. קיבלתי קובץ של כמה מאות שורות כל בדיקה בנויה באותו סגנון:
expected = [{id: 'a', name: 'one'}]
assert_equal expected, build_list
רואים כבר את הבעיה? תכף היא תהיה ברורה. הפיצ'ר הבא למימוש היה שינוי שהמזהים יהיו אקראיים, כך שעכשיו הפונקציה build_list עדיין מחזירה מבנה נתונים בדיוק באותו מבנה אבל במקום a, b, c ו d היא משתמשת ב uuid. מבחינת הקוד זה היה שינוי של דקה אבל הבדיקה (כלומר כמה מאות שורות של בדיקות) לא שרדה. בן אדם שהיה מקבל משימה לכתוב בדיקות היה קודם כל חושב "מה בעצם חשוב לי בבדיקה הזאת", מבין שמה שחשוב זה שה next ו prev תמיד מכילים את המזהים של מה שבא לפניהם ואחריהם וכותב בדיקה גמישה שלוקחת את המזהים מהרשימה שנוצרה ומוודאת שהקשר בין הפריטים נכון. ל AI אין ולא יכולה להיות ההבנה הזאת. אגב כששאלתי את ה AI מה אפשר לעשות בשביל שהבדיקות לא ייכשלו הוא הציע בדיוק מה שבינה מלאכותית אמורה להציע - תעשה mock לפונקציית ה random וככה יהיו לך מזהים צפויים ותוכל להשתמש בהם בבדיקות. וזה בדיוק הפיתרון שמפספס את הבעיה. נשים לב - בקידוד עם AI יש לנו הזדמנות להקליד פחות ומחויבות לחשוב יותר. זה שני דברים טובים במכה אחת.