@ruvector/ruvllm 0.2.3 → 2.4.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 (94) hide show
  1. package/README.md +379 -739
  2. package/bin/cli.js +619 -2
  3. package/dist/cjs/benchmarks/embedding-benchmark.d.ts +102 -0
  4. package/dist/cjs/benchmarks/embedding-benchmark.d.ts.map +1 -0
  5. package/dist/cjs/benchmarks/embedding-benchmark.js +436 -0
  6. package/dist/cjs/benchmarks/index.d.ts +34 -0
  7. package/dist/cjs/benchmarks/index.d.ts.map +1 -0
  8. package/dist/cjs/benchmarks/index.js +132 -0
  9. package/dist/cjs/benchmarks/model-comparison.d.ts +71 -0
  10. package/dist/cjs/benchmarks/model-comparison.d.ts.map +1 -0
  11. package/dist/cjs/benchmarks/model-comparison.js +476 -0
  12. package/dist/cjs/benchmarks/routing-benchmark.d.ts +70 -0
  13. package/dist/cjs/benchmarks/routing-benchmark.d.ts.map +1 -0
  14. package/dist/cjs/benchmarks/routing-benchmark.js +289 -0
  15. package/dist/cjs/contrastive.d.ts +229 -0
  16. package/dist/cjs/contrastive.d.ts.map +1 -0
  17. package/dist/cjs/contrastive.js +589 -0
  18. package/dist/cjs/engine.d.ts +3 -0
  19. package/dist/cjs/engine.d.ts.map +1 -1
  20. package/dist/cjs/engine.js +29 -9
  21. package/dist/cjs/index.d.ts +4 -0
  22. package/dist/cjs/index.d.ts.map +1 -1
  23. package/dist/cjs/index.js +9 -1
  24. package/dist/cjs/models.d.ts +129 -0
  25. package/dist/cjs/models.d.ts.map +1 -0
  26. package/dist/cjs/models.js +323 -0
  27. package/dist/cjs/rlm/controller.d.ts +245 -0
  28. package/dist/cjs/rlm/controller.d.ts.map +1 -0
  29. package/dist/cjs/rlm/controller.js +554 -0
  30. package/dist/cjs/rlm/index.d.ts +62 -0
  31. package/dist/cjs/rlm/index.d.ts.map +1 -0
  32. package/dist/cjs/rlm/index.js +97 -0
  33. package/dist/cjs/rlm/training.d.ts +333 -0
  34. package/dist/cjs/rlm/training.d.ts.map +1 -0
  35. package/dist/cjs/rlm/training.js +680 -0
  36. package/dist/cjs/rlm/types.d.ts +189 -0
  37. package/dist/cjs/rlm/types.d.ts.map +1 -0
  38. package/dist/cjs/rlm/types.js +10 -0
  39. package/dist/esm/benchmarks/embedding-benchmark.d.ts +102 -0
  40. package/dist/esm/benchmarks/embedding-benchmark.d.ts.map +1 -0
  41. package/dist/esm/benchmarks/embedding-benchmark.js +427 -0
  42. package/dist/esm/benchmarks/index.d.ts +34 -0
  43. package/dist/esm/benchmarks/index.d.ts.map +1 -0
  44. package/dist/esm/benchmarks/index.js +110 -0
  45. package/dist/esm/benchmarks/model-comparison.d.ts +71 -0
  46. package/dist/esm/benchmarks/model-comparison.d.ts.map +1 -0
  47. package/dist/esm/benchmarks/model-comparison.js +434 -0
  48. package/dist/esm/benchmarks/routing-benchmark.d.ts +70 -0
  49. package/dist/esm/benchmarks/routing-benchmark.d.ts.map +1 -0
  50. package/dist/esm/benchmarks/routing-benchmark.js +283 -0
  51. package/dist/esm/contrastive.d.ts +229 -0
  52. package/dist/esm/contrastive.d.ts.map +1 -0
  53. package/dist/esm/contrastive.js +578 -0
  54. package/dist/esm/engine.d.ts +3 -0
  55. package/dist/esm/engine.d.ts.map +1 -1
  56. package/dist/esm/engine.js +29 -9
  57. package/dist/esm/index.d.ts +4 -0
  58. package/dist/esm/index.d.ts.map +1 -1
  59. package/dist/esm/index.js +9 -1
  60. package/dist/esm/models.d.ts +129 -0
  61. package/dist/esm/models.d.ts.map +1 -0
  62. package/dist/esm/models.js +282 -0
  63. package/dist/esm/rlm/controller.d.ts +245 -0
  64. package/dist/esm/rlm/controller.d.ts.map +1 -0
  65. package/dist/esm/rlm/controller.js +550 -0
  66. package/dist/esm/rlm/index.d.ts +62 -0
  67. package/dist/esm/rlm/index.d.ts.map +1 -0
  68. package/dist/esm/rlm/index.js +71 -0
  69. package/dist/esm/rlm/training.d.ts +333 -0
  70. package/dist/esm/rlm/training.d.ts.map +1 -0
  71. package/dist/esm/rlm/training.js +672 -0
  72. package/dist/esm/rlm/types.d.ts +189 -0
  73. package/dist/esm/rlm/types.d.ts.map +1 -0
  74. package/dist/esm/rlm/types.js +9 -0
  75. package/package.json +13 -11
  76. package/scripts/ensemble-model-compare.js +287 -0
  77. package/scripts/huggingface/README.md +537 -0
  78. package/scripts/huggingface/publish.sh +112 -0
  79. package/scripts/hybrid-model-compare.js +373 -0
  80. package/scripts/improved-model-compare.js +288 -0
  81. package/scripts/optimized-model-compare.js +364 -0
  82. package/scripts/real-model-compare.js +280 -0
  83. package/scripts/training/agentic-flow-capabilities.json +329 -0
  84. package/scripts/training/claude-code-synth.js +505 -0
  85. package/scripts/training/claude-flow-capabilities.json +1322 -0
  86. package/scripts/training/claude-hard-negatives.js +222 -0
  87. package/scripts/training/contrastive-finetune.js +517 -0
  88. package/scripts/training/ecosystem-triplets.jsonl +1467 -0
  89. package/scripts/training/generate-ecosystem-triplets.js +1324 -0
  90. package/scripts/training/rlm-dataset.js +671 -0
  91. package/scripts/training/routing-dataset.js +634 -0
  92. package/scripts/training/ruvector-capabilities.json +798 -0
  93. package/scripts/training/validate-ecosystem.js +381 -0
  94. package/scripts/training/validation-results.json +23 -0
@@ -0,0 +1,189 @@
1
+ /**
2
+ * RLM (Retrieval Language Model) Type Definitions
3
+ *
4
+ * Types for the recursive retrieval-augmented generation system
5
+ * that breaks down complex queries into sub-queries and synthesizes
6
+ * answers from retrieved memory spans.
7
+ */
8
+ /**
9
+ * Configuration for the RLM controller
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const config: RlmConfig = {
14
+ * maxDepth: 3,
15
+ * maxSubQueries: 5,
16
+ * tokenBudget: 4096,
17
+ * enableCache: true,
18
+ * cacheTtl: 300000, // 5 minutes
19
+ * retrievalTopK: 10,
20
+ * minQualityScore: 0.7,
21
+ * enableReflection: true,
22
+ * maxReflectionIterations: 2,
23
+ * };
24
+ * ```
25
+ */
26
+ export interface RlmConfig {
27
+ /** Maximum recursion depth for sub-queries (default: 3) */
28
+ maxDepth?: number;
29
+ /** Maximum number of sub-queries per level (default: 5) */
30
+ maxSubQueries?: number;
31
+ /** Token budget for generation (default: 4096) */
32
+ tokenBudget?: number;
33
+ /** Enable response caching (default: true) */
34
+ enableCache?: boolean;
35
+ /** Cache TTL in milliseconds (default: 300000 = 5 minutes) */
36
+ cacheTtl?: number;
37
+ /** Number of memory spans to retrieve (default: 10) */
38
+ retrievalTopK?: number;
39
+ /** Minimum quality score to accept answer (default: 0.7) */
40
+ minQualityScore?: number;
41
+ /** Enable self-reflection loop (default: false) */
42
+ enableReflection?: boolean;
43
+ /** Maximum reflection iterations (default: 2) */
44
+ maxReflectionIterations?: number;
45
+ }
46
+ /**
47
+ * Answer produced by the RLM controller
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const answer: RlmAnswer = {
52
+ * text: 'Machine learning is a subset of artificial intelligence...',
53
+ * confidence: 0.92,
54
+ * qualityScore: 0.88,
55
+ * sources: [
56
+ * { id: 'mem-1', text: 'ML definition from textbook', similarityScore: 0.95, metadata: {} },
57
+ * ],
58
+ * subQueries: [
59
+ * { query: 'What is artificial intelligence?', answer: 'AI is...', depth: 1 },
60
+ * ],
61
+ * tokenUsage: { prompt: 512, completion: 256, total: 768 },
62
+ * cached: false,
63
+ * };
64
+ * ```
65
+ */
66
+ export interface RlmAnswer {
67
+ /** The generated answer text */
68
+ text: string;
69
+ /** Overall confidence in the answer (0.0 - 1.0) */
70
+ confidence: number;
71
+ /** Quality score based on source coverage and coherence (0.0 - 1.0) */
72
+ qualityScore: number;
73
+ /** Memory spans used to generate the answer */
74
+ sources: MemorySpan[];
75
+ /** Sub-queries generated and answered (if recursive) */
76
+ subQueries?: SubQuery[];
77
+ /** Token usage statistics */
78
+ tokenUsage: TokenUsage;
79
+ /** Whether this answer was served from cache */
80
+ cached: boolean;
81
+ }
82
+ /**
83
+ * A span of memory retrieved for context
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * const span: MemorySpan = {
88
+ * id: 'mem-abc123',
89
+ * text: 'Relevant context from memory...',
90
+ * similarityScore: 0.89,
91
+ * source: 'documentation',
92
+ * metadata: { timestamp: Date.now(), category: 'technical' },
93
+ * };
94
+ * ```
95
+ */
96
+ export interface MemorySpan {
97
+ /** Unique identifier for the memory span */
98
+ id: string;
99
+ /** The text content of the memory span */
100
+ text: string;
101
+ /** Cosine similarity score to the query (0.0 - 1.0) */
102
+ similarityScore: number;
103
+ /** Optional source identifier (e.g., document name, URL) */
104
+ source?: string;
105
+ /** Additional metadata associated with this span */
106
+ metadata: Record<string, unknown>;
107
+ }
108
+ /**
109
+ * A sub-query generated during recursive retrieval
110
+ */
111
+ export interface SubQuery {
112
+ /** The generated sub-query text */
113
+ query: string;
114
+ /** The answer to the sub-query */
115
+ answer: string;
116
+ /** Recursion depth at which this sub-query was generated */
117
+ depth: number;
118
+ }
119
+ /**
120
+ * Token usage statistics for a query
121
+ */
122
+ export interface TokenUsage {
123
+ /** Tokens used in the prompt (including context) */
124
+ prompt: number;
125
+ /** Tokens generated in the completion */
126
+ completion: number;
127
+ /** Total tokens used (prompt + completion) */
128
+ total: number;
129
+ }
130
+ /**
131
+ * Streaming token event
132
+ *
133
+ * Discriminated union for streaming responses:
134
+ * - `type: 'token'` - A partial token was generated
135
+ * - `type: 'done'` - Generation complete with final answer
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * for await (const event of controller.queryStream('What is AI?')) {
140
+ * if (event.type === 'token') {
141
+ * process.stdout.write(event.text);
142
+ * } else {
143
+ * console.log('\n\nFinal answer:', event.answer.text);
144
+ * }
145
+ * }
146
+ * ```
147
+ */
148
+ export type StreamToken = {
149
+ /** Token event type */
150
+ type: 'token';
151
+ /** The partial text token */
152
+ text: string;
153
+ /** Always false for token events */
154
+ done: false;
155
+ } | {
156
+ /** Done event type */
157
+ type: 'done';
158
+ /** The complete answer */
159
+ answer: RlmAnswer;
160
+ /** Always true for done events */
161
+ done: true;
162
+ };
163
+ /**
164
+ * Internal cache entry for RLM answers
165
+ */
166
+ export interface RlmCacheEntry {
167
+ /** The cached answer */
168
+ answer: RlmAnswer;
169
+ /** Timestamp when the entry was cached */
170
+ timestamp: number;
171
+ /** Query hash for cache key */
172
+ queryHash: string;
173
+ }
174
+ /**
175
+ * Reflection result from self-evaluation loop
176
+ */
177
+ export interface ReflectionResult {
178
+ /** Whether the answer passed reflection criteria */
179
+ passed: boolean;
180
+ /** Critique of the current answer */
181
+ critique?: string;
182
+ /** Suggested improvements */
183
+ suggestions?: string[];
184
+ /** Updated quality score after reflection */
185
+ updatedScore: number;
186
+ /** Number of reflection iterations performed */
187
+ iterations: number;
188
+ }
189
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/rlm/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * RLM (Retrieval Language Model) Type Definitions
3
+ *
4
+ * Types for the recursive retrieval-augmented generation system
5
+ * that breaks down complex queries into sub-queries and synthesizes
6
+ * answers from retrieved memory spans.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcmxtL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUkxNIChSZXRyaWV2YWwgTGFuZ3VhZ2UgTW9kZWwpIFR5cGUgRGVmaW5pdGlvbnNcbiAqXG4gKiBUeXBlcyBmb3IgdGhlIHJlY3Vyc2l2ZSByZXRyaWV2YWwtYXVnbWVudGVkIGdlbmVyYXRpb24gc3lzdGVtXG4gKiB0aGF0IGJyZWFrcyBkb3duIGNvbXBsZXggcXVlcmllcyBpbnRvIHN1Yi1xdWVyaWVzIGFuZCBzeW50aGVzaXplc1xuICogYW5zd2VycyBmcm9tIHJldHJpZXZlZCBtZW1vcnkgc3BhbnMuXG4gKi9cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciB0aGUgUkxNIGNvbnRyb2xsZXJcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgY29uZmlnOiBSbG1Db25maWcgPSB7XG4gKiAgIG1heERlcHRoOiAzLFxuICogICBtYXhTdWJRdWVyaWVzOiA1LFxuICogICB0b2tlbkJ1ZGdldDogNDA5NixcbiAqICAgZW5hYmxlQ2FjaGU6IHRydWUsXG4gKiAgIGNhY2hlVHRsOiAzMDAwMDAsIC8vIDUgbWludXRlc1xuICogICByZXRyaWV2YWxUb3BLOiAxMCxcbiAqICAgbWluUXVhbGl0eVNjb3JlOiAwLjcsXG4gKiAgIGVuYWJsZVJlZmxlY3Rpb246IHRydWUsXG4gKiAgIG1heFJlZmxlY3Rpb25JdGVyYXRpb25zOiAyLFxuICogfTtcbiAqIGBgYFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJsbUNvbmZpZyB7XG4gIC8qKiBNYXhpbXVtIHJlY3Vyc2lvbiBkZXB0aCBmb3Igc3ViLXF1ZXJpZXMgKGRlZmF1bHQ6IDMpICovXG4gIG1heERlcHRoPzogbnVtYmVyO1xuXG4gIC8qKiBNYXhpbXVtIG51bWJlciBvZiBzdWItcXVlcmllcyBwZXIgbGV2ZWwgKGRlZmF1bHQ6IDUpICovXG4gIG1heFN1YlF1ZXJpZXM/OiBudW1iZXI7XG5cbiAgLyoqIFRva2VuIGJ1ZGdldCBmb3IgZ2VuZXJhdGlvbiAoZGVmYXVsdDogNDA5NikgKi9cbiAgdG9rZW5CdWRnZXQ/OiBudW1iZXI7XG5cbiAgLyoqIEVuYWJsZSByZXNwb25zZSBjYWNoaW5nIChkZWZhdWx0OiB0cnVlKSAqL1xuICBlbmFibGVDYWNoZT86IGJvb2xlYW47XG5cbiAgLyoqIENhY2hlIFRUTCBpbiBtaWxsaXNlY29uZHMgKGRlZmF1bHQ6IDMwMDAwMCA9IDUgbWludXRlcykgKi9cbiAgY2FjaGVUdGw/OiBudW1iZXI7XG5cbiAgLyoqIE51bWJlciBvZiBtZW1vcnkgc3BhbnMgdG8gcmV0cmlldmUgKGRlZmF1bHQ6IDEwKSAqL1xuICByZXRyaWV2YWxUb3BLPzogbnVtYmVyO1xuXG4gIC8qKiBNaW5pbXVtIHF1YWxpdHkgc2NvcmUgdG8gYWNjZXB0IGFuc3dlciAoZGVmYXVsdDogMC43KSAqL1xuICBtaW5RdWFsaXR5U2NvcmU/OiBudW1iZXI7XG5cbiAgLyoqIEVuYWJsZSBzZWxmLXJlZmxlY3Rpb24gbG9vcCAoZGVmYXVsdDogZmFsc2UpICovXG4gIGVuYWJsZVJlZmxlY3Rpb24/OiBib29sZWFuO1xuXG4gIC8qKiBNYXhpbXVtIHJlZmxlY3Rpb24gaXRlcmF0aW9ucyAoZGVmYXVsdDogMikgKi9cbiAgbWF4UmVmbGVjdGlvbkl0ZXJhdGlvbnM/OiBudW1iZXI7XG59XG5cbi8qKlxuICogQW5zd2VyIHByb2R1Y2VkIGJ5IHRoZSBSTE0gY29udHJvbGxlclxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBhbnN3ZXI6IFJsbUFuc3dlciA9IHtcbiAqICAgdGV4dDogJ01hY2hpbmUgbGVhcm5pbmcgaXMgYSBzdWJzZXQgb2YgYXJ0aWZpY2lhbCBpbnRlbGxpZ2VuY2UuLi4nLFxuICogICBjb25maWRlbmNlOiAwLjkyLFxuICogICBxdWFsaXR5U2NvcmU6IDAuODgsXG4gKiAgIHNvdXJjZXM6IFtcbiAqICAgICB7IGlkOiAnbWVtLTEnLCB0ZXh0OiAnTUwgZGVmaW5pdGlvbiBmcm9tIHRleHRib29rJywgc2ltaWxhcml0eVNjb3JlOiAwLjk1LCBtZXRhZGF0YToge30gfSxcbiAqICAgXSxcbiAqICAgc3ViUXVlcmllczogW1xuICogICAgIHsgcXVlcnk6ICdXaGF0IGlzIGFydGlmaWNpYWwgaW50ZWxsaWdlbmNlPycsIGFuc3dlcjogJ0FJIGlzLi4uJywgZGVwdGg6IDEgfSxcbiAqICAgXSxcbiAqICAgdG9rZW5Vc2FnZTogeyBwcm9tcHQ6IDUxMiwgY29tcGxldGlvbjogMjU2LCB0b3RhbDogNzY4IH0sXG4gKiAgIGNhY2hlZDogZmFsc2UsXG4gKiB9O1xuICogYGBgXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmxtQW5zd2VyIHtcbiAgLyoqIFRoZSBnZW5lcmF0ZWQgYW5zd2VyIHRleHQgKi9cbiAgdGV4dDogc3RyaW5nO1xuXG4gIC8qKiBPdmVyYWxsIGNvbmZpZGVuY2UgaW4gdGhlIGFuc3dlciAoMC4wIC0gMS4wKSAqL1xuICBjb25maWRlbmNlOiBudW1iZXI7XG5cbiAgLyoqIFF1YWxpdHkgc2NvcmUgYmFzZWQgb24gc291cmNlIGNvdmVyYWdlIGFuZCBjb2hlcmVuY2UgKDAuMCAtIDEuMCkgKi9cbiAgcXVhbGl0eVNjb3JlOiBudW1iZXI7XG5cbiAgLyoqIE1lbW9yeSBzcGFucyB1c2VkIHRvIGdlbmVyYXRlIHRoZSBhbnN3ZXIgKi9cbiAgc291cmNlczogTWVtb3J5U3BhbltdO1xuXG4gIC8qKiBTdWItcXVlcmllcyBnZW5lcmF0ZWQgYW5kIGFuc3dlcmVkIChpZiByZWN1cnNpdmUpICovXG4gIHN1YlF1ZXJpZXM/OiBTdWJRdWVyeVtdO1xuXG4gIC8qKiBUb2tlbiB1c2FnZSBzdGF0aXN0aWNzICovXG4gIHRva2VuVXNhZ2U6IFRva2VuVXNhZ2U7XG5cbiAgLyoqIFdoZXRoZXIgdGhpcyBhbnN3ZXIgd2FzIHNlcnZlZCBmcm9tIGNhY2hlICovXG4gIGNhY2hlZDogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBIHNwYW4gb2YgbWVtb3J5IHJldHJpZXZlZCBmb3IgY29udGV4dFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBzcGFuOiBNZW1vcnlTcGFuID0ge1xuICogICBpZDogJ21lbS1hYmMxMjMnLFxuICogICB0ZXh0OiAnUmVsZXZhbnQgY29udGV4dCBmcm9tIG1lbW9yeS4uLicsXG4gKiAgIHNpbWlsYXJpdHlTY29yZTogMC44OSxcbiAqICAgc291cmNlOiAnZG9jdW1lbnRhdGlvbicsXG4gKiAgIG1ldGFkYXRhOiB7IHRpbWVzdGFtcDogRGF0ZS5ub3coKSwgY2F0ZWdvcnk6ICd0ZWNobmljYWwnIH0sXG4gKiB9O1xuICogYGBgXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWVtb3J5U3BhbiB7XG4gIC8qKiBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIG1lbW9yeSBzcGFuICovXG4gIGlkOiBzdHJpbmc7XG5cbiAgLyoqIFRoZSB0ZXh0IGNvbnRlbnQgb2YgdGhlIG1lbW9yeSBzcGFuICovXG4gIHRleHQ6IHN0cmluZztcblxuICAvKiogQ29zaW5lIHNpbWlsYXJpdHkgc2NvcmUgdG8gdGhlIHF1ZXJ5ICgwLjAgLSAxLjApICovXG4gIHNpbWlsYXJpdHlTY29yZTogbnVtYmVyO1xuXG4gIC8qKiBPcHRpb25hbCBzb3VyY2UgaWRlbnRpZmllciAoZS5nLiwgZG9jdW1lbnQgbmFtZSwgVVJMKSAqL1xuICBzb3VyY2U/OiBzdHJpbmc7XG5cbiAgLyoqIEFkZGl0aW9uYWwgbWV0YWRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoaXMgc3BhbiAqL1xuICBtZXRhZGF0YTogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8qKlxuICogQSBzdWItcXVlcnkgZ2VuZXJhdGVkIGR1cmluZyByZWN1cnNpdmUgcmV0cmlldmFsXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3ViUXVlcnkge1xuICAvKiogVGhlIGdlbmVyYXRlZCBzdWItcXVlcnkgdGV4dCAqL1xuICBxdWVyeTogc3RyaW5nO1xuXG4gIC8qKiBUaGUgYW5zd2VyIHRvIHRoZSBzdWItcXVlcnkgKi9cbiAgYW5zd2VyOiBzdHJpbmc7XG5cbiAgLyoqIFJlY3Vyc2lvbiBkZXB0aCBhdCB3aGljaCB0aGlzIHN1Yi1xdWVyeSB3YXMgZ2VuZXJhdGVkICovXG4gIGRlcHRoOiBudW1iZXI7XG59XG5cbi8qKlxuICogVG9rZW4gdXNhZ2Ugc3RhdGlzdGljcyBmb3IgYSBxdWVyeVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRva2VuVXNhZ2Uge1xuICAvKiogVG9rZW5zIHVzZWQgaW4gdGhlIHByb21wdCAoaW5jbHVkaW5nIGNvbnRleHQpICovXG4gIHByb21wdDogbnVtYmVyO1xuXG4gIC8qKiBUb2tlbnMgZ2VuZXJhdGVkIGluIHRoZSBjb21wbGV0aW9uICovXG4gIGNvbXBsZXRpb246IG51bWJlcjtcblxuICAvKiogVG90YWwgdG9rZW5zIHVzZWQgKHByb21wdCArIGNvbXBsZXRpb24pICovXG4gIHRvdGFsOiBudW1iZXI7XG59XG5cbi8qKlxuICogU3RyZWFtaW5nIHRva2VuIGV2ZW50XG4gKlxuICogRGlzY3JpbWluYXRlZCB1bmlvbiBmb3Igc3RyZWFtaW5nIHJlc3BvbnNlczpcbiAqIC0gYHR5cGU6ICd0b2tlbidgIC0gQSBwYXJ0aWFsIHRva2VuIHdhcyBnZW5lcmF0ZWRcbiAqIC0gYHR5cGU6ICdkb25lJ2AgLSBHZW5lcmF0aW9uIGNvbXBsZXRlIHdpdGggZmluYWwgYW5zd2VyXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGZvciBhd2FpdCAoY29uc3QgZXZlbnQgb2YgY29udHJvbGxlci5xdWVyeVN0cmVhbSgnV2hhdCBpcyBBST8nKSkge1xuICogICBpZiAoZXZlbnQudHlwZSA9PT0gJ3Rva2VuJykge1xuICogICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKGV2ZW50LnRleHQpO1xuICogICB9IGVsc2Uge1xuICogICAgIGNvbnNvbGUubG9nKCdcXG5cXG5GaW5hbCBhbnN3ZXI6JywgZXZlbnQuYW5zd2VyLnRleHQpO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IHR5cGUgU3RyZWFtVG9rZW4gPVxuICB8IHtcbiAgICAgIC8qKiBUb2tlbiBldmVudCB0eXBlICovXG4gICAgICB0eXBlOiAndG9rZW4nO1xuICAgICAgLyoqIFRoZSBwYXJ0aWFsIHRleHQgdG9rZW4gKi9cbiAgICAgIHRleHQ6IHN0cmluZztcbiAgICAgIC8qKiBBbHdheXMgZmFsc2UgZm9yIHRva2VuIGV2ZW50cyAqL1xuICAgICAgZG9uZTogZmFsc2U7XG4gICAgfVxuICB8IHtcbiAgICAgIC8qKiBEb25lIGV2ZW50IHR5cGUgKi9cbiAgICAgIHR5cGU6ICdkb25lJztcbiAgICAgIC8qKiBUaGUgY29tcGxldGUgYW5zd2VyICovXG4gICAgICBhbnN3ZXI6IFJsbUFuc3dlcjtcbiAgICAgIC8qKiBBbHdheXMgdHJ1ZSBmb3IgZG9uZSBldmVudHMgKi9cbiAgICAgIGRvbmU6IHRydWU7XG4gICAgfTtcblxuLyoqXG4gKiBJbnRlcm5hbCBjYWNoZSBlbnRyeSBmb3IgUkxNIGFuc3dlcnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSbG1DYWNoZUVudHJ5IHtcbiAgLyoqIFRoZSBjYWNoZWQgYW5zd2VyICovXG4gIGFuc3dlcjogUmxtQW5zd2VyO1xuXG4gIC8qKiBUaW1lc3RhbXAgd2hlbiB0aGUgZW50cnkgd2FzIGNhY2hlZCAqL1xuICB0aW1lc3RhbXA6IG51bWJlcjtcblxuICAvKiogUXVlcnkgaGFzaCBmb3IgY2FjaGUga2V5ICovXG4gIHF1ZXJ5SGFzaDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlZmxlY3Rpb24gcmVzdWx0IGZyb20gc2VsZi1ldmFsdWF0aW9uIGxvb3BcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWZsZWN0aW9uUmVzdWx0IHtcbiAgLyoqIFdoZXRoZXIgdGhlIGFuc3dlciBwYXNzZWQgcmVmbGVjdGlvbiBjcml0ZXJpYSAqL1xuICBwYXNzZWQ6IGJvb2xlYW47XG5cbiAgLyoqIENyaXRpcXVlIG9mIHRoZSBjdXJyZW50IGFuc3dlciAqL1xuICBjcml0aXF1ZT86IHN0cmluZztcblxuICAvKiogU3VnZ2VzdGVkIGltcHJvdmVtZW50cyAqL1xuICBzdWdnZXN0aW9ucz86IHN0cmluZ1tdO1xuXG4gIC8qKiBVcGRhdGVkIHF1YWxpdHkgc2NvcmUgYWZ0ZXIgcmVmbGVjdGlvbiAqL1xuICB1cGRhdGVkU2NvcmU6IG51bWJlcjtcblxuICAvKiogTnVtYmVyIG9mIHJlZmxlY3Rpb24gaXRlcmF0aW9ucyBwZXJmb3JtZWQgKi9cbiAgaXRlcmF0aW9uczogbnVtYmVyO1xufVxuIl19
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ruvector/ruvllm",
3
- "version": "0.2.3",
4
- "description": "Self-learning LLM orchestration with TRM recursive reasoning, SONA adaptive learning, HNSW memory, FastGRNN routing, and SIMD inference",
3
+ "version": "2.4.0",
4
+ "description": "Self-learning LLM orchestration with SONA adaptive learning, HNSW memory, RLM recursive retrieval, FastGRNN routing, and SIMD inference",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
7
7
  "types": "dist/cjs/index.d.ts",
@@ -65,20 +65,19 @@
65
65
  "ora": "^5.4.1"
66
66
  },
67
67
  "optionalDependencies": {
68
- "@ruvector/ruvllm-linux-x64-gnu": "0.2.3",
69
- "@ruvector/ruvllm-linux-arm64-gnu": "0.2.3",
70
- "@ruvector/ruvllm-darwin-x64": "0.2.3",
71
- "@ruvector/ruvllm-darwin-arm64": "0.2.3",
72
- "@ruvector/ruvllm-win32-x64-msvc": "0.2.3"
68
+ "@ruvector/ruvllm-linux-x64-gnu": "2.3.0",
69
+ "@ruvector/ruvllm-linux-arm64-gnu": "2.3.0",
70
+ "@ruvector/ruvllm-darwin-x64": "2.3.0",
71
+ "@ruvector/ruvllm-darwin-arm64": "2.3.0",
72
+ "@ruvector/ruvllm-win32-x64-msvc": "2.3.0"
73
73
  },
74
74
  "keywords": [
75
75
  "ruvllm",
76
76
  "llm",
77
+ "rlm",
78
+ "retrieval-language-model",
77
79
  "self-learning",
78
80
  "adaptive-learning",
79
- "trm",
80
- "tiny-recursive-models",
81
- "recursive-reasoning",
82
81
  "sona",
83
82
  "lora",
84
83
  "ewc",
@@ -95,7 +94,9 @@
95
94
  "deep-learning",
96
95
  "napi",
97
96
  "rust",
98
- "ruvector"
97
+ "ruvector",
98
+ "rag",
99
+ "contrastive-learning"
99
100
  ],
