Manage the KV cache disc usage from preferences and stats
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -313,6 +313,9 @@ impl Model {
|
||||
pub(crate) struct Generator {
|
||||
executor: metal::Executor,
|
||||
checkpoint: Option<PathBuf>,
|
||||
/// Token frontier of the last transient store, so continued checkpoints are
|
||||
/// spaced like ds4's `continued_last_store_tokens`.
|
||||
last_store_tokens: u32,
|
||||
metrics: Arc<Metrics>,
|
||||
}
|
||||
|
||||
@@ -358,6 +361,7 @@ impl Generator {
|
||||
Ok(Self {
|
||||
executor,
|
||||
checkpoint: None,
|
||||
last_store_tokens: 0,
|
||||
metrics,
|
||||
})
|
||||
}
|
||||
@@ -414,7 +418,7 @@ impl Generator {
|
||||
let history = messages
|
||||
.split_last()
|
||||
.map_or(messages, |(_, history)| history);
|
||||
let store = KvStore::open(directory)?;
|
||||
let store = KvStore::open(directory, settings.kv_cache.budget_bytes)?;
|
||||
let history_key =
|
||||
conversation_key(&settings.system_prompt, settings.reasoning_mode, history);
|
||||
let history_tag: [u8; 32] = Sha256::digest(&history_key).into();
|
||||
@@ -423,14 +427,17 @@ impl Generator {
|
||||
if let Some(entry) = store.find(&history_key, self.executor.context()) {
|
||||
if self.select_checkpoint(&entry.checkpoint, entry.tag)? {
|
||||
store.touch(&entry)?;
|
||||
self.last_store_tokens = entry.tokens;
|
||||
previous_checkpoint = Some(entry.checkpoint);
|
||||
} else {
|
||||
store.discard(&entry);
|
||||
self.last_store_tokens = 0;
|
||||
previous_checkpoint = None;
|
||||
}
|
||||
} else {
|
||||
self.executor.reset()?;
|
||||
self.checkpoint = None;
|
||||
self.last_store_tokens = 0;
|
||||
previous_checkpoint = None;
|
||||
self.metrics.kv_lookup(KvLookup::Miss);
|
||||
}
|
||||
@@ -450,6 +457,17 @@ impl Generator {
|
||||
let completed_key =
|
||||
conversation_key(&settings.system_prompt, settings.reasoning_mode, &completed);
|
||||
let completed_tag: [u8; 32] = Sha256::digest(&completed_key).into();
|
||||
if !settings.kv_cache.stores(
|
||||
self.executor.position(),
|
||||
history.is_empty(),
|
||||
self.last_store_tokens,
|
||||
) {
|
||||
// A gated store still leaves the finished conversation in the
|
||||
// live KV, so mark it and drop the stale file association.
|
||||
self.executor.note_checkpoint_tag(completed_tag);
|
||||
self.checkpoint = None;
|
||||
return Ok(output);
|
||||
}
|
||||
let completed_checkpoint = store.checkpoint_path(&completed_key);
|
||||
self.save_checkpoint(&completed_checkpoint, completed_tag)?;
|
||||
let retained = store.record(
|
||||
@@ -468,6 +486,9 @@ impl Generator {
|
||||
.then(|| std::fs::metadata(&completed_checkpoint).ok())
|
||||
.flatten()
|
||||
.map_or(0, |item| item.len());
|
||||
if retained {
|
||||
self.last_store_tokens = self.executor.position();
|
||||
}
|
||||
self.checkpoint = retained.then_some(completed_checkpoint);
|
||||
}
|
||||
Ok(output)
|
||||
|
||||
Reference in New Issue
Block a user