@ruvector/ruvllm 4.0.0 → 4.1.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.
Files changed (171) hide show
  1. package/README.md +449 -158
  2. package/bin/cli.js +1066 -0
  3. package/bin/gpu-delegate.js +67 -0
  4. package/bin/ruvllm-adapters.js +5 -0
  5. package/bin/ruvllm-gpu-loop.js +5 -0
  6. package/bin/serve.js +265 -0
  7. package/dist/cjs/benchmarks/embedding-benchmark.d.ts +102 -0
  8. package/dist/cjs/benchmarks/embedding-benchmark.d.ts.map +1 -0
  9. package/dist/cjs/benchmarks/embedding-benchmark.js +436 -0
  10. package/dist/cjs/benchmarks/index.d.ts +34 -0
  11. package/dist/cjs/benchmarks/index.d.ts.map +1 -0
  12. package/dist/cjs/benchmarks/index.js +132 -0
  13. package/dist/cjs/benchmarks/model-comparison.d.ts +71 -0
  14. package/dist/cjs/benchmarks/model-comparison.d.ts.map +1 -0
  15. package/dist/cjs/benchmarks/model-comparison.js +476 -0
  16. package/dist/cjs/benchmarks/routing-benchmark.d.ts +70 -0
  17. package/dist/cjs/benchmarks/routing-benchmark.d.ts.map +1 -0
  18. package/dist/cjs/benchmarks/routing-benchmark.js +289 -0
  19. package/dist/cjs/contrastive.d.ts +229 -0
  20. package/dist/cjs/contrastive.d.ts.map +1 -0
  21. package/dist/cjs/contrastive.js +589 -0
  22. package/dist/cjs/engine.d.ts +160 -0
  23. package/dist/cjs/engine.d.ts.map +1 -0
  24. package/dist/cjs/engine.js +552 -0
  25. package/dist/cjs/export.d.ts +182 -0
  26. package/dist/cjs/export.d.ts.map +1 -0
  27. package/dist/cjs/export.js +422 -0
  28. package/dist/cjs/federated.d.ts +233 -0
  29. package/dist/cjs/federated.d.ts.map +1 -0
  30. package/dist/cjs/federated.js +525 -0
  31. package/dist/cjs/index.d.ts +68 -0
  32. package/dist/cjs/index.d.ts.map +1 -0
  33. package/dist/cjs/index.js +104 -0
  34. package/dist/cjs/intelligence.d.ts +136 -0
  35. package/dist/cjs/intelligence.d.ts.map +1 -0
  36. package/dist/cjs/intelligence.js +226 -0
  37. package/dist/cjs/lora.d.ts +251 -0
  38. package/dist/cjs/lora.d.ts.map +1 -0
  39. package/dist/cjs/lora.js +509 -0
  40. package/dist/cjs/models.d.ts +129 -0
  41. package/dist/cjs/models.d.ts.map +1 -0
  42. package/dist/cjs/models.js +323 -0
  43. package/dist/cjs/native.d.ts +140 -0
  44. package/dist/cjs/native.d.ts.map +1 -0
  45. package/dist/cjs/native.js +98 -0
  46. package/dist/cjs/session.d.ts +80 -0
  47. package/dist/cjs/session.d.ts.map +1 -0
  48. package/dist/cjs/session.js +203 -0
  49. package/dist/cjs/simd.d.ts +90 -0
  50. package/dist/cjs/simd.d.ts.map +1 -0
  51. package/dist/cjs/simd.js +209 -0
  52. package/dist/cjs/sona.d.ts +223 -0
  53. package/dist/cjs/sona.d.ts.map +1 -0
  54. package/dist/cjs/sona.js +562 -0
  55. package/dist/cjs/streaming.d.ts +55 -0
  56. package/dist/cjs/streaming.d.ts.map +1 -0
  57. package/dist/cjs/streaming.js +131 -0
  58. package/dist/cjs/training.d.ts +312 -0
  59. package/dist/cjs/training.d.ts.map +1 -0
  60. package/dist/cjs/training.js +610 -0
  61. package/dist/cjs/types.d.ts +696 -0
  62. package/dist/cjs/types.d.ts.map +1 -0
  63. package/dist/cjs/types.js +6 -0
  64. package/dist/esm/benchmarks/embedding-benchmark.d.ts +102 -0
  65. package/dist/esm/benchmarks/embedding-benchmark.d.ts.map +1 -0
  66. package/dist/esm/benchmarks/embedding-benchmark.js +427 -0
  67. package/dist/esm/benchmarks/index.d.ts +34 -0
  68. package/dist/esm/benchmarks/index.d.ts.map +1 -0
  69. package/dist/esm/benchmarks/index.js +110 -0
  70. package/dist/esm/benchmarks/model-comparison.d.ts +71 -0
  71. package/dist/esm/benchmarks/model-comparison.d.ts.map +1 -0
  72. package/dist/esm/benchmarks/model-comparison.js +434 -0
  73. package/dist/esm/benchmarks/routing-benchmark.d.ts +70 -0
  74. package/dist/esm/benchmarks/routing-benchmark.d.ts.map +1 -0
  75. package/dist/esm/benchmarks/routing-benchmark.js +283 -0
  76. package/dist/esm/contrastive.d.ts +229 -0
  77. package/dist/esm/contrastive.d.ts.map +1 -0
  78. package/dist/esm/contrastive.js +578 -0
  79. package/dist/esm/engine.d.ts +160 -0
  80. package/dist/esm/engine.d.ts.map +1 -0
  81. package/dist/esm/engine.js +548 -0
  82. package/dist/esm/export.d.ts +182 -0
  83. package/dist/esm/export.d.ts.map +1 -0
  84. package/dist/esm/export.js +414 -0
  85. package/dist/esm/federated.d.ts +233 -0
  86. package/dist/esm/federated.d.ts.map +1 -0
  87. package/dist/esm/federated.js +520 -0
  88. package/dist/esm/index.d.ts +68 -0
  89. package/dist/esm/index.d.ts.map +1 -0
  90. package/dist/esm/index.js +84 -0
  91. package/dist/esm/intelligence.d.ts +136 -0
  92. package/dist/esm/intelligence.d.ts.map +1 -0
  93. package/dist/esm/intelligence.js +188 -0
  94. package/dist/esm/lora.d.ts +251 -0
  95. package/dist/esm/lora.d.ts.map +1 -0
  96. package/dist/esm/lora.js +504 -0
  97. package/dist/esm/models.d.ts +129 -0
  98. package/dist/esm/models.d.ts.map +1 -0
  99. package/dist/esm/models.js +282 -0
  100. package/dist/esm/native.d.ts +140 -0
  101. package/dist/esm/native.d.ts.map +1 -0
  102. package/dist/esm/native.js +100 -0
  103. package/dist/esm/session.d.ts +80 -0
  104. package/dist/esm/session.d.ts.map +1 -0
  105. package/dist/esm/session.js +199 -0
  106. package/dist/esm/simd.d.ts +90 -0
  107. package/dist/esm/simd.d.ts.map +1 -0
  108. package/dist/esm/simd.js +205 -0
  109. package/dist/esm/sona.d.ts +223 -0
  110. package/dist/esm/sona.d.ts.map +1 -0
  111. package/dist/esm/sona.js +556 -0
  112. package/dist/esm/streaming.d.ts +55 -0
  113. package/dist/esm/streaming.d.ts.map +1 -0
  114. package/dist/esm/streaming.js +126 -0
  115. package/dist/esm/training.d.ts +312 -0
  116. package/dist/esm/training.d.ts.map +1 -0
  117. package/dist/esm/training.js +603 -0
  118. package/dist/esm/types.d.ts +696 -0
  119. package/dist/esm/types.d.ts.map +1 -0
  120. package/dist/esm/types.js +5 -0
  121. package/gpu/_load.cjs +38 -0
  122. package/gpu/_load.mjs +33 -0
  123. package/gpu/adapters.cjs +3 -0
  124. package/gpu/adapters.mjs +5 -0
  125. package/gpu/engine.cjs +3 -0
  126. package/gpu/engine.mjs +5 -0
  127. package/gpu/fixture.cjs +3 -0
  128. package/gpu/fixture.mjs +5 -0
  129. package/gpu/gpu-host.cjs +3 -0
  130. package/gpu/gpu-host.mjs +5 -0
  131. package/gpu/gpu-loop.cjs +3 -0
  132. package/gpu/gpu-loop.mjs +5 -0
  133. package/gpu/gpu-spool-adapter.cjs +3 -0
  134. package/gpu/gpu-spool-adapter.mjs +5 -0
  135. package/gpu/vast-host-adapter.cjs +3 -0
  136. package/gpu/vast-host-adapter.mjs +5 -0
  137. package/package.json +159 -49
  138. package/scripts/ensemble-model-compare.js +287 -0
  139. package/scripts/fix-esm-extensions.mjs +220 -0
  140. package/scripts/huggingface/README.md +537 -0
  141. package/scripts/huggingface/publish.sh +112 -0
  142. package/scripts/hybrid-model-compare.js +373 -0
  143. package/scripts/improved-model-compare.js +288 -0
  144. package/scripts/optimized-model-compare.js +364 -0
  145. package/scripts/real-model-compare.js +280 -0
  146. package/scripts/smoke-esm.mjs +82 -0
  147. package/scripts/training/agentic-flow-capabilities.json +329 -0
  148. package/scripts/training/claude-code-synth.js +505 -0
  149. package/scripts/training/claude-flow-capabilities.json +1322 -0
  150. package/scripts/training/claude-hard-negatives.js +222 -0
  151. package/scripts/training/contrastive-finetune.js +517 -0
  152. package/scripts/training/ecosystem-triplets.jsonl +1467 -0
  153. package/scripts/training/generate-ecosystem-triplets.js +1324 -0
  154. package/scripts/training/routing-dataset.js +634 -0
  155. package/scripts/training/ruvector-capabilities.json +798 -0
  156. package/scripts/training/validate-ecosystem.js +381 -0
  157. package/scripts/training/validation-results.json +23 -0
  158. package/GPU-LOOP.md +0 -229
  159. package/LICENSE +0 -201
  160. package/NOTICE +0 -9
  161. package/examples/gpu-loop.example.json +0 -26
  162. package/src/adapters-cli.mjs +0 -23
  163. package/src/adapters.mjs +0 -91
  164. package/src/cli.mjs +0 -30
  165. package/src/engine.mjs +0 -238
  166. package/src/fixture.mjs +0 -38
  167. package/src/gpu-host.mjs +0 -47
  168. package/src/gpu-loop-cli.mjs +0 -67
  169. package/src/gpu-loop.mjs +0 -184
  170. package/src/gpu-spool-adapter.mjs +0 -80
  171. package/src/vast-host-adapter.mjs +0 -274
package/README.md CHANGED
@@ -1,183 +1,474 @@
1
- # MetaHarness weight experiments
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
+ [![npm version](https://img.shields.io/npm/v/@ruvector/ruvllm.svg)](https://www.npmjs.com/package/@ruvector/ruvllm)
6
+ [![Downloads](https://img.shields.io/npm/dm/@ruvector/ruvllm)](https://www.npmjs.com/package/@ruvector/ruvllm)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
8
+ [![GitHub Stars](https://img.shields.io/github/stars/ruvnet/ruvector?style=social)](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
- Published on npm as `@ruvector/ruvllm`. Version 4.0.0 replaces the 3.x
4
- inference runtime from `ruvnet/ruvector` with this package, because ruvllm now
5
- lives in `ruvnet/ruvllm`. The 3.x API and its CLI subcommands are not part of
6
- 4.x; pin `@ruvector/ruvllm@3` to keep using them. The npm package ships the
7
- JavaScript controller, GPU loop and Vast.ai host adapter. It does not ship the
8
- native `weight_evolution` binary, model weights or adapters. Build the binary
9
- from this repository and pass its path with `--binary`.
52
+ ## Quick Start
10
53
 
11
- ```sh
12
- npm install @ruvector/ruvllm
13
- npx ruvllm --help # bounded weight-edit experiments
14
- npx ruvllm-gpu-loop status --config /abs/private/gpu-loop.json
54
+ ```typescript
55
+ import { RuvLLM, RuvLLMConfig } from '@ruvector/ruvllm';
56
+
57
+ // Initialize with default configuration
58
+ const llm = new RuvLLM();
59
+
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');
15
68
  ```
16
69
 
17
- Run multiple bounded RuVLLM edits against one unchanged checkpoint, validate
18
- supplied evaluations, package RVF evidence, restore every patched checkpoint,
19
- and rank research-qualified candidates through MetaHarness. This controller
20
- uses the actual Flywheel, Darwin and Weight-EFT packages pinned in
21
- [package-lock.json](package-lock.json).
22
-
23
- The runner does not perform inference, discover an effective weight edit, train
24
- an adapter or activate a model. CPU fixtures exercise real file editing and
25
- restoration with explicitly synthetic evaluation receipts. External evaluation
26
- files remain caller-supplied evidence; hashes do not authenticate their origin.
27
-
28
- ## Install and run the CPU fixture
29
-
30
- Requirements: Linux or macOS, Node 22+, Python 3.12+, a C linker, and Rust 1.97.1
31
- as pinned by `native/rust-toolchain.toml`. Activate any locally installed Rust
32
- toolchain before using Cargo. From the repository root:
33
-
34
- ```sh
35
- (cd integrations/metaharness && npm ci --ignore-scripts)
36
- (cd native && cargo build --locked --release --bin weight_evolution)
37
- python3 native/verify_source.py
38
- node integrations/metaharness/src/cli.mjs fixture \
39
- --dir "$PWD/runtime/metaharness-fixture" \
40
- --binary "$PWD/native/target/release/weight_evolution"
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' }
41
86
  ```
42
87
 
43
- Create the fixture's parent directory first (`mkdir -p runtime`). Its own directory
44
- must not exist: exclusive creation prevents accidental replacement. For another
45
- fixture use a new directory. The report should select `fixture-improvement`, leave
46
- `unevaluated-control` unqualified, verify RVF and exact rollback for both, and
47
- report `inferencePerformed: false`, `independentConfirmation: false` and
48
- `productionActivation: false`. A selected synthetic candidate says nothing about
49
- actual model accuracy.
50
-
51
- ## Configure real experiment inputs
52
-
53
- Prepare reviewed source checkpoint, patch, policy and optional evaluation JSON
54
- under explicit input roots. Native request/data contracts are described in the
55
- [native guide](../../native/README.md). Patch generation remains model specific;
56
- the controller does not guess useful tensor edits.
57
-
58
- Run the project-local installer with paths you control:
59
-
60
- ```sh
61
- bash scripts/install-metaharness.sh \
62
- --config-dir /absolute/private/operator-profile \
63
- --read-root /absolute/checkpoints \
64
- --read-root /absolute/experiment-inputs \
65
- --policy /absolute/experiment-inputs/policy.json \
66
- --output-root /absolute/private/experiment-outputs
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>` 3.x (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
67
133
  ```
68
134
 
69
- It installs frozen npm dependencies without lifecycle scripts, builds the native
70
- binary, verifies native provenance and runs its smoke fixture. It creates a
71
- private runtime profile and Claude launcher without changing global settings.
72
- Repeat `--read-root`/`--policy` for additional approved inputs. Existing profile
73
- files are never replaced; use another directory for a new profile. Existing config
74
- and output directories must be owner-only. `--configure-only` skips installation
75
- and building but still checks native readiness.
76
-
77
- Example plan inside an approved read root:
78
-
79
- ```json
80
- {
81
- "schema": "ruvllm-experiment-plan/v1",
82
- "evidenceMode": "external",
83
- "source": "/absolute/checkpoints/source.safetensors",
84
- "policy": "/absolute/experiment-inputs/policy.json",
85
- "candidates": [
86
- {
87
- "id": "candidate-01",
88
- "patch": "/absolute/experiment-inputs/patch.json",
89
- "evaluation": "/absolute/experiment-inputs/evaluation.json"
90
- }
91
- ]
135
+ The platform packages on npm are still 2.0.1, so on a plain `npm install`
136
+ `loadModel()` (and therefore `query`/`generate` with `--model` and
137
+ `ruvllm serve`) fails with `RUVLLM_NATIVE_TOO_OLD`. Routing, memory,
138
+ embeddings, SONA, LoRA and training work with them. Until rebuilt platform
139
+ packages ship, build the binary from source as above, or use the Rust
140
+ `ruvllm-cli` (`ruvllm serve <model>`, an OpenAI-compatible server).
141
+
142
+ | Error code | Meaning |
143
+ |------------|---------|
144
+ | `RUVLLM_NO_LANGUAGE_MODEL` | Generation was requested with no model loaded |
145
+ | `RUVLLM_NATIVE_UNAVAILABLE` | No native binary could be loaded |
146
+ | `RUVLLM_NATIVE_TOO_OLD` | The native binary predates model loading (2.0.x platform packages) |
147
+ | `RUVLLM_NO_INFERENCE_BACKEND` | The native binary was built without the `candle` backend |
148
+ | `RUVLLM_MODEL_NOT_FOUND` | The model path does not exist |
149
+ | `RUVLLM_MODEL_LOAD_FAILED` | The file could not be loaded (unsupported architecture, not GGUF, ...) |
150
+ | `RUVLLM_TOKENIZER_MISSING` | Weights loaded but no usable tokenizer was found |
151
+
152
+ ## What's New in v2.5
153
+
154
+ | Feature | Description |
155
+ |---------|-------------|
156
+ | **TurboQuant KV-Cache** | 2-4 bit asymmetric quantization with per-channel scale/zero-point — 6-8x memory reduction, <0.5% perplexity loss |
157
+ | **TurboQuant Embedding Store** | Quantized vector storage with compressed search — 10-30x memory savings |
158
+ | **H2O / PyramidKV Eviction** | Intelligent cache eviction policies for long-context inference |
159
+ | **Optimized Inner Product** | Asymmetric distance on quantized data — skip decompression for 2-4x faster search |
160
+ | **RuvLTRA Models** | Purpose-built 0.5B & 3B models for Claude Flow |
161
+ | **Task-Specific LoRA** | 5 pre-trained adapters (coder, researcher, security, architect, reviewer) |
162
+ | **HuggingFace Hub** | Download/upload models directly |
163
+ | **Adapter Merging** | TIES, DARE, SLERP strategies |
164
+ | **HNSW Routing** | 150x faster semantic matching |
165
+ | **Evaluation Harness** | SWE-Bench testing with 5 ablation modes |
166
+ | **mistral-rs Backend** | Production serving with PagedAttention, X-LoRA, ISQ |
167
+
168
+ ## TurboQuant — KV-Cache Compression
169
+
170
+ Reduce inference memory by 6-8x with <0.5% quality loss:
171
+
172
+ ```typescript
173
+ import { simd } from '@ruvector/ruvllm/simd';
174
+
175
+ // TurboQuant compresses KV-cache entries at 2-4 bit precision
176
+ // with per-channel asymmetric quantization (scale + zero-point).
177
+ // Eviction policies (H2O, Sliding Window, PyramidKV) keep the
178
+ // most important tokens in cache during long-context generation.
179
+
180
+ // Supported bit widths: 2-bit (32x), 3-bit (10.7x), 4-bit (8x), 8-bit (4x)
181
+ ```
182
+
183
+ | Bits | Compression | Perplexity Loss | Use Case |
184
+ |------|-------------|-----------------|----------|
185
+ | 2-bit | 32x | ~2% | Maximum compression, edge devices |
186
+ | 3-bit | 10.7x | <1% | Balanced — recommended for most uses |
187
+ | 4-bit | 8x | <0.5% | High quality, long-context inference |
188
+ | 8-bit | 4x | ~0% | Baseline quantization |
189
+
190
+ ## CLI Usage
191
+
192
+ ```bash
193
+ # Query a model (this package's `ruvllm` bin; needs --model, see above)
194
+ ruvllm query "What is machine learning?" --model ./qwen2.5-0.5b-instruct-q4_k_m.gguf
195
+
196
+ # The commands below are the Rust ruvllm CLI (crate ruvllm-cli)
197
+ # Stream output
198
+ ruvllm query --stream "Write a poem"
199
+
200
+ # Download a model
201
+ ruvllm download ruvector/ruvltra-small-q4km
202
+
203
+ # Benchmark
204
+ ruvllm bench ./models/model.gguf
205
+
206
+ # Run evaluation (SWE-Bench)
207
+ ruvllm eval --model ./models/model.gguf --subset lite --max-tasks 50
208
+ ```
209
+
210
+ ## HTTP server: `ruvllm serve`
211
+
212
+ `ruvllm serve` runs a local LLM server over a GGUF model, on
213
+ `127.0.0.1:3000` by default (`--host`, `--port`, `--max-context`,
214
+ `--max-tokens`, `--temperature`). It is the endpoint the
215
+ [ruflo / claude-flow](https://github.com/ruvnet/claude-flow) RuVector provider
216
+ calls:
217
+
218
+ ```bash
219
+ npx @ruvector/ruvllm serve ./qwen2.5-0.5b-instruct-q4_k_m.gguf
220
+ curl -s localhost:3000/health
221
+ curl -s localhost:3000/query -H 'content-type: application/json' -d '{"query":"What is HNSW?"}'
222
+ curl -s localhost:3000/v1/chat/completions -H 'content-type: application/json' \
223
+ -d '{"messages":[{"role":"user","content":"Hello"}],"max_tokens":32}'
224
+ ```
225
+
226
+ | Endpoint | Body / response |
227
+ | :--- | :--- |
228
+ | `GET /health` | `{ status, model, modelLoaded, native, sona, hnsw, version }` |
229
+ | `GET /v1/models` | OpenAI-style model list |
230
+ | `POST /query` | `{ query, session_id? }` → `{ id, model, content, done, usage, router_metrics }` |
231
+ | `POST /v1/chat/completions` | OpenAI chat format; `stream: true` returns the finished completion as one SSE chunk, then `[DONE]` |
232
+
233
+ The server is strict: it starts only after the model loads, and exits 1
234
+ otherwise (no placeholder answers, so clients such as ruflo fall back to
235
+ another provider instead of receiving non-model text). Generation is
236
+ synchronous, so requests are answered one at a time.
237
+
238
+ ## GPU job loop: `ruvllm gpu`
239
+
240
+ The RuVLLM GPU job loop schedules bounded GPU jobs (spending ceiling, destroy
241
+ timer, confirmed cleanup) on a Vast.ai host, packages LoRA adapter archives
242
+ and runs bounded weight-edit experiments. It lives in
243
+ [`@ruvector/ruvllm-gpu-loop`](https://www.npmjs.com/package/@ruvector/ruvllm-gpu-loop)
244
+ ([source](https://github.com/ruvnet/ruvllm/tree/main/integrations/metaharness));
245
+ this package exposes it as:
246
+
247
+ ```bash
248
+ npx ruvllm gpu loop status --config /abs/private/gpu-loop.json # = ruvllm-gpu-loop
249
+ npx ruvllm gpu adapters training-plan < plan.json # = ruvllm-adapters
250
+ npx ruvllm gpu fixture --dir /abs/new-dir --binary /abs/weight_evolution
251
+ ```
252
+
253
+ ```js
254
+ import { tickLoop, readLoopStatus } from '@ruvector/ruvllm/gpu-loop';
255
+ import { createVastAdapter } from '@ruvector/ruvllm/vast-host-adapter';
256
+ ```
257
+
258
+ ## API Reference
259
+
260
+ ### RuvLLM Class
261
+
262
+ ```typescript
263
+ class RuvLLM {
264
+ constructor(config?: RuvLLMConfig);
265
+
266
+ // Language model (see "Text Generation" above)
267
+ loadModel(path: string, options?: LoadModelOptions): LoadedModelInfo;
268
+ unloadModel(): void;
269
+ isModelLoaded(): boolean;
270
+ modelInfo(): LoadedModelInfo | null;
271
+ supportsModelLoading(): boolean; // native binary can load models
272
+
273
+ // Generation; all throw RUVLLM_NO_LANGUAGE_MODEL without a loaded model
274
+ chat(messages: ChatMessage[], config?: GenerationConfig): GenerationResult;
275
+ generateDetailed(prompt: string, config?: GenerationConfig): GenerationResult;
276
+ generate(prompt: string, config?: GenerationConfig): string;
277
+ query(text: string, config?: GenerationConfig): QueryResponse; // routed, + token usage
278
+
279
+ // Routing, memory and embeddings
280
+ route(text: string): RoutingDecision;
281
+ addMemory(content: string, metadata?: Record<string, unknown>): MemoryId;
282
+ searchMemory(text: string, k?: number): MemoryResult[];
283
+ embed(text: string): Embedding;
284
+
285
+ // Not in this package: token streaming (StreamingGenerator chunks a
286
+ // finished generate() result), mistral-rs backends.
287
+
288
+ // Get SONA learning stats
289
+ sonaStats(): SonaStats | null;
290
+
291
+ // Adapt on feedback
292
+ adapt(input: Float32Array, quality: number): void;
293
+ }
294
+ ```
295
+
296
+ ### Configuration
297
+
298
+ ```typescript
299
+ interface RuvLLMConfig {
300
+ modelPath?: string; // GGUF to load in the constructor (throws if it cannot be loaded)
301
+ modelOptions?: LoadModelOptions; // { maxContext?: number } for modelPath
302
+ allowPlaceholder?: boolean; // generate()/query() return PLACEHOLDER_TEXT instead of
303
+ // throwing when no model is loaded (default: false)
304
+ strict?: boolean; // Throw instead of warning for unsupported options (`backend`)
305
+ // ...plus routing/memory options (embeddingDim, hnswM, ...), see types.ts
306
+ }
307
+ ```
308
+
309
+ ### Generation Config and Result
310
+
311
+ ```typescript
312
+ interface GenerationConfig {
313
+ maxTokens?: number; // default 256
314
+ temperature?: number; // default 0.7; 0 = greedy
315
+ topP?: number; // default 0.9, in (0, 1]
316
+ topK?: number; // default 50; 0 disables
317
+ repetitionPenalty?: number; // default 1.1
318
+ stopSequences?: string[]; // stop text is not included in the output
319
+ seed?: number; // reproducible sampling at temperature > 0
320
+ }
321
+
322
+ interface GenerationResult {
323
+ text: string;
324
+ promptTokens: number; // after the chat template, for chat()
325
+ completionTokens: number; // includes an end-of-sequence token that ended generation
326
+ finishReason: 'stop' | 'length' | 'cancelled';
92
327
  }
93
328
  ```
94
329
 
95
- ```sh
96
- node integrations/metaharness/src/cli.mjs run \
97
- --config /absolute/private/operator-profile/runtime.json \
98
- --plan /absolute/experiment-inputs/plan.json
330
+ ## SIMD Module
331
+
332
+ For direct access to optimized SIMD kernels:
333
+
334
+ ```typescript
335
+ import { simd } from '@ruvector/ruvllm/simd';
336
+
337
+ // Dot product
338
+ const result = simd.dotProduct(vecA, vecB);
339
+
340
+ // Matrix multiplication
341
+ const output = simd.matmul(matrix, vector);
342
+
343
+ // Flash Attention
344
+ const attended = simd.flashAttention(query, key, value, scale);
345
+
346
+ // RMS Normalization
347
+ simd.rmsNorm(hidden, weights, epsilon);
99
348
  ```
100
349
 
101
- Omit `evaluation` to run mechanical checks without qualification. After an external
102
- inference runner has evaluated a candidate, submit its hash-bound evaluation in a
103
- new plan/run. Candidate checkpoint hashes are deterministic for the same patch;
104
- new artifact paths do not relax identity checks. Paired baseline, protocol, suite,
105
- runtime, precision and output-budget consistency remain the evaluator's responsibility.
350
+ ## Performance (M4 Pro)
351
+
352
+ | Operation | Performance |
353
+ |-----------|-------------|
354
+ | Inference | 88-135 tok/s |
355
+ | Flash Attention | 320µs (seq=2048) |
356
+ | HNSW Search | 17-62µs |
357
+ | SONA Adapt | <1ms |
358
+ | Evaluation | 5 ablation modes |
106
359
 
107
- Runs use new private `run-*` directories and preserve rejected candidates. Reports
108
- bind config/plan/source/policy/binary/gate/patch/evaluation identities and record
109
- rollback and RVF verification. Native rejection records a reason. Structural or
110
- restoration failures abort; interrupted runs can leave artifacts. Reconcile those
111
- directories before retrying; never erase failed evidence to manufacture success.
360
+ ## Evaluation Harness
112
361
 
113
- ## Claude Code and Ruflo
362
+ > **Not in this npm package**: `EvaluationHarness` and `AblationMode` are
363
+ > not exported by `@ruvector/ruvllm`. The sketch below shows the intended API.
114
364
 
115
- Load [ruflo-metaharness](../../plugins/ruflo-metaharness/README.md) using the
116
- generated `launch-claude.sh`, or set `RUVLLM_EXPERIMENT_CONFIG` and use Claude's
117
- `--plugin-dir`. The `/ruflo-metaharness:weight-experiment` command and reviewer
118
- agent guide the bounded workflow. Its single MCP tool accepts a plan path; the
119
- model cannot override the operator configuration. The same stdio server can be
120
- registered in a Ruflo project's MCP configuration. Portable wire tests exercise
121
- the real engine; installed Claude/Ruflo client acceptance is separate.
365
+ Run model evaluations with SWE-Bench integration:
122
366
 
123
- ## Scheduled GPU work
367
+ ```typescript
368
+ import { RuvLLM, EvaluationHarness, AblationMode } from '@ruvector/ruvllm';
124
369
 
125
- For scheduled GPU work, use the [durable GPU loop](GPU-LOOP.md). It supports
126
- host-owned ruOS secret references, Vast job descriptors, persisted reservations,
127
- deadline-aware polling and confirmed cleanup. Local contract tests require no
128
- live provider. The bundled file handoff keeps requests pending for a trusted host.
370
+ const harness = new EvaluationHarness({
371
+ modelPath: './models/model.gguf',
372
+ enableHnsw: true,
373
+ enableSona: true,
374
+ });
129
375
 
130
- ## Weight-EFT data and plans
376
+ // Run single evaluation
377
+ const result = await harness.evaluate(
378
+ 'Fix the null pointer exception',
379
+ 'def process(data): return data.split()',
380
+ AblationMode.Full
381
+ );
131
382
 
132
- The data-only adapter CLI reads JSON stdin, with a 16 MiB bound:
383
+ console.log(`Success: ${result.success}, Quality: ${result.qualityScore}`);
133
384
 
134
- ```sh
135
- node integrations/metaharness/src/adapters-cli.mjs export < reviewed-archive-input.json > export.json
136
- node integrations/metaharness/src/adapters-cli.mjs training-plan < training-input.json > plan.json
137
- node integrations/metaharness/src/adapters-cli.mjs select < measured-candidates.json > selection.json
385
+ // Run ablation study (Baseline, RetrievalOnly, AdaptersOnly, R+A, Full)
386
+ const report = await harness.runAblationStudy(tasks);
387
+ for (const [mode, metrics] of Object.entries(report.modeMetrics)) {
388
+ console.log(`${mode}: ${metrics.successRate * 100}% success`);
389
+ }
138
390
  ```
139
391
 
140
- `export` takes `{archive, evalHoldout, maxTokens?}`. Archive entries follow the
141
- pinned Weight-EFT `DarwinTrajectory` contract (`instance_id`, `model`, `tier`,
142
- boolean `resolved`, `messages`, `model_patch`). All actual evaluation instance IDs
143
- must be in `evalHoldout`. Output contains standard `sft`/`dpo` arrays, drop reports
144
- and input hashes. Reward-hacking filtering stays enabled, overlength traces are
145
- dropped, and tool calls are preserved. These filters cannot authenticate outcomes
146
- or detect all semantic contamination.
147
-
148
- `training-plan` takes `{base:{id,paramsB},sftPath,dpoPath,adapterPrefix}`. It emits
149
- upstream plans plus `executionStatus: not_executed` and
150
- `runnerCompatibility: adapter-required`. This repository has no upstream
151
- `ruvllm microlora` executable. Its existing fixed CUDA/PEFT experiment runner is
152
- not a configurable SFT/DPO trainer. No GPU, model download or paid job is started.
153
-
154
- `select` takes `{baseline,candidates,envelope}` with entries
155
- `{id,score,evidenceSha256}`. It replays finite, supplied scores through Darwin's
156
- contrastive engine. It is development ranking with an immutable envelope and no
157
- independent confirmation; it cannot authenticate caller-supplied evidence. The
158
- native runner applies its stricter qualification first.
159
-
160
- ## Tests and benchmark
161
-
162
- ```sh
163
- (cd integrations/metaharness && npm test)
164
- node --test plugins/ruflo-metaharness/test/*.test.mjs
165
- node integrations/metaharness/bench/run.mjs --iterations 7 --warmup 2 --candidates 2
392
+ ## mistral-rs Backend (Production Serving)
393
+
394
+ For production deployments with 10-100+ concurrent users, use the mistral-rs backend:
395
+
396
+ ```typescript
397
+ import { RuvLLM, MistralBackend, PagedAttentionConfig } from '@ruvector/ruvllm';
398
+
399
+ // Configure for production serving
400
+ const backend = new MistralBackend({
401
+ // PagedAttention: 5-10x more concurrent users
402
+ pagedAttention: {
403
+ blockSize: 16,
404
+ maxBlocks: 4096,
405
+ gpuMemoryFraction: 0.9,
406
+ prefixCaching: true,
407
+ },
408
+ // X-LoRA: Per-token adapter routing
409
+ xlora: {
410
+ adapters: ['./adapters/coder', './adapters/researcher'],
411
+ topK: 2,
412
+ },
413
+ // ISQ: Runtime quantization
414
+ isq: {
415
+ bits: 4,
416
+ method: 'awq',
417
+ },
418
+ });
419
+
420
+ const llm = new RuvLLM({ backend });
421
+ await llm.loadModel('mistralai/Mistral-7B-Instruct-v0.2');
422
+
423
+ // Serve multiple concurrent requests
424
+ const response = await llm.query('Write production code');
166
425
  ```
167
426
 
168
- Tests require the built native binary. In restricted agent environments the Node
169
- test runner, native child processes and package fetching may require the host's
170
- supported execution permission. Verify actual subtest counts; a file-only runner
171
- summary is insufficient evidence. Do not disable TLS/checksums or native checks.
172
-
173
- The benchmark compares fresh versus reused Node processes on identical CPU
174
- fixtures, retaining raw latency samples and implementation/binary/lock hashes.
175
- The reused process matches the MCP server architecture. All native hashing,
176
- patch validation and byte restoration remain enabled. See the
177
- [benchmark report](../../docs/benchmarks/metaharness-cpu.md) for measured scope
178
- and limits; no model-performance claim follows from orchestration speed.
179
-
180
- Architecture and threat boundaries are recorded in
181
- [ADR 012](../../docs/adr/ADR-012-metaharness-bounded-experiment-runner.md),
182
- [ADR 013](../../docs/adr/ADR-013-training-and-development-selection.md) and
183
- [ADR 014](../../docs/adr/ADR-014-claude-ruflo-integration.md).
427
+ > **Not in this npm package**: `MistralBackend` is not exported, the
428
+ > `backend` option is ignored (with a `RUVLLM_UNSUPPORTED_OPTION` warning), and
429
+ > `loadModel()` takes a local GGUF path, not a Hub id. mistral-rs serving is a
430
+ > feature of the Rust crate (`mistral-rs` feature).
431
+
432
+ ## Supported Models
433
+
434
+ GGUF files loadable with `loadModel()` (architectures llama, mistral, qwen2, qwen3):
435
+
436
+ - **RuvLTRA-Small** (494M) - Q4K, Q5K, Q8
437
+ - **RuvLTRA-Medium** (3B) - Q4K, Q5K, Q8
438
+ - **Qwen 2.5 / Qwen 3** (0.5B-72B)
439
+ - **Llama 3.x** (8B-70B)
440
+ - **Mistral** (7B-22B)
441
+
442
+ Phi-3, Gemma-2 and Qwen3.5 GGUFs are not supported: loading fails with an
443
+ error naming the architecture.
444
+
445
+ ## Platform Support
446
+
447
+ The table covers routing, memory and embeddings. Model loading additionally
448
+ needs a native binary built with the `candle` feature (see "Native binary
449
+ requirements").
450
+
451
+ | Platform | Architecture | Status |
452
+ |----------|--------------|--------|
453
+ | macOS | arm64 (M1-M4) | ✅ Full support |
454
+ | macOS | x64 | ✅ Supported |
455
+ | Linux | x64 | ✅ Supported |
456
+ | Linux | arm64 | ✅ Supported |
457
+ | Windows | x64 | ✅ Supported |
458
+
459
+ ## Related Packages
460
+
461
+ - [@ruvector/core](https://www.npmjs.com/package/@ruvector/core) - Vector operations
462
+ - [@ruvector/sona](https://www.npmjs.com/package/@ruvector/sona) - SONA learning engine
463
+ - [@ruvector/ruvllm-gpu-loop](https://www.npmjs.com/package/@ruvector/ruvllm-gpu-loop) - RuVLLM GPU job loop, Vast.ai adapter and adapter archives
464
+ - [@ruvector/ruvector](https://www.npmjs.com/package/@ruvector/ruvector) - Full Ruvector SDK
465
+
466
+ ## Links
467
+
468
+ - [GitHub Repository](https://github.com/ruvnet/ruvector)
469
+ - [API Documentation](https://docs.rs/ruvllm)
470
+ - [Crate (Rust)](https://crates.io/crates/ruvllm)
471
+
472
+ ## License
473
+
474
+ MIT OR Apache-2.0