开发机配置(PC电脑)

# Step1:下载D-Robotics_LLM_{version}.tar.gz安装包并正确解压。
wget https://d-robotics-aitoolchain.oss-cn-beijing.aliyuncs.com/llm_s100/1.0.0/D-Robotics_LLM_S100_1.0.0_SDK.tar.gz
# Step2:安装Conda环境
wget -c https://mirrors.bfsu.edu.cn/github-release/conda-forge/miniforge/LatestRelease/Miniforge3-Linux-x86_64.sh
chmod 777 Miniforge3-Linux-x86_64.sh
sh Miniforge3-Linux-x86_64.sh
conda create -n oellm python=3.10
conda activate oellm
# (oellm) xxx@xxx:~$ 
# Step3:安装必要的python环境
# D-Robotics_LLM_{version}路径下
pip install -r ./oellm_build/requirements.txt
pip install ./oellm_build/hbdk4_compiler-{version}-cp310-cp310-manylinux_2_17_x86_64.whl
pip install ./oellm_build/hbdk4_runtime_aarch64_unknown_linux_gnu_nash-{version}-py3-none-any.whl
pip install ./oellm_build/leap_llm-{version}-py310-none-any.whl

# Step4:将leapllm的model链接进本地开发目录
pip3 show leap-llm
ln -s /path/you/oellm/lib/python3.10/site-packages/leap_llm .

权重下载

        我们以siglip-so400m-patch14-384为示例来体验oe_llm

export HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download google/siglip-so400m-patch14-384 --local-dir siglip-so400m-patch14-384

二、使用OE-LLM量化编译

Leap工具链分析(仅个人分析,不代表地瓜官方)

        我个人理解,oe-llm与传统的量化流程(如离线 PTQ 或 QAT)有明显区别。它更像是一套“模型重构 + 校准 + 编译导出”的工具链:开发者需要先基于leap_llm提供的模块,将原始 PyTorch 网络改写为 Leap 可识别的实现;随后使用校准数据运行浮点forward()收集量化统计信息;最后切换到build()路径,将模型导出为 Leap/HBDK 计算图并编译成可部署到板端的 HBM 模型。

        从源码来看,leap_llm/nn/modules中常用的量化相关组件主要包括以下几类。需要注意的是,并不是所有模型都只依赖FakeQuant模块,部分模型也会混用DynamicQuantRMSNormLayerNormSplit等其他封装组件。

量化相关组件 所在文件 功能描述
FakeQuantEmbedding embedding.py 量化嵌入层
FakeQuantLinear linear.py 量化线性层
FakeQuantRMSNorm rms_norm.py 量化 RMS 归一化
ConstFakeQuant const_fake_quant.py 常量假量化/定点化
FakeQuantAdd ops.py 量化加法
FakeQuantMul ops.py 量化乘法
FakeQuantRsqrt ops.py 量化平方根倒数
FakeQuantReduceMean ops.py 量化均值归约
FakeQuantPow ops.py 量化幂运算
FakeQuantMatmul matmul.py 量化矩阵乘法
DynamicQuantMatmul matmul.py 动态量化矩阵乘法
FakeQuantSoftmax activation.py 量化 Softmax
FakeQuantSwish activation.py 量化 Swish 激活
FakeQuantGELU activation.py 量化 GELU 激活
FakeQuantPatchEmbedding vision_embedding.py 量化视觉 Patch 嵌入

        整体流程可以概括为三步。第一步是完成模型重构。通常需要将原始的nn.Module改写为继承ModelModule的 Leap 版本,并将其中的关键算子替换为对应的量化组件。每个重构后的模块通常都需要同时实现build()forward()两套逻辑:其中build()负责使用leap.*算子描述最终要编译到 BPU 上的计算图,forward()则保留 PyTorch 浮点路径,用于校准和精度对齐。

# 原始模型
class StandardLLM(nn.Module):
    def __init__(self):
        self.embedding = nn.Embedding(vocab_size, hidden_size)
        self.layers = nn.ModuleList([DecoderLayer() for _ in range(num_layers)])
        self.norm = nn.RMSNorm(hidden_size)
        self.lm_head = nn.Linear(hidden_size, vocab_size)

# OE-LLM重构后的模型(示意)
class QuantLLM(Model):
    def __init__(self):
        self.embedding = FakeQuantEmbedding(vocab_size, hidden_size)
        self.layers = nn.ModuleList([QuantDecoderLayer() for _ in range(num_layers)])
        self.norm = FakeQuantRMSNorm(hidden_size)
        self.lm_head = FakeQuantLinear(hidden_size, vocab_size)
    def build(self, inputs):
        pass
    def forward(self, inputs):
        pass

        第二步是校准。校准阶段的核心目标是让各个量化模块在浮点前向过程中收集统计信息,例如absmax、缩放因子或归一化相关的范围信息。因此,校准数据的预处理流程必须与目标模型的真实输入分布尽可能一致。对于视觉模型,往往需要单独实现适合该模型的图像预处理与 patch 化逻辑,而不能直接套用默认的 LLM 文本预处理流程。

# 收集量化统计信息
model.set_compile_mode(False)
for batch in calibration_data:
    model.forward(batch)  # 量化模块在forward过程中收集统计信息

        最后一步是编译导出。此时模型会切换到build()路径,由leap_llm将计算图导出、转换并进一步编译为板端可执行的模型文件。这里的dtypemarch并不是固定不变的,需要根据具体模型实现和目标平台来确定。以本文的 SigLip Vision 为例,最终编译阶段使用的是leap.float16

# 生成量化编译模型
model.set_compile_mode(True)
model.compile(
    dtype=leap.float16,
    march="nash-e",
    output_model_path="model.hbm"
)

SigLip结构分析与工具链适配

        我们根据包里的标准格式创建好SigLip的文件结构便可以结合SigLip的Pytorch网络结构使用FakeQuant类对应执行重构,接下来我们结合Transformer库中SigLip的PyTorch实现来对比分析实现

(xq) qi.xiong@instance-ujccspas:~/RDK_OE_LLM/D-Robotics_LLM_S100_1.0.0_SDK/leap_llm/models/siglip$ tree -L 2
.
├── __init__.py
├── blocks
│   ├── __init__.py
│   ├── attention.py
│   ├── encoder_layer.py
│   └── mlp.py
└── model.py
4 directories, 8 files
(1)MLP部分

        SigLip 的 MLP 部分非常标准,本质上就是 Vision Transformer 中最常见的前馈网络结构:先将通道维从hidden_size升维到intermediate_size,经过激活函数后再投影回原维度。由于 SigLip 使用的是普通的 GELU MLP,而不是 SwiGLU 或 MoE 这类更复杂的结构,因此这一部分也是整个工具链适配中最容易完成一一映射的部分。

官方 SigLip 实现

class SiglipMLP(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.activation_fn = ACT2FN[config.hidden_act]
        self.fc1 = nn.Linear(config.hidden_size, config.intermediate_size)
        self.fc2 = nn.Linear(config.intermediate_size, config.hidden_size)

    def forward(self, hidden_states):
        hidden_states = self.fc1(hidden_states)
        hidden_states = self.activation_fn(hidden_states)
        hidden_states = self.fc2(hidden_states)
        return hidden_states

        从结构上看,这一块没有额外的残差、没有门控、也没有特殊的数据排布变化,所以我在 Leap 中直接按照“线性层 -> 激活函数 -> 线性层”的顺序进行了重写。其核心思想就是把 PyTorch 的nn.Linear和 GELU 激活替换成 Leap 工具链里对应的量化模块,并保持张量流向完全一致。

Leap中的实现

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