{
"cells": [
{
"cell_type": "markdown",
"id": "0544343d-7181-4016-a4f4-fb9df39c4bad",
"metadata": {},
"source": [
"# Running a Qiskit Function as a function\n",
"\n",
"In this tutorial, you’ll learn how to create and run a Qiskit Function using Qiskit Serverless. A Qiskit Function is a self-contained Python script that can execute quantum workloads remotely on serverless infrastructure.\n",
"We’ll start by writing a simple function that:\n",
"\n",
" - Builds a two-qubit quantum circuit to create a Bell state.\n",
" - Transpiles the circuit for a target backend.\n",
" - Runs the circuit using the Sampler primitive.\n",
" - Saves the results so they can be retrieved later.\n"
]
},
{
"cell_type": "markdown",
"id": "77472550-b841-4546-b475-032eb4b62f99",
"metadata": {},
"source": [
"#### Install dependencies\n",
"\n",
"Before we begin, make sure the required packages are installed in your notebook environment:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "aa3aa259-e7c9-48c0-baa8-fe958280b0ad",
"metadata": {},
"outputs": [],
"source": [
"%pip install qiskit qiskit-ibm-runtime qiskit-serverless"
]
},
{
"cell_type": "markdown",
"id": "66030e20-b384-4dcf-9c5f-7664f7ad1693",
"metadata": {},
"source": [
"\n",
"## Prep Work\n",
"\n",
"### Writing the Qiskit Function\n",
"\n",
"First, we need to write the function code and save it to a file called [function.py](./source_files/function.py). This function will contain the logic for our Qiskit Function. For this example, we will create a two-qubit quantum circuit that prepares a Bell state, measures the result, and saves the measured probability distribution.\n",
"\n",
"The code for the function is shown below:\n",
"\n",
"```python\n",
"from qiskit import QuantumCircuit\n",
"from qiskit.transpiler import generate_preset_pass_manager\n",
"from qiskit_ibm_runtime import SamplerV2 as Sampler\n",
"from qiskit_ibm_runtime.fake_provider import FakeVigoV2\n",
"from qiskit_serverless import save_result\n",
"\n",
"# all print statement will be available in job logs\n",
"print(\"Running function...\")\n",
"\n",
"# Step 1: Create a Bell-state circuit\n",
"circuit = QuantumCircuit(2)\n",
"circuit.h(0)\n",
"circuit.cx(0, 1)\n",
"circuit.measure_all()\n",
"\n",
"# Step 2: Transpile for a fake backend (for demonstration)\n",
"backend = FakeVigoV2()\n",
"pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
"isa_circuit = pm.run(circuit)\n",
"\n",
"# Step 3: Run the Sampler primitive\n",
"sampler = Sampler(backend)\n",
"quasi_dists = sampler.run([isa_circuit]).result()[0].data.meas.get_counts()\n",
"\n",
"\n",
"# Step 4: Save results so they can be retrieved later by calling `.result()`\n",
"save_result(quasi_dists)\n",
"print(\"Completed running function.\")\n",
"```\n",
"Now that we’ve written our Qiskit Function, the next step is to deploy it to the serverless environment so it can run remotely.\n",
"\n",
"### Deploying the function\n",
"\n",
"To run the function, we need to import the necessary classes and configure them. One of these classes is `ServerlessClient`, which is a client class for interacting with compute resources.\n",
"\n",
"The client stores configuration information about our compute resources, such as where they are located and how to connect to them. In this example, we will use a provider that is connected to a local Docker Compose setup. In this case, it allows us to run the function locally on our machine. If you want to run the function elsewhere, you will need to provide the corresponding host and authentication details."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "81dd7807-7180-4b87-bbf9-832b7cf29d69",
"metadata": {},
"outputs": [],
"source": [
"from qiskit_serverless import ServerlessClient\n",
"import os"
]
},
{
"cell_type": "markdown",
"id": "7ac24f62-8487-47fb-9805-66f2192953d4",
"metadata": {},
"source": [
"> ⚠ This provider is set up with default credentials to a test cluster intended to run on your machine. For information on setting up infrastructure on your local machine, check out the guide on [local infrastructure setup](https://qiskit.github.io/qiskit-serverless/deployment/local.html)."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "acdec789-4967-48ee-8f6c-8d2b0ff57e91",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"client = ServerlessClient(\n",
" token=os.environ.get(\"GATEWAY_TOKEN\", \"awesome_token\"),\n",
" instance=os.environ.get(\"GATEWAY_INSTANCE\", \"an_awesome_crn\"),\n",
" host=os.environ.get(\"GATEWAY_HOST\", \"http://localhost:8000\"),\n",
" # If you are using the kubernetes approach the URL must be http://localhost\n",
")\n",
"\n",
"client"
]
},
{
"cell_type": "markdown",
"id": "4dd85621-9ab0-4f34-9ab4-07ad773c5e00",
"metadata": {},
"source": [
"### Create a Qiskit Function object\n",
"\n",
"A `QiskitFunction` represents the function you want to run. It includes:\n",
"\n",
"- `title` - name of the Qiskit Function. This name will be used to identify and retrieve the function from the service.\n",
"- `entrypoint` - the name of the Python file that will be executed.\n",
"- `working_dir` - directory where your script is located (directory size must be less than 50MB). This is optional parameter and will be current folder by default.\n",
"\n",
"This tells the serverless system what code to run and what supporting files to include. Everything in `working_dir` will be packaged and shipped to the compute node.\n",
"\n",
"> ⚠ All content of `working_dir` will be shipped to cluster for execution\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "d51df836-3f22-467c-b637-5803145d5d8a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"QiskitFunction(my-first-function)"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from qiskit_serverless import QiskitFunction\n",
"\n",
"function = QiskitFunction(\n",
" title=\"my-first-function\",\n",
" entrypoint=\"function.py\",\n",
" working_dir=\"./source_files/\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "a23d9f80-6634-48ca-9cc0-5c2146101848",
"metadata": {},
"source": [
"### Upload the function\n",
"Once the function object is created, upload it to the gateway so it can be executed later:\n",
"\n",
"> ⚠ Execution of `upload` function ships All content of `working_dir`. When the contents of `working_dir` is changed, the `upload` function must be called again to update the shipped directory contents."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f2a17837-e4b8-4ea4-a9ed-97358a06f705",
"metadata": {},
"outputs": [],
"source": [
"client.upload(function)"
]
},
{
"cell_type": "markdown",
"id": "3e5326e2-9ff8-48e8-a8a9-18716633fd01",
"metadata": {},
"source": [
"## Running the QiskitFunction\n",
"\n",
"After deploying the QiskitFunction, we can he function by its title:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "1aeefabf",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"QiskitFunction(my-first-function)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"my_first_function = client.get(\"my-first-function\")\n",
"my_first_function"
]
},
{
"cell_type": "markdown",
"id": "135eda5f",
"metadata": {},
"source": [
"We can run any function by calling `run` method on function object. This will make the job run on the gateway:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "d55e3b06-8ab4-42d6-ad47-0f974d8d2247",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"job = my_first_function.run()\n",
"job"
]
},
{
"cell_type": "markdown",
"id": "39ee31d2-3553-4e19-bcb9-4cccd0df0e4c",
"metadata": {},
"source": [
"A [Job](https://qiskit.github.io/qiskit-serverless/stubs/qiskit_serverless.core.Job.html#qiskit_serverless.core.Job) instances have a `status()` method to check status of the function execution. It will help us monitor the status of our job:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "cc7ccea6-bbae-4184-ba7f-67b6c20a0b0b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'QUEUED'"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"job.status()"
]
},
{
"cell_type": "markdown",
"id": "f496adbe-3d82-4aad-b86b-6adb3b9d287d",
"metadata": {},
"source": [
"We can retrieve the result by calling the `result()` method of an instanced `Job` object. The `result()` method will not return until the job is done running the function."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "ca05d063",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'11': 535, '00': 489}"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"job.result()"
]
},
{
"cell_type": "markdown",
"id": "719d3572",
"metadata": {},
"source": [
"To inspect the logs from a function for debugging or analysis, you can access them from the ``Job`` instance."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "eb5ec85f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2025-11-03 10:03:01,072\tINFO job_manager.py:531 -- Runtime env is setting up.\n",
"Running function...\n",
"Completed running function.\n",
"\n"
]
}
],
"source": [
"print(job.logs())"
]
},
{
"cell_type": "markdown",
"id": "9784597b-9377-4d26-8ab9-a8a9b363c924",
"metadata": {},
"source": [
"`ServerlessClient` object has method `.widget` which renders Jupyter widget to see list of executed programs."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3129d55",
"metadata": {},
"outputs": [],
"source": [
"client.widget()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python (qiskit_serverless test venv)",
"language": "python",
"name": "qiskit_serverless_test_venv"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}