Skip to main content

Standalone HTTP client for hosted and local Rescale AI inference servers

Project description

rescale-ai-client

Standalone Python client for Rescale AI hosted and local inference servers. Communicates over the shared HTTP API. No rescale_ai package dependency.

Installation

pip install rescale-ai-client

For mesh loading, prediction plotting, or VTK mesh helpers (.vtp and .vtm):

pip install "rescale-ai-client[mesh]"

For interactive 3D notebook plots:

pip install "rescale-ai-client[mesh,jupyter]"

This extra also installs jupyter_bokeh, which Panel needs for interactive rendering in VSCode notebooks.

For development (do not run unless making local changes to the rescale-ai-client library)

pip install -e ".[dev]"

License Request

uvx rescale-ai-client request-license --email user@customer.com

Writes license-request.json for the current user and machine.

License Registration

uvx rescale-ai-client register

Registers the issued license for the current user. Without a path, the command looks for a valid license in ~/Downloads, then the current directory, then prompts for the absolute path to the license file.

You can also pass the license path explicitly:

uvx rescale-ai-client register <path_to_license_file>

Quickstart

Launch Local Jupyter Notebook:

cd <path_to_workspace>/rescale-ai-client
source .venv/bin/activate
python -m ensurepip --upgrade
python -m pip install --upgrade pip
pip install uv
jupyter notebook

See example/notebooks/quickstart.ipynb for an example Jupyter notebook to get started. The directory contains other more advanced examples.

Retrieve Server-Available Models:

from rescale_ai_client import InferenceClient

client = InferenceClient.connect(base_url="http://127.0.0.1:65432") # Connects to local Inference Runner. Modify to connect to remote Host & Port
catalog = client.list_models()

model = catalog.model("MyModel").latest()
prediction = client.run_inference(
    "/path/to/case.vtm",
    parameters={"mach": 0.82},
    model_name=model.model_name,
    version_number=model.version_number,
)

print(prediction.global_predictions)
prediction.save("/tmp/result.vtm")

No-mesh Core Install, Summary-Only Inference:

from rescale_ai_client import InferenceClient

client = InferenceClient.connect(base_url="http://127.0.0.1:65432") # Connects to local Inference Runner. Modify to connect to remote Host & Port
summary = client.run_inference_summary(
    "/path/to/case.vtm",
    parameters={"mach": 0.82},
    model_name="MyModel",
    version_number=7,
)

print(summary.global_predictions)
print(summary.prediction_id)

Offline Install Bundle:

This installation path used when downloading an inference bundle directly from the Web UI.

from rescale_ai_client import InferenceClient

client = InferenceClient.connect(base_url="http://127.0.0.1:65432") # Connects to local Inference Runner. Modify to connect to remote Host & Port

installed = client.install_bundle(
    "/path/to/MyModel_v0_local_inference.zip"
)

prediction = client.run_inference(
    "/path/to/case.vtm",
    parameters={"mach": 0.82},
    model_version_path=installed.model_version_path,
)

print(installed.model_name, installed.version_number)
print(prediction.global_predictions)

An ensemble bundle loads as LoadedEnsemble and is selected by its immutable ensemble identity. Members execute sequentially, and uncertainty arrays can be requested alongside the ensemble mean:

from rescale_ai_client import EnsembleLocator, InferenceClient

client = InferenceClient.connect()
installed = client.install_bundle("/path/to/ensemble.zip")

prediction = client.run_inference(
    "/path/to/case.vtm",
    model=EnsembleLocator(ensemble_id=installed.ensemble.ensemble_id),
    include_standard_deviation=True,
    ensemble_node_output="mean",
)

for name, distribution in prediction.ensemble_global_predictions.items():
    print(name, distribution.mean, distribution.standard_deviation)
    print(distribution.member_predictions)

Global ensemble outputs always include their mean, standard deviation, and member-value vector. Node arrays default to the ensemble's primary member; set ensemble_node_output="mean" to generate mean node predictions. Node standard-deviation arrays are only generated when mean node output and include_standard_deviation=True are both requested.

extensions for Optional Future Data

Most JSON request methods accept an optional extensions={...} payload. This is the additive escape hatch for future server features that should not force a client upgrade.

Example: Send Optional Request Hints During Prediction:

from rescale_ai_client import InferenceClient

client = InferenceClient.connect(base_url="http://127.0.0.1:65432") # Connects to local Inference Runner. Modify to connect to remote Host & Port

summary = client.run_inference_summary(
    "/path/to/case.vtm",
    parameters={"mach": 0.82},
    model_name="MyModel",
    version_number=7,
    extensions={
        "rescale": {
            "ui_session": "demo-123",
            "include_debug": True,
        }
    },
)

print(summary.extensions)
print(summary.warnings)

Example: Read Capability-Style or Server-Added Metadata from Typed Responses:

from rescale_ai_client import InferenceClient

client = InferenceClient.connect(base_url="http://127.0.0.1:65432")

server_info = client.server_info()
print(server_info.capabilities)

