Skip to content

使用 AidGen 部署 VLM

介绍

端侧部署视觉多模态大模型 (Vision Language Model, VLM) 指将原本在云端运行的大模型压缩、量化并部署到本地设备上,实现离线、低时延的自然语言理解与生成。本章节以 AidGen 推理引擎为基础,演示如何在边缘设备上完成多模态大模型的部署、加载与对话流程。

在本案例中,多模态大模型推理运行在设备端,通过 C++ 代码调用相关接口接收用户输入并实时返回对话结果。

  • 设备:Rhino Pi-X1
  • 系统:Ubuntu 22.04
  • 模型:Qwen2.5-VL-3B (392x392)

支持平台

平台运行方式
Rhino Pi-X1Ubuntu 22.04, AidLux

准备工作

  1. Rhino Pi-X1 硬件

  2. Ubuntu 22.04 系统或 AidLux 系统

案例部署

步骤一:安装 AidGenSE

bash
sudo aid-pkg update
sudo aid-pkg -i aidgense
sudo aid-pkg -i aidgen-sdk
sudo aid-pkg -i aidgen-qnn236
sudo aid-pkg -i aidgen-qnn240

步骤二:模型查询 & 获取

  • 已支持模型查看
bash
# 查看已支持的模型
aidllm remote-list api

#------------------------示例输出如下------------------------

Current Soc : 8550

Name                                                    Url                                                           CreateTime
-----                                                   ---------                                                     ---------
qwen2.5-vl-3b-instruct-392x392-qnn2.36-w4a16-qcs8550    aplux/qwen2.5-vl-3b-instruct-392x392-qnn2.36-w4a16-qcs8550    2026-05-15 10:57:51
qwen2.5-vl-3b-instruct-672x672-qnn2.36-w4a16-qcs8550    aplux/qwen2.5-vl-3b-instruct-672x672-qnn2.36-w4a16-qcs8550    2026-05-15 10:57:49
...
  • 下载 qwen2.5-vl-3b-instruct-392x392-qnn2.36-w4a16-qcs8550
bash
# 下载模型
aidllm pull api aplux/qwen2.5-vl-3b-instruct-392x392-qnn2.36-w4a16-qcs8550

# 查看已下载模型
aidllm list api

步骤三:启动 HTTP 服务

bash
# 启动对应模型的 openai api 服务
aidllm start api -m qwen2.5-vl-3b-instruct-392x392-qnn2.36-w4a16-qcs8550

# 查看状态
aidllm status api

# 停止服务: aidllm stop api

# 重启服务: aidllm restart api

💡注意

默认端口号是 8888

步骤四:对话测试

使用 Web UI 对话测试

bash
# 安装 UI 前端服务
sudo aidllm install ui

# 启动 UI 服务
aidllm start ui

# 查看 UI 服务状态: aidllm status ui

# 停止 UI 服务: aidllm stop ui

UI 服务启动后访问 http://ip:51104

使用 Python 对话测试

python
import os
import sys
import requests
import json
import base64


def stream_chat_completion(messages, model="qwen2.5-vl-3b-instruct-392x392-qnn2.36-w4a16-qcs8550"):

    url = "http://127.0.0.1:8888/v1/chat/completions"
    headers = {
        "Content-Type": "application/json"
    }
    payload = {
        "model": model,
        "messages": messages,
        "stream": True    # 打开流式
    }

    # 发起带 stream=True 的请求
    response = requests.post(url, headers=headers, json=payload, stream=True)
    try:
        response.raise_for_status()
    except requests.HTTPError as e:
        print(f"\nHTTP error: {e}", file=sys.stderr)
        if response.text:
            print(response.text, file=sys.stderr)
        raise

    # 逐行读取并解析 SSE 格式
    for line in response.iter_lines():
        if not line:
            continue
        # print(line)
        line_data = line.decode('utf-8')
        # SSE 每一行以 "data: " 前缀开头
        if line_data.startswith("data: "):
            data = line_data[len("data: "):]
            # 结束标志
            if data.strip() == "[DONE]":
                break
            try:
                chunk = json.loads(data)
            except json.JSONDecodeError:
                # 解析出错时打印并跳过
                print("无法解析JSON:", data)
                continue

            # 取出模型输出的 token
            content = chunk["choices"][0]["delta"].get("content")
            if content:
                print(content, end="", flush=True)

def image_to_data_url(image_path):
    """读取图片并转换为 data URL,兼容 OpenAI 风格的 image_url 字段"""
    ext = os.path.splitext(image_path)[1].lower()
    mime_map = {
        ".jpg": "image/jpeg",
        ".jpeg": "image/jpeg",
        ".png": "image/png",
        ".webp": "image/webp",
    }
    mime_type = mime_map.get(ext, "image/jpeg")
    b64_str = image_to_base64(image_path)
    return f"data:{mime_type};base64,{b64_str}"


if __name__ == "__main__":
    image_url = image_to_data_url("/path/to/your/image.jpg")
    # 示例对话
    messages = [
        {
            "role": "system", 
            "content": "You are a helpful assistant."
        },
        {
            "role": "user", 
            "content":[
                        {
                            "type": "text",
                            "text": "这张图片描述了什么内容?"
                        },
                        {
                            "type": "image_url",
                            "image_url": 
                            {
                                "url": image_url
                            }
                        }
                    ]   
        },
    ]
    print("Assistant:", end=" ")
    stream_chat_completion(messages)
    print()  # 换行