- 开发工具
- CLI
- 机器学习
【免费下载链接】huggingface_hub
The official CLI and Python client for the Hugging Face Hub.
本篇技术指南以huggingface_hub官方集成文档为主体,系统讲解如何将任意机器学习框架接入 Hugging Face Hub:从自行实现push_to_hub/from_pretrained的 Helper 方案,到基于ModelHubMixin类继承的 Mixin 方案,再到 PyTorch 就绪集成、模型卡与配置的自动化处理。读者学完后,可以自主决定并落地一套框架接入方案,并了解其背后的源码实现原理与测试验证。
概览:框架接入 Hub 的四种方式
Hugging Face Hub 为开源生态中的数十种机器学习库提供模型托管与共享能力,而huggingface_hub库在其中扮演关键角色——它让任何 Python 脚本都能轻松地上传与加载文件。要将一个库与 Hub 集成,主要有四种途径:
- Push to Hub(推送到 Hub):实现一个方法把模型上传到 Hub,包含模型权重、模型卡以及运行模型所需的其它信息(如训练日志)。这个方法通常命名为
push_to_hub()。 - Download from Hub(从 Hub 下载):实现一个方法从 Hub 加载模型,负责下载模型配置/权重并完成实例化。这个方法通常命名为
from_pretrained或load_from_hub()。 - Widgets(在线组件):在模型主页上展示可交互组件,让用户能在浏览器中快速试用模型。
- Inference API(推理服务):为模型配置云端推理接口。
本指南聚焦前两种(上传与下载),重点介绍两种主流集成路径:Helper 函数与ModelHubMixin类继承,并在文末给出对比表供选型参考。需要说明的是,这些仅是指导性原则,你可以根据自身框架需求自由调整。
灵活方案:自行实现 Helper 函数
第一种方案是完全自己动手实现push_to_hub和from_pretrained两个方法。这样你对“上传/下载哪些文件、如何处理框架特有输入”拥有完全的控制权。上传与下载的底层 API 细节可参考 upload files 指南 与 download files 指南。这正是 FastAI 集成的实现方式(见push_to_hub_fastai与from_pretrained_fastai)。
虽然不同库的实现各有差异,但整体工作流通常是一致的。
实现 from_pretrained
一个典型的from_pretrained方法如下:
def from_pretrained(model_id: str) -> MyModelClass: # 从 Hub 下载模型文件 cached_model = hf_hub_download( repo_id=repo_id, filename="model.pkl", library_name="fastai", library_version=get_fastai_version(), ) # 加载模型 return load_model(cached_model)其中hf_hub_download是huggingface_hub提供的核心下载函数,支持revision、cache_dir、force_download、local_files_only、token、proxies等参数。以 FastAI 的真实实现为例(fastai_utils.py),from_pretrained_fastai实际通过snapshot_download拉取整个仓库(而非单个文件),随后用fastai.learner.load_learner加载model.pkl,同时通过pyproject.toml校验 fastai 与 fastcore 的版本兼容性。
实现 push_to_hub
push_to_hub通常要复杂一些,因为它要处理仓库创建、模型卡生成和权重保存。常见的做法是:把所有文件保存在一个临时目录中,整体上传后再删除。
def push_to_hub(model: MyModelClass, repo_name: str) -> None: api = HfApi() # 若仓库不存在则创建,并获取 repo_id repo_id = api.create_repo(repo_name, exist_ok=True) # 将文件保存在临时目录中,一次提交全部推送 with TemporaryDirectory() as tmpdir: tmpdir = Path(tmpdir) # 保存权重 save_model(model, tmpdir / "model.safetensors") # 生成模型卡 card = generate_model_card(model) (tmpdir / "README.md").write_text(card) # 保存日志 # 保存图表 # 保存评估指标 # ... # 推送到 Hub return api.upload_folder(repo_id=repo_id, folder_path=tmpdir)以上仅为示例。FastAI 的push_to_hub_fastai(fastai_utils.py)采用了同样的模式:先create_repo(...)确保仓库存在,再将模型、配置与模型卡写入临时目录,最后调用api.upload_folder(...)一次提交。如果你需要更复杂的操作(删除远端文件、边训练边上传权重、本地持久化等),请参考 upload files 指南。
局限与维护成本
Helper 方案虽然灵活,但维护成本较高。huggingface_hub的使用者往往习惯以下下载参数:
token:从私有仓库下载所需凭证revision:从指定分支下载cache_dir:缓存到指定目录force_download/local_files_only:决定是否复用缓存proxies:配置 HTTP 会话
推送模型时还常支持:
commit_message:自定义提交信息private:仓库不存在时创建为私有create_pr:创建 Pull Request 而非直接推送到mainbranch:推送到指定分支而非mainallow_patterns/ignore_patterns:过滤需要上传的文件token等
这些参数都可以加进上述实现并透传给huggingface_hub方法。但问题在于:一旦某个参数发生变化或有新功能加入,你就需要同步更新自己的包;同时,为这些参数编写文档也增加了你的维护负担。要缓解这些局限,请看下一节——类继承方案。
更完善的方案:ModelHubMixin 类继承
如上所述,集成库需要两个核心方法:上传文件(push_to_hub)与下载文件(from_pretrained)。自己实现固然可行,但伴随不少坑。为此,huggingface_hub提供了一套基于类继承的现成工具——ModelHubMixin。
多数库已经用 Python 类实现了自己的模型:类中包含模型属性以及加载、运行、训练、评估的方法。ModelHubMixin的思路是用Mixin(混入类)通过多重继承扩展这个已有类,为其注入上传与下载能力。Mixin 是指利用多重继承为既有类扩展一组特定特性的类。
ModelHubMixin(hub_mixin.py)实现了 3 个public方法——push_to_hub、save_pretrained与from_pretrained,这是你的用户会实际调用的接口;同时定义了 2 个private方法——_save_pretrained与_from_pretrained,这两个才是你需要自己实现的。因此,集成你的库只需三步:
- 让模型类继承
ModelHubMixin。 - 实现私有方法:
_save_pretrained:接收一个目录路径参数,把模型写入该目录。模型卡、权重、配置文件、训练日志、图表等所有与该模型相关的信息都由这个方法负责落盘。模型卡对描述模型尤其重要,可参考 Model Cards 实现指南。_from_pretrained:类方法,接收model_id参数并返回实例化后的模型,负责下载相关文件并完成加载。
- 完成。
使用ModelHubMixin的好处是:一旦你处理好了文件的序列化/加载,剩下的仓库创建、提交、PR、revision 等事项统统不用操心。ModelHubMixin还保证了 public 方法带有文档与类型注解,并且你能在 Hub 上看到模型的下载量。所有这些都由ModelHubMixin接管并提供给你的用户。
从源码结构看(hub_mixin.py),ModelHubMixin正是通过__init_subclass__(L185-L278)在子类化时自动收集元数据、检查__init__签名、注册自定义编解码器;from_pretrained(L453-L565)会先下载并解析config.json,再回调你的_from_pretrained完成加载。
具体示例:PyTorch
PyTorchModelHubMixin(hub_mixin.py)是ModelHubMixin针对 PyTorch 框架的开箱即用集成,可作为类继承方案的最佳范本。
如何使用
任何用户都可以这样加载/保存 PyTorch 模型:
>>> import torch >>> import torch.nn as nn >>> from huggingface_hub import PyTorchModelHubMixin # 像平时一样定义 PyTorch 模型 >>> class MyModel( ... nn.Module, ... PyTorchModelHubMixin, # 多重继承 ... library_name="keras-nlp", ... tags=["keras"], ... repo_url="https://github.com/keras-team/keras-nlp", ... docs_url="https://keras.io/keras_nlp/", ... # ^ 用于生成模型卡的可选元数据 ... ): ... def __init__(self, hidden_size: int = 512, vocab_size: int = 30000, output_size: int = 4): ... super().__init__() ... self.param = nn.Parameter(torch.rand(hidden_size, vocab_size)) ... self.linear = nn.Linear(output_size, vocab_size) ... def forward(self, x): ... return self.linear(x + self.param) # 1. 创建模型 >>> model = MyModel(hidden_size=128) # 配置会自动根据传入值 + 默认值生成 >>> model.param.shape[0] 128 # 2.(可选)保存到本地目录 >>> model.save_pretrained("path/to/my-awesome-model") # 3. 推送模型权重到 Hub >>> model.push_to_hub("my-awesome-model") # 4. 从 Hub 初始化模型 => 配置已被完整保留 >>> model = MyModel.from_pretrained("username/my-awesome-model") >>> model.param.shape[0] 128 # 模型卡已被正确填充 >>> from huggingface_hub import ModelCard >>> card = ModelCard.load("username/my-awesome-model") >>> card.data.tags ["keras", "pytorch_model_hub_mixin", "model_hub_mixin"] >>> card.data.library_name "keras-nlp"实现细节
PyTorchModelHubMixin的实现非常直接,完整实现位于 hub_mixin.py。
- 首先让类继承
ModelHubMixin:
from huggingface_hub import ModelHubMixin class PyTorchModelHubMixin(ModelHubMixin): (...)- 实现
_save_pretrained方法:
from huggingface_hub import ModelHubMixin class PyTorchModelHubMixin(ModelHubMixin): (...) def _save_pretrained(self, save_directory: Path) -> None: """将 PyTorch 模型的权重保存到本地目录。""" save_model_as_safetensor(self.module, str(save_directory / SAFETENSORS_SINGLE_FILE))- 实现
_from_pretrained方法:
class PyTorchModelHubMixin(ModelHubMixin): (...) @classmethod # 必须是类方法! def _from_pretrained( cls, *, model_id: str, revision: str, cache_dir: str, force_download: bool, local_files_only: bool, token: Union[str, bool, None], map_location: str = "cpu", # 附加参数 strict: bool = False, # 附加参数 **model_kwargs, ): """加载 PyTorch 预训练权重并返回加载后的模型。""" model = cls(**model_kwargs) if os.path.isdir(model_id): print("从本地目录加载权重") model_file = os.path.join(model_id, SAFETENSORS_SINGLE_FILE) return cls._load_as_safetensor(model, model_file, map_location, strict) model_file = hf_hub_download( repo_id=model_id, filename=SAFETENSORS_SINGLE_FILE, revision=revision, cache_dir=cache_dir, force_download=force_download, token=token, local_files_only=local_files_only, ) return cls._load_as_safetensor(model, model_file, map_location, strict)完成!你的库现在已具备向 Hub 上传和从 Hub 下载文件的能力。
从源码看(hub_mixin.py),PyTorchModelHubMixin._save_pretrained会优先把权重保存为model.safetensors单文件(文件名常量定义于 constants.py);_from_pretrained在远端找不到 safetensors 文件时,还会回退下载pytorch_model.bin(PYTORCH_WEIGHTS_NAME,constants.py)并以 pickle 方式加载。另外注意:_load_as_safetensor与_load_as_pickle在加载完成后都会调用model.eval(),将模型置为评估模式,dropout 等模块会被停用;如需训练需手动调用model.train()。
高级用法
上一节介绍了ModelHubMixin的基本工作机制,这里再看几个能进一步优化库集成体验的高级特性。
模型卡自动生成
ModelHubMixin会自动为你生成模型卡。模型卡是伴随模型、提供重要信息的 Markdown 文件(含附加元数据),对模型的可发现性、可复现性和共享至关重要,详见 Model Cards 指南。
半自动地生成模型卡,能确保用你的库推送的所有模型共享统一的元数据:library_name、tags、license、pipeline_tag等。这让所有模型在 Hub 上易于搜索,也为访问模型的用户提供了资源链接。你可以在继承ModelHubMixin时直接定义这些元数据:
class UniDepthV1( nn.Module, PyTorchModelHubMixin, library_name="unidepth", repo_url="https://github.com/lpiccinelli-eth/UniDepth", docs_url=..., pipeline_tag="depth-estimation", license="cc-by-nc-4.0", tags=["monocular-metric-depth-estimation", "arxiv:1234.56789"] ): ...默认情况下,ModelHubMixin会根据你提供的这些信息生成一个通用模型卡(对应 DEFAULT_MODEL_CARD 模板)。但你也可以定义自己的模型卡模板!
以下示例中,所有用VoiceCraft类推送的模型都会自动包含引用(citation)章节和许可信息。关于如何定义模型卡模板,请参考 Model Cards 指南。
MODEL_CARD_TEMPLATE = """ --- # 关于模型卡元数据的规范,参见:https://github.com/huggingface/hub-docs/blob/main/modelcard.md?plain=1 # 文档/指南:https://huggingface.co/docs/hub/model-cards {{ card_data }} --- This is a VoiceCraft model. For more details, please check out the official Github repo: https://github.com/jasonppy/VoiceCraft. This model is shared under a Attribution-NonCommercial-ShareAlike 4.0 International license. ## Citation @article{peng2024voicecraft, author = {Peng, Puyuan and Huang, Po-Yao and Li, Daniel and Mohamed, Abdelrahman and Harwath, David}, title = {VoiceCraft: Zero-Shot Speech Editing and Text-to-Speech in the Wild}, journal = {arXiv}, year = {2024}, } """ class VoiceCraft( nn.Module, PyTorchModelHubMixin, library_name="voicecraft", model_card_template=MODEL_CARD_TEMPLATE, ... ): ...最后,如果你希望在模型卡生成流程中加入动态值,可以重写generate_model_card方法(源码见 hub_mixin.py,其内部通过ModelCard.from_template将模板、元数据与repo_url/paper_url/docs_url合并渲染):
from huggingface_hub import ModelCard, PyTorchModelHubMixin class UniDepthV1(nn.Module, PyTorchModelHubMixin, ...): (...) def generate_model_card(self, *args, **kwargs) -> ModelCard: card = super().generate_model_card(*args, **kwargs) card.data.metrics = ... # 向元数据中添加指标 card.text += ... # 向模型卡追加章节 return card配置的自动处理
ModelHubMixin替你管理模型配置:实例化模型时会自动检查输入值,并将其序列化到config.json文件中。这带来两个好处:
- 用户可以用与你完全相同的参数重新加载模型。
config.json的存在会自动启用 Hub 上的统计功能(即“下载量”计数)。
它的工作原理由几条规则支撑,力求对用户透明:
- 如果
__init__方法期望一个config输入,它会自动作为config.json保存到仓库中; - 如果
config输入参数标注了 dataclass 类型(例如config: Optional[MyConfigClass] = None),那么config值会被正确地反序列化; - 初始化时传入的所有值也会被存入配置文件,因此你不一定非要声明
config输入参数才能受益。
示例:
class MyModel(ModelHubMixin): def __init__(value: str, size: int = 3): self.value = value self.size = size (...) # 实现 _save_pretrained / _from_pretrained model = MyModel(value="my_value") model.save_pretrained(...) # config.json 中包含传入值与默认值 {"value": "my_value", "size": 3}源码层面,这一逻辑在__init_subclass__(检查签名、记录可 JSON 化的默认值)与__new__(hub_mixin.py,合并默认值与传入值构建配置)中实现;save_pretrained(hub_mixin.py)负责将配置写入config.json并生成模型卡。对应的测试覆盖在 tests/test_hub_mixin.py 中,例如test_save_pretrained_as_dict_basic、test_save_pretrained_with_dataclass_config分别验证 dict 与 dataclass 形式的配置均能被正确落盘。
处理不可 JSON 序列化的自定义类型
如果一个值无法被 JSON 序列化会怎样?默认情况下它会在保存配置文件时被忽略。但在某些情况下,你的库已经期望一个无法序列化的自定义对象作为输入,而你又不希望改动内部逻辑去改变它的类型——这时你可以在继承ModelHubMixin时为任意类型传入自定义编码器/解码器。这虽然多一点工作量,但能保证集成时你的内部逻辑完全不动。
下面是一个具体例子:类期望argparse.Namespace作为配置输入。
class VoiceCraft(nn.Module): def __init__(self, args): self.pattern = self.args.pattern self.hidden_size = self.args.hidden_size ...一种解决思路是把__init__签名改成def __init__(self, pattern: str, hidden_size: int),并同步更新所有实例化该类的代码片段。这是完全有效的方式,但可能破坏下游依赖你库的应用。
另一种方案是提供一个简单的编码器/解码器,把argparse.Namespace转换成字典:
from argparse import Namespace class VoiceCraft( nn.Module, PyTorchModelHubMixin, # 继承 mixin coders={ Namespace : ( lambda x: vars(x), # 编码器:如何把 Namespace 转成可 JSON 化的值? lambda data: Namespace(**data), # 解码器:如何从字典重建 Namespace? ) } ): def __init__(self, args: Namespace): # 为 args 添加类型注解 self.pattern = self.args.pattern self.hidden_size = self.args.hidden_size ...在上面的代码中,类的内部逻辑与__init__签名都没有改变,意味着你库中所有现有代码片段可以继续工作。要达成这一点,需要做到:
- 继承 mixin(此例为
PyTorchModelHubMixin)。 - 在继承时传入
coders参数。这是一个字典,键是你想要处理的自定义类型,值是(encoder, decoder)元组:- 编码器接收指定类型的对象作为输入,返回一个可 JSON 化的值。用于
save_pretrained保存模型时; - 解码器接收原始数据(通常是字典)作为输入,重建初始对象。用于
from_pretrained加载模型时。
- 编码器接收指定类型的对象作为输入,返回一个可 JSON 化的值。用于
- 为
__init__签名添加类型注解。这很重要——它让 mixin 知道类期望哪种类型,从而选择对应的解码器。
源码中,编码/解码逻辑实现在_encode_arg与_decode_arg(hub_mixin.py):_encode_arg对 dataclass 使用asdict,否则遍历coders查找匹配类型;_decode_arg会先剥离Optional[...]包装、处理 dataclass,再回退到自定义解码器。测试test_from_cls_with_custom_type(tests/test_hub_mixin.py)验证了自定义类型在保存与重载后值完全一致(含None与默认值场景)。
需要提醒:上例中的编码器/解码器函数仅为演示,并不健壮。落地到真实库时,你很可能需要妥善处理各种边界情况。
两种方案快速对比
下表汇总了两种方案的优缺点,仅供参考。你的框架可能有需要特殊处理的特性——本指南只提供思路与指导,如有疑问欢迎联系我们。
| 集成方式 | 使用 Helper 函数 | 使用 ModelHubMixin |
|---|---|---|
| 用户体验 | model = load_from_hub(...)push_to_hub(model, ...) | model = MyModel.from_pretrained(...)model.push_to_hub(...) |
| 灵活性 | 非常灵活。 实现完全由你掌控。 | 灵活性较低。 你的框架必须有一个模型类。 |
| 维护成本 | 支持配置与新功能需要更多维护。可能还需要修复用户上报的问题。 | 维护成本低,因为与 Hub 的大部分交互已由huggingface_hub实现。 |
| 文档 / 类型注解 | 需要手动编写。 | 部分由huggingface_hub代劳。 |
| 下载量统计 | 需要手动处理。 | 若类拥有config属性,默认启用。 |
| 模型卡 | 需要手动处理。 | 默认生成,含 library_name、tags 等。 |
小结与源码指引
两条集成路线各有适用场景:追求完全掌控且实现轻量的库,适合Helper 函数方案;已有统一模型类、希望最小化维护成本的库,则强烈建议基于ModelHubMixin做类继承集成。无论选择哪条路线,底层能力都由huggingface_hub统一提供。
- 核心实现:ModelHubMixin 与 PyTorchModelHubMixin
- Helper 范本:fastai 集成的
from_pretrained_fastai/push_to_hub_fastai - 相关常量:
model.safetensors、pytorch_model.bin、config.json等文件名定义 - 测试验证:ModelHubMixin 的配置保存、类型编解码、继承与类型注解测试
- 配套指南:upload files 指南 与 download files 指南
如果你完成了框架集成并希望被收录进官方支持列表,可以联系我们。开始动手把属于你的框架接入 Hub 吧。
- 开发工具
- CLI
- 机器学习
【免费下载链接】huggingface_hub
The official CLI and Python client for the Hugging Face Hub.
相关推荐
GetQzonehistory完整导出教程:3步把QQ空间全部历史说说导出成Excel
GetQzonehistory完整导出教程:3步把QQ空间全部历史说说导出成Excel QQ空间首页只显示近几年的动态,几年前发的说说根本翻不到。GetQzon
开发工具CLI机器学习FastStream与HTTP框架集成:任意Web框架的无缝对接方案
FastStream与HTTP框架集成:任意Web框架的无缝对接方案 引言:消息驱动架构的现代挑战 在当今微服务架构盛行的时代,消息队列(Message Que
后端消息队列微服务如何用MOOTDX构建专业级量化交易系统:从数据获取到策略实现的完整指南
如何用MOOTDX构建专业级量化交易系统:从数据获取到策略实现的完整指南 MOOTDX是一个功能强大的Python通达信数据接口库,为量化投资者提供了高效、稳定
金融科技数据分析
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考