dflash-mxfp8-import-optional.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #!/usr/bin/env python3
  2. """Make vLLM's DFlash MXFP8 guards tolerant of vLLM builds that do not ship
  3. ModelOptMxFp8LinearMethod (the r39 fork predates that class).
  4. Root cause (2026-09-28, mimo26 vLLM lane): the DFlash draft loader reaches
  5. the class via two `from vllm.model_executor.layers.quantization.modelopt
  6. import (ModelOptMxFp8LinearMethod,)` statements (qwen3_dflash.py,
  7. _build_context_kv_buffers / process_weights_after_loading). r39's modelopt
  8. module ships ModelOptMxFp8Config/ModelOptMxFp8FusedMoE but no *LinearMethod*,
  9. so the import raises ImportError inside _build_fused_kv_buffers right after
  10. the bf16 draft weights load — the guards themselves only matter for MXFP8
  11. drafts, ours is bf16.
  12. Both sites become getattr-on-the-module with an explicit None check, so a
  13. real MXFP8 checkpoint on a vLLM that DOES ship the class still takes the
  14. packed-scale path unchanged, and a bf16 draft just skips it. Anchor-based,
  15. refuses on drift.
  16. """
  17. import importlib.util
  18. import sys
  19. import vllm # noqa: F401 (resolve the install from the running vllm)
  20. MODULE = "vllm.model_executor.models.qwen3_dflash"
  21. OLD1 = """ from vllm.model_executor.layers.quantization.modelopt import (
  22. ModelOptMxFp8LinearMethod,
  23. )
  24. quant_methods = [a.qkv_proj.quant_method for a in layers_attn]
  25. uses_mxfp8 = [
  26. isinstance(method, ModelOptMxFp8LinearMethod) for method in quant_methods
  27. ]
  28. """
  29. NEW1 = """ import importlib
  30. ModelOptMxFp8LinearMethod = getattr(
  31. importlib.import_module(
  32. "vllm.model_executor.layers.quantization.modelopt"
  33. ),
  34. "ModelOptMxFp8LinearMethod",
  35. None,
  36. )
  37. quant_methods = [a.qkv_proj.quant_method for a in layers_attn]
  38. uses_mxfp8 = [
  39. ModelOptMxFp8LinearMethod is not None
  40. and isinstance(method, ModelOptMxFp8LinearMethod)
  41. for method in quant_methods
  42. ]
  43. """
  44. OLD2 = """ from vllm.model_executor.layers.quantization.modelopt import (
  45. ModelOptMxFp8LinearMethod,
  46. )
  47. quant_method = self.layers[0].self_attn.qkv_proj.quant_method
  48. if not isinstance(quant_method, ModelOptMxFp8LinearMethod):
  49. return
  50. """
  51. NEW2 = """ import importlib
  52. ModelOptMxFp8LinearMethod = getattr(
  53. importlib.import_module(
  54. "vllm.model_executor.layers.quantization.modelopt"
  55. ),
  56. "ModelOptMxFp8LinearMethod",
  57. None,
  58. )
  59. quant_method = self.layers[0].self_attn.qkv_proj.quant_method
  60. if (
  61. ModelOptMxFp8LinearMethod is None
  62. or not isinstance(quant_method, ModelOptMxFp8LinearMethod)
  63. ):
  64. return
  65. """
  66. TARGETS = [(OLD1, NEW1), (OLD2, NEW2)]
  67. def _consistent(src: str, old: str, new: str) -> bool:
  68. co, cn = src.count(old), src.count(new)
  69. if cn >= 1:
  70. return cn == 1 and co == 0
  71. return co == 1
  72. def main() -> int:
  73. check = "--check" in sys.argv
  74. spec = importlib.util.find_spec(MODULE)
  75. if not spec or not spec.origin:
  76. print(f"{MODULE} not importable", file=sys.stderr)
  77. return 1
  78. path = spec.origin
  79. with open(path, encoding="utf-8") as f:
  80. src = f.read()
  81. if check:
  82. if all(_consistent(src, old, new) for old, new in TARGETS):
  83. state = "patched" if src.count(NEW1) else "pristine"
  84. print(f"CHECK OK ({state}): {path}")
  85. return 0
  86. print(f"CHECK FAIL: {path} is neither pristine nor patched", file=sys.stderr)
  87. return 1
  88. if all(src.count(new) == 1 for _, new in TARGETS):
  89. print(f"ALREADY PATCHED: {path}")
  90. return 0
  91. if src.count(OLD1) != 1 or src.count(OLD2) != 1:
  92. print(
  93. f"refusing: {path} anchors matched {src.count(OLD1)}/{src.count(OLD2)}x;"
  94. " re-sync patch",
  95. file=sys.stderr,
  96. )
  97. return 1
  98. for old, new in TARGETS:
  99. src = src.replace(old, new, 1)
  100. with open(path, "w", encoding="utf-8") as f:
  101. f.write(src)
  102. print(f"APPLIED: {path}")
  103. return 0
  104. if __name__ == "__main__":
  105. sys.exit(main())