You can run a wide range of Large Language Models (LLMs) and Vision Language Models (VLMs) on your Dragonwing development boards using llama.cpp. Models running under llama.cpp run on the GPU, not on the NPU. You can run a subset of models on the NPU via GENIE.
You’ll need to build some dependencies for llama.cpp. Open the terminal on your development board, or an ssh session to your development board, and run:
cd ~/dev/llm# Clone repositorygit clone https://github.com/ggml-org/llama.cppcd llama.cpp# We've tested this commit explicitly, you can try master if you want bleeding edgegit checkout f6da8cb86a28f0319b40d9d2a957a26a7d875f8cgit rev-parse HEAD# Expected: f6da8cb86a28f0319b40d9d2a957a26a7d875f8c# Buildmkdir -p buildcd buildcmake .. -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBS=OFF \ -DGGML_OPENCL=ONninja -j`nproc`
4
Add the llama.cpp paths to your PATH
cd ~/dev/llm/llama.cpp/build/binecho "" >> ~/.bash_profileecho "# Begin llama.cpp" >> ~/.bash_profileecho "export PATH=\$PATH:$PWD" >> ~/.bash_profileecho "# End llama.cpp" >> ~/.bash_profileecho "" >> ~/.bash_profile# To use the llama.cpp files in your current sessionsource ~/.bash_profile
To run GPU-accelerated models you’ll want pure 4-bit quantized (Q4_0) models in GGUF format (the llama.cpp format, conversion guide). You can either find pre-quantized models, or quantize a model yourself using llama-quantize. For example, for Qwen2-1.5B-Instruct:
import requests# if running from your own computer, replace localhost with the IP address of your development boardurl = "http://localhost:9876/v1/chat/completions"payload = { "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Explain Qualcomm in one sentence."} ], "temperature": 0.7, "max_tokens": 200}response = requests.post(url, headers={ "Content-Type": "application/json" }, json=payload)print(response.json())
3
Run chat.py
python3 chat.py# ...# {'choices': [{'finish_reason': 'stop', 'index': 0, 'message': {'role': 'assistant', 'content': 'Qualcomm is a leading global technology company that designs, develops, licenses, and markets semiconductor-based products and mobile platform technologies to major telecommunications and consumer electronics manufacturers worldwide.'}}], 'created': 1757073340, 'model': 'gpt-3.5-turbo', 'system_fingerprint': 'b6362-f6da8cb8', 'object': 'chat.completion', 'usage': {'completion_tokens': 34, 'prompt_tokens': 26, 'total_tokens': 60}, 'id': 'chatcmpl-3O7l005WG1DzN191FTNomJNweHMoH8Is', 'timings': {'prompt_n': 12, 'prompt_ms': 303.581, 'prompt_per_token_ms': 25.298416666666668, 'prompt_per_second': 39.52816546490064, 'predicted_n': 34, 'predicted_ms': 4052.23, 'predicted_per_token_ms': 119.18323529411765, 'predicted_per_second': 8.390441806116632}}
You can also use multi-modal LLMs. For example SmolVLM-500M-Instruct-GGUF. Download both the Q4_0 quantized weights (or quantize them yourself), and download the CLIP encoder mmproj-*.gguf file. For example:
# Download weightswget https://huggingface.co/ggml-org/SmolVLM-500M-Instruct-GGUF/resolve/main/SmolVLM-500M-Instruct-f16.ggufwget https://huggingface.co/ggml-org/SmolVLM-500M-Instruct-GGUF/resolve/main/mmproj-SmolVLM-500M-Instruct-f16.gguf# Quantize model (mmproj- models are not quantizable via llama-quantize, see below)llama-quantize --pure SmolVLM-500M-Instruct-f16.gguf SmolVLM-500M-Instruct-q4_0-pure.gguf Q4_0# Serve the modelllama-server -m ./SmolVLM-500M-Instruct-q4_0-pure.gguf --mmproj ./mmproj-SmolVLM-500M-Instruct-f16.gguf --no-warmup -b 128 -c 2048 -s 11 -n 128 --host 0.0.0.0 --port 9876
Serving multi-modal LLMs using llama-server
CLIP model is still fp16: The mmproj model is still fp16; and thus processing images will be slow. There is code to quantize the CLIP encoder in older versions of llama.cpp, that you can explore.
Add -ngl 0 to the llama-* commands to skip offloading layers to the GPU. Models will run on CPU, and you can compare performance to that of the GPU.For example, the Qwen2-1.5B-Instruct Q4_0:GPU:
llama-cli -m ./qwen2-1_5b-instruct-q4_0-pure.gguf -no-cnv --no-warmup -b 128 -c 2048 -s 11 -n 128 -p "Knock knock, " -fa off# llama_perf_sampler_print: sampling time = 26.33 ms / 133 runs ( 0.20 ms per token, 5050.70 tokens per second)# llama_perf_context_print: load time = 3535.69 ms# llama_perf_context_print: prompt eval time = 192.38 ms / 5 tokens ( 38.48 ms per token, 25.99 tokens per second)# llama_perf_context_print: eval time = 5679.81 ms / 127 runs ( 44.72 ms per token, 22.36 tokens per second)# llama_perf_context_print: total time = 9276.10 ms / 132 tokens# llama_perf_context_print: graphs reused = 122
CPU:
llama-cli -m ./qwen2-1_5b-instruct-q4_0-pure.gguf -no-cnv --no-warmup -b 128 -ngl 99 -c 2048 -s 11 -n 128 -p "Knock knock, " -fa off -ngl 0# llama_perf_sampler_print: sampling time = 15.44 ms / 133 runs ( 0.12 ms per token, 8615.66 tokens per second)# llama_perf_context_print: load time = 1061.95 ms# llama_perf_context_print: prompt eval time = 51.75 ms / 5 tokens ( 10.35 ms per token, 96.62 tokens per second)# llama_perf_context_print: eval time = 2789.13 ms / 127 runs ( 21.96 ms per token, 45.53 tokens per second)# llama_perf_context_print: total time = 3885.55 ms / 132 tokens# llama_perf_context_print: graphs reused = 122
Here the CPU evaluates tokens about twice as fast as the GPU.