metadata = client.get_model_version_metadata(
    model_name="MyModel",
    version_number=7,
)
print(metadata.extensions)
print(metadata.warnings)

Run a Saved System

Saved systems created in the Design Studio are available through the local inference server. Inputs may be partial; omitted values use the defaults stored in the system definition. Passing the catalog hash prevents accidentally running a definition that changed after it was inspected:

from rescale_ai_client import InferenceClient

client = InferenceClient.connect()
catalog = client.list_systems()
system = catalog.system("booth")

result = client.run_system(
    system.system_id,
    {"x1": 1.0, "x2": 3.0},
    expected_system_hash=system.system_hash,
)

print(result.outputs)
print(result.resolved_models)

get_system(system_id) returns the declared inputs, outputs, components, and validation state. A run records the exact model versions resolved at its start, including models configured as latest. System catalog and execution endpoints are intentionally available only through a loopback connection (direct local access or an SSH tunnel).

Design rules:

  • extensions are optional and additive
  • unknown request extensions are ignored by the server
  • unknown response extensions are ignored by clients
  • if a field becomes core contract, it should graduate into a typed top-level field

Optimization

The rescale_ai_client.optimization package turns mesh inference into a design-optimization loop. Define an Objective (built-ins cover global scalar outputs, point-field reductions, and multi-model chains) and hand it to a search driver. Every driver minimizes ObjectiveResult.value (use maximize=True on the built-in objectives to flip the sign) and returns a result carrying the full evaluation history, which the plot_* helpers can render.

Install the extra:

pip install "rescale-ai-client[optimization]"   # adds SciPy
pip install "rescale-ai-client[cma]"             # also adds CMA-ES support

Available drivers:

Driver Kind Use when
minimize_scipy Local (L-BFGS-B / SLSQP / TNC) A good starting point is known and the response is smooth
sqp_minimize Local SQP (SLSQP / trust-constr) with nonlinear constraints The problem has constraints (e.g. max_stress <= 500); warm-start from a global driver
differential_evolution Global, population Multi-modal landscape, evaluations are cheap
random_search Baseline sampling A quick lower bound / sanity check
bayesian_optimization Global, GP surrogate + Expected Improvement Each evaluation is an expensive inference call (most sample-efficient)
cma_es Global evolution strategy (needs [cma]) Noisy or ill-conditioned, multi-modal objectives
from rescale_ai_client import InferenceClient
from rescale_ai_client.optimization import (
    GlobalOutputObjective,
    bayesian_optimization,
    cma_es,
    minimize_scipy,
    random_search,
)

client = InferenceClient.connect(base_url="http://127.0.0.1:65432")
obj = GlobalOutputObjective(
    client,
    model_name="MyModel",
    version=0,
    vtp="/path/to/case.vtm",
    output_name="Cd",
    maximize=False,
)
bounds = {"AngleBeta1": (10.0, 35.0), "RPM": (25000.0, 32000.0)}

# Sample-efficient global search — best for expensive inference objectives.
result = bayesian_optimization(obj, bounds=bounds, n_calls=25, seed=0, verbose=True)
print(result.x, result.fun)

# Other drivers share the same call/return shape:
# minimize_scipy(obj, x0={...}, bounds=bounds)
# cma_es(obj, x0={...}, bounds=bounds)            # requires the [cma] extra
# random_search(obj, bounds=bounds, n_calls=50)

Constrained optimization with SQP

sqp_minimize adds nonlinear constraints. Each Constraint receives both the parameters and the cached ObjectiveResult at that point, so a constraint on a model output reuses the objective's inference (no extra call):

from rescale_ai_client.optimization import Constraint, sqp_minimize

constraints = [
    # Keep a predicted global output under a limit (read from the cached result).
    Constraint(
        fn=lambda params, result: result.info["global_outputs"]["max_stress"],
        upper=500.0,
        name="max_stress",
    ),
    # A purely geometric/parameter constraint ignores the result argument.
    Constraint(fn=lambda params, result: params["t1"] - params["t2"], lower=0.0),
]

result = sqp_minimize(
    obj,
    x0={"AngleBeta1": 20.0, "RPM": 29607.0},
    bounds=bounds,
    constraints=constraints,
    method="SLSQP",          # or "trust-constr" for harder problems
    verbose=True,
)
print(result.x, result.fun, result.feasible, result.constraint_values)

Because SQP estimates gradients by finite differences, it's most effective on a smooth response and warm-started from a global driver's best point.

API

InferenceClient.connect(*, base_url=None, host=None, port=None, url=None, timeout=600.0)

Factory method. If omitted, defaults to local loopback at http://127.0.0.1:65432. base_url first. host / port and url remain convenience inputs. Scheme-less non-local endpoints default to HTTPS; explicit HTTP for non-local endpoints raises an InsecureConnectionWarning and stores the message on client.insecure_transport_warning.

// Give example here: connecting to my most recent Workstation

