Skip to content

Commit 6d48fbb

Browse files
committed
Add ONNX Runtime support for embeddings on macOS
- Introduced ONNX Runtime as an optional embedding provider with CPU and CoreML execution providers. - Updated README.md with instructions for using ONNX embeddings and enabling CoreML support. - Modified configuration to include ONNX settings and compatibility. - Implemented ONNX embedding provider with support for model loading from Hugging Face Hub. - Enhanced local embedding provider to handle device fallbacks for CUDA and Metal. - Added tolerant cleaning mechanism in the parser to improve parsing robustness. - Updated dependencies in Cargo.toml to include ONNX Runtime and related features.
1 parent 1a957aa commit 6d48fbb

File tree

13 files changed

+1084
-517
lines changed

13 files changed

+1084
-517
lines changed

Cargo.lock

Lines changed: 597 additions & 452 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ futures = "0.3"
4141
# Serialization
4242
serde = { version = "1.0", features = ["derive"] }
4343
serde_json = "1.0"
44-
toml = "0.8"
44+
toml = "0.9.5"
4545

4646
# Zero-copy serialization
4747
rkyv = { version = "0.8", features = ["alloc", "std"] }
4848
bytecheck = "0.8"
4949
rend = "0.5"
5050

5151
# Error Handling
52-
thiserror = "1.0"
52+
thiserror = "2.0.16"
5353
anyhow = "1.0"
5454

5555
# Utilities
@@ -69,29 +69,32 @@ arc-swap = "1.7"
6969

7070
# System Information
7171
num_cpus = "1.16"
72-
sysinfo = "0.30"
72+
sysinfo = "0.37.0"
7373

7474
# Database
7575
rocksdb = "0.22"
7676

7777
# Vector Search (FAISS bindings and scientific computing)
7878
faiss = "0.12"
79-
ndarray = "0.15"
79+
ndarray = "0.16.1"
8080

8181
# OpenAI API client
8282
# Minimize reqwest features for smaller binaries; prefer system TLS
8383
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "native-tls"] }
8484

85+
# ONNX ort format
86+
# ort = "=2.0.0-rc.10"
87+
ort = { version = "2", features = [ "load-dynamic" ] }
8588

8689
# Additional utilities
8790
bincode = "1.3"
8891
dashmap = "6.0"
8992
parking_lot = "0.12"
9093
tokio-util = "0.7"
91-
tokio-uring = { version = "0.4" }
94+
tokio-uring = { version = "0.5.0" }
9295

9396
# File system monitoring and diff processing
94-
notify = "6.1"
97+
notify = "8.2.0"
9598
similar = "2.4"
9699
memmap2 = "0.9"
97100
flate2 = "1.0"
@@ -100,18 +103,18 @@ zstd = "0.13"
100103
lz4_flex = "0.11"
101104
globset = "0.4"
102105
ignore = "0.4"
103-
rand = "0.8"
106+
rand = "0.9.2"
104107

105108
# Git integration
106109
git2 = "0.20"
107110

108111
# Tree-sitter for parsing
109112
tree-sitter = "0.25"
110113
tree-sitter-rust = "0.24"
111-
tree-sitter-python = "0.23"
114+
tree-sitter-python = "0.25.0"
112115
tree-sitter-javascript = "0.25"
113116
tree-sitter-typescript = "0.23"
114-
tree-sitter-go = "0.23"
117+
tree-sitter-go = "0.25.0"
115118
tree-sitter-java = "0.23"
116119
tree-sitter-cpp = "0.23"
117120

@@ -121,15 +124,15 @@ async-graphql-axum = "7.0"
121124

122125
# Web framework
123126
axum = "0.8"
124-
tower = { version = "0.4", features = ["util"] }
125-
tower-http = "0.5"
126-
hyper = "1.0"
127-
http = "1.1"
128-
prometheus = { version = "0.13", features = ["process"] }
127+
tower = { version = "0.5.2", features = ["util"] }
128+
tower-http = "0.6.6"
129+
hyper = "1.7.0"
130+
http = "1.3.1"
131+
prometheus = { version = "0.14.0", features = ["process"] }
129132

130133
# OpenAPI / Swagger documentation for Axum
131-
utoipa = { version = "4", features = ["axum_extras", "uuid", "chrono"] }
132-
utoipa-swagger-ui = { version = "7", features = ["axum"] }
134+
utoipa = { version = "5.4.0", features = ["axum_extras", "uuid", "chrono"] }
135+
utoipa-swagger-ui = { version = "9.0.2", features = ["axum"] }
133136

134137
# Memory leak detection and tracking (optional, feature-gated in binaries)
135138
memscope-rs = "0.1.4"
@@ -143,26 +146,26 @@ tracing = "0.1"
143146
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
144147
tracing-appender = "0.2"
145148
once_cell = "1.19"
146-
hashbrown = "0.14"
147-
rustc-hash = "1.1"
149+
hashbrown = "0.16.0"
150+
rustc-hash = "2.1.1"
148151
bytes = "1.6"
149152

