litert-cli 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. examples/litert_cli.ipynb +313 -0
  2. examples/models/presets/default.py +19 -0
  3. examples/run_cli_demo.sh +38 -0
  4. examples/run_cli_npu.sh +89 -0
  5. examples/run_commands.sh +67 -0
  6. examples/run_models.sh +63 -0
  7. examples/run_smoke_tests.sh +58 -0
  8. examples/utils.ps1 +163 -0
  9. examples/utils.sh +184 -0
  10. litert_cli/__init__.py +15 -0
  11. litert_cli/commands/benchmark/__init__.py +16 -0
  12. litert_cli/commands/benchmark/android.py +212 -0
  13. litert_cli/commands/benchmark/cli.py +294 -0
  14. litert_cli/commands/benchmark/desktop.py +228 -0
  15. litert_cli/commands/benchmark/gcp.py +336 -0
  16. litert_cli/commands/clean.py +73 -0
  17. litert_cli/commands/compile.py +211 -0
  18. litert_cli/commands/convert/__init__.py +20 -0
  19. litert_cli/commands/convert/cli.py +255 -0
  20. litert_cli/commands/convert/generic.py +211 -0
  21. litert_cli/commands/convert/huggingface.py +175 -0
  22. litert_cli/commands/delete.py +56 -0
  23. litert_cli/commands/download.py +274 -0
  24. litert_cli/commands/import.py +124 -0
  25. litert_cli/commands/list.py +132 -0
  26. litert_cli/commands/lm.py +74 -0
  27. litert_cli/commands/quantize.py +193 -0
  28. litert_cli/commands/run/__init__.py +16 -0
  29. litert_cli/commands/run/android.py +394 -0
  30. litert_cli/commands/run/cli.py +297 -0
  31. litert_cli/commands/run/desktop.py +340 -0
  32. litert_cli/commands/visualize.py +234 -0
  33. litert_cli/core/android_utils.py +304 -0
  34. litert_cli/core/android_utils_test.py +236 -0
  35. litert_cli/core/constants.py +131 -0
  36. litert_cli/core/deps.py +180 -0
  37. litert_cli/core/deps_test.py +101 -0
  38. litert_cli/core/inputs.py +203 -0
  39. litert_cli/core/inputs_test.py +176 -0
  40. litert_cli/core/log_filters.py +50 -0
  41. litert_cli/core/models.py +96 -0
  42. litert_cli/core/npu_utils.py +382 -0
  43. litert_cli/core/targets_manager.py +192 -0
  44. litert_cli/core/utils.py +58 -0
  45. litert_cli/litert.py +119 -0
  46. litert_cli/litert_help_test.py +51 -0
  47. litert_cli/litert_test.py +88 -0
  48. litert_cli/models/__init__.py +145 -0
  49. litert_cli/models/asr/__init__.py +15 -0
  50. litert_cli/models/asr/asr_model.py +108 -0
  51. litert_cli/models/asr/parakeet_ctc.py +165 -0
  52. litert_cli/models/asr/runner.py +482 -0
  53. litert_cli/models/base.py +57 -0
  54. litert_cli/test_data/dummy_calib_data.py +26 -0
  55. litert_cli/test_data/dummy_cv_model.py +52 -0
  56. litert_cli/test_data/dummy_cv_model.tflite +0 -0
  57. litert_cli/test_data/generate_test_inputs.py +51 -0
  58. litert_cli/test_data/mobilenet_v3_calib_data.py +25 -0
  59. litert_cli/test_data/quantize_recipe.json +16 -0
  60. litert_cli/test_data/resnet18.py +31 -0
  61. litert_cli-0.1.0.dist-info/METADATA +38 -0
  62. litert_cli-0.1.0.dist-info/RECORD +67 -0
  63. litert_cli-0.1.0.dist-info/WHEEL +5 -0
  64. litert_cli-0.1.0.dist-info/entry_points.txt +2 -0
  65. litert_cli-0.1.0.dist-info/licenses/LICENSE +202 -0
  66. litert_cli-0.1.0.dist-info/top_level.txt +3 -0
  67. tools/build_wheels.py +122 -0