InferenceClient.connect_via_ssh(*, ssh_user_host, remote_port=65432, ...)

SSH tunnel helper. ssh_user_host required. If remote_port is omitted, defaults to 65432.

run_inference(vtp, parameters=None, *, model=None, model_version_path=None, model_name=None, model_uuid=None, version_number=None, ...)

Canonical Python entrypoint. model= accepts either ModelVersionLocator or EnsembleLocator. The vtp argument name is kept for compatibility, but path inputs may be .vtp or .vtm; .vtm paths are sent to the inference server so block structure is preserved. Same shape for hosted and local servers. CamelCase aliases still work, but new code should use snake_case. JSON request methods also accept extensions=... for optional future payloads.

run_inference_summary(...)

Lightweight entrypoint for core installs without the optional mesh dependencies. Returns typed prediction metadata plus global scalar outputs without constructing a pyvista mesh.

list_models(...)

Returns a typed ListModelsResult with helpers like .model("name"), .get("name", version_number=7), and .model("name").latest().

list_systems() / get_system(system_id)

Lists saved Design Studio systems or returns one typed SystemDescription.

run_system(system_id, inputs=None, *, expected_system_hash=None, require_convergence=False, extensions=None)

Runs a saved system on the local inference server and returns a typed SystemRunResult containing scalar outputs, resolved model versions, iteration diagnostics, warnings, and reproducibility hashes.

inspect_bundle(...) / install_bundle(...)

Inspect, upload, and install an offline local-inference bundle zip into the local installer. install_bundle(...) is idempotent for identical content. Ensemble IDs are immutable, so installing different content under an existing ensemble ID is rejected.

get_model_version_metadata(version_number, *, model_name=None, model_uuid=None, ...)

Fetches typed metadata for one model version.

get_loaded_model()

Returns the server's current active-model bookkeeping status.

server_info()

Returns typed inference server capability and compatibility metadata:

  • api_version
  • supported_api_versions
  • schema_revision
  • server_build
  • capabilities

Client

Compatibility alias for one release. Use InferenceClient for new code.

Advanced

Protocol Sync

The committed wire DTOs under src/rescale_ai_client/_generated/ are generated from the closed-source inference server OpenAPI schema snapshot at openapi/inference-server.openapi.json.

Update flow:

# from the closed-source rescale_ai repo
PYTHONPATH=/path/to/rescale_ai \
  /path/to/rescale_ai/.venv/bin/python \
  - <<'PY'
from pathlib import Path
from rescale_ai.inference.server.openapi_compat import export_openapi_schema

export_openapi_schema(
    Path("/path/to/rescale-ai-client/openapi/inference-server.openapi.json")
)
PY

# from this repo
python scripts/generate_protocol_models.py
python scripts/generate_protocol_models.py --check

Releasing

Releases are published by GitHub Actions with uv build and uv publish.

One-Time Setup:

  1. In GitHub, create an environment named pypi under Settings -> Environments.
  2. In PyPI, add a trusted publisher for:
    • Owner: rescale
    • Repository: rescale-ai-client
    • Workflow: release.yml
    • Environment: pypi

No PyPI API token needs to be stored in GitHub secrets for this workflow. PyPI issues a short-lived publishing credential to the tagged GitHub Actions run through OIDC.

Publish a Release:

uv version 0.1.1
git commit -am "Release 0.1.1"
git tag -a v0.1.1 -m v0.1.1
git push origin main
git push origin v0.1.1

The workflow runs tests, verifies generated protocol models, builds both wheel and source distributions, smoke-tests both artifacts, and publishes to PyPI.

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rescale_ai_client-0.3.4.tar.gz (1.2 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rescale_ai_client-0.3.4-py3-none-any.whl (77.8 kB view details)

Uploaded Python 3

File details

Details for the file rescale_ai_client-0.3.4.tar.gz.

File metadata

  • Download URL: rescale_ai_client-0.3.4.tar.gz
  • Upload date:
  • Size: 1.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for rescale_ai_client-0.3.4.tar.gz
Algorithm Hash digest
SHA256 028264143ce761f0bbbf7d0d137938e595b80af6d05d13a49dea947a58a32d04
MD5 c44440f1b42167b1be78b23e3c6d5fc7
BLAKE2b-256 96e36807ffe80f2c67aa0c333cf32f7bf745e557eabc6e699f2fa0f96ae6a3e2

See more details on using hashes here.

File details

Details for the file rescale_ai_client-0.3.4-py3-none-any.whl.

File metadata

  • Download URL: rescale_ai_client-0.3.4-py3-none-any.whl
  • Upload date:
  • Size: 77.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for rescale_ai_client-0.3.4-py3-none-any.whl
Algorithm Hash digest
SHA256 450a20ab30f66f860451df8a89221cda2a11f89a027c5acb3c822b5af1621498
MD5 588fa01781419bfa7aca1bdc46ee0e57
BLAKE2b-256 c7c2fcd043339b8196da1e1a51214481dbec895adc8674a760f43ced2fb4f16f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page