דלג לתוכן הראשי
פרויקט זה בשלב בטא. מצאת באג? פתח issue ב-GitHub. יש שאלה או רעיון? שאל ב-Discussions — נשמח לשמוע ממך!
מה איכות התרגום בדף זה?

הגדרת קלט ופלט

workflow מנוהל עובד כמו פונקציית Python שרצה על מחשוב מרוחק. השוו פונקציה מקומית לאותו קוד כ-workflow:

Local Python

def my_workflow(circuits, shots=4096):
...
return {"counts": counts}

result = my_workflow(circuits=circuits, shots=1024)

ב-workflow מנוהל, run() היא הקריאה, get_arguments() נותנת ל-workflow את הפרמטרים שלו, ו-save_result() היא משפט ה-return שלו. מכיוון שה-workflow רץ כמשימה נפרדת על מחשוב מרוחק, הוא שונה מקריאה לפונקציה מקומית בשלוש דרכים:

Your local notebook, run_workflow_remotely.ipynb, calls run(args). A workflow runs an optional schema check, then creates the managed workflow job, source_files/my_workflow.py. The job reads its arguments with get_arguments(), runs your code, such as mapping, transpiling circuits, running primitives, and post-processing, and returns a result with save_result(). A workflow stores the result, and your notebook reads it with job.result().

קריאת ארגומנטים ב-workflow שלכם​

העבירו קלט ל-workflow מהמחברת המקומית שלכם:

run_workflow_remotely.ipynb

job = my_workflow.run(circuits=circuits, shots=1024)

כדי לאפשר זאת, ערכו את קוד ה-workflow כך שיביא ארגומנטים באמצעות get_arguments(), שמחזירה מילון שהמפתחות שלו הם שמות הארגומנטים:

source_files/my_workflow.py

from qiskit_serverless import get_arguments

arguments = get_arguments()
circuits = arguments["circuits"]
shots = arguments.get("shots", 4096)

המילון מכיל רק את הארגומנטים שההרצה העבירה, ולכן השתמשו ב-arguments.get() עם ערך ברירת מחדל עבור ארגומנטים אופציונליים. אפשר להשתמש בכל שם ארגומנט חוץ ממילות המפתח המוגנות config ו-function_size, כי run() משתמשת במילות המפתח האלה ישירות. run() גם דוחה את compute_profile. כדי לבחור משאבי חישוב, העבירו function_size.

כדי לקרוא את הגודל שבו המשימה רצה, קראו ל-get_function_size() בקוד ה-workflow שלכם:

source_files/my_workflow.py

from qiskit_serverless import get_function_size

size = get_function_size() # For example, "M"

אם ההרצה לא מעבירה function_size, הפונקציה get_function_size() מחזירה את גודל ברירת המחדל של ה-workflow. ראו בחירת גודל לכל הרצה.

סוגי ארגומנטים נתמכים​

כל ערך חייב להיות ניתן לסריאליזציה ל-JSON, או אובייקט שהלקוח יכול לקודד, כמו Circuit של Qiskit או מערך NumPy. מכיוון שהלקוח מקודד כל ארגומנט לפני ששולח את המשימה ו-get_arguments() מפענחת אותו בתוך ה-workflow, ה-workflow מקבל את אובייקט ה-Python המקורי.

הלקוח שולח int, float, str, bool, None, ורשימות או מילונים שלהם ללא שינוי. הוא מקודד אובייקטים אחרים, כמו QuantumCircuit, numpy.ndarray או מספר complex, כמילון עם תג __type__ ו-__value__. אתם צריכים את הצורה הזו כשכותבים סכמת ארגומנטים.

מכיוון שב-JSON אין מקבילה לחלק מהסוגים, הסוגים האלה משתנים במהלך הקידוד. Tuples מגיעים כרשימות, מפתחות של מילון מגיעים כמחרוזות, ומספרים שלמים של NumPy כמו np.int64 מגיעים כ-int. אם הלקוח לא יכול לקודד ערך, כמו bytes או np.float32, הפונקציה run() מעלה TypeError ולא יוצרת משימה.

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

מגבלות גודל​

הארגומנטים של הרצה אחת יכולים להגיע עד 32 MB אחרי הקידוד. לדוגמה, Circuit אחד של 100 Qubits בעומק 100 מקודד לכ-39 KB, ולכן הרצה אחת יכולה לקבל אצווה של כ-800 Circuits כאלה. עבור קלט גדול יותר, העלו קובץ והעבירו את שמו כארגומנט.

שמירת תוצאות​

השתמשו ב-save_result() בסוף ה-workflow כדי להחזיר תוצאה למחברת שלכם. קראו את התוצאה במחברת באמצעות job.result():

run_workflow_remotely.ipynb

result = job.result()

כדי לאפשר זאת, קראו ל-save_result() בקוד ה-workflow שלכם:

source_files/my_workflow.py

from qiskit_serverless import save_result

if not save_result({"counts": counts, "circuit": isa_circuit}):
raise ValueError("The result could not be encoded.")

save_result() מקודדת את התוצאה באותו אופן שבו הלקוח מקודד ארגומנטים, ו-job.result() מפענחת אותה. לכן תוצאה יכולה להכיל את סוגי הארגומנטים הנתמכים, כמו Circuits, מערכי NumPy והתוצאה של משימת primitive, עם אותם שינויי סוגים.

  • בדקו את ערך ההחזרה. אם save_result() לא מצליחה לקודד את הערך, היא רושמת אזהרה ללוג ומחזירה False במקום להעלות שגיאה. בלי בדיקה, המשימה יכולה להסתיים בסטטוס DONE וללא תוצאה.

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

  • מילון ריק פירושו שאין תוצאה. אם ה-workflow אף פעם לא קורא ל-save_result(), הפונקציה job.result() מחזירה {}.

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

שיטה מומלצת: אימות ארגומנטים באמצעות סכמה​

כשיטה מומלצת, צרפו JSON Schema לכל workflow שמקבל ארגומנטים. הסכמה מתארת את הארגומנטים שה-workflow מקבל, וה-workflow בודק מולה את הארגומנטים של כל הרצה לפני שהוא יוצר את המשימה. אם הארגומנטים לא תואמים, run() נכשלת מיד עם שגיאה ששמה את השדה הפגום, וה-workflow לא יוצר משימה. בלי סכמה, ארגומנטים פגומים מגיעים ל-workflow אחרי שהמשימה מתחילה, וה-workflow מתעלם משם ארגומנט שנכתב בטעות.

הגדירו את הסכמה באמצעות arguments_schema כשאתם מעלים את ה-workflow. העבירו מילון, לא מחרוזת JSON:

run_workflow_remotely.ipynb

from qiskit_ibm_catalog import ManagedWorkflow, ManagedWorkflowClient

arguments_schema = {
"type": "object",
"additionalProperties": False,
"required": ["circuits"],
"properties": {
"circuits": {
"type": "array",
"minItems": 1,
"items": {"$ref": "#/$defs/circuit"},
},
"shots": {"type": "integer", "minimum": 1, "maximum": 100000},
"backend_name": {"type": "string", "minLength": 1},
},
"$defs": {
"circuit": {
"type": "object",
"required": ["__type__", "__value__"],
"properties": {
"__type__": {"const": "QuantumCircuit"},
"__value__": {"type": "string"},
},
}
},
}

client = ManagedWorkflowClient()

my_workflow = client.upload(
ManagedWorkflow(
title="my-workflow",
entrypoint="my_workflow.py",
working_dir="./source_files/",
arguments_schema=arguments_schema,
)
)

שימו לב לנקודות הבאות כשאתם כותבים סכמה:

  • תארו את הצורה המקודדת של אובייקטי Qiskit ו-NumPy. הסכמה בודקת את הארגומנטים כפי שהלקוח שולח אותם, ולכן Circuit הוא אובייקט כמו {"__type__": "QuantumCircuit", "__value__": "<base64-encoded QPY>"}, ולא מחרוזת או מערך. בדקו את התג __type__, והתייחסו ל-__value__ כמחרוזת אטומה. סכמה שמתארת Circuit כמחרוזת דוחה כל הרצה תקינה.

  • הגדירו "additionalProperties": false. בלי ההגדרה הזו, ה-workflow מתעלם משם ארגומנט שנכתב בטעות, כמו shotz, בלי אזהרה, ורץ עם ערך ברירת המחדל. הצהירו על כל ארגומנט שה-workflow מקבל לפני שאתם מפעילים את ההגדרה הזו.

  • סמנו ארגומנטים כנדרשים. הוסיפו ל-required כל ארגומנט שה-workflow קורא בלי ערך ברירת מחדל.

אם הארגומנטים לא תואמים לסכמה, הודעת השגיאה ממנה את הכלל ואת מיקום הערך הפגום:

'type' validation failed, schema requires 'integer': rejected value '4096'
path: ['shots']

סכמה בודקת את הסוג, הצורה והטווח של כל ארגומנט. סכמה לא יכולה לבדוק אם שני ארגומנטים תקינים סותרים זה את זה, או אם Circuit מתאים ל-Backend. השאירו את הבדיקות האלה בקוד ה-workflow.

עדכון או הסרה של סכמה​

  • כדי להחליף את הסכמה, הגדירו arguments_schema חדשה והעלו את ה-workflow שוב.

  • כדי להסיר את הסכמה, העלו את ה-workflow עם arguments_schema={}.

  • אם מעלים את ה-workflow בלי arguments_schema, ה-workflow שומר את הסכמה שנשמרה.

כדי לראות את הסכמה שבתוקף, קראו את my_workflow.arguments_schema. ערך None פירושו שלא workflow אין סכמה.

בדיקת ארגומנטים לפני ההרצה​

קראו ל-validate_arguments() כדי לבדוק קבוצת ארגומנטים מול הסכמה בלי להתחיל משימה:

run_workflow_remotely.ipynb

my_workflow.validate_arguments({"circuits": [circuit], "shots": 1024})
# {'valid': True}

אם הארגומנטים אינם תקינים, validate_arguments() מעלה QiskitServerlessException עם אותה הודעה ש-run() מחזירה עבור הארגומנטים האלה. אם ל-workflow אין סכמה, כל ארגומנטים תקינים. תוצאה תקינה לא מבטיחה ש-run() תצליח, כי run() בודקת גם מגבלות אחרות, כמו מספר המשימות הפעילות.

כללי סכמה​

workflow מנוהל דוחה את ההעלאה אם הסכמה מפרה אחד מהכללים הבאים:

  • הסכמה יכולה להגיע עד 64 KiB, עם עד 64 רמות קינון ועד 200 תת-סכמות.

  • הפניות חייבות להצביע לתוך אותה סכמה, כמו #/$defs/circuit, וכל הפניה חייבת להיפתר. הפניות ל-URL או לקבצים אינן מותרות.

  • הסכמה חייבת להיות אובייקט או ערך בוליאני.

הימנעו גם מהבעיות הבאות, שההעלאה לא תופסת:

  • כמתים מקוננים ב-pattern. תבנית כמו ^(a+)+$ יכולה לקחת זמן רב מאוד להערכה. workflow מפסיק את האימות אחרי מגבלת זמן CPU ודוחה את ההרצה. כתבו תבניות בלי כמת סביב קבוצה שכבר מכילה כמת, כמו ^ibm_[a-z0-9_]{1,40}$.

  • false כסכמה. הסכמה false דוחה כל הרצה. כדי להסיר אימות, השתמשו ב-{}.

פתרון בעיות בסכמה​

בעיהסיבה
כל הרצה נדחית בגלל ארגומנט Circuit.הסכמה מתארת את ה-Circuit כמחרוזת או כמערך. תארו אותו כאובייקט עם תג __type__.
הרצות תקינות נדחות.additionalProperties הוא false, והסכמה לא מצהירה על ארגומנט שההרצה מעבירה. ה-path בשגיאה ממנה את הארגומנט.
הרצות לא תקינות לא נדחות.ל-workflow אין סכמה. בדקו את my_workflow.arguments_schema.
שום הרצה לא נבדקת, למרות שהגדרתם סכמה.הסכמה הועברה כמחרוזת JSON. העבירו מילון.
ההעלאה נכשלת עם שגיאת 400.הסכמה מפרה אחד מכללי הסכמה.
השגיאה אומרת שהאימות לקח יותר מדי זמן CPU.ל-pattern יש כמתים מקוננים. כתבו את התבנית מחדש.