kopitiam_tensor/lib.rs
1//! Kopitiam Runtime: tensor.
2//!
3//! The CPU tensor type and the inference-time op set (matmul, broadcasting
4//! arithmetic, softmax, reductions, normalization, activations, embedding
5//! gather) that every layer of a transformer forward pass is built from,
6//! plus decoders for the `f16`/`bf16`/GGUF-quantized formats model weights
7//! ship in.
8//!
9//! # Scope: Phase 1, inference only
10//!
11//! This crate has no autograd, no gradient tape, and no training ops. That
12//! is a scope decision, not an oversight: the Kopitiam Runtime's stated
13//! purpose (see `docs/ai-decisions/`) is local inference, and every op
14//! here is chosen because a forward pass needs it. Concretely, this means:
15//!
16//! * Every general-purpose op (arithmetic, softmax, reductions,
17//! normalization, activations, [`Tensor::matmul`]) works on `f32` and
18//! rejects other dtypes with [`Error::DTypeMismatch`] (see
19//! [`Tensor::require_dtype`]). The one exception is
20//! [`Tensor::quantized_matmul`], which computes directly on Q4_0/Q8_0
21//! weight blocks — see that method's docs for why a fused quantized
22//! matmul earns an exception to "everything is f32" (memory: a
23//! dequantized 7B Q4_0 model is ~28GB of `f32` vs ~4GB quantized) and for
24//! the correctness gate that keeps it honest against the plain
25//! `to_dtype(F32)` + [`Tensor::matmul`] reference path, which remains
26//! this crate's default and stays permanently, both as the general
27//! fallback for every other op and as that oracle.
28//! * There is no backward pass, so there is nothing here resembling a
29//! `requires_grad` flag or a computation graph — `Tensor` is a plain
30//! value type.
31//! * [`Tensor::gather_rows`] implements embedding lookup specifically
32//! (indices select whole rows), not PyTorch's general per-element
33//! `gather`; see that method's docs for why the general form is out of
34//! scope.
35//! * There is still no *general* `f32 -> quantized` encoder (no
36//! `Tensor::to_dtype(DType::Q4_0)`) — see [`Tensor::to_dtype`]'s docs for
37//! why requantizing weights is a model-export concern out of this
38//! crate's scope. The quantized module's `quantize_row_q8_0` is a
39//! narrower thing: an *activation*-only Q8_0 encoder, private to
40//! [`Tensor::quantized_matmul`]'s implementation, not a public
41//! `Tensor -> Tensor` conversion.
42//!
43//! # Layering
44//!
45//! This crate depends only on `kopitiam-core` for the shared vocabulary
46//! ([`DType`], [`Shape`], [`Device`], [`Error`]) and re-exports it so
47//! downstream crates (`kopitiam-loader`, `kopitiam-runtime`) need not add
48//! a direct `kopitiam-core` dependency just to name a dtype:
49//!
50//! ```text
51//! kopitiam-runtime -> { kopitiam-loader, kopitiam-tokenizer } -> kopitiam-tensor -> kopitiam-core
52//! ```
53//!
54//! # Module map
55//!
56//! * [`Tensor`] — the shape + strided-view + shared-storage tensor type,
57//! and every op, split across `tensor/*.rs` by concern (see that
58//! module's docs for why the split is by Rust module rather than by
59//! flat file, and how that lets internals stay module-private instead of
60//! crate-wide `pub(crate)`).
61//! * [`Storage`] — the owned CPU buffer `Tensor` is a view into.
62//! * `half` — `f16`/`bf16` <-> `f32` conversion (re-exported as free
63//! functions; useful on their own, e.g. for a loader converting a whole
64//! weight file up front).
65//! * `quant` (private) — GGUF block-quantized format decoders, used only
66//! through [`Tensor::to_dtype`].
67
68mod half;
69mod quant;
70mod storage;
71mod tensor;
72
73pub use half::{bf16_to_f32, f16_to_f32, f32_to_bf16, f32_to_f16};
74pub use storage::Storage;
75pub use tensor::{has_fused_matmul_kernel, LstmState, Tensor};
76
77// Re-export the runtime's shared vocabulary so downstream crates can depend
78// on `kopitiam-tensor` alone for the common inference-time types, the same
79// way `kopitiam-ontology` types flow through the Semantic Runtime's crates.
80pub use kopitiam_core::{DType, Device, Error, Result, Shape};