メインコンテンツへスキップ
このプロジェクトはベータ版です。バグを見つけましたか?GitHub Issueを開く。質問やアイデアがありますか?Discussionsで質問する — フィードバックをお待ちしています!
このページの翻訳品質はいかがですか?

入力と出力の定義

マネージド・ワークフローは、リモートのコンピュート上で実行される Python 関数のように動作します。ローカル関数と、同じコードをワークフローにしたものを比較します。

Local Python

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

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

マネージド・ワークフローでは、run() が呼び出し、get_arguments() がワークフローにパラメーターを渡し、save_result() がその return 文に相当します。ワークフローはリモートのコンピュート上で別のジョブとして実行されるため、ローカル関数の呼び出しとは次の3点で異なります。

  • クライアントが引数と結果をエンコードします。 各値は、クライアントがエンコードできるものでなければならず、一部の型は変化します。ワークフローでの引数の読み取りを参照してください。

  • 呼び出しは待機しません。 run() はジョブをすぐに返し、結果は後で job.result() で読み取ります。結果の保存を参照してください。

  • 呼び出しは何もチェックされません。 Python 関数は未知のキーワード引数を拒否しますが、ワークフローはスキーマを添付しない限りそれを無視します。ベストプラクティス:スキーマで引数を検証するを参照してください。

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

ワークフローでの引数の読み取り​

ローカルのノートブックから、ワークフローに入力を渡します。

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() はワークフローのデフォルトのサイズを返します。実行ごとのサイズの選択を参照してください。

サポートされている引数の型​

各値は、JSON シリアライズ可能であるか、Qiskit の回路や NumPy 配列など、クライアントがエンコードできるオブジェクトでなければなりません。クライアントはジョブを送信する前に各引数をエンコードし、get_arguments() がワークフロー内でそれをデコードするため、ワークフローは元の Python オブジェクトを受け取ります。

クライアントは、int、float、str、bool、None、およびこれらのリストや辞書を、そのまま送信します。QuantumCircuit、numpy.ndarray、complex 数などの他のオブジェクトは、__type__ タグと __value__ を持つ辞書としてエンコードします。引数スキーマを作成する際には、この形式が必要です。

JSON には一部の型に相当するものがないため、これらの型はエンコード時に変化します。タプルはリストとして、辞書のキーは文字列として、np.int64 などの NumPy 整数は int として届きます。bytes や np.float32 など、クライアントが値をエンコードできない場合、run() は TypeError を発生させ、ジョブを作成しません。

一部のオブジェクトは引数として渡せません。たとえば、バックエンドは Backend オブジェクトではなく、その名前を文字列として渡し、ワークフロー内でバックエンドを作成します。ワークフローから量子ジョブを実行するを参照してください。

サイズの上限​

1回の実行の引数は、エンコード後に最大 32 MB までです。たとえば、深さ 100 の100量子ビット回路1つは約 39 KB にエンコードされるため、1回の実行で約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() がそれをデコードします。したがって、結果には、回路、NumPy 配列、プリミティブジョブの結果など、サポートされている引数の型を含めることができ、同じ型の変化が生じます。

  • 戻り値を確認してください。 save_result() が値をエンコードできない場合、エラーを発生させる代わりに、警告をログに記録して False を返します。確認しないと、ジョブが結果なしで DONE ステータスで終了することがあります。

  • 最後の save_result() のみが保存されます。 呼び出しのたびに、保存された結果が置き換えられます。複数の値を返すには、1つの辞書にまとめて保存するか、ログに書き込んでください。

  • 空の辞書は結果がないことを意味します。 ワークフローが save_result() を一度も呼び出さない場合、job.result() は {} を返します。

大きな配列やプロットなどのファイルを返すには、それらをファイルストレージに保存し、結果にその名前を含めて返します。

ベストプラクティス:スキーマで引数を検証する​

ベストプラクティスとして、引数を受け取るすべてのワークフローに JSON Schema を添付してください。スキーマはワークフローが受け付ける引数を記述し、ワークフローはジョブを作成する前に、実行ごとの引数をそれに照らして確認します。引数が一致しない場合、run() は不正なフィールドを示すエラーですぐに失敗し、ワークフローはジョブを作成しません。スキーマがないと、不正な引数はジョブの開始後にワークフローに到達し、ワークフローは誤ったスペルの引数名を無視します。

