在🤗 Hub上进行超级搜索

'超级搜索 Hub'

huggingface_hub库是一个轻量级接口,提供了一种以编程方式探索Hugging Face提供的托管端点(模型、数据集和Spaces)的方法。

到目前为止,通过该接口在Hub上进行搜索是非常棘手的,用户必须“只知道”并适应其中的许多方面。

在本文中,我们将介绍一些添加到huggingface_hub中的令人兴奋的新功能,以帮助降低门槛,并为用户提供友好的API,以在不离开Jupyter或Python界面的情况下搜索他们想要使用的模型和数据集。

在开始之前,请确保您的系统上安装了最新版本的huggingface_hub库,请运行以下单元格:

!pip install huggingface_hub -U

问题背景:

首先,让我们想象一下你的情景。您想要找到在Hugging Face Hub上托管的用于文本分类的所有模型,这些模型是在GLUE数据集上训练的,并且与PyTorch兼容。

您可以简单地打开https://huggingface.co/models并使用其中的小部件。但这需要离开您的IDE,并扫描这些结果,所有这些都需要点击几个按钮才能获得您所需的信息。

如果有一种解决方案,而无需离开您的IDE,该怎么办?通过编程接口,也可以轻松将其集成到探索Hub的工作流程中。

这就是huggingface_hub的作用。

对于熟悉该库的人来说,您可能已经知道我们可以搜索这些类型的模型。然而,正确设置查询是一个痛苦的试错过程。

我们能简化这个过程吗?让我们找出来!

找到我们需要的内容

首先,我们将导入HfApi类,它是一个帮助我们与Hugging Face的后端托管进行交互的类。我们可以通过它与模型、数据集等进行交互。此外,我们还将导入一些辅助类: ModelFilterModelSearchArguments

from huggingface_hub import HfApi, ModelFilter, ModelSearchArguments

api = HfApi()

这两个类可以帮助我们构建解决方案来解决上述问题。 ModelSearchArguments 类是一个类似命名空间的类,它包含我们可以搜索的每个有效参数!

让我们来看一下:

>>> model_args = ModelSearchArguments()

>>> model_args

可用的属性或键:
 * 作者(author)
 * 数据集(dataset)
 * 语言(language)
 * 库(library)
 * 许可证(license)
 * 模型名称(model_name)
 * 流水线标签(pipeline_tag)

我们可以看到许多可用的属性(稍后会介绍这种神奇的实现方式)。如果我们要对我们想要的内容进行分类,我们可能可以将它们分开:

  • 流水线标签(pipeline_tag)(或任务):文本分类
  • 数据集(dataset):GLUE
  • 库(library):PyTorch

在这种分离下,我们应该能够在我们声明的model_args中找到它们:

>>> model_args.pipeline_tag.TextClassification

'text-classification'

>>> model_args.dataset.glue

'dataset:glue'

>>> model_args.library.PyTorch

'pytorch'

然而,我们开始注意到这里的一些便利包装。 ModelSearchArguments(以及配套的DatasetSearchArguments)具有人类可读的界面,其格式化输出与API所需的格式相匹配,例如如何使用dataset:glue搜索GLUE数据集。

这很重要,因为如果没有这个“备忘单”,您很容易在尝试使用API搜索模型时感到沮丧!

现在我们知道了正确的参数,我们可以轻松搜索API:

>>> models = api.list_models(filter = (
>>>     model_args.pipeline_tag.TextClassification, 
>>>     model_args.dataset.glue, 
>>>     model_args.library.PyTorch)
>>> )
>>> print(len(models))

    140

我们发现有140个符合我们要求的匹配模型!(截止到撰写本文时)。如果我们仔细观察其中一个模型,我们可以看到它确实是正确的:

>>> models[0]

    ModelInfo: {
        modelId: Jiva/xlm-roberta-large-it-mnli
        sha: c6e64469ec4aa17fedbd1b2522256f90a90b5b86
        lastModified: 2021-12-10T14:56:38.000Z
        tags: ['pytorch', 'xlm-roberta', 'text-classification', 'it', 'dataset:multi_nli', 'dataset:glue', 'arxiv:1911.02116', 'transformers', 'tensorflow', 'license:mit', 'zero-shot-classification']
        pipeline_tag: zero-shot-classification
        siblings: [ModelFile(rfilename='.gitattributes'), ModelFile(rfilename='README.md'), ModelFile(rfilename='config.json'), ModelFile(rfilename='pytorch_model.bin'), ModelFile(rfilename='sentencepiece.bpe.model'), ModelFile(rfilename='special_tokens_map.json'), ModelFile(rfilename='tokenizer.json'), ModelFile(rfilename='tokenizer_config.json')]
        config: None
        private: False
        downloads: 680
        library_name: transformers
        likes: 1
    }

这样更易读,并且不需要猜测”我是否正确获取了这个参数?”

您知道您还可以使用模型ID以编程方式获取此模型的信息吗?下面是您可以执行此操作的方法:

api.model_info('Jiva/xlm-roberta-large-it-mnli')

提升一级

我们看到了如何使用ModelSearchArgumentsDatasetSearchArguments来消除在搜索Hub时的猜测工作,但是如果我们有一个非常复杂、混乱的查询呢?

例如:我想搜索所有针对text-classificationzero-shot分类进行过训练的模型,这些模型是在Multi NLI和GLUE数据集上训练的,并且与PyTorch和TensorFlow都兼容(一个更精确的查询以获取上述模型)。

为了设置这个查询,我们将使用ModelFilter类。它专门处理这些类型的情况,所以我们不需要费脑筋:

>>> filt = ModelFilter(
>>>     task = ["text-classification", "zero-shot-classification"],
>>>     trained_dataset = [model_args.dataset.multi_nli, model_args.dataset.glue],
>>>     library = ['pytorch', 'tensorflow']
>>> )
>>> api.list_models(filt)

    [ModelInfo: {
         modelId: Jiva/xlm-roberta-large-it-mnli
         sha: c6e64469ec4aa17fedbd1b2522256f90a90b5b86
         lastModified: 2021-12-10T14:56:38.000Z
         tags: ['pytorch', 'xlm-roberta', 'text-classification', 'it', 'dataset:multi_nli', 'dataset:glue', 'arxiv:1911.02116', 'transformers', 'tensorflow', 'license:mit', 'zero-shot-classification']
         pipeline_tag: zero-shot-classification
         siblings: [ModelFile(rfilename='.gitattributes'), ModelFile(rfilename='README.md'), ModelFile(rfilename='config.json'), ModelFile(rfilename='pytorch_model.bin'), ModelFile(rfilename='sentencepiece.bpe.model'), ModelFile(rfilename='special_tokens_map.json'), ModelFile(rfilename='tokenizer.json'), ModelFile(rfilename='tokenizer_config.json')]
         config: None
         private: False
         downloads: 680
         library_name: transformers
         likes: 1
     }]

非常快地,我们可以看到这是一种更协调的API搜索方法,而且不会给您增加任何麻烦!

魔法是什么?

我们简要地讨论一下底层的魔法,它使我们得到这种类似于枚举字典的数据类型AttributeDictionary

受到fastcore库中AttrDict类的启发,其基本思想是我们将一个普通的字典进行增强,通过为字典中的每个键提供制表符补全,从而为探索性编程提供支持。

正如我们之前所看到的,当我们拥有可以通过的嵌套字典时,例如model_args.dataset.glue,这种功能变得更强大!

对于熟悉JavaScript的人来说,我们模仿了object类的工作方式。

这个简单的实用类可以在探索嵌套数据类型和尝试理解API请求的返回值等情况下,提供更加以用户为中心的体验!

如前所述,我们通过一些关键的方式对AttrDict进行了扩展:

  • 您可以使用del model_args[key]del model_args.key删除键
  • 我们之前看到的干净的__repr__

但是需要注意的一个非常重要的概念是,如果一个键包含数字或特殊字符,则必须将其索引为字典,而不是对象。

>>> from huggingface_hub.utils.endpoint_helpers import AttributeDictionary

一个非常简单的例子是,如果我们有一个键为3_cAttributeDictionary

>>> d = {"a":2, "b":3, "3_c":4}
>>> ad = AttributeDictionary(d)

>>> # 作为属性
>>> ad.3_c

 File "<ipython-input-6-c0fe109cf75d>", line 2
    ad.3_c
        ^
SyntaxError: invalid token

>>> # 作为字典键
>>> ad["3_c"]

4

总结

希望到目前为止,您对这种新的搜索API如何直接影响您的工作流程和对Hub的探索有了一个简要的了解!除此之外,也许您知道在您的代码中有一个可以使用AttributeDictionary的地方。

从这里开始,请确保查阅有关高效搜索Hub的官方文档,也不要忘记给我们一个星星!