diff --git a/notebooks/service_health.ipynb b/notebooks/service_health.ipynb index f4e8976..f382847 100644 --- a/notebooks/service_health.ipynb +++ b/notebooks/service_health.ipynb @@ -47,7 +47,9 @@ }, "source": [ "# Service Health\n", - "Fetch the typed `/healthz` payload from the configured JointFM deployment and display every field. Use this notebook to diagnose health-endpoint issues: version pins, advertised modes, `decoding_strategy` (parallel vs autoregressive horizon decoding), sample-count budgets, and the optional `data_generation` capability block." + "Fetch the typed `/healthz` payload from the configured JointFM deployment and display every field. Use this notebook to diagnose health-endpoint issues: version pins, advertised modes, `decoding_strategy` (parallel vs autoregressive horizon decoding), sample-count budgets, and the optional `data_generation` capability block.\n", + "\n", + "`JOINTFM_DEPLOYMENT_IDS` configures a round-robin pool of hosted deployments. Each endpoint's health payload describes only that endpoint, so the client probes every configured peer and aggregates locally: `health()` returns consensus metadata whose `max_sample_count` is the **minimum** reachable cap, which is the sample-batch size used to split oversized sample requests. `cache=True` stores this probe so the topology section below reuses it instead of issuing a second round of requests." ] }, { @@ -66,17 +68,67 @@ "from jointfm_client import JointFMClient\n", "\n", "client = JointFMClient.from_env()\n", - "health = client.health(refresh=True)\n", - "pprint(asdict(health), sort_dicts=False, width=100)\n", - "health" + "health = client.health(cache=True, refresh=True)\n", + "pprint(asdict(health), sort_dicts=False, width=100)" + ] + }, + { + "cell_type": "markdown", + "id": "4", + "metadata": { + "id": "service-health-topology-description", + "language": "markdown" + }, + "source": [ + "## Deployment Topology\n", + "`health_instances()` returns the per-endpoint results behind that consensus: one entry per configured deployment ID, including peers skipped as unreachable or contract-incompatible. Its `max_sample_count` is the **sum** of reachable caps, the overall parallel capacity of the pool, and `topology_label` groups those caps as `x`. Reachable peers must agree on `model_version` and `checkpoint_version`; a mismatch fails the probe rather than silently mixing models across requests." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": { + "id": "service-health-topology", + "language": "python" + }, + "outputs": [], + "source": [ + "settings = client.settings\n", + "instances = client.health_instances(cache=True)\n", + "# A pool repeats its primary endpoint in `instances`; the seed covers single-endpoint configs.\n", + "predict_url_by_id: dict[str | None, str] = {\n", + " settings.deployment_id: settings.predict_url\n", + "}\n", + "for instance in settings.instances:\n", + " predict_url_by_id[instance.deployment_id] = instance.predict_url\n", + "\n", + "print(f\"selector: {settings.deployment_selector}\")\n", + "print(f\"configured endpoints: {len(instances.instances)}\")\n", + "print(f\"topology: {instances.topology_label}\")\n", + "print(f\"parallel capacity: {instances.max_sample_count} (sum of reachable caps)\")\n", + "print(f\"sample-batch cap: {health.max_sample_count} (minimum reachable cap)\")\n", + "\n", + "for instance in instances.instances:\n", + " print()\n", + " if instance.metadata is None:\n", + " print(f\"{instance.deployment_id}: unavailable\")\n", + " print(f\" error: {instance.error}\")\n", + " continue\n", + " print(f\"{instance.deployment_id}: available\")\n", + " print(f\" url: {predict_url_by_id[instance.deployment_id]}\")\n", + " print(f\" device: {instance.metadata.device}\")\n", + " print(f\" image: {instance.metadata.image_version}\")\n", + " print(f\" checkpoint: {instance.metadata.checkpoint_version}\")\n", + " print(f\" samples: {instance.metadata.max_sample_count}\")" ] } ], "metadata": { "kernelspec": { - "display_name": "joint-client-python (3.13.3)", + "display_name": "Python (joint-client-python)", "language": "python", - "name": "python3" + "name": "joint-client-python" }, "language_info": { "codemirror_mode": {