neura-decoder 0.7.4

Assembling the decoder only models a gguf weighs onto the graph
Documentation
use neura_abi::Element;
use neura_decoder::{Cache, matrix, vector};
use neura_gguf::Gguf;
use neura_graph::{Graph, Shape};

#[path = "support/mod.rs"]
mod support;

use support::{build, quantized, singles};

fn refuses<T>(action: impl FnOnce() -> T) -> bool {
    std::panic::catch_unwind(std::panic::AssertUnwindSafe(action)).is_err()
}

fn archive(tensors: &[(&str, u32, &[u64], &[u8])]) -> Gguf {
    Gguf::decode(&build(tensors))
}

#[test]
fn a_matrix_reads_the_rows_and_the_columns_the_file_weighs() {
    let payload = singles(&[0.0; 6]);
    let source = archive(&[("weight", 0, &[3, 2], &payload)]);
    let graph = Graph::new();
    let held = matrix(&graph, &source, "weight", 2, 3);
    assert_eq!(graph.shape(held).dims(), [1, 1, 2, 3]);
    assert_eq!(graph.element(held), Element::Single);
    assert!(refuses(|| matrix(&graph, &source, "weight", 3, 2)));
    assert!(refuses(|| matrix(&graph, &source, "other", 2, 3)));
}

#[test]
fn a_quantized_matrix_walks_the_blocks_the_file_packs() {
    let payload = quantized(4);
    let source = archive(&[("weight", 8, &[32, 4], &payload)]);
    let graph = Graph::new();
    let held = matrix(&graph, &source, "weight", 4, 32);
    assert_eq!(graph.shape(held).dims(), [1, 1, 4, 32]);
    assert_eq!(graph.element(held), Element::Q8_0);
}

#[test]
fn a_vector_reads_the_width_the_file_weighs() {
    let payload = singles(&[0.0; 4]);
    let source = archive(&[("norm", 0, &[4], &payload)]);
    let graph = Graph::new();
    let held = vector(&graph, &source, "norm", 4);
    assert_eq!(graph.shape(held).dims(), [1, 1, 1, 4]);
    assert!(refuses(|| vector(&graph, &source, "norm", 5)));
    assert!(refuses(|| vector(&graph, &source, "weight", 4)));
}

#[test]
fn a_cache_takes_the_rows_of_every_chunk_it_holds() {
    let graph = Graph::new();
    let cache = Cache::new(&graph, 2, 4, 8, 3);
    let [keys, values] = cache.states();
    assert_eq!(graph.shape(keys).dims(), [2, 1, 8, 4]);
    assert_eq!(graph.shape(values).dims(), [2, 1, 8, 4]);
    assert_eq!(cache.rows(), 3);
    let cursor = graph.input(Shape::scalar(), Element::Single);
    let chunk = graph.fill(Shape::of([2, 1, 3, 4]), 1.0);
    let scale = graph.knob(0.5);
    cache.write(
        &graph,
        cursor,
        chunk,
        graph.fill(Shape::of([2, 1, 3, 4]), 0.0),
    );
    assert_eq!(
        graph
            .shape(cache.attend(&graph, chunk, cursor, scale))
            .dims(),
        [2, 1, 3, 4],
    );
    let row = graph.fill(Shape::of([2, 1, 1, 4]), 0.0);
    assert!(refuses(|| cache.write(&graph, cursor, row, chunk)));
    assert!(refuses(|| {
        cache.write(
            &graph,
            cursor,
            chunk,
            graph.fill(Shape::of([3, 1, 3, 4]), 0.0),
        )
    }));
    assert!(refuses(|| cache.attend(&graph, row, cursor, scale)));
    assert!(refuses(|| {
        cache.attend(
            &graph,
            graph.fill(Shape::of([2, 1, 3, 3]), 0.0),
            cursor,
            scale,
        )
    }));
    assert!(refuses(|| Cache::new(&graph, 2, 4, 8, 9)));
    assert!(refuses(|| Cache::new(&graph, 2, 4, 8, 0)));
}