今天來介紹 candle 這個開源專案,candle 由 Hugging Face 團隊打造,是近乎全由 Rust 所實現的神經網路模型框架,主要被視為推理引擎。Hugging Face 的團隊和社群應該不用多做說明,是現今爆發的大型語言模型時代下最閃耀的平台,提供工程師、技術者、研究員等能夠下載和分享大型語言模型與資料集的平台。Hugging Face 平台已經非常強大,也無庸置疑的可以被稱之為 Hugging Face 生態系,它們本身早已有成熟強大的 Python library,如:transformers、optimum 等等,都是在大型語言模型領域中不可或缺的基石。如今,Hugging Face 也加入戰局,推出 candle,有別於前幾日介紹的 ort 是由 C++ 所建構的 onnx runtime 進行 FFI binding 來實現神經網路模型的導入和推理,而 candle 是以 Rust 的方式建構神經網路底層的邏輯演算法,最終實現高效能、輕量化、易於部署。
需要清楚說明的也還是這三個核心理念:高效能、輕量化、易於部署。高效能的部分並不是說比 C++ 所建構的生態來得好,而是從 Rust 的軟體開發面作為出發點進行討論,從頭到尾都是同一種語言規則下,在演算法優化的過程中自然就只需要考慮這一種環境,如果開發是 C++ 為底層的方式,這對 Rust 軟體便會綁手綁腳的,受制於 C++ 的套件,你也無法控制其底層邏輯,除非你同時精通 Rust 和 C/C++ 語言,不過開發和維運的成本自然較高。
同樣的,上面提到的輕量化和易於部署亦同,全 Rust 實現,意味著在編譯優化的階段是為同一環境下進行優化,並且編譯成可執行檔案也都全然在一起,這和 C++ FFI binding 的分離比較起來,必然相對輕量化和易於部署。所以,這並不是 Rust 具備上述的絕對性優勢,而是在單純以 Rust 軟體開發維運的角度下所產生的核心理念。
Candle 是一個專為 Rust 語言設計的極簡機器學習框架,專注於高效能(包括 GPU 支援)和易用性。它的核心目標是讓無伺服器推理成為可能,並從生產工作負載中移除 Python。
Candle 採用 Rust workspace 架構,包含以下主要模組:
candle/
├── .cargo/                     # Cargo 配置
│   └── config.toml
├── .github/                    # GitHub Actions 工作流程
│   ├── dependabot.yml
│   └── workflows/
├── candle-core/                # 核心張量操作和裝置管理
│   ├── src/
│   │   ├── lib.rs             # 主要 API 入口點
│   │   ├── tensor.rs          # 張量實作
│   │   ├── device.rs          # 裝置抽象(CPU/CUDA/Metal)
│   │   ├── dtype.rs           # 資料型別定義
│   │   ├── backend.rs         # 後端介面
│   │   ├── cpu/               # CPU 實作
│   │   ├── cpu_backend/       # CPU 後端
│   │   ├── quantized/         # 量化支援
│   │   └── ...
│   └── tests/                 # 單元測試
├── candle-nn/                  # 神經網路建構模組
│   ├── src/
│   │   ├── lib.rs             # 神經網路 API
│   │   ├── linear.rs          # 線性層
│   │   ├── conv.rs            # 卷積層
│   │   ├── activation.rs      # 激活函數
│   │   ├── optim.rs           # 優化器(Adam、SGD 等)
│   │   ├── loss.rs            # 損失函數
│   │   ├── layer_norm.rs      # 層正規化
│   │   ├── batch_norm.rs      # 批次正規化
│   │   └── ...
│   └── tests/                 # 神經網路測試
├── candle-transformers/        # 預建 Transformer 模型
│   ├── src/
│   │   ├── models/            # 各種模型實作
│   │   │   ├── llama.rs       # LLaMA 模型
│   │   │   ├── bert.rs        # BERT 模型
│   │   │   ├── mistral.rs     # Mistral 模型
│   │   │   ├── whisper/       # Whisper 語音模型
│   │   │   ├── stable_diffusion/ # Stable Diffusion
│   │   │   └── ...
│   │   ├── generation/        # 文字生成工具
│   │   └── pipelines/         # 預建管道
│   └── tests/
├── candle-examples/            # 範例和教學
│   ├── examples/
│   │   ├── mnist-training/    # MNIST 訓練範例
│   │   ├── llama/             # LLaMA 推理範例
│   │   ├── whisper/           # 語音識別範例
│   │   ├── yolo-v8/           # 物件偵測範例
│   │   └── ...
│   └── src/
├── candle-datasets/            # 資料集工具
│   └── src/
│       ├── vision/            # 視覺資料集(MNIST、CIFAR 等)
│       └── nlp/               # NLP 資料集
├── candle-kernels/             # CUDA 自訂核心
│   └── src/
│       ├── *.cu               # CUDA 核心檔案
│       └── lib.rs
├── candle-flash-attn/          # Flash Attention 實作
├── candle-metal-kernels/       # Metal 核心(macOS GPU)
├── candle-onnx/                # ONNX 模型支援
├── candle-pyo3/                # Python 綁定
├── candle-wasm-examples/       # WebAssembly 範例
│   ├── bert/                  # 瀏覽器中的 BERT
│   ├── yolo/                  # 瀏覽器中的 YOLO
│   └── ...
├── candle-book/                # 官方文檔
└── tensor-tools/               # 張量工具
Tensor:多維陣列操作Device:CPU/CUDA/Metal 裝置抽象DType:資料型別系統Storage:記憶體管理cargo add --git https://github.com/huggingface/candle.git candle-core
use candle_core::{Device, Tensor};
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let device = Device::Cpu;
    // 創建隨機張量
    let a = Tensor::randn(0f32, 1., (2, 3), &device)?;
    let b = Tensor::randn(0f32, 1., (3, 4), &device)?;
    // 矩陣乘法
    let c = a.matmul(&b)?;
    println!("{c}");
    
    Ok(())
}
| 操作 | PyTorch | Candle | 
|---|---|---|
| 創建張量 | torch.Tensor([[1, 2], [3, 4]]) | 
Tensor::new(&[[1f32, 2.], [3., 4.]], &Device::Cpu)? | 
| 零張量 | torch.zeros((2, 2)) | 
Tensor::zeros((2, 2), DType::F32, &Device::Cpu)? | 
| 索引 | tensor[:, :4] | 
tensor.i((.., ..4))? | 
| 重塑 | tensor.view((2, 2)) | 
tensor.reshape((2, 2))? | 
| 矩陣乘法 | a.matmul(b) | 
a.matmul(&b)? | 
| 算術運算 | a + b | 
&a + &b | 
| 裝置轉換 | tensor.to(device="cuda") | 
tensor.to_device(&Device::new_cuda(0)?)? |