100
101
  "author": "rUv Team <team@ruv.io>",
101
102
  "license": "MIT OR Apache-2.0",
@@ -118,6 +119,7 @@
118
119
  "files": [
119
120
  "dist",
120
121
  "bin",
122
+ "scripts",
121
123
  "*.node",
122
124
  "README.md"
123
125
  ]
@@ -0,0 +1,287 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Ensemble Model Comparison
4
+ *
5
+ * Strategies:
6
+ * 1. Task prefix - prepend context to make tasks more aligned with descriptions
7
+ * 2. Ensemble voting - combine multiple description variants
8
+ * 3. Agent-specific thresholds based on training patterns
9
+ */
10
+
11
+ const { execSync } = require('child_process');
12
+ const { existsSync } = require('fs');
13
+ const { join } = require('path');
14
+ const { homedir } = require('os');
15
+
16
+ const MODELS_DIR = join(homedir(), '.ruvllm', 'models');
17
+ const RUVLTRA_MODEL = join(MODELS_DIR, 'ruvltra-claude-code-0.5b-q4_k_m.gguf');
18
+ const QWEN_MODEL = join(MODELS_DIR, 'qwen2.5-0.5b-instruct-q4_k_m.gguf');
19
+
20
+ // Original V1 descriptions (best baseline)
21
+ const DESCRIPTIONS_V1 = {
22
+ coder: 'implement create write build add code function class component feature',
23
+ researcher: 'research find investigate analyze explore search discover examine',
24
+ reviewer: 'review check evaluate assess inspect examine code quality',
25
+ tester: 'test unit integration e2e coverage mock assertion spec',
26
+ architect: 'design architecture schema system structure plan database',
27
+ 'security-architect': 'security vulnerability xss injection audit cve authentication',
28
+ debugger: 'debug fix bug error issue broken crash exception trace',
29
+ documenter: 'document readme jsdoc comment explain describe documentation',
30
+ refactorer: 'refactor extract rename consolidate clean restructure simplify',
31
+ optimizer: 'optimize performance slow fast cache speed memory latency',
32
+ devops: 'deploy ci cd kubernetes docker pipeline container infrastructure',
33
+ 'api-docs': 'openapi swagger api documentation graphql schema endpoint',
34
+ planner: 'plan estimate prioritize sprint roadmap schedule milestone',
35
+ };
36
+
37
+ // V6: Keywords reformulated as action phrases
38
+ const DESCRIPTIONS_V6 = {
39
+ coder: 'implement new functionality write code build features create components',
40
+ researcher: 'research and analyze investigate patterns explore best practices',
41
+ reviewer: 'review code quality check pull requests evaluate implementations',
42
+ tester: 'write tests create test coverage add unit and integration tests',
43
+ architect: 'design system architecture plan database schemas structure systems',
44
+ 'security-architect': 'audit security vulnerabilities check xss and injection attacks',
45
+ debugger: 'debug and fix bugs trace errors resolve exceptions',
46
+ documenter: 'write documentation add jsdoc comments create readme files',
47
+ refactorer: 'refactor code modernize to async await restructure modules',
48
+ optimizer: 'optimize performance improve speed cache data reduce latency',
49
+ devops: 'deploy to cloud setup ci cd pipelines manage containers kubernetes',
50
+ 'api-docs': 'generate openapi documentation create swagger api specs',
51
+ planner: 'plan sprints create roadmaps estimate timelines schedule milestones',
52
+ };
53
+
54
+ // Task prefixes to try
55
+ const TASK_PREFIXES = [
56
+ '', // No prefix (baseline)
57
+ 'Task: ', // Simple task prefix
58
+ 'The developer needs to: ', // Contextual prefix
59
+ 'Claude Code task - ', // Model-specific prefix
60
+ ];
61
+
62
+ const ROUTING_TESTS = [
63
+ { task: 'Implement a binary search function in TypeScript', expected: 'coder' },
64
+ { task: 'Write unit tests for the authentication module', expected: 'tester' },
65
+ { task: 'Review the pull request for security vulnerabilities', expected: 'reviewer' },
66
+ { task: 'Research best practices for React state management', expected: 'researcher' },
67
+ { task: 'Design the database schema for user profiles', expected: 'architect' },
68
+ { task: 'Fix the null pointer exception in the login handler', expected: 'debugger' },
69
+ { task: 'Audit the API endpoints for XSS vulnerabilities', expected: 'security-architect' },
70
+ { task: 'Write JSDoc comments for the utility functions', expected: 'documenter' },
71
+ { task: 'Refactor the payment module to use async/await', expected: 'refactorer' },
72
+ { task: 'Optimize the database queries for the dashboard', expected: 'optimizer' },
73
+ { task: 'Set up the CI/CD pipeline for the microservices', expected: 'devops' },
74
+ { task: 'Generate OpenAPI documentation for the REST API', expected: 'api-docs' },
75
+ { task: 'Create a sprint plan for the next two weeks', expected: 'planner' },
76
+ { task: 'Build a React component for user registration', expected: 'coder' },
77
+ { task: 'Debug memory leak in the WebSocket handler', expected: 'debugger' },
78
+ { task: 'Investigate slow API response times', expected: 'researcher' },
79
+ { task: 'Check code for potential race conditions', expected: 'reviewer' },
80
+ { task: 'Add integration tests for the payment gateway', expected: 'tester' },
81
+ { task: 'Plan the architecture for real-time notifications', expected: 'architect' },
82
+ { task: 'Cache the frequently accessed user data', expected: 'optimizer' },
83
+ ];
84
+
85
+ function getEmbedding(modelPath, text) {
86
+ try {
87
+ const sanitized = text.replace(/"/g, '\\"').replace(/\n/g, ' ');
88
+ const result = execSync(
89
+ `llama-embedding -m "${modelPath}" -p "${sanitized}" --embd-output-format json 2>/dev/null`,
90
+ { encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 }
91
+ );
92
+ const json = JSON.parse(result);
93
+ return json.data[json.data.length - 1].embedding;
94
+ } catch {
95
+ return null;
96
+ }
97
+ }
98
+
99
+ function cosineSimilarity(a, b) {
100
+ if (!a || !b || a.length !== b.length) return 0;
101
+ let dot = 0, normA = 0, normB = 0;
102
+ for (let i = 0; i < a.length; i++) {
103
+ dot += a[i] * b[i];
104
+ normA += a[i] * a[i];
105
+ normB += b[i] * b[i];
106
+ }
107
+ return dot / (Math.sqrt(normA) * Math.sqrt(normB) || 1);
108
+ }
109
+
110
+ function routeTask(taskEmbedding, agentEmbeddings) {
111
+ let bestAgent = 'coder';
112
+ let bestSim = -1;
113
+ const allScores = {};
114
+ for (const [agent, emb] of Object.entries(agentEmbeddings)) {
115
+ const sim = cosineSimilarity(taskEmbedding, emb);
116
+ allScores[agent] = sim;
117
+ if (sim > bestSim) {
118
+ bestSim = sim;
119
+ bestAgent = agent;
120
+ }
121
+ }
122
+ return { agent: bestAgent, confidence: bestSim, scores: allScores };
123
+ }
124
+
125
+ /**
126
+ * Ensemble routing - vote across multiple description sets
127
+ */
128
+ function routeTaskEnsemble(taskEmbedding, allAgentEmbeddings) {
129
+ const votes = {};
130
+ const agents = Object.keys(allAgentEmbeddings[0]);
131
+
132
+ for (const agent of agents) votes[agent] = 0;
133
+
134
+ // Each embedding set votes
135
+ for (const agentEmbeddings of allAgentEmbeddings) {
136
+ const { agent } = routeTask(taskEmbedding, agentEmbeddings);
137
+ votes[agent] = (votes[agent] || 0) + 1;
138
+ }
139
+
140
+ // Return agent with most votes
141
+ let bestAgent = 'coder';
142
+ let maxVotes = 0;
143
+ for (const [agent, count] of Object.entries(votes)) {
144
+ if (count > maxVotes) {
145
+ maxVotes = count;
146
+ bestAgent = agent;
147
+ }
148
+ }
149
+
150
+ return { agent: bestAgent, votes, voteCount: maxVotes };
151
+ }
152
+
153
+ function runBenchmark(modelPath, descriptions, prefix = '') {
154
+ const agentEmbeddings = {};
155
+ for (const [agent, desc] of Object.entries(descriptions)) {
156
+ agentEmbeddings[agent] = getEmbedding(modelPath, desc);
157
+ }
158
+
159
+ let correct = 0;
160
+ for (const test of ROUTING_TESTS) {
161
+ const taskEmb = getEmbedding(modelPath, prefix + test.task);
162
+ const { agent } = routeTask(taskEmb, agentEmbeddings);
163
+ if (agent === test.expected) correct++;
164
+ }
165
+
166
+ return { accuracy: correct / ROUTING_TESTS.length, correct, total: ROUTING_TESTS.length };
167
+ }
168
+
169
+ function runEnsembleBenchmark(modelPath, descriptionSets, prefix = '') {
170
+ // Precompute embeddings for all description sets
171
+ const allAgentEmbeddings = descriptionSets.map(descriptions => {
172
+ const embeds = {};
173
+ for (const [agent, desc] of Object.entries(descriptions)) {
174
+ embeds[agent] = getEmbedding(modelPath, desc);
175
+ }
176
+ return embeds;
177
+ });
178
+
179
+ let correct = 0;
180
+ const results = [];
181
+ for (const test of ROUTING_TESTS) {
182
+ const taskEmb = getEmbedding(modelPath, prefix + test.task);
183
+ const { agent, votes } = routeTaskEnsemble(taskEmb, allAgentEmbeddings);
184
+ const isCorrect = agent === test.expected;
185
+ if (isCorrect) correct++;
186
+ results.push({ task: test.task, expected: test.expected, got: agent, correct: isCorrect, votes });
187
+ }
188
+
189
+ return { accuracy: correct / ROUTING_TESTS.length, correct, total: ROUTING_TESTS.length, results };
190
+ }
191
+
192
+ async function main() {
193
+ console.log('\n╔═══════════════════════════════════════════════════════════════════════════════════╗');
194
+ console.log('║ ENSEMBLE & PREFIX MODEL COMPARISON ║');
195
+ console.log('╚═══════════════════════════════════════════════════════════════════════════════════╝\n');
196
+
197
+ if (!existsSync(RUVLTRA_MODEL)) {
198
+ console.error('RuvLTRA model not found.');
199
+ process.exit(1);
200
+ }
201
+
202
+ // Test prefix variations
203
+ console.log('─────────────────────────────────────────────────────────────────');
204
+ console.log(' PREFIX VARIATIONS (RuvLTRA)');
205
+ console.log('─────────────────────────────────────────────────────────────────\n');
206
+
207
+ const prefixResults = {};
208
+ for (const prefix of TASK_PREFIXES) {
209
+ const label = prefix || '(no prefix)';
210
+ process.stdout.write(` Testing "${label.padEnd(25)}"... `);
211
+ const result = runBenchmark(RUVLTRA_MODEL, DESCRIPTIONS_V1, prefix);
212
+ prefixResults[label] = result;
213
+ console.log(`${(result.accuracy * 100).toFixed(1)}%`);
214
+ }
215
+
216
+ // Find best prefix
217
+ const bestPrefix = Object.entries(prefixResults).reduce((a, b) =>
218
+ a[1].accuracy > b[1].accuracy ? a : b
219
+ );
220
+
221
+ console.log(`\n Best prefix: "${bestPrefix[0]}" = ${(bestPrefix[1].accuracy * 100).toFixed(1)}%`);
222
+
223
+ // Test ensemble voting
224
+ console.log('\n─────────────────────────────────────────────────────────────────');
225
+ console.log(' ENSEMBLE VOTING (RuvLTRA)');
226
+ console.log('─────────────────────────────────────────────────────────────────\n');
227
+
228
+ process.stdout.write(' Computing V1 + V6 ensemble... ');
229
+ const ensembleResult = runEnsembleBenchmark(RUVLTRA_MODEL, [DESCRIPTIONS_V1, DESCRIPTIONS_V6], '');
230
+ console.log(`${(ensembleResult.accuracy * 100).toFixed(1)}%`);
231
+
232
+ // Compare with Qwen
233
+ console.log('\n─────────────────────────────────────────────────────────────────');
234
+ console.log(' QWEN COMPARISON');
235
+ console.log('─────────────────────────────────────────────────────────────────\n');
236
+
237
+ process.stdout.write(' Qwen V1 baseline... ');
238
+ const qwenV1 = runBenchmark(QWEN_MODEL, DESCRIPTIONS_V1, '');
239
+ console.log(`${(qwenV1.accuracy * 100).toFixed(1)}%`);
240
+
241
+ process.stdout.write(' Qwen V1+V6 ensemble... ');
242
+ const qwenEnsemble = runEnsembleBenchmark(QWEN_MODEL, [DESCRIPTIONS_V1, DESCRIPTIONS_V6], '');
243
+ console.log(`${(qwenEnsemble.accuracy * 100).toFixed(1)}%`);
244
+
245
+ // Final results table
246
+ console.log('\n═══════════════════════════════════════════════════════════════════════════════════');
247
+ console.log(' FINAL RESULTS');
248
+ console.log('═══════════════════════════════════════════════════════════════════════════════════\n');
249
+
250
+ const fmt = (v) => `${(v * 100).toFixed(1)}%`.padStart(10);
251
+
252
+ console.log('┌───────────────────────────────┬────────────┬────────────┐');
253
+ console.log('│ Strategy │ RuvLTRA │ Qwen │');
254
+ console.log('├───────────────────────────────┼────────────┼────────────┤');
255
+ console.log(`│ V1 Baseline │${fmt(prefixResults['(no prefix)'].accuracy)} │${fmt(qwenV1.accuracy)} │`);
256
+ console.log(`│ V1 + Best Prefix │${fmt(bestPrefix[1].accuracy)} │ - │`);
257
+ console.log(`│ V1+V6 Ensemble │${fmt(ensembleResult.accuracy)} │${fmt(qwenEnsemble.accuracy)} │`);
258
+ console.log('└───────────────────────────────┴────────────┴────────────┘');
259
+
260
+ // Best overall
261
+ const ruvBest = Math.max(
262
+ prefixResults['(no prefix)'].accuracy,
263
+ bestPrefix[1].accuracy,
264
+ ensembleResult.accuracy
265
+ );
266
+ const qwenBest = Math.max(qwenV1.accuracy, qwenEnsemble.accuracy);
267
+
268
+ console.log(`\n RuvLTRA Best: ${(ruvBest * 100).toFixed(1)}%`);
269
+ console.log(` Qwen Best: ${(qwenBest * 100).toFixed(1)}%`);
270
+ console.log(` Advantage: RuvLTRA +${((ruvBest - qwenBest) * 100).toFixed(1)} points`);
271
+
272
+ // Show detailed ensemble results
273
+ console.log('\n─────────────────────────────────────────────────────────────────');
274
+ console.log(' ENSEMBLE VOTING DETAILS (RuvLTRA)');
275
+ console.log('─────────────────────────────────────────────────────────────────\n');
276
+
277
+ for (const r of ensembleResult.results) {
278
+ const mark = r.correct ? '✓' : '✗';
279
+ const task = r.task.slice(0, 45).padEnd(45);
280
+ const exp = r.expected.padEnd(18);
281
+ console.log(`${mark} ${task} ${exp}${r.correct ? '' : '→ ' + r.got}`);
282
+ }
283
+
284
+ console.log('\n');
285
+ }
286
+
287
+ main().catch(console.error);