Saltar al contenido principal
Este proyecto está en fase beta. ¿Encontraste un error? Abre un issue en GitHub. ¿Tienes una pregunta o una idea? Pregunta en Discussions — ¡nos encantaría tu opinión!
¿Cómo es la calidad de la traducción en esta página?

Despliega tu primer managed workflow

Versiones de los paquetes

El código de esta página se desarrolló con los siguientes requisitos. Recomendamos usar estas versiones o posteriores.

qiskit[all]~=2.6.1
qiskit-serverless~=0.38.0

Usa esta página para subir un workflow, ejecutarlo y obtener su resultado. El workflow de ejemplo optimiza y simula un circuito de Qiskit. Simula el circuito en hardware clásico, por lo que no consume tiempo de QPU.

Antes de empezar, instala el paquete cliente y autentícate.

Usa habilidades de IA (opcional)

Para desplegar tu propio código con ayuda de un asistente de IA, usa las habilidades de IA del repositorio de plantillas de Qiskit Function.

# 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")

Escribir un workflow​

Crear la estructura de carpetas​

Un managed workflow es una carpeta de archivos Python con un archivo de punto de entrada. Un managed workflow sube todo lo que hay en la carpeta, hasta 50 MB, y ejecuta el punto de entrada como un script. Como un workflow sube la carpeta completa, mantén tus archivos locales, como deploy.ipynb, fuera de la carpeta. Crea la siguiente estructura:

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

Escribir el punto de entrada hello world​

El punto de entrada lee un circuito, lo optimiza y lo simula, y guarda los conteos y la profundidad de dos qubits. Guarda el siguiente código como source_files/hello_world.py:

nota

Si lees esta página como un cuaderno, la celda de código de hello_world.py comienza con el comando mágico %%writefile. Cuando ejecutas esta celda, guarda el código en el archivo en lugar de ejecutarlo.

# 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

El punto de entrada usa tres funciones de qiskit_serverless:

  • get_arguments() devuelve como diccionario los argumentos con nombre que pasas a run(). Cada valor debe ser serializable en JSON, o un objeto que el cliente pueda codificar, como un QuantumCircuit. Los objetos codificados llegan como los mismos objetos que pasaste.

  • update_status(Job.OPTIMIZING_HARDWARE) establece el estado detallado RUNNING: OPTIMIZING_FOR_HARDWARE, que puedes ver mientras el trabajo se ejecuta. Consulta Informar del progreso con update_status().

  • save_result() almacena un valor serializable en JSON que lees más tarde con job.result(). El workflow devuelve los conteos como un diccionario y la profundidad de dos qubits del circuito optimizado como un entero.

Todo lo que el workflow escribe en la salida estándar, como la profundidad de dos qubits, va a los registros del trabajo. Para añadir marcas de tiempo y niveles de registro, usa el módulo logging. Consulta Escribir registros y gestionar errores.

Subir el workflow​

En tu cuaderno local, ejecuta el siguiente código desde la carpeta hello_world_project. El código se conecta con tu cuenta guardada, define el workflow y lo sube. entrypoint es el archivo que ejecuta el workflow, y working_dir es la carpeta que subes:

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)

Ejecutar el workflow con entradas​

Construye un circuito GHZ de tres qubits para pasarlo a hello_world como entrada:

from qiskit import QuantumCircuit

circuit = QuantumCircuit(3)
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure_all()

Ejecuta hello_world con el circuito y el número de shots como argumentos con nombre. Los nombres de los argumentos coinciden con las claves que el punto de entrada lee con get_arguments():

job = hello_world.run(circuit=circuit, shots=1024)
print(job.job_id)
54705348-5117-44b7-935b-e6986ef182fa

run() devuelve un Job después de que el workflow pone el trabajo en cola. No espera a que el trabajo se ejecute. El trabajo continúa en la nube después de que cierres tu sesión de Python. Para encontrarlo más tarde, lista tus trabajos recientes con client.jobs().

Obtener el estado, el resultado y los registros​

Inmediatamente después de llamar a run(), el estado suele ser QUEUED:

job.status()
'QUEUED'

El estado cambia de QUEUED a INITIALIZING, RUNNING y luego DONE.

job.result() espera hasta que el trabajo termina y luego devuelve el valor que el workflow pasó a save_result():

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"])

Output of the previous code cell

Puedes leer los registros mientras el trabajo se ejecuta. El workflow sube líneas nuevas aproximadamente cada 15 segundos. Los registros incluyen la línea que imprimió el workflow:

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()

Actualizar el workflow​

Para cambiar un workflow, edita sus archivos y llama de nuevo a upload() con el mismo title. La nueva subida reemplaza a la anterior, y los trabajos que ya comenzaron no se ven afectados.

Campos como arguments_schema y sizes_map conservan sus valores almacenados cuando los omites en la nueva subida.

Próximos pasos​

Recomendaciones