surface: tag recent nodes as (new) instead of hiding them
Links to nodes created after the conversation window start are tagged with (new) in memory_render output. The surface prompt tells the agent not to surface these — they're its own recent output, not prior memories. Observe can still see and update them. POC_MEMORIES_OLDER_THAN env var set from the oldest message timestamp in the conversation window. Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
7fc1d60113
commit
27861a44e5
5 changed files with 75 additions and 23 deletions
|
|
@ -11,7 +11,7 @@ use super::store::Store;
|
|||
pub struct MemoryNode {
|
||||
pub key: String,
|
||||
pub content: String,
|
||||
pub links: Vec<(String, f32)>, // (target_key, strength)
|
||||
pub links: Vec<(String, f32, bool)>, // (target_key, strength, is_new)
|
||||
pub version: u32,
|
||||
pub weight: f32,
|
||||
}
|
||||
|
|
@ -27,20 +27,34 @@ impl MemoryNode {
|
|||
pub fn from_store(store: &Store, key: &str) -> Option<Self> {
|
||||
let node = store.nodes.get(key)?;
|
||||
|
||||
let mut neighbors: std::collections::HashMap<&str, f32> = std::collections::HashMap::new();
|
||||
// If set, tag links to nodes created after this timestamp as (new)
|
||||
let older_than: i64 = std::env::var("POC_MEMORIES_OLDER_THAN")
|
||||
.ok()
|
||||
.and_then(|s| s.parse().ok())
|
||||
.unwrap_or(0);
|
||||
|
||||
let mut neighbors: std::collections::HashMap<&str, (f32, bool)> = std::collections::HashMap::new();
|
||||
for r in &store.relations {
|
||||
if r.deleted { continue; }
|
||||
if r.source_key == key {
|
||||
let e = neighbors.entry(&r.target_key).or_insert(0.0);
|
||||
*e = e.max(r.strength);
|
||||
let neighbor_key = if r.source_key == key {
|
||||
&r.target_key
|
||||
} else if r.target_key == key {
|
||||
let e = neighbors.entry(&r.source_key).or_insert(0.0);
|
||||
*e = e.max(r.strength);
|
||||
}
|
||||
&r.source_key
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let is_new = older_than > 0 && store.nodes.get(neighbor_key.as_str())
|
||||
.map(|n| n.created_at > older_than)
|
||||
.unwrap_or(false);
|
||||
|
||||
let e = neighbors.entry(neighbor_key.as_str()).or_insert((0.0, false));
|
||||
e.0 = e.0.max(r.strength);
|
||||
e.1 = e.1 || is_new;
|
||||
}
|
||||
|
||||
let mut links: Vec<(String, f32)> = neighbors.into_iter()
|
||||
.map(|(k, s)| (k.to_string(), s))
|
||||
let mut links: Vec<(String, f32, bool)> = neighbors.into_iter()
|
||||
.map(|(k, (s, new))| (k.to_string(), s, new))
|
||||
.collect();
|
||||
links.sort_by(|a, b| b.1.total_cmp(&a.1));
|
||||
|
||||
|
|
@ -58,15 +72,16 @@ impl MemoryNode {
|
|||
let mut out = self.content.clone();
|
||||
|
||||
// Footer: links not already referenced inline
|
||||
let footer: Vec<&(String, f32)> = self.links.iter()
|
||||
.filter(|(target, _)| !self.content.contains(target.as_str()))
|
||||
let footer: Vec<&(String, f32, bool)> = self.links.iter()
|
||||
.filter(|(target, _, _)| !self.content.contains(target.as_str()))
|
||||
.collect();
|
||||
|
||||
if !footer.is_empty() {
|
||||
let total = footer.len();
|
||||
out.push_str("\n\n---\nLinks:");
|
||||
for (target, strength) in footer.iter().take(15) {
|
||||
out.push_str(&format!("\n ({:.2}) `{}`", strength, target));
|
||||
for (target, strength, is_new) in footer.iter().take(15) {
|
||||
let tag = if *is_new { " (new)" } else { "" };
|
||||
out.push_str(&format!("\n ({:.2}) `{}`{}", strength, target, tag));
|
||||
}
|
||||
if total > 15 {
|
||||
out.push_str(&format!("\n ... and {} more (memory_links({{\"{}\"}}))",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue