Source code for nemo_rl.utils.weight_transfer_http

# Copyright (c) 2026, NVIDIA CORPORATION.  All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""HTTP control-plane utilities shared by remote sparse-refit transports."""

import os
import threading
from collections.abc import Iterable, Mapping, Sequence
from concurrent.futures import ThreadPoolExecutor
from functools import cache
from typing import Any

import requests
from urllib3.util.retry import Retry

G_VLLM_REFIT_S3_MANIFEST_PATH = "/nemo-rl/refit/s3-manifest"
G_VLLM_REFIT_PREPARE_PATH = "/nemo-rl/refit/prepare"
G_VLLM_REFIT_FLUSH_PATH = "/nemo-rl/refit/flush"
G_VLLM_REFIT_ZMQ_FLUSH_PATH = "/nemo-rl/refit/zmq-flush"
G_VLLM_REFIT_API_KEY_HEADER = "x-nemo-rl-refit-key"
_HTTP_LOCAL = threading.local()
_HTTP_ADAPTER = requests.adapters.HTTPAdapter(
    pool_connections=64,
    pool_maxsize=64,
    max_retries=Retry(
        total=3,
        backoff_factor=0.25,
        status_forcelist=(502, 503, 504),
        allowed_methods={"POST"},
    ),
)


[docs] def vllm_refit_endpoints(base_urls: Sequence[str], path: str) -> list[str]: return list( dict.fromkeys( f"{url.strip().rstrip('/')}{path}" for url in base_urls if url.strip() ) )
[docs] def vllm_refit_api_key(api_key_env_var: str | None) -> str | None: if not api_key_env_var: return None token = os.environ.get(api_key_env_var) if not token: raise RuntimeError( "vLLM sparse refit API key env var " f"{api_key_env_var!r} is configured but unset or empty." ) return token
[docs] def refit_http_session() -> requests.Session: session = getattr(_HTTP_LOCAL, "session", None) if session is None: session = requests.Session() session.mount("http://", _HTTP_ADAPTER) session.mount("https://", _HTTP_ADAPTER) _HTTP_LOCAL.session = session return session
[docs] @cache def _http_executor(workers: int) -> ThreadPoolExecutor: return ThreadPoolExecutor(max_workers=workers, thread_name_prefix="nrl-refit-http")
[docs] def post_vllm_refit_endpoints( endpoint_urls: Sequence[str], body: Mapping[str, Any], *, api_key: str | None, timeout_s: float, ) -> list[dict[str, Any]]: request_headers = {} if api_key: request_headers[G_VLLM_REFIT_API_KEY_HEADER] = api_key def post(url: str) -> dict[str, Any]: response = refit_http_session().post( url, json=body, headers=request_headers, timeout=timeout_s, ) try: result: dict[str, Any] = response.json() if response.content else {} except requests.exceptions.JSONDecodeError: result = {} if response.status_code >= 400 or result.get("ok") is not True: raise RuntimeError( f"vLLM refit failed for {url}: HTTP {response.status_code}: " f"{response.text[:512]}" ) return result return list(_http_executor(len(endpoint_urls)).map(post, endpoint_urls))
[docs] def merge_vllm_refit_metrics( result: dict[str, Any], metrics: Iterable[Mapping[str, Any]], *, maximum: bool, candidate_maximum: bool | None = None, ) -> dict[str, Any]: for metric in metrics: for key, value in metric.items(): if key.startswith("receiver_") and key.endswith("_s"): number, use_maximum = float(value), maximum elif candidate_maximum is not None and key.startswith("verification_"): number = value use_maximum = key == "verification_max_abs" or ( key == "verification_candidates" and candidate_maximum ) else: continue if key in result: number = ( max(result[key], number) if use_maximum else result[key] + number ) result[key] = number return result