π€ Assistant
OK, I've done a thorough deep-dive. Here's the full picture:
π’ Viability: HIGHLY VIABLE β Go for it!
This is actually surprisingly well-supported already. Here's the breakdown:
1. β
GGUF Conversion β Already Done
The repo jsonMartin/voyage-4-nano-gguf has a ready-to-use conversion script (make_voyage4_gguf.py) and pre-built GGUF files on HuggingFace at jsonMartin/voyage-4-nano-gguf:
|
File |
Size |
Quality |
|
voyage-4-nano-f16.gguf |
695 MB |
1.000000 cosine sim (identical) |
|
voyage-4-nano-q8_0.gguf |
372 MB |
0.999903 cosine sim (excellent) |
|
voyage-4-nano-linear.pt |
~4 MB |
Linear projection 1024β2048 |
The conversion uses standard convert_hf_to_gguf.py from llama.cpp. The model is Qwen3-based with bidirectional attention.
2. β
Q4 Quantization β Fully Possible
llama-quantize supports all K-quant formats from Q2_K through Q8_0. You can produce a Q4_K_M quant easily:
bash
./llama-quantize voyage-4-nano-f16.gguf voyage-4-nano-q4_k_m.gguf q4_k_m
Estimated size for Q4_K_M: ~250 MB (the model is 340M params, Q8_0 is 372MB). Perfectly reasonable for CPU inference.
3. β
Rust GGUF Inference β The llama-gguf Crate
The Lexmata/llama-gguf crate (v0.14.0, crates.io) is a full Rust reimplementation of llama.cpp. It:
- β
Supports Qwen3 architecture (what voyage-4-nano is based on)
- β
CPU-only inference with SIMD (AVX2, AVX-512, NEON) β no GPU needed
- β
All quant formats (Q2_K through Q8_0, F16/F32)
- β
Embedding/pooling support β mean pooling, L2 normalization
- β
Use as a library: just add llama-gguf = "0.14" to your Cargo.toml
- β
50K+ lines of battle-tested Rust
4. π§ How It Would Integrate Into Moofile
Here's the architecture thinking:
βββββββββββββββββββββββββββββββββββββββββββββββ
β Moofile Rust Core β
β β
β βββββββββββββββ ββββββββββββββββββββββββ β
β β Document β β Embedding Engine β β
β β Store + β β (llama-gguf) β β
β β Indexes β β β β
β β β β voyage-4-nano-q4 β β
β β text_search β β .gguf (250 MB) β β
β β vector_searchβ β + linear.weight β β
β β hybrid_searchβ β (4 MB, Rust-native) β β
β ββββββββ¬ββββββββ ββββββββββββ¬ββββββββββββ β
β β β β
β βββββββββββ¬ββββββββββββ β
β β β
β Auto-embed docs on insert β
βββββββββββββββββββββββββββββββββββββββββββββββ
The key integration points:
- Add llama-gguf dependency to moofile-core/Cargo.toml
- On Collection open (if embedding model configured), load the GGUF file + linear projection weights
- Auto-embedding on insert: When a document is inserted with text fields for embedding, run the model and store the resulting vector
- The linear projection (1024β2048) is a simple matrix multiply followed by L2 normalization β trivially implementable in Rust with ndarray or raw Vec<f32> operations
- The llama-embedding CLI works like this (for reference on what flags are needed):
bash
./llama-embedding \
-m voyage-4-nano-q8_0.gguf \
--pooling mean \
--attention non-causal \
--embd-normalize 2 \
-p "Your text here"
5. β‘οΈ CPU Performance Estimate
With a 340M param model in Q4:
- Memory: ~250 MB for weights + ~100 MB for runtime buffers β 350 MB total
- Speed: On a modern x86 CPU with AVX2, expect roughly 50-100 tokens/second per document
- At 32K context, embedding a short doc (~100 tokens) would take ~1-2 seconds
6. β οΈ Gotchas to Watch For
- Bidirectional attention β The --attention non-causal flag is critical. The llama-gguf crate needs to support this for correct embeddings. The README lists Qwen3 support so it should work.
- Linear projection layer β The GGUF model only outputs 1024-dim embeddings. To get the full 2048-dim output, you need the linear.weight matrix (shape 2048Γ1024). You'd need to store this as a separate weights file in GGUF or as raw binary and load it in Rust.
- Tokenizer β voyage-4-nano uses Qwen3's tokenizer (151936 vocab size), which llama-gguf should handle natively.
- Prompt format β Query needs "Represent the query for retrieving supporting documents: " prefix, documents need "Represent the document for retrieval: " prefix.
π Bottom Line
Absolutely viable. The stars have aligned unusually well:
- β
Model is Apache 2.0 licensed
- β
Pre-built GGUF files exist
- β
A mature Rust GGUF inference crate (llama-gguf) exists with Qwen3 support
- β
Model is tiny (340M params, Q4 = ~250MB)
- β
Moofile already has a Rust core and vector search infra
- β
CPU-only inference is a first-class target
The integration work would involve:
- Adding llama-gguf as a Rust dependency (~1 day)
- Implementing the model loading & embedding pipeline (~2-3 days)
- Wiring it into Moofile's insert/query lifecycle (~1-2 days)
- Storing the linear projection weights in GGUF metadata or as a separate embedded file (~0.5 day)
Want me to prototype a basic Rust embedding module that loads the voyage-4-nano-gguf and generates embeddings?