ワークフローをアップロードするときに、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,
)
)

スキーマを作成する際は、次の点に注意してください。

  • Qiskit と NumPy のオブジェクトのエンコード後の形式を記述してください。 スキーマは、クライアントが送信する形式で引数を確認します。そのため、回路は文字列や配列ではなく、{"__type__": "QuantumCircuit", "__value__": "<base64-encoded QPY>"} のようなオブジェクトです。__type__ タグを確認し、__value__ は不透明な文字列として扱ってください。回路を文字列として記述するスキーマは、有効な実行をすべて拒否します。

  • "additionalProperties": false を設定してください。 この設定がないと、ワークフローは shotz のような誤ったスペルの引数名を警告なしで無視し、デフォルト値で実行します。この設定を有効にする前に、ワークフローが受け付けるすべての引数を宣言してください。

  • 引数を必須に設定してください。 ワークフローがデフォルト値なしで読み取る各引数を、required に追加します。

引数がスキーマと一致しない場合、エラーメッセージには、違反したルールと不正な値の場所が示されます。

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

スキーマは、各引数の型、形状、範囲を確認します。2つの有効な引数が競合するかどうか、または回路がバックエンドに適合するかどうかは、スキーマでは確認できません。これらの確認は、ワークフローのコードで行ってください。

スキーマの更新または削除​

  • スキーマを置き換えるには、新しい arguments_schema を設定して、ワークフローを再度アップロードします。

  • スキーマを削除するには、arguments_schema={} を指定してワークフローをアップロードします。

  • arguments_schema を指定せずにワークフローをアップロードした場合、ワークフローは保存済みのスキーマを保持します。

有効なスキーマを確認するには、my_workflow.arguments_schema を読み取ります。値が None の場合、ワークフローにスキーマがないことを意味します。

実行前の引数の確認​

validate_arguments() を呼び出すと、ジョブを開始せずに、一連の引数をスキーマに照らして確認できます。

run_workflow_remotely.ipynb

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

引数が有効でない場合、validate_arguments() は、その引数に対して run() が返すのと同じメッセージの QiskitServerlessException を発生させます。ワークフローにスキーマがない場合、どの引数も有効です。run() はアクティブなジョブの数などの他の制限も確認するため、有効という結果が run() の成功を保証するものではありません。

スキーマのルール​

スキーマが次のいずれかのルールに違反する場合、マネージド・ワークフローはアップロードを拒否します。

  • スキーマは最大 64 KiB、ネストは最大64レベル、サブスキーマは最大200個までです。

  • 参照は、#/$defs/circuit のように同じスキーマ内を指す必要があり、すべての参照が解決できなければなりません。URL やファイルへの参照は使用できません。

  • スキーマは、オブジェクトまたはブール値でなければなりません。

また、アップロード時には検出されない次の問題も避けてください。

  • pattern 内のネストされた量指定子。 ^(a+)+$ のようなパターンは、評価に非常に長い時間がかかることがあります。ワークフローは、CPU 時間の上限を超えると検証を停止し、その実行を拒否します。^ibm_[a-z0-9_]{1,40}$ のように、すでに量指定子を含むグループの周りに量指定子を付けないパターンを書いてください。

  • スキーマとしての false。 スキーマ false は、すべての実行を拒否します。検証を無効にするには、{} を使用します。

スキーマのトラブルシューティング​

問題原因
回路の引数で、すべての実行が拒否される。スキーマが回路を文字列または配列として記述しています。__type__ タグを持つオブジェクトとして記述してください。
有効な実行が拒否される。additionalProperties が false で、スキーマが実行で渡される引数を宣言していません。エラーの path が引数を示します。
無効な実行が拒否されない。ワークフローにスキーマがありません。my_workflow.arguments_schema を確認してください。
スキーマを設定したのに、どの実行も確認されない。スキーマが JSON 文字列として渡されました。辞書を渡してください。
アップロードが 400 エラーで失敗する。スキーマがスキーマのルールのいずれかに違反しています。
検証に CPU 時間がかかりすぎたというエラーが出る。pattern にネストされた量指定子があります。パターンを書き直してください。