| 88 | | |
| 89 | | = NXP Ara240 DNPU AI Accelerator Quick Start |
| 90 | | |
| 91 | | [=#ara2-runtime] |
| 92 | | == Ara Runtime |
| 93 | | NXP has a runtime library for the Ara240 which consists of some statically built libraries as well as a dynamic linked GStreamer plugin. |
| 94 | | |
| 95 | | The Ara runtime includes a couple of Python Wheels. A Python Wheel is a standard built-package format for distributing Python libraries. It is essentially a ZIP-format archive with a .whl extension that contains all the files needed for a package to run immediately after being. It's fairly standard when using Python to run into package version incompatibilities which is why user based Python virtual environments are used. |
| 96 | | |
| 97 | | The Ara runtime provides a complete runtime environment for AI/ML acceleration using the Ara240 NPU on for aarch64. This package includes: |
| 98 | | * Runtime libraries for Ara240 NPU integration |
| 99 | | * Python bindings (DVAPI) for custom inference applications |
| 100 | | * Optimum-Ara framework for LLMs and VLMs |
| 101 | | * GStreamer plugin for Real-Time Detection Object Applications |
| 102 | | * Helper scripts for monitoring, benchmarking, and model management |
| 103 | | * Systemd service for automatic hardware initialization |
| 104 | | |
| 105 | | Installation on a Gateworks board with Ubuntu based OS: |
| 106 | | - Download and extract the self-extracting binary from NXP: |
| 107 | | {{{#!bash |
| 108 | | VER=imx-nxp-ara2-2.1.1-063d56c |
| 109 | | wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/$VER.bin |
| 110 | | sh $VER.bin |
| 111 | | }}} |
| 112 | | - take care of postinst steps |
| 113 | | - miscellaneous |
| 114 | | {{{#!bash |
| 115 | | # create dirs (used for models) |
| 116 | | mkdir -pv /usr/share/{cnn,llm} |
| 117 | | }}} |
| 118 | | - configure swap (necessary if using VLM) |
| 119 | | {{{#!bash |
| 120 | | /usr/bin/enable_swap 2 |
| 121 | | }}} |
| 122 | | - install uv package manager for Python virtualization and packaging for local user (which is installed to ~/.local/bin so we create symlinks to /usr/bin) |
| 123 | | {{{#!bash |
| 124 | | apt update && apt install -y curl |
| 125 | | curl -LsSf https://astral.sh/uv/install.sh | sh |
| 126 | | ln -s /root/.local/bin/uv /usr/bin/uv |
| 127 | | ln -s /root/.local/bin/uvx /usr/bin/uvx |
| 128 | | }}} |
| 129 | | - build driver |
| 130 | | {{{#!bash |
| 131 | | apt update && apt install -y build-essential git bc file flex bison |
| 132 | | git clone https://github.com/nxp-imx-support/uiodma-driver |
| 133 | | ( cd uiodma-driver/uiodma; make ) |
| 134 | | # install it where the rt service expects to find it (over the top of the non-compatible one) |
| 135 | | cp uiodma-driver/uiodma/uiodma.ko /usr/share/rt-sdk-ara240/driver/ |
| 136 | | }}} |
| 137 | | - enable service: |
| 138 | | {{{#!bash |
| 139 | | # enable service |
| 140 | | systemctl enable rt-sdk-ara2.service |
| 141 | | # start service now (unless you reboot) |
| 142 | | systemctl start rt-sdk-ara2.service |
| 143 | | }}} |
| 144 | | - use 'fetch_models' to pre-compiled models for testing via the fetch_models script which will fetch models from !HuggingFace. |
| 145 | | {{{#!bash |
| 146 | | # list models available for nxp/ara |
| 147 | | fetch_models --list |
| 148 | | # install YOLOv8 |
| 149 | | fetch_models --repo-id nxp/YOLOv8 # 746MB (711MiB) |
| 150 | | }}} |
| 151 | | - the script is a python wrapper that uses uvx and the fetch-models python wheel (/usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl) to fetch and install models from !HuggingFace HUB |
| 152 | | - the models will be installed in either /usr/share/cnn (Convolutional Neural Network) and /usr/share/llm (Large Language Model) |
| 153 | | - NXP has Ara2 optimized models at https://huggingface.co/nxp |
| 154 | | - the script has a hard coded list of models available and where to install them locally. You can use 'python -m zipfile -e /usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl ./fetch_models' to see what it's doing |
| 155 | | |
| 156 | | Notable Files: |
| 157 | | - /usr/lib/ |
| 158 | | - libaraclient_aarch64.so - base library for interfacing with ara2 |
| 159 | | - libara_vision_inference.so - inference lib that builds on libaraclient |
| 160 | | - /usr/lib/gstreamer-1.0 |
| 161 | | - libgstdvInf.so - GStreamer plugin |
| 162 | | - /usr/share/rt-sdk-ara240 (symlink to a version independent dir at same location) |
| 163 | | - hw_utils/boot_img - firmware files |
| 164 | | - hw_utils/ddr_config - ddr binaries |
| 165 | | - hw_utils/bins/ - the hw utils for bringup/programming |
| 166 | | - optimum-ara/ - extension of the Hugging Face library that integrates with Ara240 DNPU |
| 167 | | - scripts - various wrappers around the tools etc |
| 168 | | - nnapp - tool for benchmarking models |
| 169 | | - config - various example yaml config files used for proxy/nnapp |
| 170 | | - include/dvapi.py - python bindings to dvapi |
| 171 | | - driver/uiodma.ko - driver (where the setup script expects to find it) |
| 172 | | - /usr/share/python-wheels - python wheels for fetch_models and optimum_ara |
| 173 | | - /usr/shar/doc/rt-sdk-ara2 - license info |
| 174 | | - /usr/include/sdk_ara - headers for C libs |
| 175 | | - /usr/bin - various scripts |
| 176 | | - /etc/udev/rules.d/99-ara2.rules - udev rule which makes the PCI ID dependent on the systemd service |
| 177 | | - /etc/systemd/system/rt-sdk-ara2.service - systemd service that handles the various hw util config |
| 178 | | - /etc/rt-sdk-ara240/cnn_config.yaml - config for nnapp |
| 179 | | - /etc/rt-sdk-ara240/proxy_config.yam - config for proxy |
| 180 | | |
| 181 | | Notes: |
| 182 | | - The 'uv' package manager is a fast all-in-one Python package and project manager written in Rust which makes it easy to work with virtual env's to avoid Python package version clashing which is essential |
| 183 | | - on bootup make sure you wait for the console messages indicating the Proxy is launched before using it as it can take a couple of minutes |
| 184 | | - the binary tools and libs are all static linked for compatibility |
| 185 | | - the GStreamer libs require GStreamer 1.26 or newer and is dynamic linked |
| 186 | | |
| 187 | | Verification steps: |
| 188 | | 1. show chip_info |
| 189 | | {{{#!bash |
| 190 | | chip_info.sh |
| 191 | | }}} |
| 192 | | 1. verify service |
| 193 | | {{{#!bash |
| 194 | | # show service status |
| 195 | | systemctl status rt-sdk-ara2.service --no-pager -l |
| 196 | | # view detailed service logs for the current boot and follow the journal |
| 197 | | journalctl --boot --follow --unit rt-sdk-ara2.service |
| 198 | | # verify proxy is running (critical) |
| 199 | | ps -eaf | grep proxy_ara240 |
| 200 | | }}} |
| 201 | | |
| 202 | | Examples: |
| 203 | | - Download pre-compiled models for testing: |
| 204 | | - The fetch_models script from the ara2-rt will fetch models from !HuggingFace. |
| 205 | | {{{#!bash |
| 206 | | # list models available for nxp/ara |
| 207 | | fetch_models --list |
| 208 | | # install YOLOv8 |
| 209 | | fetch_models --repo-id nxp/YOLOv8 # 746MB (711MiB) |
| 210 | | }}} |
| 211 | | - the 'fetch_models' script is a python wrapper that uses uvx and the fetch-models python wheel (/usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl) to fetch and install models from !HuggingFace HUB |
| 212 | | - the models will be installed in /usr/share/cnn (Convolutional Neural Network) and /usr/share/llm (Large Language Model) |
| 213 | | - NXP has Ara2 optimized models at https://huggingface.co/nxp |
| 214 | | - Run performance benchmark (uses nnapp) |
| 215 | | {{{#!bash |
| 216 | | run_model_perf.sh |
| 217 | | }}} |
| 218 | | - the 'run_model_perf.sh' script makes it easy to list and show model categories and models and is a wrapper around the nnapp app which has a lot of options and a config file |
| 219 | | - monitor real-time NPU metrics including utilization, temperature, DRAM usage and device state (interactively during benchmarking or model execution) |
| 220 | | {{{#!bash |
| 221 | | ara2_metrics.sh |
| 222 | | }}} |
| 223 | | |
| 224 | | [=#gstreamer] |
| 225 | | === GStreamer plugins |
| 226 | | The Ara runtime provides an OpenSource GStreamer plugin for detection models: |
| 227 | | - [https://github.com/nxp-imx-support/gstreamer-plugins-ara240 dvInf] |
| 228 | | |
| 229 | | The plugin can sink 32bit pixel samples (ie format=BGRx using 4 bytes per pixel, blue, green, red, and a pading byte as a structural spacer) |
| 230 | | |
| 231 | | The model is specified via the 'model' property. If using yolov8x for example you would specify the path to the yolov8x.dvm |
| 232 | | |
| 233 | | For detection models the element frame data will contain a buffer with number of bytes (32bit) followed by a series of detection structures containing the bounding box, confidence level, and COCO class ID of the object detected. |
| 234 | | |
| 235 | | The units for the bounding box are relative to the models size and will need to be scaled back to your original image size. For example the YOLO models operate on 640x640 pixel data. You can pass something larger in and it will essentially tile but its unclear if there is an advantage of doing that. |
| 236 | | |
| 237 | | While the gstreamer plugin source provided is provided [https://github.com/nxp-imx-support/gstreamer-plugins-ara240 here] it is included in the Ara runtime pre-compiled for convenience linked against stdlibc (libc.so.6) and libgstreamer-1.0.so.0 and compatible with GStreamer 1.26 or newer. |
| 238 | | |
| 239 | | Install GStreamer: |
| 240 | | {{{#!bash |
| 241 | | apt-get update && apt install -y \ |
| 242 | | gstreamer1.0-x \ |
| 243 | | gstreamer1.0-tools \ |
| 244 | | gstreamer1.0-plugins-base \ |
| 245 | | gstreamer1.0-plugins-good \ |
| 246 | | gstreamer1.0-plugins-bad \ |
| 247 | | gstreamer1.0-plugins-ugly \ |
| 248 | | gstreamer1.0-libav \ |
| 249 | | v4l-utils |
| 250 | | }}} |
| 251 | | - this adds about 500MiB of disk space |
| 252 | | |
| 253 | | Specify Plugin path: |
| 254 | | {{{#!bash |
| 255 | | # export now to current shell |
| 256 | | export GST_PLUGIN_PATH=/usr/lib/gstreamer-1.0/ |
| 257 | | # put in .bashrc so it happens for any new bash shell |
| 258 | | echo "export GST_PLUGIN_PATH=/usr/lib/gstreamer-1.0/" >> ~/.bashrc |
| 259 | | }}} |
| 260 | | - this tells GStreamer to look for plugins in the non-standard location of the ARA gstreamer plugins |
| 261 | | |
| 262 | | At this point you can inspect the dvInf element: |
| 263 | | {{{#!bash |
| 264 | | gst-inspect-1.0 dvInf |
| 265 | | }}} |
| 266 | | |
| 267 | | Examples: |
| 268 | | * gst-launch pipeline prototyping: |
| 269 | | - enabling debug level 6 on dvPost will show the number of object detections in its debug output but if you want to do anything with that data you need to write an application that can decode frame buffers. Still this is useful for prototyping: |
| 270 | | * perform detection on a v4l2 video device like a webcam: |
| 271 | | {{{#!bash |
| 272 | | DEV=/dev/video_webcam |
| 273 | | MODEL=/usr/share/cnn/detection/yolov8n/model.dvm |
| 274 | | GST_DEBUG="dvInf:6" \ |
| 275 | | gst-launch-1.0 -v \ |
| 276 | | v4l2src device=$DEV ! \ |
| 277 | | video/x-raw,width=640,height=480,framerate=30/1 ! \ |
| 278 | | videoconvert ! video/x-raw,format=BGRx ! \ |
| 279 | | dvInf model=$MODEL orig-width=640 orig-height=480 stream=0 \ |
| 280 | | sock=/var/run/proxy.sock use-shm=true shm-path=/dev/shm/ara_shm ! \ |
| 281 | | fakesink sync=false | grep Detected |
| 282 | | }}} |
| 283 | | - see wiki:linux/persistent_device_naming#video for details about making video devices have persistent device names |
| 284 | | * perform a detection on an image: |
| 285 | | {{{#!bash |
| 286 | | URI=file:///$PWD/traffic.png |
| 287 | | MODEL=/usr/share/cnn/detection/yolov8n/model.dvm |
| 288 | | GST_DEBUG="dvInf:6" \ |
| 289 | | gst-launch-1.0 -v \ |
| 290 | | filesrc location=traffic.png ! \ |
| 291 | | pngdec ! imagefreeze num-buffers=10 ! \ |
| 292 | | videoscale ! videoconvert ! video/x-raw,format=BGRx,width=640,height=480 ! \ |
| 293 | | dvInf model=$MODEL orig-width=640 orig-height=480 stream=0 \ |
| 294 | | sock=/var/run/proxy.sock use-shm=true shm-path=/dev/shm/ara_shm ! \ |
| 295 | | fakesink sync=false | grep Detected |
| 296 | | }}} |
| 297 | | |
| 298 | | For a more complete example see below |
| 299 | | |
| 300 | | |
| 301 | | [=#eiq-aaf-connector] |
| 302 | | == eIQ AAF Connector for LLM inference |
| 303 | | The eIQ AAF Connector (edge Intelligence Ara Application Framework) |
| 304 | | is a REST-based server that enables LLM inference on NXP i.MX processors with the ARA-240 DNPU. The API implemented is the de-facto API standard created by OpenAI for ChatGPT. It provides a simple Chat Completions-based HTTP interface for serving models to client applications. |
| 305 | | |
| 306 | | Requirements: |
| 307 | | - python 3.13 (we will install in a virtual env) |
| 308 | | - uv - used for the user-specific Python virtual environment |
| 309 | | - Optimum Ara framework for running Large Language Models (LLMs) and Vision-Language Models (VLMs) on Ara240 (part of rt-sdk) |
| 310 | | - OpenCV (dependency of the QwenVL engine) |
| 311 | | - Models |
| 312 | | |
| 313 | | Source: |
| 314 | | - https://github.com/nxp-imx-support/eiq-aaf-connector |
| 315 | | |
| 316 | | For ease of use Gateworks provides a pre-built deb package of eiq-aaf-connector v2.1 built from the NXP IMX Yocto BSP which you can install with: |
| 317 | | {{{#!bash |
| 318 | | # fetch |
| 319 | | wget https://dev.gateworks.com/ara/eiq-aaf-connector_2.1-r0_arm64.deb |
| 320 | | # extract data (but don't install) |
| 321 | | dpkg-deb --vextract eiq-aaf-connector_2.1-r0_arm64.deb / |
| 322 | | # run the install script |
| 323 | | /usr/share/eiq/aaf-connector/install.sh |
| 324 | | # fetch LLM models (installed to /usr/share/llm) |
| 325 | | fetch_models --repo-id nxp/Qwen2.5-7B-Instruct-Ara240 # 7.7GiB LLM |
| 326 | | fetch_models --repo-id nxp/Qwen2.5-Coder-1.5B-Ara240 # 1.67GiB LLM |
| 327 | | fetch_models --repo-id nxp/Qwen2.5-VL-7B-Instruct-Ara240 # 12GB VLM |
| 328 | | }}} |
| 329 | | |
| 330 | | files: |
| 331 | | - /usr/share/eiq/aaf-connector/install.sh (install script) |
| 332 | | - /usr/share/python-wheels/eiq_aaf_connector-2.1-py3-none-any.whl (python wheel) |
| 333 | | - /usr/share/eiq/aaf-connector/server_config.json (config file) |
| 334 | | - /etc/systemd/system/eiq-aaf-connector.service (created from install script) |
| 335 | | |
| 336 | | The install script creates a systemd eiq-aaf-connector.service: |
| 337 | | {{{#!bash |
| 338 | | # Enable service on boot |
| 339 | | systemctl enable eiq-aaf-connector.service |
| 340 | | # Start the service now (or reboot) |
| 341 | | systemctl start eiq-aaf-connector.service |
| 342 | | }}} |
| 343 | | |
| 344 | | Notes: |
| 345 | | - By default the connector will listen on 127.0.0.1:8000. If you wish the service to be accessible externally set the host to '0.0.0.0' instead: |
| 346 | | {{{#!bash |
| 347 | | sed -i 's|--host 127.0.0.1|--host 0.0.0.0|g' /etc/systemd/system/eiq-aaf-connector.service |
| 348 | | }}} |
| 349 | | - the default config file has configuration for all of the above Ara models but they are not 'enabled' by default. You must only enable 1 model at a time and doing so loads the model onto the Ara when the servoce starts. To enable a model change the appropriate 'enabled' property to 'true' in /etc/systemd/system/eiq-aaf-connector.service and restart the service |
| 350 | | - it takes several minutes for the service to actually be ready for connections as it must process the models (monitor with 'journalctl -u eiq-aaf-connector.service --no-pager -f' and test that its ready for listening with 'ss -tulpn | grep :8000'). |
| 351 | | - the connector self-hosts API documentation at http://<serverip>:8000/docs (available externally if configured for a host of 0.0.0.0) |
| 352 | | |
| 353 | | Example Usage: |
| 354 | | - verify connector running |
| 355 | | {{{#!bash |
| 356 | | # show service status |
| 357 | | systemctl status eiq-aaf-connector.service --no-pager -l |
| 358 | | # view detailed service logs for the current boot and follow the journal |
| 359 | | journalctl --boot --follow --unit eiq-aaf-connector.service |
| 360 | | # verify process exists |
| 361 | | ps -ef | grep aaf-connector |
| 362 | | # verify port open |
| 363 | | ss -tulpn | grep :8000 # show IP:PORT server is listening on |
| 364 | | }}} |
| 365 | | - view API docs and interact with server (requires changing the host to '0.0.0.0' in the !ExecStart config for /etc/systemd/system/eiq-aaf-connector.service by opening !http://<serverip>:8000/docs |
| 366 | | - use API via curl/jq |
| 367 | | {{{#!bash |
| 368 | | # make sure curl and jq are installed (jq allows easy interaction with json data) |
| 369 | | apt install -y curl jq |
| 370 | | # list of models |
| 371 | | curl -X 'GET' \ |
| 372 | | 'http://127.0.0.1:8000/v1/models' \ |
| 373 | | -H 'accept: application/json' | jq |
| 374 | | # get info about a specific model (Qwen2.5-7B-Instruct) |
| 375 | | curl -X 'GET' \ |
| 376 | | 'http://127.0.0.1:8000/params/Qwen2.5-7B-Instruct' \ |
| 377 | | -H 'accept: application/json' | jq |
| 378 | | # send a LLM query |
| 379 | | curl -X POST http://127.0.0.1:8000/v1/chat/completions -H "Content-Type: application/json" -d '{ |
| 380 | | "model": "Qwen2.5-7B-Instruct", |
| 381 | | "messages": [ |
| 382 | | {"role": "system", "content": "You are a helpful assistant running on NXP i.MX hardware."}, |
| 383 | | {"role": "user", "content": "Explain what an NPU is in one sentence."} |
| 384 | | ], |
| 385 | | "max_tokens": 50 |
| 386 | | }' | jq |
| 387 | | }}} |
| 388 | | - run connector by hand (useful for troubleshooting or monitoring) |
| 389 | | {{{#!bash |
| 390 | | systemctl stop eiq-aaf-connector.service |
| 391 | | source "/usr/share/eiq/aaf-connector/venv/bin/activate" |
| 392 | | connector --host 0.0.0.0 --port 8000 # will run until stopped |
| 393 | | deactivate |
| 394 | | }}} |
| 395 | | |
| 396 | | |
| 397 | | [=#examples] |
| 398 | | == Examples |
| 399 | | Here are some Ara example applications put together by Gateworks |
| 400 | | |
| 401 | | === dvapi stats |
| 402 | | This is an ANSI c app that provides an example of using the dvapi to connect to the proxy and obtain NPU endpoint stats such as temperature, clocks and usage. Basically it's a re-implementation of the closed source /usr/share/rt-sdk-ara240/scripts/ara2_metrics_bin/hw_metrics.out. |
| 403 | | |
| 404 | | ara_status.c: |
| 405 | | {{{#!c |
| 406 | | #include <stdio.h> |
| 407 | | #include <stdlib.h> |
| 408 | | #include "dvapi.h" |
| 409 | | |
| 410 | | int main() { |
| 411 | | dv_session_t *session = NULL; |
| 412 | | dv_endpoint_t *ep_list = NULL; |
| 413 | | int ep_count = 0; |
| 414 | | dv_status_code_t status; |
| 415 | | const char *socket_path = "/run/proxy.sock"; |
| 416 | | |
| 417 | | // 1. Establish session |
| 418 | | status = dv_session_create_via_unix_socket(socket_path, &session); |
| 419 | | if (status != DV_SUCCESS) { |
| 420 | | fprintf(stderr, "Failed to connect: %s\n", dv_stringify_status_code(status)); |
| 421 | | return 1; |
| 422 | | } |
| 423 | | |
| 424 | | // 2. Get list of NPU endpoints |
| 425 | | dv_endpoint_get_list(session, &ep_list, &ep_count); |
| 426 | | |
| 427 | | for (int i = 0; i < ep_count; i++) { |
| 428 | | dv_endpoint_t *ep = &ep_list[i]; |
| 429 | | dv_endpoint_statistics_t *stats = NULL; |
| 430 | | int s_count = 0; |
| 431 | | bool is_busy = false; |
| 432 | | |
| 433 | | // 3. Retrieve status and statistics |
| 434 | | dv_get_endpoint_busyness(session, ep, &is_busy); |
| 435 | | status = dv_endpoint_get_statistics(session, ep, &stats, &s_count); |
| 436 | | |
| 437 | | if (status == DV_SUCCESS && s_count > 0) { |
| 438 | | // DRAM Calculations (Bytes to GB) |
| 439 | | double used_gb = (double)stats->ep_dram_stats.ep_total_dram_occupancy_size / 1073741824.0; |
| 440 | | double total_gb = (double)stats->ep_dram_stats.ep_total_dram_size / 1073741824.0; |
| 441 | | double dram_pct = (total_gb > 0) ? (used_gb / total_gb) * 100.0 : 0.0; |
| 442 | | |
| 443 | | // NPU Utilization (Queue occupancy) |
| 444 | | double npu_load = 0.0; |
| 445 | | if (stats->ep_infq_stats && stats->ep_infq_stats->length > 0) { |
| 446 | | npu_load = ((double)stats->ep_infq_stats->occupancy_count / stats->ep_infq_stats->length) * 100.0; |
| 447 | | } |
| 448 | | |
| 449 | | printf("--- NPU Endpoint %d Statistics ---\n", i); |
| 450 | | printf("Busy State: %s\n", is_busy ? "TRUE" : "FALSE"); |
| 451 | | printf("NPU Utilization: %.1f%%\n", npu_load); |
| 452 | | printf("Temperature: %.1f C\n", stats->ep_temp); |
| 453 | | printf("NNP Clock: %d MHz\n", stats->ep_nnp_clk); |
| 454 | | printf("SBP Clock: %d MHz\n", stats->ep_sbp_clk); |
| 455 | | printf("DRAM Clock: %d MHz\n", stats->ep_dram_clk); |
| 456 | | |
| 457 | | // Format: DRAM Usage: 8.2GB/16.0GB (51.3%) |
| 458 | | printf("DRAM Usage: %.1fGB/%.1fGB (%.1f%%)\n", used_gb, total_gb, dram_pct); |
| 459 | | printf("\n"); |
| 460 | | |
| 461 | | dv_endpoint_free_statistics(stats, s_count); |
| 462 | | } |
| 463 | | } |
| 464 | | |
| 465 | | // 4. Cleanup |
| 466 | | dv_endpoint_free_group(ep_list); |
| 467 | | dv_session_close(session); |
| 468 | | return 0; |
| 469 | | } |
| 470 | | }}} |
| 471 | | |
| 472 | | Compile: |
| 473 | | {{{#!bash |
| 474 | | apt update && apt install build-essential |
| 475 | | gcc ara_status.c -I/usr/include/sdk_ara/ -L/usr/lib/ -laraclient_aarch64 -o ara_status |
| 476 | | }}} |
| 477 | | |
| 478 | | Execution: |
| 479 | | {{{#!bash |
| 480 | | # ./ara_status |
| 481 | | --- NPU Endpoint 0 Statistics --- |
| 482 | | Busy State: FALSE |
| 483 | | NPU Utilization: 0.0% |
| 484 | | Temperature: 56.0 C |
| 485 | | NNP Clock: 900 MHz |
| 486 | | SBP Clock: 355 MHz |
| 487 | | DRAM Clock: 1066 MHz |
| 488 | | DRAM Usage: 10.0GB/16.0GB (62.5%) |
| 489 | | }}} |
| 490 | | |
| 491 | | |
| 492 | | === Image Detection with boxying via Python |
| 493 | | Python is incredibly useful for accessing GStreamer and handling the ARA detection frame data and imagemagick provides excellent tools for converting and drawing on images. We use PyGObject which is a Python package that provides bindings for libraries based on GObject Introspection such as GTK, !WebKit, and GStreamer. It allows you to use C-based frameworks in python. |
| 494 | | |
| 495 | | Steps: |
| 496 | | 1. We need to install the C libs for GStreamer and build utilities: |
| 497 | | {{{#!bash |
| 498 | | apt-get install -y \ |
| 499 | | libcairo2-dev \ |
| 500 | | libgirepository-2.0-dev \ |
| 501 | | python3-dev \ |
| 502 | | python3-gst-1.0 \ |
| 503 | | cmake pkg-config |
| 504 | | # we are also going to need to install gstreamer and its dev packages |
| 505 | | apt-get install -y \ |
| 506 | | libgstreamer1.0-dev \ |
| 507 | | libgstreamer-plugins-base1.0-dev \ |
| 508 | | libgstreamer-plugins-bad1.0-dev \ |
| 509 | | gstreamer1.0-plugins-base \ |
| 510 | | gstreamer1.0-plugins-good \ |
| 511 | | gstreamer1.0-plugins-bad \ |
| 512 | | gstreamer1.0-plugins-ugly \ |
| 513 | | gstreamer1.0-libav \ |
| 514 | | gstreamer1.0-tools |
| 515 | | }}} |
| 516 | | 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need: |
| 517 | | {{{#!bash |
| 518 | | # create a dir for the venv |
| 519 | | mkdir image-detect |
| 520 | | cd image-detect |
| 521 | | # create a venv (.venv) |
| 522 | | uv venv |
| 523 | | # install our scripts dependencies |
| 524 | | uv pip install pygobject |
| 525 | | }}} |
| 526 | | 1. (optional) fetch some images for detection |
| 527 | | {{{#!bash |
| 528 | | # fetch a coco validation image; it contains a dog on a bench and the dog is at 208,147 to 293,289 |
| 529 | | wget http://images.cocodataset.org/val2017/000000546829.jpg -O dog.jpg |
| 530 | | # use ffmpeg to grab a frame from within an MP4 |
| 531 | | apt install -y ffmpeg |
| 532 | | ffmpeg -i /usr/share/ara2-vision-examples/sample_videos/video_0.mp4 -f null - # shows how lon git is (time=00:00:15.50) |
| 533 | | ffmpeg -i /usr/share/ara2-vision-examples/sample_videos/video_0.mp4 -ss 00:00:5 -frames:v 1 traffic.png |
| 534 | | }}} |
| 535 | | 1. fetch the script |
| 536 | | {{{#!bash |
| 537 | | wget https://dev.gateworks.com/ara/examples/image_detect.py |
| 538 | | }}} |
| 539 | | 1. run the script (image_detect.py <source-image> <destination-image> [model-path]) |
| 540 | | {{{#!bash |
| 541 | | uv run image_detect.py dog.jpg coco_detections.jpg |
| 542 | | }}} |
| 543 | | - Note that without shm the pipeline needs to copy the raw image bytes over a local network-style socket connection. By mounting a dedicated memory path to /dev/shm you can eliminate that transfer (zero-copy): dvPre dumps the processed directly into a designated block of system RAM and dvInf uses a pointer to it |
| 544 | | - you would think that if your original image was 1080x1920 and you resized it to the model size of 640x640 that if you tell dvPost the orig-width=1080 orig-height=1920 that it would scale the bounding boxes properly however in practice it seems it does not unless your image has the same aspect ratio of the model. mapping it as above (telling dvPost that the image is 640x640 and scaling ourselves) resolves this |
| 545 | | - images: |
| 546 | | |
| 547 | | [[Image(dog.jpg,400px)]] |
| 548 | | [[Image(dog_detect.jpg,400px)]] |
| 549 | | |
| 550 | | [[Image(traffic.jpg,400px)]] |
| 551 | | [[Image(traffic_detect_yolo8n.jpg,400px)]] |
| 552 | | [[Image(traffic_detect_yolo8x.jpg,400px)]] |
| 553 | | |
| 554 | | |
| 555 | | === Video Detection Webapp via Python |
| 556 | | Python is incredibly useful for accessing GStreamer and handling the ARA detection frame data and building webapps. The script using PyGObject which is a Python package that provides bindings for libraries based on GObject Introspection such as GTK, !WebKit, and GStreamer. It allows you to use C-based frameworks in python. We need to install the C libs for GStreamer for this |
| 557 | | |
| 558 | | Steps: |
| 559 | | 1. We need to install the C libs for GStreamer and build utilities: |
| 560 | | {{{#!bash |
| 561 | | apt-get install -y \ |
| 562 | | libcairo2-dev \ |
| 563 | | libgirepository-2.0-dev \ |
| 564 | | python3-dev \ |
| 565 | | python3-gst-1.0 \ |
| 566 | | cmake pkg-config |
| 567 | | # we are also going to need to install GStreamer and its dev packages |
| 568 | | apt-get install -y \ |
| 569 | | libgstreamer1.0-dev \ |
| 570 | | libgstreamer-plugins-base1.0-dev \ |
| 571 | | libgstreamer-plugins-bad1.0-dev \ |
| 572 | | gstreamer1.0-plugins-base \ |
| 573 | | gstreamer1.0-plugins-good \ |
| 574 | | gstreamer1.0-plugins-bad \ |
| 575 | | gstreamer1.0-plugins-ugly \ |
| 576 | | gstreamer1.0-libav \ |
| 577 | | gstreamer1.0-tools |
| 578 | | }}} |
| 579 | | 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need: |
| 580 | | {{{#!bash |
| 581 | | # create a dir for the venv |
| 582 | | mkdir vision-webapp |
| 583 | | cd vision-webapp |
| 584 | | # create a venv (.venv) |
| 585 | | uv venv |
| 586 | | # install our scripts dependencies |
| 587 | | uv pip install pygobject opencv-python-headless flask |
| 588 | | }}} |
| 589 | | 1. fetch the script |
| 590 | | {{{#!bash |
| 591 | | wget https://dev.gateworks.com/ara/examples/vision-webapp.py |
| 592 | | }}} |
| 593 | | 1. run the script (vison-webapp.py [--port <portno>] [--camera <camera-dev>] [--mp4 <mp4-dir>] |
| 594 | | {{{#!bash |
| 595 | | uv run vision-webapp.py --camera /dev/video_webcam --mp4 /usr/share/media/sample_videos/ |
| 596 | | }}} |
| 597 | | - you can provide a webcam device path to enable streaming from a webcam and/or an mp4 directory to enable processing those. A dropdown will allow you to select the input stream and the model and the browser window will show you detections and statistics |
| 598 | | |
| 599 | | [[Image(vision-webapp.jpg,400px)]] |
| 600 | | |
| 601 | | |
| 602 | | === command-line python eIQ chatbot (chat.py) |
| 603 | | This is a command-line chatbot written in python using the eIQ AAF Connector |
| 604 | | 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need: |
| 605 | | {{{#!bash |
| 606 | | # create a dir for the venv |
| 607 | | mkdir chat |
| 608 | | cd chat |
| 609 | | # create a venv (.venv) |
| 610 | | uv venv |
| 611 | | # install our scripts dependencies |
| 612 | | uv pip install -q requests |
| 613 | | }}} |
| 614 | | 1. fetch the script |
| 615 | | {{{#!bash |
| 616 | | wget https://dev.gateworks.com/ara/examples/chat.py |
| 617 | | }}} |
| 618 | | 1. run the script |
| 619 | | {{{#!bash |
| 620 | | uv run chat.py |
| 621 | | }}} |
| 622 | | |
| 623 | | Example session: |
| 624 | | {{{#!bash |
| 625 | | --- i.MX LLM Session (Model: Qwen2.5-7B-Instruct) --- |
| 626 | | Type 'exit' to stop. |
| 627 | | |
| 628 | | You: Why is the sky blue |
| 629 | | AI: The sky appears blue because of a phenomenon called Rayleigh scattering. When sunlight enters the Earth's atmosphere, it collides with molecules and small particles in the air. Sunlight is made up of different colors, each of which has a different wavelength. Blue light has a shorter wavelength and is scattered more than other colors by the gases and particles in the atmosphere. This scattering makes the sky appear blue to our eyes. |
| 630 | | |
| 631 | | During sunrise and sunset, the sky can appear red or orange because the light has to travel through more of the Earth's atmosphere. This longer path means that more blue and green light is scattered out of the beam, leaving the red and orange wavelengths to dominate the light that reaches our eyes. |
| 632 | | |
| 633 | | So, the blue color of the sky is primarily due to the way shorter wavelength light is scattered by the Earth's atmosphere. |
| 634 | | |
| 635 | | --- Stats --- |
| 636 | | Time taken: 29.18 seconds |
| 637 | | Throughput: 5.04 tokens/sec |
| 638 | | ------------- |
| 639 | | |
| 640 | | You: exit |
| 641 | | }}} |
| 642 | | |
| 643 | | |
| 644 | | === Web based python eIQ chatbot (webchat.py) |
| 645 | | This is a web based chatbot in python using eIQ AAF Connector |
| 646 | | |
| 647 | | 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need: |
| 648 | | {{{#!bash |
| 649 | | # create a dir for the venv |
| 650 | | mkdir webchat |
| 651 | | cd webchat |
| 652 | | # create a venv (.venv) |
| 653 | | uv venv |
| 654 | | # install our scripts dependencies |
| 655 | | uv pip install -q fastapi psutil uvicorn |
| 656 | | }}} |
| 657 | | 1. fetch the script |
| 658 | | {{{#!bash |
| 659 | | wget https://dev.gateworks.com/ara/examples/webchat.py |
| 660 | | }}} |
| 661 | | 1. run the script |
| 662 | | {{{#!bash |
| 663 | | uv run webchat.py |
| 664 | | }}} |
| 665 | | 1. Open a web browser to your boards IP address port 8080: http://<ipaddr>:8080 |
| 666 | | |
| 667 | | Notes: |
| 668 | | * By default this will listen for HTTP requests on port 8080 |
| 669 | | * On startup it will enable the model (specified in the script) and restart the eIQ server if needed - waiting for the model to load may take several minutes |
| 670 | | |
| 671 | | |
| 672 | | [=#vlm] |
| 673 | | === Web based python VLM eIQ example (webvlm.py) |
| 674 | | The eIQ AAF Connector can be used to analyze video and images. |
| 675 | | |
| 676 | | Here is an example of a headless web-app based off NXP's [https://github.com/nxp-imx-support/vlm-edge-studio/tree/main/src vlm-edge-studio example] using: |
| 677 | | - Qwen2.5-VL-7B-Instruct-Ara240 |
| 678 | | - eIQ AAF Connector |
| 679 | | |
| 680 | | Requirements: |
| 681 | | - Ara runtime |
| 682 | | - eIQ AAF Connector |
| 683 | | - Qwen2.5-VL-7B-Instruct-Ara240 model |
| 684 | | |
| 685 | | Steps: |
| 686 | | 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need: |
| 687 | | {{{#!bash |
| 688 | | # create a dir for the venv |
| 689 | | mkdir webvlm |
| 690 | | cd webvlm |
| 691 | | # create a venv (.venv) |
| 692 | | uv venv |
| 693 | | # install our scripts dependencies |
| 694 | | uv pip install -q httpx uvicorn fastapi argparse |
| 695 | | }}} |
| 696 | | 1. fetch the script |
| 697 | | {{{#!bash |
| 698 | | wget https://dev.gateworks.com/ara/examples/webvlm.py |
| 699 | | }}} |
| 700 | | 1. run the script |
| 701 | | {{{#!bash |
| 702 | | uv run webvlm.py --video-dir /usr/share/media/sample_videos/ |
| 703 | | }}} |
| 704 | | 1. Open a web browser to your boards IP address port 8080: http://<ipaddr>:8080 |
| 705 | | |
| 706 | | Notes: |
| 707 | | * By default this will listen for HTTP requests on port 8080 |
| 708 | | * On startup it will enable the model (specified in the script) and restart the eIQ server if needed - waiting for the model to load may take several minutes |
| 709 | | |
| 710 | | |
| 711 | | [[Image(vlm-webapp.jpg,400px)]] |
| 712 | | |
| 713 | | |
| 714 | | == Troubleshooting |
| 715 | | |
| 716 | | Please note software support should be routed through NXP, who produces the Ara240 DNPU Chip and Software SDK. |
| 717 | | |
| 718 | | [https://community.nxp.com] |
| | 476 | |
| | 477 | |
| | 478 | = NXP Ara240 DNPU AI Accelerator Quick Start |
| | 479 | Below are details regarding installing the ARA2 runtime software requirements manually. If you are using the Gateworks i.MX95 Catalina AI Devkit this software is already installed. Please see [#ai-devkit above for details] |
| | 480 | |
| | 481 | [=#ara2-runtime] |
| | 482 | == Ara Runtime |
| | 483 | NXP has a runtime library for the Ara240 which consists of some statically built libraries as well as a dynamic linked GStreamer plugin. |
| | 484 | |
| | 485 | The Ara runtime includes a couple of Python Wheels. A Python Wheel is a standard built-package format for distributing Python libraries. It is essentially a ZIP-format archive with a .whl extension that contains all the files needed for a package to run immediately after being. It's fairly standard when using Python to run into package version incompatibilities which is why user based Python virtual environments are used. |
| | 486 | |
| | 487 | The Ara runtime provides a complete runtime environment for AI/ML acceleration using the Ara240 NPU on for aarch64. This package includes: |
| | 488 | * Runtime libraries for Ara240 NPU integration |
| | 489 | * Python bindings (DVAPI) for custom inference applications |
| | 490 | * Optimum-Ara framework for LLMs and VLMs |
| | 491 | * GStreamer plugin for Real-Time Detection Object Applications |
| | 492 | * Helper scripts for monitoring, benchmarking, and model management |
| | 493 | * Systemd service for automatic hardware initialization |
| | 494 | |
| | 495 | Installation on a Gateworks board with Ubuntu based OS: |
| | 496 | - Download and extract the self-extracting binary from NXP: |
| | 497 | {{{#!bash |
| | 498 | VER=imx-nxp-ara2-2.1.1-063d56c |
| | 499 | wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/$VER.bin |
| | 500 | sh $VER.bin |
| | 501 | }}} |
| | 502 | - take care of postinst steps |
| | 503 | - miscellaneous |
| | 504 | {{{#!bash |
| | 505 | # create dirs (used for models) |
| | 506 | mkdir -pv /usr/share/{cnn,llm} |
| | 507 | }}} |
| | 508 | - configure swap (necessary if using VLM) |
| | 509 | {{{#!bash |
| | 510 | /usr/bin/enable_swap 2 |
| | 511 | }}} |
| | 512 | - install uv package manager for Python virtualization and packaging for local user (which is installed to ~/.local/bin so we create symlinks to /usr/bin) |
| | 513 | {{{#!bash |
| | 514 | apt update && apt install -y curl |
| | 515 | curl -LsSf https://astral.sh/uv/install.sh | sh |
| | 516 | ln -s /root/.local/bin/uv /usr/bin/uv |
| | 517 | ln -s /root/.local/bin/uvx /usr/bin/uvx |
| | 518 | }}} |
| | 519 | - build driver |
| | 520 | {{{#!bash |
| | 521 | apt update && apt install -y build-essential git bc file flex bison |
| | 522 | git clone https://github.com/nxp-imx-support/uiodma-driver |
| | 523 | ( cd uiodma-driver/uiodma; make ) |
| | 524 | # install it where the rt service expects to find it (over the top of the non-compatible one) |
| | 525 | cp uiodma-driver/uiodma/uiodma.ko /usr/share/rt-sdk-ara240/driver/ |
| | 526 | }}} |
| | 527 | - enable service: |
| | 528 | {{{#!bash |
| | 529 | # enable service |
| | 530 | systemctl enable rt-sdk-ara2.service |
| | 531 | # start service now (unless you reboot) |
| | 532 | systemctl start rt-sdk-ara2.service |
| | 533 | }}} |
| | 534 | - use 'fetch_models' to pre-compiled models for testing via the fetch_models script which will fetch models from !HuggingFace. |
| | 535 | {{{#!bash |
| | 536 | # list models available for nxp/ara |
| | 537 | fetch_models --list |
| | 538 | # install YOLOv8 |
| | 539 | fetch_models --repo-id nxp/YOLOv8 # 746MB (711MiB) |
| | 540 | }}} |
| | 541 | - the script is a python wrapper that uses uvx and the fetch-models python wheel (/usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl) to fetch and install models from !HuggingFace HUB |
| | 542 | - the models will be installed in either /usr/share/cnn (Convolutional Neural Network) and /usr/share/llm (Large Language Model) |
| | 543 | - NXP has Ara2 optimized models at https://huggingface.co/nxp |
| | 544 | - the script has a hard coded list of models available and where to install them locally. You can use 'python -m zipfile -e /usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl ./fetch_models' to see what it's doing |
| | 545 | |
| | 546 | Notable Files: |
| | 547 | - /usr/lib/ |
| | 548 | - libaraclient_aarch64.so - base library for interfacing with ara2 |
| | 549 | - libara_vision_inference.so - inference lib that builds on libaraclient |
| | 550 | - /usr/lib/gstreamer-1.0 |
| | 551 | - libgstdvInf.so - GStreamer plugin |
| | 552 | - /usr/share/rt-sdk-ara240 (symlink to a version independent dir at same location) |
| | 553 | - hw_utils/boot_img - firmware files |
| | 554 | - hw_utils/ddr_config - ddr binaries |
| | 555 | - hw_utils/bins/ - the hw utils for bringup/programming |
| | 556 | - optimum-ara/ - extension of the Hugging Face library that integrates with Ara240 DNPU |
| | 557 | - scripts - various wrappers around the tools etc |
| | 558 | - nnapp - tool for benchmarking models |
| | 559 | - config - various example yaml config files used for proxy/nnapp |
| | 560 | - include/dvapi.py - python bindings to dvapi |
| | 561 | - driver/uiodma.ko - driver (where the setup script expects to find it) |
| | 562 | - /usr/share/python-wheels - python wheels for fetch_models and optimum_ara |
| | 563 | - /usr/shar/doc/rt-sdk-ara2 - license info |
| | 564 | - /usr/include/sdk_ara - headers for C libs |
| | 565 | - /usr/bin - various scripts |
| | 566 | - /etc/udev/rules.d/99-ara2.rules - udev rule which makes the PCI ID dependent on the systemd service |
| | 567 | - /etc/systemd/system/rt-sdk-ara2.service - systemd service that handles the various hw util config |
| | 568 | - /etc/rt-sdk-ara240/cnn_config.yaml - config for nnapp |
| | 569 | - /etc/rt-sdk-ara240/proxy_config.yam - config for proxy |
| | 570 | |
| | 571 | Notes: |
| | 572 | - The 'uv' package manager is a fast all-in-one Python package and project manager written in Rust which makes it easy to work with virtual env's to avoid Python package version clashing which is essential |
| | 573 | - on bootup make sure you wait for the console messages indicating the Proxy is launched before using it as it can take a couple of minutes |
| | 574 | - the binary tools and libs are all static linked for compatibility |
| | 575 | - the GStreamer libs require GStreamer 1.26 or newer and is dynamic linked |
| | 576 | |
| | 577 | Verification steps: |
| | 578 | 1. show chip_info |
| | 579 | {{{#!bash |
| | 580 | chip_info.sh |
| | 581 | }}} |
| | 582 | 1. verify service |
| | 583 | {{{#!bash |
| | 584 | # show service status |
| | 585 | systemctl status rt-sdk-ara2.service --no-pager -l |
| | 586 | # view detailed service logs for the current boot and follow the journal |
| | 587 | journalctl --boot --follow --unit rt-sdk-ara2.service |
| | 588 | # verify proxy is running (critical) |
| | 589 | ps -eaf | grep proxy_ara240 |
| | 590 | }}} |
| | 591 | |
| | 592 | Examples: |
| | 593 | - Download pre-compiled models for testing: |
| | 594 | - The fetch_models script from the ara2-rt will fetch models from !HuggingFace. |
| | 595 | {{{#!bash |
| | 596 | # list models available for nxp/ara |
| | 597 | fetch_models --list |
| | 598 | # install YOLOv8 |
| | 599 | fetch_models --repo-id nxp/YOLOv8 # 746MB (711MiB) |
| | 600 | }}} |
| | 601 | - the 'fetch_models' script is a python wrapper that uses uvx and the fetch-models python wheel (/usr/share/python-wheels/fetch_models-1.0.0-py3-none-any.whl) to fetch and install models from !HuggingFace HUB |
| | 602 | - the models will be installed in /usr/share/cnn (Convolutional Neural Network) and /usr/share/llm (Large Language Model) |
| | 603 | - NXP has Ara2 optimized models at https://huggingface.co/nxp |
| | 604 | - Run performance benchmark (uses nnapp) |
| | 605 | {{{#!bash |
| | 606 | run_model_perf.sh |
| | 607 | }}} |
| | 608 | - the 'run_model_perf.sh' script makes it easy to list and show model categories and models and is a wrapper around the nnapp app which has a lot of options and a config file |
| | 609 | - monitor real-time NPU metrics including utilization, temperature, DRAM usage and device state (interactively during benchmarking or model execution) |
| | 610 | {{{#!bash |
| | 611 | ara2_metrics.sh |
| | 612 | }}} |
| | 613 | |
| | 614 | [=#gstreamer] |
| | 615 | === GStreamer plugins |
| | 616 | The Ara runtime provides an OpenSource GStreamer plugin for detection models: |
| | 617 | - [https://github.com/nxp-imx-support/gstreamer-plugins-ara240 dvInf] |
| | 618 | |
| | 619 | The plugin can sink 32bit pixel samples (ie format=BGRx using 4 bytes per pixel, blue, green, red, and a pading byte as a structural spacer) |
| | 620 | |
| | 621 | The model is specified via the 'model' property. If using yolov8x for example you would specify the path to the yolov8x.dvm |
| | 622 | |
| | 623 | For detection models the element frame data will contain a buffer with number of bytes (32bit) followed by a series of detection structures containing the bounding box, confidence level, and COCO class ID of the object detected. |
| | 624 | |
| | 625 | The units for the bounding box are relative to the models size and will need to be scaled back to your original image size. For example the YOLO models operate on 640x640 pixel data. You can pass something larger in and it will essentially tile but its unclear if there is an advantage of doing that. |
| | 626 | |
| | 627 | While the gstreamer plugin source provided is provided [https://github.com/nxp-imx-support/gstreamer-plugins-ara240 here] it is included in the Ara runtime pre-compiled for convenience linked against stdlibc (libc.so.6) and libgstreamer-1.0.so.0 and compatible with GStreamer 1.26 or newer. |
| | 628 | |
| | 629 | Install GStreamer: |
| | 630 | {{{#!bash |
| | 631 | apt-get update && apt install -y \ |
| | 632 | gstreamer1.0-x \ |
| | 633 | gstreamer1.0-tools \ |
| | 634 | gstreamer1.0-plugins-base \ |
| | 635 | gstreamer1.0-plugins-good \ |
| | 636 | gstreamer1.0-plugins-bad \ |
| | 637 | gstreamer1.0-plugins-ugly \ |
| | 638 | gstreamer1.0-libav \ |
| | 639 | v4l-utils |
| | 640 | }}} |
| | 641 | - this adds about 500MiB of disk space |
| | 642 | |
| | 643 | Specify Plugin path: |
| | 644 | {{{#!bash |
| | 645 | # export now to current shell |
| | 646 | export GST_PLUGIN_PATH=/usr/lib/gstreamer-1.0/ |
| | 647 | # put in .bashrc so it happens for any new bash shell |
| | 648 | echo "export GST_PLUGIN_PATH=/usr/lib/gstreamer-1.0/" >> ~/.bashrc |
| | 649 | }}} |
| | 650 | - this tells GStreamer to look for plugins in the non-standard location of the ARA gstreamer plugins |
| | 651 | |
| | 652 | At this point you can inspect the dvInf element: |
| | 653 | {{{#!bash |
| | 654 | gst-inspect-1.0 dvInf |
| | 655 | }}} |
| | 656 | |
| | 657 | Examples: |
| | 658 | * gst-launch pipeline prototyping: |
| | 659 | - enabling debug level 6 on dvPost will show the number of object detections in its debug output but if you want to do anything with that data you need to write an application that can decode frame buffers. Still this is useful for prototyping: |
| | 660 | * perform detection on a v4l2 video device like a webcam: |
| | 661 | {{{#!bash |
| | 662 | DEV=/dev/video_webcam |
| | 663 | MODEL=/usr/share/cnn/detection/yolov8n/model.dvm |
| | 664 | GST_DEBUG="dvInf:6" \ |
| | 665 | gst-launch-1.0 -v \ |
| | 666 | v4l2src device=$DEV ! \ |
| | 667 | video/x-raw,width=640,height=480,framerate=30/1 ! \ |
| | 668 | videoconvert ! video/x-raw,format=BGRx ! \ |
| | 669 | dvInf model=$MODEL orig-width=640 orig-height=480 stream=0 \ |
| | 670 | sock=/var/run/proxy.sock use-shm=true shm-path=/dev/shm/ara_shm ! \ |
| | 671 | fakesink sync=false | grep Detected |
| | 672 | }}} |
| | 673 | - see wiki:linux/persistent_device_naming#video for details about making video devices have persistent device names |
| | 674 | * perform a detection on an image: |
| | 675 | {{{#!bash |
| | 676 | URI=file:///$PWD/traffic.png |
| | 677 | MODEL=/usr/share/cnn/detection/yolov8n/model.dvm |
| | 678 | GST_DEBUG="dvInf:6" \ |
| | 679 | gst-launch-1.0 -v \ |
| | 680 | filesrc location=traffic.png ! \ |
| | 681 | pngdec ! imagefreeze num-buffers=10 ! \ |
| | 682 | videoscale ! videoconvert ! video/x-raw,format=BGRx,width=640,height=480 ! \ |
| | 683 | dvInf model=$MODEL orig-width=640 orig-height=480 stream=0 \ |
| | 684 | sock=/var/run/proxy.sock use-shm=true shm-path=/dev/shm/ara_shm ! \ |
| | 685 | fakesink sync=false | grep Detected |
| | 686 | }}} |
| | 687 | |
| | 688 | For a more complete example see below |
| | 689 | |
| | 690 | |
| | 691 | [=#eiq-aaf-connector] |
| | 692 | == eIQ AAF Connector for LLM inference |
| | 693 | The eIQ AAF Connector (edge Intelligence Ara Application Framework) |
| | 694 | is a REST-based server that enables LLM inference on NXP i.MX processors with the ARA-240 DNPU. The API implemented is the de-facto API standard created by OpenAI for ChatGPT. It provides a simple Chat Completions-based HTTP interface for serving models to client applications. |
| | 695 | |
| | 696 | Requirements: |
| | 697 | - python 3.13 (we will install in a virtual env) |
| | 698 | - uv - used for the user-specific Python virtual environment |
| | 699 | - Optimum Ara framework for running Large Language Models (LLMs) and Vision-Language Models (VLMs) on Ara240 (part of rt-sdk) |
| | 700 | - OpenCV (dependency of the QwenVL engine) |
| | 701 | - Models |
| | 702 | |
| | 703 | Source: |
| | 704 | - https://github.com/nxp-imx-support/eiq-aaf-connector |
| | 705 | |
| | 706 | For ease of use Gateworks provides a pre-built deb package of eiq-aaf-connector v2.1 built from the NXP IMX Yocto BSP which you can install with: |
| | 707 | {{{#!bash |
| | 708 | # fetch |
| | 709 | wget https://dev.gateworks.com/ara/eiq-aaf-connector_2.1-r0_arm64.deb |
| | 710 | # extract data (but don't install) |
| | 711 | dpkg-deb --vextract eiq-aaf-connector_2.1-r0_arm64.deb / |
| | 712 | # run the install script |
| | 713 | /usr/share/eiq/aaf-connector/install.sh |
| | 714 | # fetch LLM models (installed to /usr/share/llm) |
| | 715 | fetch_models --repo-id nxp/Qwen2.5-7B-Instruct-Ara240 # 7.7GiB LLM |
| | 716 | fetch_models --repo-id nxp/Qwen2.5-Coder-1.5B-Ara240 # 1.67GiB LLM |
| | 717 | fetch_models --repo-id nxp/Qwen2.5-VL-7B-Instruct-Ara240 # 12GB VLM |
| | 718 | }}} |
| | 719 | |
| | 720 | files: |
| | 721 | - /usr/share/eiq/aaf-connector/install.sh (install script) |
| | 722 | - /usr/share/python-wheels/eiq_aaf_connector-2.1-py3-none-any.whl (python wheel) |
| | 723 | - /usr/share/eiq/aaf-connector/server_config.json (config file) |
| | 724 | - /etc/systemd/system/eiq-aaf-connector.service (created from install script) |
| | 725 | |
| | 726 | The install script creates a systemd eiq-aaf-connector.service: |
| | 727 | {{{#!bash |
| | 728 | # Enable service on boot |
| | 729 | systemctl enable eiq-aaf-connector.service |
| | 730 | # Start the service now (or reboot) |
| | 731 | systemctl start eiq-aaf-connector.service |
| | 732 | }}} |
| | 733 | |
| | 734 | Notes: |
| | 735 | - By default the connector will listen on 127.0.0.1:8000. If you wish the service to be accessible externally set the host to '0.0.0.0' instead: |
| | 736 | {{{#!bash |
| | 737 | sed -i 's|--host 127.0.0.1|--host 0.0.0.0|g' /etc/systemd/system/eiq-aaf-connector.service |
| | 738 | }}} |
| | 739 | - the default config file has configuration for all of the above Ara models but they are not 'enabled' by default. You must only enable 1 model at a time and doing so loads the model onto the Ara when the servoce starts. To enable a model change the appropriate 'enabled' property to 'true' in /etc/systemd/system/eiq-aaf-connector.service and restart the service |
| | 740 | - it takes several minutes for the service to actually be ready for connections as it must process the models (monitor with 'journalctl -u eiq-aaf-connector.service --no-pager -f' and test that its ready for listening with 'ss -tulpn | grep :8000'). |
| | 741 | - the connector self-hosts API documentation at http://<serverip>:8000/docs (available externally if configured for a host of 0.0.0.0) |
| | 742 | |
| | 743 | Example Usage: |
| | 744 | - verify connector running |
| | 745 | {{{#!bash |
| | 746 | # show service status |
| | 747 | systemctl status eiq-aaf-connector.service --no-pager -l |
| | 748 | # view detailed service logs for the current boot and follow the journal |
| | 749 | journalctl --boot --follow --unit eiq-aaf-connector.service |
| | 750 | # verify process exists |
| | 751 | ps -ef | grep aaf-connector |
| | 752 | # verify port open |
| | 753 | ss -tulpn | grep :8000 # show IP:PORT server is listening on |
| | 754 | }}} |
| | 755 | - view API docs and interact with server (requires changing the host to '0.0.0.0' in the !ExecStart config for /etc/systemd/system/eiq-aaf-connector.service by opening !http://<serverip>:8000/docs |
| | 756 | - use API via curl/jq |
| | 757 | {{{#!bash |
| | 758 | # make sure curl and jq are installed (jq allows easy interaction with json data) |
| | 759 | apt install -y curl jq |
| | 760 | # list of models |
| | 761 | curl -X 'GET' \ |
| | 762 | 'http://127.0.0.1:8000/v1/models' \ |
| | 763 | -H 'accept: application/json' | jq |
| | 764 | # get info about a specific model (Qwen2.5-7B-Instruct) |
| | 765 | curl -X 'GET' \ |
| | 766 | 'http://127.0.0.1:8000/params/Qwen2.5-7B-Instruct' \ |
| | 767 | -H 'accept: application/json' | jq |
| | 768 | # send a LLM query |
| | 769 | curl -X POST http://127.0.0.1:8000/v1/chat/completions -H "Content-Type: application/json" -d '{ |
| | 770 | "model": "Qwen2.5-7B-Instruct", |
| | 771 | "messages": [ |
| | 772 | {"role": "system", "content": "You are a helpful assistant running on NXP i.MX hardware."}, |
| | 773 | {"role": "user", "content": "Explain what an NPU is in one sentence."} |
| | 774 | ], |
| | 775 | "max_tokens": 50 |
| | 776 | }' | jq |
| | 777 | }}} |
| | 778 | - run connector by hand (useful for troubleshooting or monitoring) |
| | 779 | {{{#!bash |
| | 780 | systemctl stop eiq-aaf-connector.service |
| | 781 | source "/usr/share/eiq/aaf-connector/venv/bin/activate" |
| | 782 | connector --host 0.0.0.0 --port 8000 # will run until stopped |
| | 783 | deactivate |
| | 784 | }}} |
| | 785 | |
| | 786 | |
| | 787 | [=#examples] |
| | 788 | == Examples |
| | 789 | Here are some Ara example applications put together by Gateworks |
| | 790 | |
| | 791 | === dvapi stats |
| | 792 | This is an ANSI c app that provides an example of using the dvapi to connect to the proxy and obtain NPU endpoint stats such as temperature, clocks and usage. Basically it's a re-implementation of the closed source /usr/share/rt-sdk-ara240/scripts/ara2_metrics_bin/hw_metrics.out. |
| | 793 | |
| | 794 | ara_status.c: |
| | 795 | {{{#!c |
| | 796 | #include <stdio.h> |
| | 797 | #include <stdlib.h> |
| | 798 | #include "dvapi.h" |
| | 799 | |
| | 800 | int main() { |
| | 801 | dv_session_t *session = NULL; |
| | 802 | dv_endpoint_t *ep_list = NULL; |
| | 803 | int ep_count = 0; |
| | 804 | dv_status_code_t status; |
| | 805 | const char *socket_path = "/run/proxy.sock"; |
| | 806 | |
| | 807 | // 1. Establish session |
| | 808 | status = dv_session_create_via_unix_socket(socket_path, &session); |
| | 809 | if (status != DV_SUCCESS) { |
| | 810 | fprintf(stderr, "Failed to connect: %s\n", dv_stringify_status_code(status)); |
| | 811 | return 1; |
| | 812 | } |
| | 813 | |
| | 814 | // 2. Get list of NPU endpoints |
| | 815 | dv_endpoint_get_list(session, &ep_list, &ep_count); |
| | 816 | |
| | 817 | for (int i = 0; i < ep_count; i++) { |
| | 818 | dv_endpoint_t *ep = &ep_list[i]; |
| | 819 | dv_endpoint_statistics_t *stats = NULL; |
| | 820 | int s_count = 0; |
| | 821 | bool is_busy = false; |
| | 822 | |
| | 823 | // 3. Retrieve status and statistics |
| | 824 | dv_get_endpoint_busyness(session, ep, &is_busy); |
| | 825 | status = dv_endpoint_get_statistics(session, ep, &stats, &s_count); |
| | 826 | |
| | 827 | if (status == DV_SUCCESS && s_count > 0) { |
| | 828 | // DRAM Calculations (Bytes to GB) |
| | 829 | double used_gb = (double)stats->ep_dram_stats.ep_total_dram_occupancy_size / 1073741824.0; |
| | 830 | double total_gb = (double)stats->ep_dram_stats.ep_total_dram_size / 1073741824.0; |
| | 831 | double dram_pct = (total_gb > 0) ? (used_gb / total_gb) * 100.0 : 0.0; |
| | 832 | |
| | 833 | // NPU Utilization (Queue occupancy) |
| | 834 | double npu_load = 0.0; |
| | 835 | if (stats->ep_infq_stats && stats->ep_infq_stats->length > 0) { |
| | 836 | npu_load = ((double)stats->ep_infq_stats->occupancy_count / stats->ep_infq_stats->length) * 100.0; |
| | 837 | } |
| | 838 | |
| | 839 | printf("--- NPU Endpoint %d Statistics ---\n", i); |
| | 840 | printf("Busy State: %s\n", is_busy ? "TRUE" : "FALSE"); |
| | 841 | printf("NPU Utilization: %.1f%%\n", npu_load); |
| | 842 | printf("Temperature: %.1f C\n", stats->ep_temp); |
| | 843 | printf("NNP Clock: %d MHz\n", stats->ep_nnp_clk); |
| | 844 | printf("SBP Clock: %d MHz\n", stats->ep_sbp_clk); |
| | 845 | printf("DRAM Clock: %d MHz\n", stats->ep_dram_clk); |
| | 846 | |
| | 847 | // Format: DRAM Usage: 8.2GB/16.0GB (51.3%) |
| | 848 | printf("DRAM Usage: %.1fGB/%.1fGB (%.1f%%)\n", used_gb, total_gb, dram_pct); |
| | 849 | printf("\n"); |
| | 850 | |
| | 851 | dv_endpoint_free_statistics(stats, s_count); |
| | 852 | } |
| | 853 | } |
| | 854 | |
| | 855 | // 4. Cleanup |
| | 856 | dv_endpoint_free_group(ep_list); |
| | 857 | dv_session_close(session); |
| | 858 | return 0; |
| | 859 | } |
| | 860 | }}} |
| | 861 | |
| | 862 | Compile: |
| | 863 | {{{#!bash |
| | 864 | apt update && apt install build-essential |
| | 865 | gcc ara_status.c -I/usr/include/sdk_ara/ -L/usr/lib/ -laraclient_aarch64 -o ara_status |
| | 866 | }}} |
| | 867 | |
| | 868 | Execution: |
| | 869 | {{{#!bash |
| | 870 | # ./ara_status |
| | 871 | --- NPU Endpoint 0 Statistics --- |
| | 872 | Busy State: FALSE |
| | 873 | NPU Utilization: 0.0% |
| | 874 | Temperature: 56.0 C |
| | 875 | NNP Clock: 900 MHz |
| | 876 | SBP Clock: 355 MHz |
| | 877 | DRAM Clock: 1066 MHz |
| | 878 | DRAM Usage: 10.0GB/16.0GB (62.5%) |
| | 879 | }}} |
| | 880 | |
| | 881 | |
| | 882 | === Image Detection with boxying via Python |
| | 883 | Python is incredibly useful for accessing GStreamer and handling the ARA detection frame data and imagemagick provides excellent tools for converting and drawing on images. We use PyGObject which is a Python package that provides bindings for libraries based on GObject Introspection such as GTK, !WebKit, and GStreamer. It allows you to use C-based frameworks in python. |
| | 884 | |
| | 885 | Steps: |
| | 886 | 1. We need to install the C libs for GStreamer and build utilities: |
| | 887 | {{{#!bash |
| | 888 | apt-get install -y \ |
| | 889 | libcairo2-dev \ |
| | 890 | libgirepository-2.0-dev \ |
| | 891 | python3-dev \ |
| | 892 | python3-gst-1.0 \ |
| | 893 | cmake pkg-config |
| | 894 | # we are also going to need to install gstreamer and its dev packages |
| | 895 | apt-get install -y \ |
| | 896 | libgstreamer1.0-dev \ |
| | 897 | libgstreamer-plugins-base1.0-dev \ |
| | 898 | libgstreamer-plugins-bad1.0-dev \ |
| | 899 | gstreamer1.0-plugins-base \ |
| | 900 | gstreamer1.0-plugins-good \ |
| | 901 | gstreamer1.0-plugins-bad \ |
| | 902 | gstreamer1.0-plugins-ugly \ |
| | 903 | gstreamer1.0-libav \ |
| | 904 | gstreamer1.0-tools |
| | 905 | }}} |
| | 906 | 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need: |
| | 907 | {{{#!bash |
| | 908 | # create a dir for the venv |
| | 909 | mkdir image-detect |
| | 910 | cd image-detect |
| | 911 | # create a venv (.venv) |
| | 912 | uv venv |
| | 913 | # install our scripts dependencies |
| | 914 | uv pip install pygobject |
| | 915 | }}} |
| | 916 | 1. (optional) fetch some images for detection |
| | 917 | {{{#!bash |
| | 918 | # fetch a coco validation image; it contains a dog on a bench and the dog is at 208,147 to 293,289 |
| | 919 | wget http://images.cocodataset.org/val2017/000000546829.jpg -O dog.jpg |
| | 920 | # use ffmpeg to grab a frame from within an MP4 |
| | 921 | apt install -y ffmpeg |
| | 922 | ffmpeg -i /usr/share/ara2-vision-examples/sample_videos/video_0.mp4 -f null - # shows how lon git is (time=00:00:15.50) |
| | 923 | ffmpeg -i /usr/share/ara2-vision-examples/sample_videos/video_0.mp4 -ss 00:00:5 -frames:v 1 traffic.png |
| | 924 | }}} |
| | 925 | 1. fetch the script |
| | 926 | {{{#!bash |
| | 927 | wget https://dev.gateworks.com/ara/examples/image_detect.py |
| | 928 | }}} |
| | 929 | 1. run the script (image_detect.py <source-image> <destination-image> [model-path]) |
| | 930 | {{{#!bash |
| | 931 | uv run image_detect.py dog.jpg coco_detections.jpg |
| | 932 | }}} |
| | 933 | - Note that without shm the pipeline needs to copy the raw image bytes over a local network-style socket connection. By mounting a dedicated memory path to /dev/shm you can eliminate that transfer (zero-copy): dvPre dumps the processed directly into a designated block of system RAM and dvInf uses a pointer to it |
| | 934 | - you would think that if your original image was 1080x1920 and you resized it to the model size of 640x640 that if you tell dvPost the orig-width=1080 orig-height=1920 that it would scale the bounding boxes properly however in practice it seems it does not unless your image has the same aspect ratio of the model. mapping it as above (telling dvPost that the image is 640x640 and scaling ourselves) resolves this |
| | 935 | - images: |
| | 936 | |
| | 937 | [[Image(dog.jpg,400px)]] |
| | 938 | [[Image(dog_detect.jpg,400px)]] |
| | 939 | |
| | 940 | [[Image(traffic.jpg,400px)]] |
| | 941 | [[Image(traffic_detect_yolo8n.jpg,400px)]] |
| | 942 | [[Image(traffic_detect_yolo8x.jpg,400px)]] |
| | 943 | |
| | 944 | |
| | 945 | === Video Detection Webapp via Python |
| | 946 | Python is incredibly useful for accessing GStreamer and handling the ARA detection frame data and building webapps. The script using PyGObject which is a Python package that provides bindings for libraries based on GObject Introspection such as GTK, !WebKit, and GStreamer. It allows you to use C-based frameworks in python. We need to install the C libs for GStreamer for this |
| | 947 | |
| | 948 | Steps: |
| | 949 | 1. We need to install the C libs for GStreamer and build utilities: |
| | 950 | {{{#!bash |
| | 951 | apt-get install -y \ |
| | 952 | libcairo2-dev \ |
| | 953 | libgirepository-2.0-dev \ |
| | 954 | python3-dev \ |
| | 955 | python3-gst-1.0 \ |
| | 956 | cmake pkg-config |
| | 957 | # we are also going to need to install GStreamer and its dev packages |
| | 958 | apt-get install -y \ |
| | 959 | libgstreamer1.0-dev \ |
| | 960 | libgstreamer-plugins-base1.0-dev \ |
| | 961 | libgstreamer-plugins-bad1.0-dev \ |
| | 962 | gstreamer1.0-plugins-base \ |
| | 963 | gstreamer1.0-plugins-good \ |
| | 964 | gstreamer1.0-plugins-bad \ |
| | 965 | gstreamer1.0-plugins-ugly \ |
| | 966 | gstreamer1.0-libav \ |
| | 967 | gstreamer1.0-tools |
| | 968 | }}} |
| | 969 | 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need: |
| | 970 | {{{#!bash |
| | 971 | # create a dir for the venv |
| | 972 | mkdir vision-webapp |
| | 973 | cd vision-webapp |
| | 974 | # create a venv (.venv) |
| | 975 | uv venv |
| | 976 | # install our scripts dependencies |
| | 977 | uv pip install pygobject opencv-python-headless flask |
| | 978 | }}} |
| | 979 | 1. fetch the script |
| | 980 | {{{#!bash |
| | 981 | wget https://dev.gateworks.com/ara/examples/vision-webapp.py |
| | 982 | }}} |
| | 983 | 1. run the script (vison-webapp.py [--port <portno>] [--camera <camera-dev>] [--mp4 <mp4-dir>] |
| | 984 | {{{#!bash |
| | 985 | uv run vision-webapp.py --camera /dev/video_webcam --mp4 /usr/share/media/sample_videos/ |
| | 986 | }}} |
| | 987 | - you can provide a webcam device path to enable streaming from a webcam and/or an mp4 directory to enable processing those. A dropdown will allow you to select the input stream and the model and the browser window will show you detections and statistics |
| | 988 | |
| | 989 | [[Image(vision-webapp.jpg,400px)]] |
| | 990 | |
| | 991 | |
| | 992 | === command-line python eIQ chatbot (chat.py) |
| | 993 | This is a command-line chatbot written in python using the eIQ AAF Connector |
| | 994 | 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need: |
| | 995 | {{{#!bash |
| | 996 | # create a dir for the venv |
| | 997 | mkdir chat |
| | 998 | cd chat |
| | 999 | # create a venv (.venv) |
| | 1000 | uv venv |
| | 1001 | # install our scripts dependencies |
| | 1002 | uv pip install -q requests |
| | 1003 | }}} |
| | 1004 | 1. fetch the script |
| | 1005 | {{{#!bash |
| | 1006 | wget https://dev.gateworks.com/ara/examples/chat.py |
| | 1007 | }}} |
| | 1008 | 1. run the script |
| | 1009 | {{{#!bash |
| | 1010 | uv run chat.py |
| | 1011 | }}} |
| | 1012 | |
| | 1013 | Example session: |
| | 1014 | {{{#!bash |
| | 1015 | --- i.MX LLM Session (Model: Qwen2.5-7B-Instruct) --- |
| | 1016 | Type 'exit' to stop. |
| | 1017 | |
| | 1018 | You: Why is the sky blue |
| | 1019 | AI: The sky appears blue because of a phenomenon called Rayleigh scattering. When sunlight enters the Earth's atmosphere, it collides with molecules and small particles in the air. Sunlight is made up of different colors, each of which has a different wavelength. Blue light has a shorter wavelength and is scattered more than other colors by the gases and particles in the atmosphere. This scattering makes the sky appear blue to our eyes. |
| | 1020 | |
| | 1021 | During sunrise and sunset, the sky can appear red or orange because the light has to travel through more of the Earth's atmosphere. This longer path means that more blue and green light is scattered out of the beam, leaving the red and orange wavelengths to dominate the light that reaches our eyes. |
| | 1022 | |
| | 1023 | So, the blue color of the sky is primarily due to the way shorter wavelength light is scattered by the Earth's atmosphere. |
| | 1024 | |
| | 1025 | --- Stats --- |
| | 1026 | Time taken: 29.18 seconds |
| | 1027 | Throughput: 5.04 tokens/sec |
| | 1028 | ------------- |
| | 1029 | |
| | 1030 | You: exit |
| | 1031 | }}} |
| | 1032 | |
| | 1033 | |
| | 1034 | === Web based python eIQ chatbot (webchat.py) |
| | 1035 | This is a web based chatbot in python using eIQ AAF Connector |
| | 1036 | |
| | 1037 | 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need: |
| | 1038 | {{{#!bash |
| | 1039 | # create a dir for the venv |
| | 1040 | mkdir webchat |
| | 1041 | cd webchat |
| | 1042 | # create a venv (.venv) |
| | 1043 | uv venv |
| | 1044 | # install our scripts dependencies |
| | 1045 | uv pip install -q fastapi psutil uvicorn |
| | 1046 | }}} |
| | 1047 | 1. fetch the script |
| | 1048 | {{{#!bash |
| | 1049 | wget https://dev.gateworks.com/ara/examples/webchat.py |
| | 1050 | }}} |
| | 1051 | 1. run the script |
| | 1052 | {{{#!bash |
| | 1053 | uv run webchat.py |
| | 1054 | }}} |
| | 1055 | 1. Open a web browser to your boards IP address port 8080: http://<ipaddr>:8080 |
| | 1056 | |
| | 1057 | Notes: |
| | 1058 | * By default this will listen for HTTP requests on port 8080 |
| | 1059 | * On startup it will enable the model (specified in the script) and restart the eIQ server if needed - waiting for the model to load may take several minutes |
| | 1060 | |
| | 1061 | |
| | 1062 | [=#vlm] |
| | 1063 | === Web based python VLM eIQ example (webvlm.py) |
| | 1064 | The eIQ AAF Connector can be used to analyze video and images. |
| | 1065 | |
| | 1066 | Here is an example of a headless web-app based off NXP's [https://github.com/nxp-imx-support/vlm-edge-studio/tree/main/src vlm-edge-studio example] using: |
| | 1067 | - Qwen2.5-VL-7B-Instruct-Ara240 |
| | 1068 | - eIQ AAF Connector |
| | 1069 | |
| | 1070 | Requirements: |
| | 1071 | - Ara runtime |
| | 1072 | - eIQ AAF Connector |
| | 1073 | - Qwen2.5-VL-7B-Instruct-Ara240 model |
| | 1074 | |
| | 1075 | Steps: |
| | 1076 | 1. create a python virtual env (always a good idea to keep python dependencies containerized) and install python libs we need: |
| | 1077 | {{{#!bash |
| | 1078 | # create a dir for the venv |
| | 1079 | mkdir webvlm |
| | 1080 | cd webvlm |
| | 1081 | # create a venv (.venv) |
| | 1082 | uv venv |
| | 1083 | # install our scripts dependencies |
| | 1084 | uv pip install -q httpx uvicorn fastapi argparse |
| | 1085 | }}} |
| | 1086 | 1. fetch the script |
| | 1087 | {{{#!bash |
| | 1088 | wget https://dev.gateworks.com/ara/examples/webvlm.py |
| | 1089 | }}} |
| | 1090 | 1. run the script |
| | 1091 | {{{#!bash |
| | 1092 | uv run webvlm.py --video-dir /usr/share/media/sample_videos/ |
| | 1093 | }}} |
| | 1094 | 1. Open a web browser to your boards IP address port 8080: http://<ipaddr>:8080 |
| | 1095 | |
| | 1096 | Notes: |
| | 1097 | * By default this will listen for HTTP requests on port 8080 |
| | 1098 | * On startup it will enable the model (specified in the script) and restart the eIQ server if needed - waiting for the model to load may take several minutes |
| | 1099 | |
| | 1100 | |
| | 1101 | [[Image(vlm-webapp.jpg,400px)]] |
| | 1102 | |
| | 1103 | |
| | 1104 | == Troubleshooting |
| | 1105 | |
| | 1106 | Please note software support should be routed through NXP, who produces the Ara240 DNPU Chip and Software SDK. |
| | 1107 | |
| | 1108 | [https://community.nxp.com] |
| | 1109 | |