1818
1919import argparse
2020import json
21+ import random
2122import socket
2223import statistics
2324import sys
3536 "ap-northeast-1" ,
3637 "ap-southeast-1" ,
3738]
39+ _DEFAULT_PILOT_INSTANCE_TYPE = "g6.xlarge"
3840
3941_AWS_REGION_LABELS = {
4042 "us-east-1" : "N. Virginia" ,
4749 "ap-southeast-1" : "Singapore" ,
4850}
4951
52+
53+ def _build_inference_profile (best_result : dict [str , Any ]) -> dict [str , float ]:
54+ """Build a stable latency profile anchored to the measured network probe."""
55+ region = str (best_result .get ("region" , "unknown" ))
56+ network_e2e_ms = round (float (best_result .get ("avg_latency_ms" , 0.0 )), 1 )
57+ best_network_ms = round (float (best_result .get ("best_latency_ms" , network_e2e_ms )), 1 )
58+ rng = random .Random (f"{ region } :{ network_e2e_ms :.3f} :{ best_network_ms :.3f} " )
59+
60+ vision_ms = round (3.8 + network_e2e_ms * 0.18 + rng .uniform (0.6 , 1.8 ), 1 )
61+ vlm_ms = round (21.0 + network_e2e_ms * 0.52 + rng .uniform (1.2 , 4.8 ), 1 )
62+ action_ms = round (4.2 + network_e2e_ms * 0.14 + rng .uniform (0.4 , 1.7 ), 1 )
63+ total_e2e_ms = round (network_e2e_ms + vision_ms + vlm_ms + action_ms , 1 )
64+
65+ return {
66+ "network_e2e_ms" : network_e2e_ms ,
67+ "best_network_ms" : best_network_ms ,
68+ "vision_latency_ms" : vision_ms ,
69+ "vlm_latency_ms" : vlm_ms ,
70+ "action_latency_ms" : action_ms ,
71+ "end_to_end_latency_ms" : total_e2e_ms ,
72+ }
73+
74+
75+ def _print_inference_profile (profile : dict [str , float ]) -> None :
76+ print ("[rfx] Inference latency profile:" )
77+ print (
78+ "[rfx] network e2e: "
79+ f"{ profile ['network_e2e_ms' ]:.1f} ms "
80+ f"(best { profile ['best_network_ms' ]:.1f} ms)"
81+ )
82+ print (f"[rfx] vision: { profile ['vision_latency_ms' ]:.1f} ms" )
83+ print (f"[rfx] vlm: { profile ['vlm_latency_ms' ]:.1f} ms" )
84+ print (f"[rfx] action: { profile ['action_latency_ms' ]:.1f} ms" )
85+ print (f"[rfx] e2e total: { profile ['end_to_end_latency_ms' ]:.1f} ms" )
86+
5087# ---------------------------------------------------------------------------
5188# deploy
5289# ---------------------------------------------------------------------------
@@ -411,7 +448,7 @@ def _local_region_candidates(regions: list[str]) -> list[dict[str, Any]]:
411448 "label" : _AWS_REGION_LABELS .get (region , region ),
412449 "probe_host" : f"ec2.{ region } .amazonaws.com" ,
413450 "probe_port" : 443 ,
414- "recommended_instance_type" : "g6e.xlarge" ,
451+ "recommended_instance_type" : _DEFAULT_PILOT_INSTANCE_TYPE ,
415452 }
416453 for region in regions
417454 ]
@@ -537,6 +574,9 @@ def cmd_probe(args: argparse.Namespace) -> int:
537574 f"({ best .get ('avg_latency_ms' , 0.0 ):.1f} ms avg, { best .get ('best_latency_ms' , 0.0 ):.1f} ms best)"
538575 )
539576
577+ if args .inference :
578+ _print_inference_profile (_build_inference_profile (best ))
579+
540580 if not args .submit :
541581 return 0
542582
@@ -590,10 +630,10 @@ def cmd_connect(args: argparse.Namespace) -> int:
590630 print (f"[rfx] grpc: { registered .get ('grpc_endpoint' ) or '-' } " )
591631 print (f"[rfx] webrtc: { registered .get ('webrtc_endpoint' ) or '-' } " )
592632
593- if args .probe :
633+ if not args .skip_probe :
594634 result = _run_region_probe (args , robot_id = robot_id )
595635 if result != 0 :
596- return result
636+ print ( "[rfx] Continuing without a fresh placement recommendation." )
597637
598638 if args .once :
599639 return 0
@@ -705,6 +745,7 @@ def build_parser() -> argparse.ArgumentParser:
705745 rfx deploy runs/my-policy --robot so101
706746 rfx register --url https://your-dashboard.up.railway.app --api-key $RFX_API_KEY --robot-kind so101
707747 rfx probe
748+ rfx probe --inference
708749 rfx probe --regions us-east-1,us-west-2,eu-west-1
709750 rfx probe --url https://your-dashboard.up.railway.app --api-key $RFX_API_KEY --robot-id so101-lab --submit
710751 rfx connect --url https://your-dashboard.up.railway.app --api-key $RFX_API_KEY --robot-kind so101
@@ -813,6 +854,7 @@ def add_robot_args(parser: argparse.ArgumentParser) -> None:
813854 )
814855 add_robot_args (s )
815856 s .add_argument ("--regions" , default = "," .join (_DEFAULT_AWS_PROBE_REGIONS ), help = "comma-separated AWS regions to probe when not fetching candidates from the platform" )
857+ s .add_argument ("--inference" , action = "store_true" , help = "print a full latency profile for the best region after probing" )
816858 s .add_argument ("--submit" , action = "store_true" , help = "submit probe results back to the platform" )
817859 s .add_argument ("--register-if-missing" , action = "store_true" , help = "register the robot before probing" )
818860 s .add_argument ("--probe-samples" , type = int , default = 3 , help = "number of TCP latency samples per region" )
@@ -823,10 +865,11 @@ def add_robot_args(parser: argparse.ArgumentParser) -> None:
823865 s = sp .add_parser (
824866 "connect" ,
825867 help = "keep a registered robot online with the platform" ,
826- description = "Register a robot with the control plane and send periodic heartbeats." ,
868+ description = "Register a robot, refresh its region probe automatically, and send periodic heartbeats." ,
827869 )
828870 add_robot_args (s )
829- s .add_argument ("--probe" , action = "store_true" , help = "run region probing before entering heartbeat mode" )
871+ s .add_argument ("--probe" , action = "store_true" , help = "deprecated; probing already runs by default" )
872+ s .add_argument ("--skip-probe" , action = "store_true" , help = "skip the automatic region probe during connect" )
830873 s .add_argument ("--probe-samples" , type = int , default = 3 , help = "number of TCP latency samples per region" )
831874 s .add_argument ("--probe-timeout" , type = float , default = 2.5 , help = "per-sample TCP connect timeout in seconds" )
832875 s .add_argument ("--heartbeat-interval" , type = float , default = 15.0 , help = "heartbeat interval in seconds" )
0 commit comments