Skip to content

Commit fea3d28

Browse files
committed
LP: Multimodal On-Device Inference on Armv9 with MNN for Audio and Vision
1 parent e45251a commit fea3d28

8 files changed

Lines changed: 467 additions & 0 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
title: Understand MNN and Omni for Armv9 on-device inference
3+
weight: 2
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
## Why MNN for on-device deployment
10+
11+
- **Portable inference runtime** with strong support for mobile and edge platforms
12+
- **CPU-first workflow** that maps naturally to Armv9 servers and development boards
13+
- Native builds allow you to benefit from **Arm-specific optimizations** (such as KleidiAI)
14+
- Single codebase can target x86, Arm Linux, Android, and iOS
15+
16+
## Why Omni multimodal
17+
18+
- **Single model** that can handle **image, audio, and text** in one pipeline
19+
- Enables **cross-modal tasks** such as “look at this shelf + listen to this note → generate an operational ticket”
20+
- **Prompt-based control** with tags like `<img>…</img>` and `<audio>…</audio>`
21+
- No need to maintain separate models for vision and speech
22+
23+
## Scope boundaries for reproducibility
24+
25+
To keep this Learning Path simple and repeatable, we deliberately limit the scope:
26+
27+
- **CPU-only**
28+
No GPU or NPU acceleration is required.
29+
30+
- **No quantization**
31+
You use a **prebuilt MNN Omni model package** as-is. No additional export or quantization steps are needed.
32+
33+
- **No CPU–NPU heterogeneous pipeline**
34+
All compute runs on the Armv9 CPU. Focus is on **correctness and reproducibility**, not maximum throughput.
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
title: Build MNN and prepare an Omni model on Armv9
3+
weight: 3
4+
layout: "learningpathall"
5+
---
6+
7+
## Get source and native build
8+
9+
Create a working directory under your home folder:
10+
11+
```bash
12+
cd ~
13+
mkdir -p ~/mnn_lp
14+
cd ~/mnn_lp
15+
```
16+
17+
Clone MNN and build:
18+
19+
```bash
20+
git clone https://github.com/alibaba/MNN.git
21+
cd MNN
22+
23+
rm -rf build
24+
mkdir build && cd build
25+
26+
cmake .. \
27+
-DMNN_BUILD_SHARED=ON \
28+
-DMNN_BUILD_LLM=ON \
29+
-DMNN_BUILD_AUDIO=ON \
30+
-DMNN_BUILD_LLM_OMNI=ON \
31+
-DMNN_LOW_MEMORY=ON \
32+
-DMNN_KLEIDIAI=ON
33+
34+
make -j$(nproc)
35+
```
36+
37+
**Key CMake options:**
38+
39+
- `MNN_BUILD_LLM=ON` – enables LLM support
40+
- `MNN_BUILD_AUDIO=ON` – enables audio features needed for Omni
41+
- `MNN_BUILD_LLM_OMNI=ON` – enables multimodal Omni support
42+
- `MNN_LOW_MEMORY=ON` – uses lower memory configurations where possible
43+
- `MNN_KLEIDIAI=ON` – enables KleidiAI-related optimizations on supported Arm platforms
44+
45+
Verify that `llm_demo` was built:
46+
47+
```bash
48+
ls -l ~/mnn_lp/MNN/build/llm_demo
49+
```
50+
51+
---
52+
53+
## Avoid library mismatch
54+
55+
On systems with multiple MNN builds, a common pitfall is a **binary from one build tree** loading a **shared library from another**.
56+
57+
Check which libraries `llm_demo` will use:
58+
59+
```bash
60+
cd ~/mnn_lp/MNN/build
61+
ldd ./llm_demo
62+
```
63+
64+
Ensure that `libMNN.so` and related libraries point to your **current build directory**.
65+
66+
If you see a mismatch, set `LD_LIBRARY_PATH` explicitly:
67+
68+
```bash
69+
export LD_LIBRARY_PATH=~/mnn_lp/MNN/build:$LD_LIBRARY_PATH
70+
```
71+
72+
Re-run `ldd` or `./llm_demo` to confirm the correct shared libraries are used.
73+
74+
---
75+
76+
## Download a prebuilt MNN Omni model
77+
78+
This Learning Path assumes you have a prebuilt Omni model package, for example:
79+
80+
```bash
81+
~/mnn_lp/Qwen2.5-Omni-7B-MNN
82+
```
83+
84+
The directory should contain at least a `config.json` and the associated model files.
85+
86+
Verify the config path:
87+
88+
```bash
89+
ls -l ~/mnn_lp/Qwen2.5-Omni-7B-MNN/config.json
90+
```
91+
92+
**Important:** This is an **MNN-ready Omni package**. You **do not** need to export from PyTorch or perform additional quantization.
93+
94+
---
95+
96+
## Checkpoint
97+
98+
You should be able to start `llm_demo` with your config:
99+
100+
```bash
101+
cd ~/mnn_lp/MNN/build
102+
./llm_demo ~/mnn_lp/Qwen2.5-Omni-7B-MNN/config.json
103+
```
104+
105+
If the binary starts without `undefined symbol` or library errors, you are ready for the next module.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
title: Run a text baseline with an Omni model on MNN
3+
weight: 4
4+
layout: "learningpathall"
5+
---
6+
7+
## Steps
8+
9+
Create a simple text prompt file:
10+
11+
```bash
12+
cat > ~/mnn_lp/text_baseline_prompt.txt <<'EOF'
13+
You are an on-device assistant. In one short sentence, describe the goal of this tutorial.
14+
EOF
15+
```
16+
17+
Run `llm_demo`:
18+
19+
```bash
20+
cd ~/mnn_lp/MNN/build
21+
./llm_demo ~/mnn_lp/Qwen2.5-Omni-7B-MNN/config.json ~/mnn_lp/text_baseline_prompt.txt
22+
```
23+
24+
You should see a short textual response describing the tutorial’s goal.
25+
26+
## Checkpoint
27+
28+
You have completed this module when:
29+
30+
- `llm_demo` successfully loads the config and model
31+
- At least one text prompt returns a stable, sensible response
32+
- No crashes or runtime errors occur
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
title: Run a vision retail shelf audit with MNN Omni
3+
weight: 5
4+
layout: "learningpathall"
5+
---
6+
7+
## Scenario
8+
9+
In this module you will implement a **smart retail shelf audit** using a single local image.
10+
11+
The model will:
12+
13+
- Inspect a **pet food aisle** image
14+
- Estimate **facing coverage** for three shelf levels: **top / middle / bottom**
15+
- Identify a **priority zone** that appears most sparse
16+
- Use `NOT_SURE` where the image is ambiguous
17+
18+
19+
## Assets
20+
21+
Create an `assets` directory:
22+
23+
```bash
24+
mkdir -p ~/mnn_lp/assets
25+
```
26+
27+
Download the tutorial image:
28+
29+
```bash
30+
curl -L -o ~/mnn_lp/assets/pet_food_aisle.jpg \
31+
"https://upload.wikimedia.org/wikipedia/commons/5/57/Pet_Food_Aisle.jpg"
32+
33+
file ~/mnn_lp/assets/pet_food_aisle.jpg
34+
```
35+
36+
The `file` command confirms that this is a valid JPEG image.
37+
38+
39+
## Prompt design
40+
41+
You will design a prompt that:
42+
43+
- Uses `<img>…</img>` to attach the local image
44+
- Restricts the model to auditing **only the main left shelf**
45+
- Requests coverage as **high/medium/low** for each level
46+
- Asks for a single **priority zone** on the left shelf
47+
- Encodes the output as a **single line** with `;`-separated segments
48+
49+
Create the prompt file (adjust `/home/radxa` to your actual user home if needed):
50+
51+
```bash
52+
cat > ~/mnn_lp/prompt_picture_coverage.txt <<'EOF'
53+
<img>/home/radxa/mnn_lp/assets/pet_food_aisle.jpg</img> You are an on-device retail shelf auditing assistant. Audit ONLY the main left shelf (ignore the aisle on the right, hanging toys, and floor items). Do NOT count every item. Estimate facing coverage for top/middle/bottom as high|medium|low and identify the sparsest zone. Output ONE line only using bullet-style segments separated by semicolons: Shelf audit; - Coverage: top=<high|medium|low>, middle=<high|medium|low>, bottom=<high|medium|low>; - Priority zone: <top|middle|bottom>-<left|center|right>; - Reason: <one short sentence>; - Notes: <NOT_SURE if unclear>.
54+
EOF
55+
```
56+
57+
Run the vision demo:
58+
59+
```bash
60+
cd ~/mnn_lp/MNN/build
61+
./llm_demo ~/mnn_lp/Qwen2.5-Omni-7B-MNN/config.json ~/mnn_lp/prompt_picture_coverage.txt
62+
```
63+
64+
65+
## Checkpoint
66+
67+
You have completed this module when the output:
68+
69+
- Includes coverage estimates for **top / middle / bottom**
70+
- Identifies a **priority zone** such as `middle-center`
71+
- Provides a **short reason** that clearly references visible sparsity on the shelf
72+
- Uses `NOT_SURE` only where the image is genuinely unclear
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
title: Convert audio restock instructions into tickets with MNN Omni
3+
weight: 6
4+
layout: "learningpathall"
5+
---
6+
7+
## Scenario
8+
9+
In this module you will convert a **spoken restock note** into a structured **restock ticket**.
10+
11+
For example, a store associate might say:
12+
13+
> We need to restock large dog food bags on the bottom-left, four units, before tomorrow afternoon. If large bags are out of stock, use medium bags as a substitute.
14+
15+
Your goal is to:
16+
17+
- Extract **items, quantities, zones, deadlines, and substitution policy**
18+
- Encode them as a **single-line ticket** with clearly labeled fields
19+
20+
## Assets
21+
22+
Prepare a WAV file under `assets`:
23+
24+
```bash
25+
file ~/mnn_lp/assets/restock_note.wav
26+
```
27+
28+
If you only have an MP3 file, convert it to a suitable WAV format:
29+
30+
```bash
31+
ffmpeg -y -i input.mp3 -ac 1 -ar 16000 -c:a pcm_s16le ~/mnn_lp/assets/restock_note.wav
32+
```
33+
34+
This produces a **mono, 16 kHz, 16-bit PCM** WAV file, which is commonly used for speech models.
35+
36+
37+
## Prompt design
38+
39+
You will ask the model to produce a **readable, single-line ticket** with:
40+
41+
- Item
42+
- Quantity (or `NOT_SURE` if not spoken)
43+
- Shelf zone
44+
- Deadline
45+
- Substitution policy
46+
- Notes and confidence
47+
48+
Create the prompt file:
49+
50+
```bash
51+
cat > ~/mnn_lp/prompt_audio_ticket.txt <<'EOF'
52+
<audio>/home/radxa/mnn_lp/assets/restock_note.wav</audio> You are a retail store replenishment assistant. Convert the spoken note into a restocking ticket. Output EXACTLY ONE line using bullet-style segments separated by semicolons: Restock ticket; - Location: pet food aisle left shelf; - Task 1: <generic item> | qty <number or NOT_SURE> | zone <top|middle|bottom>-<left|center|right or NOT_SURE>; - Task 2: <generic item> | qty <number or NOT_SURE> | zone <top|middle|bottom>-<left|center|right or NOT_SURE>; - Deadline: <time or NOT_SURE>; - Substitution: <use similar substitute|no substitute|NOT_SURE>; - Notes: <short note>; - Confidence: <high|medium|low>. Rules: do not invent quantities if not in audio.
53+
EOF
54+
```
55+
56+
Run the audio demo:
57+
58+
```bash
59+
cd ~/mnn_lp/MNN/build
60+
./llm_demo ~/mnn_lp/Qwen2.5-Omni-7B-MNN/config.json ~/mnn_lp/prompt_audio_ticket.txt
61+
```
62+
63+
64+
## Checkpoint
65+
66+
You have completed this module when:
67+
68+
- The ticket’s **quantities and deadline** match what is actually spoken
69+
- Fields that are **not mentioned** in the audio are filled with `NOT_SURE` rather than invented values
70+
- The resulting line is easy to parse and understand
71+

0 commit comments

Comments
 (0)