use crate::array::Array;
use crate::error::{Error, Result};
use crate::ops;
#[derive(Default, Clone)]
pub struct KvCache {
keys: Option<Array>,
values: Option<Array>,
}
impl KvCache {
pub fn new() -> Self {
Self::default()
}
pub fn offset(&self) -> i32 {
self.keys.as_ref().map(|k| k.dim(-2)).unwrap_or(0)
}
pub fn update_and_fetch(&mut self, keys: Array, values: Array) -> Result<(Array, Array)> {
let (full_k, full_v) = match (self.keys.take(), self.values.take()) {
(Some(ok), Some(ov)) => (
ops::concatenate(&[&ok, &keys], -2)?,
ops::concatenate(&[&ov, &values], -2)?,
),
_ => (keys, values),
};
self.keys = Some(full_k.clone());
self.values = Some(full_v.clone());
Ok((full_k, full_v))
}
}
#[derive(Default, Clone)]
pub struct GatedDeltaCache {
pub conv_state: Option<Array>,
pub recur_state: Option<Array>,
}
impl GatedDeltaCache {
pub fn new() -> Self {
Self::default()
}
}
#[derive(Default, Clone)]
pub struct DharaCache {
pub attn: KvCache,
pub canon_a: Option<Array>,
pub canon_b_q: Option<Array>,
pub canon_b_k: Option<Array>,
pub canon_b_v: Option<Array>,
pub canon_c: Option<Array>,
pub canon_d: Option<Array>,
}
impl DharaCache {
pub fn new() -> Self {
Self::default()
}
}
#[derive(Clone)]
pub enum LayerCache {
Attention(KvCache),
GatedDelta(GatedDeltaCache),
Dhara(DharaCache),
}
impl LayerCache {
pub fn new_attention() -> Self {
LayerCache::Attention(KvCache::new())
}
pub fn new_gated_delta() -> Self {
LayerCache::GatedDelta(GatedDeltaCache::new())
}
pub fn new_dhara() -> Self {
LayerCache::Dhara(DharaCache::new())
}
pub fn as_attention(&mut self) -> Result<&mut KvCache> {
match self {
LayerCache::Attention(c) => Ok(c),
_ => Err(Error::Model(
"expected an attention cache, found a different cache kind".into(),
)),
}
}
pub fn as_gated_delta(&mut self) -> Result<&mut GatedDeltaCache> {
match self {
LayerCache::GatedDelta(c) => Ok(c),
_ => Err(Error::Model(
"expected a gated-delta cache, found a different cache kind".into(),
)),
}
}
pub fn as_dhara(&mut self) -> Result<&mut DharaCache> {
match self {
LayerCache::Dhara(c) => Ok(c),
_ => Err(Error::Model(
"expected a dhara cache, found a different cache kind".into(),
)),
}
}
}