paddle.js 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129
  1. var paddle = paddle || {};
  2. var flatbuffers = flatbuffers || require('./flatbuffers');
  3. var protobuf = protobuf || require('./protobuf');
  4. var python = python || require('./python');
  5. var base = base || require('./base');
  6. paddle.ModelFactory = class {
  7. match(context) {
  8. const identifier = context.identifier;
  9. const extension = identifier.split('.').pop().toLowerCase();
  10. if (identifier === '__model__' || extension === '__model__' || extension === 'paddle' || extension === 'pdmodel') {
  11. const tags = context.tags('pb');
  12. if (tags.get(1) === 2) {
  13. return 'paddle.pb';
  14. }
  15. }
  16. if (extension === 'pbtxt' || extension === 'txt') {
  17. const tags = context.tags('pbtxt');
  18. if (tags.has('blocks')) {
  19. return 'paddle.pbtxt';
  20. }
  21. }
  22. const stream = context.stream;
  23. if (stream.length > 16 && stream.peek(16).every((value) => value === 0x00)) {
  24. return 'paddle.params';
  25. }
  26. if (paddle.Pickle.open(context)) {
  27. return 'paddle.pickle';
  28. }
  29. if (paddle.Entries.open(context)) {
  30. return 'paddle.entries';
  31. }
  32. if (paddle.NaiveBuffer.open(context)) {
  33. return 'paddle.naive';
  34. }
  35. return undefined;
  36. }
  37. open(context, match) {
  38. return paddle.Metadata.open(context).then((metadata) => {
  39. switch (match) {
  40. case 'paddle.naive': {
  41. return context.require('./paddle-schema').then(() => {
  42. paddle.schema = flatbuffers.get('paddlelite').paddle.lite.fbs.proto;
  43. const file = paddle.NaiveBuffer.open(context);
  44. return new paddle.Model(metadata, file.format, file.model, file.weights);
  45. });
  46. }
  47. default: {
  48. return context.require('./paddle-proto').then(() => {
  49. paddle.proto = protobuf.get('paddle').paddle.framework.proto;
  50. const identifier = context.identifier;
  51. const parts = identifier.split('.');
  52. const extension = parts.pop().toLowerCase();
  53. const base = parts.join('.');
  54. const openProgram = (stream, match) => {
  55. const program = {};
  56. switch (match) {
  57. case 'paddle.pbtxt': {
  58. try {
  59. const reader = protobuf.TextReader.open(stream);
  60. program.desc = paddle.proto.ProgramDesc.decodeText(reader);
  61. }
  62. catch (error) {
  63. const message = error && error.message ? error.message : error.toString();
  64. throw new paddle.Error('File text format is not paddle.ProgramDesc (' + message.replace(/\.$/, '') + ').');
  65. }
  66. break;
  67. }
  68. case 'paddle.pb': {
  69. try {
  70. const reader = protobuf.BinaryReader.open(stream);
  71. program.desc = paddle.proto.ProgramDesc.decode(reader);
  72. }
  73. catch (error) {
  74. const message = error && error.message ? error.message : error.toString();
  75. throw new paddle.Error('File format is not paddle.ProgramDesc (' + message.replace(/\.$/, '') + ').');
  76. }
  77. break;
  78. }
  79. default: {
  80. throw new paddle.Error("Unsupported Paddle format '" + match + "'.");
  81. }
  82. }
  83. const formatVersion = (version) => {
  84. if (version && version.version && version.version.toNumber) {
  85. const number = version.version.toNumber();
  86. if (number > 0) {
  87. const list = [ Math.floor(number / 1000000) % 1000, Math.floor(number / 1000) % 1000, number % 1000 ];
  88. if (list.slice(-1).pop() === 0) {
  89. list.pop();
  90. if (list.slice(-1).pop() === 0) {
  91. list.pop();
  92. }
  93. }
  94. return ' v' + list.map((item) => item.toString()).join('.');
  95. }
  96. }
  97. return '';
  98. };
  99. program.format = 'PaddlePaddle' + formatVersion(program.desc.version);
  100. const variables = new Set();
  101. for (const block of program.desc.blocks) {
  102. const blockVars = new Set();
  103. for (const variable of block.vars) {
  104. if (variable.persistable && variable.type &&
  105. variable.type.type != paddle.DataType.FETCH_LIST &&
  106. variable.type.type != paddle.DataType.FEED_MINIBATCH) {
  107. blockVars.add(variable.name);
  108. }
  109. }
  110. for (const op of block.ops) {
  111. for (const input of op.inputs) {
  112. for (const argument of input.arguments) {
  113. if (blockVars.has(argument)) {
  114. variables.add(argument);
  115. }
  116. }
  117. }
  118. }
  119. }
  120. program.vars = Array.from(variables).sort();
  121. return program;
  122. };
  123. const createModel = (metadata, format, desc, tensors) => {
  124. return new paddle.Model(metadata, format, desc, tensors);
  125. };
  126. const loadParams = (stream) => {
  127. const params = [];
  128. while (stream.position < stream.length) {
  129. const tensor = paddle.Utility.openTensorDesc(stream);
  130. params.push(tensor);
  131. }
  132. return params;
  133. };
  134. const mapParams = (params, program) => {
  135. const weights = new Map();
  136. const vars = program.vars.slice();
  137. for (const param of params) {
  138. weights.set(vars.shift(), param);
  139. }
  140. return weights;
  141. };
  142. switch (match) {
  143. case 'paddle.pickle': {
  144. const container = paddle.Pickle.open(context);
  145. return createModel(metadata, container.format, null, container.weights);
  146. }
  147. case 'paddle.entries': {
  148. const container = paddle.Entries.open(context);
  149. return createModel(metadata, container.format, null, container.weights);
  150. }
  151. case 'paddle.params': {
  152. const file = identifier !== 'params' ? base + '.pdmodel' : 'model';
  153. const params = loadParams(context.stream);
  154. return context.request(file, null).then((stream) => {
  155. const program = openProgram(stream, 'paddle.pb');
  156. const weights = mapParams(params, program);
  157. return createModel(metadata, program.format, program.desc, weights);
  158. }).catch(() => {
  159. const weights = new Map(params.map((param, index) => [ index.toString(), param ]));
  160. return createModel(metadata, 'PaddlePaddle Inference Weights', null, weights);
  161. });
  162. }
  163. case 'paddle.pb':
  164. case 'paddle.pbtxt': {
  165. const loadEntries = (context, program) => {
  166. const promises = program.vars.map((name) => context.request(name, null).then((stream) => stream).catch(() => null));
  167. return Promise.all(promises).then((streams) => {
  168. const params = streams.map((stream) => stream ? paddle.Utility.openTensorDesc(stream) : null);
  169. const weights = mapParams(params, program);
  170. return createModel(metadata, program.format, program.desc, weights);
  171. });
  172. };
  173. const openNumPyArrayPickle = (stream, weights) => {
  174. const execution = new python.Execution(null);
  175. const unpickler = python.Unpickler.open(stream);
  176. const obj = unpickler.load((name, args) => execution.invoke(name, args));
  177. paddle.Utility.openNumPyArrayList(obj, weights);
  178. };
  179. const program = openProgram(context.stream, match);
  180. if (extension === 'pdmodel') {
  181. return context.request(base + '.pdiparams', null).then((stream) => {
  182. const params = loadParams(stream);
  183. const weights = mapParams(params, program);
  184. return createModel(metadata, program.format, program.desc, weights);
  185. }).catch((/* err */) => {
  186. const weights = new Map();
  187. return context.request(base + '.pdparams', null).then((stream) => {
  188. openNumPyArrayPickle(stream, weights);
  189. return context.request(base + '.pdopt', null).then((stream) => {
  190. openNumPyArrayPickle(stream, weights);
  191. return createModel(metadata, program.format, program.desc, weights);
  192. }).catch((/* err */) => {
  193. return createModel(metadata, program.format, program.desc, weights);
  194. });
  195. }).catch((/* err */) => {
  196. return context.request(base + '.pdopt', null).then((stream) => {
  197. openNumPyArrayPickle(stream, weights);
  198. return createModel(metadata, program.format, program.desc, weights);
  199. }).catch((/* err */) => {
  200. return loadEntries(context, program);
  201. });
  202. });
  203. });
  204. }
  205. if (identifier === 'model') {
  206. return context.request('params', null).then((stream) => {
  207. const params = loadParams(stream);
  208. const weights = mapParams(params, program);
  209. return createModel(metadata, program.format, program.desc, weights);
  210. }).catch((/* err */) => {
  211. return loadEntries(context, program);
  212. });
  213. }
  214. return loadEntries(context, program);
  215. }
  216. default: {
  217. throw new paddle.Error("Unsupported PaddlePaddle format '" + match + "'.");
  218. }
  219. }
  220. });
  221. }
  222. }
  223. });
  224. }
  225. };
  226. paddle.Model = class {
  227. constructor(metadata, format, programDesc, tensors) {
  228. this._format = format;
  229. this._graphs = programDesc ?
  230. programDesc.blocks.map((block) => new paddle.Graph(metadata, block, tensors)) :
  231. [ new paddle.Graph(metadata, null, tensors) ];
  232. }
  233. get format() {
  234. return this._format;
  235. }
  236. get graphs() {
  237. return this._graphs;
  238. }
  239. };
  240. paddle.Graph = class {
  241. constructor(metadata, block, tensors) {
  242. this._nodes = [];
  243. this._inputs = [];
  244. this._outputs = [];
  245. if (block) {
  246. this._name = block.idx.toString();
  247. const args = new Map();
  248. for (const variable of block.vars) {
  249. const type = variable.type && variable.type.type && variable.type.lod_tensor && variable.type.lod_tensor.tensor ? paddle.Utility.createTensorType(variable.type.lod_tensor.tensor.data_type, variable.type.lod_tensor.tensor.dims) : null;
  250. 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;
  251. args.set(variable.name, new paddle.Argument(variable.name, type, tensor));
  252. }
  253. const scope = {};
  254. for (let i = 0; i < block.ops.length; i++) {
  255. for (const input of block.ops[i].inputs) {
  256. input.arguments = input.arguments.map((argument) => scope[argument] ? scope[argument] : argument);
  257. }
  258. for (const output of block.ops[i].outputs) {
  259. output.arguments = output.arguments.map((argument) => {
  260. if (scope[argument]) {
  261. const next = argument + '\n' + i.toString(); // custom argument id
  262. scope[argument] = next;
  263. return next;
  264. }
  265. scope[argument] = argument;
  266. return argument;
  267. });
  268. }
  269. }
  270. for (const op of block.ops) {
  271. for (const input of op.inputs) {
  272. for (const argument of input.arguments) {
  273. const name = argument;
  274. if (!args.has(name)) {
  275. args.set(name, new paddle.Argument(name, null, null));
  276. }
  277. }
  278. }
  279. for (const output of op.outputs) {
  280. for (const argument of output.arguments) {
  281. const name = argument;
  282. if (!args.has(name)) {
  283. args.set(name, new paddle.Argument(name, null, null));
  284. }
  285. }
  286. }
  287. }
  288. let lastNode = null;
  289. let lastOutput = null;
  290. for (const op of block.ops) {
  291. if (op.type == 'feed') {
  292. const inputName = op.attrs.filter((attr) => attr.name == 'col')[0].i.toString();
  293. this._inputs.push(new paddle.Parameter(inputName, op.outputs[0].arguments.map((id) => args.get(id))));
  294. }
  295. else if (op.type == 'fetch') {
  296. const outputName = op.attrs.filter((attr) => attr.name == 'col')[0].i.toString();
  297. this._outputs.push(new paddle.Parameter(outputName, op.inputs[0].arguments.map((id) => args.get(id))));
  298. }
  299. else {
  300. const node = new paddle.Node(metadata, op, args);
  301. if (op.inputs.length == 1 && op.inputs[0].arguments.length == 1 &&
  302. op.outputs.length >= 1 && op.outputs[0].arguments.length == 1 &&
  303. op.inputs[0].arguments[0].split('\n').shift() == op.outputs[0].arguments[0].split('\n').shift() &&
  304. lastNode &&
  305. lastOutput == op.inputs[0].arguments[0].split('\n').shift()) {
  306. lastNode.chain.push(node);
  307. }
  308. else {
  309. this._nodes.push(node);
  310. lastNode = null;
  311. lastOutput = null;
  312. if (op.outputs.length == 1 && op.outputs[0].arguments.length == 1) {
  313. lastNode = node;
  314. lastOutput = op.outputs[0].arguments[0].split('\n').shift();
  315. }
  316. }
  317. }
  318. }
  319. }
  320. else {
  321. const args = new Map();
  322. const ops = new Map();
  323. for (const pair of tensors) {
  324. const name = pair[0];
  325. const tensor = pair[1];
  326. args.set(name, new paddle.Argument(name, tensor.type, tensor));
  327. const separator = name.indexOf('.') !== -1 ? '.' : '_';
  328. const regex = /(.*)_((w_attr|scale|weights|offset|b|w|b_attr)_(moment|beta|velocity|mean_square|mean_grad).*)/;
  329. const parts = separator === '.' ? name.split(separator) : (regex.test(name) ? regex.exec(name).slice(1, 3) : [ '', name ]);
  330. const parameter_name = parts.pop();
  331. const op_name = parts.join(separator);
  332. if (!ops.has(op_name)) {
  333. ops.set(op_name, { name: op_name, type: 'Weights', inputs: [] });
  334. }
  335. const op = ops.get(op_name);
  336. op.inputs.push({ parameter: parameter_name, arguments: [ name ] });
  337. }
  338. for (const pair of ops) {
  339. const op = pair[1];
  340. this._nodes.push(new paddle.Node(metadata, op, args));
  341. }
  342. }
  343. }
  344. get name() {
  345. return this._name;
  346. }
  347. get inputs() {
  348. return this._inputs;
  349. }
  350. get outputs() {
  351. return this._outputs;
  352. }
  353. get nodes() {
  354. return this._nodes;
  355. }
  356. };
  357. paddle.Parameter = class {
  358. constructor(name, args) {
  359. this._name = name;
  360. this._arguments = args;
  361. }
  362. get name() {
  363. return this._name;
  364. }
  365. get visible() {
  366. return true;
  367. }
  368. get arguments() {
  369. return this._arguments;
  370. }
  371. };
  372. paddle.Argument = class {
  373. constructor(name, type, initializer) {
  374. if (typeof name !== 'string') {
  375. throw new paddle.Error("Invalid argument identifier '" + JSON.stringify(name) + "'.");
  376. }
  377. this._name = name;
  378. this._type = type || null;
  379. this._initializer = initializer || null;
  380. }
  381. get name() {
  382. return this._name;
  383. }
  384. get type() {
  385. if (this._type) {
  386. return this._type;
  387. }
  388. if (this._initializer) {
  389. return this._initializer.type;
  390. }
  391. return null;
  392. }
  393. get initializer() {
  394. return this._initializer;
  395. }
  396. };
  397. paddle.Node = class {
  398. constructor(metadata, op, args) {
  399. const type = op.type;
  400. this._type = metadata.type(type) || { name: type };
  401. this._name = op.name || '';
  402. this._attributes = [];
  403. this._inputs = [];
  404. this._outputs = [];
  405. this._chain = [];
  406. if (op.attrs) {
  407. this._attributes = op.attrs.map((attr) => new paddle.Attribute(metadata.attribute(type, this._name), attr));
  408. }
  409. if (op.inputs) {
  410. for (const input of op.inputs) {
  411. if (input.arguments.length > 0) {
  412. this._inputs.push(new paddle.Parameter(input.parameter, input.arguments.map((name) => args.get(name))));
  413. }
  414. }
  415. }
  416. if (op.outputs) {
  417. for (const output of op.outputs) {
  418. if (output.arguments.length > 0) {
  419. this._outputs.push(new paddle.Parameter(output.parameter, output.arguments.map((name) => args.get(name))));
  420. }
  421. }
  422. }
  423. this._update(this._inputs, 'X');
  424. this._update(this._inputs, 'Input');
  425. this._update(this._outputs, 'Y');
  426. this._update(this._outputs, 'Out');
  427. }
  428. get type() {
  429. return this._type;
  430. }
  431. get name() {
  432. return this._name;
  433. }
  434. get attributes() {
  435. return this._attributes;
  436. }
  437. get inputs() {
  438. return this._inputs;
  439. }
  440. get outputs() {
  441. return this._outputs;
  442. }
  443. get chain() {
  444. return this._chain;
  445. }
  446. _update(list, name) {
  447. let item = null;
  448. for (let i = 0; i < list.length; i++) {
  449. if (list[i].name == name) {
  450. item = list[i];
  451. list.splice(i, 1);
  452. break;
  453. }
  454. }
  455. if (item) {
  456. list.splice(0, 0, item);
  457. }
  458. }
  459. };
  460. paddle.Attribute = class {
  461. constructor(schema, attr) {
  462. this._name = attr.name;
  463. this._value = '?';
  464. switch (attr.type) {
  465. case paddle.AttributeType.STRING:
  466. this._type = 'string';
  467. this._value = attr.s;
  468. break;
  469. case paddle.AttributeType.STRINGS:
  470. this._type = 'string[]';
  471. this._value = Array.from(attr.strings);
  472. break;
  473. case paddle.AttributeType.BOOLEAN:
  474. this._type = 'boolean';
  475. this._value = attr.b;
  476. break;
  477. case paddle.AttributeType.BOOLEANS:
  478. this._type = 'boolean[]';
  479. this._value = Array.from(attr.bools);
  480. break;
  481. case paddle.AttributeType.FLOAT:
  482. this._type = 'float32';
  483. this._value = attr.f;
  484. break;
  485. case paddle.AttributeType.FLOATS:
  486. this._type = 'float[]';
  487. this._value = Array.from(attr.floats);
  488. break;
  489. case paddle.AttributeType.INT:
  490. this._type = 'int32';
  491. this._value = attr.i;
  492. break;
  493. case paddle.AttributeType.INTS:
  494. this._type = 'int32[]';
  495. this._value = Array.from(attr.ints);
  496. break;
  497. case paddle.AttributeType.LONG:
  498. this._type = 'int64';
  499. break;
  500. case paddle.AttributeType.LONGS:
  501. this._type = 'int64[]';
  502. break;
  503. default:
  504. break;
  505. }
  506. switch (this._name) {
  507. case 'use_mkldnn':
  508. case 'use_cudnn':
  509. case 'op_callstack':
  510. case 'op_role':
  511. case 'op_role_var':
  512. case 'op_namescope':
  513. case 'is_test':
  514. this._visible = false;
  515. break;
  516. default:
  517. break;
  518. }
  519. if (schema) {
  520. if (Object.prototype.hasOwnProperty.call(schema, 'default')) {
  521. const defaultValue = schema.default;
  522. const value = this._value;
  523. if (defaultValue == value) {
  524. this._visible = false;
  525. }
  526. else if (Array.isArray(value) && Array.isArray(defaultValue) && value.length == defaultValue.length) {
  527. if (value.every((item, index) => { return item == defaultValue[index]; })) {
  528. this._visible = false;
  529. }
  530. }
  531. }
  532. }
  533. }
  534. get name() {
  535. return this._name;
  536. }
  537. get type() {
  538. return this._type;
  539. }
  540. get value() {
  541. return this._value;
  542. }
  543. get visible() {
  544. return this._visible == false ? false : true;
  545. }
  546. };
  547. paddle.Tensor = class {
  548. constructor(type, data, kind) {
  549. this._type = type;
  550. this._data = data;
  551. this._kind = kind || '';
  552. }
  553. get kind() {
  554. return this._kind;
  555. }
  556. get type() {
  557. return this._type;
  558. }
  559. get state() {
  560. return this._context().state || null;
  561. }
  562. get value() {
  563. const context = this._context();
  564. if (context.state) {
  565. return null;
  566. }
  567. context.limit = Number.MAX_SAFE_INTEGER;
  568. return this._decode(context, 0);
  569. }
  570. toString() {
  571. const context = this._context();
  572. if (context.state) {
  573. return '';
  574. }
  575. context.limit = 10000;
  576. const value = this._decode(context, 0);
  577. return paddle.Tensor._stringify(value, '', ' ');
  578. }
  579. _context() {
  580. const context = {};
  581. context.index = 0;
  582. context.count = 0;
  583. context.state = null;
  584. if (!this._data) {
  585. context.state = 'Tensor data is empty.';
  586. return context;
  587. }
  588. if (!this._type) {
  589. context.state = 'Tensor has no data type.';
  590. return context;
  591. }
  592. context.dataType = this._type.dataType;
  593. context.shape = this._type.shape.dimensions;
  594. context.view = new DataView(this._data.buffer, this._data.byteOffset, this._data.byteLength);
  595. switch (context.dataType) {
  596. case 'float32':
  597. case 'int32':
  598. case 'int64':
  599. break;
  600. default:
  601. context.state = "Tensor data type '" + context.dataType + "' is not implemented.";
  602. break;
  603. }
  604. return context;
  605. }
  606. _decode(context, dimension) {
  607. const shape = context.shape.length !== 0 ? context.shape : [ 1 ];
  608. const results = [];
  609. const size = shape[dimension];
  610. if (dimension == shape.length - 1) {
  611. for (let i = 0; i < size; i++) {
  612. if (context.count > context.limit) {
  613. results.push('...');
  614. return results;
  615. }
  616. switch (context.dataType) {
  617. case 'float32':
  618. results.push(context.view.getFloat32(context.index, true));
  619. context.index += 4;
  620. context.count++;
  621. break;
  622. case 'int32':
  623. results.push(context.view.getInt32(context.index, true));
  624. context.index += 4;
  625. context.count++;
  626. break;
  627. case 'int64':
  628. results.push(context.view.getInt64(context.index, true));
  629. context.index += 8;
  630. context.count++;
  631. break;
  632. default:
  633. throw new paddle.Error("Unsupported tensor data type '" + context.dataType + "'.");
  634. }
  635. }
  636. }
  637. else {
  638. for (let j = 0; j < size; j++) {
  639. if (context.count > context.limit) {
  640. results.push('...');
  641. return results;
  642. }
  643. results.push(this._decode(context, dimension + 1));
  644. }
  645. }
  646. if (context.shape.length == 0) {
  647. return results[0];
  648. }
  649. return results;
  650. }
  651. static _stringify(value, indentation, indent) {
  652. if (Array.isArray(value)) {
  653. const result = [];
  654. result.push(indentation + '[');
  655. const items = value.map((item) => paddle.Tensor._stringify(item, indentation + indent, indent));
  656. if (items.length > 0) {
  657. result.push(items.join(',\n'));
  658. }
  659. result.push(indentation + ']');
  660. return result.join('\n');
  661. }
  662. if (typeof value == 'string') {
  663. return indentation + value;
  664. }
  665. if (value == Infinity) {
  666. return indentation + 'Infinity';
  667. }
  668. if (value == -Infinity) {
  669. return indentation + '-Infinity';
  670. }
  671. if (isNaN(value)) {
  672. return indentation + 'NaN';
  673. }
  674. return indentation + value.toString();
  675. }
  676. };
  677. paddle.TensorType = class {
  678. constructor(dataType, shape) {
  679. this._dataType = dataType;
  680. this._shape = shape;
  681. }
  682. get dataType() {
  683. return this._dataType;
  684. }
  685. get shape() {
  686. return this._shape;
  687. }
  688. get denotation() {
  689. return this._denotation;
  690. }
  691. toString() {
  692. return this._dataType + this._shape.toString();
  693. }
  694. };
  695. paddle.TensorShape = class {
  696. constructor(dimensions) {
  697. dimensions = dimensions.map((dimension) => Number.isInteger(dimension) ? dimension : dimension.toNumber());
  698. this._dimensions = dimensions.map((dimension) => {
  699. return dimension != -1 ? dimension : '?';
  700. });
  701. }
  702. get dimensions() {
  703. return this._dimensions;
  704. }
  705. toString() {
  706. return (this._dimensions && this._dimensions.length) ? ('[' + this._dimensions.join(',') + ']') : '';
  707. }
  708. };
  709. paddle.Utility = class {
  710. static createTensorType(data_type, shape) {
  711. if (!paddle.Utility._dataTypes) {
  712. const length = Math.max.apply(null, Object.entries(paddle.DataType).map((entry) => entry[1]));
  713. paddle.Utility._dataTypes = new Array(length);
  714. const map = new Map([ [ 'bool', 'boolean' ], [ 'bf16', 'bfloat16' ], [ 'fp16', 'float16' ], [ 'fp32', 'float32' ], [ 'fp64', 'float64' ] ]);
  715. for (const entry of Object.entries(paddle.DataType)) {
  716. const index = entry[1];
  717. const key = entry[0].toLowerCase();
  718. paddle.Utility._dataTypes[index] = map.has(key) ? map.get(key) : key;
  719. }
  720. }
  721. const dataType = data_type < paddle.Utility._dataTypes.length ? paddle.Utility._dataTypes[data_type] : '?';
  722. return new paddle.TensorType(dataType, new paddle.TensorShape(shape));
  723. }
  724. static openTensorDesc(stream) {
  725. const signature = stream.read(16);
  726. if (!signature.every((value) => value === 0x00)) {
  727. throw new paddle.Error('Invalid paddle.TensorDesc signature.');
  728. }
  729. const length = new base.BinaryReader(stream.read(4)).uint32();
  730. const buffer = stream.read(length);
  731. const reader = protobuf.BinaryReader.open(buffer);
  732. const tensorDesc = paddle.proto.VarType.TensorDesc.decode(reader);
  733. const size = tensorDesc.dims.reduce((a, b) => a * b.toNumber(), 1);
  734. let itemsize = 0;
  735. switch (tensorDesc.data_type) {
  736. case paddle.DataType.FP16: itemsize = 2; break;
  737. case paddle.DataType.FP32: itemsize = 4; break;
  738. case paddle.DataType.FP64: itemsize = 8; break;
  739. case paddle.DataType.INT8: itemsize = 1; break;
  740. case paddle.DataType.INT16: itemsize = 2; break;
  741. case paddle.DataType.INT32: itemsize = 4; break;
  742. case paddle.DataType.INT64: itemsize = 8; break;
  743. case paddle.DataType.UINT8: itemsize = 1; break;
  744. default: throw new paddle.Error("Invalid inference params data type '" + tensorDesc.data_type + "'.");
  745. }
  746. const type = paddle.Utility.createTensorType(tensorDesc.data_type, tensorDesc.dims);
  747. const data = stream.read(itemsize * size);
  748. return new paddle.Tensor(type, data);
  749. }
  750. static openNumPyArrayList(obj, weights) {
  751. const map = null; // this._data['StructuredToParameterName@@'];
  752. for (const entry of Object.entries(obj)) {
  753. const key = entry[0];
  754. const value = entry[1];
  755. if (paddle.Utility.isNumPyArray(value)) {
  756. const name = map ? map[key] : key;
  757. const type = new paddle.TensorType(value.dtype.__name__, new paddle.TensorShape(value.shape));
  758. const data = value.data;
  759. const tensor = new paddle.Tensor(type, data, 'NumPy Array');
  760. weights.set(name, tensor);
  761. }
  762. }
  763. }
  764. static isNumPyArray(value) {
  765. return value && !Array.isArray(value) && value.__class__ && value.__class__.__module__ === 'numpy' && value.__class__.__name__ === 'ndarray';
  766. }
  767. };
  768. paddle.Entries = class {
  769. static open(context) {
  770. const extension = [ 'zip', 'tar' ].find((extension) => context.entries(extension).size > 0);
  771. if (extension) {
  772. const entries = new Map(Array.from(context.entries(extension)).filter((entry) => !entry[0].endsWith('/') && !entry[0].split('/').pop().startsWith('.')).slice());
  773. if (entries.size > 2 && Array.from(entries).every((entry) => entry[0].split('_').length > 0 && entry[1].peek(16).every((value) => value === 0x00))) {
  774. return new paddle.Entries(entries);
  775. }
  776. }
  777. return null;
  778. }
  779. constructor(data) {
  780. this._data = data;
  781. }
  782. get format() {
  783. return 'PaddlePaddle Weights';
  784. }
  785. get model() {
  786. this._initialize();
  787. return this._model;
  788. }
  789. get weights() {
  790. this._initialize();
  791. return this._weights;
  792. }
  793. _initialize() {
  794. if (!this._weights) {
  795. let rootFolder = null;
  796. for (const entry of this._data) {
  797. const name = entry[0];
  798. if (!name.startsWith('.') || name.startsWith('./')) {
  799. const parts = name.split('/');
  800. const folder = ((parts.length > 2 && parts[0] === '.') ? ('./' + parts[1] + '/') : (parts.length > 1 ? parts[0] + '/' : ''));
  801. rootFolder = (rootFolder === null) ? folder : (rootFolder !== '' && folder !== rootFolder) ? '' : folder;
  802. }
  803. }
  804. this._weights = new Map();
  805. for (const entry of this._data) {
  806. if (entry[0].startsWith(rootFolder)) {
  807. const name = entry[0].substring(rootFolder.length);
  808. const stream = entry[1];
  809. const tensor = paddle.Utility.openTensorDesc(stream);
  810. this._weights.set(name, tensor);
  811. }
  812. }
  813. }
  814. }
  815. };
  816. paddle.Pickle = class {
  817. static open(context) {
  818. const obj = context.open('pkl');
  819. if (obj && !Array.isArray(obj) && Object(obj) === obj &&
  820. Object.entries(obj).filter((entry) => paddle.Utility.isNumPyArray(entry[1])).length > 0) {
  821. return new paddle.Pickle(obj);
  822. }
  823. return null;
  824. }
  825. constructor(data) {
  826. this._data = data;
  827. }
  828. get format() {
  829. return 'PaddlePaddle Pickle';
  830. }
  831. get model() {
  832. this._initialize();
  833. return this._model;
  834. }
  835. get weights() {
  836. this._initialize();
  837. return this._weights;
  838. }
  839. _initialize() {
  840. if (!this._weights) {
  841. this._weights = new Map();
  842. paddle.Utility.openNumPyArrayList(this._data, this._weights);
  843. }
  844. }
  845. };
  846. paddle.NaiveBuffer = class {
  847. static open(context) {
  848. const stream = context.stream;
  849. if (stream.length > 4) {
  850. const buffer = stream.peek();
  851. const reader = new base.BinaryReader(buffer);
  852. if (context.identifier === '__model__.nb' || context.identifier === 'param.nb') {
  853. if (buffer[0] > 2 || buffer[1] !== 0x00 || buffer[2] !== 0x76 || buffer[2] !== 0x32) {
  854. return new paddle.NaiveBuffer(reader, -1);
  855. }
  856. }
  857. const meta_version = reader.uint16();
  858. if (meta_version <= 2) {
  859. return new paddle.NaiveBuffer(reader, meta_version);
  860. }
  861. }
  862. return null;
  863. }
  864. constructor(reader, meta_version) {
  865. this.reader = reader;
  866. this.meta_version = meta_version;
  867. }
  868. get format() {
  869. this._read();
  870. return this._format;
  871. }
  872. get model() {
  873. this._read();
  874. return this._model;
  875. }
  876. get weights() {
  877. this._read();
  878. return this._weights;
  879. }
  880. _read() {
  881. if (this.reader) {
  882. const reader = this.reader;
  883. delete this.reader;
  884. const decoder = new TextDecoder();
  885. const opt_version = reader.read(16);
  886. const version = decoder.decode(opt_version.slice(0, opt_version.indexOf(0x00)));
  887. this._format = 'Paddle Lite' + (version ? ' ' + version : '');
  888. const topo_size = reader.uint64();
  889. const openProgramDesc = (buffer) => {
  890. const reader = flatbuffers.BinaryReader.open(buffer);
  891. return paddle.schema.ProgramDesc.create(reader);
  892. };
  893. const openParamDesc = (buffer) => {
  894. const reader = flatbuffers.BinaryReader.open(buffer);
  895. return paddle.schema.ParamDesc.create(reader);
  896. };
  897. switch (this.meta_version) {
  898. case -1: {
  899. throw new paddle.Error('Paddle Lite naive buffer format is deprecated.');
  900. }
  901. case 0:
  902. case 1: {
  903. throw new paddle.Error("Paddle Lite meta format '" + this.meta_version.toString() + "' is deprecated.");
  904. }
  905. case 2: {
  906. const topo_data = new Uint8Array(topo_size);
  907. topo_data.set(reader.read(topo_size), 0);
  908. this._model = openProgramDesc(topo_data);
  909. reader.uint16(); // version
  910. reader.uint16(); // meta_size
  911. const header_size = reader.uint16();
  912. const params_size = reader.uint16();
  913. reader.uint32(); // max_tensor_size
  914. reader.skip(header_size - 6);
  915. this._weights = new Map();
  916. for (let i = 0; i < params_size; i++) {
  917. const total_size = reader.uint32();
  918. const offset = reader.uint32();
  919. const param_bytes = total_size - offset;
  920. const param_data = reader.read(param_bytes);
  921. const desc = openParamDesc(param_data);
  922. const data = desc.variable.data;
  923. const data_type = desc.variable.data_type;
  924. const dim = desc.variable.dim;
  925. const type = paddle.Utility.createTensorType(data_type, dim);
  926. const tensor = new paddle.Tensor(type, data);
  927. this._weights.set(desc.name, tensor);
  928. }
  929. break;
  930. }
  931. default: {
  932. throw new paddle.Error("Unsupported Paddle Lite naive buffer meta format '" + this.meta_version.toString() + "'.");
  933. }
  934. }
  935. }
  936. }
  937. };
  938. paddle.DataType = {
  939. BOOL: 0,
  940. INT16: 1,
  941. INT32: 2,
  942. INT64: 3,
  943. FP16: 4,
  944. FP32: 5,
  945. FP64: 6,
  946. LOD_TENSOR: 7,
  947. SELECTED_ROWS: 8,
  948. FEED_MINIBATCH: 9,
  949. FETCH_LIST: 10,
  950. STEP_SCOPES: 11,
  951. LOD_RANK_TABLE: 12,
  952. LOD_TENSOR_ARRAY: 13,
  953. PLACE_LIST: 14,
  954. READER: 15,
  955. RAW: 17,
  956. TUPLE: 18,
  957. SIZE_T: 19,
  958. UINT8: 20,
  959. INT8: 21,
  960. BF16: 22,
  961. COMPLEX64: 23,
  962. COMPLEX128: 24,
  963. };
  964. paddle.AttributeType = {
  965. INT: 0,
  966. FLOAT: 1,
  967. STRING: 2,
  968. INTS: 3,
  969. FLOATS: 4,
  970. STRINGS: 5,
  971. BOOLEAN: 6,
  972. BOOLEANS: 7,
  973. BLOCK: 8,
  974. LONG: 9,
  975. BLOCKS: 10,
  976. LONGS: 11,
  977. FLOAT64S: 12
  978. };
  979. paddle.Metadata = class {
  980. static open(context) {
  981. if (paddle.Metadata._metadata) {
  982. return Promise.resolve(paddle.Metadata._metadata);
  983. }
  984. return context.request('paddle-metadata.json', 'utf-8', null).then((data) => {
  985. paddle.Metadata._metadata = new paddle.Metadata(data);
  986. return paddle.Metadata._metadata;
  987. }).catch(() => {
  988. paddle.Metadata._metadata = new paddle.Metadata(null);
  989. return paddle.Metadata._metadata;
  990. });
  991. }
  992. constructor(data) {
  993. this._map = new Map();
  994. this._attributeCache = new Map();
  995. if (data) {
  996. const metadata = JSON.parse(data);
  997. this._map = new Map(metadata.map((item) => [ item.name, item ]));
  998. }
  999. }
  1000. type(name) {
  1001. return this._map.get(name) || null;
  1002. }
  1003. attribute(type, name) {
  1004. let map = this._attributeCache.get(type);
  1005. if (!map) {
  1006. map = new Map();
  1007. const metadata = this.type(type);
  1008. if (metadata && metadata.attributes && metadata.attributes.length > 0) {
  1009. for (const attribute of metadata.attributes) {
  1010. map.set(attribute.name, attribute);
  1011. }
  1012. }
  1013. this._attributeCache.set(type, map);
  1014. }
  1015. return map.get(name) || null;
  1016. }
  1017. };
  1018. paddle.Error = class extends Error {
  1019. constructor(message) {
  1020. super(message);
  1021. this.name = 'Error loading PaddlePaddle model.';
  1022. }
  1023. };
  1024. if (typeof module !== 'undefined' && typeof module.exports === 'object') {
  1025. module.exports.ModelFactory = paddle.ModelFactory;
  1026. }