forked from kent/consciousness
subconscious: lift continuation gen + render helpers into shared homes
- context.rs gains is_assistant, render_branch_text, render_prior_context alongside memory_key / is_memory_node. They're pure AST helpers, used by both the finetune pipeline and the forthcoming compare screen. - new subconscious/generate.rs holds gen_continuation(context, entry_idx, skip, client): build the prompt from a context prefix with an arbitrary skip predicate, send to the model, decode the completion. Takes both the predicate and the client so callers can aim it at memory-stripped contexts (finetune), same-context-different-model (F7 compare), or whatever else. - learn.rs drops its private copies of those helpers and the inline generate_alternate; the finetune path now reads as gen_continuation(context, idx, is_memory_node, client). Pure refactor, no behavior change. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
eea7de4753
commit
c5745e38e2
4 changed files with 98 additions and 87 deletions
|
|
@ -934,6 +934,53 @@ pub fn is_memory_node(node: &AstNode) -> bool {
|
|||
matches!(node, AstNode::Leaf(leaf) if matches!(leaf.body(), NodeBody::Memory { .. }))
|
||||
}
|
||||
|
||||
pub fn is_assistant(node: &AstNode) -> bool {
|
||||
matches!(node, AstNode::Branch { role: Role::Assistant, .. })
|
||||
}
|
||||
|
||||
/// Concatenate the text of a Branch's Leaf children — what the model
|
||||
/// actually produced on that turn (Content + Thinking + ToolCall name).
|
||||
pub fn render_branch_text(children: &[AstNode]) -> String {
|
||||
children.iter()
|
||||
.filter_map(|c| match c {
|
||||
AstNode::Leaf(leaf) => Some(leaf.body().text().to_string()),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
}
|
||||
|
||||
/// Render the last `max_msgs` user/assistant branches before `idx` as a
|
||||
/// review-friendly string with `[user]` / `[assistant]` markers.
|
||||
pub fn render_prior_context(entries: &[AstNode], idx: usize, max_msgs: usize) -> String {
|
||||
let mut picked: Vec<&AstNode> = Vec::with_capacity(max_msgs);
|
||||
for i in (0..idx).rev() {
|
||||
if picked.len() >= max_msgs { break; }
|
||||
if let AstNode::Branch { role, .. } = &entries[i] {
|
||||
if matches!(role, Role::User | Role::Assistant) {
|
||||
picked.push(&entries[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
picked.reverse();
|
||||
|
||||
let mut out = String::new();
|
||||
for node in picked {
|
||||
if let AstNode::Branch { role, children, .. } = node {
|
||||
let marker = match role {
|
||||
Role::User => "[user]",
|
||||
Role::Assistant => "[assistant]",
|
||||
_ => continue,
|
||||
};
|
||||
out.push_str(marker);
|
||||
out.push('\n');
|
||||
out.push_str(render_branch_text(children).trim());
|
||||
out.push_str("\n\n");
|
||||
}
|
||||
}
|
||||
out.trim_end().to_string()
|
||||
}
|
||||
|
||||
impl ContextState {
|
||||
/// Assemble the prompt in wire form: token stream with a single
|
||||
/// `<|image_pad|>` per image (vLLM expands back to N), plus the list
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue