Skip to content

feat(brain): ONNX runtime integration with Jina v2 base code embeddings #500

Description

@ajianaz

Summary

Add ONNX Runtime-based contextual code embeddings using jina-embeddings-v2-base-code (154MB quantized ONNX, Apache-2.0). This provides full transformer inference for Brain Mode semantic search, dramatically improving query relevance over static lookup methods.

Background

Corona-code currently has two embedding backends (neither is a full neural network):

  1. Hashing trick 256d — token hash → pseudo-random vector. Zero dependency, very fast, but low quality (~15-20 estimated CoIR NDCG@10).
  2. Nomic distilled 768d — static token→vector lookup table (40,856 tokens × 768d int8 = 31MB embedded in binary). Medium quality (~30-35 estimated CoIR NDCG@10). Not contextual — same token always gets same vector regardless of surrounding code.

Both lack contextual understanding — a token like render gets the same embedding whether it appears in render_template, render_html, or render_pipeline.

Proposed: Tier 3 — ONNX Full Transformer

Model: jinaai/jina-embeddings-v2-base-code — quantized ONNX variant.

Property Value
ONNX size (int8 quantized) 154 MB
Embedding dimension 768
Max sequence length 8,192 tokens
License Apache-2.0 ✅ (commercial-safe)
Code-specific training ✅ (30+ code languages)
Tokenizer BPE (tokenizer.json — HuggingFace standard)
Architecture BERT 12-layer, mean pooling, L2 normalization
CoIR NDCG@10 (estimated) ~57

Why Jina v2 base code?

Evaluated 9 models. Jina v2 base code is the only model that passes all criteria:

Model ONNX? License Size Verdict
jina-v2-base-code ✅ 3 variants ✅ Apache-2.0 154MB (q8) CHOSEN
jina-code-0.5b ⚠️ CC-BY-NC-4.0 942MB License blocked
codet5p-110m BSD-3 439MB No ONNX, seq=512
SFR-Code-400M_R ⚠️ CC-BY-NC-4.0 424MB (q8) License blocked
nomic-embed-code Apache-2.0 27 GB Non-starter
bge-code-v1 MIT 5.9 GB Non-starter

Proposed Changes

1. New Dependencies (Cargo.toml)

[dependencies]
ort = { version = "2.0", features = ["half"] }       # ONNX Runtime (CPU)
tokenizers = { version = "0.21", features = ["onnx"] } # HuggingFace BPE

Note: ort links against ONNX Runtime shared library (~15MB). Consider static linking or bundling.

2. New Module: src/embed/onnx.rs

pub struct OnnxEmbedder {
    session: ort::Session,        // ONNX inference session
    tokenizer: tokenizers::Tokenizer,
    dim: usize,                   // 768
}

impl OnnxEmbedder {
    pub fn load(model_path: &Path) -> Result<Self>;
    pub fn embed(&self, code: &str) -> Result<Vec<f32>>;  // BPE → forward pass → mean pool → L2 norm
}

3. Lazy Model Download

$ cora brain --setup
🧠 Brain Mode Setup

Select embedding backend:
  > auto (recommended)
    pretrained (nomic 768d, embedded)
    onnx (Jina v2 base code, 154MB download)
    hashing (256d, zero dependency)

Downloading jina-embeddings-v2-base-code (quantized)...
  → ~/.local/share/cora/models/jina-code-q8.onnx (154 MB)
  → ~/.local/share/cora/models/jina-tokenizer.json (1.2 MB)
✅ Done! Brain Mode will use ONNX embeddings.

Download URL: https://huggingface.co/jinaai/jina-embeddings-v2-base-code/resolve/main/onnx/model_quantized.onnx

4. Config

# .cora.yaml
brain:
  embedding: onnx
  onnx_model_path: ~/.local/share/cora/models/jina-code-q8.onnx

5. Incremental Embedding (builds on #499)

With 154MB model + 50-100ms inference per symbol, full re-embed is expensive:

Project Full re-embed Incremental (1 file)
Uteke (1106 symbols) ~110 seconds ~5-10 seconds
Corin (537 symbols) ~54 seconds ~3-5 seconds

Per-symbol fingerprint tracking from #499 is mandatory for ONNX backend.

6. Brain Search Query Embedding

Brain search must embed the query string using the same ONNX model:

fn vector_search(conn, project_id, query, limit) {
    let query_vec = match active_backend() {
        Backend::Onnx(model) => model.embed(query),     // ~50-100ms
        Backend::Pretrained => embed_code_pretrained(query), // ~0.01ms
        Backend::Hashing => tokens::embed_code(query),       // ~0.01ms
    };
    // usearch KNN search...
}

Query embedding latency: ~50-100ms per cora brain invocation. Acceptable for interactive CLI.

Performance Targets

Metric Target
Model download < 2 minutes on broadband
Full index (1106 symbols) < 120 seconds
Incremental (1 file, ~10 symbols) < 5 seconds
Brain search query < 300ms (including query embed)
Memory usage < 500MB during inference

Risk Assessment

Risk Mitigation
ort crate binary size (+15-20MB) Feature-gate behind onnx-embed
ONNX Runtime platform differences CI test on Linux/macOS/Windows
Model download failures Retry + resume + checksum verify
Inference too slow on old CPUs Benchmark on minimum hardware, document requirements
Tokenizer mismatch Use official tokenizer.json from HF repo

Dependencies

Files to Create/Change

File Change Est. Lines
src/embed/onnx.rs NEW — ONNX inference module ~200
src/embed/mod.rs Add OnnxBackend to dispatch ~30
src/commands/brain_setup.rs NEW — interactive setup wizard ~150
src/config/schema.rs Add ONNX fields to BrainConfig ~10
Cargo.toml Add ort, tokenizers, onnx-embed feature ~5
src/index/brain.rs Query embedding via active backend ~15

Total: ~410 lines new/changed code.

Testing

  • cargo test --features tree-sitter,onnx-embed
  • Model download + load works on Linux/macOS/Windows
  • Embedding output matches Python reference (cosine sim > 0.99)
  • Brain search with ONNX returns vector signal with high relevance
  • Incremental embed: only changed symbols re-embedded
  • Memory stays under 500MB during full index
  • Config: embedding: onnx without model file → helpful error message

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions