กำหนดอินพุตและเอาต์พุต
เวิร์กโฟลว์แบบ managed ทำงานเหมือนฟังก์ชัน Python ที่รันบนคอมพิวต์ระยะไกล เปรียบเทียบฟังก์ชันในเครื่องกับโค้ดเดียวกันที่เป็นเวิร์กโฟลว์:
Local Python
def my_workflow(circuits, shots=4096):
...
return {"counts": counts}
result = my_workflow(circuits=circuits, shots=1024)
ในเวิร์กโฟลว์แบบ managed run() คือการเรียกใช้ get_arguments() ให้พารามิเตอร์แก่เวิร์กโฟลว์ และ save_result() คือคำสั่ง return ของเวิร์กโฟลว์ เนื่องจากเวิร์กโฟลว์รันเป็นงานแยกต่างหากบนคอมพิวต์ระยะไกล จึงต่างจากการเรียกฟังก์ชันในเครื่องสามประการ:
-
ไคลเอนต์เข้ารหัสอาร์กิวเมนต์และผลลัพธ์ ทุกค่าต้องเป็นค่าที่ไคลเอนต์เข้ารหัสได้ และบางชนิดจะเปลี่ยนไป ดู อ่านอาร์กิวเมนต์ในเวิร์กโฟลว์ของคุณ
-
การเรียกไม่รอผล
run()คืนงานทันที และคุณอ่านผลลัพธ์ภายหลังด้วยjob.result()ดู บันทึกผลลัพธ์ -
ไม่มีอะไรตรวจสอบการเรียก ฟังก์ชัน Python จะปฏิเสธอาร์กิวเมนต์แบบ keyword ที่ไม่รู้จัก แต่เวิร์กโฟลว์จะเพิกเฉยต่ออาร์กิวเมนต์นั้น เว้นแต่คุณจะแนบ schema ดู แนวปฏิบัติที่ดี: ตรวจสอบอาร์กิวเมนต์ด้วย schema
อ่านอาร์กิวเมนต์ในเวิร์กโฟลว์ของคุณ
ส่งอินพุตไปยังเวิร์กโฟลว์ของคุณจากโน้ตบุ๊กในเครื่อง:
run_workflow_remotely.ipynb
job = my_workflow.run(circuits=circuits, shots=1024)
เพื่อให้ใช้งานได้ ให้แก้ไขโค้ดเวิร์กโฟลว์ของคุณให้ดึงอาร์กิวเมนต์ด้วย 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() ในโค้ดเวิร์กโฟลว์ของคุณ:
source_files/my_workflow.py
from qiskit_serverless import get_function_size
size = get_function_size() # For example, "M"
ถ้าการรันไม่ได้ส่ง function_size แล้ว get_function_size() จะคืนขนาดเริ่มต้นของเวิร์กโฟลว์ ดู เลือกขนาดสำหรับแต่ละการรัน
ชนิดอาร์กิวเมนต์ที่รองรับ
ทุกค่าต้อง serialize เป็น JSON ได้ หรือเป็นอ็อบเจกต์ที่ไคลเอนต์เข้ารหัสได้ เช่น Qiskit circuit หรืออาร์เรย์ NumPy เนื่องจากไคลเอนต์เข้ารหัสแต่ละอาร์กิวเมนต์ก่อนส่งงาน และ get_arguments() ถอดรหัสภายในเวิร์กโฟลว์ เวิร์กโฟลว์จึงได้รับอ็อบเจกต์ Python ต้นฉบับ
ไคลเอนต์ส่ง int, float, str, bool, None และลิสต์หรือดิกชันนารีของชนิดเหล่านี้โดยไม่เปลี่ยนแปลง ส่วนอ็อบเจกต์อื่น เช่น QuantumCircuit, numpy.ndarray หรือจำนวน complex จะถูกเข้ารหัสเป็นดิกชันนารีที่มีแท็ก __type__ และ __value__ คุณต้องใช้รูปแบบนี้เมื่อเขียน schema ของอาร์กิวเมนต์
เนื่องจาก JSON ไม่มีชนิดที่เทียบเท่ากับบางชนิด ชนิดเหล่านี้จึงเปลี่ยนไประหว่างการเข้ารหัส tuple จะมาถึงเป็นลิสต์ คีย์ของดิกชันนารีจะมาถึงเป็นสตริง และจำนวนเต็ม NumPy เช่น np.int64 จะมาถึงเป็น int ถ้าไคลเอนต์เข้ารหัสค่าไม่ได้ เช่น bytes หรือ np.float32 แล้ว run() จะ raise TypeError และไม่สร้างงาน
อ็อบเจกต์บางอย่างส่งเป็นอาร์กิวเมนต์ไม่ได้ ตัวอย่างเช่น ให้ส่งชื่อ backend เป็นสตริงแทนอ็อบเจกต์ Backend แล้วสร้าง backend ภายในเวิร์กโฟลว์ ดู รันงานควอนตัมจากเวิร์กโฟลว์
ขีดจำกัดขนาด
อาร์กิวเมนต์ของการรันหนึ่งครั้งมีขนาดได้สูงสุด 32 MB หลังเข้ารหัส ตัวอย่างเช่น circuit 100 qubit ที่มี depth 100 หนึ่งวงจรเข้ารหัสได้ประมาณ 39 KB ดังนั้นการรันครั้งเดียวรับ batch ของ circuit ลักษณะนี้ได้ประมาณ 800 วงจร สำหรับอินพุตที่ใหญ่กว่านี้ ให้อัปโหลดไฟล์แล้วส่งชื่อไฟล์เป็นอาร์กิวเมนต์
บันทึกผลลัพธ์
ใช้ save_result() ที่ท้ายเวิร์กโฟลว์ของคุณเพื่อส่งผลลัพธ์กลับไปยังโน้ตบุ๊ก อ่านผลลัพธ์ในโน้ตบุ๊กด้วย job.result():
run_workflow_remotely.ipynb
result = job.result()
เพื่อให้ใช้งานได้ ให้เรียก save_result() ในโค้ดเวิร์กโฟลว์ของคุณ:
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() ถอดรหัสผลลัพธ์ ผลลัพธ์จึงมีชนิดอาร์กิวเมนต์ที่รองรับ เช่น circuit อาร์เรย์ NumPy และผลลัพธ์ของงาน primitive ได้ โดยมีการเปลี่ยนแปลงชนิดแบบเดียวกัน
-
ตรวจสอบค่าที่คืนมา ถ้า
save_result()เข้ารหัสค่าไม่ได้ จะบันทึกคำเตือนและคืนค่าFalseแทนที่จะ raise ข้อผิดพลาด หากไม่ตรวจสอบ งานอาจจบด้วยสถานะDONEโดยไม่มีผลลัพธ์ -
เก็บเฉพาะ
save_result()ครั้งสุดท้าย การเรียกแต่ละครั้งจะแทนที่ผลลัพธ์ที่บันทึกไว้ หากต้องการส่งคืนหลายค่า ให้บันทึกรวมกันในดิกชันนารีเดียว หรือเขียนลงบันทึก (logs) -
ดิกชันนารีว่างหมายถึงไม่มีผลลัพธ์ ถ้าเวิร์กโฟลว์ไม่เคยเรียก
save_result()แล้วjob.result()จะคืน{}
หากต้องการส่งคืนไฟล์ เช่น อาร์เรย์ขนาดใหญ่หรือกราฟ ให้บันทึกไว้ในพื้นที่จัดเก็บไฟล์แล้วส่งคืนชื่อไฟล์ในผลลัพธ์
แนวปฏิบัติที่ดี: ตรวจสอบอาร์กิวเมนต์ด้วย schema
ตามแนวปฏิบัติที่ดี ให้แนบ JSON Schema กับทุกเวิร์กโฟลว์ที่รับอาร์กิวเมนต์ schema อธิบายอาร์กิวเมนต์ที่เวิร์กโฟลว์ยอมรับ และเวิร์กโฟลว์จะตรวจสอบอาร์กิวเมนต์ของทุกการรันกับ schema ก่อนสร้างงาน ถ้าอาร์กิวเมนต์ไม่ตรงกัน run() จะล้มเหลวทันทีพร้อมข้อผิดพลาดที่ระบุฟิลด์ที่ผิด และเวิร์กโฟลว์จะไม่สร้างงาน หากไม่มี schema อาร์กิวเมนต์ที่ไม่ถูกต้องจะไปถึงเวิร์กโฟลว์หลังจากงานเริ่มแล้ว และเวิร์กโฟลว์จะเพิกเฉยต่อชื่ออาร์กิวเมนต์ที่สะกดผิด
ตั้งค่า schema ด้วย arguments_schema เมื่ออัปโหลดเวิร์กโฟลว์ ส่งเป็นดิกชันนารี ไม่ใช่สตริง 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,
)
)
โปรดจำประเด็นต่อไปนี้เมื่อเขียน schema:
-
อธิบายรูปแบบที่เข้ารหัสแล้วของอ็อบเจกต์ Qiskit และ NumPy schema ตรวจสอบอาร์กิวเมนต์ตามที่ไคลเอนต์ส่ง ดังนั้น circuit จึงเป็นอ็อบเจกต์ เช่น
{"__type__": "QuantumCircuit", "__value__": "<base64-encoded QPY>"}ไม่ใช่สตริงหรืออาร์เรย์ ให้ตรวจสอบแท็ก__type__และถือว่า__value__เป็นสตริงทึบ (opaque) schema ที่อธิบาย circuit เป็นสตริงจะปฏิเสธทุกการรันที่ถูกต้อง -
ตั้งค่า
"additionalProperties": falseหากไม่ตั้งค่านี้ เวิร์กโฟลว์จะเพิกเฉยต่อชื่ออาร์กิวเมนต์ที่สะกดผิด เช่นshotzโดยไม่เตือน และรันด้วยค่าเริ่มต้น ให้ประกาศทุกอาร์กิวเมนต์ที่เวิร์กโฟลว์ยอมรับก่อนเปิดใช้การตั้งค่านี้ -
ทำเครื่องหมายอาร์กิวเมนต์ที่จำเป็น เพิ่มทุกอาร์กิวเมนต์ที่เวิร์กโฟลว์อ่านโดยไม่มีค่าเริ่มต้นลงใน
required
ถ้าอาร์กิวเมนต์ไม่ตรงกับ schema ข้อความข้อผิดพลาดจะระบุกฎและตำแหน่งของค่าที่ผิด:
'type' validation failed, schema requires 'integer': rejected value '4096'
path: ['shots']
schema ตรวจสอบชนิด รูปร่าง และช่วงของแต่ละอาร์กิวเมนต์ แต่ตรวจสอบไม่ได้ว่าอาร์กิวเมนต์ที่ถูกต้องสองตัวขัดแย้งกันหรือไม่ หรือ circuit เหมาะกับ backend หรือไม่ ให้เก็บการตรวจสอบเหล่านั้นไว้ในโค้ดเวิร์กโฟลว์
อัปเดตหรือลบ schema
-
หากต้องการแทนที่ schema ให้ตั้งค่า
arguments_schemaใหม่แล้วอัปโหลดเวิร์กโฟลว์อีกครั้ง -
หากต้องการลบ schema ให้อัปโหลดเวิร์กโฟลว์ด้วย
arguments_schema={} -
ถ้าคุณอัปโหลดเวิร์กโฟลว์โดยไม่ระบุ
arguments_schemaเวิร์กโฟลว์จะคง schema ที่เก็บไว้เดิม
หากต้องการดู schema ที่มีผลอยู่ ให้อ่าน my_workflow.arguments_schema ค่า None หมายความว่าเวิร์กโฟลว์ไม่มี schema
ตรวจสอบอาร์กิวเมนต์ก่อนรัน
เรียก validate_arguments() เพื่อตรวจสอบชุดอาร์กิวเมนต์กับ schema โดยไม่เริ่มงาน:
run_workflow_remotely.ipynb
my_workflow.validate_arguments({"circuits": [circuit], "shots": 1024})
# {'valid': True}
ถ้าอาร์กิวเมนต์ไม่ถูกต้อง validate_arguments() จะ raise QiskitServerlessException พร้อมข้อความเดียวกับที่ run() คืนสำหรับอาร์กิวเมนต์เหล่านั้น ถ้าเวิร์กโฟลว์ไม่มี schema อาร์กิวเมนต์ใดก็ถือว่าถูกต้อง ผลที่ถูกต้องไม่ได้รับประกันว่า run() จะสำเร็จ เพราะ run() ตรวจสอบขีดจำกัดอื่นด้วย เช่น จำนวนงานที่ทำงานอยู่
กฎของ schema
เวิร์กโฟลว์แบบ managed จะปฏิเสธการอัปโหลดถ้า schema ฝ่าฝืนกฎข้อใดข้อหนึ่งต่อไปนี้:
-
schema มีขนาดได้สูงสุด 64 KiB ซ้อนกันได้สูงสุด 64 ระดับ และมี subschema ได้สูงสุด 200 รายการ
-
reference ต้องชี้ไปภายใน schema เดียวกัน เช่น
#/$defs/circuitและทุก reference ต้องresolve ได้ ไม่อนุญาต reference ไปยัง URL หรือไฟล์ -
schema ต้องเป็นอ็อบเจกต์หรือบูลีน
นอกจากนี้ให้หลีกเลี่ยงปัญหาต่อไปนี้ ซึ่งการอัปโหลดตรวจไม่พบ:
-
quantifier ซ้อนกันใน
patternรูปแบบเช่น^(a+)+$อาจใช้เวลาประเมินนานมาก เวิร์กโฟลว์จะหยุดการตรวจสอบเมื่อเกินขีดจำกัดเวลา CPU และปฏิเสธการรัน ให้เขียนรูปแบบโดยไม่ใช้ quantifier ครอบกลุ่มที่มี quantifier อยู่แล้ว เช่น^ibm_[a-z0-9_]{1,40}$ -
falseเป็น schema schemafalseปฏิเสธทุกการรัน หากต้องการยกเลิกการตรวจสอบ ให้ใช้{}
แก้ปัญหา schema
| ปัญหา | สาเหตุ |
|---|---|
| ทุกการรันถูกปฏิเสธที่อาร์กิวเมนต์ circuit | schema อธิบาย circuit เป็นสตริงหรืออาร์เรย์ ให้อธิบายเป็นอ็อบเจกต์ที่มีแท็ก __type__ |
| การรันที่ถูกต้องถูกปฏิเสธ | additionalProperties เป็น false และ schema ไม่ได้ประกาศอาร์กิวเมนต์ที่การรันส่งมา path ในข้อผิดพลาดจะระบุอาร์กิวเมนต์นั้น |
| การรันที่ไม่ถูกต้องไม่ถูกปฏิเสธ | เวิร์กโฟลว์ไม่มี schema ตรวจสอบ my_workflow.arguments_schema |
| ไม่มีการตรวจสอบการรันเลย แม้ตั้ง schema แล้ว | ส่ง schema เป็นสตริง JSON ให้ส่งเป็นดิกชันนารี |
การอัปโหลดล้มเหลวด้วยข้อผิดพลาด 400 | schema ฝ่าฝืนหนึ่งในกฎของ schema |
| ข้อผิดพลาดระบุว่าการตรวจสอบใช้เวลา CPU มากเกินไป | pattern มี quantifier ซ้อนกัน ให้เขียนรูปแบบใหม่ |