use crate::{Engine, Error, Matrix, Result};
use super::{Embedding, Linear};
use crate::ml::{Module, ModuleRegistry, Parameter, byte};
pub struct ByteEmbedding {
inner: Embedding,
}
impl ByteEmbedding {
pub fn with_seed(engine: &Engine, embedding_dim: usize, seed: u64) -> Result<Self> {
Ok(Self {
inner: Embedding::with_seed(engine, byte::VOCAB_SIZE, embedding_dim, seed)?,
})
}
pub fn from_matrix(weight: Matrix) -> Result<Self> {
if weight.shape().first() != Some(&byte::VOCAB_SIZE) {
return Err(Error::invalid_argument(
"byte embedding weight must have shape [256, D]",
));
}
Ok(Self {
inner: Embedding::from_matrix(weight)?,
})
}
pub fn forward(&self, byte_ids: &Matrix) -> Result<Matrix> {
self.inner.forward(byte_ids)
}
pub const fn embedding_dim(&self) -> usize {
self.inner.embedding_dim()
}
pub fn weight(&self) -> Parameter {
self.inner.weight()
}
}
impl Module for ByteEmbedding {
fn forward(&self, input: &Matrix) -> Result<Matrix> {
ByteEmbedding::forward(self, input)
}
fn registry(&self) -> &ModuleRegistry {
self.inner.registry()
}
}
pub struct ByteHead {
inner: Linear,
}
impl ByteHead {
pub fn with_seed(engine: &Engine, input_features: usize, seed: u64) -> Result<Self> {
Ok(Self {
inner: Linear::with_seed(engine, input_features, byte::VOCAB_SIZE, seed)?,
})
}
pub fn forward(&self, hidden: &Matrix) -> Result<Matrix> {
self.inner.forward(hidden)
}
pub const fn input_features(&self) -> usize {
self.inner.input_features()
}
pub fn weight(&self) -> Parameter {
self.inner.weight()
}
pub fn bias(&self) -> Parameter {
self
.inner
.bias()
.expect("byte head always constructs a trainable bias")
}
}
impl Module for ByteHead {
fn forward(&self, input: &Matrix) -> Result<Matrix> {
ByteHead::forward(self, input)
}
fn registry(&self) -> &ModuleRegistry {
self.inner.registry()
}
}