# Inférence à distance

Les politiques de grande taille nécessitent un GPU, et avec un déroulement synchrone, le robot cesse de bouger à chaque fois que la politique calcule son prochain lot d’actions. L’inférence distante divise la tâche en deux : un **serveur de politique** exécute le point de contrôle sur un GPU, tandis que l’**ordinateur du robot** conserve le contrôle des caméras, des moteurs, de la téléopération et de l’enregistrement. Le robot continue d’exécuter les actions dont il dispose déjà pendant que le serveur calcule les suivantes, si bien que le mouvement ne s’arrête plus pour l’inférence.

À utiliser lorsque :

- l'ordinateur connecté au robot ne dispose pas de GPU, ou d'un GPU trop faible pour la politique : un ordinateur portable ou un ordinateur à carte unique à côté du bras et une station de travail GPU de l'autre côté du laboratoire ;
- l'inférence représente une part notable de chaque segment d'action et vous souhaitez un mouvement continu ;
- vous souhaitez décider à quelle fréquence le robot doit replanifier sans toucher au point de contrôle.

Le seul compromis à régler est **la fraîcheur par rapport à la continuité**. Demander un nouveau plan plus tôt permet au robot de réagir à ce qu’il perçoit ; suivre davantage le plan en cours préserve l’avancement de la tâche.

## Fonctionnement

```mermaid
flowchart LR
  %% The server subgraph is declared first so that the layout keeps the robot computer on the left.
  subgraph server["Policy server (GPU)"]
    P["Policy checkpoint"]
  end
  subgraph robot["Robot computer"]
    direction TB
    B[("Action buffer")] -->|next action, every tick| R["Cameras and motors<br/>teleoperation, recording"]
  end
  R -->|observation + instruction| P
  P -.->|chunk of upcoming actions| B
```

L'ordinateur du robot maintient un tampon d'actions à venir. Lorsque le tampon est presque vide, il envoie une nouvelle observation, continue de s'exécuter à partir du tampon pendant que le serveur calcule, et insère le nouveau segment dans la partie du plan qui n'a pas encore été exécutée.

```mermaid
sequenceDiagram
  participant R as Robot computer
  participant S as Policy server (GPU)
  Note over R: executing actions from the buffer
  Note over R: buffer runs low (refill threshold)
  R->>S: observation + instruction
  rect rgb(235, 245, 255)
    Note over R: keeps moving from the buffer
    S->>S: predict the next chunk
  end
  S-->>R: chunk of upcoming actions
  Note over R: new plan replaces the part of the buffer not yet executed
```

Trois paramètres client déterminent ce comportement. `refill_seconds` définit à quel moment demander le plan suivant, `chunk_merge` définit comment le nouveau plan est fusionné avec l’ancien, et le lissage adoucit la transition entre les deux. Le serveur n’a besoin que du point de contrôle et d’une description du robot pour lequel il a été entraîné. Les sections ci-dessous partent d’une configuration fonctionnelle, puis développent l’intuition pour chaque paramètre.

**RTC local** (`--inference.type=rtc`) est l'autre option asynchrone : l'inférence s'exécute dans un thread en arrière-plan du processus de rollout, sur la même machine, sans serveur. L'inférence distante sur le même hôte utilise toujours deux processus et `--inference.type=remote`, et offre l'alignement et le mélange pour les politiques sans RTC. Voir [comment le RTC se rapporte à l'inférence distante](./rtc#how-rtc-relates-to-remote-inference).

### Politiques et robots pris en charge

Un point de contrôle peut être servi lorsque ses processeurs sauvegardés prédisent un segment d’actions à partir d’une seule observation actuelle ; ACT nécessite que l’ensembling temporel soit désactivé. Les points de contrôle ACT, SmolVLA, XVLA, EVO1 et LaWAM ont fonctionné sur des robots réels via ce chemin. Plusieurs autres politiques sont prises en charge au niveau du contrat mais n’ont pas été validées sur du matériel, et les politiques dépendantes de l’historique nécessitent une intégration supplémentaire. Le [tableau de prise en charge des politiques](https://github.com/huggingface/lerobot/blob/main/src/lerobot/remote_inference/README.md#policy-support) répertorie le statut et les restrictions de chaque politique.

Le pilote robotique doit déclarer le support du maintien de position, car le client rafraîchit la dernière cible appliquée pendant qu'il attend les actions. SO, OMX, Koch, HopeJr, Rebot et les suiveurs YAM le déclarent ; OpenArm, Reachy2 et les enveloppes bimanuelles en dépendent selon leur configuration ; le Unitree G1 ne le déclare qu'avec le contrôleur SONIC, dont la cible conservée est le dernier jeton de mouvement ; les bases mobiles ne le font pas. Consultez le [tableau matériel](./integrate_hardware#waiting-between-predictions). Les contrats de robot ou de politique non pris en charge sont rejetés à l'admission, avant tout mouvement.

## Commencer par un déroulement fonctionnel

Conservez une commande `lerobot-rollout` synchrone réussie comme référence, et maintenez ses paramètres de robot, de caméras, de tâche, de FPS, de téléopérateur et d’interpolation. Le checkpoint et l’appareil du modèle passent sur le serveur ; le client distant ne charge pas les poids.

Les exemples ci-dessous décrivent un **SO-101 générique à six actionneurs avec une caméra avant**. Adaptez le checkpoint, les vues caméra, l’ordre des composants et les unités de manière cohérente.

### 1. Installer sur les deux ordinateurs

Les deux côtés ont besoin de l’extra `remote`. Conservez les extras matériel sur le client et l’extra de la politique sélectionnée sur le serveur :

```bash
uv sync --locked --extra remote --extra core_scripts --extra feetech
# Add the policy extra on the server when required, for example --extra pi.
```

La plage de versions Zenoh prise en charge est `>=1.9.0,<1.11.0` ; `uv sync --locked` installe la version du fichier de verrouillage, actuellement 1.10.1.

### 2. Configurer et démarrer le serveur

Copiez la [configuration générique](https://github.com/huggingface/lerobot/blob/main/examples/remote_inference/server.yaml), puis modifiez-la :

```bash
cp examples/remote_inference/server.yaml server.yaml
```

Définissez `model.repo_or_path` et `model.device`. Pour un checkpoint du Hub, fixez `model.revision` sur le commit que vous souhaitez valider. Alignez `features`, `action_feature`, `semantics`, `robot_type` et `execution.action_fps` sur votre configuration de travail ; consultez les [exemples de schéma et de renommage des caméras](#configuration-and-networking) ci-dessous.

```bash
uv run --no-sync lerobot-policy-server --config_path=server.yaml
```

Le serveur charge le point de contrôle, valide ses déclarations, exécute le réchauffement puis journalise `Policy server ready: deployment=<name> instance=<id>; awaiting one client`. Chaque champ YAML accepte une surcharge CLI imbriquée :

```bash
uv run --no-sync lerobot-policy-server --config_path=server.yaml \
  --model.device=cuda \
  --execution.idle_timeout_s=10
```

### 3. Démarrer le client robot

Dans un autre terminal, adaptez les arguments matériel à la même configuration :

```bash
uv run --no-sync lerobot-rollout \
  --inference.type=remote \
  --inference.endpoint=tcp/127.0.0.1:7447 \
  --inference.deployment=manipulation \
  --inference.mode=chunk \
  --inference.chunk_merge=aligned \
  --inference.semantics=so101-degrees-gripper-percent-v1 \
  --robot.type=so101_follower \
  --robot.port=/dev/ttyACM0 \
  --robot.use_degrees=true \
  --robot.cameras='{front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}' \
  --fps=30 \
  --task="pick up the cube" \
  --interactive=true
```

Après l’admission, tapez `/start`. `/stop` met fin à l’exécution ; voir [ce que le robot fait en attendant ou en s’arrêtant](#what-the-robot-does-while-waiting-or-stopping). Conservez les options de téléopération et d’enregistrement de votre déroulement de travail. Ne transmettez pas `--policy.path`, les remplacements locaux de modèle-appareil ni les drapeaux de compilation au client distant.

`deployment` sélectionne le serveur et `semantics` nomme les unités d’action validées et leur ordre ; les deux doivent correspondre à la configuration du serveur. L’exemple utilise les degrés de liberté des articulations du corps et une plage de pince calibrée de 0 à 100.

Utiliser un LAN de confiance plutôt que localhost

Lier le serveur à son interface LAN, en remplaçant l'adresse d'exemple par son IP réelle :

```bash
uv run --no-sync lerobot-policy-server --config_path=server.yaml \
  --zenoh.listen_endpoints='[tcp/172.18.133.214:7447]'
```

Côté client, utilisez la même adresse : `--inference.endpoint=tcp/172.18.133.214:7447`. Les deux hôtes doivent pouvoir accéder à ce point de terminaison.

Lier une interface spécifique limite l’exposition mais n’authentifie pas les pairs. Utilisez des [connexions de routeur authentifiées](#configuration-and-networking) en dehors d’un réseau de laboratoire de confiance.

## Choisissez comment poursuivre le mouvement

Au moment où un nouveau chunk arrive, l’observation à partir de laquelle il a été calculé est déjà un peu obsolète, et le robot a déjà avancé. Le mode de fusion décide quoi faire à ce sujet : jouer le nouveau chunk après l’ancien, supprimer les étapes que le robot a déjà franchies, ou lisser la jonction.

| Choix               | Paramètres du client                                          | Point de départ utile                                                                                                     |
| -------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Ajouter               | `mode=chunk`, `chunk_merge=append`                       | Conservez la tranche d'exécution acceptée complète ; utile comme référence, mais le prochain bloc peut démarrer à partir d'une observation plus ancienne. |
| Alignement            | `mode=chunk`, `chunk_merge=aligned` (la valeur par défaut `auto`) | Supprimez les étapes entrantes déjà passées et remplacez uniquement les futures, réduisant ainsi les collisions en arrière-plan entre les chunks indépendants.     |
| Alignement + mélange | Alignement plus `blend_steps > 0` et composants explicites | Superposition fluide des cibles anciennes/nouvelles après que la cadence et la progression de la tâche sont opérationnelles.                                           |
| RTC                  | `mode=rtc_guided` ou `rtc_trained`                       | À utiliser lorsque le point de contrôle prend en charge le RTC : l’inférence elle-même conditionne sur la trajectoire restante.                            |

Les paramètres de ce tableau utilisent le préfixe `--inference.`. Les blocs simples sont alignés par défaut, avec le mélange désactivé. Une cible déjà interpolée est validée et ne peut pas être remplacée.

L’alignement abandonne les étapes entrantes déjà validées. Le mélange moyenne les cibles futures qui se chevauchent. L’interpolation ajoute des commandes motrices intermédiaires entre les points extrêmes. RTC modifie la manière dont la prédiction est générée. Aucune de ces méthodes ne garantit un mouvement fluide ou une prise réussie.

Ajouter un court fondu à l’exemple

Le mélange est entièrement configuré côté client ; le serveur n'a besoin d'aucun paramètre de mélange ni de redémarrage. Sélectionnez les coordonnées des bras en continu parmi les noms d'actions du déploiement :

```bash
--inference.chunk_merge=aligned \
--inference.blend_steps=5 \
--inference.blend_weight=0.5 \
--inference.blend_components='[shoulder_pan.pos, shoulder_lift.pos, elbow_flex.pos, wrist_flex.pos, wrist_roll.pos]'
```

Il s’agit de paramètres de comparaison, et non d’une recommandation optimisée. Excluez le gripper et les autres contrôles discrets ou sensibles au contact, sauf s’ils ont été validés. Les composants non sélectionnés utilisent la cible entrante.

Le blending calcule `q_t + b_w * (i_t - q_t)` : `q_t` est la cible en file d'attente, `i_t` la cible entrante pour le même créneau futur, et `b_w` la fraction entrante (`blend_weight`). Un poids de 1 équivaut à un remplacement. Le chevauchement réel limite la fenêtre de blending ; dix étapes configurées ne peuvent pas créer dix étapes en chevauchement. Des remplacements répétés peuvent mélanger une cible non validée plus d'une fois, en conservant l'influence plus ancienne et son âge d'origine. Le blending ne rafraîchit jamais les données expirées.

Servir un RTC guidé sur un point de contrôle compatible

Conservez le schéma validé et configurez le serveur :

```bash
uv run --no-sync lerobot-policy-server --config_path=server.yaml \
  --execution.supported_modes='[rtc_guided]' \
  --execution.rtc.enabled=true \
  --execution.rtc.mode=guided \
  --execution.rtc.execution_horizon=15
```

Sur le client, définissez `--inference.mode=rtc_guided`. RTC utilise sa propre gestion des continuations, et non l’alignement ou le mélange par blocs simples. Remesurez le temps de réponse, car le guidage ajoute du travail. L’horizon de 15 étapes est un exemple, pas une valeur optimisée.

Trained RTC nécessite un point de contrôle entraîné pour le conditionnement par préfixe d'action et des paramètres de délai/horizon compatibles ; voir [Configuration RTC](./rtc). La demande d'un mode non pris en charge échoue avant le mouvement.

## Paramètres qui comptent

Les options client ci-dessous utilisent le préfixe `--inference.` sauf indication contraire. Les valeurs par défaut sont des valeurs de départ, et non des garanties pour un robot particulier.

| Paramètre                    | Défaut / unité                      | Effet et compromis                                                                                                      |
| ---------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `refill_seconds`             | `0.5` secondes de lecture restantes | Une valeur plus élevée demande généralement une exécution plus précoce ; une valeur plus faible permet à une plus grande partie du plan de s'exécuter. Un seuil de latence mesuré peut le remplacer.     |
| `blend_steps`                | `0` étapes de politique                    | Zero désactive le mélange. Des fenêtres plus grandes mélangent davantage de cibles futures superposées.                                              |
| `blend_weight`               | `0.5` fraction entrante             | Lower conserve davantage de l'ancienne cible : des modifications potentiellement plus douces, mais une correction plus lente.                                |
| `blend_components`           | `[]`                                | Sous-ensemble explicite des coordonnées autorisées par le serveur ; requis lorsque le mélange est activé.                                |
| `max_observation_age_s`      | `5.0` secondes                       | Âge maximal de la source originale lors de l'exécution, y compris les contributeurs de mélange plus anciens. Doit couvrir l'inférence et la lecture. |
| `action_starvation_grace_s`  | `1.0` seconde                       | Attente bornée après épuisement de la lecture ; `0` déclenche une erreur immédiatement. Ne remplace pas les autres délais.                         |
| `--fps`                      | Correspondance du serveur `action_fps`           | Fréquence des actions de la politique. Pour `N` actions, la lecture nominale est de `N / fps` secondes.                                         |
| `--interpolation_multiplier` | `1`                                 | Plus de commandes motrices intermédiaires ; n'étend pas la lecture ni n'ajoute de décisions de politique.                                      |

Le remplissage effectif est `max(refill_seconds, recent maximum turnaround + 1 / fps)`. Le délai inclut l’encodage, le réseau, la mise en file d’attente, l’inférence et le décodage. La première requête acceptée fournit une estimation initiale ; les estimations ultérieures utilisent jusqu’à 100 échantillons en régime permanent.

Refill n’est donc ni une période de requête fixe ni un nombre garanti d’actions exécutées. Inspectez le refill **configuré et effectif** dans les journaux. Un seuil couvrant l’horizon d’exécution complet entraîne un remplacement très fréquent.

Délais d'opération et propriété du serveur

Toutes les valeurs sont en secondes.

| Paramètre client      | Par défaut | Limites                                                     |
| --------------------- | ------- | ---------------------------------------------------------- |
| `handshake_timeout_s` | `10`    | Découverte/admission ; budget de base pour les échanges de contrôle     |
| `startup_timeout_s`   | `10`    | Nouvelle action de démarrage après réinitialisation/invalidation reconnue |
| `action_timeout_s`    | `5`     | Une demande d'action en suspens                             |
| `language_timeout_s`  | `60`    | Une requête de texte                                           |

Le serveur dispose également de `execution.action_deadline_s=5` et de `language.deadline_s=60`. Les limites du client et du serveur s’appliquent toutes deux ; modifier l’une ne relâche pas l’autre. Les échanges de contrôle de réinitialisation/invalidation autorisent en outre le budget de travail annoncé par le serveur, car ils doivent attendre derrière un appel de modèle en cours d’exécution.

Le serveur `execution.idle_timeout_s=10` contrôle le nettoyage après **l'absence observée du client**, et non la tolérance à la faim d'actions. Le nettoyage attend derrière le travail du modèle en cours ; un appel bloqué ne peut pas être repris. Un client connecté en pause conserve sa session.

## Ce que le robot fait en attendant ou en s'arrêtant

Lors d'une attente prise en charge, le client actualise le **dernier objectif réellement appliqué par le pilote**, y compris l'interpolation, le rognage et la pince. Avant la première commande, une pose mesurée l'initialise. Cela arrête l'avancement de la trajectoire ; le robot peut encore se stabiliser vers cet objectif. Cela ne désactive pas le couple ni ne garantit l'immobilité. Le RTC local utilise la même attente bornée sur les robots pris en charge et déclenche une erreur immédiatement en cas d'épuisement ailleurs.

| Situation                                                           | Comportement attendu                                                                                                                          |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Inférence initiale                                                   | En attente locale jusqu'à l'arrivée d'actions utilisables, dans le délai de démarrage.                                                                     |
| Échec d'exécution des Actions                                                     | Finalisez l'interpolation engagée, puis conservez la cible jusqu'à la fin de la période de grâce contre la famine. Reprenez uniquement à partir d'une nouvelle observation et d'une nouvelle prédiction.  |
| `/vqa` ou requête de pilotage automatique                                        | Pause avant la génération de texte ; reprendre à partir de nouvelles actions par la suite si l'exécution reste active. Les limites de langue s'appliquent.                        |
| Changement d'instruction pendant l'inférence                                 | Abandonnez l’ancienne prédiction, mettez en pause et obtenez de nouvelles actions pour la nouvelle instruction. Les modifications entre les requêtes peuvent conserver le mouvement accepté. |
| Enregistrement de la sauvegarde ou pause de l'opérateur                                    | Conservez la cible, ou confiez le contrôle à la téléopération. L’enregistrement bloquant reprend avec de nouvelles inférences lorsque cela est approprié.                |
| Délai dépassé, action obsolète, réponse mal formée ou délai de grâce de famine expiré | Défaut terminal : révoquer la motion de politique et suivre l’arrêt configuré.                                                                       |
| `/stop` ou Ctrl+C normal                                            | Mettre fin au mouvement de la politique et respecter le comportement de retour/déconnexion configuré.                                                                         |

La récupération après une période de famine (starvation) élimine une ancienne prédiction en cours et obtient une prédiction fraîche à partir d'une capture effectuée après le début de l'attente. Les anciens résultats ne peuvent pas redémarrer le mouvement. Les paquets et les résultats inutilisables ne renouvellent pas la période de grâce. Des attentes fréquentes indiquent une couverture insuffisante de la lecture ou de la latence.

**La perte du serveur ou de la connexion n’est pas récupérée automatiquement.** Les actions tamponnées valides peuvent être vidées, suivies d’une attente jusqu’à l’expiration du délai de grâce ou d’un autre délai limite. Une fois la perte de présence du serveur observée, cette session ne peut pas reprendre lorsque la connectivité revient ; redémarrez le déroulement pour une nouvelle session. Pendant le travail sur le texte, la perte du serveur observée provoque une erreur sur la requête.

Avec une acquisition d’observations et un contrôle des actionneurs sains, l’arrêt du terminal respecte `--return_to_initial_position=true` (la valeur par défaut), puis se déconnecte. Le retour lit une observation complète, de sorte qu’une défaillance persistante de la caméra peut l’empêcher. Une action échouée ou l’application d’un maintien supprime tout mouvement ultérieur. Définir l’option sur `false` ignore le retour, mais pas la déconnexion. La déconnexion peut libérer le couple selon la configuration du robot. Les échecs du terminal se terminent avec un statut non nul après le nettoyage ; un processus tué de force ne peut pas garantir le nettoyage.

## Ajuster une tâche fonctionnelle

Commencez près de la référence synchrone : exécutez une part substantielle de chaque prédiction, mais faites la demande assez tôt pour masquer la latence d’inférence. Évaluez ensuite si un replanification plus fréquente est bénéfique.

1. **Utilisez d’abord l’alignement sans mélange.** Gardez le FPS, l’interpolation et la configuration fixes. Inspectez l’horizon d’exécution, le temps de traitement complet et les requêtes lentes.
2. **Choisissez une couverture de recharge avec une marge.** Laissez suffisamment de lecture pour une autre requête et la variation de latence, sans remplacer continuellement le plan.
3. **Ajoutez un court mélange à cette cadence.** Comparez séparément l’achèvement de la tâche, la prise/relâche et les chocs. Une moyenne lissée de plans incompatibles peut manquer l’objet.
4. **Demander plus tôt uniquement si cela est bénéfique.** Augmenter la fréquence de recharge peut améliorer la réactivité, mais risque d'interrompre des progrès utiles. Revenir au rythme stable si les performances de la tâche se dégradent.
5. **Modifiez un paramètre à la fois.** Augmenter les délais d’attente ou la période de grâce ne fournit pas les actions manquantes. Réduire le réapprovisionnement n’est pas un remède universel à l’épuisement.

Pour un horizon d'exécution de `0.8 s` et un alignement stable et réussi, l'espacement entre les requêtes est d'environ `0.8 - effective_refill` :

| Réapprovisionnement effectif | Espacement approximatif | À surveiller                                              |
| ---------------- | ------------------- | ---------------------------------------------------------- |
| `0.2 s`          | `0.6 s`             | Plus de suivi, moins de protection contre les requêtes lentes |
| `0.4 s`          | `0.4 s`             | Un remplacement plus précoce offre plus d'opportunités de correction         |
| `0.6 s`          | `0.2 s`             | Modifications fréquentes ; vérifiez l'avancement de la tâche                      |

Cela exclut les effets de démarrage, de maintien, de saturation et de pas de contrôle. Une requête qui démarre avec `0.2 s` restants et qui prend `0.1 s` ne laisse que `0.1 s` pour le fondu, soit trois pas à 30 Hz. Une cadence quasi synchrone peut donc ne nécessiter qu'un court fondu.

Pour l’alignement et le RTC, vérifiez **la durée de lecture utile après rognage**, et non la longueur nominale du chunk. Si l’inférence prend 1 seconde sur une prédiction de 1,67 seconde, il ne reste qu’environ 0,67 seconde. Une autre requête d’une seconde ne peut pas tenir ; aucune valeur de refill ne corrige cela. Réduisez le temps de traitement, utilisez un horizon pris en charge plus long, ou validez une fréquence d’action différente.

L’âge de la source inclut l’exécution. Pour l’ajout, autorisez approximativement `execution horizon + effective refill` plus une marge de capture/inférence. Un bloc de 100 étapes à 30 Hz couvre déjà 3,33 secondes. L’alignement réduit généralement l’âge, mais un mélange répété peut conserver des contributeurs plus anciens.

## Lire les journaux et diagnostiquer une exécution

Les journaux INFO affichent les paramètres d’admission et effectifs, les résultats des requêtes texte, les transitions d’attente/arrêt ainsi qu’un résumé d’activité environ toutes les cinq secondes. Lisez le temps de traitement et la lecture en file d’attente ensemble. Pour plus de détails, utilisez `--log_level=DEBUG` côté serveur et `--inference.log_level=DEBUG` côté client. Les sessions interactives atténuent les journaux client en dessous du niveau ERROR ; utilisez une exécution non interactive lors de la collecte de journaux de chronométrage en direct.

Lors de l’enregistrement des journaux, utilisez `2>&1 | tee -i server.log` (ou `client.log`). L’option `-i` maintient `tee` actif lorsque Ctrl+C atteint l’ensemble du pipeline, ce qui permet de capturer également les messages d’arrêt propre.

| Observation                                | Prochaine vérification utile                                                                                                      |
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| Append provoque des bosses en arrière               | Comparez l’alignement avec la même configuration ; le prochain bloc complet peut démarrer à partir d’une observation plus ancienne.                          |
| L'alignement est fluide mais le taux de réussite des tâches diminue | Réduisez le seuil de réapprovisionnement au sein de la marge de latence afin de diminuer la fréquence de remplacement. Ajustez la cadence avant le mélange.                  |
| Le mélange semble indécis                  | Raccourcissez sa fenêtre ou augmentez le poids entrant ; comparez sans mélange à la cadence de travail.                       |
| Attente répétée / épuisement des actions       | Vérifiez les délais de traitement lents, les requêtes perdues ou bloquées et la lecture après la suppression. Augmentez la marge de manœuvre uniquement si l’horizon le permet. |
| Les modifications de recharge n'ont aucun effet                  | La latence mesurée peut dominer ; inspectez le remplissage effectif.                                                     |
| Défaut de source obsolète                         | Inspecter l'âge de la source la plus ancienne, l'horizon et le mélange. Les nouvelles réponses ne rafraîchissent pas les anciens contributeurs.                          |
| `BUSY` après un redémarrage du client              | En attente du nettoyage des clients absents et des tâches en cours. Les reconnections refusées ne renouvellent pas la période de grâce de la propriété.                 |
| Incohérence de contrat                          | Comparez les schémas, les modes et les métadonnées logicielles de démarrage ; redémarrez ou mettez à jour le processus incompatible.                      |

DEBUG inclut, pour chaque requête, la lecture à la soumission, l’âge de l’observation et la progression du curseur, ainsi que les étapes élaguées/utilisables et le chevauchement par résultat. Ces éléments décrivent la progression commandée, et non l’exécution physique mesurée.

## Configuration et réseau

Conservez un seul YAML de déploiement pour le checkpoint, le schéma du robot et les paramètres du serveur ; utilisez des substitutions CLI imbriquées pour les expériences. Attribuez des noms de déploiement distincts aux expériences indépendantes. Les deux processus journalisent leurs versions de package et de protocole ; l’admission vérifie le protocole ainsi que les contrats d’exécution et de données, sans exiger des versions de package identiques.

Schéma, noms des caméras et exigences relatives aux points de contrôle

Le [server.yaml](https://github.com/huggingface/lerobot/blob/main/examples/remote_inference/server.yaml) maintenu inclut tous les champs requis. `features` et `action_feature` déclarent la forme, le dtype et la sémantique ; les vecteurs d'état/action déclarent également l'ordre des composants. Les images utilisent le format RGB `uint8`, hauteur × largeur × 3. Par exemple :

```yaml
features:
  - name: observation.state
    shape: [6]
    dtype: float32
    names:
      [
        shoulder_pan.pos,
        shoulder_lift.pos,
        elbow_flex.pos,
        wrist_flex.pos,
        wrist_roll.pos,
        gripper.pos,
      ]
    semantics: so101-degrees-gripper-percent-v1
  - name: observation.images.front
    shape: [480, 640, 3]
    dtype: uint8
    kind: rgb
    semantics: rgb-front-table-v1
```

Utilisez les noms orientés checkpoint. Pour associer une caméra de robot nommée `scene` à la vue `front` du checkpoint, définissez le paramètre client `--rename_map='{"observation.images.scene":"observation.images.front"}'`. Le renommage ne peut pas modifier la vue, la résolution ou l’étalonnage. Des caméras supplémentaires peuvent rester disponibles pour l’enregistrement sans être envoyées au serveur.

Les politiques prises en charge utilisent des processeurs enregistrés et la prédiction directe de chunks à partir d’une observation actuelle. Les politiques dépendantes de l’historique, les sorties du contrôleur latent et la préparation disponibles uniquement via `select_action()` nécessitent une intégration supplémentaire. Une inférence synchrone ou un warmup réussi ne suffisent pas à prouver la qualité de la tâche distante ou le support du langage/RTC.

Pour un point de contrôle pris en charge de type « chunk-only », le serveur `--execution.n_action_steps=30` raccourcit sa tranche d’exécution sans modifier le point de contrôle. Cette valeur ne peut pas dépasser l’horizon de prédiction et est rejetée pour les déploiements RTC. L’option facultative côté client `--inference.expected_artifact=...` fixe le contenu du modèle/processeur et les paramètres d’inférence effectifs ; un simple nom de déploiement ne constitue pas une identité de point de contrôle.

Déploiements indépendants, bande passante et perte de connexion

Associer le serveur `--deployment=arm-a` au client `--inference.deployment=arm-a`. Les noms doivent être des segments uniques alphanumériques/underscore/point/tiret. Chaque processus serveur sert toujours un seul client actif. Si plusieurs instances annoncent le même nom, sélectionner `--inference.instance=...` ou utiliser des noms distincts ; la découverte ne choisit pas arbitrairement.

Le trafic est structuré sous `lerobot/inference/v1/deployments/{deployment}`, puis par instance de serveur et par session. Les requêtes/réponses gèrent la découverte, l’admission et le contrôle ; la publication/abonnement transporte les données d’inférence ; la vitalité suit la présence. Les points de terminaison explicites désactivent la découverte par multicast/gossip. Les identités de séquence/génération et la temporisation locale au client régissent le mouvement ; des horlogues d’hôtes synchronisées ne sont pas nécessaires.

Le format RGB brut est sans perte et constitue le réglage par défaut. Essayez `--inference.encoding=jpeg --inference.jpeg_quality=90` pour réduire la bande passante des images, puis comparez le temps de traitement et la qualité de la tâche. La qualité varie de 1 à 100 ; les tenseurs arbitraires ne sont jamais encodés en JPEG.

Liveliness ne détecte une connexion rompue qu’après l’expiration du bail de transport. Un fichier Zenoh JSON5 fourni via le paramètre client `--inference.zenoh_config_path` ou le paramètre serveur `--zenoh.config_file` permet d’ajuster `transport/link/tx/lease`. Cela ne modifie pas les délais d’action, la tolérance à la famine ni le nettoyage de la propriété en cas d’absence du client. En cas de congestion d’observation, les données sont abandonnées plutôt que de bloquer l’envoi des commandes moteur.

La `presence restored` du serveur annule le nettoyage de la propriété ; elle ne peut pas réanimer un client qui a déjà rencontré une erreur. Un échec de réinitialisation de la politique rend le déploiement indisponible, même si son processus reste actif ; résolvez l’échec et redémarrez-le.

Connexions privées via un routeur authentifié

Un routeur offre un point de rencontre accessible pour les processus robot et GPU, y compris pour plusieurs expériences distinctes. Il ajoute de la latence et un point de défaillance ; il ne fournit pas de traversée automatique de pare-feu, de planification de modèles ni de récupération de mouvement. Le TCP brut et les identifiants de session n’authentifient pas les pairs.

Utilisez les [configurations Zenoh](https://github.com/huggingface/lerobot/tree/main/examples/remote_inference/zenoh) maintenues : `router.json5`, `server.json5` et `robot.json5`. Elles utilisent TLS, la vérification mutuelle des certificats, la découverte désactivée et des ACL basées sur les rôles. Approvisionnez une CA privée et des certificats distincts pour le routeur, le serveur et le robot sous les chemins configurés. Chaque processus n'a besoin que de sa propre clé privée et du certificat de la CA ; conservez la clé de la CA ailleurs. Pour un déploiement en LAN, remplacez `localhost` de manière cohérente par le nom d'hôte du routeur et émettez un certificat couvrant ce nom.

```bash
zenohd --config examples/remote_inference/zenoh/router.json5

uv run --no-sync lerobot-policy-server --config_path=server.yaml \
  --zenoh.mode=client \
  --zenoh.listen_endpoints='[]' \
  --zenoh.connect_endpoints='[tls/localhost:7447]' \
  --zenoh.config_file=examples/remote_inference/zenoh/server.json5
```

Ajoutez à la commande de déploiement normale :

```bash
--inference.endpoint=tls/localhost:7447 \
--inference.zenoh_mode=client \
--inference.zenoh_config_path=examples/remote_inference/zenoh/robot.json5
```

Modifiez les chemins de déploiement ACL conjointement avec le nom du déploiement. Tous les participants utilisent le mode client sans liens pairs directs. L’exemple sépare les rôles robot et serveur, mais le partage des certificats de rôle partage les autorisations ; utilisez des identités autorisées distinctes pour différents groupes de confiance. Les ACL du routeur ne peuvent pas protéger un processus robot compromis ni réguler son trafic local interne. Consultez la documentation [TLS](https://zenoh.io/docs/manual/tls/) et [ACL](https://zenoh.io/docs/manual/access-control/) de Zenoh.

Les versions du binaire `zenohd` et du binding Python doivent être compatibles. Pour vérifier la compatibilité entre le routeur installé et le binding installé, y compris l’application du TLS et des ACL :

```bash
LEROBOT_ZENOHD=/absolute/path/to/zenohd \
  uv run --no-sync pytest tests/remote_inference/test_zenoh.py -q -rs
```

Les vérifications nécessitent également `openssl` ; les prérequis indisponibles sont signalés comme des sauts. Le pilotage d'un robot via un routeur, un GPU hébergé en privé ou un Hugging Face Space n'a pas encore été validé. Mesurez le délai total et le comportement en cas d'interruption avant de piloter un robot via une nouvelle topologie ; un transport fonctionnel seul ne garantit pas un budget de mouvement exploitable.

## Langue et enregistrement

Utilisez `/vqa`, `/subtask` et `/autosteer` via le [interactive rollout](./inference#interactive-sessions). Activez le paramètre serveur `language.enabled=true` uniquement sur un checkpoint qui implémente la génération de texte ; autosteering nécessite en outre un checkpoint entraîné pour la génération de sous-tâches avec un prompting compatible pour les objectifs/sous-tâches. Le serveur expose ces commandes lorsque le checkpoint déclare la capacité ; l'utilité des réponses et des sous-tâches dépend du checkpoint.

Le travail de texte met le mouvement en pause et abandonne la continuation mise en tampon. VQA conserve votre instruction et reprend avec une nouvelle prédiction, de sorte que le robot peut perdre la progression de la tâche lors d’une nouvelle planification, même après une réponse réussie. Le maintien du mouvement mis en tampon pendant une requête VQA informative est prévu ; voir [travaux futurs](https://github.com/huggingface/lerobot/blob/main/src/lerobot/remote_inference/README.md#13-future-work).

L’enregistrement utilise le format de jeu de données local standard. Les étiquettes de tâche suivent l’action dispatchée. Les diagnostics restent dans les journaux de l’application ; ils ne sont ni écrits dans le jeu de données ni téléversés. Avec un jeu de données, utilisez `--dataset.single_task` pour l’instruction initiale ; sinon, utilisez `--task`. Préférez l’un à l’autre pour éviter une configuration conflictuelle.

## L'utiliser depuis Python

Les moteurs partagés et la configuration se trouvent dans `lerobot.inference` ; le client distant, le moteur et le serveur se trouvent dans `lerobot.remote_inference`. Une boucle de contrôle extérieure à `lerobot-rollout` connecte et admet un client, l’encapsule dans un moteur, publie les captures et achemine chaque tick moteur via `dispatch_tick`, qui applique le même contrat de permission, de maintien et d’accusé de réception que le CLI :

```python
import time

import numpy as np

from lerobot.inference import RemoteInferenceConfig, dispatch_tick
from lerobot.remote_inference import RemoteClient, RemoteInferenceEngine
from lerobot.utils.action_interpolator import ActionInterpolator

config = RemoteInferenceConfig(
    endpoint="tcp/127.0.0.1:7447",
    deployment="manipulation",
    semantics="so101-degrees-gripper-percent-v1",
)
client = RemoteClient.connect(config)
caps = client.capabilities
client.admit(
    features=caps.features,
    action_feature=caps.action_feature,
    semantics=config.semantics,
    action_interval=caps.action_interval,
    mode=config.mode,
)
engine = RemoteInferenceEngine(client, config, task="pick up the cube")
interpolator = ActionInterpolator(multiplier=1)

engine.start()
engine.resume()
try:
    while running():
        captured = time.monotonic()
        engine.submit_observation(
            {"observation.state": state_vector(), "observation.images.front": front_rgb()},
            capture_time=captured,
        )
        # send() receives a torch tensor in the deployment's action order; hold() refreshes
        # the last applied target. Returns None when the tick was held or starved.
        dispatch_tick(engine, interpolator, send=robot_send, hold=robot_hold)
finally:
    engine.stop()  # revokes motion and closes the client
```

Les observations sont indexées par les noms de fonctionnalités côté point de contrôle et doivent correspondre au schéma du serveur : vecteurs `float32` dans l’ordre des composants déclaré, images RGB `uint8` de la taille déclarée. [`tests/remote_inference/test_library_client.py`](https://github.com/huggingface/lerobot/blob/main/tests/remote_inference/test_library_client.py) exécute ce chemin face à un serveur en boucle locale et sert de référence pour la séquence d’appels. `lerobot-rollout` ajoute par-dessus la conversion du pilote, les vérifications de maintien de position, les commandes interactives et l’enregistrement ; `lerobot-policy-server` est le point d’entrée de service et ne se configure que par ses surcharges YAML et CLI.

Migration depuis lerobot[async]

L’extra `lerobot[async]` retiré et les commandes `lerobot.async_inference` sont remplacés par `lerobot[remote]`, `lerobot-policy-server` et `lerobot-rollout --inference.type=remote`. Les anciens seuils de taille de bloc et les poids d’agrégation ne sont pas interchangeables avec le refill, l’alignement et le blending ; réajustez à partir des [paramètres](#parameters-that-matter) ci-dessus.

L'emplacement d'importation `lerobot.rollout.inference` a été supprimé au profit de `lerobot.inference` et `lerobot.remote_inference`. Il n'existe pas d'option `hold_mode` : l'exécution à distance nécessite la déclaration de maintien de position du pilote, que le rollout vérifie automatiquement.

Pour Unitree G1 avec SONIC, suivez la [recette de télécommande G1](./unitree_g1#run-on-the-physical-robot) plutôt que d’adapter les anciennes commandes ; les contrôleurs de locomotion G1 ne sont toujours pas pris en charge.

Pour l’architecture, les contrats d’exécution et les extensions prévues, consultez la [référence de conception technique](https://github.com/huggingface/lerobot/blob/main/src/lerobot/remote_inference/README.md).

