Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ INSTALL_HYS.md
AGENTS.md
_version.py.mcp.json
telefuser/_version.py
!telefuser/pipelines/lingbot_vla_v2/assets/*.json
# LingBot regression example assets
!examples/data/lingbot_world_fast/image.jpg
!examples/data/lingbot_world_fast/poses.npy
Expand Down
31 changes: 29 additions & 2 deletions benchmarks/telefuser_aiperf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,31 @@ Available batch configs:
| `configs/video_generation_rate.yaml` | Poisson-arrival load |
| `configs/video_generation_wan21_i2v_480p_compare.yaml` | Fixed Wan2.1 I2V comparison |

## LingBot-VLA v2 Structured Actions

Start the native VLA service from its isolated model environment, then run the AIPerf workload from the repository
root:

```bash
bash benchmarks/telefuser_aiperf/scripts/run_vla_structured_bench.sh
```

The repository-owned `telefuser_vla_structured` endpoint and `telefuser_structured_http` transport submit
`POST /v1/tasks/structured`, poll `GET /v1/tasks/{task_id}/status`, and pass request latency, throughput, success,
trace, and server metric facts into AIPerf's normal warmup and aggregation pipeline. Defaults are two excluded warmup
requests followed by 20 measured requests at concurrency one. Override them without changing the checked-in config:

```bash
TELEFUSER_AIPERF_REQUESTS=100 \
TELEFUSER_AIPERF_CONCURRENCY=2 \
bash benchmarks/telefuser_aiperf/scripts/run_vla_structured_bench.sh
```

Each terminal result is required to contain a finite `50x55` action chunk and the frozen structured result fields.
The adapter retains an action hash, bounds, dimensions, verification status, target inference time, and peak memory;
it does not copy full action arrays or Base64 cameras into AIPerf response records. This validates service execution
and normalized action structure, not physical robot control semantics.

## LingBot-World v2 Streaming

The v2 pipeline expects the following files below `TF_MODEL_ZOO_PATH`:
Expand Down Expand Up @@ -264,10 +289,12 @@ AIPerf environment first, then run the checks from the repository root:
PYTHONPATH=benchmarks/telefuser_aiperf \
.venv-aiperf/bin/python -m pytest \
benchmarks/telefuser_aiperf/tests/test_livekit_adapter.py \
benchmarks/telefuser_aiperf/tests/test_sglang_adapter.py
benchmarks/telefuser_aiperf/tests/test_sglang_adapter.py \
benchmarks/telefuser_aiperf/tests/test_vla_structured.py

bash -n \
scripts/setup_aiperf.sh \
benchmarks/telefuser_aiperf/scripts/run_stream_bench.sh \
benchmarks/telefuser_aiperf/scripts/run_sglang_lingbot_world_v2_4gpu.sh
benchmarks/telefuser_aiperf/scripts/run_sglang_lingbot_world_v2_4gpu.sh \
benchmarks/telefuser_aiperf/scripts/run_vla_structured_bench.sh
```
49 changes: 49 additions & 0 deletions benchmarks/telefuser_aiperf/configs/vla_structured_e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# yaml-language-server: $schema=../../aiperf/src/aiperf/config/schema/aiperf-config.schema.json

schemaVersion: "2.0"

randomSeed: 42

benchmark:
model: lingbot-vla-v2-6b

endpoint:
url: ${TELEFUSER_AIPERF_URL:http://127.0.0.1:18080}
type: telefuser_vla_structured
transport: telefuser_structured_http
timeout: ${TELEFUSER_AIPERF_TIMEOUT:120}

tokenizer:
name: builtin

dataset:
type: file
path: ./benchmarks/telefuser_aiperf/data/vla_structured.jsonl
format: single_turn
sampling: sequential

warmup:
type: concurrency
concurrency: 1
requests: ${TELEFUSER_AIPERF_WARMUP_REQUESTS:2}
excludeFromResults: true

profiling:
type: concurrency
concurrency: ${TELEFUSER_AIPERF_CONCURRENCY:1}
requests: ${TELEFUSER_AIPERF_REQUESTS:20}
duration: ${TELEFUSER_AIPERF_DURATION:3600}
gracePeriod: ${TELEFUSER_AIPERF_GRACE_PERIOD:120}

artifacts:
dir: ./artifacts/telefuser_aiperf/vla_structured
summary: [json]
records: [jsonl]
showTraceTiming: true
trace: true

serverMetrics:
enabled: ${TELEFUSER_AIPERF_SERVER_METRICS:true}
urls:
- ${TELEFUSER_AIPERF_METRICS_URL:http://127.0.0.1:18080/v1/service/metrics}
formats: [json, csv]
1 change: 1 addition & 0 deletions benchmarks/telefuser_aiperf/data/vla_structured.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"text":"pick up the object","image":"examples/data/101235-video-720_0.png","extra":{"state":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],"seed":7}}
25 changes: 25 additions & 0 deletions benchmarks/telefuser_aiperf/scripts/run_vla_structured_bench.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
cd "${ROOT_DIR}"

CONFIG_PATH="${1:-benchmarks/telefuser_aiperf/configs/vla_structured_e2e.yaml}"
SERVER_URL="${TELEFUSER_AIPERF_URL:-http://127.0.0.1:18080}"
HEALTH_URL="${TELEFUSER_AIPERF_HEALTH_URL:-${SERVER_URL}/v1/service/ready}"
DEFAULT_PYTHON="${ROOT_DIR}/.venv-aiperf/bin/python"
ADAPTER_ROOT="${ROOT_DIR}/benchmarks/telefuser_aiperf"
AIPERF_PYTHON="${TELEFUSER_AIPERF_PYTHON:-${DEFAULT_PYTHON}}"

if [[ ! -x "${AIPERF_PYTHON}" ]]; then
echo "The isolated AIPerf environment is unavailable. Run: bash scripts/setup_aiperf.sh" >&2
exit 1
fi

if command -v curl >/dev/null 2>&1; then
echo "Checking TeleFuser VLA readiness: ${HEALTH_URL}"
curl --noproxy '*' --fail --silent --show-error "${HEALTH_URL}" >/dev/null
fi

export PYTHONPATH="${ADAPTER_ROOT}${PYTHONPATH:+:${PYTHONPATH}}"
exec "${AIPERF_PYTHON}" -m telefuser_aiperf.cli profile --config "${CONFIG_PATH}"
47 changes: 46 additions & 1 deletion benchmarks/telefuser_aiperf/telefuser_aiperf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

from telefuser_aiperf.adapter import TeleFuserLiveKitAdapter
from telefuser_aiperf.sglang_adapter import SGLangRealtimeAdapter
from telefuser_aiperf.vla_structured import (
ENDPOINT_METADATA,
TRANSPORT_METADATA,
TeleFuserStructuredHttpTransport,
TeleFuserVlaStructuredEndpoint,
)


def register_adapters(*, replace: bool = False) -> None:
Expand All @@ -23,4 +29,43 @@ def register_adapters(*, replace: bool = False) -> None:
)


__all__ = ["SGLangRealtimeAdapter", "TeleFuserLiveKitAdapter", "register_adapters"]
def register_plugins(*, replace: bool = False) -> None:
"""Register repository-owned AIPerf batch endpoint and transport plugins."""
from aiperf.plugin import plugins
from aiperf.plugin.enums import EndpointType, TransportType

if "telefuser_vla_structured" not in EndpointType:
EndpointType.register("TELEFUSER_VLA_STRUCTURED", "telefuser_vla_structured")
if "telefuser_structured_http" not in TransportType:
TransportType.register("TELEFUSER_STRUCTURED_HTTP", "telefuser_structured_http")

definitions = (
(
"endpoint",
"telefuser_vla_structured",
TeleFuserVlaStructuredEndpoint,
ENDPOINT_METADATA,
),
(
"transport",
"telefuser_structured_http",
TeleFuserStructuredHttpTransport,
TRANSPORT_METADATA,
),
)
for category, name, plugin_class, metadata in definitions:
if plugins.has_entry(category, name):
if not replace:
continue
plugins.unregister(category, name)
plugins.register(category, name, plugin_class, metadata=metadata)


__all__ = [
"SGLangRealtimeAdapter",
"TeleFuserLiveKitAdapter",
"TeleFuserStructuredHttpTransport",
"TeleFuserVlaStructuredEndpoint",
"register_adapters",
"register_plugins",
]
3 changes: 2 additions & 1 deletion benchmarks/telefuser_aiperf/telefuser_aiperf/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
def main() -> None:
"""Register TeleFuser adapters and delegate to the AIPerf CLI."""

from telefuser_aiperf import register_adapters
from telefuser_aiperf import register_adapters, register_plugins

register_adapters()
register_plugins()

from aiperf.cli import app

Expand Down
Loading
Loading