examples/utils.ps1 ADDED
@@ -0,0 +1,163 @@
1
+ # Copyright 2026 The LiteRT CLI Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+
16
+ # Shared utilities and helpers for LiteRT CLI demo scripts on Windows
17
+
18
+ $esc = [char]27
19
+ $GREEN = "$esc[0;32m"
20
+ $BLUE = "$esc[0;34m"
21
+ $YELLOW = "$esc[0;33m"
22
+ $RED = "$esc[0;31m"
23
+ $NC = "$esc[0m"
24
+ $BOLD = "$esc[1m"
25
+
26
+ $script:TOTAL_CASES = 0
27
+ $script:TOTAL_PASSED = 0
28
+ $script:TOTAL_FAILED = 0
29
+ $script:PASSED_CASES = @()
30
+ $script:FAILED_CASES = @()
31
+
32
+ # Helper for dynamic Android check (supports both authorized and unauthorized devices)
33
+ function Has-AndroidDevice {
34
+ try {
35
+ $devices = adb devices 2>$null
36
+ if ($null -ne $devices) {
37
+ foreach ($line in $devices) {
38
+ if ($line -match "\s+(device|unauthorized)$") {
39
+ return $true
40
+ }
41
+ }
42
+ }
43
+ } catch {}
44
+ return $false
45
+ }
46
+
47
+ # Helper to verify if LiteRT GPU accelerator is supported on Desktop (excluding software emulation like llvmpipe)
48
+ function Has-DesktopGpu {
49
+ param([string]$modelFile)
50
+
51
+ # Double escape backslashes for Python string literal
52
+ $pythonModelPath = $modelFile.Replace('\', '\\')
53
+
54
+ $pythonCmd = @"
55
+ import sys
56
+ try:
57
+ from ai_edge_litert.compiled_model import CompiledModel
58
+ from ai_edge_litert.hardware_accelerator import HardwareAccelerator
59
+ cm = CompiledModel.from_file('$pythonModelPath', HardwareAccelerator.GPU)
60
+ except Exception as e:
61
+ sys.exit(1)
62
+ "@
63
+
64
+ try {
65
+ $output = & python -c $pythonCmd 2>&1
66
+ $status = $LASTEXITCODE
67
+ if ($status -eq 0 -and $output -notmatch "llvmpipe" -and $output -notmatch "lavapipe") {
68
+ return $true
69
+ }
70
+ } catch {}
71
+ return $false
72
+ }
73
+
74
+ # Robust runner for a test command with isolation and formatting
75
+ function Run-Case {
76
+ param(
77
+ [string]$title,
78
+ [scriptblock]$cmdBlock
79
+ )
80
+
81
+ $esc = [char]27
82
+ $BLUE = "$esc[0;34m"
83
+ $GREEN = "$esc[0;32m"
84
+ $RED = "$esc[0;31m"
85
+ $NC = "$esc[0m"
86
+ $BOLD = "$esc[1m"
87
+
88
+ Write-Host ""
89
+ Write-Host "${BLUE}▶ Running:${NC} ${BOLD}$title${NC}"
90
+ $cmdStr = $cmdBlock.ToString().Trim()
91
+ Write-Host "$esc[90mCommand: $cmdStr$NC"
92
+ Write-Host "$esc[90m------------------------------------------------------------$NC"
93
+
94
+ $oldErrorActionPreference = $ErrorActionPreference
95
+ $ErrorActionPreference = "Continue"
96
+
97
+ & $cmdBlock
98
+ $status = $LASTEXITCODE
99
+
100
+ if ($null -eq $status) {
101
+ if ($?) { $status = 0 } else { $status = 1 }
102
+ }
103
+
104
+ $ErrorActionPreference = $oldErrorActionPreference
105
+
106
+ Write-Host "$esc[90m------------------------------------------------------------$NC"
107
+ if ($status -eq 0) {
108
+ Write-Host "${GREEN}✔ SUCCESS:${NC} ${GREEN}${BOLD}$title${NC}"
109
+ $script:TOTAL_PASSED++
110
+ $script:PASSED_CASES += $title
111
+ } else {
112
+ Write-Host "${RED}✘ FAILED (Exit Code: $status):${NC} ${RED}${BOLD}$title${NC}"
113
+ $script:TOTAL_FAILED++
114
+ $script:FAILED_CASES += $title
115
+ }
116
+ $script:TOTAL_CASES++
117
+ return $status
118
+ }
119
+
120
+ # Prints the final summary report for the demo
121
+ function Print-SummaryReport {
122
+ param([string]$modelName)
123
+
124
+ $esc = [char]27
125
+ $BLUE = "$esc[0;34m"
126
+ $GREEN = "$esc[0;32m"
127
+ $RED = "$esc[0;31m"
128
+ $NC = "$esc[0m"
129
+ $BOLD = "$esc[1m"
130
+
131
+ $upperModel = $modelName.ToUpper()
132
+
133
+ Write-Host ""
134
+ Write-Host "${BLUE}${BOLD}==================================================================${NC}"
135
+ Write-Host "${BLUE}${BOLD}>>> ${upperModel} TEST SUMMARY${NC}"
136
+ Write-Host "${BLUE}${BOLD}==================================================================${NC}"
137
+ Write-Host "Total Cases Run: ${BOLD}$script:TOTAL_CASES${NC}"
138
+ Write-Host "Passed: ${GREEN}${BOLD}$script:TOTAL_PASSED${NC}"
139
+ Write-Host "Failed: ${RED}${BOLD}$script:TOTAL_FAILED${NC}"
140
+
141
+ if ($script:TOTAL_PASSED -gt 0) {
142
+ Write-Host ""
143
+ Write-Host "${GREEN}${BOLD}Passed Cases:${NC}"
144
+ foreach ($case in $script:PASSED_CASES) {
145
+ Write-Host " - ${GREEN}$case${NC}"
146
+ }
147
+ }
148
+
149
+ if ($script:TOTAL_FAILED -gt 0) {
150
+ Write-Host ""
151
+ Write-Host "${RED}${BOLD}Failed Cases:${NC}"
152
+ foreach ($case in $script:FAILED_CASES) {
153
+ Write-Host " - ${RED}$case${NC}"
154
+ }
155
+ Write-Host "${BLUE}${BOLD}==================================================================${NC}"
156
+ Exit 1
157
+ }
158
+
159
+ Write-Host ""
160
+ Write-Host "${GREEN}${BOLD}All ${modelName} CLI commands executed successfully!${NC}"
161
+ Write-Host "${BLUE}${BOLD}==================================================================${NC}"
162
+ Exit 0
163
+ }
examples/utils.sh ADDED
@@ -0,0 +1,184 @@
1
+ #!/bin/bash
2
+ # Copyright 2026 The LiteRT CLI Authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ==============================================================================
16
+
17
+ # Shared utilities and helpers for LiteRT CLI demo scripts
18
+
19
+ # Color codes for beautiful output
20
+ GREEN='\033[0;32m'
21
+ BLUE='\033[0;34m'
22
+ YELLOW='\033[0;33m'
23
+ RED='\033[0;31m'
24
+ NC='\033[0m' # No Color
25
+ BOLD='\033[1m'
26
+
27
+ # Run case tracking variables
28
+ TOTAL_CASES=0
29
+ TOTAL_PASSED=0
30
+ TOTAL_FAILED=0
31
+ PASSED_CASES=()
32
+ FAILED_CASES=()
33
+
34
+ # Helper for dynamic Android check (supports both authorized and unauthorized devices)
35
+ function has_android_device() {
36
+ adb devices 2>/dev/null | grep -E -q "\s+(device|unauthorized)$"
37
+ }
38
+
39
+ # Helper to verify if LiteRT GPU accelerator is supported on Desktop (excluding software emulation like llvmpipe)
40
+ function has_desktop_gpu() {
41
+ local model_file="$1"
42
+ local output
43
+ output=$(python3 -c "
44
+ import sys
45
+ try:
46
+ from ai_edge_litert.compiled_model import CompiledModel
47
+ from ai_edge_litert.hardware_accelerator import HardwareAccelerator
48
+ cm = CompiledModel.from_file('$model_file', HardwareAccelerator.GPU)
49
+ except Exception:
50
+ sys.exit(1)
51
+ " 2>&1)
52
+ local status=$?
53
+
54
+ if [ $status -eq 0 ] && [[ ! "$output" =~ "llvmpipe" && ! "$output" =~ "lavapipe" ]]; then
55
+ return 0
56
+ else
57
+ return 1
58
+ fi
59
+ }
60
+
61
+
62
+
63
+ # Auto-detect REPO_ROOT from utils.sh location
64
+ export UTILS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
65
+ export REPO_ROOT="$(cd "$UTILS_DIR/.." && pwd)"
66
+
67
+ # Shared environment initialization for demo scripts
68
+ function setup_test_env() {
69
+ local test_name="$1"
70
+ local title="$2"
71
+ local extra_deps="${3:-}"
72
+
73
+ echo -e "${BLUE}${BOLD}==================================================================${NC}"
74
+ echo -e "${BLUE}${BOLD}>>> LiteRT CLI $title${NC}"
75
+ echo -e "${BLUE}${BOLD}==================================================================${NC}"
76
+
77
+ if [ "${LITERT_CLI_SHARED_VENV:-false}" == "true" ]; then
78
+ export LITERT_CLI_ROOT="/tmp/litert_cli_shared"
79
+ local test_root="$LITERT_CLI_ROOT"
80
+ mkdir -p "$test_root"
81
+ cd "$test_root"
82
+
83
+ if [ ! -d ".venv" ] || [ ! -f ".venv/bin/litert" ]; then
84
+ echo -e "\n${YELLOW}Creating Shared Python virtual environment with UV...${NC}"
85
+ UV_INDEX_URL=https://pypi.org/simple uv venv --clear --python=3.13 --seed
86
+ source .venv/bin/activate
87
+ echo -e "${YELLOW}Installing litert-cli with all extras into shared venv...${NC}"
88
+ uv pip install -e "$REPO_ROOT[convert,quantize,lm,compile]"
89
+ else
90
+ echo -e "\n${GREEN}Reusing existing shared virtual environment at $test_root...${NC}"
91
+ source .venv/bin/activate
92
+ fi
93
+ else
94
+ export LITERT_CLI_ROOT="/tmp/litert_cli_$test_name"
95
+ local test_root="$LITERT_CLI_ROOT"
96
+
97
+ echo -e "\n${YELLOW}Setting up isolated workspace at: $test_root...${NC}"
98
+ rm -rf "$test_root"
99
+ mkdir -p "$test_root"
100
+ cd "$test_root"
101
+
102
+ echo -e "${YELLOW}Creating Isolated Python virtual environment with UV...${NC}"
103
+ UV_INDEX_URL=https://pypi.org/simple uv venv --clear --python=3.13 --seed
104
+ source .venv/bin/activate
105
+
106
+ if [ -n "$extra_deps" ]; then
107
+ echo -e "${YELLOW}Installing litert-cli with [$extra_deps] extra...${NC}"
108
+ uv pip install -e "$REPO_ROOT[$extra_deps]"
109
+ else
110
+ echo -e "${YELLOW}Installing litert-cli...${NC}"
111
+ uv pip install -e "$REPO_ROOT"
112
+ fi
113
+ fi
114
+
115
+ export MODEL_DIR="$test_root/models"
116
+ export MODELS_CACHE="$test_root/models"
117
+ mkdir -p "$MODEL_DIR"
118
+
119
+ export TEST_DATA_DIR="$REPO_ROOT/litert_cli/test_data"
120
+ # Symlink test data directly into workspace for clean command syntax
121
+ ln -sf "$TEST_DATA_DIR/"* .
122
+ }
123
+
124
+
125
+ # Robust runner for a test command with isolation and formatting
126
+ function run_case() {
127
+ local title="$1"
128
+ shift
129
+
130
+ echo -e "\n${BLUE}▶ Running:${NC} ${BOLD}$title${NC}"
131
+ echo -e "\033[90mCommand: $*\033[0m"
132
+ echo -e "\033[90m------------------------------------------------------------\033[0m"
133
+
134
+ set +e
135
+ "$@"
136
+ local status=$?
137
+ set -e
138
+
139
+ echo -e "\033[90m------------------------------------------------------------\033[0m"
140
+ if [ $status -eq 0 ]; then
141
+ echo -e "${GREEN}✔ SUCCESS:${NC} ${GREEN}${BOLD}$title${NC}"
142
+ TOTAL_PASSED=$((TOTAL_PASSED + 1))
143
+ PASSED_CASES+=("$title")
144
+ else
145
+ echo -e "${RED}✘ FAILED (Exit Code: $status):${NC} ${RED}${BOLD}$title${NC}"
146
+ TOTAL_FAILED=$((TOTAL_FAILED + 1))
147
+ FAILED_CASES+=("$title")
148
+ fi
149
+ TOTAL_CASES=$((TOTAL_CASES + 1))
150
+ return $status
151
+ }
152
+
153
+ # Prints the final summary report for the demo
154
+ function print_summary_report() {
155
+ local model_name="$1"
156
+ local model_name_upper=$(echo "$model_name" | tr '[:lower:]' '[:upper:]')
157
+
158
+ echo -e "\n${BLUE}${BOLD}==================================================================${NC}"
159
+ echo -e "${BLUE}${BOLD}>>> ${model_name_upper} TEST SUMMARY${NC}"
160
+ echo -e "${BLUE}${BOLD}==================================================================${NC}"
161
+ echo -e "Total Cases Run: ${BOLD}$TOTAL_CASES${NC}"
162
+ echo -e "Passed: ${GREEN}${BOLD}$TOTAL_PASSED${NC}"
163
+ echo -e "Failed: ${RED}${BOLD}$TOTAL_FAILED${NC}"
164
+
165
+ if [ $TOTAL_PASSED -gt 0 ]; then
166
+ echo -e "\n${GREEN}${BOLD}Passed Cases:${NC}"
167
+ for case in "${PASSED_CASES[@]}"; do
168
+ echo -e " - ${GREEN}$case${NC}"
169
+ done
170
+ fi
171
+
172
+ if [ $TOTAL_FAILED -gt 0 ]; then
173
+ echo -e "\n${RED}${BOLD}Failed Cases:${NC}"
174
+ for case in "${FAILED_CASES[@]}"; do
175
+ echo -e " - ${RED}$case${NC}"
176
+ done
177
+ echo -e "${BLUE}${BOLD}==================================================================${NC}"
178
+ exit 1
179
+ fi
180
+
181
+ echo -e "${GREEN}${BOLD}All ${model_name} CLI commands executed successfully!${NC}"
182
+ echo -e "${BLUE}${BOLD}==================================================================${NC}"
183
+ exit 0
184
+ }
litert_cli/__init__.py ADDED
@@ -0,0 +1,15 @@
1
+ # Copyright 2026 The LiteRT CLI Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+
@@ -0,0 +1,16 @@
1
+ # Copyright 2026 The LiteRT CLI Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+
16
+ """CLI command for benchmarking LiteRT models."""
@@ -0,0 +1,212 @@
1
+ # Copyright 2026 The LiteRT CLI Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+
16
+ """Android Benchmark Module."""
17
+
18
+ from __future__ import annotations
19
+
20
+ import pathlib
21
+ import shlex
22
+ import subprocess
23
+
24
+ import click
25
+ from litert_cli.core import android_utils
26
+ from litert_cli.core import constants
27
+ from litert_cli.core import npu_utils as npu
28
+
29
+
30
+ def run_android(
31
+ *,
32
+ model_path: pathlib.Path,
33
+ accelerator: str,
34
+ num_runs: int = 50,
35
+ warmup_runs: int = 1,
36
+ min_secs: float = 1.0,
37
+ max_secs: float = 150.0,
38
+ warmup_min_secs: float = 0.5,
39
+ input_layer_value_range: str | None = None,
40
+ signature_key: str | None = None,
41
+ ) -> None:
42
+ """Runs the model on an Android device.
43
+
44
+ Pushes the model and benchmark_model binary to the device and runs it.
45
+
46
+ Args:
47
+ model_path: Path to the local LiteRT model file.
48
+ accelerator: Hardware accelerator to use (cpu, gpu, npu).
49
+ num_runs: Target number of benchmark iterations.
50
+ warmup_runs: Number of warmup iterations before benchmarking.
51
+ min_secs: Minimum seconds to run.
52
+ max_secs: Maximum seconds to run.
53
+ warmup_min_secs: Minimum warmup duration in seconds.
54
+ input_layer_value_range: Value range for input layers.
55
+ signature_key: The signature key to benchmark.
56
+
57
+ Raises:
58
+ subprocess.CalledProcessError: If any adb command fails on the device.
59
+ """
60
+ click.echo("Preparing to run on Android device via adb...")
61
+
62
+ android_utils.check_adb()
63
+ abi = android_utils.get_android_abi()
64
+ click.echo(f"Detected Android device ABI: {abi}")
65
+
66
+ cli_android_root = constants.LITERT_CLI_ANDROID_ROOT
67
+
68
+ model_name = model_path.name
69
+ remote_model_path = f"{cli_android_root}/{model_name}"
70
+
71
+ benchmark_model_bin = android_utils.find_android_binary(
72
+ "benchmark_model", abi
73
+ )
74
+
75
+ remote_dispatch_dir = ""
76
+ if accelerator == "npu":
77
+ remote_dispatch_dir = npu.push_npu_runtime_libraries(None, cli_android_root)
78
+
79
+ # Download and push SOC-specific LiteRT dispatch and compiler plugin libraries
80
+ target_model = npu.get_soc_target_model(None)
81
+ soc_vendor = "mediatek" if "mt" in target_model else "qualcomm"
82
+ lib_dispatch = android_utils.find_npu_dispatch_lib(soc_vendor, abi)
83
+ lib_compiler = android_utils.find_npu_compiler_plugin_lib(soc_vendor, abi)
84
+
85
+ remote_lib_dispatch = f"{cli_android_root}/{lib_dispatch.name}"
86
+ if (
87
+ subprocess.run(
88
+ ["adb", "shell", f"[ -f {remote_lib_dispatch} ]"], check=False
89
+ ).returncode
90
+ == 0
91
+ ):
92
+ click.echo(f" Skipping {lib_dispatch.name} (already on device)")
93
+ else:
94
+ click.echo(f"Pushing {lib_dispatch.name} to device...")
95
+ subprocess.run(
96
+ ["adb", "push", str(lib_dispatch), remote_lib_dispatch], check=True
97
+ )
98
+
99
+ remote_lib_compiler = f"{cli_android_root}/{lib_compiler.name}"
100
+ if (
101
+ subprocess.run(
102
+ ["adb", "shell", f"[ -f {remote_lib_compiler} ]"], check=False
103
+ ).returncode
104
+ == 0
105
+ ):
106
+ click.echo(f" Skipping {lib_compiler.name} (already on device)")
107
+ else:
108
+ click.echo(f"Pushing {lib_compiler.name} to device...")
109
+ subprocess.run(
110
+ ["adb", "push", str(lib_compiler), remote_lib_compiler], check=True
111
+ )
112
+
113
+ click.echo(f"Pushing model {model_name} to device...")
114
+ subprocess.run(["adb", "shell", "mkdir", "-p", cli_android_root], check=True)
115
+ subprocess.run(
116
+ ["adb", "push", str(model_path), remote_model_path], check=True
117
+ )
118
+
119
+ click.echo("Pushing benchmark_model to device...")
120
+ subprocess.run(
121
+ [
122
+ "adb",
123
+ "push",
124
+ str(benchmark_model_bin),
125
+ f"{cli_android_root}/benchmark_model",
126
+ ],
127
+ check=True,
128
+ )
129
+ subprocess.run(
130
+ ["adb", "shell", "chmod", "+x", f"{cli_android_root}/benchmark_model"],
131
+ check=True,
132
+ )
133
+
134
+ click.echo("Executing benchmark on device...\n")
135
+ try:
136
+ bench_args = [
137
+ f"{cli_android_root}/benchmark_model",
138
+ f"--graph={shlex.quote(remote_model_path)}",
139
+ ]
140
+ if accelerator == "gpu":
141
+ bench_args.append("--use_gpu=true")
142
+ elif accelerator == "npu":
143
+ bench_args.append("--use_npu=true")
144
+ bench_args.append(f"--dispatch_library_path={shlex.quote(cli_android_root)}")
145
+ bench_args.append(
146
+ f"--compiler_plugin_library_path={shlex.quote(cli_android_root)}"
147
+ )
148
+
149
+ if soc_vendor == "mediatek":
150
+ recommend_version = constants.MEDIATEK_SOC_VERSION_MAP.get(
151
+ target_model, ""
152
+ )
153
+ if "v9" in recommend_version:
154
+ bench_args.append("--mediatek_nerun_pilot_version=version9")
155
+ elif "v8" in recommend_version:
156
+ bench_args.append("--mediatek_nerun_pilot_version=version8")
157
+
158
+ if num_runs != 50:
159
+ bench_args.append(f"--num_runs={num_runs}")
160
+ if warmup_runs != 1:
161
+ bench_args.append(f"--warmup_runs={warmup_runs}")
162
+ if min_secs != 1.0:
163
+ bench_args.append(f"--min_secs={min_secs}")
164
+ if max_secs != 150.0:
165
+ bench_args.append(f"--max_secs={max_secs}")
166
+ if warmup_min_secs != 0.5:
167
+ bench_args.append(f"--warmup_min_secs={warmup_min_secs}")
168
+ if input_layer_value_range:
169
+ bench_args.append(
170
+ f"--input_layer_value_range={shlex.quote(input_layer_value_range)}"
171
+ )
172
+ if signature_key:
173
+ bench_args.append(f"--signature_to_run_for={shlex.quote(signature_key)}")
174
+
175
+ env_vars = ""
176
+ if remote_dispatch_dir:
177
+ quoted_dispatch_dir = shlex.quote(remote_dispatch_dir)
178
+ env_vars = (
179
+ f"LD_LIBRARY_PATH={quoted_dispatch_dir} "
180
+ f"ADSP_LIBRARY_PATH={quoted_dispatch_dir} "
181
+ )
182
+
183
+ full_command = env_vars + " ".join(bench_args)
184
+ process = subprocess.Popen(
185
+ ["adb", "shell", full_command],
186
+ stdout=subprocess.PIPE,
187
+ stderr=subprocess.STDOUT,
188
+ text=True,
189
+ )
190
+
191
+ from litert_cli.core.log_filters import BenchmarkLogFilter
192
+
193
+ output_lines = []
194
+ log_filter = BenchmarkLogFilter(constants.DEFAULT_QUIET)
195
+
196
+ for line in process.stdout:
197
+ output_lines.append(line)
198
+ if log_filter.should_show(line):
199
+ click.echo(line, nl=False)
200
+
201
+ process.wait()
202
+ if process.returncode != 0:
203
+ click.secho(
204
+ f"Execution failed on device with exit code {process.returncode}",
205
+ fg="red",
206
+ )
207
+ click.echo("Full output for debugging:")
208
+ for line in output_lines:
209
+ click.echo(line, nl=False)
210
+ raise click.ClickException("Benchmark failed on device.")
211
+ except Exception as e:
212
+ raise click.ClickException(f"Failed to execute benchmark on device: {e}")