Files
mineru-rocm/docker/scripts/patch_vllm_platform.py
T

180 lines
6.4 KiB
Python
Raw Normal View History

2026-06-04 16:16:30 +08:00
#!/usr/bin/env python3
"""vllm 平台检测补丁
问题 1:amdsmi 不可用时 platform 回退到 torch.version.hip
2026-06-12 10:56:36 +08:00
问题 2:rocm.py 中 logger.warning_once() 导致循环导入(默认不再改写;仅保留为显式开关)
2026-06-04 16:16:30 +08:00
"""
import os
2026-06-15 10:48:31 +08:00
import re
2026-06-12 13:45:51 +08:00
import sys
2026-06-15 10:48:31 +08:00
import sysconfig
2026-06-12 10:56:36 +08:00
import traceback
2026-06-04 16:16:30 +08:00
VLLM_DIR = '/opt/vllm/vllm'
2026-06-12 13:45:51 +08:00
VLLM_SRC_DIR = '/opt/vllm'
2026-06-04 16:16:30 +08:00
def patch6_init_platform_fallback():
"""补丁 6:platforms/__init__.py —— torch.version.hip 兜底"""
f = os.path.join(VLLM_DIR, 'platforms', '__init__.py')
c = open(f).read()
old = " return 'vllm.platforms.rocm.RocmPlatform' if is_rocm else None"
new = (" # amdsmi fallback: also check torch.version.hip\n"
" if not is_rocm:\n"
" try:\n"
" import torch\n"
" if torch.version.hip is not None:\n"
" is_rocm = True\n"
" except Exception:\n"
" pass\n"
" return 'vllm.platforms.rocm.RocmPlatform' if is_rocm else None")
c2 = c.replace(old, new)
if c2 != c:
open(f, 'w').write(c2)
print('Patch 6: __init__.py platform fallback applied.')
else:
print('Patch 6: already applied or pattern not found.')
def patch7_rocm_break_import_cycle():
2026-06-12 10:56:36 +08:00
"""补丁 7:platforms/rocm.py —— logger.warning_once → sys.stderr.write
2026-06-15 10:48:31 +08:00
默认启用安全的“整段 except 块”替换,避免 logger.warning_once() 在平台检测
期间触发循环导入,导致 current_platform 落到 UnspecifiedPlatform。
如需禁用,设置 VLLM_PATCH_ROCM_WARNING_ONCE=0。
2026-06-12 10:56:36 +08:00
"""
2026-06-15 10:48:31 +08:00
if os.environ.get('VLLM_PATCH_ROCM_WARNING_ONCE') == '0':
print('Patch 7: skipped (VLLM_PATCH_ROCM_WARNING_ONCE=0).')
2026-06-12 10:56:36 +08:00
return
2026-06-04 16:16:30 +08:00
f = os.path.join(VLLM_DIR, 'platforms', 'rocm.py')
c = open(f).read()
2026-06-15 10:48:31 +08:00
if 'amdsmi unavailable, using torch.cuda fallback' in c:
print('Patch 7: already applied.')
return
pattern = re.compile(
r'(\n\s*except Exception as e:\n'
r'\s*logger\.debug\("Failed to get GCN arch via amdsmi: %s", e\)\n'
r'\s*logger\.warning_once\(\n'
r'(?:\s*"[^"]*"\n)+'
r'\s*\)\n)',
re.MULTILINE,
)
def repl(match):
indent = re.search(r'\n(\s*)except Exception as e:', match.group(1)).group(1)
body_indent = indent + ' '
return (
f'\n{indent}except Exception as e:\n'
f'{body_indent}import sys as _sys\n'
f'{body_indent}_sys.stderr.write('
'"vLLM ROCm: amdsmi unavailable, using torch.cuda fallback for GPU detection\\n")\n'
)
c2, n = pattern.subn(repl, c, count=1)
2026-06-04 16:16:30 +08:00
if c2 != c:
open(f, 'w').write(c2)
2026-06-15 10:48:31 +08:00
print('Patch 7: rocm.py logger.warning_once circular import patch applied.')
2026-06-04 16:16:30 +08:00
else:
print('Patch 7: already applied or pattern not found.')
2026-06-15 10:48:31 +08:00
def ensure_vllm_dist_info():
"""为 /opt/vllm 源码导入创建最小 dist-info。
vLLM 平台检测会通过 importlib.metadata 查询 vllm 分发元数据/entry points。
如果只靠 PYTHONPATH 导入源码,没有 dist-info,就会出现:
"The vLLM package was not found...",并可能得到 UnspecifiedPlatform。
"""
try:
import vllm
except Exception:
return
version = getattr(vllm, '__version__', '0.1.dev1') or '0.1.dev1'
site_packages = sysconfig.get_paths().get('purelib')
if not site_packages:
return
dist_info = os.path.join(site_packages, f'vllm-{version}.dist-info')
os.makedirs(dist_info, exist_ok=True)
metadata = os.path.join(dist_info, 'METADATA')
if not os.path.exists(metadata):
with open(metadata, 'w') as fp:
fp.write(
'Metadata-Version: 2.1\n'
'Name: vllm\n'
f'Version: {version}\n'
'Summary: vLLM source tree mounted at /opt/vllm\n'
)
with open(os.path.join(dist_info, 'top_level.txt'), 'w') as fp:
fp.write('vllm\n')
with open(os.path.join(dist_info, 'INSTALLER'), 'w') as fp:
fp.write('mineru-rocm-runtime\n')
with open(os.path.join(dist_info, 'entry_points.txt'), 'w') as fp:
fp.write(
'[vllm.platform_plugins]\n'
'rocm = vllm.platforms.rocm:rocm_platform_plugin\n'
)
with open(os.path.join(dist_info, 'RECORD'), 'w') as fp:
fp.write('')
print(f'vllm dist-info ensured: {dist_info}')
2026-06-12 13:45:51 +08:00
def ensure_vllm_installed():
"""确保 vLLM Python 包在当前虚拟环境中可导入。
2026-06-12 14:18:43 +08:00
某些 MinerU 依赖安装流程后,site-packages 中可能缺少 vLLM 分发元数据,但
/opt/vllm 源码仍在。此时直接把 /opt/vllm 加入 PYTHONPATH/sys.path 再导入,
避免 editable 安装触发 pyproject 元数据校验失败。
2026-06-12 13:45:51 +08:00
"""
try:
import vllm # noqa: F401
return
except ModuleNotFoundError as exc:
if exc.name != 'vllm':
raise
if not os.path.isdir(VLLM_SRC_DIR):
raise ModuleNotFoundError(
'vllm is not installed and /opt/vllm source directory is missing'
)
2026-06-12 14:18:43 +08:00
print('vllm package missing; trying PYTHONPATH fallback with /opt/vllm...')
current = os.environ.get('PYTHONPATH', '')
paths = [p for p in current.split(':') if p]
if VLLM_SRC_DIR not in paths:
os.environ['PYTHONPATH'] = f"{VLLM_SRC_DIR}:{current}" if current else VLLM_SRC_DIR
if VLLM_SRC_DIR not in sys.path:
sys.path.insert(0, VLLM_SRC_DIR)
2026-06-12 13:45:51 +08:00
import vllm # noqa: F401
2026-06-12 14:18:43 +08:00
print('vllm import recovered via PYTHONPATH fallback.')
2026-06-12 13:45:51 +08:00
2026-06-04 16:16:30 +08:00
def main():
patch6_init_platform_fallback()
patch7_rocm_break_import_cycle()
2026-06-12 10:56:36 +08:00
try:
2026-06-12 13:45:51 +08:00
ensure_vllm_installed()
2026-06-15 10:48:31 +08:00
ensure_vllm_dist_info()
2026-06-12 10:56:36 +08:00
import vllm
from vllm.platforms import current_platform
print(f'vllm runtime import OK: {vllm.__version__}, platform={type(current_platform).__name__}')
2026-06-15 10:48:31 +08:00
if type(current_platform).__name__ == 'UnspecifiedPlatform':
raise RuntimeError(
'vLLM platform detection returned UnspecifiedPlatform; '
'ROCm backend is not usable. Check amdsmi, /dev/kfd, /dev/dri, '
'and vllm.platform_plugins metadata.'
)
2026-06-12 10:56:36 +08:00
except Exception:
print('ERROR: vllm runtime import failed after platform patches:')
traceback.print_exc()
raise
2026-06-04 16:16:30 +08:00
print('vllm platform patches done.')
if __name__ == '__main__':
main()