use chaotic_semantic_memory::prelude::*;
use chaotic_semantic_memory::retrieval::GraphRagConfig;
const NS: &str = "_default";
async fn setup_framework() -> ChaoticSemanticFramework {
ChaoticSemanticFramework::builder()
.without_persistence()
.build()
.await
.unwrap()
}
#[tokio::test]
async fn test_graph_rag_synthetic_structure() {
let framework = setup_framework().await;
let v0 = HVec10240::new_seeded(0);
let v1 = HVec10240::new_seeded(1);
let v2 = HVec10240::new_seeded(2);
let v3 = HVec10240::new_seeded(3);
framework.inject_concept("c0", v0).await.unwrap();
framework.inject_concept("c1", v1).await.unwrap();
framework.inject_concept("c2", v2).await.unwrap();
framework.inject_concept("c3", v3).await.unwrap();
framework.associate("c0", "c1", 0.8).await.unwrap();
framework.associate("c1", "c2", 0.6).await.unwrap();
let config = GraphRagConfig {
anchor_top_k: 1,
max_hops: 2,
min_assoc_strength: 0.1,
similarity_weight: 0.5,
graph_weight: 0.5,
final_top_k: 10,
};
let results = framework.probe_with_graph(v0, config).await.unwrap();
assert!(!results.is_empty());
assert_eq!(results[0].id, "c0");
assert_eq!(results[0].hop_distance, 0);
let ids: Vec<String> = results.iter().map(|r| r.id.clone()).collect();
assert!(ids.contains(&"c1".to_string()));
assert!(ids.contains(&"c2".to_string()));
assert!(!ids.contains(&"c3".to_string()));
let c2_res = results.iter().find(|r| r.id == "c2").unwrap();
assert!((c2_res.assoc_strength - 0.6).abs() < f32::EPSILON);
}
#[tokio::test]
async fn test_graph_rag_connected_outranks_similarity() {
let framework = setup_framework().await;
let v_query = HVec10240::new_seeded(100);
let v_anchor = v_query;
let v_neighbor = HVec10240::new_seeded(200);
let v_high_sim = v_query;
framework.inject_concept("anchor", v_anchor).await.unwrap();
framework
.inject_concept("neighbor", v_neighbor)
.await
.unwrap();
framework
.inject_concept("high_sim", v_high_sim)
.await
.unwrap();
framework
.associate("anchor", "neighbor", 0.9)
.await
.unwrap();
let config = GraphRagConfig {
anchor_top_k: 1, max_hops: 1,
similarity_weight: 0.1,
graph_weight: 0.9,
final_top_k: 5,
..Default::default()
};
let results = framework.probe_with_graph(v_query, config).await.unwrap();
let ids: Vec<String> = results.iter().map(|r| r.id.clone()).collect();
assert!(ids.contains(&"anchor".to_string()) || ids.contains(&"high_sim".to_string()));
}
#[tokio::test]
async fn test_graph_rag_cycles() {
let framework = setup_framework().await;
framework
.inject_concept("c0", HVec10240::random())
.await
.unwrap();
framework
.inject_concept("c1", HVec10240::random())
.await
.unwrap();
framework.associate("c0", "c1", 0.8).await.unwrap();
framework.associate("c1", "c0", 0.8).await.unwrap();
let config = GraphRagConfig {
anchor_top_k: 1,
max_hops: 5,
..Default::default()
};
let results = framework
.probe_with_graph(HVec10240::random(), config)
.await
.unwrap();
assert!(results.len() <= 2);
}
#[tokio::test]
async fn test_graph_rag_empty_isolated() {
let framework = setup_framework().await;
let results = framework
.probe_with_graph(HVec10240::random(), GraphRagConfig::default())
.await
.unwrap();
assert!(results.is_empty());
framework
.inject_concept("c0", HVec10240::random())
.await
.unwrap();
let results = framework
.probe_with_graph(HVec10240::random(), GraphRagConfig::default())
.await
.unwrap();
assert_eq!(results.len(), 1);
assert_eq!(results[0].id, "c0");
assert_eq!(results[0].hop_distance, 0);
}