memory_search: accept optional params

max_hops (default 3), edge_decay (default 0.3), min_activation
(default 0.01), limit (default 20). No longer reads from store.params.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
ProofOfConcept 2026-04-12 22:49:40 -04:00
parent d1d57267d3
commit 051198b3d1

View file

@ -8,7 +8,6 @@ use anyhow::{Context, Result};
use std::sync::OnceLock;
use crate::hippocampus::memory::MemoryNode;
use crate::store::StoreView;
use crate::store::Store;
// ── Store handle ───────────────────────────────────────────────
@ -142,7 +141,7 @@ pub fn memory_tools() -> [super::Tool; 14] {
parameters_json: r#"{"type":"object","properties":{"key":{"type":"string","description":"Node key"},"content":{"type":"string","description":"Full content (markdown)"}},"required":["key","content"]}"#,
handler: Arc::new(|a, v| Box::pin(async move { dispatch("memory_write", &a, v).await })) },
Tool { name: "memory_search", description: "Search the memory graph via spreading activation. Give 2-4 seed node keys.",
parameters_json: r#"{"type":"object","properties":{"keys":{"type":"array","items":{"type":"string"},"description":"Seed node keys to activate from"}},"required":["keys"]}"#,
parameters_json: r#"{"type":"object","properties":{"keys":{"type":"array","items":{"type":"string"},"description":"Seed node keys to activate from"},"max_hops":{"type":"integer","description":"Max graph hops (default 3)"},"edge_decay":{"type":"number","description":"Decay per hop (default 0.3)"},"min_activation":{"type":"number","description":"Cutoff threshold (default 0.01)"},"limit":{"type":"integer","description":"Max results (default 20)"}},"required":["keys"]}"#,
handler: Arc::new(|a, v| Box::pin(async move { dispatch("memory_search", &a, v).await })) },
Tool { name: "memory_links", description: "Show a node's neighbors with link strengths.",
parameters_json: r#"{"type":"object","properties":{"key":{"type":"string","description":"Node key"}},"required":["key"]}"#,
@ -264,10 +263,16 @@ async fn search(args: &serde_json::Value) -> Result<String> {
if keys.is_empty() {
anyhow::bail!("memory_search requires at least one seed key");
}
// Optional params with defaults
let max_hops = args.get("max_hops").and_then(|v| v.as_u64()).unwrap_or(3) as u32;
let edge_decay = args.get("edge_decay").and_then(|v| v.as_f64()).unwrap_or(0.3);
let min_activation = args.get("min_activation").and_then(|v| v.as_f64()).unwrap_or(0.01);
let limit = args.get("limit").and_then(|v| v.as_u64()).unwrap_or(20) as usize;
let arc = cached_store().await?;
let store = arc.lock().await;
let graph = crate::graph::build_graph_fast(&*store);
let params = store.params();
let seeds: Vec<(String, f64)> = keys.iter()
.filter_map(|k| {
let resolved = store.resolve_key(k).ok()?;
@ -281,11 +286,11 @@ async fn search(args: &serde_json::Value) -> Result<String> {
.map(|(k, _)| k.as_str()).collect();
let results = crate::search::spreading_activation(
&seeds, &graph, &*store,
params.max_hops, params.edge_decay, params.min_activation,
max_hops, edge_decay, min_activation,
);
Ok(results.iter()
.filter(|(k, _)| !seed_set.contains(k.as_str()))
.take(20)
.take(limit)
.map(|(key, score)| format!(" {:.2} {}", score, key))
.collect::<Vec<_>>().join("\n"))
}