Ricerca potenziata su 🤗 Hub

Ricerca avanzata su 🤗 Hub.

La libreria huggingface_hub è un’interfaccia leggera che fornisce un approccio programmatico per esplorare i punti di hosting forniti da Hugging Face: modelli, dataset e Spazi.

Fino ad ora, cercare su Hub attraverso questa interfaccia era difficile da realizzare e c’erano molti aspetti di cui l’utente doveva “conoscere” e abituarsi.

In questo articolo, esamineremo alcune nuove funzionalità aggiunte a huggingface_hub per aiutare a ridurre quella barriera e fornire agli utenti un’API amichevole per cercare i modelli e i dataset che desiderano utilizzare senza lasciare le loro interfacce Jupyter o Python.

Prima di iniziare, se non hai l’ultima versione della libreria huggingface_hub nel tuo sistema, esegui il seguente blocco:

!pip install huggingface_hub -U

Situatione del Problema:

Prima di tutto, immaginiamo la situazione in cui ti trovi. Vorresti trovare tutti i modelli ospitati su Hugging Face Hub per la Classificazione del Testo, che sono stati addestrati sul dataset GLUE e sono compatibili con PyTorch.

Potresti semplicemente aprire https://huggingface.co/models e utilizzare i widget presenti lì. Ma questo richiede di lasciare il tuo IDE e esaminare quei risultati, il tutto richiede alcuni clic per ottenere le informazioni di cui hai bisogno.

E se ci fosse una soluzione a questo senza dover lasciare il tuo IDE? Con un’interfaccia programmatica, potrebbe anche essere facile vedere tutto questo integrato nei flussi di lavoro per esplorare l’Hub.

Ecco dove entra in gioco huggingface_hub.

Per coloro che sono familiari con la libreria, potresti già sapere che possiamo cercare questi tipi di modelli. Tuttavia, ottenere la query corretta è un processo doloroso di tentativi ed errori.

Potremmo semplificarlo? Scopriamolo!

Trovare ciò di cui abbiamo bisogno

Prima di tutto importeremo la classe HfApi, che è una classe che ci aiuta a interagire con l’hosting di backend per Hugging Face. Possiamo interagire con i modelli, i dataset e altro ancora attraverso di essa. Insieme a questa, importeremo alcune classi di supporto: ModelFilter e ModelSearchArguments

from huggingface_hub import HfApi, ModelFilter, ModelSearchArguments

api = HfApi()

Queste due classi possono aiutarci a formulare una soluzione al nostro problema sopra. La classe ModelSearchArguments è una sorta di spazio dei nomi che contiene ogni singolo parametro valido che possiamo cercare!

Diamo un’occhiata:

>>> model_args = ModelSearchArguments()

>>> model_args

Attributi o chiavi disponibili:
 * autore
 * dataset
 * lingua
 * libreria
 * licenza
 * nome_modello
 * tag_del_pipeline

Possiamo vedere una varietà di attributi disponibili per noi (ulteriori informazioni su come viene fatto questo trucco più tardi). Se dovessimo categorizzare ciò che vogliamo, potremmo probabilmente separarli come:

  • tag_del_pipeline (o compito): Classificazione del Testo
  • dataset: GLUE
  • libreria: PyTorch

Dato questo separazione, avrebbe senso trovarli all’interno dei nostri model_args che abbiamo dichiarato:

>>> model_args.tag_del_pipeline.ClassificazioneDelTesto

'classificazione-del-testo'

>>> model_args.dataset.glue

'dataset:glue'

>>> model_args.libreria.PyTorch

'pytorch'

Ciò che iniziamo a notare però è alcuni dei comodi wrapping che facciamo qui. ModelSearchArguments (e il complementare DatasetSearchArguments) hanno un’interfaccia leggibile dall’umano con output formattati che l’API desidera, come ad esempio come il dataset GLUE dovrebbe essere cercato con dataset:glue.

Questo è fondamentale perché senza questo “foglio di suggerimenti” di conoscere come determinati parametri dovrebbero essere scritti, è molto facile sedersi nella frustrazione mentre si sta cercando modelli con l’API!

Ora che sappiamo quali sono i parametri corretti, possiamo cercare facilmente nell’API:

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

    140

Troviamo che ci sono 140 modelli corrispondenti ai nostri criteri! (al momento della stesura di questo testo). E se guardiamo da vicino uno di essi, possiamo vedere che sembra corretto:

>>> modelli[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
    }

È un po’ più leggibile e non c’è bisogno di indovinare se “ho inserito correttamente questo parametro?”

Sapevi che puoi ottenere anche le informazioni di questo modello in modo programmato con il suo ID del modello? Ecco come lo faresti:

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

Migliorando ancora di più

Abbiamo visto come possiamo utilizzare ModelSearchArguments e DatasetSearchArguments per eliminare l’incertezza quando vogliamo cercare nell’Hub, ma cosa succede se abbiamo una query molto complessa e disordinata?

Ad esempio: vogliamo cercare tutti i modelli addestrati sia per la classificazione del testo che per la classificazione senza etichette, addestrati sui dataset Multi NLI e GLUE e compatibili sia con PyTorch che con TensorFlow (una query più precisa per ottenere il modello sopra).

Per impostare questa query, useremo la classe ModelFilter. È progettata per gestire questo tipo di situazioni, quindi non dobbiamo grattarci la testa:

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

    [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
     }]

Quindi velocemente vediamo che si tratta di un approccio molto più coordinato per la ricerca attraverso l’API, senza alcun mal di testa aggiuntivo per te!

Cosa è la magia?

In modo molto breve parleremo della magia sottostante che ci permette di avere questo tipo di dato simile a un dizionario enumerato, il AttributeDictionary.

Fortemente ispirato dalla classe AttrDict della libreria fastcore, l’idea generale è quella di prendere un dizionario normale e potenziarlo per la programmazione esplorativa fornendo il completamento automatico per ogni chiave nel dizionario.

Come abbiamo visto in precedenza, ciò diventa ancora più potente quando abbiamo dizionari nidificati che possiamo esplorare, come ad esempio model_args.dataset.glue !

Per coloro che sono familiari con JavaScript, imitiamo come funziona la classe object.

Questa semplice classe di utilità può offrire un’esperienza molto più focalizzata sull’utente durante l’esplorazione di tipi di dati nidificati e nel tentativo di capire cosa c’è, come il risultato di una richiesta API!

Come accennato in precedenza, espandiamo l’AttrDict in alcuni modi chiave:

  • Puoi eliminare chiavi con del model_args[key] o con del model_args.key
  • Quella pulita __repr__ che abbiamo visto in precedenza

Tuttavia, un concetto molto importante da notare è che se una chiave contiene un numero o un carattere speciale, deve essere indicizzata come un dizionario e non come un oggetto.

>>> from huggingface_hub.utils.endpoint_helpers import AttributeDictionary

Un esempio molto breve di ciò è se abbiamo un AttributeDictionary con una chiave di 3_c :

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

>>> # Come attributo
>>> ad.3_c

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

>>> # Come chiave di un dizionario
>>> ad["3_c"]

4

Considerazioni finali

Spero che a questo punto tu abbia una breve comprensione di come questa nuova API di ricerca possa influire direttamente sul tuo flusso di lavoro e sull’esplorazione dell’Hub! Inoltre, forse conosci un punto nel tuo codice in cui l’uso di AttributeDictionary potrebbe essere utile.

Da qui, assicurati di consultare la documentazione ufficiale sulla Ricerca Efficiente nell’Hub e non dimenticare di darci una stella !