Journal: walk backwards with token budget, not load-all
Iterate journal entries backwards from the conversation cutoff, accumulating within ~10K token budget (~8% of context window). Stops when budget is full, keeps at least one entry. Much more efficient than loading all entries and trimming. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
e4285ba75f
commit
7776d87d53
1 changed files with 29 additions and 29 deletions
|
|
@ -800,51 +800,51 @@ impl Agent {
|
|||
.collect();
|
||||
journal_nodes.sort_by_key(|n| n.created_at);
|
||||
|
||||
// Filter: entries older than oldest conversation message,
|
||||
// plus the first one that overlaps (no gap)
|
||||
let entries: Vec<journal::JournalEntry> = if let Some(cutoff) = oldest_msg_ts {
|
||||
let mut result = Vec::new();
|
||||
let mut included_overlap = false;
|
||||
for node in &journal_nodes {
|
||||
// Find the cutoff index — entries older than conversation, plus one overlap
|
||||
let cutoff_idx = if let Some(cutoff) = oldest_msg_ts {
|
||||
let mut idx = journal_nodes.len();
|
||||
for (i, node) in journal_nodes.iter().enumerate() {
|
||||
let ts = chrono::DateTime::from_timestamp(node.created_at, 0)
|
||||
.unwrap_or_default();
|
||||
if ts < cutoff || !included_overlap {
|
||||
result.push(journal::JournalEntry {
|
||||
timestamp: ts,
|
||||
content: node.content.clone(),
|
||||
});
|
||||
if ts >= cutoff {
|
||||
included_overlap = true;
|
||||
}
|
||||
} else {
|
||||
if ts >= cutoff {
|
||||
idx = i + 1; // include this overlapping entry
|
||||
break;
|
||||
}
|
||||
}
|
||||
result
|
||||
idx
|
||||
} else {
|
||||
// No conversation yet — include recent entries for orientation
|
||||
let n = 20;
|
||||
let skip = journal_nodes.len().saturating_sub(n);
|
||||
journal_nodes.iter().skip(skip).map(|node| {
|
||||
journal::JournalEntry {
|
||||
timestamp: chrono::DateTime::from_timestamp(node.created_at, 0)
|
||||
.unwrap_or_default(),
|
||||
content: node.content.clone(),
|
||||
}
|
||||
}).collect()
|
||||
journal_nodes.len()
|
||||
};
|
||||
|
||||
// Walk backwards from cutoff, accumulating entries within token budget
|
||||
let count = |s: &str| self.tokenizer.encode_with_special_tokens(s).len();
|
||||
let journal_budget_tokens = 10_000; // ~8% of 128K context
|
||||
let mut entries = Vec::new();
|
||||
let mut total_tokens = 0;
|
||||
|
||||
for node in journal_nodes[..cutoff_idx].iter().rev() {
|
||||
let tokens = count(&node.content);
|
||||
if total_tokens + tokens > journal_budget_tokens && !entries.is_empty() {
|
||||
break;
|
||||
}
|
||||
entries.push(journal::JournalEntry {
|
||||
timestamp: chrono::DateTime::from_timestamp(node.created_at, 0)
|
||||
.unwrap_or_default(),
|
||||
content: node.content.clone(),
|
||||
});
|
||||
total_tokens += tokens;
|
||||
}
|
||||
entries.reverse(); // chronological order
|
||||
|
||||
if entries.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let count = |s: &str| self.tokenizer.encode_with_special_tokens(s).len();
|
||||
let context_message = self.context.render_context_message();
|
||||
|
||||
let plan = crate::agent::context::plan_context(
|
||||
&self.context.system_prompt,
|
||||
&context_message,
|
||||
&[], // no conversation yet
|
||||
&[],
|
||||
&entries,
|
||||
&self.client.model,
|
||||
&count,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue