Spaces:
Running
Running
zhan1206
fix: comprehensive audit fixes - Thinking Dial unification, deployment scripts, README, bilingual filter, data download
bce487e | """ | |
| ONNX 部署 — 将 FusionModel 导出为 ONNX 格式 | |
| 使用方式: | |
| python deployment/export_onnx.py --checkpoint output/mini_model --output output/onnx/model.onnx | |
| python deployment/export_onnx.py --checkpoint output/mini_model --output output/onnx/ --dynamic-batch | |
| 依赖: onnx, onnxruntime (pip install onnx onnxruntime) | |
| """ | |
| import sys | |
| import os | |
| import argparse | |
| from pathlib import Path | |
| sys.path.insert(0, '.') | |
| def export_to_onnx(model, output_path, dynamic_batch=False, dynamic_seq=True, opset=14): | |
| """Export FusionModel to ONNX format. | |
| Args: | |
| model: FusionModel instance | |
| output_path: Output .onnx file path | |
| dynamic_batch: Enable dynamic batch dimension | |
| dynamic_seq: Enable dynamic sequence length | |
| opset: ONNX opset version | |
| """ | |
| try: | |
| import onnx | |
| import onnxruntime as ort | |
| except ImportError: | |
| print("[ERROR] onnx and onnxruntime required. Install with:") | |
| print(" pip install onnx onnxruntime") | |
| return False | |
| import torch | |
| model.eval() | |
| output_path = Path(output_path) | |
| output_path.parent.mkdir(parents=True, exist_ok=True) | |
| # Create dummy input | |
| batch_size = 1 | |
| seq_len = 16 | |
| dummy_input_ids = torch.randint(0, model.config.vocab_size, (batch_size, seq_len)) | |
| dummy_attention_mask = torch.ones(batch_size, seq_len, dtype=torch.long) | |
| # Dynamic axes | |
| dynamic_axes = {} | |
| if dynamic_batch or dynamic_seq: | |
| input_axes = {} | |
| if dynamic_batch: | |
| input_axes[0] = "batch_size" | |
| if dynamic_seq: | |
| input_axes[1] = "seq_len" | |
| dynamic_axes = { | |
| "input_ids": input_axes, | |
| "attention_mask": input_axes, | |
| "logits": input_axes, | |
| } | |
| # Export | |
| print(f"[EXPORT] Exporting to ONNX (opset={opset})...") | |
| torch.onnx.export( | |
| model, | |
| (dummy_input_ids, dummy_attention_mask), | |
| str(output_path), | |
| input_names=["input_ids", "attention_mask"], | |
| output_names=["logits"], | |
| dynamic_axes=dynamic_axes if dynamic_axes else None, | |
| opset_version=opset, | |
| do_constant_folding=True, | |
| ) | |
| # Verify | |
| print("[VERIFY] Checking ONNX model...") | |
| onnx_model = onnx.load(str(output_path)) | |
| onnx.checker.check_model(onnx_model) | |
| # Test with ONNX Runtime | |
| print("[VERIFY] Running ONNX Runtime inference test...") | |
| session = ort.InferenceSession(str(output_path)) | |
| ort_inputs = { | |
| "input_ids": dummy_input_ids.numpy(), | |
| "attention_mask": dummy_attention_mask.numpy(), | |
| } | |
| ort_outputs = session.run(None, ort_inputs) | |
| # Compare with PyTorch output | |
| with torch.no_grad(): | |
| pt_outputs = model(input_ids=dummy_input_ids, attention_mask=dummy_attention_mask, return_dict=True) | |
| import numpy as np | |
| max_diff = np.max(np.abs(ort_outputs[0] - pt_outputs.logits.numpy())) | |
| print(f"[VERIFY] Max diff between PyTorch and ONNX Runtime: {max_diff:.6e}") | |
| if max_diff < 1e-4: | |
| print(f"[PASS] ONNX export verified: {output_path}") | |
| else: | |
| print(f"[WARN] Diff {max_diff:.6e} exceeds 1e-4, check model compatibility") | |
| # Save model metadata | |
| metadata = { | |
| "model_type": "fusion", | |
| "vocab_size": model.config.vocab_size, | |
| "hidden_size": model.config.hidden_size, | |
| "num_hidden_layers": model.config.num_hidden_layers, | |
| "num_attention_heads": model.config.num_attention_heads, | |
| "dynamic_batch": dynamic_batch, | |
| "dynamic_seq": dynamic_seq, | |
| "onnx_opset": opset, | |
| } | |
| import json | |
| meta_path = output_path.with_suffix(".meta.json") | |
| with open(meta_path, "w", encoding="utf-8") as f: | |
| json.dump(metadata, f, indent=2) | |
| print(f"[DONE] ONNX export complete: {output_path}") | |
| return True | |
| if __name__ == "__main__": | |
| parser = argparse.ArgumentParser(description="Export FusionModel to ONNX format") | |
| parser.add_argument("--checkpoint", required=True, help="Path to model checkpoint") | |
| parser.add_argument("--output", default="output/onnx/model.onnx", help="Output ONNX path") | |
| parser.add_argument("--dynamic-batch", action="store_true", help="Enable dynamic batch dim") | |
| parser.add_argument("--opset", type=int, default=14, help="ONNX opset version") | |
| args = parser.parse_args() | |
| from models.fusion_model import FusionModel | |
| model = FusionModel.from_pretrained(args.checkpoint) | |
| export_to_onnx(model, args.output, args.dynamic_batch, opset=args.opset) | |