Files
wehub-resource-sync 7254f7b4d1
Build / Build (macos-latest) (push) Has been cancelled
Build / Build (ubuntu-latest) (push) Has been cancelled
Build / Build (windows-latest) (push) Has been cancelled
Build / Analyze (javascript) (push) Has been cancelled
Build / Analyze (python) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:37:45 +08:00

199 lines
7.1 KiB
JavaScript

const kann = {};
kann.ModelFactory = class {
async match(context) {
const reader = await context.peek('flatbuffers.binary');
if (reader && reader.identifier === 'KaNN') {
return context.set('kann.flatbuffers', reader);
}
return null;
}
async open(context) {
kann.schema = await context.require('./kann-schema');
kann.schema = kann.schema.kann;
let model = null;
switch (context.type) {
case 'kann.flatbuffers': {
try {
const reader = context.value;
model = kann.schema.Model.create(reader);
} catch (error) {
const message = error && error.message ? error.message : error.toString();
throw new kann.Error(`File format is not kann.Model (${message.replace(/\.$/, '')}).`);
}
break;
}
default: {
throw new kann.Error(`Unsupported KaNN format '${context.type}'.`);
}
}
const metadata = await context.metadata('kann-metadata.json');
return new kann.Model(metadata, model, context.identifier);
}
};
kann.Model = class {
constructor(metadata, model, identifier) {
this.format = 'KaNN';
this.name = identifier;
this.modules = model.graph.map((graph) => new kann.Graph(metadata, graph));
}
};
kann.Graph = class {
constructor(metadata, graph) {
const arcs = new Map();
for (const arc of graph.arcs) {
arcs.set(arc.name, new kann.Value(arc.name, arc.type, null));
}
this.nodes = graph.nodes.map((node) => new kann.Node(metadata, node, arcs));
this.inputs = graph.inputs.map((input) => new kann.Argument(input, [arcs.get(input)]));
this.outputs = graph.outputs.map((output) => new kann.Argument(output, [arcs.get(output)]));
}
};
kann.Node = class {
constructor(metadata, node, arcs) {
this.type = metadata.type(node.type);
this.name = node.name;
this.inputs = [];
this.outputs = [];
this.attributes = [];
const extractData = (value) => {
switch (value.type) {
case 'int': case 'int8': case 'int16': case 'int32': case 'int64': return value.value_int;
case 'uint': case 'uint8': case 'uint16': case 'uint32': case 'uint64': return value.value_uint;
case 'float': case 'float16': case 'float32': case 'float64': return value.value_float;
case 'string': return value.value_string;
case 'int[]': case 'int8[]': case 'int16[]': case 'int32[]': case 'int64[]': return Array.from(value.list_int);
case 'uint[]': case 'uint8[]': case 'uint16[]': case 'uint32[]': case 'uint64[]': return Array.from(value.list_uint);
case 'float[]': case 'float16[]': case 'float32[]': case 'float64[]': return Array.from(value.list_float);
case 'string[]': return Array.from(value.list_string);
default: throw new kann.Error(`Unsupported data type '${value.type}'.`);
}
};
const getAttributeValue = (attribute) => {
if (attribute.type === 'attributes') {
const obj = {};
for (const attr of attribute.attributes) {
obj[attr.name] = getAttributeValue(attr);
}
return obj;
}
if (attribute.value !== null) {
return extractData(attribute.value);
}
throw new kann.Error(`${attribute.name} doesn't have a value.`);
};
if (Array.isArray(node.attributes) && node.attributes.length > 0) {
for (const attr of node.attributes) {
let value = attr.type ? getAttributeValue(attr) : attr;
value = Array.isArray(value) ? value : [value];
const type = value.type === 'attributes' ? null : attr.type || null;
const attribute = new kann.Argument(attr.name, value, type);
this.attributes.push(attribute);
}
}
if (Array.isArray(node.inputs) && node.inputs.length > 0) {
const name = node.inputs.length > 1 ? 'inputs' : 'input';
const argument = new kann.Argument(name, node.inputs.map((input) => arcs.get(input)));
this.inputs.push(argument);
}
if (Array.isArray(node.outputs) && node.outputs.length > 0) {
const name = node.outputs.length > 1 ? 'outputs' : 'output';
const argument = new kann.Argument(name, node.outputs.map((output) => arcs.get(output)));
this.outputs.push(argument);
}
if (Array.isArray(node.params) && node.params.length > 0) {
for (const param of node.params) {
const type = new kann.TensorType(param.type, param.shape);
const data = param.value ? extractData(param.value) : null;
const quantization = param.scale && param.zero_point ? {
type: 'linear',
scale: extractData(param.scale),
offset: extractData(param.zero_point)
} : null;
const tensor = new kann.Tensor(param.name, type, data, quantization);
const value = new kann.Value('', type, tensor);
const argument = new kann.Argument(param.name, [value]);
this.inputs.push(argument);
}
}
if (node.relu) {
const relu = { type: 'ReLU', name: `${node.name}/relu`, params: [] };
this.chain = [new kann.Node(metadata, relu, arcs)];
}
}
};
kann.Argument = class {
constructor(name, value, type = null) {
this.name = name;
this.value = value;
this.type = type;
}
};
kann.Value = class {
constructor(name, type, initializer) {
this.name = name;
this.type = type;
this.initializer = initializer;
this.quantization = initializer && initializer.quantization ? initializer.quantization : null;
}
};
kann.Tensor = class {
constructor(name, type, values, quantization) {
this.name = name;
this.type = type;
this.encoding = Array.isArray(values) ? '|' : '<';
this.values = values;
this.quantization = quantization ? quantization : null;
}
};
kann.TensorType = class {
constructor(dataType, shape) {
this.dataType = dataType || '?';
this.shape = new kann.TensorShape(shape);
}
toString() {
return this.dataType + this.shape.toString();
}
};
kann.TensorShape = class {
constructor(dimensions) {
this.dimensions = Array.from(dimensions);
}
toString() {
if (Array.isArray(this.dimensions) && this.dimensions.length > 0) {
return `[${this.dimensions.map((dimension) => dimension.toString()).join(',')}]`;
}
return '';
}
};
kann.Error = class extends Error {
constructor(message) {
super(message);
this.name = 'Error loading KaNN model.';
}
};
export const ModelFactory = kann.ModelFactory;