@huggingface/transformers
Version:
State-of-the-art Machine Learning for the web. Run đŸ¤— Transformers directly in your browser, with no need for a server!
83 lines (74 loc) • 2.68 kB
JavaScript
import { Tensor } from './utils/tensor.js';
/**
* A cache class that stores past key values as named tensors.
*/
class _DynamicCache {
/**
* Create a DynamicCache, optionally pre-populated with entries.
* @param {Record<string, Tensor>} [entries] Initial name→Tensor mappings.
*/
constructor(entries) {
if (!entries) return;
for (const key in entries) {
if (key in this) {
throw new TypeError(`Key "${key}" conflicts with an existing property on DynamicCache`);
}
const value = entries[key];
if (!(value instanceof Tensor)) {
throw new TypeError(`Expected a Tensor for key "${key}", got ${typeof value}`);
}
this[key] = value;
}
}
/**
* Get the cached sequence length. This requires at least one attention cache entry to be present.
* @returns {number} The past sequence length.
*/
get_seq_length() {
/** @type {Record<string, Tensor>} */
const self = /** @type {any} */ (this);
if (Object.keys(self).length === 0) {
return 0;
}
for (const name in self) {
if (name.startsWith('past_key_values.')) {
return self[name].dims.at(-2);
}
}
throw new Error('Unable to determine sequence length from the cache.');
}
/**
* Update the cache in-place with new entries, disposing replaced GPU tensors.
* @param {Record<string, Tensor>} newEntries The new name → Tensor mappings.
*/
update(newEntries) {
for (const key in newEntries) {
const oldValue = this[key];
const newValue = newEntries[key];
if (oldValue && oldValue !== newValue && oldValue.location === 'gpu-buffer') {
oldValue.dispose();
}
this[key] = newValue;
}
}
/**
* Dispose all contained tensors whose data resides on the GPU.
* Returns a promise that resolves when all disposals are complete.
* @returns {Promise<void>} Promise that resolves when all GPU tensors are disposed.
*/
async dispose() {
const promises = [];
for (const t of /** @type {Tensor[]} */ (Object.values(this))) {
if (t.location === 'gpu-buffer') {
promises.push(t.dispose());
}
}
await Promise.all(promises);
}
}
/**
* @typedef {Record<string, Tensor> & _DynamicCache} DynamicCache
*/
export const DynamicCache = /** @type {new (entries?: Record<string, Tensor>) => DynamicCache} */ (
/** @type {unknown} */ (_DynamicCache)
);