ruvector-sona 0.1.1

Self-Optimizing Neural Architecture - Runtime-adaptive learning for LLM routers with two-tier LoRA, EWC++, and ReasoningBank
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
# SONA - Self-Optimizing Neural Architecture

<div align="center">

**Runtime-adaptive learning for LLM routers and AI systems without expensive retraining.**

[![Crates.io](https://img.shields.io/crates/v/sona.svg)](https://crates.io/crates/sona)
[![Documentation](https://docs.rs/sona/badge.svg)](https://docs.rs/sona)
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](LICENSE)
[![Build Status](https://img.shields.io/github/actions/workflow/status/ruvnet/ruvector/ci.yml?branch=main)](https://github.com/ruvnet/ruvector/actions)

[Quick Start]#quick-start | [Documentation]https://docs.rs/sona | [Examples]#tutorials | [API Reference]#api-reference

</div>

---

## Overview

SONA enables your AI applications to **continuously improve from user feedback**, learning in real-time with sub-millisecond overhead. Instead of expensive model retraining, SONA uses a two-tier LoRA (Low-Rank Adaptation) system that adapts routing decisions, response quality, and model selection on-the-fly.

```rust
use sona::{SonaEngine, SonaConfig, LearningSignal};

// Create adaptive learning engine
let engine = SonaEngine::new(SonaConfig::default());

// Track user interaction
let traj_id = engine.start_trajectory(query_embedding);
engine.record_step(traj_id, selected_model, confidence, latency_us);
engine.end_trajectory(traj_id, response_quality);

// Learn from feedback - takes ~500μs
engine.learn_from_feedback(LearningSignal::from_feedback(user_liked, latency_ms, quality));

// Future queries benefit from learned patterns
let optimized_embedding = engine.apply_lora(&new_query_embedding);
```

## Why SONA?

| Challenge | Traditional Approach | SONA Solution |
|-----------|---------------------|---------------|
| Improving response quality | Retrain model ($$$, weeks) | Real-time learning (<1ms) |
| Adapting to user preferences | Manual tuning | Automatic from feedback |
| Model selection optimization | Static rules | Learned patterns |
| Preventing knowledge loss | Start fresh each time | EWC++ preserves knowledge |
| Cross-platform deployment | Separate implementations | Rust + WASM + Node.js |

### Key Benefits

- **Zero-downtime learning** - Adapt to user preferences without service interruption
- **Sub-millisecond overhead** - Real-time learning with <1ms per request
- **Memory-efficient** - Two-tier LoRA reduces memory by 95% vs full fine-tuning
- **Catastrophic forgetting prevention** - EWC++ preserves learned knowledge across tasks
- **Cross-platform** - Native Rust, WASM for browsers, NAPI-RS for Node.js
- **Production-ready** - Lock-free data structures, 157 tests, comprehensive benchmarks

## Performance

| Metric | Target | Achieved | Improvement |
|--------|--------|----------|-------------|
| Instant Loop Latency | <1ms | **34μs** | 29x better |
| Trajectory Recording | <1μs | **112ns** | 9x better |
| MicroLoRA Forward (256d) | <100μs | **45μs** | 2.2x better |
| Memory per Trajectory | <1KB | **~800B** | 20% better |
| Pattern Extraction | <10ms | **~5ms** | 2x better |

### Comparison with Alternatives

| Feature | SONA | Fine-tuning | RAG | Prompt Engineering |
|---------|------|-------------|-----|-------------------|
| Learning Speed | **Real-time** | Hours/Days | N/A | Manual |
| Memory Overhead | **<1MB** | GBs | Variable | None |
| Preserves Knowledge | **Yes (EWC++)** | Risk of forgetting | Yes | Yes |
| Adapts to Users | **Automatic** | Requires retraining | No | Manual |
| Deployment | **Any platform** | GPU required | Server | Any |

## Architecture

```
┌─────────────────────────────────────────────────────────────────────────┐
│                           SONA Engine                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────────┐   │
│  │    MicroLoRA     │  │     BaseLoRA     │  │    ReasoningBank     │   │
│  │   (Rank 1-2)     │  │   (Rank 4-16)    │  │  (Pattern Storage)   │   │
│  │                  │  │                  │  │                      │   │
│  │  • Per-request   │  │  • Hourly batch  │  │  • K-means++ cluster │   │
│  │  • <100μs update │  │  • Consolidation │  │  • Similarity search │   │
│  │  • SIMD accel.   │  │  • Deep patterns │  │  • Quality filtering │   │
│  └────────┬─────────┘  └────────┬─────────┘  └──────────┬───────────┘   │
│           │                     │                       │               │
│  ┌────────▼─────────────────────▼───────────────────────▼───────────┐   │
│  │                      Learning Loops                               │   │
│  │  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐   │   │
│  │  │   Instant (A)   │  │  Background (B) │  │   Coordinator   │   │   │
│  │  │   Per-Query     │  │     Hourly      │  │  Orchestration  │   │   │
│  │  │   ~34μs         │  │     ~5ms        │  │   Sync & Scale  │   │   │
│  │  └─────────────────┘  └─────────────────┘  └─────────────────┘   │   │
│  └──────────────────────────────────────────────────────────────────┘   │
│                                                                          │
│  ┌────────────────────────┐  ┌──────────────────────────────────────┐   │
│  │   Trajectory Buffer    │  │        EWC++ (Anti-Forgetting)       │   │
│  │     (Lock-Free)        │  │                                      │   │
│  │                        │  │  • Online Fisher estimation          │   │
│  │  • Crossbeam ArrayQueue│  │  • Automatic task boundaries         │   │
│  │  • Zero contention     │  │  • Adaptive constraint strength      │   │
│  │  • ~112ns per record   │  │  • Multi-task memory preservation    │   │
│  └────────────────────────┘  └──────────────────────────────────────┘   │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘
```

## Installation

### Rust

```toml
[dependencies]
sona = "0.1"

# With SIMD optimization (default)
sona = { version = "0.1", features = ["simd"] }

# With serialization support
sona = { version = "0.1", features = ["serde-support"] }
```

### JavaScript/TypeScript (Node.js)

```bash
npm install @ruvector/sona
```

### WASM (Browser)

```bash
# Build WASM package
cd crates/sona
wasm-pack build --target web --features wasm

# Use in your project
cp -r pkg/ your-project/sona/
```

## Quick Start

### Rust - Basic Usage

```rust
use sona::{SonaEngine, SonaConfig, LearningSignal};

fn main() {
    // 1. Create engine with configuration
    let config = SonaConfig {
        hidden_dim: 256,
        micro_lora_rank: 2,
        base_lora_rank: 16,
        ..Default::default()
    };
    let engine = SonaEngine::new(config);

    // 2. Record a query trajectory
    let query_embedding = vec![0.1; 256];
    let traj_id = engine.start_trajectory(query_embedding);

    // 3. Record routing decisions
    engine.record_step(traj_id, 42, 0.85, 150);  // node_id, score, latency_us
    engine.record_step(traj_id, 17, 0.92, 120);

    // 4. Complete with outcome quality
    engine.end_trajectory(traj_id, 0.90);

    // 5. Learn from user feedback
    let signal = LearningSignal::from_feedback(true, 50.0, 0.95);
    engine.learn_from_feedback(signal);

    // 6. Apply learned optimizations to new queries
    let new_query = vec![1.0; 256];
    let optimized = engine.apply_lora(&new_query);

    println!("Learning complete! Stats: {:?}", engine.stats());
}
```

### Rust - LLM Router Integration

```rust
use sona::{SonaEngine, SonaConfig, LearningSignal};
use std::time::Instant;

pub struct AdaptiveLLMRouter {
    sona: SonaEngine,
    models: Vec<Box<dyn LLMModel>>,
}

impl AdaptiveLLMRouter {
    pub fn new(models: Vec<Box<dyn LLMModel>>) -> Self {
        Self {
            sona: SonaEngine::new(SonaConfig::default()),
            models,
        }
    }

    pub async fn route(&self, query: &str, embedding: Vec<f32>) -> Response {
        // Start tracking this query
        let traj_id = self.sona.start_trajectory(embedding.clone());

        // Apply learned optimizations
        let optimized = self.sona.apply_lora(&embedding);

        // Select best model based on learned patterns
        let start = Instant::now();
        let (model_idx, confidence) = self.select_model(&optimized);
        let latency_us = start.elapsed().as_micros() as u64;

        // Record the routing decision
        self.sona.record_step(traj_id, model_idx as u32, confidence, latency_us);

        // Execute query
        let response = self.models[model_idx].generate(query).await;

        // Complete trajectory with response quality
        self.sona.end_trajectory(traj_id, response.quality_score());

        response
    }

    pub fn record_feedback(&self, was_helpful: bool, latency_ms: f32) {
        let quality = if was_helpful { 0.9 } else { 0.2 };
        let signal = LearningSignal::from_feedback(was_helpful, latency_ms, quality);
        self.sona.learn_from_feedback(signal);
    }

    fn select_model(&self, embedding: &[f32]) -> (usize, f32) {
        // Your model selection logic here
        // SONA's optimized embedding helps make better decisions
        (0, 0.95)
    }
}
```

### Node.js

```javascript
const { SonaEngine } = require('@ruvector/sona');

// Create engine
const engine = new SonaEngine();

// Or with custom configuration
const customEngine = SonaEngine.withConfig(
    2,      // micro_lora_rank
    16,     // base_lora_rank
    10000,  // trajectory_buffer_size
    0.4     // ewc_lambda
);

// Record user interaction
const embedding = Array(256).fill(0.1);
const trajId = engine.startTrajectory(embedding);

engine.recordStep(trajId, 42, 0.85, 150);
engine.recordStep(trajId, 17, 0.92, 120);
engine.endTrajectory(trajId, 0.90);

// Learn from feedback
engine.learnFromFeedback(true, 50.0, 0.95);

// Apply to new queries
const newQuery = Array(256).fill(1.0);
const optimized = engine.applyLora(newQuery);

console.log('Stats:', engine.getStats());
```

### JavaScript (WASM in Browser)

```html
<!DOCTYPE html>
<html>
<head>
    <title>SONA Demo</title>
</head>
<body>
    <script type="module">
        import init, { WasmSonaEngine } from './pkg/sona.js';

        async function main() {
            await init();

            // Create engine (256 = hidden dimension)
            const engine = new WasmSonaEngine(256);

            // Record trajectory
            const embedding = new Float32Array(256).fill(0.1);
            const trajId = engine.start_trajectory(embedding);

            engine.record_step(trajId, 42, 0.85, 150);
            engine.end_trajectory(trajId, 0.90);

            // Learn from feedback
            engine.learn_from_feedback(true, 50.0, 0.95);

            // Apply LoRA transformation
            const input = new Float32Array(256).fill(1.0);
            const output = engine.apply_lora(input);

            console.log('Stats:', engine.get_stats());
        }

        main();
    </script>
</body>
</html>
```

## Core Components

### Two-Tier LoRA System

SONA uses a novel two-tier LoRA architecture for different learning timescales:

| Tier | Rank | Latency | Update Frequency | Purpose |
|------|------|---------|------------------|---------|
| **MicroLoRA** | 1-2 | <100μs | Per-request | Instant user adaptation |
| **BaseLoRA** | 4-16 | ~1ms | Hourly | Pattern consolidation |

```rust
// Apply individual tiers
engine.apply_micro_lora(&input, &mut output);  // Fast, per-request
engine.apply_base_lora(&input, &mut output);   // Deeper patterns

// Apply both tiers (recommended)
let output = engine.apply_lora(&input);
```

### Three Learning Loops

| Loop | Frequency | Purpose | Typical Latency |
|------|-----------|---------|-----------------|
| **Instant (A)** | Per-request | Immediate adaptation from feedback | ~34μs |
| **Background (B)** | Hourly | Pattern extraction & consolidation | ~5ms |
| **Coordinator** | Continuous | Loop synchronization & scaling | Minimal |

```rust
// Loops run automatically, but can be triggered manually
engine.run_instant_cycle();      // Force instant learning
engine.run_background_cycle();   // Force pattern extraction
```

### EWC++ (Elastic Weight Consolidation)

Prevents catastrophic forgetting when learning new patterns:

| Feature | Description |
|---------|-------------|
| **Online Fisher** | Real-time parameter importance estimation |
| **Task Boundaries** | Automatic detection via distribution shift |
| **Adaptive Lambda** | Dynamic constraint strength per task |
| **Multi-Task Memory** | Circular buffer preserving task knowledge |

```rust
let config = SonaConfig {
    ewc_lambda: 0.4,           // Constraint strength (0.0-1.0)
    ewc_gamma: 0.95,           // Fisher decay rate
    ewc_fisher_samples: 100,   // Samples for estimation
    ..Default::default()
};
```

### ReasoningBank

K-means++ clustering for trajectory pattern discovery and retrieval:

```rust
// Patterns are extracted automatically during background learning
// Query similar patterns for a given embedding:
let similar = engine.query_patterns(&query_embedding, k: 5);

for pattern in similar {
    println!("Quality: {:.2}, Usage: {}", pattern.quality, pattern.usage_count);
}
```

## Configuration

```rust
pub struct SonaConfig {
    // Dimensions
    pub hidden_dim: usize,              // Default: 256
    pub embedding_dim: usize,           // Default: 256

    // LoRA Configuration
    pub micro_lora_rank: usize,         // Default: 2 (recommended: 1-2)
    pub base_lora_rank: usize,          // Default: 16 (recommended: 4-16)
    pub lora_alpha: f32,                // Default: 1.0
    pub lora_dropout: f32,              // Default: 0.0

    // Trajectory Buffer
    pub trajectory_buffer_size: usize,  // Default: 10000
    pub max_trajectory_steps: usize,    // Default: 50

    // EWC++ Configuration
    pub ewc_lambda: f32,                // Default: 0.4
    pub ewc_gamma: f32,                 // Default: 0.95
    pub ewc_fisher_samples: usize,      // Default: 100
    pub ewc_online: bool,               // Default: true

    // ReasoningBank
    pub pattern_clusters: usize,        // Default: 32
    pub pattern_quality_threshold: f32, // Default: 0.7
    pub consolidation_interval: usize,  // Default: 1000

    // Learning Rates
    pub micro_lr: f32,                  // Default: 0.01
    pub base_lr: f32,                   // Default: 0.001
}
```

## Practical Use Cases

### 1. Chatbot Response Quality

```rust
// Thumbs up/down feedback
match user_feedback {
    Feedback::ThumbsUp => {
        engine.learn_from_feedback(LearningSignal::positive(latency, 0.95));
    }
    Feedback::ThumbsDown => {
        engine.learn_from_feedback(LearningSignal::negative(latency, 0.2));
    }
    Feedback::Regenerate => {
        engine.learn_from_feedback(LearningSignal::negative(latency, 0.4));
    }
}
```

### 2. Multi-Model Router Optimization

```rust
// Record which models perform best for different query types
async fn route_with_learning(&self, query: &str, embedding: Vec<f32>) {
    let traj_id = self.sona.start_trajectory(embedding);

    // Try multiple models, record scores
    for (idx, model) in self.models.iter().enumerate() {
        let start = Instant::now();
        let response = model.evaluate(query).await;
        let latency = start.elapsed().as_micros() as u64;

        self.sona.record_step(traj_id, idx as u32, response.score, latency);
    }

    // Select best and complete trajectory
    let best = self.select_best();
    self.sona.end_trajectory(traj_id, best.quality);
}
```

### 3. A/B Test Acceleration

```rust
// Quickly converge on winning variants using learned patterns
async fn smart_ab_test(&self, query: &str, variants: &[Variant]) -> Response {
    let embedding = self.embed(query);
    let traj_id = self.sona.start_trajectory(embedding.clone());

    // Use learned patterns to bias toward better variants
    let optimized = self.sona.apply_lora(&embedding);
    let variant = self.select_variant_ucb(variants, &optimized);

    let response = variant.execute(query).await;
    self.sona.record_step(traj_id, variant.id, response.quality, latency);
    self.sona.end_trajectory(traj_id, response.quality);

    response
}
```

### 4. Personalized Recommendations

```rust
// Learn user preferences over time
fn record_interaction(&self, user_id: &str, item: &Item, engaged: bool) {
    let embedding = self.get_user_embedding(user_id);
    let traj_id = self.sona.start_trajectory(embedding);

    self.sona.record_step(traj_id, item.category_id, item.relevance, 0);
    self.sona.end_trajectory(traj_id, if engaged { 1.0 } else { 0.0 });

    let signal = LearningSignal::from_feedback(engaged, 0.0, if engaged { 0.9 } else { 0.1 });
    self.sona.learn_from_feedback(signal);
}
```

## Tutorials

### Tutorial 1: Basic Learning Loop

```rust
use sona::{SonaEngine, SonaConfig, LearningSignal};

fn main() {
    let engine = SonaEngine::new(SonaConfig::default());

    // Simulate 1000 queries with feedback
    for i in 0..1000 {
        // Generate query embedding
        let query: Vec<f32> = (0..256).map(|_| rand::random()).collect();

        // Record trajectory
        let traj_id = engine.start_trajectory(query);

        for step in 0..3 {
            let score = 0.5 + rand::random::<f32>() * 0.5;
            let latency = 50 + rand::random::<u64>() % 100;
            engine.record_step(traj_id, step, score, latency);
        }

        let quality = 0.6 + rand::random::<f32>() * 0.4;
        engine.end_trajectory(traj_id, quality);

        // 70% positive feedback
        let positive = rand::random::<f32>() > 0.3;
        let signal = LearningSignal::from_feedback(positive, 100.0, quality);
        engine.learn_from_feedback(signal);

        // Run background learning every 100 queries
        if i % 100 == 0 {
            engine.run_background_cycle();
        }
    }

    let stats = engine.stats();
    println!("Trajectories: {}", stats.trajectories_recorded);
    println!("Patterns: {}", stats.patterns_extracted);
    println!("Learning cycles: {}", stats.learning_cycles);
}
```

### Tutorial 2: Production Integration

```rust
use sona::SonaEngine;
use std::sync::Arc;
use tokio::time::{interval, Duration};

#[tokio::main]
async fn main() {
    let engine = Arc::new(SonaEngine::new(Default::default()));

    // Background learning task
    let bg_engine = engine.clone();
    tokio::spawn(async move {
        let mut interval = interval(Duration::from_secs(3600)); // Hourly
        loop {
            interval.tick().await;
            bg_engine.run_background_cycle();
            println!("Background learning completed: {:?}", bg_engine.stats());
        }
    });

    // Request handling
    let server_engine = engine.clone();
    // ... your server code using server_engine
}
```

## API Reference

### SonaEngine Methods

| Method | Description | Latency |
|--------|-------------|---------|
| `new(config)` | Create new engine | - |
| `start_trajectory(embedding)` | Begin recording query | ~50ns |
| `record_step(id, node, score, latency)` | Record routing step | ~112ns |
| `end_trajectory(id, quality)` | Complete trajectory | ~100ns |
| `learn_from_feedback(signal)` | Apply learning signal | ~500μs |
| `apply_lora(input)` | Transform with both LoRA tiers | ~45μs |
| `apply_micro_lora(input, output)` | MicroLoRA only | ~20μs |
| `apply_base_lora(input, output)` | BaseLoRA only | ~25μs |
| `run_instant_cycle()` | Force instant learning | ~34μs |
| `run_background_cycle()` | Force background learning | ~5ms |
| `query_patterns(embedding, k)` | Find similar patterns | ~100μs |
| `stats()` | Get engine statistics | ~1μs |

### LearningSignal

| Method | Description |
|--------|-------------|
| `from_feedback(success, latency_ms, quality)` | Create from user feedback |
| `from_trajectory(trajectory)` | Create using REINFORCE algorithm |
| `positive(latency_ms, quality)` | Shorthand for positive signal |
| `negative(latency_ms, quality)` | Shorthand for negative signal |

## Feature Flags

| Flag | Description | Default |
|------|-------------|---------|
| `default` | Includes `serde-support` | Yes |
| `simd` | AVX2 SIMD acceleration | No |
| `serde-support` | Serialization with serde | Yes |
| `wasm` | WebAssembly bindings | No |
| `napi` | Node.js NAPI-RS bindings | No |

```toml
# Minimal (no serialization)
sona = { version = "0.1", default-features = false }

# With WASM support
sona = { version = "0.1", features = ["wasm"] }

# With Node.js support
sona = { version = "0.1", features = ["napi"] }

# Full features
sona = { version = "0.1", features = ["simd", "serde-support"] }
```

## Test Coverage

| Component | Tests | Status |
|-----------|-------|--------|
| Core Types | 4 | Passing |
| MicroLoRA | 6 | Passing |
| Trajectory Buffer | 10 | Passing |
| EWC++ | 7 | Passing |
| ReasoningBank | 5 | Passing |
| Learning Loops | 7 | Passing |
| Engine | 6 | Passing |
| Integration | 15 | Passing |
| **Total** | **57** | **All Passing** |

## Benchmarks

Run benchmarks:

```bash
cargo bench -p sona
```

Key results:
- MicroLoRA forward (256d): **45μs**
- Trajectory recording: **112ns**
- Instant learning cycle: **34μs**
- Background learning: **5ms**
- Pattern extraction (1000 trajectories): **5ms**

## Contributing

Contributions are welcome! Please see our [Contributing Guide](CONTRIBUTING.md).

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit changes (`git commit -m 'Add amazing feature'`)
4. Push to branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

Licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT License ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

## Acknowledgments

- [LoRA: Low-Rank Adaptation of Large Language Models]https://arxiv.org/abs/2106.09685
- [Elastic Weight Consolidation]https://arxiv.org/abs/1612.00796 for continual learning
- [K-means++]https://theory.stanford.edu/~sergei/papers/kMeansPP-soda.pdf initialization algorithm

---

<div align="center">

**[Documentation]https://docs.rs/sona** | **[GitHub]https://github.com/ruvnet/ruvector** | **[Crates.io]https://crates.io/crates/sona**

Made with Rust by the RuVector Team

</div>