Deinen ersten Managed Workflow bereitstellen
Paketversionen
Der Code auf dieser Seite wurde mit den folgenden Anforderungen entwickelt. Wir empfehlen, diese Versionen oder neuere zu verwenden.
qiskit[all]~=2.6.1
qiskit-serverless~=0.38.0
Verwende diese Seite, um einen Workflow hochzuladen, auszuführen und sein Ergebnis abzurufen. Der Beispiel-Workflow optimiert und simuliert einen Qiskit-Circuit. Er simuliert den Circuit auf klassischer Hardware und verbraucht daher keine QPU-Zeit.
Bevor du beginnst, installiere das Client-Paket und authentifiziere dich.
Um deinen eigenen Code mit Hilfe eines KI-Assistenten bereitzustellen, verwende die KI-Skills im Qiskit-Function-Templates-Repository.
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"qiskit": "qiskit", "qiskit_ibm_catalog": "qiskit-ibm-catalog", "qiskit_serverless": "qiskit-serverless"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
Einen Workflow schreiben
Die Ordnerstruktur erstellen
Ein Managed Workflow ist ein Ordner mit Python-Dateien und einer Entrypoint-Datei. Ein Managed Workflow lädt alles im Ordner hoch, bis zu 50 MB, und führt den Entrypoint als Skript aus. Da ein Workflow den gesamten Ordner hochlädt, bewahre deine lokalen Dateien, wie deploy.ipynb, außerhalb des Ordners auf. Erstelle das folgende Layout:
hello_world_project/
├── deploy.ipynb # Your local notebook: upload and run the workflow
└── source_files/ # The working directory that you upload
└── hello_world.py # The entrypoint
Den Hello-World-Entrypoint schreiben
Der Entrypoint liest einen Circuit, optimiert und simuliert ihn und speichert die Zählungen und die Zwei-Qubit-Tiefe. Speichere den folgenden Code als source_files/hello_world.py:
Wenn du diese Seite als Notebook liest, beginnt die Codezelle für hello_world.py mit dem Magic Command %%writefile. Wenn du diese Zelle ausführst, speichert sie den Code in der Datei, anstatt ihn auszuführen.
# This cell is hidden from users. It creates the working directory.
from pathlib import Path
Path("./source_files").mkdir(exist_ok=True)
%%writefile ./source_files/hello_world.py
from qiskit.primitives import StatevectorSampler
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_serverless import Job, get_arguments, save_result, update_status
# Read the arguments that you pass to run()
arguments = get_arguments()
circuit = arguments["circuit"]
shots = arguments.get("shots", 1024)
# Optimize the circuit. Printed text goes to the job's logs.
update_status(Job.OPTIMIZING_HARDWARE)
pass_manager = generate_preset_pass_manager(
optimization_level=1, basis_gates=["cz", "rz", "sx", "x"]
)
isa_circuit = pass_manager.run(circuit)
two_qubit_depth = isa_circuit.depth(lambda instruction: instruction.operation.num_qubits == 2)
print(f"Two-qubit depth after optimization: {two_qubit_depth}", flush=True)
# Simulate the circuit and return the counts
sampler = StatevectorSampler(seed=1234)
pub_result = sampler.run([isa_circuit], shots=shots).result()[0]
save_result({"counts": pub_result.data.meas.get_counts(), "two_qubit_depth": two_qubit_depth})
Writing ./source_files/hello_world.py
Der Entrypoint verwendet drei Funktionen aus qiskit_serverless:
-
get_arguments()gibt die Schlüsselwortargumente, die du anrun()übergibst, als Dictionary zurück. Jeder Wert muss JSON-serialisierbar sein oder ein Objekt, das der Client kodieren kann, etwa einQuantumCircuit. Kodierte Objekte kommen als dieselben Objekte an, die du übergeben hast. -
update_status(Job.OPTIMIZING_HARDWARE)setzt den detaillierten StatusRUNNING: OPTIMIZING_FOR_HARDWARE, den du während der Ausführung des Jobs sehen kannst. Siehe Fortschritt mit update_status() melden. -
save_result()speichert einen JSON-serialisierbaren Wert, den du später mitjob.result()liest. Der Workflow gibt die Zählungen als Dictionary und die Zwei-Qubit-Tiefe des optimierten Circuits als Ganzzahl zurück.
Alles, was der Workflow in die Standardausgabe schreibt, etwa die Zwei-Qubit-Tiefe, landet in den Logs des Jobs. Um Zeitstempel und Log-Level hinzuzufügen, verwende das Modul logging. Siehe Logs schreiben und Fehler behandeln.
Den Workflow hochladen
Führe in deinem lokalen Notebook den folgenden Code im Ordner hello_world_project aus. Der Code verbindet sich mit deinem gespeicherten Konto, definiert den Workflow und lädt ihn hoch. entrypoint ist die Datei, die der Workflow ausführt, und working_dir ist der Ordner, den du hochlädst:
from qiskit_ibm_catalog import ManagedWorkflow, ManagedWorkflowClient
client = ManagedWorkflowClient()
hello_world = ManagedWorkflow(
title="hello-world",
entrypoint="hello_world.py",
working_dir="./source_files/",
)
hello_world = client.upload(hello_world)
Den Workflow mit Eingaben ausführen
Erstelle einen Drei-Qubit-GHZ-Circuit, den du als Eingabe an hello_world übergibst:
from qiskit import QuantumCircuit
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure_all()
Führe hello_world mit dem Circuit und der Anzahl der Shots als Schlüsselwortargumente aus. Die Argumentnamen entsprechen den Schlüsseln, die der Entrypoint mit get_arguments() liest:
job = hello_world.run(circuit=circuit, shots=1024)
print(job.job_id)
54705348-5117-44b7-935b-e6986ef182fa
run() gibt einen Job zurück, nachdem der Workflow den Job in die Warteschlange gestellt hat. Es wartet nicht darauf, dass der Job läuft. Der Job läuft in der Cloud weiter, nachdem du deine Python-Sitzung geschlossen hast. Um ihn später wiederzufinden, liste deine letzten Jobs mit client.jobs() auf.
Status, Ergebnis und Logs abrufen
Unmittelbar nach dem Aufruf von run() ist der Status normalerweise QUEUED:
job.status()
'QUEUED'
Der Status wechselt von QUEUED zu INITIALIZING, RUNNING und dann DONE.
job.result() wartet, bis der Job endet, und gibt dann den Wert zurück, den der Workflow an save_result() übergeben hat:
job.result()
{'counts': {'111': 514, '000': 510}, 'two_qubit_depth': 2}
# This cell is hidden from users. It checks the result.
assert set(_["counts"]) <= {"000", "111"} # noqa: F821
assert sum(_["counts"].values()) == 1024 # noqa: F821
from qiskit.visualization import plot_histogram
plot_histogram(job.result()["counts"])
Du kannst die Logs lesen, während der Job läuft. Der Workflow lädt etwa alle 15 Sekunden neue Zeilen hoch. Die Logs enthalten die Zeile, die der Workflow ausgegeben hat:
print(job.logs())
Two-qubit depth after optimization: 2
# This cell is hidden from users. It checks the logs.
assert "Two-qubit depth after optimization" in job.logs()
Den Workflow aktualisieren
Um einen Workflow zu ändern, bearbeite seine Dateien und rufe upload() erneut mit demselben title auf. Der neue Upload ersetzt den früheren, und bereits gestartete Jobs sind davon nicht betroffen.
Felder wie arguments_schema und sizes_map behalten ihre gespeicherten Werte, wenn du sie im neuen Upload weglässt.
Nächste Schritte
- Eingaben und Ausgaben definieren, um zu erfahren, welche Argument- und Ergebnistypen ein Workflow unterstützt.
- Abhängigkeiten deklarieren, um weitere Python-Pakete in deinem Workflow zu verwenden.
- Quantenjobs aus einem Workflow ausführen, um deine Circuits auf einer QPU auszuführen, jede Phase zu melden und die QPU-Jobs zu verfolgen.
- Einen Managed Workflow ausführen, um alle Job-Status kennenzulernen, einen fehlgeschlagenen Job zu debuggen und einen Job später wiederzufinden.
- Um mit funktionierendem Code zu starten, stelle eine der Qiskit Function templates bereit oder passe eine Vorlage für deinen eigenen Workflow an.