开源项目将 Ollama 的本地 LLM 运行能力移植到智能手机,拓展了边缘设备的应用场景。
一个面向移动设备和可穿戴设备的混合边缘-云 AI 引擎。
┌─────────────────┐
│ Cactus Engine │ ←── OpenAI-compatible APIs for text, speech, and vision.
└─────────────────┘
│
┌─────────────────┐
│ Cactus Graph │ ←── Zero-copy computation graph
└─────────────────┘
│
┌─────────────────┐
│ Cactus Kernels │ ←── CPU/GPU kernels for (Apple, Samsung, Pixel, etc.)
└─────────────────┘
│
┌─────────────────┐
│ Cactus Quants │ ←── Custom rotation-based quantization technique
└─────────────────┘
│
┌─────────────────┐
│Cactus Transpiler│ ←── Transpiles custom PyTorch model to Cactus.
└─────────────────┘
#include "cactus_engine.h"
cactus_model_t model = cactus_init(
"path/to/weight/folder",
"path to txt or dir of txts for auto-rag",
false
);
const char* messages = R"([
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "My name is Henry Ndubuaku"}
])";
const char* options = R"({
"max_tokens": 50,
"stop_sequences": ["<|im_end|>"]
})";
char response[4096];
int result = cactus_complete(
model, // model handle
messages, // JSON chat messages
response, // response buffer
sizeof(response), // buffer size
options, // generation options
nullptr, // tools JSON
nullptr, // streaming callback
nullptr, // user data
nullptr, // pcm audio buffer
0 // pcm buffer size
);
{
"success": true, // generation succeeded
"error": null, // error details if failed
"cloud_handoff": false, // true if cloud model used
"response": "Hi there!",
"function_calls": [], // parsed tool calls
"segments": [], // transcription segments (empty for chat)
"confidence": 0.8193, // model confidence
"confidence_threshold": 0.7, // resolved handoff threshold (model-dependent)
"time_to_first_token_ms": 45.23,
"total_time_ms": 163.67,
"prefill_tps": 1621.89,
"decode_tps": 168.42,
"ram_usage_mb": 245.67,
"prefill_tokens": 28,
"decode_tokens": 50,
"total_tokens": 78
}
#include "cactus_graph.h"
CactusGraph graph;
auto a = graph.input({2, 3}, Precision::FP16);
auto b = graph.input({3, 4}, Precision::INT8);
auto x1 = graph.matmul(a, b, false);
auto x2 = graph.transpose(x1);
auto result = graph.matmul(b, x2, true);
float a_data[6] = {1.1f, 2.3f, 3.4f, 4.2f, 5.7f, 6.8f};
float b_data[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
graph.set_input(a, a_data, Precision::FP16);
graph.set_input(b, b_data, Precision::INT8);
graph.execute();
void* output_data = graph.get_output(result);
graph.hard_reset();
LLM:Gemma-4-E2B-CQ4(1k 上下文预填充 / 100 个令牌的解码)
VLM:Gemma-4-E2B-CQ4(256px 图像编码时间 / 解码)
转录:Parakeet-TDT-0.6B-CQ4(20秒音频端到端转录时间)
1k 上下文 RAM:LLM 基准测试期间的峰值 MB
无推测解码或 MTP,纯解码
命令:cactus benchmark [optional --ios or --android]
注:在 M5 Max 上进行 1k 上下文预填充和 100 次运行解码
LFM2.5-VL-1.6B = 289toks/sec
Qwen3-1.7B = 155toks/sec
LFM2.5-VL-450m = 472toks/sec,图像编码时间 43ms
LFM22.5-VL-230m = 555toks/sec
Gemma-4-E2B-it 在不同比特宽度上的准确率,基于 3 个种子的平均值。
CQ3.26 和 CQ2.54 是混合精度,CQ2/CQ3/CQ4 是均匀量化。
完整结果见 docs/cactus_quants.md:
任何 HuggingFace 模型都可以使用 cactus convert [HF-Name] 转换,但仍处于实验阶段。
Liquid、Gemma、whisper、parakeet 和 Qwen 模型系列已特别测试。
一些模型已预先上传,只需运行 cactus download [HF-Name]。
cactus run [HF-Name] 会先下载或转换未找到的模型。
Needle 是一个 26m 参数模型,用于设备上的工具调用:
cactus run Cactus-Compute/needle [--tools my_tools.json] # OpenAI function-calling format; demo toolset by default
┌────────────────────────────────────────────────────────────────────────────────┐
│ │
│ 第 0 步:如果在 Linux(Ubuntu/Debian)上 │
│ sudo apt-get install python3.12 python3.12-venv python3-pip cmake │
│ build-essential libcurl4-openssl-dev │
│ │
│ 第 1 步:克隆和设置 │
│ git clone https://github.com/cactus-compute/cactus && cd cactus │
│ source ./setup │
│ │
│ 第 2 步:使用命令 │
│────────────────────────────────────────────────────────────────────────────────│
│ │
│ cactus auth 管理云 API 密钥 │
│ --status 显示密钥状态 │
│ --clear 删除已保存的密钥 │
│ │
│ cactus run [model|path] 运行模型(需要时下载) │
│ --bits 1|2|3|4|2.54|3.26 CQ 量化(默认:4) │
│ --backend cpu|metal 推理后端(默认:自动) │
│ --image <path> VLM 推理的图像文件 │
│ --audio <path> 音频聊天的音频文件 │
│ --system <prompt> 系统提示 │
│ --prompt <text> 立即发送提示 │
│ --tools <json|file> 工具调用的工具定义 │
│ --thinking 启用思考/推理模式 │
│ --token <token> HuggingFace 令牌(门控模型) │
│ --reconvert 强制从源代码本地重建 │
│ │
│ cactus transcribe [model] 使用模型进行实时麦克风转录 │
│ --file <audio.wav> 要转录的音频文件 (WAV) │
│ --language <code> 语言代码(默认:en) │
│ --bits 1|2|3|4|2.54|3.26 CQ 量化(默认:4) │
│ --token <token> HuggingFace 令牌(门控模型) │
│ --reconvert 强制从源代码本地重建 │
│ │
│ cactus download [model] 获取包(预构建,否则构建) │
│ --bits 1|2|3|4|2.54|3.26 CQ 量化(默认:4) │
│ --token <token> HuggingFace 令牌(门控模型) │
│ --reconvert 强制从源代码本地重建 │
│ │
│ cactus convert <model> [dir] HuggingFace -> 可运行的 cactus 包 │
│ (CQ 权重 + 运行时图) │
│ --bits 1|2|3|4 CQ 量化(默认:4) │
│ --token <token> HuggingFace 令牌(门控模型) │
│ --reconvert 强制从源代码本地重建 │
│ --lora <path> 转换前合并 LoRA 适配器 │
│ --weights-only 转换后停止(跳过图形) │
│ --artifact-
如果你在研究中使用 Cactus,请按以下方式引用:
@software{cactus,
title = {Cactus: AI Inference Engine for Phones & Wearables},
author = {Ndubuaku, Henry and Cactus Team},
url = {https://github.com/cactus-compute/cactus},
year = {2025}
}
注:向上滚动并点击shields链接获取资源!