欢迎光临
我们一直在努力

20 天、800KB、零依赖:AI Agent 结对写出的纯 C 国密 LLM 推理引擎

文章首发于 CSDN 技术社区 | 开源仓库:https://gitee.com/pei-xiaoguang/kestrel-llm。原创声明:本文首发于 CSDN,作者保留版权;转载需注明出处。

引子:一张软盘就能装下的 LLM 推理引擎

当听到“800KB”这个词时,你大概会下意识补一句“……的模型”或“……的脚本”。但我们这次想说:一个能跑大模型的 LLM 推理引擎,编译出来的可执行文件只有约 0.8 MB(RK3588 板端实测 818,872 字节)。不是剪裁过的玩具:它跑的是 Qwen3-VL 2B/8B 的纯文本与图片/视频多模态推理,自带 OpenAI 兼容 HTTP 服务、管理页与模型转换工具;没有 GPU、没有 PyTorch、没有 CUDA,甚至没有 OpenMP 运行时和任何第三方密码学库——整条技术栈从 NEON 量化 GEMM、线程池、VQF 权重格式,到国密 SM3/SM4/SM2,全部自己写。而这套东西,是我们和 Trae(AI IDE) 的 Agent 结对、用了 20 天从零做出来的——它负责把设计变成能编译的 C、把结论变成文档与测试,正确性红线始终由我们把关。

先说清“20 天”的口径:这里的 20 天指从立项到 RK3588 板端可跑初版的核心开发周期,不含此前更早的研究探索(如同态加密推理内核 RNS-CKKS、x86↔aarch64 位级一致验证等,那部分另有论文与文档)。完整技术细节见仓库 docs/。

〇、三分钟上手(想动手的直接看这里)

在 RK3588(aarch64)或任意支持编译该工程的 Linux 上:

git clone https://gitee.com/pei-xiaoguang/kestrel-llm.git && cd kestrel-llm
./build_rk3588.sh # 板端原生构建(Release,产物 build-rk3588/vllm_kestrel)
权重转换(一次性):safetensors / GGUF → VQF v2 单文件
./vllm_kestrel –convert-vqf model.vqf –model <hf-model-dir> –wmode q4
或:
./vllm_kestrel –convert-gguf model.vqf –model model.gguf –wmode q4
启动服务
./vllm_kestrel –serve –model <model-dir> –port 8080 –wmode q4 –auto-load
验证
curl http://<板端IP>:8080/health
curl http://<板端IP>:8080/v1/chat/completions

-H 'Content-Type: application/json'

-d '{"model":"qwen3-vl","messages":[{"role":"user","content":"你好"}],"max_tokens":64}'

构建自检(无模型即可跑):

$ ./build-rk3588/vllm_kestrel –test-l3
[PASS] q4 dot vs scalar reference (rel 7.68e-08)
[PASS] eviction deterministic (11 == 11 blocks evicted)
=== L3 self-test PASSED (0 failures) ===

一、800KB 是怎么做到的:把“重”留给引擎自己,不留给依赖

主流推理路径的体积大家都有体感:Python 解释器 + 推理框架 + CUDA 栈,动辄几个 GB。我们的思路反着来:既然目标只有一块 RK3588 开发板,那就只为一个架构、一个模型家族、一种部署形态写代码,其他一概不引。

常见依赖我们怎么办
Python / PyTorch / 推理框架运行时 没有——一个 C11 可执行文件就是完整服务
GPU 计算栈(CUDA/ROCm) 没有——纯 CPU,NEON 量化内核手写
第三方推理/矩阵库(ggml、OpenBLAS…) 没有——GEMM/GEMV 手写(8×8 / 4×4 / SDOT)
密码学库(OpenSSL/GmSSL/MbedTLS) 没有——SM3 / SM4-CTR / HMAC-SM3 / SM2 自研,按国密标准向量 KAT 逐字节验证
OpenCV / FFmpeg 等媒体库 没有——图片解码用单头 stb_image.h(MIT)
Web/HTTP 框架、JSON 库 没有——自研 select 轮询 HTTP + SSE,自研最小 JSON
OpenMP 运行时 引擎核心并行走自研线程池 vllm_tp(OpenMP 仅在 NPU 直驱的打包并行区用到,且 libgomp 是 gcc 自带的)

代码里仅有的第三方是两段 MIT 授权的数据面组件:stb_image.h(Sean Barrett)与从 llama.cpp 提取并署名的 4×4 asm GEMM 内核(文件头均有版权声明)。引擎本体没有任何第三方项目运行时随包分发——动态构建只依赖系统工具链的 glibc/libgomp;开 -DVLLM_STATIC=ON 全静态构建后,产物连 .so 都没有,拷到任意 aarch64 Linux 上直接跑。

# 全静态构建(零 .so 依赖)
cmake -S . -B build-static -DVLLM_STATIC=ON -DCMAKE_BUILD_TYPE=Release
cmake –build build-static -j8
ldd build-static/vllm_kestrel # 输出:not a dynamic executable

二、为什么敢碰“边缘端跑 LLM”:先解决加载,再解决计算

边缘设备跑大模型有两个天然矛盾:内存小、算力弱。拆成两个工程问题逐个击破。

1. 把“量化+布局”固化到文件里:VQF 格式

常规流程是启动时“读权重 → 逐层量化 → 重排布局”,2B 模型在板端要 20 多秒。我们自研 VQF v2 权重格式:转换阶段就把量化与 8×8/4×4 布局重排做好,推理时 mmap 映射 + 指针直挂,冷启动被压到 2 秒级(板端实测 spawn→HTTP ready 2.01s,模型加载约 1.2s)。格式层用编译期守卫锁死布局,防止三方代码漂移(引擎 / 离线签名工具 / KAT 测试共用同一头文件):

/* include/model/vqf_format.h */
_Static_assert(sizeof(VQFSig) == 200, "VQFSig layout drift");
_Static_assert(sizeof(VQFHeader) == 432, "VQFHeader layout drift");
_Static_assert(sizeof(VQFTensor) == 64, "VQFTensor layout drift");

转换与推理共用同一套量化代码,也顺带解决了“位级一致”这个强迫症问题——两套实现漂移的情况不存在。

2. 把“能省的”都省掉:稀疏注意力 + KV 复用

边缘端 decode 的瓶颈是内存带宽:每生成一个 token 都要扫一遍全部 KV 缓存。我们实现了稀疏注意力(top-k 块)与 INT8 量化 KV,把每词 KV 扫描限定在固定块数内——这是长上下文下 decode 端拉开差距的原因。服务端再做三件“懒”事:内存前缀 KV 复用(多轮只 prefill 差异)、磁盘 KV 快照(跨进程/重启恢复)、推测解码。

3. 位级确定性:工程红线

引擎数值路径完全确定:同输入同参数,多轮实测输出逐位一致。这为“可验证推理”打了地基——如果引擎自己都不确定,谈何给别人出凭证。

三、跑分只说同机对照:RK3588 vs llama.cpp

所有数据在同一块 RK3588(Orange Pi 5 Plus,15GB RAM,无 GPU/NPU 参与)、同一份 Qwen3-VL-2B 权重、串行单引擎实测,方法学与原始数据见仓库基准报告:

指标Kestrel (vllm_kestrel)llama.cpp (Q4_0)结论
冷启动(spawn→HTTP ready) 2.0 s 5.0 s 快 2.5×
峰值内存(VmHWM) 2.47 GB 3.03 GB 低 ~560 MB
decode @8K(TPOT) 136.7 ms 411.6 ms 快 3.0×
跨进程磁盘 KV 恢复 15.4 s(全量 202 s 的 13.1×) 无等价物 架构级差异
同进程前缀恢复 TTFT 202→13.8 s slot 缓存命中(增量随上下文增长) 稀疏恒定 vs 全量线性

两点必须诚实交代:prefill 1K–4K 档 llama 比我们快 1.4–1.6×(它的 ggml NEON 点积打磨更久),8K 才打平;二进制体积我们只报自己,不做跨框架对比(动态/静态构建口径太复杂,硬比是耍流氓)。本表仅同机同任务口径,非全局结论。

四、国密与可信:为什么边缘 LLM 需要“签名”

医疗诊断、法务审查这类场景真正的问题是:权重会不会被替换?输出记录会不会被篡改?这个结果到底是不是这台机器算出来的?我们把 SM3 / SM4-CTR / HMAC-SM3 / SM2 四个国密原语用纯 C 从零实现(零内联汇编、跨架构一致,按 GB/T 32907/32905、GM/T 0003 标准向量 KAT 验证),并在此基础上叠三道防线:

  • 存储态加密(VQF-Enc):权重落盘即 SM4-CTR 密文 + HMAC-SM3 认证,拔卡 dump 也读不出可用权重;解密用 mmap 写时复制单遍完成,磁盘密文不变。
  • 供应链签名(SM2):模型文件带发布方 SM2 签名,设备侧只存公钥、验签通过才加载——防“模型被掉包成投毒版”。
  • 可验证推理(attestation):每次响应把“模型指纹 + 请求原文 + 输出 + 参数 + 时间”算成 SM3 摘要并做 SM2 设备签名,附在响应里;验证方离线用纯 Python 脚本即可复算验签,任何一字节篡改都会让验签失败。
  • # 逐响应凭证的离线验签(验证方无需安装任何引擎依赖)
    python3 tools/verify_attestation.py –sig response.sig –pubkey device_pub.pem

    这三道防线默认全关、零开销;需要合规时按开关逐层打开。它不是 ZK/STARK 式的“计算证明”——我们诚实标注为“司法/工程层面的完整性 + 来源真实性 + 责任追溯”,这恰好是医疗/法务记录合规的核心诉求。

    五、踩过的坑与不敢说的边界

    • 只适配了 Qwen3-VL:tokenizer、mrope、DeepStack 视觉塔都是为该架构特化写的。Llama、旧版 Qwen 没适配——它不是通用推理引擎,别拿别的模型来跑然后说翻车。
    • “支持”不等于“通用”:GGUF 读取能反量化 Q4_0…Q8_K,但架构层仍然只认 Qwen3-VL 的权重形态。
    • 批量位级一致性不是普遍保证:跨 prompt 的连续批处理存在极小概率的数值翻转(margin 0.71 vs 0.032 级别),我们如实写进了文档。
    • 视觉单图场景稀疏注意力无收益、部分优化档在特定模型上是负优化……这些“不漂亮”的结论,全都写进了文档的诚实清单。

    六、20 天,AI Agent 在中间扮演了什么

    最后聊聊标题里的“AI Agent 结对”。这 20 天的开发全程在 Trae(AI IDE) 里进行,它扮演的是高强度的结对工程师 + 文档写手 + 测试搭子:

    • 算子原型、布局重排、NEON 内联的初稿大量由 Trae 的 Agent 生成,我们再逐行 review 并交叉验证;
    • 正确性把关始终在人:位级一致性要靠我们自己写参考实现对拍,国密实现要靠国密标准 KAT 向量逐字节验,这是 AI 给不了的“红线”;
    • 它真正省下的是“搬运型工作”——在 Trae 的会话里把设计意图变成可编译的 C、把实验结论整理成可复现的文档、把板端脚本串成自动化;跨 x86→RK3588 的移植与回归,很多也交给了它生成的脚本。

    我们的体感是:当方向清楚、边界收紧(单架构、单模型族、零依赖)时,AI Agent 能把“从想法到可跑”的周期压缩一个数量级;而它无法替代的,是想清楚“800KB 的代价是什么”的那个人。这个项目的代价我们写在了文档里:只服务一种设备、一类模型、一种可信模型——但你换来的是一个能审计全部代码、能在断电后拔了 SD 卡也能跑的推理引擎。

    Kestrel 已开源(双许可:学习与学术研究免费,商业使用需授权):https://gitee.com/pei-xiaoguang/kestrel-llm。相关数据与方案:性能基准报告、权重保护与可验证推理方案、技术文档均在仓库 docs/。欢迎在仓库 Issues 交流,或邮件 398152090@qq.com。

    赞(0)
    未经允许不得转载:171主机测评 » 20 天、800KB、零依赖:AI Agent 结对写出的纯 C 国密 LLM 推理引擎
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址