在 Hugging Face 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 後端託管服務互動的類。透過它,我們可以與模型、資料集等進行互動。同時,我們還會匯入幾個輔助類:ModelFilter
和 ModelSearchArguments
。
from huggingface_hub import HfApi, ModelFilter, ModelSearchArguments
api = HfApi()
這兩個類可以幫助我們為上述問題構建解決方案。ModelSearchArguments
類類似於一個名稱空間,包含了我們可以搜尋的每一個有效引數!
讓我們來看一看。
>>> model_args = ModelSearchArguments()
>>> model_args
Available Attributes or Keys:
* author
* dataset
* language
* library
* license
* model_name
* pipeline_tag
我們可以看到有多種可用的屬性(稍後會詳細介紹這背後的魔法)。如果我們要對我們想要的東西進行分類,大概可以分為:
pipeline_tag
(或任務):文字分類dataset
(資料集):GLUElibrary
(庫):PyTorch
鑑於這樣的分類,我們很自然地會在我們宣告的 model_args
中找到它們。
>>> model_args.pipeline_tag.TextClassification
'text-classification'
>>> model_args.dataset.glue
'dataset:glue'
>>> model_args.library.PyTorch
'pytorch'
不過,我們開始注意到這裡進行的一些便利性封裝。ModelSearchArguments
(以及與之配套的 DatasetSearchArguments
)提供了一個人類可讀的介面,其中包含了 API 期望的格式化輸出,例如 GLUE 資料集應該用 dataset: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')
更進一步
我們已經瞭解瞭如何使用 ModelSearchArguments
和 DatasetSearchArguments
來消除搜尋 Hub 時的猜測,但如果我們有一個非常複雜、混亂的查詢呢?
例如:我想搜尋所有同時為 text-classification
(文字分類)和 zero-shot
(零樣本)分類任務訓練的模型,這些模型在 MultiNLI 和 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
類的啟發,其核心思想是我們將一個普通字典進行“超級充電”,透過為字典中的每個鍵提供 Tab 補全功能,來支援_探索式程式設計_。
正如我們之前所見,當我們擁有可以探索的巢狀字典時,例如 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_c
的 AttributeDictionary
。
>>> d = {"a":2, "b":3, "3_c":4}
>>> ad = AttributeDictionary(d)
>>> # As an attribute
>>> ad.3_c
File "<ipython-input-6-c0fe109cf75d>", line 2
ad.3_c
^
SyntaxError: invalid token
>>> # As a dictionary key
>>> ad["3_c"]
4
總結
希望現在你對這個新的搜尋 API 如何直接影響你的工作流程和 Hub 探索有了一個初步的瞭解!同時,也許你也想到了在你的程式碼中,AttributeDictionary
可能會派上用場的地方。