150153
# Memory allocator + profiling
151-
tikv-jemallocator = { version = "0.5", default-features = true }
152-
tikv-jemalloc-ctl = "0.5"
154+
tikv-jemallocator = { version = "0.6.0", default-features = true }
155+
tikv-jemalloc-ctl = "0.6.0"
153156
backtrace = "0.3"
154157

155158
# Configuration
156-
config = "0.14"
157-
schemars = "0.8"
158-
secrecy = { version = "0.8", features = ["serde"] }
159+
config = "0.15.15"
160+
schemars = "1.0.4"
161+
secrecy = { version = "0.10.3", features = ["serde"] }
159162
chacha20poly1305 = { version = "0.10", features = ["std"] }
160163
base64 = "0.22"
161164

162165
# CLI
163166
clap = { version = "4.5", features = ["derive", "cargo", "env", "wrap_help"] }
164-
colored = "2.1"
165-
indicatif = "0.17"
167+
colored = "3.0.0"
168+
indicatif = "0.18.0"
166169

167170
# Security
168171
jsonwebtoken = "9.3"
@@ -172,13 +175,13 @@ argon2 = "0.5"
172175
tempfile = "3.8"
173176
tokio-test = "0.4"
174177
approx = "0.5"
175-
criterion = { version = "0.5", features = ["html_reports"] }
178+
criterion = { version = "0.7.0", features = ["html_reports"] }
176179

177180
# LRU cache utility
178-
lru = "0.12"
181+
lru = "0.16.1"
179182

180183
# Official MCP Rust SDK
181-
rmcp = { version = "0.6.0", features = ["server", "transport-io", "transport-streamable-http-server"] }
184+
rmcp = { version = "0.6.4", features = ["server", "transport-io", "transport-streamable-http-server"] }
182185

183186
# Internal crates
184187
codegraph-core = { path = "crates/codegraph-core" }

README.md

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,36 @@ CodeGraph System Architecture
9292
└─────────────────────────────────────────────────────┘
9393
```
9494

95+
## 🧠 Embeddings with ONNX Runtime (macOS)
96+
97+
- Default provider: CPU EP. Works immediately with Homebrew `onnxruntime`.
98+
- Optional CoreML EP: Set `CODEGRAPH_ONNX_EP=coreml` to prefer CoreML when using an ONNX Runtime build that includes CoreML.
99+
- Fallback: If CoreML EP init fails, CodeGraph logs a warning and falls back to CPU.
100+
101+
How to use ONNX embeddings
102+
103+
```bash
104+
# CPU-only (default)
105+
export CODEGRAPH_EMBEDDING_PROVIDER=onnx
106+
export CODEGRAPH_ONNX_EP=cpu
107+
108+
# CoreML (requires CoreML-enabled ORT build)
109+
export CODEGRAPH_EMBEDDING_PROVIDER=onnx
110+
export CODEGRAPH_ONNX_EP=coreml
111+
```
112+
113+
Notes
114+
115+
- ONNX Runtime on Apple platforms accelerates via CoreML, not Metal. If you need GPU acceleration on Apple Silicon, use CoreML where supported.
116+
- Some models/operators may still run on CPU if CoreML doesn’t support them.
117+
118+
Enabling CoreML feature at build time
119+
120+
- The CoreML registration path is gated by the Cargo feature `onnx-coreml` in `codegraph-vector`.
121+
- Build with: `cargo build -p codegraph-vector --features "onnx,onnx-coreml"`
122+
- In a full workspace build, enable it via your consuming crate’s features or by adding: `--features codegraph-vector/onnx,codegraph-vector/onnx-coreml`.
123+
- You still need an ONNX Runtime library that was compiled with CoreML support; the feature only enables the registration call in our code.
124+
95125
## 📦 Prerequisites
96126

97127
### System Requirements
@@ -118,7 +148,7 @@ sudo dnf install cmake clang openssl-devel
118148
### Optional Dependencies
119149

120150
- **FAISS** (for vector search acceleration)
121-
- **Local Embeddings (Hugging Face + Candle)**
151+
- **Local Embeddings (Hugging Face + Candle + ONNX osx-metal/cuda/cpu)**
122152
- Enables on-device embedding generation (no external API calls)
123153
- Downloads models from Hugging Face Hub on first run and caches them locally
124154
- Internet access required for the initial model download (or pre-populate cache)
@@ -132,7 +162,7 @@ sudo dnf install cmake clang openssl-devel
132162

133163
```bash
134164
# Clone the repository
135-
git clone https://github.com/your-org/codegraph-cli-mcp.git
165+
git clone https://github.com/jakedismo/codegraph-cli-mcp.git
136166
cd codegraph-cli-mcp
137167

138168
# Build the project
@@ -183,7 +213,7 @@ Model cache locations:
183213

184214
```bash
185215
# Download the latest release
186-
curl -L https://github.com/your-org/codegraph-cli-mcp/releases/latest/download/codegraph-$(uname -s)-$(uname -m).tar.gz | tar xz
216+
curl -L https://github.com/jakedismo/codegraph-cli-mcp/releases/latest/download/codegraph-$(uname -s)-$(uname -m).tar.gz | tar xz
187217

188218
# Move to PATH
189219
sudo mv codegraph /usr/local/bin/
@@ -248,8 +278,6 @@ export CODEGRAPH_LOCAL_MODEL=sentence-transformers/all-MiniLM-L6-v2
248278
cargo run -p codegraph-api --features codegraph-vector/local-embeddings
249279
```
250280

