| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415 |
- import * as base from './base.js';
- import * as flatbuffers from './flatbuffers.js';
- import * as protobuf from './protobuf.js';
- import * as python from './python.js';
- const paddle = {};
- paddle.ModelFactory = class {
- async match(context) {
- const identifier = context.identifier;
- const extension = identifier.lastIndexOf('.') > 0 ? identifier.split('.').pop().toLowerCase() : '';
- if (identifier === '__model__' || extension === '__model__' || extension === 'paddle' || extension === 'pdmodel') {
- const tags = await context.tags('pb');
- if (tags.get(1) === 2) {
- return context.set('paddle.pb');
- }
- }
- if (extension === 'pbtxt' || extension === 'txt') {
- const tags = await context.tags('pbtxt');
- if (tags.has('blocks')) {
- return context.set('paddle.pbtxt');
- }
- }
- const stream = context.stream;
- if (stream && stream.length > 16 && stream.peek(16).every((value) => value === 0x00)) {
- return context.set('paddle.params');
- }
- const pickle = await paddle.Pickle.open(context);
- if (pickle) {
- return context.set(pickle.name, pickle);
- }
- const entries = await paddle.Entries.open(context);
- if (entries) {
- return context.set(entries.name, entries);
- }
- const naive = await paddle.NaiveBuffer.open(context);
- if (naive) {
- return context.set(naive.name, naive);
- }
- const obj = await context.peek('json');
- if (obj && obj.base_code && obj.program) {
- return context.set('paddle.ir', obj);
- }
- return null;
- }
- filter(context, match) {
- if (context.type === 'paddle.pb' && (match.type === 'paddle.params' || match.type === 'paddle.pickle')) {
- return false;
- }
- if (context.type === 'paddle.naive.model' && match.type === 'paddle.naive.param') {
- return false;
- }
- return true;
- }
- async open(context) {
- const metadata = await context.metadata('paddle-metadata.json');
- switch (context.type) {
- case 'paddle.naive':
- case 'paddle.naive.model':
- case 'paddle.naive.param': {
- paddle.schema = await context.require('./paddle-schema');
- paddle.schema = paddle.schema.paddle.lite.fbs.proto;
- const target = context.value;
- target.read();
- return new paddle.Model(metadata, target.format, target.model, target.weights);
- }
- case 'paddle.ir': {
- const ir = new paddle.IR(context.value);
- const format = `PaddlePaddle IR v${ir.version}`;
- return new paddle.Model(metadata, format, ir.desc, ir.tensors);
- }
- default: {
- paddle.proto = await context.require('./paddle-proto');
- paddle.proto = paddle.proto.paddle.framework.proto;
- const identifier = context.identifier;
- const parts = identifier.split('.');
- const extension = parts.pop().toLowerCase();
- const base = parts.join('.');
- const openProgram = async (context, type) => {
- const program = {};
- switch (type) {
- case 'paddle.pbtxt': {
- try {
- const reader = await context.read('protobuf.text');
- reader.enum = function(type) {
- const token = this.token();
- this.next();
- this.semicolon();
- if (type[token] !== undefined) {
- return type[token];
- }
- if (token === 'LOD_TENSOR') {
- return type.DENSE_TENSOR;
- }
- throw new paddle.Error(`Unknown enum value '${token}' ${this.location()}`);
- };
- reader.field = function(tag, message) {
- if (message instanceof paddle.proto.VarType && tag === 'lod_tensor') {
- message.dense_tensor = paddle.proto.VarType.DenseTensorDesc.decodeText(reader);
- } else {
- throw new Error(`Unknown field '${tag}' ${this.location()}`);
- }
- };
- program.desc = paddle.proto.ProgramDesc.decodeText(reader);
- } catch (error) {
- const message = error && error.message ? error.message : error.toString();
- throw new paddle.Error(`File text format is not paddle.ProgramDesc (${message.replace(/\.$/, '')}).`);
- }
- break;
- }
- case 'paddle.pb': {
- try {
- const reader = await context.read('protobuf.binary');
- program.desc = paddle.proto.ProgramDesc.decode(reader);
- } catch (error) {
- const message = error && error.message ? error.message : error.toString();
- throw new paddle.Error(`File format is not paddle.ProgramDesc (${message.replace(/\.$/, '')}).`);
- }
- break;
- }
- default: {
- throw new paddle.Error(`Unsupported Paddle format '${type}'.`);
- }
- }
- const formatVersion = (version) => {
- if (version && version.version !== undefined) {
- const number = version.version.toNumber();
- if (number > 0) {
- const list = [Math.floor(number / 1000000) % 1000, Math.floor(number / 1000) % 1000, number % 1000];
- if (list.slice(-1).pop() === 0) {
- list.pop();
- if (list.slice(-1).pop() === 0) {
- list.pop();
- }
- }
- return ` v${list.map((item) => item.toString()).join('.')}`;
- }
- }
- return '';
- };
- program.format = `PaddlePaddle${formatVersion(program.desc.version)}`;
- const variables = new Set();
- for (const block of program.desc.blocks) {
- const blockVars = new Set();
- for (const variable of block.vars) {
- if (variable.persistable && variable.type &&
- variable.type.type !== paddle.DataType.FETCH_LIST &&
- variable.type.type !== paddle.DataType.FEED_MINIBATCH) {
- blockVars.add(variable.name);
- }
- }
- for (const op of block.ops) {
- for (const input of op.inputs) {
- for (const argument of input.arguments) {
- if (blockVars.has(argument)) {
- variables.add(argument);
- }
- }
- }
- }
- }
- program.vars = Array.from(variables).sort();
- return program;
- };
- const loadParams = (stream) => {
- const params = [];
- while (stream.position < stream.length) {
- const tensor = paddle.Utility.openTensorDesc(stream);
- params.push(tensor);
- }
- return params;
- };
- const mapParams = (params, program) => {
- const weights = new Map();
- const vars = program.vars.slice();
- for (const param of params) {
- weights.set(vars.shift(), param);
- }
- return weights;
- };
- switch (context.type) {
- case 'paddle.pickle': {
- const target = context.value;
- return new paddle.Model(metadata, target.format, null, target.weights);
- }
- case 'paddle.entries': {
- const target = context.value;
- target.read();
- return new paddle.Model(metadata, target.format, null, target.weights);
- }
- case 'paddle.params': {
- const file = identifier === 'params' ? 'model' : `${base}.pdmodel`;
- const params = loadParams(context.stream);
- try {
- const content = await context.fetch(file);
- const program = await openProgram(content, 'paddle.pb');
- const weights = mapParams(params, program);
- return new paddle.Model(metadata, program.format, program.desc, weights);
- } catch {
- const weights = new Map(params.map((param, index) => [index.toString(), param]));
- return new paddle.Model(metadata, 'PaddlePaddle Inference Weights', null, weights);
- }
- }
- case 'paddle.pb':
- case 'paddle.pbtxt': {
- const loadEntries = async (context, program) => {
- const promises = program.vars.map((name) => context.fetch(name).then((context) => context.stream).catch(() => null));
- const streams = await Promise.all(promises);
- const params = streams.map((stream) => stream ? paddle.Utility.openTensorDesc(stream) : null);
- const weights = mapParams(params, program);
- return new paddle.Model(metadata, program.format, program.desc, weights);
- };
- const openNumPyArrayPickle = (stream) => {
- const execution = new python.Execution();
- const pickle = execution.__import__('pickle');
- const unpickler = new pickle.Unpickler(stream);
- const obj = unpickler.load();
- const container = new paddle.Pickle(obj);
- return container.weights || new Map();
- };
- const program = await openProgram(context, context.type);
- if (extension === 'pdmodel') {
- try {
- const name = `${base}.pdiparams`;
- const content = await context.fetch(name);
- const params = loadParams(content.stream);
- const weights = mapParams(params, program);
- return new paddle.Model(metadata, program.format, program.desc, weights);
- } catch {
- try {
- const name = `${base}.pdparams`;
- const content = await context.fetch(name);
- const weights = openNumPyArrayPickle(content.stream);
- try {
- const name = `${base}.pdopt`;
- const content = await context.fetch(name);
- for (const [name, value] of openNumPyArrayPickle(content.stream)) {
- if (!weights.has(name)) {
- weights.set(name, value);
- }
- }
- return new paddle.Model(metadata, program.format, program.desc, weights);
- } catch {
- return new paddle.Model(metadata, program.format, program.desc, weights);
- }
- } catch {
- try {
- const name = `${base}.pdopt`;
- const content = await context.fetch(name);
- const weights = openNumPyArrayPickle(content.stream);
- return new paddle.Model(metadata, program.format, program.desc, weights);
- } catch {
- return loadEntries(context, program);
- }
- }
- }
- }
- if (identifier === 'model') {
- try {
- const content = await context.fetch('params');
- const params = loadParams(content.stream);
- const weights = mapParams(params, program);
- return new paddle.Model(metadata, program.format, program.desc, weights);
- } catch {
- return loadEntries(context, program);
- }
- }
- return loadEntries(context, program);
- }
- default: {
- throw new paddle.Error(`Unsupported PaddlePaddle format '${context.type}'.`);
- }
- }
- }
- }
- }
- };
- paddle.Model = class {
- constructor(metadata, format, desc, tensors) {
- desc = desc && Array.isArray(desc.blocks) ? desc : { blocks: [null] };
- this.format = format;
- this.modules = desc.blocks.map((block) => new paddle.Graph(metadata, block, tensors));
- }
- };
- paddle.Graph = class {
- constructor(metadata, block, tensors) {
- this.nodes = [];
- this.inputs = [];
- this.outputs = [];
- if (block) {
- this.name = block.idx.toString();
- const values = new Map();
- if (block.kind === 'block') {
- for (const [name, input] of block.argInputs) {
- const [parameter, tensorType] = input;
- const value = new paddle.Value(name, tensorType, null, null);
- values.set(name, value);
- this.inputs.push(new paddle.Argument(parameter, [value]));
- }
- }
- for (const variable of block.vars) {
- const type = variable.type && variable.type.type && variable.type.dense_tensor && variable.type.dense_tensor.tensor ? paddle.Utility.createTensorType(variable.type.dense_tensor.tensor.data_type, variable.type.dense_tensor.tensor.dims) : null;
- const tensor = variable.persistable && variable.type && variable.type.type !== paddle.DataType.FETCH_LIST && variable.type.type !== paddle.DataType.FEED_MINIBATCH ? (tensors.get(variable.name) || new paddle.Tensor(type)) : null;
- values.set(variable.name, new paddle.Value(variable.name, type, tensor));
- }
- const scope = {};
- for (let i = 0; i < block.ops.length; i++) {
- for (const input of block.ops[i].inputs) {
- input.arguments = input.arguments.map((argument) => scope[argument] ? scope[argument] : argument);
- }
- for (const output of block.ops[i].outputs) {
- output.arguments = output.arguments.map((argument) => {
- if (scope[argument]) {
- const next = `${argument}\n${i}`; // custom argument id
- scope[argument] = next;
- return next;
- }
- scope[argument] = argument;
- return argument;
- });
- }
- }
- for (const op of block.ops) {
- for (const input of op.inputs) {
- for (const name of input.arguments) {
- if (!values.has(name)) {
- values.set(name, new paddle.Value(name, null, null));
- }
- }
- }
- for (const output of op.outputs) {
- for (const name of output.arguments) {
- if (output.values && output.values.has(name)) {
- values.set(name, output.values.get(name));
- }
- if (!values.has(name)) {
- values.set(name, new paddle.Value(name, null, null));
- }
- }
- }
- }
- let lastNode = null;
- let lastOutput = null;
- for (const op of block.ops) {
- if (op.type === 'feed') {
- let name = '';
- const attr = op.attrs.find((attr) => attr.name === 'col');
- if (attr) {
- if (op.kind === 'op') {
- name = attr.irValue.toString();
- } else {
- name = attr.i.toString();
- }
- }
- const argument = new paddle.Argument(name, op.outputs[0].arguments.map((id) => values.get(id)));
- this.inputs.push(argument);
- } else if (op.type === 'fetch') {
- let name = '';
- const attr = op.attrs.find((attr) => attr.name === 'col');
- if (attr) {
- if (op.kind === 'op') {
- name = attr.irValue.toString();
- } else {
- name = attr.i.toString();
- }
- }
- const argument = new paddle.Argument(name, op.inputs[0].arguments.map((id) => values.get(id)));
- this.outputs.push(argument);
- } else {
- const node = new paddle.Node(metadata, op, values);
- if (op.inputs.length === 1 && op.inputs[0].arguments.length === 1 &&
- op.outputs.length >= 1 && op.outputs[0].arguments.length === 1 &&
- op.inputs[0].arguments[0].split('\n').shift() === op.outputs[0].arguments[0].split('\n').shift() &&
- lastNode &&
- lastOutput === op.inputs[0].arguments[0].split('\n').shift()) {
- lastNode.chain.push(node);
- } else {
- this.nodes.push(node);
- lastNode = null;
- lastOutput = null;
- if (op.outputs.length === 1 && op.outputs[0].arguments.length === 1) {
- lastNode = node;
- lastOutput = op.outputs[0].arguments[0].split('\n').shift();
- }
- }
- }
- }
- } else {
- const values = new Map();
- const ops = new Map();
- for (const [name, tensor] of tensors) {
- values.set(name, new paddle.Value(name, tensor.type, tensor));
- const separator = name.indexOf('.') === -1 ? '_' : '.';
- const regex = /(.*)_((w_attr|scale|weights|offset|b|w|b_attr)_(moment|beta|velocity|mean_square|mean_grad).*)/;
- let parts = [];
- if (separator === '.') {
- parts = name.split(separator);
- } else if (regex.test(name)) {
- parts = regex.exec(name).slice(1, 3);
- } else {
- parts = ['', name];
- }
- const parameter_name = parts.pop();
- const op_name = parts.join(separator);
- if (!ops.has(op_name)) {
- ops.set(op_name, { name: op_name, type: 'Weights', inputs: [] });
- }
- const op = ops.get(op_name);
- op.inputs.push({ parameter: parameter_name, arguments: [name] });
- }
- for (const op of Array.from(ops.values())) {
- this.nodes.push(new paddle.Node(metadata, op, values));
- }
- }
- }
- };
- paddle.Argument = class {
- constructor(name, value, type, visible) {
- this.name = name;
- this.value = value;
- if (type) {
- this.type = type;
- }
- if (visible === false) {
- this.visible = visible;
- }
- }
- };
- paddle.Value = class {
- constructor(name, type, initializer = null) {
- if (typeof name !== 'string') {
- throw new paddle.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);
- }
- this.name = name;
- this.type = !type && initializer ? initializer.type : type;
- this.initializer = initializer;
- }
- };
- paddle.Node = class {
- constructor(metadata, op, values) {
- const type = op.type;
- this.type = metadata.type(type) || { name: type };
- this.name = op.name || '';
- this.description = op.description || '';
- this.identifier = op.identifier || '';
- this.attributes = [];
- this.inputs = [];
- this.outputs = [];
- this.chain = [];
- if (op.attrs) {
- this.attributes = op.attrs.map((attr) => {
- const name = attr.name;
- const meta = metadata.attribute(this.type.name, name);
- let value = '?';
- let visible = true;
- let type = null;
- switch (attr.type) {
- case paddle.AttributeType.STRING:
- type = 'string';
- value = attr.s;
- break;
- case paddle.AttributeType.STRINGS:
- type = 'string[]';
- value = Array.from(attr.strings);
- break;
- case paddle.AttributeType.BOOLEAN:
- type = 'boolean';
- value = attr.b;
- break;
- case paddle.AttributeType.BOOLEANS:
- type = 'boolean[]';
- value = attr.bools ? Array.from(attr.bools) : attr.bools;
- break;
- case paddle.AttributeType.FLOAT:
- type = 'float32';
- value = attr.f;
- break;
- case paddle.AttributeType.FLOATS:
- type = 'float32[]';
- value = attr.floats ? Array.from(attr.floats) : attr.floats;
- break;
- case paddle.AttributeType.FLOAT64:
- type = 'float64';
- value = attr.float64;
- break;
- case paddle.AttributeType.FLOAT64S:
- type = 'float64[]';
- value = attr.float64s ? Array.from(attr.float64s) : attr.float64s;
- break;
- case paddle.AttributeType.INT:
- type = 'int32';
- value = attr.i;
- break;
- case paddle.AttributeType.INTS:
- type = 'int32[]';
- value = attr.ints ? Array.from(attr.ints) : attr.ints;
- break;
- case paddle.AttributeType.LONG:
- type = 'int64';
- break;
- case paddle.AttributeType.LONGS:
- type = 'int64[]';
- break;
- case 1000: // ir
- type = attr.irType;
- value = attr.irValue;
- break;
- case 1001: // graph
- type = 'graph';
- value = new paddle.Graph(metadata, attr.block, attr.vars);
- break;
- default:
- break;
- }
- switch (name) {
- case 'use_mkldnn':
- case 'use_cudnn':
- case 'op_callstack':
- case 'op_role':
- case 'op_role_var':
- case 'op_namescope':
- case 'is_test':
- visible = false;
- break;
- default:
- break;
- }
- if (meta) {
- if (meta.default !== undefined) {
- const defaultValue = meta.default;
- if (defaultValue === value) {
- visible = false;
- } else if (Array.isArray(value) && Array.isArray(defaultValue) && value.length === defaultValue.length) {
- if (value.every((item, index) => item === defaultValue[index])) {
- visible = false;
- }
- }
- }
- }
- return new paddle.Argument(name, value, type, visible);
- });
- }
- if (op.inputs) {
- for (const input of op.inputs) {
- if (input.arguments.length > 0) {
- this.inputs.push(new paddle.Argument(input.parameter, input.arguments.map((name) => values.get(name))));
- }
- }
- }
- if (op.outputs) {
- for (const output of op.outputs) {
- if (output.arguments.length > 0) {
- this.outputs.push(new paddle.Argument(output.parameter, output.arguments.map((name) => values.get(name))));
- }
- }
- }
- const updates = [
- [this.inputs, 'X'],
- [this.inputs, 'Input'],
- [this.outputs, 'Y'],
- [this.outputs, 'Out']
- ];
- for (const [list, name] of updates) {
- let item = null;
- for (let i = 0; i < list.length; i++) {
- if (list[i].name === name) {
- item = list[i];
- list.splice(i, 1);
- break;
- }
- }
- if (item) {
- list.splice(0, 0, item);
- }
- }
- }
- };
- paddle.Tensor = class {
- constructor(type, data, category = '') {
- this.type = type;
- this.values = data;
- this.category = category;
- }
- };
- paddle.TensorType = class {
- constructor(dataType, shape, layout, denotation) {
- this.dataType = dataType;
- this.shape = shape;
- this.layout = layout;
- this.denotation = denotation;
- }
- toString() {
- return this.dataType + this.shape.toString();
- }
- };
- paddle.TensorShape = class {
- constructor(dimensions) {
- dimensions = dimensions.map((dim) => typeof dim === 'bigint' ? dim.toNumber() : dim);
- this.dimensions = dimensions.map((dimension) => {
- return dimension === -1 ? '?' : dimension;
- });
- }
- toString() {
- return (this.dimensions && this.dimensions.length) ? (`[${this.dimensions.join(',')}]`) : '';
- }
- };
- paddle.Entries = class {
- static async open(context) {
- let entries = await context.peek('zip');
- if (entries instanceof Map === false) {
- entries = await context.peek('tar');
- }
- if (entries instanceof Map) {
- entries = Array.from(entries);
- entries = new Map(entries.filter(([name]) => !name.endsWith('/') && !name.split('/').pop().startsWith('.')).slice());
- if (entries.size > 2 && Array.from(entries).every(([name, value]) => name.split('_').length > 0 && value.peek(16).every((value) => value === 0x00))) {
- return new paddle.Entries(entries);
- }
- }
- return null;
- }
- constructor(data) {
- this.name = 'paddle.entries';
- this.format = 'PaddlePaddle Weights';
- this.data = data;
- }
- read() {
- if (this.data) {
- let rootFolder = null;
- for (const [name] of this.data) {
- if (!name.startsWith('.') || name.startsWith('./')) {
- const parts = name.split('/');
- let folder = '';
- if (parts.length > 2 && parts[0] === '.') {
- folder = `./${parts[1]}/`;
- } else if (parts.length > 1) {
- folder = `${parts[0]}/`;
- }
- if (rootFolder !== null && rootFolder !== '' && folder !== rootFolder) {
- rootFolder = '';
- } else {
- rootFolder = folder;
- }
- }
- }
- this.weights = new Map();
- for (const [name, stream] of this.data) {
- if (name.startsWith(rootFolder)) {
- const key = name.substring(rootFolder.length);
- const tensor = paddle.Utility.openTensorDesc(stream);
- this.weights.set(key, tensor);
- }
- }
- delete this.data;
- }
- }
- };
- paddle.Pickle = class {
- static async open(context) {
- const obj = await context.peek('pkl');
- const container = new paddle.Pickle(obj);
- if (container.weights !== null) {
- return container;
- }
- return null;
- }
- constructor(obj) {
- this.name = 'paddle.pickle';
- this.format = 'PaddlePaddle Pickle';
- this._weights = null;
- if (obj && !Array.isArray(obj) && (obj instanceof Map || Object(obj) === obj)) {
- const entries = (obj) => {
- if (obj instanceof Map) {
- return Array.from(obj);
- } else if (Object(obj) === obj) {
- return Object.entries(obj);
- }
- return [];
- };
- const filter = (obj) => {
- const list = [];
- if (obj && !Array.isArray(obj)) {
- for (const [name, value] of entries(obj)) {
- if (name !== 'StructuredToParameterName@@') {
- const obj = value && Array.isArray(value) && value.length === 2 && value[0] === name ? value[1] : value;
- if (obj && !Array.isArray(obj) && obj.__class__ && obj.__class__.__module__ === 'numpy' && obj.__class__.__name__ === 'ndarray') {
- list.push([name, obj]);
- }
- }
- }
- }
- return list;
- };
- const weights = filter(obj);
- if (weights.length > 0) {
- this._weights = weights;
- } else {
- const list = entries(obj);
- if (list.filter(([name]) => name !== 'StructuredToParameterName@@').length === 1) {
- const weights = filter(list[0][1]);
- if (weights.length > 0) {
- this._weights = weights;
- }
- }
- if (this._weights === null && list.filter(([name]) => name === 'StructuredToParameterName@@').length > 0) {
- this._weights = [];
- }
- }
- }
- }
- get weights() {
- if (this._weights && Array.isArray(this._weights)) {
- const weights = new Map();
- for (const [name, value] of this._weights) {
- const type = new paddle.TensorType(value.dtype.__name__, new paddle.TensorShape(value.shape));
- const data = value.data;
- const tensor = new paddle.Tensor(type, data, 'NumPy Array');
- weights.set(name, tensor);
- }
- this._weights = weights;
- }
- return this._weights;
- }
- };
- paddle.NaiveBuffer = class {
- static async open(context) {
- const stream = context.stream;
- if (stream && stream.length > 4) {
- const buffer = stream.peek(4);
- if (buffer[0] > 2 || buffer[1] !== 0x00 || buffer[2] !== 0x76 || buffer[3] !== 0x32) {
- if (context.identifier === '__model__.nb') {
- return new paddle.NaiveBuffer('paddle.naive.model', stream, -1);
- }
- if (context.identifier === 'param.nb') {
- return new paddle.NaiveBuffer('paddle.naive.param', stream, -1);
- }
- }
- if (buffer[1] === 0x00 && buffer[0] <= 2) {
- return new paddle.NaiveBuffer('paddle.naive', stream, buffer[0]);
- }
- }
- return null;
- }
- constructor(name, stream, meta_version) {
- this.name = name;
- this.stream = stream;
- this.meta_version = meta_version;
- }
- read() {
- const reader = base.BinaryReader.open(this.stream);
- if (this.meta_version >= 2) {
- reader.skip(2);
- }
- const decoder = new TextDecoder('utf-8');
- const opt_version = reader.read(16);
- const version = decoder.decode(opt_version.slice(0, opt_version.indexOf(0x00)));
- this.format = `Paddle Lite${version && version.match(/^v\d+\.\d+\.\d+$/) ? ` ${version}` : ''}`;
- const topo_size = reader.uint64().toNumber();
- const openProgramDesc = (buffer) => {
- const reader = flatbuffers.BinaryReader.open(buffer);
- return paddle.schema.ProgramDesc.create(reader);
- };
- const openParamDesc = (buffer) => {
- const reader = flatbuffers.BinaryReader.open(buffer);
- return paddle.schema.ParamDesc.create(reader);
- };
- switch (this.meta_version) {
- case -1: {
- throw new paddle.Error('Paddle Lite naive buffer format is deprecated.');
- }
- case 0:
- case 1: {
- throw new paddle.Error(`Paddle Lite meta format '${this.meta_version}' is deprecated.`);
- }
- case 2: {
- const topo_data = new Uint8Array(topo_size);
- topo_data.set(reader.read(topo_size), 0);
- this.model = openProgramDesc(topo_data);
- reader.uint16(); // version
- reader.uint16(); // meta_size
- const header_size = reader.uint16();
- const params_size = reader.uint16();
- reader.uint32(); // max_tensor_size
- reader.skip(header_size - 6);
- this.weights = new Map();
- for (let i = 0; i < params_size; i++) {
- const total_size = reader.uint32();
- const offset = reader.uint32();
- const param_bytes = total_size - offset;
- const param_data = reader.read(param_bytes);
- const desc = openParamDesc(param_data);
- const data = desc.variable.data;
- const data_type = desc.variable.data_type;
- const dim = desc.variable.dim;
- const type = paddle.Utility.createTensorType(data_type, dim);
- const tensor = new paddle.Tensor(type, data);
- this.weights.set(desc.name, tensor);
- }
- break;
- }
- default: {
- throw new paddle.Error(`Unsupported Paddle Lite naive buffer meta format '${this.meta_version}'.`);
- }
- }
- delete this.stream;
- }
- };
- paddle.Utility = class {
- static createTensorType(data_type, shape) {
- if (!paddle.Utility._dataTypes) {
- const length = Math.max.apply(null, Object.entries(paddle.DataType).map(([, value]) => value));
- paddle.Utility._dataTypes = new Array(length);
- const types = new Map([
- ['bool', 'boolean'],
- ['bf16', 'bfloat16'], ['fp16', 'float16'], ['fp32', 'float32'], ['fp64', 'float64'],
- ['fp8_e4m3fn', 'float8e4m3fn'], ['fp8_e5m2', 'float8e5m2']
- ]);
- for (const [name, index] of Object.entries(paddle.DataType)) {
- const key = name.toLowerCase();
- paddle.Utility._dataTypes[index] = types.has(key) ? types.get(key) : key;
- }
- }
- const dataType = data_type < paddle.Utility._dataTypes.length ? paddle.Utility._dataTypes[data_type] : '?';
- return new paddle.TensorType(dataType, new paddle.TensorShape(shape));
- }
- static openTensorDesc(stream) {
- const signature = stream.read(16);
- if (!signature.every((value) => value === 0x00)) {
- throw new paddle.Error('Invalid paddle.TensorDesc signature.');
- }
- const length = base.BinaryReader.open(stream.read(4)).uint32();
- const buffer = stream.read(length);
- const reader = protobuf.BinaryReader.open(buffer);
- const tensorDesc = paddle.proto.VarType.TensorDesc.decode(reader);
- const dims = tensorDesc.dims.map((dim) => dim.toNumber());
- const size = dims.reduce((a, b) => a * b, 1);
- let itemsize = 0;
- switch (tensorDesc.data_type) {
- case paddle.DataType.BOOL: itemsize = 1; break;
- case paddle.DataType.FP16: itemsize = 2; break;
- case paddle.DataType.FP32: itemsize = 4; break;
- case paddle.DataType.FP64: itemsize = 8; break;
- case paddle.DataType.INT8: itemsize = 1; break;
- case paddle.DataType.INT16: itemsize = 2; break;
- case paddle.DataType.INT32: itemsize = 4; break;
- case paddle.DataType.INT64: itemsize = 8; break;
- case paddle.DataType.UINT8: itemsize = 1; break;
- default: throw new paddle.Error(`Invalid inference params data type '${tensorDesc.data_type}'.`);
- }
- const type = paddle.Utility.createTensorType(tensorDesc.data_type, tensorDesc.dims);
- const data = stream.read(itemsize * size);
- return new paddle.Tensor(type, data);
- }
- };
- paddle.DataType = {
- BOOL: 0,
- INT16: 1,
- INT32: 2,
- INT64: 3,
- FP16: 4,
- FP32: 5,
- FP64: 6,
- DENSE_TENSOR: 7,
- SELECTED_ROWS: 8,
- FEED_MINIBATCH: 9,
- FETCH_LIST: 10,
- STEP_SCOPES: 11,
- LOD_RANK_TABLE: 12,
- DENSE_TENSOR_ARRAY: 13,
- PLACE_LIST: 14,
- READER: 15,
- RAW: 17,
- TUPLE: 18,
- SIZE_T: 19,
- UINT8: 20,
- INT8: 21,
- BF16: 22,
- COMPLEX64: 23,
- COMPLEX128: 24,
- STRING: 25,
- STRINGS: 26,
- FP8_E4M3FN: 32,
- FP8_E5M2: 33,
- };
- paddle.AttributeType = {
- INT: 0,
- FLOAT: 1,
- STRING: 2,
- INTS: 3,
- FLOATS: 4,
- STRINGS: 5,
- BOOLEAN: 6,
- BOOLEANS: 7,
- BLOCK: 8,
- LONG: 9,
- BLOCKS: 10,
- LONGS: 11,
- FLOAT64S: 12,
- VAR: 13,
- VARS: 14,
- FLOAT64: 15
- };
- paddle.IR = class {
- constructor(obj) {
- this._names = new Map();
- this._crossRegionInputs = new Map();
- this.base_code = obj.base_code;
- this.version = obj.base_code.version;
- const program = obj.program;
- const regions = [];
- for (const region of program.regions) {
- regions.push(this.region(region));
- }
- const [programRegion] = regions;
- this.desc = programRegion;
- this.tensors = new Map();
- }
- region(value) {
- const obj = {};
- obj.kind = 'region';
- obj.name = value['#'];
- obj.idx = value['#'];
- obj.vars = new Map();
- obj.blocks = [];
- for (const block of value.blocks) {
- obj.blocks.push(this.block(block));
- }
- const [block] = obj.blocks;
- obj.block = block;
- return obj;
- }
- block(value) {
- const obj = {};
- obj.kind = 'block';
- obj.name = value['#'];
- obj.idx = value['#'];
- obj.vars = new Map();
- obj.argInputs = new Map();
- if (value.args) {
- for (const input of value.args) {
- const [, type] = input.TT && input.TT['#'] ? input.TT['#'].split('.') : null;
- if (type === 't_dtensor') {
- const [parameter, name,] = this.getParaName(input);
- const tensorType = this.createTensorType(input);
- obj.argInputs.set(name, [parameter, tensorType]);
- }
- }
- }
- let inputNames = new Set();
- let outputNames = new Set();
- obj.ops = [];
- for (const op of value.ops) {
- const irOp = this.op(op);
- obj.ops.push(irOp);
- inputNames = new Set([...inputNames, ...irOp.inputNames]);
- outputNames = new Set([...outputNames, ...irOp.outputNames]);
- }
- const missInputs = new Set([...inputNames].filter((item) => !outputNames.has(item)));
- if (missInputs) {
- for (const name of missInputs) {
- const output = this.getCrossInput(name);
- if (output) {
- obj.argInputs.set(name, [output.parameter, output.tensorType]);
- }
- }
- }
- return obj;
- }
- op(op) {
- const obj = {};
- obj.kind = 'op';
- const opInfo = this.getOpInfo(op);
- obj.name = opInfo.fullName;
- obj.type = opInfo.type;
- obj.identifier = opInfo.rawType;
- obj.attrs = [];
- for (const [idx, value] of Object.entries(op.A)) {
- obj.attrs.push(this.attr(idx, value, opInfo));
- }
- if (op.regions !== undefined) {
- for (const region of op.regions) {
- const regionAttr = this.region(region);
- obj.attrs.push(this.attr(null, regionAttr, null));
- }
- }
- const inputNames = new Set();
- const outputNames = new Set();
- const createInput = (input, opInfo) => {
- const [parameterName, inputName] = this.getParaName(input, opInfo.namePrefix);
- return { arguments: [inputName], parameter: parameterName };
- };
- const inputs = [];
- if (op.I) {
- const inputArray = Array.isArray(op.I) ? op.I : [op.I];
- for (const input of inputArray) {
- inputs.push(createInput(input, opInfo));
- const [, name] = this.getParaName(input, opInfo.namePrefix);
- inputNames.add(name);
- }
- }
- const createOutput = (output, opInfo, idx, outputAttr) => {
- const [parameterName, outputName] = this.getParaName(output, opInfo.namePrefix);
- const valuesMap = new Map();
- let tType = null;
- const [, typeType] = output.TT['#'].split('.');
- if (typeType === 't_dtensor') {
- const denotation = this.getOutputAttr(opInfo, idx, outputAttr);
- const tensorType = this.createTensorType(output, denotation);
- valuesMap.set(outputName, new paddle.Value(outputName, tensorType, null));
- tType = tensorType;
- } else {
- valuesMap.set(outputName, new paddle.Value(outputName, null, null, null));
- }
- return {
- arguments: [outputName],
- parameter: parameterName,
- tensorType: tType,
- values: valuesMap
- };
- };
- const outputs = [];
- if (op.O) {
- const outputArray = Array.isArray(op.O) ? op.O : [op.O];
- for (const [idx, output] of Object.entries(outputArray)) {
- const irOutput = createOutput(output, opInfo, idx, op.OA);
- outputs.push(irOutput);
- const [, name, isNegative] = this.getParaName(output, opInfo.namePrefix);
- outputNames.add(name);
- if (!isNegative && !this.hasCrossInput(name)) {
- this.addCrossInput(name, irOutput);
- }
- }
- }
- if (op.regions) {
- const collectRegions = (irReader, regions) => {
- let inputs = new Map();
- let outputs = new Map();
- for (const region of regions) {
- for (const block of region.blocks) {
- for (const op of block.ops) {
- const opInfo = this.getOpInfo(op);
- if (op.I) {
- const opInputs = Array.isArray(op.I) ? op.I : [op.I];
- for (const input of opInputs) {
- const [, name, isNegative] = irReader.getParaName(input, opInfo.namePrefix);
- if (!isNegative && !inputs.has(name)) {
- inputs.set(name, [input, opInfo]);
- }
- }
- }
- if (op.O) {
- const opOutputs = Array.isArray(op.O) ? op.O : [op.O];
- for (const [idx, output] of Object.entries(opOutputs)) {
- const [, name, isNegative] = irReader.getParaName(output, opInfo.namePrefix);
- if (!isNegative && !outputs.has(name)) {
- outputs.set(name, [output, opInfo, idx, op.OA]);
- }
- }
- }
- if (op.regions) {
- const [subInputs, subOutputs] = collectRegions(irReader, op.regions);
- inputs = new Map([...inputs, ...subInputs]);
- outputs = new Map([...outputs, ...subOutputs]);
- }
- }
- }
- }
- return [inputs, outputs];
- };
- const [subInputs, subOutputs] = collectRegions(this, op.regions);
- for (const [name, inputArgs] of subInputs) {
- if (!inputNames.has(name) && !subOutputs.has(name)) {
- const [input, opInfo] = inputArgs;
- inputs.push(createInput(input, opInfo));
- inputNames.add(name);
- }
- }
- for (const [name, outputArgs] of subOutputs) {
- if (!outputNames.has(name) && !subInputs.has(name)) {
- const [output, opInfo, idx, oa] = outputArgs;
- outputs.push(createOutput(output, opInfo, idx, oa));
- outputNames.add(name);
- }
- }
- }
- obj.inputs = inputs;
- obj.outputs = outputs;
- obj.inputNames = inputNames;
- obj.outputNames = outputNames;
- return obj;
- }
- attr(idx, value, opInfo) {
- const obj = {};
- obj.kind = 'attr';
- if (value.kind === 'region') {
- obj.name = value.name;
- obj.type = 1001; // graph
- obj.block = value.block;
- obj.vars = value.vars;
- } else {
- const [attrName, attrType, attrValue] = this.getAttr(opInfo, idx, value);
- obj.name = attrName;
- obj.type = 1000; // ir
- obj.irType = attrType;
- obj.irValue = attrValue;
- }
- return obj;
- }
- getParaName(tensor, namePrefix) {
- let idx = '';
- if ('%' in tensor) {
- idx = tensor['%'];
- } else if ('#' in tensor) {
- idx = tensor['#'];
- }
- if (tensor.TT && !this._names.has(idx)) {
- const prefix = namePrefix || idx;
- this._names.set(idx, `${prefix}`);
- }
- return [`${idx}`, this._names.has(idx) ? this._names.get(idx) : `${idx}`, Number.isInteger(idx) ? idx < 0 : false];
- }
- hasCrossInput(name) {
- return this._crossRegionInputs.has(name);
- }
- getCrossInput(name) {
- return this._crossRegionInputs.has(name) ? this._crossRegionInputs.get(name) : null;
- }
- addCrossInput(name, input) {
- this._crossRegionInputs.set(name, input);
- }
- getOpInfo(op) {
- const obj = {};
- obj.rawType = op['#'];
- obj._type = op['#'];
- obj._name = op['#'];
- switch (op['#']) {
- case 'p': {
- obj.kind = 'p';
- [obj._name] = op.A.slice(3);
- obj._type = this.getCompressOp(obj._type);
- op.OA = [...op.OA, ...op.A];
- obj.type = obj._type;
- obj.name = obj._type;
- obj.fullName = obj._type;
- obj.namePrefix = obj._name;
- break;
- }
- case '1.data': {
- obj.kind = 'data';
- [obj._opKey, obj._opType] = obj._name.split('.');
- let prefix = '';
- for (const attr of op.A) {
- if (attr.N === 'name') {
- prefix = attr.AT.D;
- break;
- }
- }
- obj._attr = op.A;
- obj.type = obj._opType;
- obj.name = obj._opType;
- obj.fullName = `${this.getCompressOp(obj._opKey)}.${obj._opType}`;
- obj.namePrefix = prefix;
- break;
- }
- default: {
- obj.kind = '';
- [obj._opKey, obj._opType] = obj._name.split('.');
- obj.type = obj._opType;
- obj.name = obj._opType;
- obj.fullName = `${this.getCompressOp(obj._opKey)}.${obj._opType}`;
- obj.namePrefix = null;
- break;
- }
- }
- return obj;
- }
- createTensorType(data, denotation) {
- const [type, dims, layout, ,] = data.TT.D;
- const [, dataType] = type['#'].split('.');
- const dtype = this.getType(dataType);
- const shape = new paddle.TensorShape(dims);
- return new paddle.TensorType(dtype, shape, layout, denotation);
- }
- getType(type) {
- type = type.includes('_') ? type.split('_')[1] : type;
- switch (type) {
- case 'bool': return 'boolean';
- case 'bf16': return 'bfloat16';
- case 'fp16': return 'float16';
- case 'fp32': return 'float32';
- case 'fp64': return 'float64';
- case 'fp8_e4m3fn': return 'float8e4m3fn';
- case 'fp8_e5m2': return 'float8e5m2';
- case 'f8e4m3fn': return 'float8e4m3fn';
- case 'f8e5m2': return 'float8e5m2';
- case 'f16': return 'float16';
- case 'f32': return 'float32';
- case 'f64': return 'float64';
- case 'i8': return 'int8';
- case 'ui8': return 'uint8';
- case 'i16': return 'int16';
- case 'i32': return 'int32';
- case 'i64': return 'int64';
- case 'c64': return 'complex<float32>';
- case 'c128': return 'complex<float64>';
- case 'str': return 'string';
- default: return type;
- }
- }
- getCompressOp(opType) {
- switch (opType) {
- case '0': return 'builtin';
- case '1': return 'pd_op';
- case '2': return 'cf';
- case '3': return 'custom_op';
- case '4': return 'pd_dist';
- case 'p': return 'parameter';
- default: return opType;
- }
- }
- getAttrDenotation(name, value) {
- if (value) {
- if (typeof value === 'boolean') {
- return `${name}`;
- }
- if (name !== 'name' && name !== 'dtype') {
- return `${name}:${value}`;
- }
- }
- return '';
- }
- getAttr(opInfo, idx, value) {
- if (opInfo.kind === 'p') {
- let attrName = '';
- let attrType = '';
- let attrValue = '';
- switch (idx) {
- case '0':
- attrName = 'is_distributed';
- attrType = this.getType('a_bool');
- break;
- case '1':
- attrName = 'is_parameter';
- attrType = this.getType('a_bool');
- break;
- case '2':
- attrName = 'need_clip';
- attrType = this.getType('a_bool');
- break;
- case '3':
- attrName = 'name';
- attrType = this.getType('a_str');
- break;
- default:
- break;
- }
- attrValue = attrType === this.getType('a_bool') ? value === 1 : value;
- return [attrName, attrType, attrValue];
- }
- const attrName = value.N;
- let attrType = this.getType(value.AT['#'].split('.')[1]);
- let attrValue = value.AT.D;
- if (attrType === this.getType('a_array') && attrValue.length > 0) {
- const subType = this.getType(attrValue[0]['#'].split('.')[1]);
- attrType = `${subType}[]`;
- const valueData = [];
- for (const attr of attrValue) {
- valueData.push(attr.D);
- }
- attrValue = valueData;
- }
- if (attrName === 'place') {
- const [place, val,] = attrValue;
- let device = place;
- switch (device) {
- case 0: device = 'UNDEFINED'; break;
- case 1: device = 'CPU'; break;
- case 2: device = 'GPU'; break;
- case 3: device = 'GPUPINNED'; break;
- case 4: device = 'XPU'; break;
- case 7: device = 'IPU'; break;
- case 9: device = 'CUSTOM'; break;
- default: break;
- }
- attrValue = `${device}:${val}`;
- }
- if (attrName === 'shape') {
- attrValue = new paddle.TensorShape(attrValue);
- }
- return [attrName, attrType, attrValue];
- }
- getOutputAttr(opInfo, idx, outputAttr) {
- switch (opInfo.kind) {
- case 'p': {
- const denotation = [];
- if (outputAttr[0] === 1) {
- denotation.push('persistable');
- }
- if (outputAttr[1] === 1) {
- denotation.push('stop_gradient');
- }
- if (outputAttr[2] === 1) {
- denotation.push('trainable');
- }
- if (outputAttr[3] === 1) {
- denotation.push('is_distributed');
- }
- if (outputAttr[4] === 1) {
- denotation.push('is_parameter');
- }
- if (outputAttr[5] === 1) {
- denotation.push('need_clip');
- }
- return denotation.join(';');
- }
- case 'data': {
- const denotation = [];
- for (const attr of outputAttr) {
- const attrName = attr.N;
- const attrValue = attr.AT.D[idx].D;
- const attrDenotation = this.getAttrDenotation(attrName, attrValue);
- if (attrDenotation) {
- denotation.push(attrDenotation);
- }
- }
- for (const value of opInfo._attr) {
- const [attrName, , attrValue] = this.getAttr(opInfo, null, value);
- const attrDenotation = this.getAttrDenotation(attrName, attrValue);
- if (attrDenotation) {
- denotation.push(attrDenotation);
- }
- }
- return denotation.join(';');
- }
- default: {
- const denotation = [];
- for (const attr of outputAttr) {
- const attrName = attr.N;
- const attrValue = attr.AT.D[idx].D;
- const attrDenotation = this.getAttrDenotation(attrName, attrValue);
- if (attrDenotation) {
- denotation.push(attrDenotation);
- }
- }
- return denotation.join(';');
- }
- }
- }
- };
- paddle.Error = class extends Error {
- constructor(message) {
- super(message);
- this.name = 'Error loading PaddlePaddle model.';
- }
- };
- export const ModelFactory = paddle.ModelFactory;
|