Menu

Prompt Chaining: לפצל משימה לשלבים

Prompt chaining (שרשור פרומפטים) מפצל עבודה לרצף של פרומפטים קטנים יותר, שבו הפלט של כל שלב הופך לקלט של הבא. כל שלב עושה דבר אחד, ואפשר לבדוק את התוצאה שלו לפני שהשלב הבא רץ.

כל פרומפט למטה ניתן לעריכה: שנו אותו, ואז פתחו אותו ב-ChatGPT, ב-Claude או באפליקציית AI אחרת.

Prompt chaining פירושו לפצל עבודה לרצף של פרומפטים, שבו הפלט של פרומפט אחד הופך לחלק מהקלט של הבא. במקום לבקש ממודל לקרוא חמישים ביקורות, למצוא את הבעיות, לדרג אותן ולכתוב דוח בבת אחת, מבקשים כל אחד מהדברים האלה בתורו. לכל פרומפט יש עבודה אחת, ובין השלבים אתם (או הקוד שלכם) יכולים להסתכל על התוצאה, לתקן אותה או לעצור.

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

Fill in
פרט כל תלונה בביקורות שבתוך תגיות <reviews>. התעלם משבחים. החזר מערך JSON של אובייקטים עם המפתחות "review" (מספר הביקורת) ו-"complaint" (שמונה מילים לכל היותר). החזר רק את ה-JSON. <reviews> 1. הסוללה מתה אחרי 4 שעות, וכבל הטעינה קצר מדי. 2. סאונד מעולה. אבל האפליקציה כל הזמן מנתקת אותי. 3. אני אוהב אותן, אבל הסוללה בקושי מחזיקה את הנסיעה הביתה. 4. האפליקציה קרסה פעמיים בזמן הצימוד, והסוללה מתרוקנת מהר. 5. הכבל כל כך קצר שאני לא יכול להשתמש בהן בזמן טעינה ליד השולחן. </reviews>
Try it
Example replyReplies vary between models and runs.
[
  {"review": 1, "complaint": "הסוללה מתה אחרי 4 שעות"},
  {"review": 1, "complaint": "כבל הטעינה קצר מדי"},
  {"review": 2, "complaint": "האפליקציה מנתקת כל הזמן"},
  {"review": 3, "complaint": "הסוללה לא מחזיקה נסיעה"},
  {"review": 4, "complaint": "האפליקציה קרסה בזמן הצימוד"},
  {"review": 4, "complaint": "הסוללה מתרוקנת מהר"},
  {"review": 5, "complaint": "הכבל קצר מדי לשימוש בזמן טעינה"}
]

שלב 1 רק קורא ומחלץ. שלב 2 לא רואה את הביקורות בכלל, רק את הרשימה, ולכן הוא לא יכול לגלוש חזרה לסיכום שלהן. שלב 3 רק כותב. אם שלב 3 חוזר בטון הלא נכון, מריצים מחדש רק את שלב 3; החילוץ והקיבוץ נשארים כמו שהיו.

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

למה לשרשר במקום לכתוב פרומפט אחד גדול

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

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

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

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

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

איך לתכנן שרשרת

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

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

לבדוק שלב לפני שמעבירים אותו הלאה
השווה את הביקורות בתגיות <reviews> לרשימת התלונות בתגיות <complaints>. האם הרשימה מכילה כל תלונה בביקורות? ענה "מלאה" או "חסרה" בשורה הראשונה. אם היא חסרה, פרט כל תלונה חסרה עם מספר הביקורת שלה. <reviews> 1. הסוללה מתה אחרי 4 שעות, וכבל הטעינה קצר מדי. 2. סאונד מעולה. אבל האפליקציה כל הזמן מנתקת אותי. 3. אני אוהב אותן, אבל הסוללה בקושי מחזיקה את הנסיעה הביתה. 4. האפליקציה קרסה פעמיים בזמן הצימוד, והסוללה מתרוקנת מהר. 5. הכבל כל כך קצר שאני לא יכול להשתמש בהן בזמן טעינה ליד השולחן. </reviews> <complaints> ביקורת 1: הסוללה מתה אחרי 4 שעות ביקורת 1: כבל הטעינה קצר מדי ביקורת 2: האפליקציה מנתקת כל הזמן ביקורת 3: הסוללה לא מחזיקה נסיעה ביקורת 4: האפליקציה קרסה בזמן הצימוד ביקורת 5: הכבל קצר מדי לשימוש בזמן טעינה </complaints>
Try it
Example replyReplies vary between models and runs.

חסרה

  • ביקורת 4: הסוללה מתרוקנת מהר

אם הבדיקה אומרת "חסרה", הריצו מחדש את שלב 1 או הוסיפו את הפריט החסר ידנית לפני ששלב 2 רץ.

שרשרת בקוד

בקוד, שרשרת היא רצף של קריאות שבו כל פרומפט נבנה מהתשובה הקודמת. הגרסה הזו משתמשת ב-Anthropic Python SDK; אותו מבנה עובד עם כל ספק.

import json
import anthropic

client = anthropic.Anthropic()
MODEL = "your-model-id"  # e.g. from your provider's model list

def ask(prompt):
    response = client.messages.create(
        model=MODEL,
        max_tokens=1024,
        messages=[{"role": "user", "content": prompt}],
    )
    return response.content[0].text

reviews = open("reviews.txt", encoding="utf-8").read()

complaints = ask(
    "List every complaint in the reviews inside the <reviews> tags. Ignore praise. "
    'Return a JSON array of objects with the keys "review" and "complaint". '
    "Return only the JSON, with no code fence.\n\n"
    f"<reviews>\n{reviews}\n</reviews>"
)
json.loads(complaints)  # raises an error here if step 1 did not return valid JSON

themes = ask(
    "Group these complaints into themes. Return only a JSON array with the keys "
    '"theme", "count" and "reviews", sorted by count, highest first.\n\n'
    f"<complaints>\n{complaints}\n</complaints>"
)

note = ask(
    "Write a note of at most four sentences to the product team based on these "
    f"themes. Lead with the most common one.\n\n<themes>\n{themes}\n</themes>"
)
print(note)

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

שרשור באפליקציית צ'אט

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

שרשור בהשוואה לטכניקות קרובות

Chain of thought הוא נימוק שנכתב בתוך תשובה אחת; שרשרת פרומפטים היא כמה תשובות, כשאתם שולטים במה שעובר ביניהן. השתיים משתלבות היטב: כל שלב בשרשרת יכול לבקש נימוק שלב אחרי שלב.

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

שאלות נפוצות

מה זה prompt chaining?

Prompt chaining הוא טכניקה שבה מפרקים משימה לכמה פרומפטים שרצים אחד אחרי השני, והפלט של כל פרומפט מוכנס לבא אחריו. למשל, פרומפט אחד מחלץ תלונות מביקורות, שני מקבץ אותן לנושאים, ושלישי כותב דוח מהנושאים.

מה ההבדל בין prompt chaining ל-chain of thought?

Chain of thought קורה בתוך תשובה אחת: המודל כותב את הנימוק שלו לפני התשובה. Prompt chaining משתמש בכמה קריאות נפרדות, ואתם או הקוד שלכם מעבירים את התוצאה של אחת לבאה. אפשר לבדוק, לתקן או להריץ מחדש כל שלב בודד בשרשרת, מה שאי אפשר לעשות עם נימוק בתוך תשובה אחת.

אפשר לעשות prompt chaining ב-ChatGPT או ב-Claude בלי קוד?

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

מתי להשתמש ב-prompt chaining במקום בפרומפט אחד?

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

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל