Skip to content

Commit 9e5a0e5

Browse files
Merge pull request #73 from ApiliumCode/dev
release: v0.4.2 — HNSW vector search for Ineru
2 parents edeefcd + 5ab94ff commit 9e5a0e5

18 files changed

Lines changed: 1141 additions & 23 deletions

File tree

Cargo.lock

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ai_hash/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ai_hash"
3-
version = "0.4.1"
3+
version = "0.4.2"
44
authors = ["Apilium Technologies <hello@apilium.com>"]
55
keywords = [ "aingle", "ai", "hash", "blake", "blake2b" ]
66
categories = [ "cryptography" ]

crates/aingle/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "aingle"
3-
version = "0.4.1"
3+
version = "0.4.2"
44
description = "AIngle, a framework for distributed applications"
55
license = "Apache-2.0 OR LicenseRef-Commercial"
66
homepage = "https://apilium.com"

crates/aingle_ai/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "aingle_ai"
3-
version = "0.4.1"
3+
version = "0.4.2"
44
description = "AI integration layer for AIngle - Ineru, Nested Learning, Kaneru"
55
license = "Apache-2.0 OR LicenseRef-Commercial"
66
repository = "https://github.com/ApiliumCode/aingle"

crates/aingle_contracts/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "aingle_contracts"
3-
version = "0.4.1"
3+
version = "0.4.2"
44
description = "Smart Contracts DSL and WASM Runtime for AIngle"
55
license = "Apache-2.0 OR LicenseRef-Commercial"
66
repository = "https://github.com/ApiliumCode/aingle"

crates/aingle_cortex/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "aingle_cortex"
3-
version = "0.4.1"
3+
version = "0.4.2"
44
description = "Córtex API - REST/GraphQL/SPARQL interface for AIngle semantic graphs"
55
license = "Apache-2.0 OR LicenseRef-Commercial"
66
repository = "https://github.com/ApiliumCode/aingle"

crates/aingle_cortex/src/rest/memory.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,104 @@ pub async fn restore_checkpoint(
328328
Ok(StatusCode::OK)
329329
}
330330

331+
// ============================================================================
332+
// Vector Search (Motomeru)
333+
// ============================================================================
334+
335+
#[derive(Debug, Deserialize)]
336+
pub struct VectorSearchRequest {
337+
pub embedding: Vec<f32>,
338+
pub k: usize,
339+
#[serde(default = "default_min_similarity")]
340+
pub min_similarity: f32,
341+
pub entry_type: Option<String>,
342+
pub tags: Option<Vec<String>>,
343+
}
344+
345+
fn default_min_similarity() -> f32 {
346+
0.0
347+
}
348+
349+
#[derive(Debug, Serialize)]
350+
pub struct VectorIndexStatsDto {
351+
pub point_count: usize,
352+
pub deleted_count: usize,
353+
pub dimensions: usize,
354+
pub memory_bytes: usize,
355+
}
356+
357+
/// Vector search over memory entries using HNSW index.
358+
pub async fn vector_search(
359+
State(state): State<AppState>,
360+
Json(req): Json<VectorSearchRequest>,
361+
) -> Result<Json<Vec<MemoryResultDto>>> {
362+
let memory = state.memory.read().await;
363+
let results = memory.ltm.vector_search_memories(&req.embedding, req.k, req.min_similarity);
364+
365+
let mut dtos: Vec<MemoryResultDto> = results
366+
.into_iter()
367+
.map(|(entry, similarity)| MemoryResultDto {
368+
id: entry.id.to_hex(),
369+
entry_type: entry.entry_type.clone(),
370+
data: entry.data.clone(),
371+
tags: entry.tags.iter().map(|t| t.0.clone()).collect(),
372+
importance: entry.metadata.importance,
373+
relevance: similarity,
374+
source: "LongTerm".to_string(),
375+
created_at: entry.metadata.created_at.0.to_string(),
376+
last_accessed: entry.metadata.last_accessed.0.to_string(),
377+
access_count: entry.metadata.access_count,
378+
})
379+
.collect();
380+
381+
// Apply optional filters
382+
if let Some(ref entry_type) = req.entry_type {
383+
dtos.retain(|d| &d.entry_type == entry_type);
384+
}
385+
if let Some(ref tags) = req.tags {
386+
if !tags.is_empty() {
387+
dtos.retain(|d| tags.iter().any(|t| d.tags.contains(t)));
388+
}
389+
}
390+
391+
Ok(Json(dtos))
392+
}
393+
394+
/// Get HNSW vector index statistics.
395+
pub async fn vector_index_stats(
396+
State(state): State<AppState>,
397+
) -> Result<Json<VectorIndexStatsDto>> {
398+
let memory = state.memory.read().await;
399+
let stats = memory.ltm.hnsw_index()
400+
.map(|idx| idx.stats())
401+
.unwrap_or(ineru::hnsw::HnswStats {
402+
point_count: 0,
403+
deleted_count: 0,
404+
dimensions: 0,
405+
max_layer: 0,
406+
memory_bytes: 0,
407+
});
408+
409+
Ok(Json(VectorIndexStatsDto {
410+
point_count: stats.point_count,
411+
deleted_count: stats.deleted_count,
412+
dimensions: stats.dimensions,
413+
memory_bytes: stats.memory_bytes,
414+
}))
415+
}
416+
417+
/// Force rebuild of the HNSW vector index.
418+
pub async fn rebuild_vector_index(
419+
State(state): State<AppState>,
420+
) -> Result<StatusCode> {
421+
let mut memory = state.memory.write().await;
422+
if let Some(hnsw) = memory.ltm.hnsw_index_mut() {
423+
hnsw.rebuild();
424+
tracing::info!("HNSW index rebuilt, {} active points", hnsw.len());
425+
}
426+
Ok(StatusCode::OK)
427+
}
428+
331429
// ============================================================================
332430
// Helpers
333431
// ============================================================================
@@ -376,4 +474,8 @@ pub fn memory_router() -> axum::Router<AppState> {
376474
.route("/api/v1/memory/checkpoint", post(checkpoint))
377475
.route("/api/v1/memory/checkpoints", get(list_checkpoints))
378476
.route("/api/v1/memory/restore/{id}", post(restore_checkpoint))
477+
// Motomeru: HNSW vector search endpoints
478+
.route("/api/v1/memory/search", post(vector_search))
479+
.route("/api/v1/memory/index/stats", get(vector_index_stats))
480+
.route("/api/v1/memory/index/rebuild", post(rebuild_vector_index))
379481
}

crates/aingle_graph/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "aingle_graph"
3-
version = "0.4.1"
3+
version = "0.4.2"
44
description = "Native GraphDB for AIngle - Semantic triple store with SPO indexes"
55
license = "Apache-2.0 OR LicenseRef-Commercial"
66
repository = "https://github.com/ApiliumCode/aingle"

crates/aingle_logic/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "aingle_logic"
3-
version = "0.4.1"
3+
version = "0.4.2"
44
description = "Proof-of-Logic validation engine for AIngle semantic graphs"
55
license = "Apache-2.0 OR LicenseRef-Commercial"
66
repository = "https://github.com/ApiliumCode/aingle"

crates/aingle_minimal/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "aingle_minimal"
3-
version = "0.4.1"
3+
version = "0.4.2"
44
description = "Ultra-light AIngle node for IoT devices (<1MB RAM)"
55
license = "Apache-2.0 OR LicenseRef-Commercial"
66
repository = "https://github.com/ApiliumCode/aingle"

0 commit comments

Comments
 (0)