Skip to content

Commit 39fb398

Browse files
committed
feat(tiny-dancer): add score() raw-forward inference + 0.1.22
score(modelPath, embedding) loads a trainRouter .safetensors and runs the FastGRNN directly on the raw embedding (the inference path that matches how trainRouter trains — Router.route's 5-feature engineering is a different model contract). Validated easy=1.0/hard=0.0 on a freshly built binary. Co-Authored-By: claude-flow <ruv@ruv.net>
1 parent 5173ce7 commit 39fb398

3 files changed

Lines changed: 52 additions & 9 deletions

File tree

crates/ruvector-tiny-dancer-node/src/lib.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,3 +398,29 @@ pub async fn train_router(
398398
.map_err(|e| Error::from_reason(format!("Task failed: {}", e)))?
399399
.map_err(Error::from_reason)
400400
}
401+
402+
/// Score a query embedding with a trained FastGRNN model (raw forward pass).
403+
///
404+
/// Loads the `.safetensors` produced by {@link train_router} and runs the model
405+
/// directly on `embedding` (which must match the model's `input_dim`). Returns
406+
/// the sigmoid output in 0..1 — high means "the cheap model is good enough"
407+
/// (route to the cheaper model); low means route to a stronger model.
408+
///
409+
/// This is the inference path that matches `trainRouter` (trained on raw
410+
/// embeddings); it does not run `Router`'s feature engineering.
411+
#[napi]
412+
pub async fn score(model_path: String, embedding: Vec<f64>) -> Result<f64> {
413+
use ruvector_tiny_dancer_core::model::FastGRNN;
414+
415+
tokio::task::spawn_blocking(move || -> std::result::Result<f64, String> {
416+
let model = FastGRNN::load(&model_path).map_err(|e| format!("load: {e}"))?;
417+
let feats: Vec<f32> = embedding.into_iter().map(|v| v as f32).collect();
418+
let s = model
419+
.forward(&feats, None)
420+
.map_err(|e| format!("forward: {e}"))?;
421+
Ok(s as f64)
422+
})
423+
.await
424+
.map_err(|e| Error::from_reason(format!("Task failed: {}", e)))?
425+
.map_err(Error::from_reason)
426+
}

npm/packages/tiny-dancer/index.d.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,20 @@ export function trainRouter(
191191
prices: Record<string, number>,
192192
options: TrainRouterOptions
193193
): Promise<TrainRouterResult>;
194+
195+
/**
196+
* Score a query embedding with a trained FastGRNN model (raw forward pass).
197+
*
198+
* Loads the `.safetensors` produced by {@link trainRouter} and runs the model
199+
* directly on `embedding` (which must match the model's `inputDim`). Returns the
200+
* sigmoid output in 0..1 — high means "the cheap model is good enough" (route to
201+
* the cheaper model); low means route to a stronger model. This is the inference
202+
* path that matches `trainRouter`; it does not run `Router`'s feature engineering.
203+
*
204+
* @example
205+
* ```javascript
206+
* const s = await score('./router.safetensors', queryEmbedding);
207+
* const useCheap = s >= 0.5;
208+
* ```
209+
*/
210+
export function score(modelPath: string, embedding: number[]): Promise<number>;

npm/packages/tiny-dancer/package.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ruvector/tiny-dancer",
3-
"version": "0.1.21",
3+
"version": "0.1.22",
44
"description": "Neural router for AI agent orchestration - FastGRNN-based intelligent routing with circuit breaker, uncertainty estimation, and hot-reload",
55
"main": "index.js",
66
"types": "index.d.ts",
@@ -31,14 +31,14 @@
3131
"@napi-rs/cli": "^2.18.0"
3232
},
3333
"optionalDependencies": {
34-
"@ruvector/tiny-dancer-linux-x64-gnu": "0.1.21",
35-
"@ruvector/tiny-dancer-linux-x64-musl": "0.1.21",
36-
"@ruvector/tiny-dancer-linux-arm64-gnu": "0.1.21",
37-
"@ruvector/tiny-dancer-linux-arm64-musl": "0.1.21",
38-
"@ruvector/tiny-dancer-darwin-x64": "0.1.21",
39-
"@ruvector/tiny-dancer-darwin-arm64": "0.1.21",
40-
"@ruvector/tiny-dancer-win32-x64-msvc": "0.1.21",
41-
"@ruvector/tiny-dancer-win32-arm64-msvc": "0.1.21"
34+
"@ruvector/tiny-dancer-linux-x64-gnu": "0.1.22",
35+
"@ruvector/tiny-dancer-linux-x64-musl": "0.1.22",
36+
"@ruvector/tiny-dancer-linux-arm64-gnu": "0.1.22",
37+
"@ruvector/tiny-dancer-linux-arm64-musl": "0.1.22",
38+
"@ruvector/tiny-dancer-darwin-x64": "0.1.22",
39+
"@ruvector/tiny-dancer-darwin-arm64": "0.1.22",
40+
"@ruvector/tiny-dancer-win32-x64-msvc": "0.1.22",
41+
"@ruvector/tiny-dancer-win32-arm64-msvc": "0.1.22"
4242
},
4343
"publishConfig": {
4444
"access": "public"

0 commit comments

Comments
 (0)