diff --git a/source/server.js b/source/message.js similarity index 75% rename from source/server.js rename to source/message.js index 34c23479dc..510b4e0b62 100644 --- a/source/server.js +++ b/source/message.js @@ -31,6 +31,7 @@ message.Model = class { constructor(data) { this.format = data.format || ''; + this.format = this.format.replace(/\s+(\d+\.\d+)$/, ' v$1'); // Format v2.0 this.producer = data.producer || ''; this.version = data.version || ''; this.description = data.description || ''; @@ -47,25 +48,49 @@ message.Graph = class { this.inputs = []; this.outputs = []; this.nodes = []; - const values = data.values ? data.values.map((value) => new message.Value(value)) : []; + const values = new Map(); + values.map = (index) => { + if (!values.has(index)) { + values.set(index, new message.Value({ name: index.toString() })); + } + return values.get(index); + }; + if (Array.isArray(data.values)) { + for (let i = 0; i < data.values.length; i++) { + values.set(i, new message.Value(data.values[i])); + } + } + if (Array.isArray(data.arguments)) { + for (let i = 0; i < data.arguments.length; i++) { + values.set(data.arguments[i].name, new message.Value(data.arguments[i])); + } + } for (const argument of data.inputs || []) { - argument.value = argument.value.map((index) => values[index]).filter((argument) => !argument.initializer); + argument.value = argument.value.map((index) => values.map(index)).filter((argument) => !argument.initializer); if (argument.value.filter((argument) => !argument.initializer).length > 0) { this.inputs.push(new message.Argument(argument)); } } for (const argument of data.outputs || []) { - argument.value = argument.value.map((index) => values[index]); + argument.value = argument.value.map((index) => values.map(index)); if (argument.value.filter((argument) => !argument.initializer).length > 0) { this.outputs.push(new message.Argument(argument)); } } for (const node of data.nodes || []) { for (const argument of node.inputs || []) { - argument.value = argument.value.map((index) => values[index]); + if (!argument.value && argument.arguments) { + argument.value = argument.arguments; + delete argument.arguments; + } + argument.value = argument.value.map((index) => values.map(index)); } for (const argument of node.outputs || []) { - argument.value = argument.value.map((index) => values[index]); + if (!argument.value && argument.arguments) { + argument.value = argument.arguments; + delete argument.arguments; + } + argument.value = argument.value.map((index) => values.map(index)); } this.nodes.push(new message.Node(node)); } @@ -77,14 +102,14 @@ message.Argument = class { constructor(data) { this.name = data.name || ''; this.value = data.value || []; - this.type = data.type || ''; + this.type = data.type || null; } }; message.Value = class { constructor(data) { - this.name = data.name || ''; + this.name = data.name ? data.name.toString() : ''; this.initializer = data.initializer ? new message.Tensor(data.initializer) : null; if (this.initializer && this.initializer.type) { this.type = this.initializer.type; @@ -98,7 +123,7 @@ message.Node = class { constructor(data) { this.type = { name: data.type.name, category: data.type.category }; - this.name = data.name; + this.name = data.name || ''; this.inputs = (data.inputs || []).map((input) => new message.Argument(input)); this.outputs = (data.outputs || []).map((output) => new message.Argument(output)); this.attributes = (data.attributes || []).map((attribute) => new message.Argument(attribute)); diff --git a/source/server.py b/source/server.py index 3f029fc47d..c3d8dd3f08 100755 --- a/source/server.py +++ b/source/server.py @@ -291,7 +291,7 @@ def serve(file, data=None, address=None, browse=False, verbosity=1): _log(verbosity > 1, 'Experimental\n') model = _open(data) if model: - text = json.dumps(model.to_json(), indent=4, ensure_ascii=False) + text = json.dumps(model.to_json(), indent=2, ensure_ascii=False) content = _ContentProvider(text.encode('utf-8'), 'model.netron', None, file) address = _make_address(address) diff --git a/source/view.js b/source/view.js index 51d5a0d706..5fec83d03f 100644 --- a/source/view.js +++ b/source/view.js @@ -5733,7 +5733,7 @@ view.ModelFactoryService = class { this._host = host; this._patterns = new Set(['.zip', '.tar', '.tar.gz', '.tgz', '.gz']); this._factories = []; - this.register('./server', ['.netron']); + this.register('./message', ['.message', '.netron', '.maxviz']); this.register('./pytorch', ['.pt', '.pth', '.ptl', '.pt1', '.pyt', '.pyth', '.pkl', '.pickle', '.h5', '.t7', '.model', '.dms', '.tar', '.ckpt', '.chkpt', '.tckpt', '.bin', '.pb', '.zip', '.nn', '.torchmodel', '.torchscript', '.pytorch', '.ot', '.params', '.trt', '.ff', '.ptmf', '.jit', '.pte', '.bin.index.json', 'model.json', 'serialized_exported_program.json', 'serialized_state_dict.json'], ['.model', '.pt2']); this.register('./onnx', ['.onnx', '.onnx.data', '.onn', '.pb', '.onnxtxt', '.pbtxt', '.prototxt', '.txt', '.model', '.pt', '.pth', '.pkl', '.ort', '.ort.onnx', '.ngf', '.json', '.bin', 'onnxmodel']); this.register('./tflite', ['.tflite', '.lite', '.tfl', '.bin', '.pb', '.tmfile', '.h5', '.model', '.json', '.txt', '.dat', '.nb', '.ckpt', '.onnx']); @@ -5790,7 +5790,6 @@ view.ModelFactoryService = class { this.register('./nnc', ['.nnc','.tflite']); this.register('./safetensors', ['.safetensors', '.safetensors.index.json']); this.register('./tvm', ['.json', '.params']); - this.register('./modular', ['.maxviz']); this.register('./graphviz', ['.dot']); this.register('./catboost', ['.cbm']); this.register('./weka', ['.model']); diff --git a/test/models.json b/test/models.json index d860fb7bea..b7f6488898 100644 --- a/test/models.json +++ b/test/models.json @@ -2949,6 +2949,21 @@ "format": "MegEngine Mge v2", "link": "https://github.com/lutzroeder/netron/issues/607" }, + { + "type": "message", + "target": "inception_v3_traced.message", + "source": "https://github.com/user-attachments/files/17640875/inception_v3_traced.message.zip[inception_v3_traced.message]", + "format": "TorchScript v2.6.0.dev20241105", + "link": "https://github.com/lutzroeder/netron/issues/607" + }, + { + "type": "message", + "target": "resnet34.maxviz", + "source": "https://github.com/lutzroeder/netron/files/13421032/resnet34.maxviz.zip[resnet34.maxviz]", + "tags": "skip-render", + "format": "Modular v0.0", + "link": "https://github.com/lutzroeder/netron/issues/1187" + }, { "type": "mlnet", "target": "BinaryClassification_AutoML_SentimentModel.zip", @@ -3243,14 +3258,6 @@ "error": "Invalid tensor data length.", "link": "https://github.com/xindongzhang/MNN-APPLICATIONS" }, - { - "type": "modular", - "target": "resnet34.maxviz", - "source": "https://github.com/lutzroeder/netron/files/13421032/resnet34.maxviz.zip[resnet34.maxviz]", - "tags": "skip-render", - "format": "Modular", - "link": "https://github.com/lutzroeder/netron/issues/1187" - }, { "type": "mslite", "target": "blazeface_quant.ms",