Skip to content

Sparkline bucketing produces degenerate output for small attention weight arrays #33

@CarsonBurke

Description

@CarsonBurke

Summary

In tui/src/pages/model_observations_page.rs (lines 401-402), the sparkline bucketing for temporal attention weights hardcodes 10 buckets:

let buckets = 10;
let bucket_size = len / buckets;

When len < 10, integer division makes bucket_size = 0. This causes:

  1. Degenerate sparkline: All non-last buckets iterate over empty slices (weights_f[0..0]), producing sum=0. Only the last bucket (which uses end = len) contains any data. The result is 9 zero bars and one bar with all the data — a meaningless visualization.

  2. Potential NaN: If all weights happen to be zero, bucket_max = 0.0, and the normalization v / bucket_max produces NaN. The subsequent NaN.round() as usize is technically undefined behavior in Rust (though practically yields 0).

Reproduction

Any observations.json where an inner attention_weights array has fewer than 10 elements will trigger this. While the current model uses SEQ_LEN = 4000 making this unlikely in normal operation, the code should be defensive since the data comes from a JSON file.

Suggested Fix

Dynamically reduce the bucket count: let buckets = len.min(10);

This ensures bucket_size >= 1 when len > 0 (already guarded by the !weights_f.is_empty() check). Also add a guard for bucket_max == 0.0 to avoid division by zero.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority: lowLow severity bug

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions