【Bug已解决】Error When Loading Private Adapters 解决方案
【Bug已解决】Error When Loading Private Adapters 解决方案一、现象长什么样在 Hugging Face Hub 上很多 LoRA adapter 是放在私有仓库private repo里的——可能是公司内部微调权重、付费社区模型、或者还没公开的检查点。当你用标准写法去加载时from peft import PeftModel model PeftModel.from_pretrained(base, my-org/my-private-lora)经常会出现下面几种报错HTTP 401 Unauthorized: You must be authenticated—— 没带 tokenHub 直接拒绝下载adapter_model.safetensors/adapter_config.jsonRepository Not Found或401 Client Error即便你已经huggingface-cli login过因为from_pretrained没有把当前会话的 token 透传下去OSError: Cant load config for my-org/some-base ... 401—— adapter 的base_model_name_or_path指向一个私有基座加载基座时也卡在鉴权Entry Not Found/adapter_model.safetensors is not found—— token 对了但仓库里那个 revision分支/commit不存在或文件在 LFS 上没下下来更隐蔽你本地huggingface-cli whoami显示已登录但程序跑在另一个用户 / 另一个虚拟环境 / 容器里那个环境并没有登录态于是加载仍然 401。核心症状就是公有 adapter 能加载换成私有 adapter 就各种 401 / 404。二、背景PEFT 加载 adapter 时涉及两次Hub 访问很多人只想到其中一次下载 adapter 文件from_pretrained内部用huggingface_hub的snapshot_download/hf_hub_download去拉adapter_model.safetensors、adapter_config.json、可能的tokenizer等。这一步需要能访问该私有仓库的 token。解析并加载基座模型如果base参数你传的是字符串而不是已实例化的模型from_pretrained会去 Hub 拉base_model_name_or_path指向的基座。若该基座也是私有的同样要 token。huggingface_hub找 token 的顺序是显式传入的token参数最高优先级环境变量HF_TOKEN/HUGGING_FACE_HUB_TOKEN本地缓存的登录态文件~/.cache/huggingface/token由huggingface-cli login写入。问题就出在PEFT 的from_pretrained早期版本对token参数的透传并不总是完整部分子调用比如拉基座、拉 tokenizer没拿到 token或者你以为登录了但运行环境其实没有那份 token 文件。下面用可运行代码演示“不带 token 必 401”以及“正确带 token / 环境变量”的几种稳妥姿势。注意私有仓库需要你自己的真实 token示例代码里的字符串只是占位。三、根因根因可以归为四类token 没透传from_pretrained只把 token 用在了下载 adapter 这一步加载基座 / tokenizer 时没传导致局部 401。运行环境没有登录态huggingface-cli login是在你当前 shell 用户下写的文件程序若在容器、CI、另一用户、或sudo下运行那份 token 文件读不到。基座也是私有只给 adapter 仓库授权不够base_model_name_or_path指向的基座若私有同样 401。revision / LFS 问题指定了错误的revision或 adapter 文件在 Git LFS 上没正确上传导致 404 / 文件 0 字节。修复的核心思路是让 token 在所有 Hub 访问路径上都可见——最稳妥的就是环境变量HF_TOKEN全局生效且基座和 adapter 两个仓库都有权限。四、最小可运行复现下面演示鉴权失败与成功的判定逻辑token 用占位符真实运行请替换为你自己的。import os from huggingface_hub import HfApi, hf_hub_download # 模拟不带 token 去访问一个私有仓库的文件 def try_download_with_token(repo_id, filename, tokenNone): try: path hf_hub_download( repo_idrepo_id, filenamefilename, tokentoken, # None 表示用环境变量/登录态 ) return fOK - {path} except Exception as e: return fFAIL - {type(e).__name__}: {e} PRIVATE my-org/my-private-lora # 情形 1Token 为 None且环境无登录态 - 大概率 401 print(无 token:, try_download_with_token(PRIVATE, adapter_config.json, tokenNone)) # 情形 2显式传入有效 token - OK MY_TOKEN os.environ.get(HF_TOKEN) # 从环境变量取别硬编码 print(带 token:, try_download_with_token(PRIVATE, adapter_config.json, tokenMY_TOKEN))更贴近 PEFT 的写法from peft import PeftModel, LoraConfig from transformers import AutoModelForCausalLM token os.environ.get(HF_TOKEN) # 关键从环境变量读取绝不写死 # 基座若是私有也要带 token base AutoModelForCausalLM.from_pretrained( my-org/my-private-base, tokentoken, ) # adapter 加载同样带 token并指定 revision如有 model PeftModel.from_pretrained( base, my-org/my-private-lora, tokentoken, # revisionmain, # 明确指定分支/commit避免拉到不存在的版本 ) model model.merge_and_unload()运行前确保export HF_TOKENhf_你的真实token # 可选确认登录态 huggingface-cli whoami五、解决方案第一层最小直接修复修复 1用环境变量全局注入 token最稳export HF_TOKENhf_xxx python your_script.py环境变量会被huggingface_hub在所有 Hub 调用里读取adapter 和基座都受益不需要在代码里到处传token。修复 2代码里统一从环境变量读绝不硬编码import os from peft import PeftModel token os.environ.get(HF_TOKEN) if not token: raise RuntimeError(未检测到 HF_TOKEN无法加载私有 adapter) model PeftModel.from_pretrained(base, my-org/my-private-lora, tokentoken)修复 3基座和 adapter 都显式传 tokenbase AutoModelForCausalLM.from_pretrained(my-org/my-private-base, tokentoken) model PeftModel.from_pretrained(base, my-org/my-private-lora, tokentoken)不要只给 adapter 传、忘了基座也是私有。六、解决方案第二层结构性改进改进 1封装一个“带鉴权的加载器”import os from peft import PeftModel from transformers import AutoModelForCausalLM from huggingface_hub import HfFileSystem def load_private_adapter(base_id, adapter_id, revisionmain, token_envHF_TOKEN): token os.environ.get(token_env) if not token: raise RuntimeError(f环境变量 {token_env} 未设置拒绝加载私有 adapter) # 先验证两个仓库都可访问提前给出清晰报错 fs HfFileSystem(tokentoken) for rid in (base_id, adapter_id): if not fs.exists(fdatasets/{rid}) and not fs.exists(fmodels/{rid}): # 再次用 try 确认HfFileSystem 路径约定不同这里仅做存在性探测 pass base AutoModelForCausalLM.from_pretrained(base_id, tokentoken) model PeftModel.from_pretrained( base, adapter_id, tokentoken, revisionrevision ) return model.merge_and_unload() model load_private_adapter( my-org/my-private-base, my-org/my-private-lora, )改进 2本地镜像私有权重彻底不依赖运行时鉴权把私有 adapter 和基座先下载到本地受控目录from_pretrained直接吃本地路径运行时无需任何 token也避免 CI / 容器里登录态缺失# 在本机已登录先把仓库拉到本地 huggingface-cli download my-org/my-private-lora --local-dir ./adapters/my-private-lora --token $HF_TOKEN huggingface-cli download my-org/my-private-base --local-dir ./bases/my-private-base --token $HF_TOKENbase AutoModelForCausalLM.from_pretrained(./bases/my-private-base) model PeftModel.from_pretrained(base, ./adapters/my-private-lora)改进 3CI / 容器里用 secret不落盘明文在 CI 配置里把 token 作为 secret 注入环境变量脚本从os.environ读取不要把 token 写进代码或镜像层# .github/workflows/train.yml 片段 env: HF_TOKEN: ${{ secrets.HF_TOKEN }}七、解决方案第三层断言 / CI 守护把“私有 adapter 必须在有 token 时才能加载、无 token 必须明确失败”做成测试。import os import pytest from huggingface_hub import hf_hub_download def _has_token(): return bool(os.environ.get(HF_TOKEN)) def test_private_adapter_requires_token(): # 没有 token 时访问私有仓库应当失败验证鉴权链路有效 if _has_token(): pytest.skip(当前环境已有 token跳过否定测试) with pytest.raises(Exception): hf_hub_download( repo_idmy-org/my-private-lora, filenameadapter_config.json, tokenNone, ) def test_private_adapter_loads_with_token(): token os.environ.get(HF_TOKEN) if not token: pytest.skip(无 HF_TOKEN跳过真实加载测试) path hf_hub_download( repo_idmy-org/my-private-lora, filenameadapter_config.json, tokentoken, ) assert os.path.exists(path) def test_token_not_hardcoded(): # 守护代码里不能出现硬编码 token 前缀 src open(load_adapter.py).read() assert hf_ not in src, 检测到硬编码 token请改用环境变量这三个测试守护“无 token 必失败、有 token 可加载、token 不硬编码”。八、排查清单加载私有 adapter 报错时按序查确认 token 存在echo $HF_TOKEN和huggingface-cli whoami确认运行环境不是你敲命令的环境有登录态。adapter 和基座都授权base_model_name_or_path指向的基座若是私有也要给 token 权限。代码里统一传 tokenAutoModelForCausalLM.from_pretrained(..., token...)和PeftModel.from_pretrained(..., token...)都要带。优先用环境变量export HF_TOKEN...全局生效避免每个调用漏传。指定 revision明确revisionmain或具体 commit避免拉到不存在的版本导致 404。检查 LFS确认adapter_model.safetensors真的在 LFS 上、文件大小非 0而不是指针文件。本地镜像兜底CI/容器场景先把仓库下到本地目录运行时走本地路径免鉴权。token 不落盘明文用环境变量 / secret不要把hf_xxx写进代码或镜像层。九、小结Error When Loading Private Adapters的本质是加载私有 adapter 涉及“下载 adapter”和“加载基座”两次 Hub 访问token 必须在两条路径上都可见而huggingface-cli login的登录态文件是按运行环境隔离的CI / 容器 / 另一用户下往往读不到于是出现“我本地能下、程序里 401”的经典矛盾。最小修复是用环境变量HF_TOKEN全局注入 token且基座与 adapter 都显式传 token结构性改进是封装带鉴权的加载器、把私有权重本地镜像后在运行时走本地路径、用 CI secret 而非硬编码最后用测试守护“无 token 必失败、有 token 可加载、token 不硬编码”。把鉴权链路在入口处固化私有 adapter 就能稳定加载。