use context_forge::{
ChunkingDistiller, Config, ContextForge, DistilledMemory, Distiller, Fact, FactKind,
SaveOptions,
};
use std::path::PathBuf;
struct LineCountDistiller;
impl Distiller for LineCountDistiller {
fn distill(&self, transcript: &str) -> context_forge::Result<DistilledMemory> {
let lines: Vec<&str> = transcript.lines().filter(|l| !l.is_empty()).collect();
eprintln!(" -> distilling a chunk of {} line(s)", lines.len());
Ok(DistilledMemory {
summary: format!(
"This chunk covered {} line(s) of conversation.",
lines.len()
),
facts: lines
.into_iter()
.map(|line| Fact {
kind: FactKind::State,
text: line.to_owned(),
})
.collect(),
})
}
}
#[tokio::main]
async fn main() -> Result<(), context_forge::Error> {
let mut config = Config::default();
config.db_path = PathBuf::from("chunked-distill-example.db");
let cf = ContextForge::open(config).await?;
let transcript = "\
User: I want to switch our deploy pipeline to use canary releases.
Assistant: Sounds good -- what rollout percentage do you want to start with?
User: Let's start at 5% and ramp to 100% over an hour if metrics stay green.
Assistant: Noted, I'll wire that into the pipeline config.
User: Also, remember I prefer terse commit messages, one line max.
";
const MAX_CHUNK_CHARS: usize = 120;
let distiller = ChunkingDistiller::new(LineCountDistiller, MAX_CHUNK_CHARS);
let opts = SaveOptions {
scope: Some("project:demo".to_owned()),
..SaveOptions::default()
};
println!(
"Distilling a {}-character transcript in chunks of <= {MAX_CHUNK_CHARS} characters:",
transcript.len()
);
let ids = cf.distill_and_save(transcript, &distiller, &opts).await?;
println!(
"Saved {} entries (1 merged summary + {} facts).",
ids.len(),
ids.len() - 1
);
let hits = cf
.query("canary commit", Some("project:demo"), 2048)
.await?;
println!("\nQuery results for \"canary commit\":");
for hit in &hits {
println!("{}: {}", hit.id, hit.content);
}
Ok(())
}