context: tighten the Branch token-cache invariant
Two pieces around the cache that landed when Branch nodes started
holding `token_ids: Some(server_authoritative_stream)`:
1. wire_into / wire_chunks now pair cached vision blocks with their
child Image leaves. Previously the cached-branch arm spliced the
cache verbatim and didn't recurse for images, so a Branch whose
cache contained `VISION_START..VISION_END` blocks would emit those
tokens with no matching `WireImage` push — leading to a panic
downstream when `pair_images_to_ranges` tried to attach the
missing image. New `pair_cached_images` walks the children
depth-first for image leaves and zips them against
`vision_blocks(cache)` to emit correctly-offset entries; mismatched
counts panic loudly because that's an AST/cache invariant
violation that would otherwise mis-pair on the wire.
2. `conversation_mut() -> &mut Vec<AstNode>` was the one public
escape hatch that let callers reach into a Branch's children and
mutate them without invalidating the cached token stream. Removed
in favor of a focused `set_branch_memory_score(section, index,
key, score)` for the only legitimate use we had today (the
full-matrix scorer writing per-memory divergence onto the
Assistant Branch). Updated the lone caller in subconscious/learn.
Documented the invariants explicitly on `ContextState`: every
`Leaf.token_ids` matches `body.compute_token_ids()`, and every
`Branch { token_ids: Some(_) }` is a faithful walk of its children.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
006b99bdac
commit
c2433c1773
2 changed files with 160 additions and 19 deletions
|
|
@ -240,25 +240,23 @@ pub async fn score_memories(
|
|||
vec![0.0; baseline.len()]
|
||||
}
|
||||
};
|
||||
// Write this memory's scores to the live AST nodes
|
||||
// Write this memory's scores to the live AST nodes via the
|
||||
// focused setter — keeps the AST mutation surface narrow.
|
||||
{
|
||||
let mut ctx = agent.context.lock().await;
|
||||
let mut set_count = 0;
|
||||
|
||||
for (resp_idx, &idx) in response_indices.iter().enumerate() {
|
||||
if idx >= ctx.conversation().len() { continue; }
|
||||
let node = &mut ctx.conversation_mut()[idx];
|
||||
if let AstNode::Branch {
|
||||
role: Role::Assistant, memory_scores, ..
|
||||
} = node {
|
||||
if let Some(&score) = row.get(resp_idx) {
|
||||
if score > 0.01 {
|
||||
memory_scores.insert(key.clone(), score);
|
||||
set_count += 1;
|
||||
} else {
|
||||
memory_scores.remove(key.as_str());
|
||||
}
|
||||
}
|
||||
let Some(&score) = row.get(resp_idx) else { continue };
|
||||
let normalized = if score > 0.01 { Some(score) } else { None };
|
||||
ctx.set_branch_memory_score(
|
||||
crate::agent::context::Section::Conversation,
|
||||
idx,
|
||||
&key,
|
||||
normalized,
|
||||
);
|
||||
if normalized.is_some() {
|
||||
set_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue