🌰 Acorn Framework
Big models. Tiny footprint. —— 芥子纳须弥,把大模型装进口袋。
以小搏大的 AI 运行与训练框架:INT4 压缩态常驻 + 原生 AVX2 内核 + 自研 CUDA int4 内核 + KV int8 + 层流式 + 投机解码 + LoRA + AutoBit + 能效治理 + 本地 OpenAI 兼容 API,零依赖核心,全部自研。
⚡ 60 秒看到它跑真模型
pip install acorn-llm # 零依赖;有 gcc 会自动编译 AVX2 内核
pip install 'acorn-llm[fast]' # 真实模型(Qwen/LLaMA)需要 NumPy
acorn chat # ← 打开本地 AI 聊天 TUI
============================================================
Acorn 本地聊天室 | Qwen3-8B | eco=whisper | CPU
/exit 退出 · /new 新对话 · /eco 切档 · /spec 投机 · /raw 渲染开关
============================================================
你> 1+1等于几?
AI> thinking...
嗯,用户问的是 1+1 等于几。这是最基础的算术……
think done
1+1 等于 2。这是整数加法的基本运算……
实测数据(本机:16 核 CPU / 16.5GB RAM / 无 GPU / 一块 P620)
| 模型 | 原始体积 | Acorn INT4 | 常驻内存 | decode | 备注 |
|---|---|---|---|---|---|
| Qwen3-8B | 16.38 GB (bf16) | 4.10 GB (7.99×) | 4.10 GB | 4.9 tok/s(turbo 16 线程) | 36 层/32 头/8 KV,纯 CPU 跑通中文思维链;v0.10.0 提速 +41%(修 scales 转换开销 + eco 线程贯通) |
| Qwen2.5-0.5B | 0.99 GB | 0.25 GB (4×) | 0.25 GB | 10–15.7 tok/s | 静音档 2 线程仍同速 |
| 7B 规格(合成) | 18.5 GB (fp32) | 2.91 GB | 154 MB(层流式) | 4.7 tok/s | 省内存 19× |
| int4 GEMV (4096×11008) | 12.3 ms (fp32 BLAS) | 1.95 ms | 0.5 B/参数 | 18.6 GB/s | 自研 AVX2,机器带宽上限的 72% |
| GPU int4 GEMV (4096×11008) | — | 1.68 ms | 0.5 B/参数 | 13.4 GB/s | 自研 CUDA 内核(NVRTC),0.9.10 起全形状快于 CPU 内核 |
🧠 这个框架到底做了什么(不是 PPT,全部实测)
| 能力 | 实现 | 实测/验证 |
|---|---|---|
| INT4 压缩态常驻 | 权重以 int4 留在内存,推理时在线解包参与 GEMM,绝不物化 fp 矩阵 | 7.99× 压缩;数值与参考实现 rel=1.5e-7 |
| 原生 AVX2 内核 | C 手写:nibble 在线解包 + 256-bit FMA 点积 + 常驻线程池,64 值/迭代 + 软件预取 | 比 fp32 BLAS 快 6.3×;turbo 24.0 GB/s(带宽上限 92%) |
| 真实模型接入 | 零依赖 safetensors 读写(单文件/多分片)、LLaMA/Qwen2/Qwen3 架构、BPE 分词器 | Qwen3-8B 实跑,中文思维链正确 |
| AutoBit 混合位宽 | 逐层 KL 敏感度实测 → 字节预算下贪心分配 int4/int8/fp32 | 同预算质量 KL ↓87% |
| 投机解码 | n-gram 草稿 + 批量验证 + cache 回退 | ×1.3–1.7,且与常规贪心输出逐字一致(金标准) |
| KV Cache int8 | 逐 token absmax 量化 | 内存 28%,输出偏差 0.4% |
| 层流式加载 | 按层惰性读取 + LRU 驱逐 | 7B 常驻 154 MB(4GB 内存设备可跑) |
| 结构化剪枝 + 稀疏内核 | FFN 神经元幅度剪枝 + 位图跳零 + 紧凑存储 | 50% 剪枝:字节 50%、加速 ×1.6、loss 仅 ×1.08 |
| LoRA 轻训练 | 冻结基座 + 低秩适配器 + 合并回稠密 | 25.3% 参数学新语料 |
| 能效治理 (eco) | whisper/balanced/turbo + race-to-idle + 进程优先级;v0.10.0 起真实模型路径也真正生效(此前线程设置被忽略,一直满核) | Qwen3-8B:2 线程 1.6 tok/s / 4 线程 2.6 / 16 线程 4.9(同功耗包络下按需取舍) |
| CUDA Graph 后端 | 自研 GPU 解码图(捕获+回放) | 数值正确;P620 上仍不及 CPU int4 内核(诚实数据) |
| 自研 CUDA int4 内核 | NVRTC 运行时编译 + CUDA 驱动 API,8 路在途加载,无需 CUDA Toolkit | 数值 rel≤1.3e-7;P620 上 8.8–15.3 GB/s,全形状快于 CPU 内核(0.9.10) |
| int4 权重常驻显存 | LLaMA/Qwen 全模型 int4 权重直接住显存,0.5 B/参数 | 0.5B 模型 249 MB 显存;与 CPU 模型 prefill+decode rel≤1.4e-5 |
| 本地 API(Ollama 风格) | OpenAI 兼容端点 + SSE 流式 | /v1/chat/completions /v1/models /health /api/show 实测通过 |
📦 安装
pip install acorn-llm # 零依赖核心(训练栈 / TinyGPT)
pip install acorn-llm[fast] # + NumPy(真实模型 LLaMA/Qwen 必需,约 50× 提速)
pip install acorn-llm[gpu] # + PyTorch(GPU int4 内核 / CUDA Graph 后端)
要求 Python ≥ 3.9。有 gcc/cl 时首次运行自动编译原生内核(缓存到 ~/.cache/acorn);没有编译器也不影响使用(自动回退 NumPy 路径,功能一致、速度较低)。
依赖边界要说清楚:
- 零依赖核心 = autograd / 训练引擎 / TinyGPT / 打包 / 量化 / 内核编译 ——
pip install acorn-llm即可跑通- 真实模型路径(LLaMA / Qwen 推理、转换、API 服务)需要 NumPy —— 装
[fast]或[gpu](GPU extra 会带上 NumPy 依赖链)- 缺 NumPy 时会直接给出明确提示(
pip install 'acorn-llm[fast]'),而不是在深处报类型错误
💬 TUI 聊天(装完就能用)
acorn chat # 自动搜索本地模型
acorn chat --model-dir ./models/Qwen3-8B # 指定模型目录
acorn chat --model-dir ./qwen --auto-convert # 目录里是 safetensors 就地转换
acorn chat --system "你是一个简洁的技术助手" # 设定人设
acorn chat --gpu # 用 CUDA 后端(若有)
acorn chat --eco turbo # 全速(风扇起飞)
模型从哪来?(三种方式)
① 直接下载已转换的模型? —— 没有官方分发,但转换只需一次(10 分钟内完成)。
② 从 ModelScope / HuggingFace 下载原始权重 → 自动转换(推荐)
# ModelScope(国内直连,无需梯子)
mkdir -p models/Qwen2.5-0.5B
curl -L -o models/Qwen2.5-0.5B/model.safetensors \
"https://modelscope.cn/api/v1/models/Qwen/Qwen2.5-0.5B-Instruct/repo?FilePath=model.safetensors"
curl -L -o models/Qwen2.5-0.5B/tokenizer.json \
"https://modelscope.cn/api/v1/models/Qwen/Qwen2.5-0.5B-Instruct/repo?FilePath=tokenizer.json"
curl -L -o models/Qwen2.5-0.5B/config.json \
"https://modelscope.cn/api/v1/models/Qwen/Qwen2.5-0.5B-Instruct/repo?FilePath=config.json"
# 然后二选一:
acorn chat --model-dir models/Qwen2.5-0.5B --auto-convert # 自动转 + 直接聊
手动转换(可复用、参数自动读 config.json,rope_theta 等超参不会手填错):
python -m acorn convert --src models/Qwen2.5-0.5B/model.safetensors \
--out models/Qwen2.5-0.5B/qwen.acorn
自动从
config.json读取:层数 / 维度 / 头数 / KV 头 / FFN / 词表 / rope_theta(Qwen2/3 是 1e6!)/ tie_word_embeddings / qk_norm(Qwen3)。 转换是流式的:RAM 峰值 ≈ 单个张量,16GB 内存机器可转 16GB 模型(多分片自动走流式路径)。
HuggingFace 同理,把 URL 换成 https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct/resolve/main/...。
③ 已有的第三方 .acorn / GGUF? —— GGUF 暂不支持,请先用 acorn convert(支持 safetensors 系)。
模型目录长什么样
models/Qwen2.5-0.5B/
├── model.safetensors # 原始权重(可选,--auto-convert 用)
├── config.json # HF 配置(--auto-convert / convert 自动读它)
├── tokenizer.json # 必需
└── qwen.acorn # 转换产物(必需,或由 --auto-convert 生成)
该下载哪个模型?(已验证可跑)
| 模型 | 规格 | 下载量 | Acorn INT4 后 | 速度(实测) | 备注 |
|---|---|---|---|---|---|
| Qwen2.5-0.5B-Instruct | 0.49B · 24L · d896 · 14Q/2KV | 0.99 GB | 0.25 GB | 14–16 tok/s | 首选,秒级响应 |
| Qwen2.5-1.5B-Instruct | 1.54B · 28L · d1536 | 3.1 GB | ~0.8 GB | ~7 tok/s | 中文更好 |
| Qwen3-8B | 8.2B · 36L · d4096 · 32Q/8KV · QK-Norm | 16.4 GB | 4.10 GB | 2.4–3.1 tok/s | 思维链最强,本机 16GB 可跑 |
| Qwen3-1.7B | 1.7B · 28L · d2048 | 3.4 GB | ~0.9 GB | ~6 tok/s | 质量/体积最佳平衡 |
Qwen3 用 QK-Norm 架构,Acorn 已支持(数值 vs 独立参考实现 rel=3.8e-7); Qwen2/3 的
rope_theta=1e6会在转换时自动从 config.json 读取(手填 10000 会得到乱码)。
TUI 里的命令
| 命令 | 作用 |
|---|---|
/new |
开新对话(清空上下文与 KV) |
/eco whisper|balanced|turbo |
能效档位:静音 / 甜点 / 全速 |
/spec |
投机解码开关(重复文本/代码可提速) |
/think |
思考内容显隐开关(隐藏时只留 think done · N 字 行) |
/len [N] |
查看/调整单轮回答上限(默认 4096;触顶会有 ⏹ 已达上限 提示) |
/raw |
关闭 Markdown 渲染(看原始输出) |
/info |
当前档位、线程数、轮次、上下文长度 |
| Ctrl+C | 中断本轮生成——上下文自动回滚,会话可继续(不重算历史) |
/exit |
退出 |
界面说明
- 思考流:模型的 thinking 内容以深灰逐字显示,头部
thinking...,结束切think done · N 字 - 正文:完整流式 Markdown——标题/列表/引用/代码块结构着色,行内
**粗体**/*斜体*/`代码`/[链接](url)同样渲染(标记延迟闭合缓冲:纯文本逐字即出,标记闭合即整段着色,未闭合原样保留不吞内容) - 跨轮复用 KV:每轮只前向增量,历史不重算
- 回答上限:默认 4096 token(
--max-tokens//len N可调);自动钳制到上下文剩余额度,不会写越界 - 颜色:自动探测终端能力——不支持 ANSI 的终端(老 conhost / 输出重定向)一个转义都不发,只输出干净文本(markdown 标记会被剥离,不会看到
**残留);强制开色用ACORN_FORCE_COLOR=1,强制关色用NO_COLOR=1
think done 的判定规则(不是靠猜)
思维链的结束必须可靠,否则正文会被误吞或被提前吐出。Acorn 用三级判定,从精确到兜底:
| 优先级 | 规则 | 为什么 |
|---|---|---|
| ① 显式标签(主路径) | 解码器把 </think> special token 透传为文本,状态机在标签处精确切换;词表含 </think> 时空行启发式整体关闭 |
Qwen3 的 </think> 是 special token 不在普通 vocab——曾因被流式解码器丢弃而只能靠空行猜边界(v0.9.8 位置 bug 根因);且启发式若先切,随后到达的真标签会泄漏成正文文字(v0.9.9 实测) |
| ② 空行启发式(兜底) | 仅当词表没有 </think> 标签时启用;单/双空行均要求思考已 > 600 字符 |
思考内部出现空行(哪怕 \n\n\n 整块 token)很常见——实测 Qwen3-int4 在 ~240 字符处吐过 \n\n\n |
| ③ 生成结束 | finish() 兜底切换 |
保证 think done 一定出现 |
设计取向:早切(思考尾部当正文,不可挽回)比晚切(正文短暂灰色,随流纠正)危害更大。 标签容错:thinking 态重复
<think>静默吞掉;answer 态游离</think>吞掉不泄漏;answer 态新<think>重新进入思考。
🌐 本地 API(Ollama 风格,OpenAI 兼容)
一条命令把你的模型变成局域网服务,任何 OpenAI 客户端(LangChain / LlamaIndex / Cursor / Continue / 自写脚本)都能直接接:
acorn serve --model-dir ./models/Qwen2.5-0.5B --port 11434
# 或从 safetensors 自动转换后直接起服务
acorn serve --model-dir ./models/Qwen3-8B --auto-convert
| 端点 | 方法 | 说明 |
|---|---|---|
/v1/chat/completions |
POST | 对话;"stream": true 返回 SSE 增量(data: 帧,末帧 data: [DONE]) |
/v1/completions |
POST | 文本补全 |
/v1/models |
GET | 模型列表(OpenAI 格式) |
/health |
GET | 健康检查 |
/api/show |
POST | Acorn 扩展:常驻内存 / 位宽 / 内核状态 / 档位 |
用 curl 直接聊(零依赖验证):
curl http://127.0.0.1:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"qwen","messages":[{"role":"user","content":"1+1等于几?"}],"stream":true}'
服务端默认
--eco whisper(静音档,风扇不转);要吞吐就--eco turbo。 纯标准库http.server实现,零额外依赖。
🔥 自研 CUDA int4 内核(不装 CUDA Toolkit 也能跑)
acorn/gpu_int4.py 是自己写的 CUDA int4 GEMV/GEMM/gather 内核,不是调 torch eager:
- 编译方式:用 PyTorch wheel 自带的
nvrtc64_*.dll运行时编译 PTX,无需安装 CUDA Toolkit(不用 nvcc) - 驱动接入:直接调
nvcuda.dll驱动 API(cuModuleLoadData/cuLaunchKernel),不依赖 numba - 内核内容:nibble 在线解包 →
__dp4a/FMA 点积 → 共享内存分块 → 多行 GEMM(prefill 友好) - 数值正确:GEMV/GEMM 相对误差 ≤ 1.3e-7;int4 GPU 模型 vs CPU 模型 prefill+decode rel ≤ 1.4e-5
from acorn import gpu_int4 as GI
print(GI.info())
# {'available': True, 'device': 'Quadro P620', 'cc': (6, 1),
# 'toolchain': 'NVRTC (torch 自带) + CUDA 驱动 API, 无需 nvcc'}
诚实的速度对比(本机 Quadro P620 / CC 6.1 / 4GB VRAM)
0.9.10 内核升级:GEMV/GEMM 改用 8 路在途加载(该内核是访存延迟受限,提高内存级并行才有效)。 变体实测(4096×11008):逐字节 4 路 ILP 12.0 GB/s → 8 路 ILP 13.9 GB/s;而 uint4 向量化 5.0、x 驻留 shared memory 7.2——在 Pascal 上反而劣化(教训如实记录)。
| R × C | GPU int4(自研 CUDA) | CPU int4(自研 AVX2) | torch fp32 | GPU/CPU |
|---|---|---|---|---|
| 1024×1024 | 0.06 ms · 8.8 GB/s | 0.13 ms · 3.9 GB/s | 0.06 ms · 72 GB/s | ×2.22 |
| 2048×2048 | 0.16 ms · 13.4 GB/s | 0.34 ms · 6.2 GB/s | 0.22 ms · 77 GB/s | ×2.16 |
| 4096×4096 | 0.55 ms · 15.3 GB/s | 0.86 ms · 9.8 GB/s | 0.88 ms · 76 GB/s | ×1.57 |
| 4096×11008 | 1.68 ms · 13.4 GB/s | 2.10 ms · 10.7 GB/s | 2.50 ms · 72 GB/s | ×1.25 |
| 4096×14336 | 2.55 ms · 11.5 GB/s | 2.69 ms · 10.9 GB/s | 3.29 ms · 71 GB/s | ×1.06 |
| 8192×8192 | 2.35 ms · 14.3 GB/s | 2.54 ms · 13.2 GB/s | 5.19 ms · 52 GB/s | ×1.08 |
测量方法:每格 3 轮 × 20 次迭代取最小值(
examples/bench_gpu_kernel.py可复现)。 0.9.10 起 GPU 内核在全部形状反超 CPU 内核(×1.06–×2.22;0.9.9 及之前为 0.7×)。 本机同时有其他程序(含另一个 LLM 运行时)占用 CPU/GPU,实测方差可达 ±40%。
结论必须说清楚:
- 在这张 P620(2016 年 Pascal,1.9 TFLOPS FP32、186 GB/s 显存带宽) 上,自研 GPU int4 内核达 8.8–15.3 GB/s,已全面快于 CPU AVX2 int4 内核,但仍远低于显存带宽理论值——Pascal 无 int4 tensor core,这是架构上限
- torch fp32 因为能用 tensor core(TF32 通路)跑到 52–77 GB/s,仍快于我们的 int4 内核
- GPU int4 内核的核心价值是把 int4 权重常驻显存:0.5B 模型仅占 249 MB 显存(0.5 B/参数),CPU 侧则可把系统内存留给别的任务
- 在现代 GPU(Ampere/Hopper,带 int4 tensor core)上预期会大幅提升 —— 但这一点我们还没有硬件验证,不作为已证实的结论
CPU AVX2 内核(0.9.10 小幅提效 + 一个缓存 bug 修复)
- 点积主循环 32 → 64 值/迭代(8 路累加器)+ 软件预取。严格 A/B(新旧 DLL 同进程交替测量,消除时间漂移):
- whisper 2 线程:+1.5 ~ +3.3%;balanced 4 线程:+2.0 ~ +3.8%;turbo 16 线程:±0(已逼近带宽上限)
- 提升发生在能效档位——同线程数、同功耗包络下的纯每字节效率提升("温度不提高的提速")
- 修复内核缓存 bug:编译缓存原本只按
平台_CPU数命名、不含源码哈希——升级 acorn 后仍加载旧内核 DLL(静默性能回退)。现在缓存名含源码 SHA1,源码升级自动重编
另一组诚实数字(turbo 16 线程,交替 A/B):4096×14336 达 24.0 GB/s(机器带宽上限 26 GB/s 的 92%); 而 whisper 2 线程即达 10 GB/s——每线程效率是 16 线程的 3.6 倍,这是 eco 能效治理的数据支撑。
int4 权重常驻显存(gpu_model.py)
from acorn.runtime import load
m = load("models/Qwen2.5-0.5B/qwen.acorn", device="cuda") # 自动走 GPU int4 路径
- 所有 int4 权重直接住显存(不物化 fp32),0.5B 模型 249 MB
- 完整 LLaMA/Qwen 前向:RMSNorm / RoPE / GQA / SwiGLU / QK-Norm / KV Cache 全部在 GPU
- 与 CPU int4 路径逐 token 数值一致(top-1 相同,logits rel ≤ 1.4e-5)
- ⚠️ P620 只有 4GB 显存:8B 模型 int4 需 4.10 GB,放不下
🖼️ 多模态(视觉塔 + 投影器)
Acorn 支持 LLaVA / Gemma 3 一类"视觉塔 + projector"架构的图像输入:PNG 零依赖解码 → 视觉塔 → projector → 图像 embedding 注入 LLM 的输入序列。
# 1) 转换(LLM 走常规 .acorn;视觉塔走 .mm 旁挂,不重写主文件)
acorn convert --src model.safetensors --out model.acorn \
--vision-src ./model_dir --vision-preset llava
# 2) 聊天时带图
acorn chat --model-dir ./model_dir --image cat.png
# 会话内也可: /image cat.png
# 3) API(OpenAI 多模态格式)
curl http://127.0.0.1:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"m","messages":[{"role":"user","content":[
{"type":"text","text":"这是什么?"},
{"type":"image_url","image_url":{"url":"data:image/png;base64,..."}}]}]}'
| 组件 | 实现 | 说明 |
|---|---|---|
| PNG 解码 | acorn/vision.py 零依赖(zlib + 反滤波) |
8bit 灰度/RGB/调色板/RGBA,非隔行;JPEG 需 Pillow(可选) |
| 预处理 | 双线性缩放 + 归一化 | → (3, S, S) float32 |
| 视觉塔 | patch embed + pre-LN transformer 块 + 末端 LN | ViT/SigLIP 通用形态,QKV 融合,权重 int4 可用 |
| 投影器 | linear / 2 层 MLP | 输出维度与 LLM hidden_size 强校验(不一致直接报错) |
| 注入 | 图像占位 token 展开成 N 个位置 + embedding 覆盖 | 占位展开与注入严格对齐 |
诚实限制:
- 只实现通用 ViT/SigLIP 形态的视觉塔;Gemma 3 的 pan-and-scan 多裁剪与 SigLIP resampler 未实现(Gemma 3 需额外适配)
- Gemma 3 的 LLM 侧也不兼容:GeGLU(tanh) 而非 SwiGLU、RMSNorm 用
(1+w)、logit softcapping、滑窗/全局混合注意力 —— 直接加载会静默出错,需先补这几项 - 转换器只搬运张量,不做数值等价验证(需真 checkpoint 对照)
- 视觉塔默认 fp32(0.4B → 1.6 GB),可
--vision-quant走 int4
🧪 30 秒训一个自己的模型
import acorn
model = acorn.train(corpus=open("my_novel.txt", encoding="utf-8").read(),
steps=300, batch_size=12, ctx=64)
acorn.pack(model, "mymodel.acorn") # INT4 打包
m = acorn.load("mymodel.acorn")
print(m.generate("第一章", 200, temperature=0.8))
训练栈全是自研:矩阵级 autograd(13 个可微节点)· AdamW · warmup + 余弦调度 · 全局范数梯度裁剪 · 数值对拍测试(44+9 位置有限差分)。
LoRA 轻量微调
import acorn
from acorn import lora
model = acorn.train(steps=100)
lora.inject_lora(model, rank=8) # 冻结基座 + 注入低秩适配器
acorn.train(model=model, corpus="新领域文本…", steps=60)
lora.merge_lora(model) # 合并回稠密权重
acorn.pack(model, "tuned.acorn")
真实模型微调(诚实说明)
- 0.5B 级:本机可行(
acorn.to_trainable(acorn.load(...))→ LoRA 流程同上) - 8B 级:fp32 反量化需 32GB 内存,本机不可行;且 LLaMA 路径目前是数值推理路径,尚未接入 autograd 图——这是路线图 M2 项
🖥️ CLI 全表
acorn chat # ★ 交互式 TUI 聊天
acorn serve --model-dir ./models/Qwen2.5-0.5B # ★ 本地 OpenAI 兼容 API
acorn train --steps 200 --out m.acorn # 训练 + INT4 打包
acorn run --model m.acorn --stream # TinyGPT 推理
acorn convert --src X.safetensors --out X.acorn # 真实模型转换(自动读 config.json)
acorn run-llama --model X.acorn --tokenizer tok.json --prompt "你好" --stream
acorn bench --model m.acorn # 基准(吞吐/带宽/规模外推/内核状态)
acorn lora --model m.acorn --corpus my.txt --steps 150 # LoRA 微调
🧰 Python API 速查
| API | 用途 |
|---|---|
acorn.train(steps=, corpus=, lr=, batch_size=, ctx=) |
训练 |
acorn.pack(model, path) |
INT4 量化打包(投影融合 + 嵌入表 gather 布局) |
acorn.load(path, tokenizer_path=, kv_cache_kind="int8", ctx=, eco=, device=) |
加载(自动按架构分派) |
m.generate_chat(prompt, …, repetition=, speculative=) |
对话式生成(自动模板 + 重复惩罚 + 停止序列) |
m.generate_stream(...) / m.generate(...) |
生成(token 级流式) |
ChatSession(m).send(text) |
多轮对话(跨轮 KV 复用) |
m.set_eco("whisper") |
能效档位切换 |
acorn.load_streaming(path, max_resident_layers=2) |
层流式加载(内存省 19×) |
acorn.bench(m) |
性能基准 |
acorn.autobit / acorn.prune |
混合位宽量化 / 结构化剪枝 |
acorn.llama.convert_safetensors(...) / acorn.shard.convert_sharded(...) |
真实模型转换器 |
acorn._kernels.info() |
内核状态(AVX2/线程/编译器) |
acorn.gpu_int4.info() |
GPU int4 内核状态(设备/CC/工具链) |
acorn.server.main(["--model-dir", ...]) |
起本地 OpenAI 兼容 API 服务 |
🎛️ 调优菜单(按需叠加,互不冲突)
| 手段 | 效果 | 怎么用 |
|---|---|---|
| INT4 量化 | 权重 ÷8 | 默认开启 |
| KV int8 | 长上下文 KV ÷4 | load(..., kv_cache_kind="int8") |
| 能效静音 | 同速、省电、风扇不转 | load(..., eco="whisper") 或 m.set_eco() |
| 层流式 | 常驻 ÷19(吞吐换空间) | acorn.load_streaming(path) |
| AutoBit | 同体积质量 ↑87% | convert(..., autobit={...}, model=...) |
| 剪枝 + 稀疏 | 字节 ÷2、加速 ×1.6 | acorn.prune.prune_ffn(...) |
| 投机解码 | 有效 tok/s ×1.3–1.7 | generate_chat(..., speculative=True) |
| CUDA Graph | GPU 解码零发射开销 | load(..., device="cuda") |
🏗️ 架构
L5 用户 API acorn chat / serve / train / pack / load / generate_chat / bench
L4 编排层 AutoBit · LoRA · 剪枝 · 转换器 · 能效治理
L3 运行时 AcornPack 容器 · 层流式调度 · 分页/int8 KV Cache · 投机解码
L2 计算层 微型 autograd(13 节点) · RoPE · SwiGLU · GQA
L1 内核后端 AVX2 int4 GEMM(在线解包+FMA) · 常驻线程池 · CUDA Graph
CUDA int4 GEMV/GEMM (NVRTC 运行时编译) · int4 权重常驻显存
L0 算子层 NumPy 加速 + 纯 Python 回退(零依赖)
📁 项目结构
acorn-framework/
├── PLAN.md # 总体项目计划(里程碑/风险/验收标准)
├── RUNTIME_PLAN.md # 运行模型详细计划(格式/内存/量化/API)
├── USAGE.md # 使用手册
├── assets/ # Logo(主/深色/favicon/横版字标)
├── acorn/
│ ├── _kernels/ # 原生内核:acorn_int4.c + 自动编译/ctypes 绑定
│ ├── _ops.py # 张量算子(NumPy 加速 + 纯 Python 回退)
│ ├── _autograd.py # 微型自动微分(requires_grad 冻结机制)
│ ├── model.py # TinyGPT(RoPE/因果注意力/MLP)
│ ├── llama.py # LLaMA/Qwen 架构 + 转换器
│ ├── shard.py # 多分片流式转换(RAM 峰值 < 1GB)
│ ├── safetensors.py # 零依赖 safetensors 读写
│ ├── tokenizer.py # BPE 分词器(字节级 + 增量解码)
│ ├── pack.py # INT4 量化 + .acorn 容器(mmap 加载)
│ ├── stream.py # 层流式加载
│ ├── kvcache.py # fp32 / int8 KV 缓存
│ ├── runtime.py # 运行时主循环
│ ├── session.py # 多轮对话(跨轮 KV 复用)
│ ├── chat.py # 模板/惩罚/停止序列
│ ├── chat_cli.py # TUI 入口(acorn chat)
│ ├── tui.py # 终端 UI(思考流 + 流式 Markdown)
│ ├── speculative.py # 投机解码(Prompt-Lookup)
│ ├── autobit.py # 动态混合位宽
│ ├── prune.py # 结构化剪枝
│ ├── lora.py # LoRA
│ ├── train.py # 训练引擎(AdamW/裁剪/调度)
│ ├── bench.py # 性能基准
│ ├── eco.py # 能效治理
│ ├── gpu.py # CUDA Graph 后端
│ ├── gpu_int4.py # 自研 CUDA int4 内核(NVRTC 运行时编译)
│ ├── gpu_model.py # int4 权重常驻显存的 LLaMA/Qwen GPU 模型
│ ├── vision.py # 多模态:PNG 解码 / 视觉塔 / 投影器 / 图像注入
│ ├── multimodal.py # 多模态 checkpoint 转换器(llava/gemma3/clip 预设)
│ ├── server.py # 本地 OpenAI 兼容 API(零依赖 http.server)
│ └── __main__.py # CLI
├── examples/ # 演示脚本(hello_acorn / run_qwen3 / bench_* /
│ # bench_gpu_kernel / bench_gpu_model / api_test)
└── tests/ # 105 项自测
🧪 测试与质量保证
python tests/test_seed.py # 基础(autograd 数值对拍 / 量化 round-trip)
python tests/test_v02.py # 框架(RoPE/KV Cache/LoRA/CLI)
python tests/test_v03.py # 内核(AVX2 数值 / 压缩态 / 性能)
python tests/test_v04.py # 真实模型(LLaMA 数值 / Qwen bias / BPE)
python tests/test_v04b.py # 端到端流水线
python tests/test_v06.py # AutoBit
python tests/test_v07.py # 层流式
python tests/test_v08.py # KV int8
python tests/test_v09.py # 真实模型回归(Qwen2.5)
python tests/test_v10.py # 剪枝 / 稀疏内核
python tests/test_v11.py # Chat 层 / 投机解码金标准
python tests/test_v12.py # Qwen3 QK-Norm / 分片转换
python tests/test_v13.py # 能效治理
python tests/test_v14.py # GPU int4 内核(数值/速度/模型一致性,无 CUDA 自动跳过)
python tests/test_v15.py # API 服务健壮性(500 JSON / 依赖边界)
python tests/test_v16.py # think done 位置(</think> 透传 / 空行兜底门槛)
python tests/test_v17.py # 流式 Markdown 完整渲染 / 回答上限提示
python tests/test_v18.py # 颜色能力探测 / 4096 上限 / 上下文钳制
python tests/test_v19.py # 多模态(PNG 解码/视觉塔/投影器/图像注入)
质量红线(均有测试守护):
- LLaMA/Qwen 前向 vs 独立参考实现:rel ≤ 3.8e-7
- 投机解码 vs 常规贪心:逐字一致
- 稀疏内核 vs 稠密:diff = 0
- AutoBit 同预算:质量 ↓87% 误差
🗺️ 路线图
| 阶段 | 内容 | 状态 |
|---|---|---|
| M0 | 种子内核:autograd / INT4 / 内核 / 训练 / 容器 | ✅ |
| M1.0 | 原生 AVX2 内核 + 常驻线程池 + 压缩态常驻 | ✅ |
| M1.1 | 真实模型接入(safetensors / LLaMA / BPE / 转换器) | ✅ |
| M1.2 | Qwen3-8B 上机 + QK-Norm + 多分片流式转换 | ✅ |
| M2.0 | 投机解码 + Chat 层 + 能效治理 + 剪枝稀疏 + KV int8 | ✅ |
| M2.1 | GPU int4 内核(NVRTC 运行时编译,无需 CUDA Toolkit)+ int4 权重常驻显存 | ✅ |
| M2.2 | LLaMA 路径接入 autograd → 真实模型 LoRA 训练 | 🔜 |
| M2.3 | 连续批处理 / 多用户服务 / Hub 分发 | 🔜 |
| M2.4 | 本地 OpenAI 兼容 API(acorn serve) |
✅ |
| M2.5 | 多模态:PNG 解码 / 视觉塔 / 投影器 / 图像注入(.mm 旁挂) | ✅ |
⚠️ 已知限制(诚实清单)
- int3 量化已实现但很慢(3-bit 无法 SIMD 化,实测比 int4 慢 4 个数量级),默认不用
- 多模态只覆盖通用 ViT/SigLIP 形态:Gemma 3 的 pan-and-scan 多裁剪、SigLIP resampler 未实现;Gemma 3 的 LLM 侧也不兼容(GeGLU / RMSNorm(1+w) / logit softcapping / 滑窗混合注意力),直接加载会静默出错,需先补这几项
- 多模态转换器不做数值等价验证(只搬运张量),需真 checkpoint 对照
- CUDA Graph 后端在 P620 上仍不及 CPU int4 内核(Pascal 算力弱 + eager 开销)
- 自研 GPU int4 内核在 P620 上 8.8–15.3 GB/s,0.9.10 起全形状快于 CPU AVX2;但仍远低于 186 GB/s 显存理论带宽(Pascal 无 int4 tensor core);torch fp32 借 tensor core 仍最快(52–77 GB/s)。GPU 路径的核心价值是 int4 权重常驻显存(0.5B 仅 249 MB)
- 8B 模型放不进 4GB 显存的 P620(int4 需 4.10 GB);且 LLaMA 路径尚未接入 autograd,8B 训练在本机不可行(fp32 反量化 32GB)
- 不支持 GGUF / AWQ / GPTQ 权重,只支持 safetensors 系
- 单机单卡,无分布式训练
- TensorFlow 2 对比:在算子库/编译器/分布式/生态上 Acorn 落后几个数量级;Acorn 的主张限定在「小内存 CPU 推理 + 训推一体 + 零依赖 + 能效治理」这条窄道
🤝 参与
git clone <your-fork> && cd acorn-framework
pip install -e .[fast,dev]
python tests/test_seed.py && python tests/test_v04.py
欢迎提交 PR:新模型架构适配、新内核、基准数据、文档。
📄 License
MIT
🌍 English summary (for PyPI visitors)
Acorn is a from-scratch AI runtime & training framework built on one idea: big models should not require big machines.
- INT4 compressed-resident inference — weights stay int4 in memory and are unpacked on the fly inside a hand-written AVX2 SIMD kernel (never materialized as fp32). 7.99× smaller; numerically identical to an independent reference implementation (rel ≤ 3.8e-7).
- Real models, zero dependencies — ships its own safetensors reader (single-file & sharded, streaming), BPE tokenizer, LLaMA/Qwen2/Qwen3 architectures (RoPE-rotate_half, GQA, SwiGLU, QK-Norm), and converters. Runs Qwen3-8B on a 16 GB, GPU-less laptop.
- Memory & speed arsenal — KV cache int8 (28% memory), layer streaming (19× less resident memory), speculative decoding (1.3–1.7×, bit-identical to greedy), AutoBit mixed-precision (87% better quality at equal bytes), structured pruning + sparse kernels, and a performance-per-watt governor that keeps the fan quiet while matching full-core speed.
- Training too — own autodiff (13 differentiable ops, numerically checked by finite differences), AdamW, warmup+cosine, gradient clipping, LoRA.
- Self-written CUDA int4 kernel — compiles PTX at runtime with the NVRTC shipped inside the PyTorch wheel (no CUDA Toolkit needed) and drives the GPU through the raw driver API. Numerically exact (rel ≤ 1.3e-7); int4 weights stay resident in VRAM (0.5 B/param, 249 MB for a 0.5B model).
- Local OpenAI-compatible API —
acorn serveexposes/v1/chat/completions(with SSE streaming),/v1/completions,/v1/models,/health, using nothing but the standard library.
pip install acorn-llm
acorn chat # interactive TUI with a local model
acorn serve # local OpenAI-compatible HTTP API
Big models. Tiny footprint.
一颗橡子,长成参天大树。 🌰
Metadata
Release files for acorn-llm 0.10.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| acorn_llm-0.10.0.tar.gz | 187.8 kB | Without provenance | Details for acorn_llm-0.10.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| acorn_llm-0.10.0-py3-none-any.whl | Python 3 | none | any | Details for acorn_llm-0.10.0-py3-none-any.whl |
Total release size: 331.3 kB
Release files / acorn_llm-0.10.0.tar.gz
| Download URL | acorn_llm-0.10.0.tar.gz |
|---|---|
| Size | 187.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2e5a9056d6434ba6f86eb3d428a2afbdc6f97546a9b100a0f61a2f1313d9afab
|
|
BLAKE2b-256 checksum How to use checksums |
131b6ca9d925a817e3fdeac723921ac6d793e23cff305a8cbaeeb3942a88b5c6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.6
|
Release files / acorn_llm-0.10.0-py3-none-any.whl
| Download URL | acorn_llm-0.10.0-py3-none-any.whl |
|---|---|
| Size | 143.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f8a2463daed923e7d9500fee6347d7c9f154402b86c94df7774a0f0eadbd6977
|
|
BLAKE2b-256 checksum How to use checksums |
82bdab0913fe3d5062987ea4f4165324d43fbe07fff87d600112d84b181c8ef9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.6
|
Security for acorn-llm 0.10.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.