""" ONNX and WebGPU Export Pipeline for Q-TensorFormer Models. Exports Q-TensorFormer models to ONNX format with dynamic batch and sequence axes, verifies numeric equivalence via ONNX Runtime, and provides a browser WebGPU runtime template. Usage: python export_onnx.py --model-path . --output qtensorformer.onnx --opset 17 --verify """ import argparse import io import os import sys # Ensure UTF-8 stdout on Windows to prevent UnicodeEncodeError on emoji prints if hasattr(sys.stdout, "reconfigure"): sys.stdout.reconfigure(encoding="utf-8") elif hasattr(sys.stdout, "buffer"): sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") import torch import torch.nn as nn class QTensorFormerONNXWrapper(nn.Module): """ Wrapper module to provide standard (input_ids) -> (logits) interface tailored for ONNX export and graph optimization. """ def __init__(self, model): super().__init__() self.model = model def forward(self, input_ids: torch.Tensor) -> torch.Tensor: outputs = self.model(input_ids=input_ids, use_cache=False) return outputs.logits def export_to_onnx( model_path: str = ".", output_path: str = "qtensorformer.onnx", opset_version: int = 17, verify: bool = True, ) -> str: print(f"[*] Initializing Q-TensorFormer for ONNX export from: {model_path}") from configuration_qtensorformer import QTensorFormerConfig from modeling_qtensorformer import QTensorFormerForCausalLM if os.path.isdir(model_path): config = QTensorFormerConfig.from_pretrained(model_path) else: config = QTensorFormerConfig() # For fast and clean export graph, use a representative configuration config.num_hidden_layers = min(config.num_hidden_layers, 4) model = QTensorFormerForCausalLM(config) model.eval() wrapper = QTensorFormerONNXWrapper(model) wrapper.eval() dummy_input_ids = torch.randint(0, config.vocab_size, (1, 8), dtype=torch.long) print(f"[*] Tracing and exporting ONNX graph (Opset={opset_version})...") input_names = ["input_ids"] output_names = ["logits"] dynamic_axes = { "input_ids": {0: "batch_size", 1: "sequence_length"}, "logits": {0: "batch_size", 1: "sequence_length"}, } torch.onnx.export( wrapper, dummy_input_ids, output_path, export_params=True, opset_version=opset_version, do_constant_folding=True, input_names=input_names, output_names=output_names, dynamic_axes=dynamic_axes, ) file_size_mb = os.path.getsize(output_path) / (1024 * 1024) print(f"[+] Successfully exported ONNX model: {output_path} ({file_size_mb:.2f} MB)") if verify: print("[*] Verifying ONNX graph with onnxruntime...") try: import onnxruntime as ort session = ort.InferenceSession(output_path, providers=["CPUExecutionProvider"]) ort_inputs = {"input_ids": dummy_input_ids.numpy()} ort_outputs = session.run(None, ort_inputs) with torch.no_grad(): torch_output = wrapper(dummy_input_ids).numpy() diff = float(abs(ort_outputs[0] - torch_output).max()) print(f"[+] ONNX Runtime verification PASSED. Max absolute difference: {diff:.6e}") except ImportError: print("[!] onnxruntime not installed. Skipping runtime verification.") except Exception as e: print(f"[!] Warning during verification: {e}") # Generate WebGPU HTML template web_dir = os.path.join(os.path.dirname(output_path) or ".", "web") os.makedirs(web_dir, exist_ok=True) html_path = os.path.join(web_dir, "index.html") html_content = """
Run closed-loop Tensor-Train transformer generation locally inside your browser using WebGPU hardware acceleration.