Files
wifi-densepose/vendor/ruvector/examples/rvf/examples/reasoning_trace.rs

389 lines
14 KiB
Rust

//! Chain-of-Thought Reasoning Traces — Agentic AI
//!
//! Demonstrates how to capture multi-step reasoning chains with RVF lineage:
//! 1. Create a parent store for "problem statement" embeddings
//! 2. Derive a child store for "reasoning step" embeddings (DerivationType::Transform)
//! 3. Derive a grandchild for "conclusion" embeddings (DerivationType::Filter)
//! 4. Add witness entries at each reasoning step (COMPUTATION type)
//! 5. Verify lineage chain: parent_id, parent_hash, lineage_depth
//! 6. Print the full reasoning chain with lineage verification
//!
//! RVF segments used: VEC_SEG, MANIFEST_SEG, FileIdentity (lineage), WITNESS_SEG
//!
//! Run with:
//! cargo run --example reasoning_trace
use rvf_runtime::{
MetadataEntry, MetadataValue, QueryOptions, RvfOptions, RvfStore, SearchResult,
};
use rvf_runtime::options::DistanceMetric;
use rvf_types::DerivationType;
use rvf_crypto::{create_witness_chain, verify_witness_chain, shake256_256, WitnessEntry};
use tempfile::TempDir;
/// Simple pseudo-random number generator (LCG) for deterministic results.
fn random_vector(dim: usize, seed: u64) -> Vec<f32> {
let mut v = Vec::with_capacity(dim);
let mut x = seed.wrapping_add(1);
for _ in 0..dim {
x = x.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
v.push(((x >> 33) as f32) / (u32::MAX as f32) - 0.5);
}
v
}
/// Format bytes as a hex string (first N bytes).
fn hex_short(bytes: &[u8], n: usize) -> String {
bytes.iter().take(n).map(|b| format!("{:02x}", b)).collect()
}
fn main() {
println!("=== RVF Chain-of-Thought Reasoning Trace Example ===\n");
let dim = 64;
let tmp_dir = TempDir::new().expect("failed to create temp dir");
let mut witness_entries: Vec<WitnessEntry> = Vec::new();
// ====================================================================
// 1. Create parent store: Problem Statements
// ====================================================================
println!("--- 1. Problem Statement Store (Root) ---");
let parent_path = tmp_dir.path().join("problems.rvf");
let options = RvfOptions {
dimension: dim as u16,
metric: DistanceMetric::L2,
..Default::default()
};
let mut parent_store =
RvfStore::create(&parent_path, options.clone()).expect("failed to create parent store");
// Insert problem statement embeddings
// Metadata field_id 0: problem_type (String)
let problem_types = [
"optimization",
"classification",
"generation",
"search",
"reasoning",
];
let num_problems = 10;
let vectors: Vec<Vec<f32>> = (0..num_problems)
.map(|i| random_vector(dim, i as u64 * 100))
.collect();
let vec_refs: Vec<&[f32]> = vectors.iter().map(|v| v.as_slice()).collect();
let ids: Vec<u64> = (0..num_problems as u64).collect();
let mut metadata = Vec::with_capacity(num_problems);
for i in 0..num_problems {
metadata.push(MetadataEntry {
field_id: 0,
value: MetadataValue::String(problem_types[i % problem_types.len()].to_string()),
});
}
parent_store
.ingest_batch(&vec_refs, &ids, Some(&metadata))
.expect("failed to ingest problems");
let parent_identity = *parent_store.file_identity();
println!(" File ID: {}", hex_short(&parent_identity.file_id, 8));
println!(" Lineage depth: {}", parent_identity.lineage_depth);
println!(" Is root: {}", parent_identity.is_root());
println!(" Problems stored: {}", num_problems);
// Witness: problem definition step
witness_entries.push(WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(b"STEP:define_problems:count=10"),
timestamp_ns: 1_700_000_000_000_000_000,
witness_type: 0x02, // COMPUTATION
});
// ====================================================================
// 2. Derive child store: Reasoning Steps (Transform)
// ====================================================================
println!("\n--- 2. Reasoning Steps Store (Child, Transform) ---");
let reasoning_path = tmp_dir.path().join("reasoning.rvf");
let mut reasoning_store = parent_store
.derive(&reasoning_path, DerivationType::Transform, None)
.expect("failed to derive reasoning store");
let reasoning_identity = *reasoning_store.file_identity();
println!(" File ID: {}", hex_short(&reasoning_identity.file_id, 8));
println!(" Parent ID: {}", hex_short(&reasoning_identity.parent_id, 8));
println!(" Lineage depth: {}", reasoning_identity.lineage_depth);
println!(" Parent hash: {}...", hex_short(&reasoning_identity.parent_hash, 8));
// Verify parent linkage
assert_eq!(
reasoning_identity.parent_id, parent_identity.file_id,
"child should reference parent's file_id"
);
assert_eq!(
reasoning_identity.lineage_depth, 1,
"child should have depth 1"
);
println!(" Parent linkage: verified");
// Insert reasoning step embeddings
// Metadata field_id 0: step_type (String), field_id 1: step_number (U64)
let step_types = [
"decompose",
"analyze",
"hypothesize",
"evaluate",
"synthesize",
];
let num_steps = 15;
let step_vectors: Vec<Vec<f32>> = (0..num_steps)
.map(|i| random_vector(dim, 1000 + i as u64))
.collect();
let step_refs: Vec<&[f32]> = step_vectors.iter().map(|v| v.as_slice()).collect();
let step_ids: Vec<u64> = (100..100 + num_steps as u64).collect();
let mut step_metadata = Vec::with_capacity(num_steps * 2);
for i in 0..num_steps {
step_metadata.push(MetadataEntry {
field_id: 0,
value: MetadataValue::String(step_types[i % step_types.len()].to_string()),
});
step_metadata.push(MetadataEntry {
field_id: 1,
value: MetadataValue::U64(i as u64),
});
}
reasoning_store
.ingest_batch(&step_refs, &step_ids, Some(&step_metadata))
.expect("failed to ingest reasoning steps");
println!(" Reasoning steps stored: {}", num_steps);
// Witness: reasoning step
witness_entries.push(WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(b"STEP:reasoning:transform:count=15"),
timestamp_ns: 1_700_001_000_000_000_000,
witness_type: 0x02,
});
// ====================================================================
// 3. Derive grandchild store: Conclusions (Filter)
// ====================================================================
println!("\n--- 3. Conclusions Store (Grandchild, Filter) ---");
let conclusions_path = tmp_dir.path().join("conclusions.rvf");
let mut conclusions_store = reasoning_store
.derive(&conclusions_path, DerivationType::Filter, None)
.expect("failed to derive conclusions store");
let conclusions_identity = *conclusions_store.file_identity();
println!(" File ID: {}", hex_short(&conclusions_identity.file_id, 8));
println!(" Parent ID: {}", hex_short(&conclusions_identity.parent_id, 8));
println!(" Lineage depth: {}", conclusions_identity.lineage_depth);
println!(" Parent hash: {}...", hex_short(&conclusions_identity.parent_hash, 8));
// Verify grandchild linkage
assert_eq!(
conclusions_identity.parent_id, reasoning_identity.file_id,
"grandchild should reference reasoning store's file_id"
);
assert_eq!(
conclusions_identity.lineage_depth, 2,
"grandchild should have depth 2"
);
println!(" Parent linkage: verified (depth 2)");
// Insert conclusion embeddings
// Metadata field_id 0: conclusion_type (String), field_id 1: confidence (U64: 0-100)
let conclusion_types = ["definitive", "tentative", "conditional"];
let num_conclusions = 5;
let conc_vectors: Vec<Vec<f32>> = (0..num_conclusions)
.map(|i| random_vector(dim, 2000 + i as u64))
.collect();
let conc_refs: Vec<&[f32]> = conc_vectors.iter().map(|v| v.as_slice()).collect();
let conc_ids: Vec<u64> = (200..200 + num_conclusions as u64).collect();
let mut conc_metadata = Vec::with_capacity(num_conclusions * 2);
for i in 0..num_conclusions {
conc_metadata.push(MetadataEntry {
field_id: 0,
value: MetadataValue::String(
conclusion_types[i % conclusion_types.len()].to_string(),
),
});
conc_metadata.push(MetadataEntry {
field_id: 1,
value: MetadataValue::U64(60 + (i as u64) * 8), // 60, 68, 76, 84, 92
});
}
conclusions_store
.ingest_batch(&conc_refs, &conc_ids, Some(&conc_metadata))
.expect("failed to ingest conclusions");
println!(" Conclusions stored: {}", num_conclusions);
// Witness: conclusion step
witness_entries.push(WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(b"STEP:conclusions:filter:count=5"),
timestamp_ns: 1_700_002_000_000_000_000,
witness_type: 0x02,
});
// ====================================================================
// 4. Query each level of the reasoning chain
// ====================================================================
println!("\n--- 4. Querying Each Reasoning Level ---");
let query = random_vector(dim, 42);
let k = 3;
// Query problems
let problem_results = parent_store
.query(&query, k, &QueryOptions::default())
.expect("problem query failed");
println!(" Problem statements (top-{}):", k);
print_results(" ", &problem_results);
// Query reasoning steps
let step_results = reasoning_store
.query(&query, k, &QueryOptions::default())
.expect("reasoning query failed");
println!(" Reasoning steps (top-{}):", k);
print_results(" ", &step_results);
// Query conclusions
let conc_results = conclusions_store
.query(&query, k, &QueryOptions::default())
.expect("conclusion query failed");
println!(" Conclusions (top-{}):", k);
print_results(" ", &conc_results);
// ====================================================================
// 5. Verify witness chain
// ====================================================================
println!("\n--- 5. Witness Chain Verification ---");
// Add a final verification witness entry
witness_entries.push(WitnessEntry {
prev_hash: [0u8; 32],
action_hash: shake256_256(b"VERIFY:lineage_chain:complete"),
timestamp_ns: 1_700_003_000_000_000_000,
witness_type: 0x0D, // WITNESS_LINEAGE_VERIFY
});
let chain_bytes = create_witness_chain(&witness_entries);
println!(
" Witness chain: {} entries, {} bytes",
witness_entries.len(),
chain_bytes.len()
);
match verify_witness_chain(&chain_bytes) {
Ok(verified) => {
println!(" Chain integrity: VALID\n");
println!(
" {:>5} {:>8} {:>20} {:>32}",
"Step", "Type", "Timestamp (ns)", "Action Hash (8 bytes)"
);
println!(" {:->5} {:->8} {:->20} {:->32}", "", "", "", "");
let type_names = ["", "PROV", "COMP", "", "", "", "", "", "", "", "", "", "", "VERIFY"];
for (i, entry) in verified.iter().enumerate() {
let tname = if (entry.witness_type as usize) < type_names.len() {
type_names[entry.witness_type as usize]
} else {
"????"
};
println!(
" {:>5} {:>8} {:>20} {}",
i,
tname,
entry.timestamp_ns,
hex_short(&entry.action_hash, 8)
);
}
}
Err(e) => println!(" Chain integrity: FAILED ({:?})", e),
}
// ====================================================================
// 6. Full lineage verification
// ====================================================================
println!("\n--- 6. Full Lineage Chain ---\n");
println!(
" {:>12} {:>8} {:>18} {:>18} {:>6}",
"Store", "Depth", "File ID (8B)", "Parent ID (8B)", "Vecs"
);
println!(
" {:->12} {:->8} {:->18} {:->18} {:->6}",
"", "", "", "", ""
);
let stores_info = [
("Problems", &parent_identity, num_problems),
("Reasoning", &reasoning_identity, num_steps),
("Conclusions", &conclusions_identity, num_conclusions),
];
for (name, identity, vec_count) in &stores_info {
println!(
" {:>12} {:>8} {:>18} {:>18} {:>6}",
name,
identity.lineage_depth,
hex_short(&identity.file_id, 8),
hex_short(&identity.parent_id, 8),
vec_count
);
}
// Verify the chain links
assert_eq!(parent_identity.lineage_depth, 0);
assert!(parent_identity.is_root());
assert_eq!(reasoning_identity.lineage_depth, 1);
assert_eq!(reasoning_identity.parent_id, parent_identity.file_id);
assert_eq!(conclusions_identity.lineage_depth, 2);
assert_eq!(conclusions_identity.parent_id, reasoning_identity.file_id);
println!("\n Lineage chain: Problems -> Reasoning -> Conclusions");
println!(" All parent links verified.");
println!(" Depth progression: 0 -> 1 -> 2");
// Close all stores
conclusions_store
.close()
.expect("failed to close conclusions");
reasoning_store.close().expect("failed to close reasoning");
parent_store.close().expect("failed to close parent");
// -- Summary --
println!("\n=== Reasoning Trace Summary ===\n");
println!(" Reasoning depth: 3 levels (problem -> reasoning -> conclusion)");
println!(" Problem statements: {}", num_problems);
println!(" Reasoning steps: {}", num_steps);
println!(" Conclusions: {}", num_conclusions);
println!(" Witness entries: {}", witness_entries.len());
println!(" Lineage verified: all parent links confirmed");
println!("\nDone.");
}
fn print_results(prefix: &str, results: &[SearchResult]) {
println!(
"{} {:>6} {:>12}",
prefix, "ID", "Distance"
);
println!("{} {:->6} {:->12}", prefix, "", "");
for r in results {
println!(
"{} {:>6} {:>12.6}",
prefix, r.id, r.distance
);
}
}