Охват к подписчикам
6,3%
ERR
Реакции к просмотрам
0,72%
20 на 26 постов
Пересылки к просмотрам
0,47%
13
Постов в день
2,0
всего 30
Где отзываются чаще
доля реакций к просмотрам- 8 авг.הג'וניורים של היום הם הסניורים של עוד חמש שנים. ג'וניורים תמיד היו לא פרודוקטיביים, הם תמיד אילצו סניורים לקרוא קוד שלהם במקום להתקדם בפיצ'רים מעניינים, הם שאלו שאלות, הם הכניסו קוד עם בעיות אבטחה או ששובר דברים במערכת. מפתחים זה לא עורכי דין שצריכים מישהו שיעשה את העבודה השחורה וזאת הסיבה שלג'וניורים תמיד היה קשה למצוא עבודה. אבל כשאתה אומר "יצטרכו הרבה פחות ג'וניורים" אתה מתכוון שבעוד חמש שנים יצטרכו הרבה פחות סניורים (כי מה לעשות בשביל להיות סניור אתה צריך להתחיל ממשהו) וזה לא נשמע סביר עם כמויות הקוד המשוגעות שכל הסוכנים שלכם כותבים. יותר מדויק להגיד שהרף עולה, שאם פעם היה מספיק לבן אדם להצליח לחבר כמה קומפוננטות לאפליקציה בשביל למצוא עבודה היום ה AI כבר יכול לעשות את זה ואנחנו מצפים מהג'וניורים שיגיעו ברמה יותר גבוהה - שיוכלו להכנס לקוד של הסוכן, להוסיף עליו, לתקן בעיות, לזהות בעיות לפני שהן קורות, להסביר מה האתגר ולמה הסוכן הסתבך איתו ואיך היה אפשר לארגן אחרת את המערכת כדי שהסוכן כן יצליח לעבוד. אז כן הכשרת ג'וניורים תצטרך להשתנות, קורסי הסבה לתכנות יצטרכו להשתנות. זה בסדר אנחנו רק בתחילת התהליך. אבל המסקנה שלי לפחות היא הפוכה - יותר קוד מוביל ליותר בעיות ולכן דורש יותר אנשים שיכולים להבין אותו ולתקן אותו. ✏ פיטורים בהייטק "הרבה חברות מפטרות היום עובדים לא כי אין להן מה לעשות עם המפתחים, אלא כי הן לא מצליחות לייעל את התהליכים מסביב". זה נכון אבל קצת יותר מורכב. חלק מהסיפור הוא באמת שבשלב מסוים אין ערך לעוד פיצ'רים. מאנדיי לא תמכור יותר רשיונות אם קצב הוספת הפיצ'רים יוכפל מחר, זה לא מה שעוצר אותם. החלק השני של הסיפור הוא העלאת הרף. מפתחים שלא נותנים מספיק ערך בעזרת הכלים החדשים, שרק כותבים פרומפטים או שמתעקשים לא לכתוב פרומפטים כלל. עבודה עם AI זה שפה חדשה, עולם חדש ודרך חשיבה חדשה והבעיה שמי שלא נכנס לזה עדיין כמו שצריך עובד יותר לאט מכל האחרים בארגון. אני לא מאלה שאוהבים להפחיד אבל כן צריך לשים לב אם אתם רואים את כל האנשים סביבכם מייצרים פיצ'רים ופותרים באגים בקצב מהיר משלכם משמעותית אז למנהל שלכם יהיה קשה להצדיק את המשכורת שלכם. כשאנחנו עובדים בצוות צריך לשים לב לעבוד יותר מהר מהממוצע הצוותי. גם זה תמיד היה נכון והפך יותר נכון עכשיו שכולם האיצו. יהיו פיטורים. יהיו חברות שייסגרו. יהיו אנשים שיחליטו לצאת לגמרי מהתעשייה ויהיו את אלה שיפרחו וחדשים שייכנסו. אני לא יודע מה יהיה העתיד ובטח לא מה יהיה העתיד האישי שלי או של מי מכם, אבל בהערכה אחת אני די בטוח - יותר קוד גורם ליותר בעיות ודורש יותר מתכנתים. מהאמת הזו אי אפשר לברוח.2,98%
- 10 авг.📌 היום למדתי: מספרים גדולים ב JavaScript ל JavaScript יש טיפוס נתונים שנקרא number לייצוג מספרים: > typeof(12) 'number' משתנה מסוג number הוא בגודל 64 ביט אבל JavaScript עצמה לא משתמשת בכל 64 הביטים כדי לייצג מספרים שלמים. הערכים שמותר לייצג כמספרים הם הטווח: > Number.MIN_SAFE_INTEGER -9007199254740991 > Number.MAX_SAFE_INTEGER 9007199254740991 ל JavaScript יש גם טיפוס נתונים בשם bigint שיודע לייצג מספרים הרבה יותר גדולים ואנחנו יוצרים ערך מסוג bigint בעזרת הסיומת n בסוף מספר: > typeof(12n) 'bigint' הגודל של bigint מוגבל רק בכמות הזכרון שיש לכם על המחשב. מה קורה כשיוצאים מחוץ לטווח הבטוח? שימו לב: > Number.MAX_SAFE_INTEGER + 1 9007199254740992 > Number.MAX_SAFE_INTEGER + 2 9007199254740992 > Number.MAX_SAFE_INTEGER + 3 9007199254740994 > Number.MAX_SAFE_INTEGER + 4 9007199254740996 > 9007199254740992 == 9007199254740993 true נו זה היה כיף. במספרים גדולים זה כמובן לא היה קורה: > 9007199254740992n == 9007199254740993n false אז למה לא להשתמש ב bigint כל הזמן? בגלל JSON כמובן: > JSON.stringify(9007199254740992) '9007199254740992' > JSON.stringify(9007199254740992n) Uncaught TypeError: Do not know how to serialize a BigInt at JSON.stringify (<anonymous>) בשביל ש JavaScript יהפוך מספר גדול ל JSON הוא יצטרך לכתוב ערך שאף אחד לא יוכל לקרוא. מה עושים? הופכים למחרוזת וזוכרים להמיר ל BigInt בחזרה: BigInt(JSON.parse(JSON.stringify(90071992547409932n.toString()))) 90071992547409932n נ.ב. הסיבה שאנחנו צריכים לדבר על זה היא שאנשים עדיין שולחים לפעמים id בתור מספר במקום בתור מחרוזת וכך כשיש יותר מדי אוביקטים במערכת המזהים מתחילים להישבר. מספרים גדולים זה אחלה לחישובים אבל רוב הזמן יהיה יותר קל לדאוג תמיד לשמור את המזהים שלנו בתור מחרוזות ולא לדאוג לגודל.2,46%
- 8 авг.📌 חמש תשובות על שילוב AI בפיתוח דה מרקר פרסמו כתבה גדולה על המצב של התעשייה בעקבות מהפכת ה AI וחלק משמעותי מוקדש שם לפיתוח. אני רוצה להתיחס ל-5 ציטוטים שעלו משם בעיקר כדי להוסיף צבע וקונטקסט כי הסיפור הרבה פחות ברור ממה שהוצג. ✏ גיוס ו AI "מועמד לעבודה שינסה היום לפתור תרגיל תכנות שאתן לו בכוחות עצמו על ידי כתיבת קוד ידנית, ייפסל מבחינתי אוטומטית". שאלות טכניות בראיונות עבודה מכילות מספר מטרות. שלוש מרכזיות הן: משימות ביצוע שמטרתן לראות שהמועמד מרגיש בנוח עם הכלים ומצליח ליצור משהו עובד, משימות תיאוריה שמטרתן לראות שהמועמד מכיר את עולם התוכן הרלוונטי ומשימות יצירתיות שמטרתן להבין איך המועמד חושב על בעיות. הציטוט שהתחלתי איתו מתיחס למשימות ביצוע, בין כאלה שמבוצעות במהלך הראיון על מחשב החברה או כאלה שמועמד מקבל לפתור בבית. אין ספק שמשימות ביצוע בראיונות עבודה צריכות להשתנות. מאחר ואנשים כבר לא מקלידים קוד בעבודה ברור שבמשימה כזאת גם המועמדים ישתמשו בסוכני קידוד. אבל הדבר החשוב הוא לא אם המשתמש הפעיל תוכנה X או Y אלא שהוא סיים את המשימה. משימות ביצוע היום צריכות להשתנות ובהרבה חברות כבר השתנו. במקום לבדוק אם הצלחת לכתוב לולאה אנחנו ניתן למועמד לכתוב מערכת שלמה ונבדוק את איכות קוד המערכת. שימוש נכון בכלים משתקף בקוד: קוד מתועד, עם בדיקות ברמה גבוהה שבאמת בודקות את מה שהקוד עושה, ללא כפילויות ועם אבסטרקציות נכונות, אחידות חזקה וטיפול נכון בשגיאות אמיתיות ובלי תכנות דפנסיבי וטיפול בשגיאות מדומיינות. מה שיפסול את המועמד בציטוט הוא לא ההחלטה לכתוב קוד ידנית אלא שהקוד שהוא יכתוב לא יעמוד בסטנדרטים ולא ייכתב בזמן המוקצה למשימה. מועמד דומה שפשוט ידביק את תיאור המשימה כפרומפט ל AI גם ייכשל כי הקוד לא מספיק טוב. משימת הביצוע בודקת את מה שהיא תמיד בדקה - שהמועמד יודע לתרגם רעיונות והבנה לקוד, פשוט עכשיו ההיקף מסנן אוטומטית את מי שלא ישתמש ב AI. ✏ הפרמטר החשוב "אתה כמובן רוצה לדעת שהמועמד מבין ארכיטקטורת תוכנה, אבל יותר חשוב לי שהוא יידע להפעיל אייג'נטים ולבנות אייג'נטים שיפעילו אייג'נטים אחרים" כשאנחנו שומעים כזה ציטוט כדאי לשים אותו בקונטקסט. יש חברות שמה שחשוב להן זה יכולת הביצוע. יש חברות אחרות שמה שחשוב להן זה ארכיטקטורה נכונה. במקומות אחרים מה שחשוב זה פתרונות יצירתיים שלא נוסו בעבר. אם מה שמעניין אותך הוא יכולת ביצוע ברור שאתה תחפש מועמד שיודע להפעיל אייג'נטים, בדיוק כמו שלפני חמש שנים אותו מנהל היה יכול להתראיין ולהגיד שיותר חשוב לו שהמועמד יודע לבנות מערכת עובדת מאשר להסביר את התיאוריה של עץ אדום שחור. להציג ציטוט אחד של מנהל פיתוח ששם דגש על פרמטר אחד לא אומר שכל התעשייה מחפשת את הפרמטר הזה או שהפרמטר הזה הוא הדבר הכי חשוב באופן כללי בעבודה בהייטק ופיתוח מערכות. חברות מוצלחות מעסיקות מגוון של מפתחים, חלקם אנשי ביצוע מעולים, חלקם אנשי רעיונות וחלקם אנשי תיאוריה. אנחנו צריכים את כולם. ✏ השאלה היא לא כמות המשימות "כדי להיות אפקטיבי היום בעבודה, אתה חייב לדעת לעבוד במקביל. אתה אומר לאייג'נט אחד מה לעשות — ובזמן שהוא רץ, צריך לעבור ולהדריך את האייג'נט השני. הציפייה שלי ממפתחים היא לעבוד לפחות על שלוש משימות במקביל, אבל יש כאלה שיכולים לעבוד גם על עשר." אפקטיביות לא נמדדת בשורות קוד ליום או במספר "משימות" שבוצעו. מפתחים עסוקים היום בחיפוש ובניית תהליכי עבודה מקביליים חדשים וכולם עדיין מחפשים את הדרך הנכונה. כל מפתח וכל מנהל פיתוח היום בא עם "שיטה" איך לבנות מוצרים טובים לאורך זמן. חלק מהחברות ידחפו למקביליות, חלק יעלו את הפיתוח לסוכנים בענן וימקדו את המפתחים בכתיבת טיקטים ומעבר על הקוד, אצל חלק אחר הדגש הוא דווקא על סינון ופיתוח "טעם אישי" והמטרה היא להכניס כמה שפחות שינויים ולשמור על אחידות. אנחנו לא יודעים עדיין מה נכון. הסטארט-אפ שהיום מנסה להכניס כמה שיותר פיצ'רים ותיקוני באגים עשוי לגלות מחר שהוא הכניס יותר מדי קוד והלקוחות שלו היו מעדיפים פחות עדכונים. סטארט אפ שעובד עם חמישה סוכנים עשוי לגלות שעלייה ל-10 סוכנים משפרת פרודוקטיביות או שבעצם ירידה ל-2 סוכנים תאפשר את הקפיצה הבאה. שימו את הדברים בקונטקסט. חפשו כמה שיותר ציטוטים כאלה והקשיבו לאנשים מגוונים מהתעשייה לפני שאתם רצים אחרי פרסומת בעיתון. ✏ תפקיד הג'וניורים "אני מכווין, מדריך ומדייק את האייג'נטים על בסיס הידע שצברתי בשנים בתעשייה, והם עושים את העבודה. אם מכפילים אותי, עם כל הניסיון שצברתי, פי שמונה, אני חושב שיצטרכו הרבה פחות ג'וניורים בתעשייה".2,00%
- 7 авг.📌 גם אתם צריכים מדיניות LLM לאחרונה ראסט הכריזו על מדיניות LLM שסוף סוף עוזבת את התבנית הקבועה של "אין לנו בעיה עם LLM" או "אין כניסה לסוכנים". אנחנו נוטים לחשוב ש"מדיניות LLM" זו בעיה של פרויקטי קוד פתוח שמקבלים קוד מן הגורן ומן היקב, אבל האמת שרוב חברות התוכנה שראיתי רק ירוויחו מהגדרת מדיניות ברורה לשימוש ב LLM מעבר ל"תבזבזו כמה שיותר טוקנים אבל לא מעבר לתקציב". אלה הדברים המרכזיים שמדיניות LLM צריכה להגדיר: 1. מתי מותר לפרסם תוכן ש LLM יצר, מתי חייבים להבהיר שמדובר בתוכן ש LLM יצר ומתי אסור להיעזר ב LLM. גם אם החלטתם שסוכני קידוד הם כלי עבודה שאי אפשר בלעדיו ו 100% מהקוד צריך להיות מיוצר על ידי סוכנים יש עוד ערימה של דברים שצוותי פיתוח מייצרים: אימיילים, טיקטים בג'ירה, דיווחי באגים, תשובות למשתמשים, סיכומי פגישות, תיעוד, מדריכים למפתחים חדשים. אם LLM יכול להכניס לבד דיווחי באגים אז יהיו דיווחי באגים מיותרים. אם LLM הולך לכתוב טקסט של טיקטים אז טיקטים יהיו לא עקביים ואולי לא מדויקים. כלל אצבע במדיניות של ראסט אומר למשל: Showing LLM output to another human without solicitation is likely banned ברור שאי אפשר לאכוף את זה וזו לא המטרה. הסיפור כאן הוא תיאום ציפיות והוגנות. אני הייתי מוסיף שאם אתה רוצה להדביק פלט של LLM לשיחה עדיף שתדביק את הפרומפט שכתבת לו. לכולם יש גישה לקלוד ויכולים לייצר בעצמם את ההשלמה. 2. איך אנחנו מתמודדים עם ירידה באיכות הקוד כתוצאה מקוד שנוצר על ידי סוכני קידוד. לא משנה מי הסוכן שכותב את הקוד יש בעיות והטיות מובנות לכל הכלים האלה: הם כותבים קוד מתגונן, הם לא מוחקים, הם כותבים בדיקות ספציפיות מדי, הם כותבים טלאים שגורמים לדברים לעבוד גם כשהם לא נכונים, הם כותבים קוד משוכפל בכמה מקומות ורוב הזמן מתקשים למצוא את המקום הנכון לכתוב את המימושים שלהם. אפשר להחליט שאחרי כל יצירת קוד עם סוכן קידוד מישהו אנושי נכנס לקוד ומתקן. זה לוקח זמן ודורש מיומנות כלומר במקום שפיצ'ר יהיה באוויר אחרי שעה ש LLM ישב עליו הוא יצטרך יומיים של מפתח אנושי. אפשר להחליט שאנחנו דוחפים כל מה ש LLM יצר אם זה לא ממש שגוי ומשקיעים זמן קבוע פעם בשבוע בניקוי הקוד כולל קוד ישן. אפשר להחליט שאנחנו מתקנים כשמזהים באגים תוך כדי תנועה. אפשר להחליט שאנחנו רצים הכי מהר שאפשר עד שהמכונה נתקעת ואז עוצרים לנקות או מתחילים פרויקט חדש. מה שלא תחליטו כדאי שכל האנשים בארגון יהיו מיושרים על ההחלטה. אם מנהל הפיתוח בטוח שכל קוד שנכנס למערכת עבר Review אנושי ואיטרציות והוא עומד בסטנדרטים הכי גבוהים של פיתוח אבל בצד השני יש מפתחת שבטוחה שהדבר הכי חשוב זה מהירות ואסור לבזבז זמן על קריאת הקוד מתישהו יהיה פיצוץ. 3. איזה תהליכים בארגון מבוצעים רק על ידי AI, איזה רק על ידי בני אדם ואיזה על ידי שילוב אם חבר מבקש שתעברו על קוד שהוא כתב זה בסדר להשתמש ב AI? אם צריך לתקן בעיה בגיט זה בסדר לתת לקלוד לסדר את זה? מה לגבי ניתוח פלט של בדיקות ותיקון בדיקות שנכשלו? אל תתנו לכל מפתח להחליט לבד רמת המיומנות שלו או שלה או לפי כמה זמן יש להם עכשיו. בואו ניישר קו - אצלנו לפני שקוד נכנס לפרודקשן הוא עובר Review של בודק ה AI, או אצלנו לפני שגרסה עולה לפרודקשן מפתח אנושי חייב לשבת יומיים ולקרוא את כל הקוד שהשתנה מאז הגרסה האחרונה, או אצלנו מפתח אנושי חייב לעבור על הפלט של בודק ה AI. מה שתחליטו זה בסדר רק תראו שאתם שלמים עם ההשלכות. למרות שמודלי שפה לא חותמים על הטקסט שהם מייצרים לבני אדם במיוחד בארץ קל מאוד להבין כשאנחנו מדברים עם מודל שפה בשונה משיחה עם בן אדם אמיתי. קל לנו מאוד לזהות פלט של מודל שפה ואפילו קוד של סוכן קידוד במיוחד על מערכת גדולה. המכונות האלה אולי מייצרות טקסט דומה לזה שבני אדם מייצרים אבל הן לא בני אדם. חלק חשוב מהיכולת לעבוד עם מכונות אלה בצורה יעילה הוא חלוקת התפקידים שתתאים ליכולות, למגבלות ולאחריות של כל אחד.1,70%
- 6 авг.📌 בואו נערבב merge ו rebase כדי לשבור את גיט ריבייס מאפשר לייצר היסטוריית גיט לינארית באמצעות יצירה מחדש של הקומיטים שבוצעו לפיצ'ר מסוים על גבי קומיט חדש יותר. זה עובד ממש טוב כשאני בונה פיצ'ר ובזמן הזה הענף הראשי התקדם. אני רוצה לשלב את הפיצ'ר במערכת אבל ההתקדמות של הענף הראשי היא לא הסיפור, ולכן אני עושה rebase מהענף שפיתחתי על הקומיט החדש ביותר בענף הראשי, מה שגורם לגיט "לבנות מחדש" את פיתוח הפיצ'ר מתוך הקומיט החדש ביותר. אחרי ריבייס אפשר למזג ובהיסטוריית גיט זה נראה כאילו חיכיתי לסיום הפיצ'רים של הענף הראשי לפני שפיתחתי את הפיצ'ר שלי, כלומר הפיצ'ר שלי נבנה על גבי הפיצ'רים מהענף הראשי. עכשיו בואו נשבור את זה. נניח שבשלב מסוים main התקדם ואני רציתי בפיצ'ר שלי לקבל שינויים שנכנסו ב main אז ביצעתי merge מ main ל feature1. המיזוג לא עבר חלק ופתרתי קונפליקטים אבל זה בסדר כי ממילא הייתי צריך לפתור את הקונפליקטים האלה לפני שאני יכול לשלב. בינתיים main ממשיך להתקדם וכעבור זמן אני מגיע לריפו במצב הבא: * 45cfa5d (main) main: 3 commits ahead * 51c18b4 main: 2 commits ahead * dfad935 main: 1 commit ahead | * fa37287 (HEAD -> merge-feature1) Merge feature1 into old main (RESOLVED CONFLICT) |/| | * 2392145 (feature1) feature1: add HTML report part 2 | * 6b24764 feature1: add HTML report part 1 * | 9961b60 main: added some changes |/ * d4d0727 fixed stuff * 9155d8f initial commit מה יקרה אם עכשיו אני מנסה להפעיל את אותו טריק ולבצע ריבייס מהענף הממוזג ל main החדש? שימו לב: (merge-feature1) $ git rebase main Auto-merging main.py CONFLICT (content): Merge conflict in main.py error: could not apply 6b24764... feature1: add HTML report part 1 hint: Resolve all conflicts manually, mark them as resolved with hint: "git add/rm <conflicted_files>", then run "git rebase --continue". hint: You can instead skip this commit: run "git rebase --skip". hint: To abort and get back to the state before "git rebase", run "git rebase --abort". hint: Disable this message with "git config set advice.mergeConflict false" Recorded preimage for 'main.py' Could not apply 6b24764... # feature1: add HTML report part 1 קיבלתי קונפליקט על קומיט 6b24764, כלומר קונפליקט שכבר פתרתי ב Merge Commit. היה לי רעיון טוב להקדים תרופה למכה ולמזג את השינויים מ main לפני שאני מסיים לעבוד על הבראנץ' אבל בסוף זו היתה עבודה מיותרת כי ריבייס מתעלם מהקונפליקטים שפתרתי. מה עושים? קודם כל כדאי לזכור שקשה להזיז merge commit ולכן עדיף לחשוב לפני שאתם מתחילים merge איפה אתם רוצים שה merge commit שלכם ישב. אם בכל זאת תבקשו מאיזה קלוד להתעקש הוא ימזג חזרה את main העדכני לתוך merge-feature1, ימחק את main ואז יבנה קומיט חדש עם git write-tree שיש לו רגל אחת על אותו ענף צד ורגל שניה איפה שהיה פעם main.1,11%
- 5 авг.📌 היום למדתי: fgrep לעומת grep כשאתם נותנים ל AI לכתוב Shell Scripts שמחפשים בקבצים הוא אוהב להשתמש ב grep. זה עובד בשמות פשוטים ויכול לבלבל כשהשמות מכילים תווים מיוחדים של ביטויים רגולארים. לדוגמה נתון קובץ טקסט עם השורות הבאות: line1 line2 line3 line4 line.txt בשביל לבדוק אם קיימת בו השורה line3 נוכל לכתוב: $ grep line3 demo.txt ונקבל את השורה. בשביל לבדוק אם קיימת בו השורה line.txt מפתה לכתוב גם: $ grep line.txt demo.txt וזה גם עובד ומדפיס את line.txt - אבל זה בטעות. הנקודה ב line.txt היא תו של ביטויים רגולאריים ובעצם מתאימה לכל תו. לדוגמה אם הקובץ שלנו מכיל: line-txt line_txt line2txt אותה פקודת grep תחזיר את כל השורות: grep line.txt demo.txt line.txt line-txt line_txt line2txt מה עושים? נזכרים בטיפ בכותרת. פקודת grep -F או פקודת fgrep מחפשות טקסט פשוט ולא ביטוי רגולארי לכן כשאנחנו מחפשים טקסט רגיל נעדיף לכתוב: $ fgrep line.txt demo.txt line.txt ונקבל רק את השורה עם הנקודה ולא את השורות שמתאימות לביטוי הרגולארי. נ.ב. grep עצמו מבלבל כי הוא מתעלם באופן אוטומטי מתווים מסוימים של ביטויים רגולאריים במיוחד פלוס, כלומר אם בקובץ יש לי את השורות: 2+4 2229 פקודת grep תחזיר ממש את הפלוס ותתעלם מהפלוס במשמעותו המיוחדת של "תו נוסף" שאנחנו מכירים מביטויים רגולאריים: $ grep '2+' demo.txt 2+4 אבל זו רק הטעיה כי אם מוסיפים לה \ לפני הפלוס היא חוזרת להתיחס אליו כמו תו של ביטויים רגולאריים: $ grep '2\+' demo.txt 2+4 22291,02%
- 12 авг.📌 החלטות מהותיות שגויות גיירמו ראוך (מייסד vercel) פרסם בטוויטר קריאה לקרוא את הקוד. אני מתרגם: אם אתם לא קוראים את הקוד אחד הבאים נכון: 1. אתם מפתחים בתחילת הדרך. 2. אתם לא צריכים את התוכנה לטווח רחוק. 3. אתם רק מנסים עדיין לא בונים מוצר אמיתי. 4. אין לכם משתמשים או הכנסות. 5. אתם בחובות. 6. אתם פותרים בעיות מאוד בסיסיות. מודלים עושים טעויות של מתחילים ובוחרים ארכיטקטורה לא נכונה. המודל הכי טוב בעולם הרגע הוסיף לי המתנה של 700ms לקוד בלי שום סיבה וכשהערתי על זה הוא ענה שאני צודק. ———————— מעניינת הרשימה שלו אבל לדעתי מפספסת את הנקודה. הדוגמה בסוף היא המפתח. בנינו מכונה אדירה שיודעת לתרגם טקסט בשפה טבעית לקוד וכמעט שכחנו ששפה טבעית היא לא קוד. היא לא מתארת את כל מה שצריך לעשות בכל המצבים. אנשים שונים יקראו טקסט בשפה טבעית ויבינו ממנו דברים אחרים. לא משנה איזה מכונה תיקח היא לא תוכל להחליט תמיד את ההחלטה הנכונה כי אין החלטה אחת נכונה. קריאת הקוד היא החוזה בינינו לבין המכונה. אנחנו לא צריכים לוודא שהמכונה כותבת נכון לולאת for אנחנו צריכים לוודא שמכל המקומות בהם אפשר לכתוב לולאת for כדי להגיע לתוצאה שרצינו היא בחרה את המקום שגם אנחנו היינו בוחרים. גיירמו טוען שזה זמני, שעוד מעט המודלים כבר לא יעשו כאלה טעויות, שנצטרך לקרוא את הקוד פחות ופחות. אני חושב שמי שאחראי על מערכת צריך להכיר אותה ולהבין איך היא עובדת והדרך היחידה לעשות את זה היא לקרוא את הקוד. ואולי יותר חשוב צריך גם לדעת איך לקרוא את הקוד. יום יבוא וההחלטות של המודלים יראו לנו כל כך הגיוניות שיהיה קשה לחשוב על אלטרנטיבה. זה לא המצב היום. כרגע גם בעבודה עם המודלים הכי טובים אם סיימתם יום עבודה ולא הערתם לסוכן על החלטות מהותיות שגויות שהוא קיבל סביר להניח שפספסתם את אותן החלטות מהותיות ושגויות.0,92%
- 11 авг.📌 שאלת המשך בנושא: merge ו rebase לפני כמה ימים הצגתי כאן דוגמה שמראה איך לשבור ריפו באמצעות ערבוב בין merge ל rebase. הפוסט כלל את המשפט "נניח שבשלב מסוים main התקדם ואני רציתי בפיצ'ר שלי לקבל שינויים שנכנסו ב main", בעקבותיו עלתה השאלה "למה לא לעשות rebase בשלב הזה?" התשובה קשורה לתוכן הענפים וכמה כאב ראש כרוך בשינוי. נפרט: ✏ מתי כדאי לעשות rebase על main פעולת rebase לוקחת את כל הקומיטים מענף מסוים שלא נמצאים בענף השני ומייצרת אותם מחדש על הענף השני. אם יצרתי ענף feature ויש בו 3 קומיטים ואז main מתקדם בשני קומיטים פעולת ריבייס מ feature ל main אז פעולת ריבייס תסתכל על שלושת הקומיטים של feature. היא תיקח את השינוי שהכניס הקומיט הראשון ותנסה "להפעיל" אותו על הקומיט העדכני ב main, וכך תמשיך את שלושת הקומיטים האחרים. אם אחד הקומיטים ב main הכניס שינוי שמשפיע על שינוי כלשהו מאחד או יותר משלושת הקומיטים של feature אקבל הודעה על קונפליקט ואצטרך להסביר לגיט איך להפעיל מחדש את אותו קומיט. (מה זה "להפעיל" קומיט בענף אחר? נניח שקומיט הוסיף 2 שורות לסוף קובץ readme.txt אז להפעיל את הקומיט זה לכתוב את אותן שתי שורות לקובץ readme.txt בענף האחר). הבעיה ב rebase היא שגיט צריך לעבור קומיט קומיט וליצור אותו מחדש ולכן ככל ש feature מכיל יותר קומיטים יהיו יותר שלבים בהם יכולים להיווצר קונפליקטים. יותר חמור מזה, אותו קונפליקט לוגי יכול לצוץ מחדש מספר פעמים לאורך אותו ריבייס. לדוגמה אם לאורך החיים של feature נוצרו קומיטים שגם שינו דברים שקומיטים לפניהם כתבו אז עליי לפתור קונפליקט מקומיט ישן שאני יודע שהולך תכף להימחק. בדוגמת ה readme נניח שמתוך שלושת הקומיטים של feature הראשון הוסיף שתי שורות לסוף הקובץ, השני הוסיף שורה לתחילת הקובץ והשלישי מחק את שתי השורות מסוף הקובץ. כשגיט עושה rebase בקומיט הראשון הוא לא יודע שעוד רגע יגיע קומיט שימחק את שתי השורות האלה שעכשיו צריך להוסיף. ✏ מתי אעדיף למזג את main לענף שלי וזה מביא אותנו ל merge. כשענף feature ארוך ועוד יצטרך להמשיך לחיות לעוד הרבה זמן אני מעדיף למזג את main לתוך feature ולהמשיך לעבוד על feature. מיזוג של main לתוך feature לוקח את הקוד העדכני של main ואת הקוד העדכני של feature ומשלב אותם לעץ אחד. אם יש קונפליקט אצטרך לפתור אותו רק פעם אחת, רק על הגרסה החדשה ביותר של שני הענפים. ה merge commit מתעד שההיסטוריות כבר מוזגו בנקודה הזו. במיזוג הבא Git ישתמש בו כחלק מההיסטוריה המשותפת, ולכן יצטרך לשלב בעיקר את השינויים שנוספו מאז. לכן העצה שלי, בענף ארוך עם היסטוריה משמעותית, במיוחד כזה שמתעדכן שוב ושוב יהיה יותר נוח לעדכן באמצעות merge מהענף הראשי מאשר לחזור ולעשות rebase על הענף הראשי.0,80%
- 15 авг.# Provider-adaptive: native fetch when available, local fallback otherwise. capabilities.append(WebFetch(local=True, native=False)) elif tool == "native": # Native-only. WebFetch itself raises UserError if the provider has no # native web-fetch tool (e.g. Gemini) — no fallback, no custom guard. capabilities.append(WebFetch(local=False)) else: raise ValueError(f"Unknown tool backend: {tool}") return Agent( model, output_type=Digest, tools=tools, capabilities=capabilities, instructions=INSTRUCTIONS, ) פרמטר tools מגדיר למודל רשימת כלים בהם יוכל להשתמש. פרמטר capabilities מגדיר כלים מובנים של הספריה או של ה API. הקוד בוחר את הכלים לפי הפרמטר tool שמגיע מבחוץ. לסוכן הזה אנחנו שולחים את ההודעה הבאה: PROGRAMMING_INDEX_SITES = [ "https://reddit.com/r/programming", "https://news.ycombinator.com", "https://lobste.rs", "https://dev.to", "https://hashnode.com", "https://daringfireball.net", "https://arstechnica.com", "https://theverge.com/tech", "https://github.com/trending", "https://www.python.org/blogs/", "https://blog.rust-lang.org", "https://go.dev/blog", "https://nodejs.org/en/blog", "https://kubernetes.io/blog", "https://www.phoronix.com", ] def build_digest(tool: str, max_articles: int) -> Digest: """Run the agent and return the produced digest.""" agent = build_agent(tool) site_list = "\n".join(f"- {s}" for s in PROGRAMMING_INDEX_SITES) prompt = ( f"Build today's programming digest with about {max_articles} articles.\n\n" f"Index pages you may browse:\n{site_list}" ) return agent.run_sync(prompt).output מה יקרה? אי אפשר לדעת. הסוכן מקבל רשימת אתרים וכלי לביקור באתר ומפה ממשיך בצורה חופשית לגמרי. הוא יוכל להכנס לאתרים ברשימה, לאתרים אחרים שאינם ברשימה, למאמרים מהם או להמציא דברים לא קשורים. זה הקסם וגם הסכנה בהפעלת כלים. ✏ עכשיו אתם 1. הריצו את הדוגמה אצלכם עם כל אחד מהכלים. שימו לב שתצטרכו מפתח API מ tavily. זה בחינם ונרשמים כאן Tavily 2. נסו לאלף את המודל - הגדירו כלי "סיום" שמקבל את ה Digest ובודק שיש בו לפחות 7 מאמרים. אם יש פחות החזירו כשלון למודל ובקשו תקציר טוב יותר. 3. נסו לשנות את הדינמיקה - במקום כלי "סיום" אחד הגדירו כלי "שמירת מאמר" ותנו למודל להפעיל אותו כמה פעמים שהוא רוצה בשביל לשמור מאמרים לתקציר היומי. האם יש הבדל במספר המאמרים? באיכות שלהם?0,00%
- 15 авг.📌 יום 3: תקציר חדשות יומי ראינו כבר איך ליצור שאלות הבנה מדף אינטרנט, אבל מה קורה אם יש כמה דפי אינטרנט? בדוגמה של היום נראה איך לתת לסוכן שלנו את החופש לחקור לבד כדי שיוכל להחליט אוטונומית מהם המאמרים הכי חשובים ולתקצר אותם עבורנו. ✏ הפעלת כלים המנגנון הבסיסי ביותר של סוכנים חכמים נקרא הפעלת כלים. זכרו שמודלים הם בסך הכל יצורים טקסטואלים - אנחנו שולחים הודעת טקסט ומקבלים חזרה הודעת טקסט. על הבסיס הזה אנחנו צריכים לבנות מנגנון שיאפשר למודל גם לעשות דברים, וזה מנגנון הכלים. הרעיון פשוט: אם המודל מחזיר טקסט מיוחד שסיכמנו עליו מראש אנחנו ניקח את זה בתור בקשה להרצת קוד, נפעיל פונקציה שסיכמנו עליה מראש ונפנה למודל שוב עם התוצאה של אותה פונקציה. לאורך השנים מנגנון הפעלת כלים התפתח והוטמע בתוך ה API של המודלים כך שהיום הם יודעים לקבל רשימה ארוכה של כאלה פונקציות כחלק מהפרומפט, לקבל חתימה מלאה של הפונקציות ואף לבקש הפעלה של מספר פונקציות במקביל. יותר מזה, ספקי המודלים בנו פונקציות (כלים) שרצות על התשתית שלהן ואלה נקראים כלים מובנים. כשאנחנו פונים לספק מודלים למשל לגוגל בשביל לדבר עם ג'מיני, אנחנו יכולים לבקש לתת לג'מיני גישה לכלים מסוימים שרצים על התשתית של גוגל כחלק מה API. וכל התיאוריה הזאת מגיעה מובנית בתוך הספריה Pydantic AI Agents בצורה נוחה לשימוש: 1. אפשר להגדיר כל פונקציה בתור "כלי" והמודל יוכל להפעיל אותה. 2. פידנטיק AI מגדירה מספר כלים "מובנים", שהם בעצם פונקציות של הספריה שנכתבו כבר בשבילכם. 3. פידנטיק AI חושפים ממשק גישה לכלים המובנים של הספק. הנה דוגמה פשוטה מתוך התיעוד של פידנטיק להגדרת כלים והעברתם לסוכן: import random from pydantic_ai import Agent, RunContext agent = Agent( 'google:gemini-3-flash-preview', deps_type=str, instructions=( "You're a dice game, you should roll the die and see if the number " "you get back matches the user's guess. If so, tell them they're a winner. " "Use the player's name in the response." ), ) @agent.tool_plain def roll_dice() -> str: """Roll a six-sided die and return the result.""" return str(random.randint(1, 6)) @agent.tool def get_player_name(ctx: RunContext[str]) -> str: """Get the player's name.""" return ctx.deps dice_result = agent.run_sync('My guess is 4', deps='Anne') print(dice_result.output) #> Congratulations Anne, you guessed correctly! You're a winner! נתחיל עם מה שקל: הפונקציות roll_dice ו get_player_name מוגדרות בתור פונקציות פייתון פשוטות עם הדקורטור @agent.tool או @agent.tool_plain. ההבדל בין השניים הוא ש tool יכול לקבל פרמטרים מהתוכנית וגם מהמודל ו tool_plain יכול לקבל פרמטרים רק מהמודל. כשהמודל יקבל את הודעת הפתיחה הוא יוכל להריץ את שתי הפונקציות. ככל הנראה הוא יריץ את הפונקציה roll_dice, יקבל מספר אקראי ואז לפי התוצאה ידפיס הודעה תוך שימוש בשם השחקנית שהוא יקבל מהפעלת הפונקציה get_player_name. משפט המפתח כאן הוא ככל הנראה. אין לנו דרך לקבוע למודל איזה כלים להפעיל או באיזה סדר. ✏ מה אנחנו בונים בדוגמה היום נבנה סוכן שירוץ על אתרי חדשות וידפיס תקציר חדשות טכנולוגיה יומי. לצורך יצירת התקציר המודל יוכל לבחור באיזה אתרים לבקר ואיזה מאמרים מהם לקרוא - וכן זה אומר שכל פעם שנפעיל את הסוכן נקבל תקציר אחר. ✏ הצגת הכלים שני הכלים בתוכנית מוגדרים בקובץ extractors.py. רציתי לנסות דרכים שונות לקבל מידע מהאינטרנט ולכן יצרתי שני כלים, אחד נקרא custom fetch והוא מקבל URL ומשתמש ב trafilatura כדי לקבל ממנו את הטקסט. כלי שני נקרא tavily fetch והוא משתמש בשירות רשת בשם tavily כדי לקחת את הטקסט מתוך URL. בנוסף לכלים שלנו התוכנית מאפשרת גם שימוש בכלי ה fetch המובנה של Gemini, ובכלי ה fetch המובנה של Pydantic AI שירוץ מהמכונה שלי. כך נראית פונקציית יצירת הסוכן בקובץ digest.py def build_agent(tool: str) -> Agent[None, Digest]: """Build the digest agent, wiring up the selected extraction backend.""" provider = GoogleProvider(api_key=os.environ["GEMINI_API_KEY"]) model = GoogleModel("gemini-3-flash-preview", provider=provider) tools: list[Tool] = [] capabilities: list = [] if tool == "tavily": tools.append(Tool(make_tavily_fetch())) elif tool == "custom": tools.append(Tool(make_custom_fetch())) elif tool == "web_fetch_tool":0,00%
- 15 авг.https://www.tocode.co.il/blog/2026-08-03-newsticker0,00%
- 14 авг.הפונקציה לוקחת טקסט ורשימה של שפות ומחזירה תרגום לכל אחת משפות היעד בעזרת הסוכן. קוד חיצוני יכול להשתמש בה בלי לדעת שמדובר ב AI. ✏ ממשק שורת פקודה הדרך הכי קלה להשתמש בסוכן שיצרנו היא דרך ממשק שורת פקודה. זה הקוד מתוך קובץ main.py: from cli_args import parse_args, parse_languages from translator import translate def main(): args = parse_args() languages = parse_languages(args.to) result = translate(args.text, languages) for item in result.translations: print(f"[{item.language}] {item.translation}") if __name__ == "__main__": main() הפונקציות parse_args ו parse_languages הן פונקציות עזר שמוגדרות בקובץ cli_args.py זה תוכנו: import argparse def parse_args(argv: list[str] | None = None) -> argparse.Namespace: """Parse command line arguments for the translator CLI.""" parser = argparse.ArgumentParser( description="Translate text into one or more languages.", ) parser.add_argument( "--text", required=True, help="The text to translate.", ) parser.add_argument( "--to", required=True, help="Comma-separated target language codes, e.g. 'es,fr'.", ) return parser.parse_args(argv) def parse_languages(value: str) -> list[str]: """Split a comma-separated language string into a clean list of codes.""" return [lang.strip() for lang in value.split(",") if lang.strip()] אפשר להפעיל את הקוד משורת הפקודה עם פקודה כמו: uv run main.py --text 'hello world' --to es,fr ולקבל תרגום לשתי השפות. ✏ ממשק ווב הממשק השני לאותו סוכן הוא ממשק ה Web. גם הוא ישתמש באותה פונקציית עזר translate ויעביר את התוצאה לפורמט HTML. זה הקוד הרלוונטי מהקובץ app.py: @app.post("/translate", response_class=HTMLResponse) def translate_endpoint( request: Request, text: str = Form(...), languages: list[str] = Form(...), ): """Translate the submitted text and render the results template.""" result = translate(text, languages) return templates.TemplateResponse( request, "result.html", { "text": text, "translations": result.translations, }, ) פלט מובנה אפשר לנו לקחת את אותו פלט של סוכן ולהשתמש בו בצורה תכנותית - גם להדפסה למסוף וגם להדפסה לדפדפן. ✏ עכשיו אתם 1. עדכנו את הקוד כך שישתמש ב NativeOutput וכך במנגנון הפלט המובנה של ספק המודלים. האם יש הבדל בתוצאות? בזמני התגובה? 2. פידנטיק מאפשר להגדיר תיעוד על שדות מידע במודלים שלו, לדוגמה: class UserProfile(BaseModel): username: str = Field( ..., title="Account Username", description="The unique handle used to identify the user across the platform." ) age: int = Field( None, description="The age of the user in years. Optional." ) הוסיפו שדה בשם comments ל Translation והגדירו בתיעוד שזה המקום להכניס טיפים על התרגום, מתי משתמשים במילה, מה משלב השפה, למה נבחר דווקא תרגום זה, האם היו אפשרויות נוספות. שימו לב איך תשובת המודל משתנה רק לפי הפלט השונה שביקשתם.0,00%