הבלוג של ינון פרק

טיפים קצרים וחדשות למתכנתים

כתיבת AI Agent שמשתמש בכלים עם Vercel AI SDK

04/05/2025

בפוסט אתמול הצגתי סוכן AI מאוד פשוט שרץ כל יום ומעצב אימייל עם סיכום מידע שעניין אותי מגיטהאב. בואו ניקח את הקוד צעד קטן קדימה ונתן לסוכן שלנו גישה לכלים כך שיוכל להפעיל קוד וכך לקבל החלטות בצורה יותר עצמאית.

הפעלת כלים מתוך קוד שניגש ל LLM זה בסך הכל בקשה ל LLM להדפיס קוד מיוחד כשהוא מרגיש שצריך להפעיל כלי, זיהוי הקוד הזה מתוך הסוכן שפנה ל LLM ואז הסוכן מפעיל את הכלי ופונה שוב ל LLM עם התוצאה להמשך עבודה. כתבתי בעבר איך לממש לבד מנגנון הפעלת כלים ב AI. היום לא אבנה את המנגנון מאפס אלא אשתמש בספריה קיימת להפעלת כלים של Vercel שנקראת פשוט AI SDK. הספריה של ורסל מתפתחת מהר וכוללת הרבה יכולות ולדעתי היא הדרך הקלה ביותר לכתוב סוכני AI בטייפסקריפט.

המשך קריאה

ה AI Agent הראשון שלי

03/05/2025

מתחת לכל המילים הגבוהות, סוכן AI הוא בסך הכל תוכנית מחשב שנעזרת ב API של ספקי ה AI כדי לבצע חלק מהעבודה שלה. הרבה פעמים סוכני AI יוכלו לקבל החלטות באיזושהי צורה - או באמצעות החזרת קוד מסוים לתוכנית ששלחה את השאלה או באמצעות הפעלת כלים.

בפוסט היום נראה דוגמה לסוכן מאוד בסיסי אבל הקוד יוכל לשמש כבסיס לסוכנים מתוחכמים יותר. הסוכן שלי ימשוך את המאגרים הפופולריים מגיטהאב (מרשימת ה Trending Repositories), יארגן לי אותה בתור ניוזלטר וישלח אליי למייל. הוא יוכל לעשות את זה כל יום בשעה קבועה, וכל זה בחינם דרך val.town.

המשך קריאה

הזדמנות ללמידה

02/05/2025

ומה אם AI היה יכול ליצור קוד שאפשר ללמוד ממנו? מה אם ההזיות היו פועלות לטובתנו? זה אפשרי אבל יש לכך מחיר.

לא מזמן קראתי מאמר שממליץ להימנע משימוש בפריימוורקים בעבודה עם AI. ההגיון שם היה שיש מספר תכונות לפריימוורק שהופכות את השילוב שלה עם AI ליותר מאתגר:

  1. גירסאות חדשות של פריימוורק נוטות לשבור תאימות אחורה, ונתוני האימון של ה AI כוללים דוגמאות קוד גם של גירסאות ישנות.

  2. יותר גרוע - גרסאות חדשות של פריימוורק נוטות לשנות דרכי עבודה מומלצות ו Best Practices. בגלל שנתוני האימון של ה AI מכילים גם את השיטות הישנות, עלינו להיות חשדנים ב AI במקומות האלה.

  3. שימוש לא נכון בפריימוורק עלול להשפיע לרעה על כל האפליקציה - לדוגמה בריאקט מימוש קוד עם חלוקה לא נכונה לקומפוננטות יוביל למערכת שתהיה יותר קשה לתחזוקה.

  4. פריימוורק נועד לתת לי מבנה טוב לאפליקציה מלאה. לפריימוורק יש הגיון פנימי שה AI נוטה להזות ולפספס.

מכל הסיבות האלה כשאני מבקש מ AI לייצר עבורי קוד ריאקט אני צריך לקרוא כל שורה בקוד, לתקן את העבודה שלו, למחוק חלקים ולתת לו ליצור מחדש. זה עדיין חוסך לי זמן, במיוחד אם אני יודע מתי להפעיל את ה AI ומתי לכתוב בעצמי, אבל זה לא משהו שהייתי רוצה ללמוד ממנו.

