첫 번째 관리형 워크플로 배포하기
패키지 버전
이 페이지의 코드는 다음 요구 사항을 사용하여 개발되었습니다. 이 버전 또는 그 이상의 버전을 사용하는 것을 권장합니다.
qiskit[all]~=2.6.1
qiskit-serverless~=0.38.0
이 페이지에서는 워크플로를 업로드하고, 실행하고, 결과를 가져오는 방법을 설명합니다. 예제 워크플로는 Qiskit Circuit을 최적화하고 시뮬레이션합니다. 고전 하드웨어에서 Circuit을 시뮬레이션하므로 QPU 시간을 사용하지 않습니다.
시작하기 전에 클라이언트 패키지를 설치하고 인증하세요.
AI 어시스턴트의 도움을 받아 자신의 코드를 배포하려면 Qiskit Function 템플릿 저장소의 AI 스킬을 사용하세요.
# 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")
워크플로 작성하기
폴더 구조 만들기
관리형 워크플로는 하나의 진입점 파일이 있는 Python 파일 폴더입니다. 관리형 워크플로는 폴더 안의 모든 내용을 최대 50 MB까지 업로드하고, 진입점을 스크립트로 실행합니다. 워크플로는 폴더 전체를 업로드하므로 deploy.ipynb 같은 로컬 파일은 폴더 밖에 두세요. 다음과 같은 구조를 만드세요.
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
hello world 진입점 작성하기
진입점은 Circuit을 읽고, 최적화하고 시뮬레이션한 다음, 카운트와 두 Qubit 깊이를 저장합니다. 다음 코드를 source_files/hello_world.py로 저장하세요.
이 페이지를 노트북으로 읽는 경우, hello_world.py의 코드 셀은 %%writefile 매직 명령어로 시작합니다. 이 셀을 실행하면 코드를 실행하는 대신 파일에 저장합니다.
# 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
진입점은 qiskit_serverless의 세 가지 함수를 사용합니다.
-
get_arguments()는run()에 전달한 키워드 인수를 딕셔너리로 반환합니다. 각 값은 JSON 직렬화가 가능하거나QuantumCircuit처럼 클라이언트가 인코딩할 수 있는 객체여야 합니다. 인코딩된 객체는 전달한 것과 동일한 객체로 도착합니다. -
update_status(Job.OPTIMIZING_HARDWARE)는 작업이 실행되는 동안 확인할 수 있는 세부 상태RUNNING: OPTIMIZING_FOR_HARDWARE를 설정합니다. update_status()로 진행 상황 보고하기를 참조하세요. -
save_result()는 나중에job.result()로 읽을 수 있는 JSON 직렬화 가능한 값을 저장합니다. 이 워크플로는 카운트를 딕셔너리로, 최적화된 Circuit의 두 Qubit 깊이를 정수로 반환합니다.
워크플로가 표준 출력에 쓰는 모든 내용(예: 두 Qubit 깊이)은 작업의 로그로 전달됩니다. 타임스탬프와 로그 수준을 추가하려면 logging 모듈을 사용하세요. 로그 작성 및 오류 처리를 참조하세요.
워크플로 업로드하기
로컬 노트북에서 hello_world_project 폴더에서 다음 코드를 실행하세요. 이 코드는 저장된 계정으로 연결하고, 워크플로를 정의한 다음 업로드합니다. entrypoint는 워크플로가 실행하는 파일이고, working_dir는 업로드할 폴더입니다.
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)
입력을 사용하여 워크플로 실행하기
hello_world에 입력으로 전달할 세 Qubit GHZ Circuit을 구성합니다.
from qiskit import QuantumCircuit
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure_all()
Circuit과 샷 수를 키워드 인수로 사용하여 hello_world를 실행합니다. 인수 이름은 진입점이 get_arguments()로 읽는 키와 일치합니다.
job = hello_world.run(circuit=circuit, shots=1024)
print(job.job_id)
54705348-5117-44b7-935b-e6986ef182fa
run()은 워크플로가 작업을 대기열에 넣은 후 Job을 반환합니다. 작업이 실행될 때까지 기다리지 않습니다. Python 세션을 닫은 후에도 작업은 클라우드에서 계속됩니다. 나중에 다시 찾으려면 client.jobs()로 최근 작업을 나열하세요.
상태, 결과, 로그 가져오기
run()을 호출한 직후 상태는 보통 QUEUED입니다.
job.status()
'QUEUED'
상태는 QUEUED에서 INITIALIZING, RUNNING을 거쳐 DONE으로 바뀝니다.
job.result()는 작업이 끝날 때까지 기다린 다음, 워크플로가 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"])
작업이 실행되는 동안 로그를 읽을 수 있습니다. 워크플로는 약 15초마다 새 줄을 업로드합니다. 로그에는 워크플로가 출력한 줄이 포함됩니다.
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()
워크플로 업데이트하기
워크플로를 변경하려면 파일을 수정한 다음 같은 title로 upload()를 다시 호출하세요. 새 업로드가 이전 업로드를 대체하며, 이미 시작된 작업에는 영향이 없습니다.
arguments_schema와 sizes_map 같은 필드는 새 업로드에서 생략하면 저장된 값을 유지합니다.
다음 단계
- 입력과 출력 정의하기에서 워크플로가 지원하는 인수 및 결과 유형을 알아보세요.
- 종속성 선언하기에서 워크플로에 더 많은 Python 패키지를 사용하는 방법을 알아보세요.
- 워크플로에서 양자 작업 실행하기에서 Circuit을 QPU에서 실행하고, 각 단계를 보고하고, QPU 작업을 추적하는 방법을 알아보세요.
- 관리형 워크플로 실행하기에서 모든 작업 상태를 알아보고, 실패한 작업을 디버그하고, 나중에 작업을 찾는 방법을 알아보세요.
- 동작하는 코드로 시작하려면 Qiskit Function 템플릿 중 하나를 배포하거나, 템플릿을 자신의 워크플로에 맞게 수정하세요.