251-
```
252-
253281
### 4. Search Your Code
254282

255283
```bash
@@ -811,7 +839,7 @@ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) f
811839

812840
```bash
813841
# Clone repository
814-
git clone https://github.com/your-org/codegraph-cli-mcp.git
842+
git clone https://github.com/jakedismo/codegraph-cli-mcp.git
815843
cd codegraph-cli-mcp
816844

817845
# Install development dependencies

crates/codegraph-core/src/config.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,11 +321,14 @@ impl ConfigManager {
321321
pub mod crypto {
322322
use super::*;
323323
use rand::rngs::OsRng;
324-
use rand::RngCore;
324+
use rand::TryRngCore;
325325

326326
pub fn generate_key() -> String {
327327
let mut key = [0u8; 32];
328-
OsRng.fill_bytes(&mut key);
328+
// rand 0.9 OsRng implements RngCore; use trait method on a mutable instance
329+
let mut rng = OsRng;
330+
// rand 0.9 switched to Result-returning try_fill_bytes
331+
rng.try_fill_bytes(&mut key).expect("OsRng available");
329332
general_purpose::STANDARD.encode(key)
330333
}
331334

@@ -334,7 +337,8 @@ pub mod crypto {
334337
anyhow::ensure!(key.len() == 32, "key must be 32 bytes (base64)");
335338
let cipher = ChaCha20Poly1305::new(Key::from_slice(&key));
336339
let mut nonce = [0u8; 12];
337-
OsRng.fill_bytes(&mut nonce);
340+
let mut rng = OsRng;
341+
rng.try_fill_bytes(&mut nonce).expect("OsRng available");
338342
let nonce_obj = Nonce::from_slice(&nonce);
339343
let mut out = Vec::with_capacity(12 + plaintext.len() + 16);
340344
out.extend_from_slice(&nonce);

crates/codegraph-core/src/security.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use std::fmt;
44
use thiserror::Error;
55
use uuid::Uuid;
66
use chrono::{DateTime, Utc};
7-
use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier, password_hash::{SaltString, rand_core::OsRng}};
7+
use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier, password_hash::{SaltString}};
8+
use rand::rngs::OsRng;
9+
use rand::RngCore;
810
use dashmap::DashMap;
911

1012
#[derive(Error, Debug)]
@@ -203,7 +205,9 @@ impl ApiKeyManager {
203205
}
204206

205207
fn hash_api_key(&self, key: &str) -> Result<String, SecurityError> {
206-
let salt = SaltString::generate(&mut OsRng);
208+
let mut rng = OsRng;
209+
// rand_core trait impl is available via rand; SaltString expects rand_core::CryptoRng + RngCore
210+
let salt = SaltString::generate(&mut rng);
207211
let password_hash = self.argon2
208212
.hash_password(key.as_bytes(), &salt)
209213
.map_err(|e| SecurityError::CryptographicFailure(e.to_string()))?;
@@ -467,4 +471,4 @@ mod tests {
467471
assert!(AuthorizationEngine::has_permission(&context, &[Permission::READ_CODE]));
468472
assert!(!AuthorizationEngine::has_permission(&context, &[Permission::ADMIN_SYSTEM]));
469473
}
470-
}
474+
}

crates/codegraph-graph/src/file_watcher.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use codegraph_core::{traits::FileWatcher, ChangeEvent, Result};
22
use crossbeam_channel::Sender;
3-
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
3+
use notify::{Error as NotifyError, RecommendedWatcher, RecursiveMode, Watcher};
44
use std::path::Path;
55

66
pub struct FileWatcherImpl {
@@ -19,9 +19,12 @@ impl FileWatcher for FileWatcherImpl {
1919
fn watch(&self, tx: Sender<ChangeEvent>) -> Result<()> {
2020
let (notify_tx, notify_rx) = std::sync::mpsc::channel();
2121

22-
let mut watcher: RecommendedWatcher = Watcher::new(notify_tx, notify::Config::default())?;
22+
let mut watcher: RecommendedWatcher = Watcher::new(notify_tx, notify::Config::default())
23+
.map_err(|e: NotifyError| codegraph_core::CodeGraphError::Notify(e))?;
2324

24-
watcher.watch(Path::new(&self.path), RecursiveMode::Recursive)?;
25+
watcher
26+
.watch(Path::new(&self.path), RecursiveMode::Recursive)
27+
.map_err(|e: NotifyError| codegraph_core::CodeGraphError::Notify(e))?;
2528

2629
for res in notify_rx {
2730
match res {
@@ -45,7 +48,7 @@ impl FileWatcher for FileWatcherImpl {
4548
})?;
4649
}
4750
}
48-
Err(e) => return Err(e.into()),
51+
Err(e) => return Err(codegraph_core::CodeGraphError::Notify(e.into())),
4952
}
5053
}
5154

0 commit comments

Comments
 (0)