לעומת זאת ברגע שמוציאים את הפריימוורק והספריות מהתמונה אנחנו יכולים להרוויח הזדמנות למידה. לדוגמה הפרומפטים הבאים:

  1. בנה לי משחק טטריס מאפס שישתמש ב Canvas בלי שימוש באף ספריה חיצונית.

  2. בנה רשימת פריטים ניתנים לגרירה וסידור מחדש ב Vanilla JavaScript בלי ספריות חיצוניות.

  3. בנה תשתית Single Page Router שמאפשרת לעבור בין דפים שונים באפליקציה ב Vanilla JavaScript ובלי ספריות חיצוניותץ

פרומפטים כאלה מאפשרים לנו לקבל קוד שאפשר לקרוא ואפילו ללמוד ממנו איך מנגנון מסוים עובד. כשאין תלויות חיצוניות נתוני האימון של ה AI עובדים לטובתנו וסכנת ההזיות יורדת משמעותית.

מה שטוב בשבילי / מה שטוב למערכת

01/05/2025

שני הדברים האלה הולכים יחד לעתים הרבה יותר קרובות ממה שנדמה, אפילו כשקשה לראות את זה בתוצאה הסופית:

  1. קל לי יותר לפתח כשאני עושה קומיט כל כמה שינויים. במבט על המערכת קל יותר לקרוא את ההיסטוריה כשיש בה מעט קומיטים עם הודעות בעלות משמעות.

  2. קל לי יותר לפתח כשאני מתעלם ממקרי קצה ומתקדם ב Happy Path לפני שאני חוזר לטפל בכל המקרים. חשוב יותר ברמת המערכת לוודא ששום באג לא יגיע לפרודקשן שעלול לפגוע באבטחה או בסקייל של המערכת בעולם האמיתי.

  3. קל לי יותר לפתח עם הודעות Debug כדי שאראה מה קורה. טוב למערכת שהמוצרים לא יכללו הודעות דיבג אלא רק מידע רלוונטי למשתמשים.

  4. קל לי יותר לקבל כל הצעה של ה AI בלי לקרוא את הקוד, טוב יותר למערכת שהקוד שנכנס עבר ביקורת ולא כולל שטויות או המצאות.

המעבר מ"מה שטוב בשבילי" ל"מה שטוב למערכת" הוא המעבר לפרודקשן. זה לא קשור לכמה לקוחות או כמה עובדים יש לנו. המעבר לפרודקשן הוא קודם כל בחירה, בחירה להוסיף עוד שלב לתהליך הפיתוח ובחירה להסתכל על העבודה כמוצר ולא כתחביב.

שלוש ביקורות שמצאתי ברשת נגד פיתוח בעזרת AI

30/04/2025

פיתוח בעזרת כלי AI הוא עובדה מוגמרת. כשחיפשתי ברשת חוות דעת שליליות על שיטת עבודה זו מצאתי הרבה תלונות על כלים ספציפיים - למשל "למה עזבתי את קופיילוט בשביל קרסר" או "תתקינו זד ותוכלו להפסיק לשלם על קרסר", אבל מעט מאוד ביקורות רציניות נגד שיטת העבודה באופן כללי. בכל זאת יש שלוש ביקורות שחוזרות על עצמן בצורות שונות ואני רוצה שנשים אותן כאן על השולחן:

המשך קריאה

פייתון מתוך רובי? אין בעיה

29/04/2025

אין ספק שפייתון יותר פופולרית מרובי, כל מי שמוציא API חדש מוציא דוגמת קוד או ספריה לפייתון, ה AI יודע לעבוד יותר טוב עם פייתון וגם כל מה שקשור לניתוח מידע או למידת מכונה קיים בפייתון.

עכשיו מה עושים אם יש לכם מערכת רובי או אתר ריילס אבל אתם צריכים להפעיל קוד מהאקוסיסטם של פייתון? דרך אחת היא פשוט לקרוא ל python בתור תהליך חיצוני, וזה יעבוד אבל זה קצת מעייף להבין אם התהליך החיצוני של הפייתון סיים או התרסק באמצע או להעביר מידע בין שתי התוכניות. מנגנון יותר פשוט הוא הספריה pycall:

https://github.com/mrkn/pycall.rb

הוראות ההתקנה באתר שלהם עבדו לי ממש בסדר. תוכנית הדוגמה שלהם היתה קצת משעממת אז כתבתי סקריפט שמצייר פרה במקום:

require 'pycall/import'
include PyCall::Import

pyimport :cowsay

puts cowsay.cow('Hello World')

בשביל שזה יעבוד צריך להתקין את pycall, להתקין את פייתון ולהקפיד לקמפל אותו עם האפשרות להשתמש בו בתור ספריה עם הפקודה:

env CONFIGURE_OPTS="--enable-shared" pyenv install 3.13.3

וזה הכל. עכשיו תוכלו להנות מהאקוסיסטם של שתי השפות בתוכנית אחת.

פיתוח משחק סנייק עם AI - מה כן עבד

28/04/2025

לפני כמה ימים כתבתי כאן על הכישלון שלי בפיתוח משחק סנייק עם קרסר. הפרומפט "תפתח לי משחק סנייק", באופן די צפוי, יצר קוד גרוע ומשחק שרק נראה עובד אבל מכיל באגים וארכיטקטורה גרועה, כך שכל תיקון של אחד שבר 3 אחרים. בפוסט היום אני רוצה להראות מה כן לעשות - איך לגרום ל AI לפתח קוד ממש בסדר, ומה זה אומר על התפקיד של מתכנתים בעולם של Vibe Coding.

המשך קריאה

פייתון 3.14 עשוי לחסוך לכם שאלת ראיונות עבודה מוזרה

27/04/2025

רוצים לבלבל מועמד למשרת פייתון? שאלו אותו מה מדפיסה התוכנית הבאה:

def return_example():
    try:
        print("In try block")
        return "Try block return"
    except Exception as e:
        print(f"Exception: {e}")
    finally:
        print("In finally block")
        return "Finally block return"

result = return_example()
print(f"Result: {result}") 

נו טוב, אולי זה לא כזה מבלבל כי יש רק שתי פקודות return בפונקציה ואם אנחנו שואלים על זה אז בטח התשובה לא יכולה להיות התשובה הצפויה. ואכן בפייתון בגלל שקוד שכתוב בבלוק finally תמיד ירוץ התוצאה תהיה:

In try block
In finally block
Result: Finally block return

זה קצת מוזר כי אנחנו מדמיינים שאחרי return אין כלום, אבל זה גם קצת הגיוני כי finally תמיד צריך לרוץ. בכל מקרה אם קוד מהסוג הזה בלבל גם אתכם תשמחו לשמוע שהחל מגירסה 3.14 של פייתון אי אפשר יהיה לסיים בלוק finally בפקודות return, break או continue וכך לפחות מהשטות הזאת לא נצטרך להתבלבל. כל הפרטים ב PEP:

https://peps.python.org/pep-0765/

אגב דוגמה מעניינת מה PEP של קוד אמיתי שנופל בבור הזה היתה:

try:
    ...
except:
    return NotImplemented
finally:
    return some_value

הרעיון כאן היה שמישהו רצה להחזיר ערך מסוים אם היה Exception או ערך אחר אם לא היה, אבל השימוש ב return בתוך finally ממסך על ה return של ה except וכך תמיד מוחזר הערך שמוגדר ב finally.

מיקרו החלטות, קוד שמשתכפל, למידה.

25/04/2025

הי קרסר - כתוב לי בבקשה משחק סנייק.

אין בעיה בוס, מתחילים בקובץ הזה:

import dynamic from 'next/dynamic'

// Use dynamic import to prevent hydration errors with canvas
const SnakeGame = dynamic(() => import('@/components/SnakeGame'), {
  ssr: false
})

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-center p-4 bg-gray-100">
      <h1 className="text-3xl font-bold mb-6">Snake Game</h1>
      <SnakeGame />
    </main>
  )
}

הי קרסר הקוד לא מתקמפל - הוא מתלונן שאי אפשר לקרוא ל dynamic בלי SSR מתוך קומפוננטת צד שרת.

אין בעיה בוס אני על זה. בוא נעשה ככה:

  1. ניצור קובץ חדש בשם SnakeGameWrapper שיתחיל ב use client ונעביר אליו את כל הקוד מ page.

  2. נעדכן את page שיטען את הקובץ החדש הזה.


קרסר מסיים. הקוד עובד. אבל מי נשאר להגיד לקרסור שאפשר היה לכתוב use client פשוט בהתחלה של page.tsx במקום להוסיף קומפוננטה מיותרת? ומי יקרא את הקוד שבוע הבא ויחשוב בטעות ש page.tsx חייב להיות קומפוננטת צד שרת? ולמה בכלל משחק הסנייק צריך את dynamic? למה שלא יהיה קומפוננטת צד לקוח רגילה?