@ruvector/ruvllm 4.0.1 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +446 -160
- package/bin/cli.js +1066 -0
- package/bin/gpu-delegate.js +67 -0
- package/bin/ruvllm-adapters.js +5 -0
- package/bin/ruvllm-gpu-loop.js +5 -0
- package/bin/serve.js +265 -0
- package/dist/cjs/benchmarks/embedding-benchmark.d.ts +102 -0
- package/dist/cjs/benchmarks/embedding-benchmark.d.ts.map +1 -0
- package/dist/cjs/benchmarks/embedding-benchmark.js +436 -0
- package/dist/cjs/benchmarks/index.d.ts +34 -0
- package/dist/cjs/benchmarks/index.d.ts.map +1 -0
- package/dist/cjs/benchmarks/index.js +132 -0
- package/dist/cjs/benchmarks/model-comparison.d.ts +71 -0
- package/dist/cjs/benchmarks/model-comparison.d.ts.map +1 -0
- package/dist/cjs/benchmarks/model-comparison.js +476 -0
- package/dist/cjs/benchmarks/routing-benchmark.d.ts +70 -0
- package/dist/cjs/benchmarks/routing-benchmark.d.ts.map +1 -0
- package/dist/cjs/benchmarks/routing-benchmark.js +289 -0
- package/dist/cjs/contrastive.d.ts +229 -0
- package/dist/cjs/contrastive.d.ts.map +1 -0
- package/dist/cjs/contrastive.js +589 -0
- package/dist/cjs/engine.d.ts +160 -0
- package/dist/cjs/engine.d.ts.map +1 -0
- package/dist/cjs/engine.js +552 -0
- package/dist/cjs/export.d.ts +182 -0
- package/dist/cjs/export.d.ts.map +1 -0
- package/dist/cjs/export.js +422 -0
- package/dist/cjs/federated.d.ts +233 -0
- package/dist/cjs/federated.d.ts.map +1 -0
- package/dist/cjs/federated.js +525 -0
- package/dist/cjs/index.d.ts +68 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +104 -0
- package/dist/cjs/intelligence.d.ts +136 -0
- package/dist/cjs/intelligence.d.ts.map +1 -0
- package/dist/cjs/intelligence.js +226 -0
- package/dist/cjs/lora.d.ts +251 -0
- package/dist/cjs/lora.d.ts.map +1 -0
- package/dist/cjs/lora.js +509 -0
- package/dist/cjs/models.d.ts +129 -0
- package/dist/cjs/models.d.ts.map +1 -0
- package/dist/cjs/models.js +323 -0
- package/dist/cjs/native.d.ts +140 -0
- package/dist/cjs/native.d.ts.map +1 -0
- package/dist/cjs/native.js +98 -0
- package/dist/cjs/session.d.ts +80 -0
- package/dist/cjs/session.d.ts.map +1 -0
- package/dist/cjs/session.js +203 -0
- package/dist/cjs/simd.d.ts +90 -0
- package/dist/cjs/simd.d.ts.map +1 -0
- package/dist/cjs/simd.js +209 -0
- package/dist/cjs/sona.d.ts +223 -0
- package/dist/cjs/sona.d.ts.map +1 -0
- package/dist/cjs/sona.js +562 -0
- package/dist/cjs/streaming.d.ts +55 -0
- package/dist/cjs/streaming.d.ts.map +1 -0
- package/dist/cjs/streaming.js +131 -0
- package/dist/cjs/training.d.ts +312 -0
- package/dist/cjs/training.d.ts.map +1 -0
- package/dist/cjs/training.js +610 -0
- package/dist/cjs/types.d.ts +696 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +6 -0
- package/dist/esm/benchmarks/embedding-benchmark.d.ts +102 -0
- package/dist/esm/benchmarks/embedding-benchmark.d.ts.map +1 -0
- package/dist/esm/benchmarks/embedding-benchmark.js +427 -0
- package/dist/esm/benchmarks/index.d.ts +34 -0
- package/dist/esm/benchmarks/index.d.ts.map +1 -0
- package/dist/esm/benchmarks/index.js +110 -0
- package/dist/esm/benchmarks/model-comparison.d.ts +71 -0
- package/dist/esm/benchmarks/model-comparison.d.ts.map +1 -0
- package/dist/esm/benchmarks/model-comparison.js +434 -0
- package/dist/esm/benchmarks/routing-benchmark.d.ts +70 -0
- package/dist/esm/benchmarks/routing-benchmark.d.ts.map +1 -0
- package/dist/esm/benchmarks/routing-benchmark.js +283 -0
- package/dist/esm/contrastive.d.ts +229 -0
- package/dist/esm/contrastive.d.ts.map +1 -0
- package/dist/esm/contrastive.js +578 -0
- package/dist/esm/engine.d.ts +160 -0
- package/dist/esm/engine.d.ts.map +1 -0
- package/dist/esm/engine.js +548 -0
- package/dist/esm/export.d.ts +182 -0
- package/dist/esm/export.d.ts.map +1 -0
- package/dist/esm/export.js +414 -0
- package/dist/esm/federated.d.ts +233 -0
- package/dist/esm/federated.d.ts.map +1 -0
- package/dist/esm/federated.js +520 -0
- package/dist/esm/index.d.ts +68 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +84 -0
- package/dist/esm/intelligence.d.ts +136 -0
- package/dist/esm/intelligence.d.ts.map +1 -0
- package/dist/esm/intelligence.js +188 -0
- package/dist/esm/lora.d.ts +251 -0
- package/dist/esm/lora.d.ts.map +1 -0
- package/dist/esm/lora.js +504 -0
- package/dist/esm/models.d.ts +129 -0
- package/dist/esm/models.d.ts.map +1 -0
- package/dist/esm/models.js +282 -0
- package/dist/esm/native.d.ts +140 -0
- package/dist/esm/native.d.ts.map +1 -0
- package/dist/esm/native.js +100 -0
- package/dist/esm/session.d.ts +80 -0
- package/dist/esm/session.d.ts.map +1 -0
- package/dist/esm/session.js +199 -0
- package/dist/esm/simd.d.ts +90 -0
- package/dist/esm/simd.d.ts.map +1 -0
- package/dist/esm/simd.js +205 -0
- package/dist/esm/sona.d.ts +223 -0
- package/dist/esm/sona.d.ts.map +1 -0
- package/dist/esm/sona.js +556 -0
- package/dist/esm/streaming.d.ts +55 -0
- package/dist/esm/streaming.d.ts.map +1 -0
- package/dist/esm/streaming.js +126 -0
- package/dist/esm/training.d.ts +312 -0
- package/dist/esm/training.d.ts.map +1 -0
- package/dist/esm/training.js +603 -0
- package/dist/esm/types.d.ts +696 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +5 -0
- package/gpu/_load.cjs +38 -0
- package/gpu/_load.mjs +33 -0
- package/gpu/adapters.cjs +3 -0
- package/gpu/adapters.mjs +5 -0
- package/gpu/engine.cjs +3 -0
- package/gpu/engine.mjs +5 -0
- package/gpu/fixture.cjs +3 -0
- package/gpu/fixture.mjs +5 -0
- package/gpu/gpu-host.cjs +3 -0
- package/gpu/gpu-host.mjs +5 -0
- package/gpu/gpu-loop.cjs +3 -0
- package/gpu/gpu-loop.mjs +5 -0
- package/gpu/gpu-spool-adapter.cjs +3 -0
- package/gpu/gpu-spool-adapter.mjs +5 -0
- package/gpu/vast-host-adapter.cjs +3 -0
- package/gpu/vast-host-adapter.mjs +5 -0
- package/package.json +159 -49
- package/scripts/ensemble-model-compare.js +287 -0
- package/scripts/fix-esm-extensions.mjs +220 -0
- package/scripts/huggingface/README.md +537 -0
- package/scripts/huggingface/publish.sh +112 -0
- package/scripts/hybrid-model-compare.js +373 -0
- package/scripts/improved-model-compare.js +288 -0
- package/scripts/optimized-model-compare.js +364 -0
- package/scripts/real-model-compare.js +280 -0
- package/scripts/smoke-esm.mjs +82 -0
- package/scripts/training/agentic-flow-capabilities.json +329 -0
- package/scripts/training/claude-code-synth.js +505 -0
- package/scripts/training/claude-flow-capabilities.json +1322 -0
- package/scripts/training/claude-hard-negatives.js +222 -0
- package/scripts/training/contrastive-finetune.js +517 -0
- package/scripts/training/ecosystem-triplets.jsonl +1467 -0
- package/scripts/training/generate-ecosystem-triplets.js +1324 -0
- package/scripts/training/routing-dataset.js +634 -0
- package/scripts/training/ruvector-capabilities.json +798 -0
- package/scripts/training/validate-ecosystem.js +381 -0
- package/scripts/training/validation-results.json +23 -0
- package/GPU-LOOP.md +0 -229
- package/LICENSE +0 -201
- package/NOTICE +0 -9
- package/examples/gpu-loop.example.json +0 -26
- package/src/adapters-cli.mjs +0 -23
- package/src/adapters.mjs +0 -91
- package/src/cli.mjs +0 -30
- package/src/engine.mjs +0 -238
- package/src/fixture.mjs +0 -38
- package/src/gpu-host.mjs +0 -47
- package/src/gpu-loop-cli.mjs +0 -67
- package/src/gpu-loop.mjs +0 -184
- package/src/gpu-spool-adapter.mjs +0 -80
- package/src/vast-host-adapter.mjs +0 -274
package/README.md
CHANGED
|
@@ -1,187 +1,473 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @ruvector/ruvllm
|
|
2
|
+
|
|
3
|
+
<p align="center"><img src="https://raw.githubusercontent.com/ruvnet/RuVector/main/assets/ruvector/packages/ruvllm.svg" alt="@ruvector/ruvllm: self-learning LLM runtime for Node.js with GGUF inference, SONA, TurboQuant KV cache and an optional GPU job loop." width="100%"></p>
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@ruvector/ruvllm)
|
|
6
|
+
[](https://www.npmjs.com/package/@ruvector/ruvllm)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
[](https://github.com/ruvnet/ruvector)
|
|
9
|
+
|
|
10
|
+
**Self-learning LLM runtime for Node.js** — GGUF inference, TurboQuant KV-cache compression (6-8x memory savings), SONA adaptive learning, FlashAttention, speculative decoding, and SIMD-optimized kernels. Built in Rust, runs everywhere.
|
|
11
|
+
|
|
12
|
+
> Inference at **88-135 tok/s** on M4 Pro | **<1ms** SONA adaptation | **6-8x** KV-cache compression via TurboQuant
|
|
13
|
+
|
|
14
|
+
## One package: the LLM runtime and the GPU job loop (4.1.0)
|
|
15
|
+
|
|
16
|
+
`@ruvector/ruvllm` is the RuVLLM **self-learning LLM runtime for Node.js**:
|
|
17
|
+
GGUF inference, SONA adaptive learning, MicroLoRA, TurboQuant KV-cache
|
|
18
|
+
compression, FlashAttention, speculative decoding, HNSW memory, the `ruvllm`
|
|
19
|
+
CLI and a local `ruvllm serve` HTTP server. Since 4.1.0 it also pulls in
|
|
20
|
+
**[`@ruvector/ruvllm-gpu-loop`](https://www.npmjs.com/package/@ruvector/ruvllm-gpu-loop)**
|
|
21
|
+
(the RuVLLM GPU job loop, Vast.ai host adapter, adapter archives and bounded
|
|
22
|
+
weight experiments) as an optional dependency, so a single
|
|
23
|
+
`npm install @ruvector/ruvllm` gives you both.
|
|
24
|
+
|
|
25
|
+
**Why 4.1.0 exists.** Versions 4.0.0 and 4.0.1 were published from a different
|
|
26
|
+
repository (`ruvnet/ruvllm`) and replaced this runtime with only the GPU job
|
|
27
|
+
loop harness: no runtime API, no native bindings, no `ruvllm` CLI. 4.1.0
|
|
28
|
+
restores the runtime (the same API as 3.0.0) and keeps every 4.0.x entry point
|
|
29
|
+
working through `@ruvector/ruvllm-gpu-loop`. Do not use 4.0.0 or 4.0.1.
|
|
30
|
+
|
|
31
|
+
| You used | In 4.1.0 |
|
|
32
|
+
| :--- | :--- |
|
|
33
|
+
| 3.x / 2.x runtime: `require('@ruvector/ruvllm')`, `import … from '@ruvector/ruvllm'` | Unchanged (CommonJS and ESM) |
|
|
34
|
+
| 4.0.x root: `import { runExperiment } from '@ruvector/ruvllm'` | `import { runExperiment } from '@ruvector/ruvllm/engine'` |
|
|
35
|
+
| 4.0.x subpaths: `@ruvector/ruvllm/gpu-loop`, `/adapters`, `/gpu-host`, `/gpu-spool-adapter`, `/vast-host-adapter`, `/fixture` | Unchanged (re-exported from `@ruvector/ruvllm-gpu-loop`) |
|
|
36
|
+
| 4.0.x CLI: `ruvllm run …`, `ruvllm fixture …` | `ruvllm gpu run …`, `ruvllm gpu fixture …` (or `ruvllm-gpu` from `@ruvector/ruvllm-gpu-loop`) |
|
|
37
|
+
| `ruvllm-gpu-loop`, `ruvllm-adapters` | Unchanged; also `ruvllm gpu loop …`, `ruvllm gpu adapters …` |
|
|
38
|
+
|
|
39
|
+
The GPU-loop subpaths are loaded lazily: importing the root never loads them.
|
|
40
|
+
They need Node 22+ (the GPU-loop package's requirement). If the optional
|
|
41
|
+
package was skipped (`--omit=optional`), they throw `RUVLLM_GPU_LOOP_MISSING`
|
|
42
|
+
naming the install command. They are ESM; `require()` of them works where
|
|
43
|
+
Node supports `require(esm)` (20.19+ / 22.12+). If you only need the GPU job
|
|
44
|
+
loop, install `@ruvector/ruvllm-gpu-loop` on its own.
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install @ruvector/ruvllm
|
|
50
|
+
```
|
|
2
51
|
|
|
3
|
-
|
|
52
|
+
## Quick Start
|
|
4
53
|
|
|
5
|
-
|
|
54
|
+
```typescript
|
|
55
|
+
import { RuvLLM, RuvLLMConfig } from '@ruvector/ruvllm';
|
|
6
56
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
lives in `ruvnet/ruvllm`. The 3.x API and its CLI subcommands are not part of
|
|
10
|
-
4.x; pin `@ruvector/ruvllm@3` to keep using them. The npm package ships the
|
|
11
|
-
JavaScript controller, GPU loop and Vast.ai host adapter. It does not ship the
|
|
12
|
-
native `weight_evolution` binary, model weights or adapters. Build the binary
|
|
13
|
-
from this repository and pass its path with `--binary`.
|
|
57
|
+
// Initialize with default configuration
|
|
58
|
+
const llm = new RuvLLM();
|
|
14
59
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
60
|
+
// Or with custom configuration
|
|
61
|
+
const llm = new RuvLLM({ embeddingDim: 384, learningEnabled: true });
|
|
62
|
+
|
|
63
|
+
// Routing, memory and embeddings (no model needed)
|
|
64
|
+
const decision = llm.route('Explain quantum computing');
|
|
65
|
+
llm.addMemory('RuvLLM routes queries with FastGRNN', { source: 'docs' });
|
|
66
|
+
const hits = llm.searchMemory('how are queries routed?', 3);
|
|
67
|
+
const vec = llm.embed('Explain quantum computing');
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Text Generation (GGUF)
|
|
71
|
+
|
|
72
|
+
Text comes only from a model you load. `loadModel()` runs a local GGUF file
|
|
73
|
+
on the native candle backend (CPU; Metal on macOS builds with the `metal`
|
|
74
|
+
feature):
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const llm = new RuvLLM();
|
|
78
|
+
llm.loadModel('./qwen2.5-0.5b-instruct-q4_k_m.gguf', { maxContext: 4096 });
|
|
79
|
+
|
|
80
|
+
const out = llm.chat([{ role: 'user', content: 'What is the capital of France?' }], {
|
|
81
|
+
maxTokens: 64,
|
|
82
|
+
temperature: 0,
|
|
83
|
+
});
|
|
84
|
+
// { text: 'The capital of France is Paris.', promptTokens: 15,
|
|
85
|
+
// completionTokens: 8, finishReason: 'stop' }
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- **Architectures**: GGUF `llama`, `mistral`, `qwen2` (Qwen2.5) and `qwen3`.
|
|
89
|
+
Any other architecture (phi, gemma, qwen3.5, ...) fails to load with an error
|
|
90
|
+
naming it.
|
|
91
|
+
- **Tokenizer**: a `tokenizer.json` next to the GGUF, else the tokenizer
|
|
92
|
+
embedded in the GGUF. The embedded one works for byte-level BPE (`gpt2`)
|
|
93
|
+
vocabularies such as Qwen and Llama 3; GGUFs with a SentencePiece vocabulary
|
|
94
|
+
(Llama 2, Mistral, TinyLlama) need the `tokenizer.json`, otherwise loading
|
|
95
|
+
fails with `RUVLLM_TOKENIZER_MISSING`.
|
|
96
|
+
- **`chat()`** applies the model's chat template, read from the GGUF's
|
|
97
|
+
embedded `tokenizer.chat_template` (ChatML for Qwen). A `qwen2`/`qwen3` GGUF
|
|
98
|
+
whose template is not ChatML (e.g. DeepSeek-R1-Distill-Qwen) fails to load
|
|
99
|
+
with `RUVLLM_MODEL_LOAD_FAILED` rather than run under the wrong format.
|
|
100
|
+
- **`generate()`** continues the prompt verbatim; **`query()`** routes, then
|
|
101
|
+
answers as a single chat message.
|
|
102
|
+
- **Usage**: `promptTokens`/`completionTokens` are counted with the model's
|
|
103
|
+
tokenizer; `finishReason` is `stop` (end-of-sequence token or a stop
|
|
104
|
+
sequence) or `length` (`maxTokens` reached or the context is full).
|
|
105
|
+
- **Blocking**: loading and generation are synchronous and block the event
|
|
106
|
+
loop; run them in a worker thread if that matters.
|
|
107
|
+
|
|
108
|
+
Without a loaded model, `generate()`, `query()`, `chat()` and
|
|
109
|
+
`generateDetailed()` throw `RUVLLM_NO_LANGUAGE_MODEL`; they never return text
|
|
110
|
+
that is not model output. For demos and tests, `new RuvLLM({ allowPlaceholder:
|
|
111
|
+
true })` (or `RUVLLM_ALLOW_MOCK=1`) makes `generate()`/`query()` return the
|
|
112
|
+
labelled `PLACEHOLDER_TEXT` instead, with a one-time warning.
|
|
113
|
+
|
|
114
|
+
### Native binary requirements
|
|
115
|
+
|
|
116
|
+
Model loading needs a native binary built with the `candle` feature;
|
|
117
|
+
`supportsModelLoading()` reports whether the installed one was.
|
|
118
|
+
|
|
119
|
+
| Native binary | `loadModel()` |
|
|
120
|
+
|---------------|---------------|
|
|
121
|
+
| Built from this source (`npm run build:native`) | Works |
|
|
122
|
+
| `@ruvector/ruvllm-<platform>` 2.1.x (installed with `@ruvector/ruvllm` 4.2.0+, built by the release workflow with `candle`) | Works |
|
|
123
|
+
| `@ruvector/ruvllm-<platform>` 2.0.x | Throws `RUVLLM_NATIVE_TOO_OLD`: they predate model loading |
|
|
124
|
+
| Built with `--features napi` only (no `candle`) | Throws `RUVLLM_NO_INFERENCE_BACKEND` |
|
|
125
|
+
| None for your platform | Throws `RUVLLM_NATIVE_UNAVAILABLE` |
|
|
126
|
+
|
|
127
|
+
To use a binary you built, point `RUVLLM_NATIVE_PATH` at it (it takes
|
|
128
|
+
precedence over the installed platform package):
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
npm run build:native # writes ruvllm.<platform>.node (needs a Rust toolchain)
|
|
132
|
+
RUVLLM_NATIVE_PATH=$PWD/ruvllm.linux-x64-gnu.node node app.js
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
From 4.2.0 the platform packages (`@ruvector/ruvllm-<platform>@2.1.0`) are
|
|
136
|
+
built with `candle`, so `loadModel()`, `query`/`generate` with `--model` and
|
|
137
|
+
`ruvllm serve` work on a plain `npm install` for linux-x64, linux-arm64,
|
|
138
|
+
darwin-x64, darwin-arm64 and win32-x64. 4.1.0 and earlier shipped the 2.0.1
|
|
139
|
+
binaries, which predate model loading.
|
|
140
|
+
|
|
141
|
+
| Error code | Meaning |
|
|
142
|
+
|------------|---------|
|
|
143
|
+
| `RUVLLM_NO_LANGUAGE_MODEL` | Generation was requested with no model loaded |
|
|
144
|
+
| `RUVLLM_NATIVE_UNAVAILABLE` | No native binary could be loaded |
|
|
145
|
+
| `RUVLLM_NATIVE_TOO_OLD` | The native binary predates model loading (2.0.x platform packages) |
|
|
146
|
+
| `RUVLLM_NO_INFERENCE_BACKEND` | The native binary was built without the `candle` backend |
|
|
147
|
+
| `RUVLLM_MODEL_NOT_FOUND` | The model path does not exist |
|
|
148
|
+
| `RUVLLM_MODEL_LOAD_FAILED` | The file could not be loaded (unsupported architecture, not GGUF, ...) |
|
|
149
|
+
| `RUVLLM_TOKENIZER_MISSING` | Weights loaded but no usable tokenizer was found |
|
|
150
|
+
|
|
151
|
+
## What's New in v2.5
|
|
152
|
+
|
|
153
|
+
| Feature | Description |
|
|
154
|
+
|---------|-------------|
|
|
155
|
+
| **TurboQuant KV-Cache** | 2-4 bit asymmetric quantization with per-channel scale/zero-point — 6-8x memory reduction, <0.5% perplexity loss |
|
|
156
|
+
| **TurboQuant Embedding Store** | Quantized vector storage with compressed search — 10-30x memory savings |
|
|
157
|
+
| **H2O / PyramidKV Eviction** | Intelligent cache eviction policies for long-context inference |
|
|
158
|
+
| **Optimized Inner Product** | Asymmetric distance on quantized data — skip decompression for 2-4x faster search |
|
|
159
|
+
| **RuvLTRA Models** | Purpose-built 0.5B & 3B models for Claude Flow |
|
|
160
|
+
| **Task-Specific LoRA** | 5 pre-trained adapters (coder, researcher, security, architect, reviewer) |
|
|
161
|
+
| **HuggingFace Hub** | Download/upload models directly |
|
|
162
|
+
| **Adapter Merging** | TIES, DARE, SLERP strategies |
|
|
163
|
+
| **HNSW Routing** | 150x faster semantic matching |
|
|
164
|
+
| **Evaluation Harness** | SWE-Bench testing with 5 ablation modes |
|
|
165
|
+
| **mistral-rs Backend** | Production serving with PagedAttention, X-LoRA, ISQ |
|
|
166
|
+
|
|
167
|
+
## TurboQuant — KV-Cache Compression
|
|
168
|
+
|
|
169
|
+
Reduce inference memory by 6-8x with <0.5% quality loss:
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
import { simd } from '@ruvector/ruvllm/simd';
|
|
173
|
+
|
|
174
|
+
// TurboQuant compresses KV-cache entries at 2-4 bit precision
|
|
175
|
+
// with per-channel asymmetric quantization (scale + zero-point).
|
|
176
|
+
// Eviction policies (H2O, Sliding Window, PyramidKV) keep the
|
|
177
|
+
// most important tokens in cache during long-context generation.
|
|
178
|
+
|
|
179
|
+
// Supported bit widths: 2-bit (32x), 3-bit (10.7x), 4-bit (8x), 8-bit (4x)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
| Bits | Compression | Perplexity Loss | Use Case |
|
|
183
|
+
|------|-------------|-----------------|----------|
|
|
184
|
+
| 2-bit | 32x | ~2% | Maximum compression, edge devices |
|
|
185
|
+
| 3-bit | 10.7x | <1% | Balanced — recommended for most uses |
|
|
186
|
+
| 4-bit | 8x | <0.5% | High quality, long-context inference |
|
|
187
|
+
| 8-bit | 4x | ~0% | Baseline quantization |
|
|
188
|
+
|
|
189
|
+
## CLI Usage
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# Query a model (this package's `ruvllm` bin; needs --model, see above)
|
|
193
|
+
ruvllm query "What is machine learning?" --model ./qwen2.5-0.5b-instruct-q4_k_m.gguf
|
|
194
|
+
|
|
195
|
+
# The commands below are the Rust ruvllm CLI (crate ruvllm-cli)
|
|
196
|
+
# Stream output
|
|
197
|
+
ruvllm query --stream "Write a poem"
|
|
198
|
+
|
|
199
|
+
# Download a model
|
|
200
|
+
ruvllm download ruvector/ruvltra-small-q4km
|
|
201
|
+
|
|
202
|
+
# Benchmark
|
|
203
|
+
ruvllm bench ./models/model.gguf
|
|
204
|
+
|
|
205
|
+
# Run evaluation (SWE-Bench)
|
|
206
|
+
ruvllm eval --model ./models/model.gguf --subset lite --max-tasks 50
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## HTTP server: `ruvllm serve`
|
|
210
|
+
|
|
211
|
+
`ruvllm serve` runs a local LLM server over a GGUF model, on
|
|
212
|
+
`127.0.0.1:3000` by default (`--host`, `--port`, `--max-context`,
|
|
213
|
+
`--max-tokens`, `--temperature`). It is the endpoint the
|
|
214
|
+
[ruflo / claude-flow](https://github.com/ruvnet/claude-flow) RuVector provider
|
|
215
|
+
calls:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
npx @ruvector/ruvllm serve ./qwen2.5-0.5b-instruct-q4_k_m.gguf
|
|
219
|
+
curl -s localhost:3000/health
|
|
220
|
+
curl -s localhost:3000/query -H 'content-type: application/json' -d '{"query":"What is HNSW?"}'
|
|
221
|
+
curl -s localhost:3000/v1/chat/completions -H 'content-type: application/json' \
|
|
222
|
+
-d '{"messages":[{"role":"user","content":"Hello"}],"max_tokens":32}'
|
|
19
223
|
```
|
|
20
224
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
225
|
+
| Endpoint | Body / response |
|
|
226
|
+
| :--- | :--- |
|
|
227
|
+
| `GET /health` | `{ status, model, modelLoaded, native, sona, hnsw, version }` |
|
|
228
|
+
| `GET /v1/models` | OpenAI-style model list |
|
|
229
|
+
| `POST /query` | `{ query, session_id? }` → `{ id, model, content, done, usage, router_metrics }` |
|
|
230
|
+
| `POST /v1/chat/completions` | OpenAI chat format; `stream: true` returns the finished completion as one SSE chunk, then `[DONE]` |
|
|
231
|
+
|
|
232
|
+
The server is strict: it starts only after the model loads, and exits 1
|
|
233
|
+
otherwise (no placeholder answers, so clients such as ruflo fall back to
|
|
234
|
+
another provider instead of receiving non-model text). Generation is
|
|
235
|
+
synchronous, so requests are answered one at a time.
|
|
236
|
+
|
|
237
|
+
## GPU job loop: `ruvllm gpu`
|
|
238
|
+
|
|
239
|
+
The RuVLLM GPU job loop schedules bounded GPU jobs (spending ceiling, destroy
|
|
240
|
+
timer, confirmed cleanup) on a Vast.ai host, packages LoRA adapter archives
|
|
241
|
+
and runs bounded weight-edit experiments. It lives in
|
|
242
|
+
[`@ruvector/ruvllm-gpu-loop`](https://www.npmjs.com/package/@ruvector/ruvllm-gpu-loop)
|
|
243
|
+
([source](https://github.com/ruvnet/ruvllm/tree/main/integrations/metaharness));
|
|
244
|
+
this package exposes it as:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
npx ruvllm gpu loop status --config /abs/private/gpu-loop.json # = ruvllm-gpu-loop
|
|
248
|
+
npx ruvllm gpu adapters training-plan < plan.json # = ruvllm-adapters
|
|
249
|
+
npx ruvllm gpu fixture --dir /abs/new-dir --binary /abs/weight_evolution
|
|
45
250
|
```
|
|
46
251
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
`unevaluated-control` unqualified, verify RVF and exact rollback for both, and
|
|
51
|
-
report `inferencePerformed: false`, `independentConfirmation: false` and
|
|
52
|
-
`productionActivation: false`. A selected synthetic candidate says nothing about
|
|
53
|
-
actual model accuracy.
|
|
54
|
-
|
|
55
|
-
## Configure real experiment inputs
|
|
56
|
-
|
|
57
|
-
Prepare reviewed source checkpoint, patch, policy and optional evaluation JSON
|
|
58
|
-
under explicit input roots. Native request/data contracts are described in the
|
|
59
|
-
[native guide](../../native/README.md). Patch generation remains model specific;
|
|
60
|
-
the controller does not guess useful tensor edits.
|
|
61
|
-
|
|
62
|
-
Run the project-local installer with paths you control:
|
|
63
|
-
|
|
64
|
-
```sh
|
|
65
|
-
bash scripts/install-metaharness.sh \
|
|
66
|
-
--config-dir /absolute/private/operator-profile \
|
|
67
|
-
--read-root /absolute/checkpoints \
|
|
68
|
-
--read-root /absolute/experiment-inputs \
|
|
69
|
-
--policy /absolute/experiment-inputs/policy.json \
|
|
70
|
-
--output-root /absolute/private/experiment-outputs
|
|
252
|
+
```js
|
|
253
|
+
import { tickLoop, readLoopStatus } from '@ruvector/ruvllm/gpu-loop';
|
|
254
|
+
import { createVastAdapter } from '@ruvector/ruvllm/vast-host-adapter';
|
|
71
255
|
```
|
|
72
256
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
257
|
+
## API Reference
|
|
258
|
+
|
|
259
|
+
### RuvLLM Class
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
class RuvLLM {
|
|
263
|
+
constructor(config?: RuvLLMConfig);
|
|
264
|
+
|
|
265
|
+
// Language model (see "Text Generation" above)
|
|
266
|
+
loadModel(path: string, options?: LoadModelOptions): LoadedModelInfo;
|
|
267
|
+
unloadModel(): void;
|
|
268
|
+
isModelLoaded(): boolean;
|
|
269
|
+
modelInfo(): LoadedModelInfo | null;
|
|
270
|
+
supportsModelLoading(): boolean; // native binary can load models
|
|
271
|
+
|
|
272
|
+
// Generation; all throw RUVLLM_NO_LANGUAGE_MODEL without a loaded model
|
|
273
|
+
chat(messages: ChatMessage[], config?: GenerationConfig): GenerationResult;
|
|
274
|
+
generateDetailed(prompt: string, config?: GenerationConfig): GenerationResult;
|
|
275
|
+
generate(prompt: string, config?: GenerationConfig): string;
|
|
276
|
+
query(text: string, config?: GenerationConfig): QueryResponse; // routed, + token usage
|
|
277
|
+
|
|
278
|
+
// Routing, memory and embeddings
|
|
279
|
+
route(text: string): RoutingDecision;
|
|
280
|
+
addMemory(content: string, metadata?: Record<string, unknown>): MemoryId;
|
|
281
|
+
searchMemory(text: string, k?: number): MemoryResult[];
|
|
282
|
+
embed(text: string): Embedding;
|
|
283
|
+
|
|
284
|
+
// Not in this package: token streaming (StreamingGenerator chunks a
|
|
285
|
+
// finished generate() result), mistral-rs backends.
|
|
286
|
+
|
|
287
|
+
// Get SONA learning stats
|
|
288
|
+
sonaStats(): SonaStats | null;
|
|
289
|
+
|
|
290
|
+
// Adapt on feedback
|
|
291
|
+
adapt(input: Float32Array, quality: number): void;
|
|
96
292
|
}
|
|
97
293
|
```
|
|
98
294
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
295
|
+
### Configuration
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
interface RuvLLMConfig {
|
|
299
|
+
modelPath?: string; // GGUF to load in the constructor (throws if it cannot be loaded)
|
|
300
|
+
modelOptions?: LoadModelOptions; // { maxContext?: number } for modelPath
|
|
301
|
+
allowPlaceholder?: boolean; // generate()/query() return PLACEHOLDER_TEXT instead of
|
|
302
|
+
// throwing when no model is loaded (default: false)
|
|
303
|
+
strict?: boolean; // Throw instead of warning for unsupported options (`backend`)
|
|
304
|
+
// ...plus routing/memory options (embeddingDim, hnswM, ...), see types.ts
|
|
305
|
+
}
|
|
103
306
|
```
|
|
104
307
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
308
|
+
### Generation Config and Result
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
interface GenerationConfig {
|
|
312
|
+
maxTokens?: number; // default 256
|
|
313
|
+
temperature?: number; // default 0.7; 0 = greedy
|
|
314
|
+
topP?: number; // default 0.9, in (0, 1]
|
|
315
|
+
topK?: number; // default 50; 0 disables
|
|
316
|
+
repetitionPenalty?: number; // default 1.1
|
|
317
|
+
stopSequences?: string[]; // stop text is not included in the output
|
|
318
|
+
seed?: number; // reproducible sampling at temperature > 0
|
|
319
|
+
}
|
|
110
320
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
321
|
+
interface GenerationResult {
|
|
322
|
+
text: string;
|
|
323
|
+
promptTokens: number; // after the chat template, for chat()
|
|
324
|
+
completionTokens: number; // includes an end-of-sequence token that ended generation
|
|
325
|
+
finishReason: 'stop' | 'length' | 'cancelled';
|
|
326
|
+
}
|
|
327
|
+
```
|
|
116
328
|
|
|
117
|
-
##
|
|
329
|
+
## SIMD Module
|
|
118
330
|
|
|
119
|
-
|
|
120
|
-
generated `launch-claude.sh`, or set `RUVLLM_EXPERIMENT_CONFIG` and use Claude's
|
|
121
|
-
`--plugin-dir`. The `/ruflo-metaharness:weight-experiment` command and reviewer
|
|
122
|
-
agent guide the bounded workflow. Its single MCP tool accepts a plan path; the
|
|
123
|
-
model cannot override the operator configuration. The same stdio server can be
|
|
124
|
-
registered in a Ruflo project's MCP configuration. Portable wire tests exercise
|
|
125
|
-
the real engine; installed Claude/Ruflo client acceptance is separate.
|
|
331
|
+
For direct access to optimized SIMD kernels:
|
|
126
332
|
|
|
127
|
-
|
|
333
|
+
```typescript
|
|
334
|
+
import { simd } from '@ruvector/ruvllm/simd';
|
|
128
335
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
deadline-aware polling and confirmed cleanup. Local contract tests require no
|
|
132
|
-
live provider. The bundled file handoff keeps requests pending for a trusted host.
|
|
336
|
+
// Dot product
|
|
337
|
+
const result = simd.dotProduct(vecA, vecB);
|
|
133
338
|
|
|
134
|
-
|
|
339
|
+
// Matrix multiplication
|
|
340
|
+
const output = simd.matmul(matrix, vector);
|
|
135
341
|
|
|
136
|
-
|
|
342
|
+
// Flash Attention
|
|
343
|
+
const attended = simd.flashAttention(query, key, value, scale);
|
|
137
344
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
node integrations/metaharness/src/adapters-cli.mjs training-plan < training-input.json > plan.json
|
|
141
|
-
node integrations/metaharness/src/adapters-cli.mjs select < measured-candidates.json > selection.json
|
|
345
|
+
// RMS Normalization
|
|
346
|
+
simd.rmsNorm(hidden, weights, epsilon);
|
|
142
347
|
```
|
|
143
348
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
349
|
+
## Performance (M4 Pro)
|
|
350
|
+
|
|
351
|
+
| Operation | Performance |
|
|
352
|
+
|-----------|-------------|
|
|
353
|
+
| Inference | 88-135 tok/s |
|
|
354
|
+
| Flash Attention | 320µs (seq=2048) |
|
|
355
|
+
| HNSW Search | 17-62µs |
|
|
356
|
+
| SONA Adapt | <1ms |
|
|
357
|
+
| Evaluation | 5 ablation modes |
|
|
358
|
+
|
|
359
|
+
## Evaluation Harness
|
|
360
|
+
|
|
361
|
+
> **Not in this npm package**: `EvaluationHarness` and `AblationMode` are
|
|
362
|
+
> not exported by `@ruvector/ruvllm`. The sketch below shows the intended API.
|
|
363
|
+
|
|
364
|
+
Run model evaluations with SWE-Bench integration:
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import { RuvLLM, EvaluationHarness, AblationMode } from '@ruvector/ruvllm';
|
|
368
|
+
|
|
369
|
+
const harness = new EvaluationHarness({
|
|
370
|
+
modelPath: './models/model.gguf',
|
|
371
|
+
enableHnsw: true,
|
|
372
|
+
enableSona: true,
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
// Run single evaluation
|
|
376
|
+
const result = await harness.evaluate(
|
|
377
|
+
'Fix the null pointer exception',
|
|
378
|
+
'def process(data): return data.split()',
|
|
379
|
+
AblationMode.Full
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
console.log(`Success: ${result.success}, Quality: ${result.qualityScore}`);
|
|
383
|
+
|
|
384
|
+
// Run ablation study (Baseline, RetrievalOnly, AdaptersOnly, R+A, Full)
|
|
385
|
+
const report = await harness.runAblationStudy(tasks);
|
|
386
|
+
for (const [mode, metrics] of Object.entries(report.modeMetrics)) {
|
|
387
|
+
console.log(`${mode}: ${metrics.successRate * 100}% success`);
|
|
388
|
+
}
|
|
170
389
|
```
|
|
171
390
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
391
|
+
## mistral-rs Backend (Production Serving)
|
|
392
|
+
|
|
393
|
+
For production deployments with 10-100+ concurrent users, use the mistral-rs backend:
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
import { RuvLLM, MistralBackend, PagedAttentionConfig } from '@ruvector/ruvllm';
|
|
397
|
+
|
|
398
|
+
// Configure for production serving
|
|
399
|
+
const backend = new MistralBackend({
|
|
400
|
+
// PagedAttention: 5-10x more concurrent users
|
|
401
|
+
pagedAttention: {
|
|
402
|
+
blockSize: 16,
|
|
403
|
+
maxBlocks: 4096,
|
|
404
|
+
gpuMemoryFraction: 0.9,
|
|
405
|
+
prefixCaching: true,
|
|
406
|
+
},
|
|
407
|
+
// X-LoRA: Per-token adapter routing
|
|
408
|
+
xlora: {
|
|
409
|
+
adapters: ['./adapters/coder', './adapters/researcher'],
|
|
410
|
+
topK: 2,
|
|
411
|
+
},
|
|
412
|
+
// ISQ: Runtime quantization
|
|
413
|
+
isq: {
|
|
414
|
+
bits: 4,
|
|
415
|
+
method: 'awq',
|
|
416
|
+
},
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
const llm = new RuvLLM({ backend });
|
|
420
|
+
await llm.loadModel('mistralai/Mistral-7B-Instruct-v0.2');
|
|
421
|
+
|
|
422
|
+
// Serve multiple concurrent requests
|
|
423
|
+
const response = await llm.query('Write production code');
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
> **Not in this npm package**: `MistralBackend` is not exported, the
|
|
427
|
+
> `backend` option is ignored (with a `RUVLLM_UNSUPPORTED_OPTION` warning), and
|
|
428
|
+
> `loadModel()` takes a local GGUF path, not a Hub id. mistral-rs serving is a
|
|
429
|
+
> feature of the Rust crate (`mistral-rs` feature).
|
|
430
|
+
|
|
431
|
+
## Supported Models
|
|
432
|
+
|
|
433
|
+
GGUF files loadable with `loadModel()` (architectures llama, mistral, qwen2, qwen3):
|
|
434
|
+
|
|
435
|
+
- **RuvLTRA-Small** (494M) - Q4K, Q5K, Q8
|
|
436
|
+
- **RuvLTRA-Medium** (3B) - Q4K, Q5K, Q8
|
|
437
|
+
- **Qwen 2.5 / Qwen 3** (0.5B-72B)
|
|
438
|
+
- **Llama 3.x** (8B-70B)
|
|
439
|
+
- **Mistral** (7B-22B)
|
|
440
|
+
|
|
441
|
+
Phi-3, Gemma-2 and Qwen3.5 GGUFs are not supported: loading fails with an
|
|
442
|
+
error naming the architecture.
|
|
443
|
+
|
|
444
|
+
## Platform Support
|
|
445
|
+
|
|
446
|
+
The table covers routing, memory and embeddings. Model loading additionally
|
|
447
|
+
needs a native binary built with the `candle` feature (see "Native binary
|
|
448
|
+
requirements").
|
|
449
|
+
|
|
450
|
+
| Platform | Architecture | Status |
|
|
451
|
+
|----------|--------------|--------|
|
|
452
|
+
| macOS | arm64 (M1-M4) | ✅ Full support |
|
|
453
|
+
| macOS | x64 | ✅ Supported |
|
|
454
|
+
| Linux | x64 | ✅ Supported |
|
|
455
|
+
| Linux | arm64 | ✅ Supported |
|
|
456
|
+
| Windows | x64 | ✅ Supported |
|
|
457
|
+
|
|
458
|
+
## Related Packages
|
|
459
|
+
|
|
460
|
+
- [@ruvector/core](https://www.npmjs.com/package/@ruvector/core) - Vector operations
|
|
461
|
+
- [@ruvector/sona](https://www.npmjs.com/package/@ruvector/sona) - SONA learning engine
|
|
462
|
+
- [@ruvector/ruvllm-gpu-loop](https://www.npmjs.com/package/@ruvector/ruvllm-gpu-loop) - RuVLLM GPU job loop, Vast.ai adapter and adapter archives
|
|
463
|
+
- [@ruvector/ruvector](https://www.npmjs.com/package/@ruvector/ruvector) - Full Ruvector SDK
|
|
464
|
+
|
|
465
|
+
## Links
|
|
466
|
+
|
|
467
|
+
- [GitHub Repository](https://github.com/ruvnet/ruvector)
|
|
468
|
+
- [API Documentation](https://docs.rs/ruvllm)
|
|
469
|
+
- [Crate (Rust)](https://crates.io/crates/ruvllm)
|
|
470
|
+
|
|
471
|
+
## License
|
|
472
|
+
|
|
473
|
+
MIT OR Apache-2.0
|