Livt packages
Livt.ML
Version 1.6.1
Fixed-size quantized inference, tensor storage, attention, and transformer building blocks for Livt.
Published files (132)
src/attention/ScaledDotProductAttention.lvt
namespace Livt.ML.Attention
using Livt.Math.Arithmetic
using Livt.ML.Activation
/**
* Computes scaled dot-product attention over a four-slot key/value cache.
*/
component ScaledDotProductAttention
{
// Number of integer elements in query, key, value, and output vectors.
public const VECTOR_SIZE: int = 8
// Maximum number of cached key/value pairs.
public const CACHE_SIZE: int = 4
// Integer divisor applied to raw dot-product scores.
public const SCORE_SCALE: int = 3
// Fixed-point scale used by SoftmaxApprox weights.
public const WEIGHT_SCALE: int = 256
// Owned inference subcomponents sharing the caller clock/reset context.
divider: IntegerDivision<32>
kvcache: KVCache
softmax: SoftmaxApprox
// Latest computed result, retained for the caller.
output: int[8]
/**
* Owns cache, softmax, and scheduled score division; serialize operations.
*/
new()
{
divider = new IntegerDivision<32>()
kvcache = new KVCache()
softmax = new SoftmaxApprox()
}
/**
* Adds one key/value pair to the attention cache.
*/
public fn Write(key: int[8], val: int[8])
{
kvcache.Write(key, val)
}
/**
* Computes attention for query against the cached key/value pairs.
*/
public fn Compute(query: int[8])
{
var activeCount = kvcache.GetSize()
if (activeCount == 0) {
for (var elem = 0; elem < VECTOR_SIZE; elem++) {
output[elem] = 0
}
return
}
var scores: int[8]
for (var slot = 0; slot < activeCount; slot++) {
var dot = 0
for (var elem = 0; elem < VECTOR_SIZE; elem++) {
dot = dot + query[elem] * kvcache.GetKeyElement(slot, elem)
}
scores[slot] = divider.Divide(dot, SCORE_SCALE)
}
softmax.ComputeCount(scores, activeCount)
for (var elem = 0; elem < VECTOR_SIZE; elem++) {
var weighted = 0
for (var slot = 0; slot < activeCount; slot++) {
weighted = weighted + softmax.GetOutput(slot) * kvcache.GetValueElement(slot, elem)
}
output[elem] = weighted / WEIGHT_SCALE
}
}
/**
* Returns one attention output element, or zero when index is out of range.
*/
public fn GetOutput(index: int) int
{
if (index < 0) {
return 0
}
if (index >= VECTOR_SIZE) {
return 0
}
return output[index]
}
/**
* Returns the number of key/value pairs currently cached.
*/
public fn GetCacheSize() int
{
return kvcache.GetSize()
}
/**
* Clears the owned key/value cache.
*/
public fn ClearCache()
{
kvcache.Clear()
}
}