Retry decorator בפייתון

לא מזמן יצא לי לכתוב קוד בפייתון. הקוד משתמש ב-API של openAI ולפעמים ה-API הזה קצת מפשל. הוא מחזיר לי שגיאה ואומר שהגזמתי עם הקריאות, או שפתאום לא זמין. זה לא רק openAI אל גם למשל Vertex של גוגל שבו אני קורא לג׳מיני, ה-LLM שלהם. בתיעוד שלהם כתוב למשל, שאם מקבלים 503 או אפילו 500, צריכים לנסות שוב. לפעמים API כושלים בגלל סיבות שונות ואז, אם הפעולה שלכם תלויה ב-API אחר, כדאי לנסות שוב.

כשישבתי לי בנחת ליצור את הקוד שלי שיוצר קשר ל-API של ג׳מיני, חשבתי על זה וביקשתי מקופיילוט לייצר לי קוד שיבצע retry בהתאם לשגיאה. כמובן שהוא יצר לי קוד בקלות ובערימות. אבל אז ב-pull requesy, כשידידי מומחה הפייתון רועי בן יוסף בחן את הקוד הוא אמר לי: ״תגיד, למה גרמת ל-LLM ליצור ערימה של קוד שעושה בדיוק מה ש tenacity decorator עושה?״ והתגובה שלי היתה ????????????.

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

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

def simple_decorator(func):
    def wrapper():
        print("Before the function call")
        func()
        print("After the function call")
    return wrapper

@simple_decorator
def say_hello():
    print("Hello!")

say_hello()

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

Before the function call
Hello!
After the function call

יש לנו הרבה דקורטורים וספריות שונות. אחת מהם היא tenacity שזה באנגלית עקשנות. לא, אין קשר ל Tenacious D שהיא הלהקה של ג׳ק בלאק, מלבד שגם השם שלה מגיע מעקשנות ( ˶ˆᗜˆ˵ ).

This image was originally posted to Flickr by spartus at https://www.flickr.com/photos/60842486@N00/408844986. It was reviewed on 1 April 2008 by FlickreviewR and was confirmed to be licensed under the terms of the cc-by-2.0.
This image was originally posted to Flickr by spartus at https://www.flickr.com/photos/60842486@N00/408844986. It was reviewed on 1 April 2008 by FlickreviewR and was confirmed to be licensed under the terms of the cc-by-2.0.

עם tenacity שהיא ספריה אולטרא פופולרית אפשר לעשות retry בקלות רבה. הבה ונראה איך זה עובד! אני אשתמש ב-uv. אם אתם לא מכירים, בהחלט כדאי לקחת את מנהל הסביבה הזה לסיבוב מהיר. בפוסט הזה כתבתי על uv – המרענן הרשמי של פייתון הקיץ הזה 🙂 ניצור פרויקט פייתון ראשוני ונוסיף אליו את tanacity:

uv init
uv add tenacity
uv venv

��כשיו אפשר להשתמש ב-tenacity בלי בעיה. הנה הקוד:

import time
from tenacity import retry, stop_after_attempt, wait_fixed, retry_if_exception_type

# Simulate a custom exception
class TemporaryAPIError(Exception):
    pass

# Retry decorator
@retry(
    stop=stop_after_attempt(5),                   # Max 5 attempts
    wait=wait_fixed(2),                           # Wait 2 seconds between attempts
    retry=retry_if_exception_type(TemporaryAPIError)  # Only retry for this exception type
)
def call_api():
    print("Calling the API...")
    # Always fail
    raise TemporaryAPIError("API is always unavailable.")

# Test the API call
try:
    result = call_api()
    print(result)
except Exception as e:
    print(f"Failed after retries: {e}")

מה שמעניין אותנו הוא ה-Retry decorator. תראו כמה פשוט ונחמד הוא. אני קורא ל-API שתמיד נכשל. הוא יחכה שתי שניות וינסה שוב, 5 פעמים. שימו לב שאני יכול להגדיר לו את סוג השגיאה לניסיון מחדש. במידה והוא מקבל את השגיאה הזו מעבר למספר הפעמים שהגדרתי, הוא ייכשל. זה הפלט שאני אקבל:

Calling the API...
Calling the API...
Calling the API...
Calling the API...
Calling the API...
Failed after retries: RetryError[<Future at 0x100ff9f30 state=finished raised TemporaryAPIError>]

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

פוסטים נוספים שכדאי לקרוא

יסודות בתכנות

backward compatibility ו forward compatibility

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

בינה מלאכותית

זיהוי אנומליות עם tflite

איך משתמשים במידע מחיישנים של IoT ובונים איתו מודל tflite. דרך ההבנה הזו נלמד על למידת מכונה.

גלילה לראש העמוד