first commit
Some checks failed
Self-hosted runner (nightly-past-ci-caller) / Get number (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.11 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.10 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.9 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.8 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.7 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.6 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.5 (push) Has been cancelled
Self-hosted runner (benchmark) / Benchmark (aws-g5-4xlarge-cache) (push) Has been cancelled
Build documentation / build (push) Has been cancelled
Build documentation / build_other_lang (push) Has been cancelled
CodeQL Security Analysis / CodeQL Analysis (push) Has been cancelled
New model PR merged notification / Notify new model (push) Has been cancelled
PR CI / pr-ci (push) Has been cancelled
Slow tests on important models (on Push - A10) / Get all modified files (push) Has been cancelled
Secret Leaks / trufflehog (push) Has been cancelled
Update Transformers metadata / build_and_package (push) Has been cancelled
Slow tests on important models (on Push - A10) / Model CI (push) Has been cancelled
Check Tiny Models / Check tiny models (push) Has been cancelled
Self-hosted runner (Intel Gaudi3 scheduled CI caller) / Model CI (push) Has been cancelled
Self-hosted runner (Intel Gaudi3 scheduled CI caller) / Pipeline CI (push) Has been cancelled
Self-hosted runner (Intel Gaudi3 scheduled CI caller) / Example CI (push) Has been cancelled
Self-hosted runner (Intel Gaudi3 scheduled CI caller) / DeepSpeed CI (push) Has been cancelled
Self-hosted runner (Intel Gaudi3 scheduled CI caller) / Trainer/FSDP CI (push) Has been cancelled
Nvidia CI - Flash Attn / Setup (push) Has been cancelled
Nvidia CI - Flash Attn / Model CI (push) Has been cancelled
Nvidia CI / Setup (push) Has been cancelled
Nvidia CI / Model CI (push) Has been cancelled
Nvidia CI / Torch pipeline CI (push) Has been cancelled
Nvidia CI / Example CI (push) Has been cancelled
Nvidia CI / Trainer/FSDP CI (push) Has been cancelled
Nvidia CI / DeepSpeed CI (push) Has been cancelled
Nvidia CI / Quantization CI (push) Has been cancelled
Nvidia CI / Kernels CI (push) Has been cancelled
Doctests / Setup (push) Has been cancelled
Doctests / Call doctest jobs (push) Has been cancelled
Doctests / Send results to webhook (push) Has been cancelled
Extras Smoke Test / Get supported Python versions (push) Has been cancelled
Extras Smoke Test / Test extras on Python ${{ matrix.python-version }} (push) Has been cancelled
Extras Smoke Test / Check Slack token availability (push) Has been cancelled
Extras Smoke Test / Notify failures to Slack (push) Has been cancelled
Self-hosted runner (AMD scheduled CI caller) / Trigger Scheduled AMD CI (push) Has been cancelled
Stale Bot / Close Stale Issues (push) Has been cancelled
Some checks failed
Self-hosted runner (nightly-past-ci-caller) / Get number (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.11 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.10 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.9 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.8 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.7 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.6 (push) Has been cancelled
Self-hosted runner (nightly-past-ci-caller) / TensorFlow 2.5 (push) Has been cancelled
Self-hosted runner (benchmark) / Benchmark (aws-g5-4xlarge-cache) (push) Has been cancelled
Build documentation / build (push) Has been cancelled
Build documentation / build_other_lang (push) Has been cancelled
CodeQL Security Analysis / CodeQL Analysis (push) Has been cancelled
New model PR merged notification / Notify new model (push) Has been cancelled
PR CI / pr-ci (push) Has been cancelled
Slow tests on important models (on Push - A10) / Get all modified files (push) Has been cancelled
Secret Leaks / trufflehog (push) Has been cancelled
Update Transformers metadata / build_and_package (push) Has been cancelled
Slow tests on important models (on Push - A10) / Model CI (push) Has been cancelled
Check Tiny Models / Check tiny models (push) Has been cancelled
Self-hosted runner (Intel Gaudi3 scheduled CI caller) / Model CI (push) Has been cancelled
Self-hosted runner (Intel Gaudi3 scheduled CI caller) / Pipeline CI (push) Has been cancelled
Self-hosted runner (Intel Gaudi3 scheduled CI caller) / Example CI (push) Has been cancelled
Self-hosted runner (Intel Gaudi3 scheduled CI caller) / DeepSpeed CI (push) Has been cancelled
Self-hosted runner (Intel Gaudi3 scheduled CI caller) / Trainer/FSDP CI (push) Has been cancelled
Nvidia CI - Flash Attn / Setup (push) Has been cancelled
Nvidia CI - Flash Attn / Model CI (push) Has been cancelled
Nvidia CI / Setup (push) Has been cancelled
Nvidia CI / Model CI (push) Has been cancelled
Nvidia CI / Torch pipeline CI (push) Has been cancelled
Nvidia CI / Example CI (push) Has been cancelled
Nvidia CI / Trainer/FSDP CI (push) Has been cancelled
Nvidia CI / DeepSpeed CI (push) Has been cancelled
Nvidia CI / Quantization CI (push) Has been cancelled
Nvidia CI / Kernels CI (push) Has been cancelled
Doctests / Setup (push) Has been cancelled
Doctests / Call doctest jobs (push) Has been cancelled
Doctests / Send results to webhook (push) Has been cancelled
Extras Smoke Test / Get supported Python versions (push) Has been cancelled
Extras Smoke Test / Test extras on Python ${{ matrix.python-version }} (push) Has been cancelled
Extras Smoke Test / Check Slack token availability (push) Has been cancelled
Extras Smoke Test / Notify failures to Slack (push) Has been cancelled
Self-hosted runner (AMD scheduled CI caller) / Trigger Scheduled AMD CI (push) Has been cancelled
Stale Bot / Close Stale Issues (push) Has been cancelled
This commit is contained in:
14
docs/source/ro/_config.py
Normal file
14
docs/source/ro/_config.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# docstyle-ignore
|
||||
INSTALL_CONTENT = """
|
||||
# Instalare Transformers
|
||||
! pip install transformers datasets evaluate accelerate
|
||||
# Pentru a instala din codul sursă în loc de cea mai nouă versiune stabilă, fă linia de mai sus comentariu, iar pe cea de mai jos activă.
|
||||
# ! pip install git+https://github.com/huggingface/transformers.git
|
||||
"""
|
||||
|
||||
notebook_first_cells = [{"type": "code", "content": INSTALL_CONTENT}]
|
||||
black_avoid_patterns = {
|
||||
"{processor_class}": "FakeProcessorClass",
|
||||
"{model_class}": "FakeModelClass",
|
||||
"{object_class}": "FakeObjectClass",
|
||||
}
|
||||
87
docs/source/ro/_toctree.yml
Normal file
87
docs/source/ro/_toctree.yml
Normal file
@@ -0,0 +1,87 @@
|
||||
- sections:
|
||||
- local: index
|
||||
title: Transformers
|
||||
- local: installation
|
||||
title: Instalare
|
||||
- local: quicktour
|
||||
title: Pornire rapidă
|
||||
title: Începe
|
||||
- isExpanded: true
|
||||
sections:
|
||||
- isExpanded: false
|
||||
sections:
|
||||
- local: weightconverter
|
||||
title: Încărcarea dinamică de weights
|
||||
- local: models
|
||||
title: Încărcarea modelelor
|
||||
- local: custom_models
|
||||
title: Personalizarea modelelor
|
||||
- local: monkey_patching
|
||||
title: Monkey patching
|
||||
- local: fusion_mapping
|
||||
title: Fusion mapping
|
||||
- local: how_to_hack_models
|
||||
title: Personalizarea componentelor modelului
|
||||
- local: model_sharing
|
||||
title: Distribuire
|
||||
- local: serialization
|
||||
title: Exportarea pentru producție
|
||||
- isExpanded: false
|
||||
sections:
|
||||
- local: contributing
|
||||
title: Contribuie la Transformers
|
||||
- local: modular_transformers
|
||||
title: Adaugă un model cu transformers modulare
|
||||
- local: multimodal_processing
|
||||
title: Procesatoare multimodale
|
||||
- local: add_vision_processing_components
|
||||
title: Componente de procesare vizuală
|
||||
- local: add_audio_processing_components
|
||||
title: Componente de procesare audio
|
||||
- local: modeling_rules
|
||||
title: Regulile de structură a modelului
|
||||
- local: model_output_tracing
|
||||
title: Urmărirea output-urilor intermediare ale modelului
|
||||
- local: auto_docstring
|
||||
title: Auto-generarea docstring-urilor
|
||||
- local: testing
|
||||
title: Scrierea testelor pentru modele
|
||||
- local: pr_checks
|
||||
title: Verificările pentru pull request
|
||||
- local: add_new_model
|
||||
title: Contribuția legacy la modele
|
||||
title: Contribuie
|
||||
title: Models
|
||||
- isExpanded: false
|
||||
sections:
|
||||
- local: fast_tokenizers
|
||||
title: Tokenizere
|
||||
- local: custom_tokenizers
|
||||
title: Personalizarea Tokenizerelor
|
||||
- local: tokenizer_summary
|
||||
title: Algoritmi de Tokenization
|
||||
- local: image_processors
|
||||
title: Procesatoare de imagini
|
||||
- local: video_processors
|
||||
title: Procesatoare video
|
||||
- local: backbones
|
||||
title: Backbone-uri
|
||||
- local: feature_extractors
|
||||
title: Feature extractors
|
||||
- local: processors
|
||||
title: Procesatoare
|
||||
title: Preprocesatoare
|
||||
title: Clase de bază
|
||||
- isExpanded: true
|
||||
sections:
|
||||
- isExpanded: false
|
||||
sections:
|
||||
- local: pipeline_tutorial
|
||||
title: Pipeline
|
||||
- local: pipeline_gradio
|
||||
title: Aplicații de Machine learning
|
||||
- local: pipeline_webserver
|
||||
title: Inferență pe web server
|
||||
- local: add_new_pipeline
|
||||
title: Adăugarea unui nou pipeline
|
||||
title: API-ul Pipeline
|
||||
103
docs/source/ro/add_audio_processing_components.md
Normal file
103
docs/source/ro/add_audio_processing_components.md
Normal file
@@ -0,0 +1,103 @@
|
||||
<!--Copyright 2026 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Adaugă componente de procesare audio
|
||||
|
||||
Modelele audio necesită un feature extractor accesibil prin punctul de intrare [`AutoFeatureExtractor`].
|
||||
|
||||
> [!NOTE]
|
||||
> Pentru pașii de modelare și configurare, urmează mai întâi ghidul [modular](./modular_transformers).
|
||||
|
||||
## Feature extractor
|
||||
|
||||
Adaugă un feature extractor când modelul consumă audio brut sau features derivate din audio.
|
||||
|
||||
Creează `feature_extraction_<model_name>.py` în directorul modelului. Moștenește din [`SequenceFeatureExtractor`] pentru ca noua clasă să obțină comportamentul comun de padding, truncare, salvare și încărcare.
|
||||
|
||||
```py
|
||||
from ...feature_extraction_sequence_utils import SequenceFeatureExtractor
|
||||
|
||||
|
||||
class MyModelFeatureExtractor(SequenceFeatureExtractor):
|
||||
model_input_names = ["input_features", "attention_mask"]
|
||||
|
||||
def __init__(self, feature_size=80, sampling_rate=16000, padding_value=0.0, **kwargs):
|
||||
super().__init__(feature_size=feature_size, sampling_rate=sampling_rate, padding_value=padding_value, **kwargs)
|
||||
|
||||
def __call__(self, raw_speech, sampling_rate=None, **kwargs):
|
||||
if sampling_rate is not None and sampling_rate != self.sampling_rate:
|
||||
raise ValueError(f"`sampling_rate` must be {self.sampling_rate}, but got {sampling_rate}.")
|
||||
|
||||
# Convertește raw_speech în features ale modelului aici.
|
||||
...
|
||||
```
|
||||
|
||||
Ține constructorul mic și serializabil. Stochează fiecare valoare necesară pentru reproducerea preprocesării ca atribut de instanță și evită stocarea valorilor exclusiv de runtime, cum ar fi fișiere deschise, dispozitive sau array-uri audio decodate.
|
||||
|
||||
Metoda `__call__` trebuie să valideze sampling rate-ul de input când utilizatorii pasează `sampling_rate`. Dacă rata de input diferă de rata așteptată de model, ridică o eroare în loc să refaci eșantionarea în tăcere.
|
||||
|
||||
Salvează feature extractor-ul cu checkpoint-ul instanțiindu-l în scriptul de conversie și apelând [`~FeatureExtractionMixin.save_pretrained`]. Nu crea sau edita manual fișierele de config de preprocesare.
|
||||
|
||||
> [!TIP]
|
||||
> Vezi [`Gemma4AudioFeatureExtractor`] ca referință.
|
||||
|
||||
## Înregistrarea claselor
|
||||
|
||||
Expune noile clase din `__init__.py`-ul pachetului modelului. Urmează pattern-ul de import lazy folosit de modelele vecine și protejează importurile cu aceleași dependențe opționale necesare clasei.
|
||||
|
||||
Mapează noua clasă la config-ul modelului pentru ca [`AutoFeatureExtractor`] să o poată încărca. Adaugă o intrare în `FEATURE_EXTRACTOR_MAPPING_NAMES` din `src/transformers/models/auto/feature_extraction_auto.py`, urmând pattern-ul intrărilor vecine. Apoi verifică dacă tipul de model apare acolo sub `FEATURE_EXTRACTOR_MAPPING_NAMES` pentru [`AutoFeatureExtractor`].
|
||||
|
||||
- `FEATURE_EXTRACTOR_MAPPING_NAMES` pentru [`AutoFeatureExtractor`]
|
||||
|
||||
## Testare
|
||||
|
||||
Adaugă teste pentru fiecare componentă de procesare audio în directorul de teste al modelului. Testele pentru feature extractor se află de obicei în `tests/models/<model_name>/test_feature_extraction_<model_name>.py`.
|
||||
|
||||
Pentru feature extractor-ele care moștenesc din [`SequenceFeatureExtractor`], moștenește din [`SequenceFeatureExtractionTestMixin`]. Mixin-ul acoperă comportamentul de salvare și încărcare, padding, truncare, conversia tensorilor și proprietățile comune ale feature extractor-ului. Furnizează un obiect tester cu `prepare_feat_extract_dict()` și `prepare_inputs_for_common()` pentru ca mixin-ul să poată instanția feature extractor-ul și construi input-uri audio dummy scurte.
|
||||
|
||||
```py
|
||||
from ...test_sequence_feature_extraction_common import SequenceFeatureExtractionTestMixin
|
||||
|
||||
class MyModelFeatureExtractionTest(SequenceFeatureExtractionTestMixin, unittest.TestCase):
|
||||
feature_extraction_class = MyModelFeatureExtractor
|
||||
|
||||
def setUp(self):
|
||||
self.feat_extract_tester = MyModelFeatureExtractionTester(self)
|
||||
```
|
||||
|
||||
Adaugă teste focalizate pentru comportamentul specific modelului pe care mixin-ul nu îl cunoaște. Pentru feature extractors audio, asta înseamnă de obicei verificarea formei feature-ului returnat de `__call__`, validarea că un `sampling_rate` incorect cauzează o eroare și verificarea oricărei normalizări personalizate sau calcul de features.
|
||||
|
||||
Dacă modelul are și un [`ProcessorMixin`] care dă wrap feature extractor-ului, adaugă `tests/models/<model_name>/test_processing_<model_name>.py` și moștenește din [`ProcessorTesterMixin`]. Setează `processor_class` și suprascrie metodele de clasă `_setup_<component>()` pentru componentele care nu pot fi construite fără argumente. Folosește `_setup_test_attributes()` ca să expui token-urile placeholder folosite de testele comune ale procesorului.
|
||||
|
||||
```py
|
||||
from ...test_processing_common import ProcessorTesterMixin
|
||||
|
||||
class MyModelProcessorTest(ProcessorTesterMixin, unittest.TestCase):
|
||||
processor_class = MyModelProcessor
|
||||
|
||||
@classmethod
|
||||
def _setup_feature_extractor(cls):
|
||||
return cls._get_component_class_from_processor("feature_extractor")(sampling_rate=16000)
|
||||
|
||||
@classmethod
|
||||
def _setup_test_attributes(cls, processor):
|
||||
cls.audio_token = getattr(processor, "audio_token", "")
|
||||
```
|
||||
|
||||
## Pașii următori
|
||||
|
||||
- Citește ghidul [Auto-generarea docstring-urilor](./auto_docstring) ca să auto-generezi docstring-uri consistente cu `@auto_docstring`.
|
||||
- Citește ghidul [Feature extractors] pentru comportamentul de preprocesare orientat către utilizator.
|
||||
651
docs/source/ro/add_new_model.md
Normal file
651
docs/source/ro/add_new_model.md
Normal file
@@ -0,0 +1,651 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Contribuția legacy la modele
|
||||
|
||||
> [!TIP]
|
||||
> Încearcă mai întâi să adaugi modele noi cu abordarea mai [modulară](./modular_transformers). Asta face contribuirea cu un model la Transformers semnificativ mai ușoară!
|
||||
|
||||
Multe din modelele din Transformers sunt contribuite de developeri și cercetători. Ca proiect open-source, suntem investiți în a da putere comunității să adauge independent mai multe modele.
|
||||
|
||||
Când adaugi un model la Transformers, vei învăța:
|
||||
|
||||
- mai multe despre cele mai bune practici open-source
|
||||
- despre arhitectura unui model
|
||||
- despre principiile de design ale Transformers
|
||||
- cum să testezi eficient modele mari
|
||||
- cum să folosești utilitare Python precum [Black](https://black.readthedocs.io/en/stable/) și [Ruff](https://docs.astral.sh/ruff/) ca să creezi cod curat și lizibil
|
||||
|
||||
Este un proces provocator, dar satisfăcător.
|
||||
|
||||
Acest ghid te va conduce prin adăugarea unui model BrandNewLlama PyTorch de exemplu în Transformers. Înainte să începi, e o idee bună să te familiarizezi cu librăria.
|
||||
|
||||
## Prezentare generală Transformers
|
||||
|
||||
Transformers este o librărie cu opinii proprii, cu propria filozofie și alegeri de design. Aceste alegeri ne ajută să scalăm și să menținem Transformers sustenabil.
|
||||
|
||||
> [!TIP]
|
||||
> Află mai multe despre principiile noastre de design în documentul [Philosophy].
|
||||
|
||||
Câteva din aceste alegeri de design sunt:
|
||||
|
||||
- compoziție > over-abstraction
|
||||
- codul duplicat nu e întotdeauna rău dacă îmbunătățește semnificativ lizibilitatea și accesibilitatea
|
||||
- fișierele de model sunt self-contained și tot codul necesar al modelului se găsește în fișierul `modeling_mymodel.py`
|
||||
|
||||
Aceste alegeri de design sunt importante *pentru toată lumea* care interacționează cu modelul. Este mai ușor de citit, înțeles și modificat.
|
||||
|
||||
Această secțiune descrie cum interacționează clasele de model și configurare și stilul de cod al Transformers.
|
||||
|
||||
### Model și configurare
|
||||
|
||||
Toate modelele Transformers moștenesc dintr-o clasă de bază [`PreTrainedModel`] și [`PreTrainedConfig`]. Configurarea este blueprint-ul modelului.
|
||||
|
||||
Nu există niciodată mai mult de două niveluri de abstractizare pentru niciun model, ca să menținem codul lizibil. Modelul de exemplu de aici, BrandNewLlama, moștenește din `BrandNewLlamaPreTrainedModel` și [`PreTrainedModel`]. Este important că un model nou depinde doar de [`PreTrainedModel`] ca să poată folosi metodele [`~PreTrainedModel.from_pretrained`] și [`~PreTrainedModel.save_pretrained`].
|
||||
|
||||
Alte funcții importante precum metoda forward sunt definite în fișierul `modeling.py`.
|
||||
|
||||
Head-urile specifice de model (de exemplu, clasificarea de secvențe sau modelarea limbajului) ar trebui să apeleze modelul de bază în forward pass, nu să moștenească din el, ca să menținem abstractizarea scăzută.
|
||||
|
||||
Modelele noi necesită o configurare, de exemplu `BrandNewLlamaConfig`, care este stocată ca atribut al [`PreTrainedModel`].
|
||||
|
||||
```py
|
||||
model = BrandNewLlamaModel.from_pretrained("username/brand_new_llama")
|
||||
model.config
|
||||
```
|
||||
|
||||
[`PreTrainedConfig`] furnizează metodele [`~PreTrainedConfig.from_pretrained`] și [`~PreTrainedConfig.save_pretrained`].
|
||||
|
||||
Când folosești [`PreTrainedModel.save_pretrained`], apelează automat [`PreTrainedConfig.save_pretrained`] ca atât modelul, cât și configurarea să fie salvate împreună.
|
||||
|
||||
Un model este salvat într-un fișier `model.safetensors` și o configurare este salvată într-un fișier `config.json`.
|
||||
|
||||
### Stilul codului
|
||||
|
||||
Transformers preferă cod curat și lizibil față de un stil mai abstractizat. Câteva din alegerile de stil includ:
|
||||
|
||||
- Codul ar trebui să fie accesibil utilizatorilor non-anglofoni. Alege nume de variabile descriptive și evită abrevierile. De exemplu, "activation" este preferată față de "act". Numele de variabile cu o singură literă sunt puternic descurajate, cu excepția unui index într-un for loop.
|
||||
|
||||
- Codul explicit este preferat — chiar dacă e mai lung — față de codul mai scurt.
|
||||
|
||||
- Evită subclasarea [nn.Sequential](https://pytorch.org/docs/stable/generated/torch.nn.Sequential.html). Subclasează în schimb [nn.Module](https://pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module) ca codul să poată fi debugged rapid cu print statements sau breakpoints.
|
||||
|
||||
- Semnăturile funcțiilor ar trebui să aibă adnotări de tip. Altfel, folosește nume bune de variabile ca să fie mai ușor de înțeles.
|
||||
|
||||
## Issue pentru adăugarea unui model nou
|
||||
|
||||
Deschide un issue [New model addition](https://github.com/huggingface/transformers/issues/new?assignees=&labels=New+model&template=new-model-addition.yml) ca să adaugi un model specific.
|
||||
|
||||
> [!TIP]
|
||||
> Filtrează după label-ul [New model](https://github.com/huggingface/transformers/labels/New%20model) pe GitHub ca să vizualizezi și să adaugi cereri de modele existente.
|
||||
|
||||
Acum este un moment bun să te familiarizezi cu BrandNewLlama. Este util să citești lucrarea de cercetare a modelului ca să înțelegi designul tehnic și implementarea. Nu trebuie neapărat să te îngrijorezi prea mult de detaliile teoretice. Concentrează-te pe cele practice. Folosește întrebările de mai jos ca să ghidezi lectura.
|
||||
|
||||
- Ce tip de model este BrandNewLlama? Este un model encoder, decoder sau encoder-decoder?
|
||||
- Pentru ce task-uri poate fi folosit BrandNewLlama?
|
||||
- Ce îl face pe BrandNewLlama diferit de alte modele?
|
||||
- Ce modele din Transformers sunt cele mai similare cu BrandNewLlama?
|
||||
- Ce tokenizer folosește BrandNewLlama?
|
||||
|
||||
Pe lângă a afla mai multe despre model, folosește sfaturile de mai jos ca să adaugi un model mai repede.
|
||||
|
||||
> [!TIP]
|
||||
> Fiecare contributor are un stil și workflow unic pentru adăugarea modelelor în Transformers. Ca exemplu, aruncă o privire la cum a fost adăugat [Gemma](https://github.com/huggingface/transformers/pull/29167).
|
||||
|
||||
- Nu reinventa roata! Ia-ți timp să explorezi modelele și tokenizatoarele existente ca să vezi ce poți copia și reutiliza. [Grep](https://www.gnu.org/software/grep/) și [ripgrep](https://github.com/BurntSushi/ripgrep) sunt instrumente excelente pentru asta.
|
||||
- Aceasta este mai degrabă o provocare de inginerie decât una de știință. Concentrează-te pe aspectele mai practice (configurarea unui mediu de debugging eficient, de exemplu) în loc de aspectele teoretice ale modelului.
|
||||
- Nu fi timid să ceri ajutor! Suntem aici să te sprijinim. 🤗
|
||||
|
||||
## Mediu de dev
|
||||
|
||||
Dă click pe butonul **Fork** din repository-ul [Transformers](https://github.com/huggingface/transformers) ca să creezi propria copie pe care să lucrezi. Clonează repository-ul pe discul local și adaugă repository-ul de bază ca remote.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/[your Github handle]/transformers.git
|
||||
cd transformers
|
||||
git remote add upstream https://github.com/huggingface/transformers.git
|
||||
```
|
||||
|
||||
Creează un mediu virtual și efectuează o [instalare editabilă](./installation#instalare-editabilă) a librăriei cu dependencies "dev" sau de development.
|
||||
|
||||
```bash
|
||||
python -m venv .env
|
||||
source .env/bin/activate
|
||||
pip install -e ".[dev]"
|
||||
```
|
||||
|
||||
Din cauza numărului de dependencies opționale pe măsură ce Transformers crește, această comandă poate eșua. În acest caz, instalează dependencies "quality". Asigură-te și că ai instalat un framework de deep learning.
|
||||
|
||||
```bash
|
||||
pip install -e ".[quality]"
|
||||
```
|
||||
|
||||
Întoarce-te la directorul părinte și clonează și instalează repository-ul original BrandNewLlama.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/org_that_created_brand_new_llama_org/brand_new_llama.git
|
||||
cd brand_new_bert
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
Întoarce-te la clona ta de Transformers ca să începi portarea BrandNewLlama.
|
||||
|
||||
```bash
|
||||
cd transformers
|
||||
```
|
||||
|
||||
Există două medii posibile de debugging pentru rularea modelului original: un notebook ([Google Colab](https://colab.research.google.com/notebooks/intro.ipynb) sau [Jupyter](https://jupyter.org/)) sau un script Python local.
|
||||
|
||||
> [!WARNING]
|
||||
> Nu recomandăm configurarea unui mediu GPU ca să rulezi modelul original, deoarece poate fi costisitor. Lucrează mai întâi într-un mediu CPU ca să verifici că modelul funcționează în Transformers. Odată ce funcționează, poți verifica pe un GPU.
|
||||
|
||||
Notebook-urile sunt excelente pentru executarea codului celulă cu celulă, ceea ce poate ajuta la separarea componentelor logice. Poate accelera și ciclurile de debugging deoarece rezultatele intermediare pot fi stocate. Poți partaja notebook-uri și când lucrezi cu alți contributori.
|
||||
|
||||
Dezavantajul este că dacă nu ești obișnuit cu ele, poate dura ceva timp să te acomodezi.
|
||||
|
||||
> [!TIP]
|
||||
> Dacă arhitectura modelului este identică cu un model existent, sari înainte la adăugarea unui [script de conversie](#conversia-checkpoint-urilor), deoarece poți reutiliza arhitectura modelului existent.
|
||||
|
||||
Rulează comanda de mai jos ca să pornești și completezi chestionarul cu informații de bază despre noul model. Această comandă pornește procesul generând automat cod de model pe care va trebui să îl adaptezi.
|
||||
|
||||
```bash
|
||||
transformers add-new-model-like
|
||||
```
|
||||
|
||||
## Crearea unui pull request
|
||||
|
||||
Înainte să începi adaptarea codului, creează un pull request ca să urmărești progresul și să primești feedback de la echipa Transformers. Intitulează pull request-ul **[WIP] Add BrandNewLlama** ca să fie clar că este o lucrare în desfășurare.
|
||||
|
||||
Creează un branch cu un nume descriptiv din branch-ul tău main.
|
||||
|
||||
```bash
|
||||
git checkout -b add_brand_new_bert
|
||||
```
|
||||
|
||||
Fă commit la cod, apoi fetch și rebase pe branch-ul main.
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit
|
||||
git fetch upstream
|
||||
git rebase upstream/main
|
||||
```
|
||||
|
||||
Fă push la orice modificări pe branch-ul tău și dă click pe **Compare & pull request** ca să deschizi un pull request pe GitHub. Deschide pull request-ul ca *draft* ca să indici că este o lucrare în desfășurare.
|
||||
|
||||
```bash
|
||||
git push -u origin a-descriptive-name-for-my-changes
|
||||
```
|
||||
|
||||
Include membrii relevanți ai echipei Hugging Face adăugând handle-urile lor GitHub în pull request pentru întrebări, feedback, comentarii și review-uri. Direcționează membrii echipei la părți specifice din cod dând click pe tab-ul **Files changed**, apoi dând click pe **+** la stânga numărului de linie ca să adaugi un comentariu. Când o întrebare sau problemă este rezolvată, dă click pe **Resolve** ca să indici că problema este rezolvată. Asta menține conversația organizată și curată.
|
||||
|
||||
Amintește-ți să faci periodic commit și push la munca ta și să actualizezi cu branch-ul main curent.
|
||||
|
||||
```bash
|
||||
git fetch upstream
|
||||
git merge upstream/main
|
||||
```
|
||||
|
||||
## Checkpoint-ul original
|
||||
|
||||
Ia-ți timp să lucrezi mai întâi la implementarea modelului original ca să înțelegi cum funcționează.
|
||||
|
||||
Aceasta poate fi dificilă dacă repository-ul modelului original nu are documentație sau dacă codebase-ul este complex. Dar ar trebui să folosești asta ca motivație pentru a implementa modelul în Transformers. Contribuția ta îl face mai accesibil și prietenos pentru toată lumea!
|
||||
|
||||
Orientează-te cu repository-ul original făcând următoarele.
|
||||
|
||||
- Localizează weights preantrenate.
|
||||
- Dă-ți seama cum să încarci weights preantrenate în model.
|
||||
- Dă-ți seama cum să rulezi tokenizer-ul independent de model.
|
||||
- Urmărește un forward pass ca să înțelegi ce clase și funcții sunt necesare. Acestea sunt probabil singurele clase și funcții pe care va trebui să le implementezi.
|
||||
- Localizează toate componentele importante (clasa model, subclasele modelului, layerul de self-attention etc.) ale modelului.
|
||||
- Dă-ți seama cum să dai debug modelul în repository-ul original. Adaugă print statements, folosește debuggers interactive precum [ipdb](https://github.com/gotcha/ipdb) sau un IDE eficient precum [PyCharm](https://www.jetbrains.com/pycharm/).
|
||||
|
||||
Ultimul punct este deosebit de important deoarece vei avea nevoie de o înțelegere profundă a ce se întâmplă în interiorul modelului original înainte de a-l reimplementa în Transformers. Nu ezita să deschizi issues și pull request-uri în repository-ul original dacă întâmpini probleme.
|
||||
|
||||
Un prim pas bun este să încarci un checkpoint preantrenat *mic* și să încerci să reproduci un singur forward pass cu un vector de exemplu de întregi ca inputuri. De exemplu, în pseudocod, ar putea arăta astfel:
|
||||
|
||||
```py
|
||||
model = BrandNewLlamaModel.load_pretrained_checkpoint("/path/to/checkpoint/")
|
||||
input_ids = [0, 4, 5, 2, 3, 7, 9] # vector de input ids
|
||||
original_output = model.generate(input_ids)
|
||||
```
|
||||
|
||||
### Debugging
|
||||
|
||||
Dacă întâmpini probleme, va trebui să alegi una din următoarele strategii de debugging în funcție de codebase-ul modelului original.
|
||||
|
||||
<hfoptions id="debug-strategy">
|
||||
<hfoption id="sub-components">
|
||||
|
||||
Această strategie se bazează pe descompunerea modelului original în sub-componente mai mici, cum ar fi atunci când codul poate fi rulat ușor în modul eager. Deși mai dificilă, există câteva avantaje ale acestei abordări.
|
||||
|
||||
1. Este mai ușor mai târziu să compari modelul original cu implementarea ta. Poți verifica automat că fiecare componentă individuală corespunde componentei corespunzătoare din implementarea Transformers. Asta e mai bine decât să te bazezi pe o comparație vizuală bazată pe print statements.
|
||||
2. Este mai ușor să portezi componente individuale în loc de întregul model.
|
||||
3. Este mai ușor să înțelegi cum funcționează un model descompunându-l în părți mai mici.
|
||||
4. Este mai ușor să previi regresiile la o etapă ulterioară când modifici codul, datorită testelor componentă cu componentă.
|
||||
|
||||
> [!TIP]
|
||||
> Consultă [integration checks](https://gist.github.com/LysandreJik/db4c948f6b4483960de5cbac598ad4ed) ELECTRA pentru un exemplu bun de cum să descompui un model în componente mai mici.
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="model and tokenizer">
|
||||
|
||||
Această strategie este viabilă când codebase-ul original este prea complex, permite doar rularea componentelor intermediare în modul compilat sau dacă este prea consumatoare de timp (poate chiar imposibil) să separi modelul în sub-componente mai mici.
|
||||
|
||||
De exemplu, implementarea MeshTensorFlow a lui [T5](https://github.com/tensorflow/mesh/tree/master/mesh_tensorflow) este prea complexă și nu oferă o modalitate simplă de a descompune modelul în sub-componentele sale. În această situație, va trebui să te bazezi pe verificarea print statements.
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
Oricare strategie alegi, este recomandat să dai debug mai întâi pentru layers inițiale și după pentru layers finale. Recuperează ieșirea, fie cu print statements fie cu funcții de sub-componentă, a layers următoare în această ordine.
|
||||
|
||||
1. input ids pasați modelului
|
||||
2. word embeddings
|
||||
3. inputul primului layer Transformer
|
||||
4. ieșirea primului layer Transformer
|
||||
5. ieșirea layers Transformer n-1 următoare
|
||||
6. ieșirea întregului model
|
||||
|
||||
Input ids ar trebui să fie doar un array de întregi precum `input_ids = [0, 4, 4, 3, 2, 4, 1, 7, 19]`.
|
||||
|
||||
Ieșirile layers-urilor constau adesea din array-uri float multidimensionale.
|
||||
|
||||
```py
|
||||
[[
|
||||
[-0.1465, -0.6501, 0.1993, ..., 0.1451, 0.3430, 0.6024],
|
||||
[-0.4417, -0.5920, 0.3450, ..., -0.3062, 0.6182, 0.7132],
|
||||
[-0.5009, -0.7122, 0.4548, ..., -0.3662, 0.6091, 0.7648],
|
||||
...,
|
||||
[-0.5613, -0.6332, 0.4324, ..., -0.3792, 0.7372, 0.9288],
|
||||
[-0.5416, -0.6345, 0.4180, ..., -0.3564, 0.6992, 0.9191],
|
||||
[-0.5334, -0.6403, 0.4271, ..., -0.3339, 0.6533, 0.8694]]],
|
||||
```
|
||||
|
||||
Fiecare ieșire de model Transformers ar trebui să aibă o precizie sau toleranță de eroare de *1e-3*. Asta compensează orice diferențe de ieșire care apar din folosirea unui framework de librărie diferit. Compară ieșirile intermediare ale modelului original cu implementarea Transformers ca să te asiguri că sunt aproape identice. A avea un mediu de debugging *eficient* este crucial pentru acest pas.
|
||||
|
||||
Iată câteva sfaturi pentru un mediu de debugging eficient.
|
||||
|
||||
- Pentru a da debug rezultatelor intermediare, depinde de framework-ul de machine learning pe care îl folosește repository-ul modelului original. Pentru PyTorch, ar trebui să scrii un script care să descompună modelul original în sub-componente mai mici ca să recuperezi valorile intermediare.
|
||||
|
||||
- Este mai rapid să dai debug cu un checkpoint preantrenat mai mic față de un checkpoint mai mare unde forward pass-ul durează mai mult de 10 secunde. Dacă sunt disponibile doar checkpoint-uri mari, creează un model dummy cu weights inițializate aleatoriu și salvează acele weights ca să le compari cu implementarea Transformers.
|
||||
|
||||
- Găsește cea mai ușoară modalitate de a apela forward pass-ul modelului. Ideal, această funcție (poate fi numită `predict`, `evaluate`, `forward` sau `__call__`) ar trebui să apeleze forward pass-ul doar *o singură dată*. Este mai dificil să dai debug unei funcții care apelează forward pass-ul de mai multe ori.
|
||||
|
||||
- Separă tokenizarea de forward pass. Localizează unde un input string este schimbat în input ids în forward pass și pornește de aici. Poate fi nevoie să creezi un script mic sau să modifici codul original ca să introduci direct input ids în loc de un input string.
|
||||
|
||||
- Asigură-te că modelul *nu* este în modul de antrenare. Asta poate produce ieșiri aleatorii din cauza mai multor layers de dropout dintr-un model. Forward pass-ul din mediul tău de debugging ar trebui să fie *determinist* ca layers-urile de dropout să nu fie folosite.
|
||||
|
||||
Odată ce poți rula checkpoint-ul original, ești gata să începi adaptarea codului de model pentru Transformers.
|
||||
|
||||
## Adaptarea codului de model
|
||||
|
||||
Comanda `transformers add-new-model-like` ar trebui să fi generat un fișier de model și de configurare.
|
||||
|
||||
- `src/transformers/models/brand_new_llama/modeling_brand_new_llama.py`
|
||||
- `src/transformers/models/brand_new_llama/configuration_brand_new_llama.py`
|
||||
|
||||
Codul generat automat din fișierul `modeling.py` are aceeași arhitectură ca Llama dacă ai răspuns că este un model decoder-only sau va avea aceeași arhitectură ca BART dacă ai răspuns că este un model encoder-decoder. Codul generat este doar un punct de plecare. Bazat pe cercetarea ta despre noul model, va trebui să implementezi acele modificări specifice adaptând codul generat. Asta poate implica modificări ale layerului de self-attention, ordinea layerului de normalizare și altele.
|
||||
|
||||
### Inițializarea modelului
|
||||
|
||||
La acest punct, codul tău nu trebuie să fie curat sau chiar complet corect. Este mai eficient să creezi rapid un prim draft și să îl îmbunătățești iterativ. Cel mai important lucru este că modelul tău poate fi instanțiat din Transformers. Comanda de mai jos creează un model din configurare cu weights aleatorii, verificând că metoda `__init__` funcționează.
|
||||
|
||||
```py
|
||||
from transformers import BrandNewLlama, BrandNewLlamaConfig
|
||||
model = BrandNewLlama(BrandNewLlamaConfig())
|
||||
```
|
||||
|
||||
Inițializarea aleatorie are loc în metoda `_init_weights` a `BrandNewLlamaPreTrainedModel`. Toate modulele leaf sunt inițializate în funcție de variabilele de configurare.
|
||||
|
||||
```py
|
||||
def _init_weights(self, module):
|
||||
"""Initialize the weights"""
|
||||
if isinstance(module, nn.Linear):
|
||||
module.weight.normal_(mean=0.0, std=self.config.initializer_range)
|
||||
if module.bias is not None:
|
||||
module.bias.zero_()
|
||||
elif isinstance(module, nn.Embedding):
|
||||
module.weight.normal_(mean=0.0, std=self.config.initializer_range)
|
||||
if module.padding_idx is not None:
|
||||
module.weight.data[module.padding_idx].zero_()
|
||||
elif isinstance(module, nn.LayerNorm):
|
||||
module.bias.zero_()
|
||||
module.weight.fill_(1.0)
|
||||
```
|
||||
|
||||
Schema de inițializare poate arăta diferit dacă trebuie s-o adaptezi la modelul tău. De exemplu, [`Wav2Vec2ForPreTraining`] inițializează [nn.Linear](https://pytorch.org/docs/stable/generated/torch.nn.Linear.html) în ultimele sale două layers liniare.
|
||||
|
||||
Flag-ul `_is_hf_initialized` se asigură că submodulul este inițializat doar o singură dată. Setarea `module.project_q` și `module.project_hid` la `True` asigură că inițializarea personalizată nu este suprascrisă mai târziu. Funcția `_init_weights` nu va fi aplicată la aceste module.
|
||||
|
||||
```py
|
||||
def _init_weights(self, module):
|
||||
"""Initialize the weights"""
|
||||
if isinstance(module, Wav2Vec2ForPreTraining):
|
||||
module.project_hid.reset_parameters()
|
||||
module.project_q.reset_parameters()
|
||||
module.project_hid._is_hf_initialized = True
|
||||
module.project_q._is_hf_initialized = True
|
||||
elif isinstance(module, nn.Linear):
|
||||
module.weight.normal_(mean=0.0, std=self.config.initializer_range)
|
||||
if module.bias is not None:
|
||||
module.bias.zero_()
|
||||
```
|
||||
|
||||
### Conversia checkpoint-urilor la Transformers
|
||||
|
||||
Checkpoint-ul original trebuie convertit într-un checkpoint compatibil cu Transformers.
|
||||
|
||||
> [!TIP]
|
||||
> Încearcă să cauți un script de conversie existent pe care să îl copiezi, adaptezi și reutilizezi pentru modelul tău!
|
||||
>
|
||||
> - Dacă portezi un model din TensorFlow la PyTorch, un bun punct de plecare poate fi [scriptul de conversie](https://github.com/huggingface/transformers/blob/7acfa95afb8194f8f9c1f4d2c6028224dbed35a2/src/transformers/models/bert/modeling_bert.py#L91) BERT.
|
||||
> - Dacă portezi un model din PyTorch la PyTorch, un bun punct de plecare poate fi [scriptul de conversie](https://github.com/huggingface/transformers/blob/main/src/transformers/models/bart/convert_bart_original_pytorch_checkpoint_to_pytorch.py) BART.
|
||||
|
||||
Asigură-te că **toate** weights necesare sunt inițializate și printează toate weights de checkpoint care nu au fost folosite pentru inițializare pentru a te asigura că modelul a fost convertit corect.
|
||||
|
||||
Poți întâlni instrucțiuni de formă greșită sau atribuiri de nume greșite în timpul conversiei. Asta se datorează cel mai probabil parametrilor incorecți în `BrandNewLlamaConfig`, arhitecturii greșite, unui bug în metoda `init` a implementării tale sau trebuie să transpoziționezi unul dintre weights checkpoint-ului.
|
||||
|
||||
Continuă să iterezi pe secțiunea [Adaptarea codului de model](#adaptarea-codului-de-model) până când toate weights de checkpoint se încarcă corect. Odată ce poți încărca un checkpoint în modelul tău, salvează-l într-un folder. Acesta ar trebui să conțină un fișier `model.safetensors` și un fișier `config.json`.
|
||||
|
||||
```py
|
||||
model.save_pretrained("/path/to/converted/checkpoint/folder")
|
||||
```
|
||||
|
||||
Ca să ajuți cu conversia, secțiunea următoare descrie pe scurt cum PyTorch stochează și definește weights și numele layer-urilor.
|
||||
|
||||
#### Weights și numele layer-urilor PyTorch
|
||||
|
||||
Este util să creezi un model PyTorch de bază ca să înțelegi cum sunt definite numele layers-urilor și cum sunt inițializate weights.
|
||||
|
||||
```py
|
||||
from torch import nn
|
||||
|
||||
class SimpleModel(nn.Module):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.dense = nn.Linear(10, 10)
|
||||
self.intermediate = nn.Linear(10, 10)
|
||||
self.layer_norm = nn.LayerNorm(10)
|
||||
```
|
||||
|
||||
Numele layers-urilor PyTorch sunt definite de numele atributului de clasă al layerului (`dense`, `intermediate`, `layer_norm`). Creează o instanță a `SimpleModel` ca să umpli toate layers-urile cu weights aleatorii.
|
||||
|
||||
```py
|
||||
model = SimpleModel()
|
||||
print(model)
|
||||
SimpleModel(
|
||||
(dense): Linear(in_features=10, out_features=10, bias=True)
|
||||
(intermediate): Linear(in_features=10, out_features=10, bias=True)
|
||||
(layer_norm): LayerNorm((10,), eps=1e-05, elementwise_affine=True)
|
||||
)
|
||||
```
|
||||
|
||||
Valorile weights unui layer specific sunt inițializate aleatoriu.
|
||||
|
||||
```py
|
||||
print(model.dense.weight.data)
|
||||
tensor([[-0.0818, 0.2207, -0.0749, -0.0030, 0.0045, -0.1569, -0.1598, 0.0212,
|
||||
-0.2077, 0.2157],
|
||||
...
|
||||
[-0.1492, -0.1616, 0.1057, 0.1950, -0.2807, -0.2710, -0.1586, 0.0739,
|
||||
0.2220, 0.2358]]).
|
||||
```
|
||||
|
||||
În scriptul de conversie, weights aleatorii ar trebui înlocuite cu weights exacte din layer-ul corespunzător în checkpoint-ul original.
|
||||
|
||||
```py
|
||||
# recuperează weights layer-ului potrivit cu algoritm recursiv
|
||||
layer_name = "dense"
|
||||
pretrained_weight = array_of_dense_layer
|
||||
|
||||
model_pointer = getattr(model, "dense")
|
||||
model_pointer.weight.data = torch.from_numpy(pretrained_weight)
|
||||
```
|
||||
|
||||
Verifică că weights inițializate aleatoriu și weights corespunzătoare din checkpoint-ul preantrenat au **forma** și **numele** identice. Adaugă instrucțiuni assert pentru formă și printează numele de weights din checkpoint.
|
||||
|
||||
```py
|
||||
assert (
|
||||
model_pointer.weight.shape == pretrained_weight.shape
|
||||
), f"Pointer shape of random weight {model_pointer.shape} and array shape of checkpoint weight {pretrained_weight.shape} mismatched"
|
||||
|
||||
logger.info(f"Initialize PyTorch weight {layer_name} from {pretrained_weight.name}")
|
||||
```
|
||||
|
||||
Când forma sau numele nu corespund, poate că ai atribuit un weight de checkpoint greșit unui layer inițializat aleatoriu. O formă greșită poate fi cauzată de parametrii `BrandNewLlama` ce nu corespund exact cu parametrii modelului original. Ar putea fi și că implementarea layerului PyTorch necesită ca weights să fie transpoziționate mai întâi.
|
||||
|
||||
### Implementarea forward pass-ului
|
||||
|
||||
Forward pass-ul ar trebui implementat următor dacă modelul se încarcă corect. Ia câteva inputuri și returnează ieșirea modelului.
|
||||
|
||||
```py
|
||||
model = BrandNewLlamaModel.from_pretrained("/path/to/converted/checkpoint/folder")
|
||||
input_ids = [0, 4, 4, 3, 2, 4, 1, 7, 19]
|
||||
output = model.generate(input_ids).last_hidden_states
|
||||
```
|
||||
|
||||
Nu te descuraja dacă forward pass-ul tău nu este identic cu ieșirea modelului original sau dacă returnează o eroare. Verifică că forward pass-ul nu aruncă erori. Asta se datorează adesea că dimensiunile sunt greșite sau că se folosește tipul de date greșit ([torch.long](https://pytorch.org/docs/stable/generated/torch.Tensor.long.html) în loc de [torch.float32](https://pytorch.org/docs/stable/tensors.html)).
|
||||
|
||||
Ieșirea ta ar trebui să aibă o precizie de *1e-3*. Asigură-te că formele de ieșire și valorile de ieșire sunt identice. Motive comune pentru care ieșirile nu sunt identice includ:
|
||||
|
||||
- Câteva layers nu au fost adăugate (un layer de activare sau o conexiune reziduală).
|
||||
- Matricea de word embedding nu este legată.
|
||||
- Se folosesc embeddings poziționale greșite deoarece implementarea originală include un offset.
|
||||
- Dropout este aplicat în timpul forward pass-ului. Remediază această eroare asigurându-te că `model.training` este `False` și pasând `self.training` la [torch.nn.functional.dropout](https://pytorch.org/docs/stable/nn.functional.html?highlight=dropout#torch.nn.functional.dropout).
|
||||
|
||||
Compară forward pass-ul modelului original cu implementarea ta ca să verifici dacă există diferențe. Ideal, dai debug și printezi ieșirile intermediare ale ambelor implementări ale forward pass-ului ca să identifici unde implementarea originală diferă de a ta.
|
||||
|
||||
1. Asigură-te că `input_ids` hardcoded în ambele implementări sunt identice.
|
||||
2. Verifică că ieșirile primei transformări ale `input_ids` (de obicei word embeddings) sunt identice și lucrează prin layers până la ultimul.
|
||||
|
||||
Orice diferență între cele două implementări ar trebui să pointeze la bug-ul din implementarea ta.
|
||||
|
||||
Una din cele mai bune strategii este să adaugi multe print statements în aceleași poziții în ambele implementări, și apoi să le elimini succesiv când produc valori identice pentru ieșirile intermediare.
|
||||
|
||||
Când ambele implementări produc aceeași ieșire, verifică că ieșirile sunt în cadrul unei precizii de *1e-3*.
|
||||
|
||||
```py
|
||||
torch.allclose(original_output, output, atol=1e-3)
|
||||
```
|
||||
|
||||
Acesta este de obicei cel mai dificil pas al procesului. Felicitări dacă ai ajuns până aici!
|
||||
|
||||
Și dacă ești blocat sau te lupți cu acest pas, nu ezita să ceri ajutor pe pull request-ul tău.
|
||||
|
||||
### Adăugarea testelor de model
|
||||
|
||||
Deși modelul funcționează, mai trebuie să adaugi teste ca să te asiguri că este compatibil cu Transformers. Testele sunt importante pentru că ajută utilizatorii să înțeleagă munca ta uitându-se la teste specifice și pentru că previn spargerea modelului în viitor dacă se fac modificări.
|
||||
|
||||
[Cookiecutter](https://cookiecutter.readthedocs.io/en/stable/) ar trebui să fi adăugat un fișier de test pentru modelul tău. Rulează fișierul de test de mai jos ca să te asiguri că toate testele comune trec.
|
||||
|
||||
```bash
|
||||
pytest tests/models/brand_new_llama/test_modeling_brand_new_llama.py
|
||||
```
|
||||
|
||||
Testele de integrare ar trebui adăugate mai întâi pentru că servesc același scop ca scripturile de debugging pe care le-ai folosit mai devreme ca să implementezi noul model în Transformers. Un șablon al acelor teste de model, `BrandNewLlamaModelIntegrationTests`, a fost adăugat de Cookiecutter și ar trebui completat. Ca să te asiguri că trece, rulează comanda de mai jos.
|
||||
|
||||
<hfoptions id="integration-test">
|
||||
<hfoption id="macOS">
|
||||
|
||||
```bash
|
||||
RUN_SLOW=1 pytest -sv tests/models/brand_new_llama/test_modeling_brand_new_llama.py::BrandNewLlamaModelIntegrationTests
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="Windows">
|
||||
|
||||
```bash
|
||||
SET RUN_SLOW=1 pytest -sv tests/models/brand_new_llama/test_modeling_brand_new_llama.py::BrandNewLlamaModelIntegrationTests
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
Toate features-urile unice ale lui BrandNewLlama ar trebui testate într-un test separat sub `BrandNewLlamaModelTester/BrandNewLlamaModelTest`. Acest test este adesea trecut cu vederea, dar este extrem de important pentru că:
|
||||
|
||||
- ajută la transferul cunoștințelor pe care le-ai dobândit în timpul procesului către comunitate, arătând cum funcționează features-urile noi ale modelului
|
||||
- contributorii viitori pot testa rapid modificările la model rulând aceste teste speciale
|
||||
|
||||
## Implementarea tokenizer-ului
|
||||
|
||||
> [!TIP]
|
||||
> Recomandăm adăugarea unui tokenizer rapid ([`PreTrainedTokenizerFast`]) ca să oferi utilizatorilor cele mai bune performanțe. Nu ezita să dai tag lui [@ArthurZucker](https://github.com/ArthurZucker) sau [@itazap](https://github.com/itazap) în PR-ul tău pentru ajutor cu adăugarea [`PreTrainedTokenizerFast`].
|
||||
|
||||
Cu modelul rezolvat, e timpul să te concentrezi pe tokenizer. Tokenizer-ul ar trebui să fie identic sau foarte similar cu un tokenizer existent în Transformers.
|
||||
|
||||
Găsește și încarcă fișierul original de tokenizer în implementarea ta. Creează un script în repository-ul original care primește un string și returnează `input_ids`. Pseudocodul ar trebui să arate similar cu codul de mai jos.
|
||||
|
||||
```py
|
||||
input_str = "This is a long example input string containing special characters .$?-, numbers 2872 234 12 and words."
|
||||
model = BrandNewLlamaModel.load_pretrained_checkpoint("/path/to/checkpoint/")
|
||||
input_ids = model.tokenize(input_str)
|
||||
```
|
||||
|
||||
Poate fi nevoie să cauți în repository-ul original ca să găsești funcția corectă de tokenizer sau să modifici tokenizer-ul existent din clona ta a repository-ului original ca să returneze doar `input_ids`. Scriptul pentru tokenizer-ul tău ar trebui să arate similar cu cel de mai jos.
|
||||
|
||||
```py
|
||||
from transformers import BrandNewLlamaTokenizer
|
||||
|
||||
input_str = "This is a long example input string containing special characters .$?-, numbers 2872 234 12 and words."
|
||||
tokenizer = BrandNewLlamaTokenizer.from_pretrained("/path/to/tokenizer/folder/")
|
||||
input_ids = tokenizer(input_str).input_ids
|
||||
```
|
||||
|
||||
Când ambele implementări au aceleași `input_ids`, adaugă un fișier de test pentru tokenizer. Acesta este analog cu fișierele de test de modelare. Fișierele de test pentru tokenizer ar trebui să conțină câteva teste de integrare hardcoded.
|
||||
|
||||
## Implementarea procesorului de imagini
|
||||
|
||||
> [!TIP]
|
||||
> Procesoarele de imagini folosesc acum o arhitectură bazată pe backend. Backend-ul implicit este [`TorchvisionBackend`], care folosește librăria [torchvision](https://pytorch.org/vision/stable/index.html) și poate efectua procesarea imaginilor pe GPU. Un backend alternativ PIL/NumPy ([`PilBackend`]) este și el furnizat. Ambele backend-uri sunt importate din `image_processing_backends`. Nu ezita să dai tag lui [@yonigozlan](https://github.com/yonigozlan) pentru ajutor.
|
||||
|
||||
Deși acest exemplu nu include un procesor de imagini, poate fi nevoie să implementezi unul dacă modelul tău necesită inputuri de imagini. Procesorul de imagini este responsabil de convertirea imaginilor într-un format potrivit pentru modelul tău. Înainte de a implementa unul nou, verifică dacă un procesor de imagini existent din librăria Transformers poate fi reutilizat, deoarece multe modele partajează tehnici similare de procesare a imaginilor. Reține că poți folosi și [modular](./modular_transformers) pentru procesoarele de imagini ca să reutilizezi componente existente.
|
||||
|
||||
Dacă ai nevoie să implementezi un procesor de imagini nou, fiecare model are două fișiere de procesor:
|
||||
|
||||
- `image_processing_<model>.py`: procesorul **implicit** cu backend torchvision (`<Model>ImageProcessor`), moștenind din [`TorchvisionBackend`]. Acesta înlocuiește vechiul procesor "fast".
|
||||
- `image_processing_pil_<model>.py`: procesorul alternativ PIL/NumPy (`<Model>ImageProcessorPil`), moștenind din [`PilBackend`]. Acesta înlocuiește vechiul procesor "slow".
|
||||
|
||||
Fișierul cu backend torchvision definește și orice clasă de kwargs personalizate pe care fișierul PIL o importă. Ambele fișiere folosesc decoratorul `@auto_docstring` — nu adăuga docstring-uri de clasă manuale. Consultă [IMAGE_PROCESSOR_REFACTORING_GUIDE.md](https://github.com/huggingface/transformers/blob/main/IMAGE_PROCESSOR_REFACTORING_GUIDE.md) pentru un walkthrough pas cu pas și exemple complete.
|
||||
|
||||
Adaugă teste pentru procesorul de imagini în `tests/models/your_model_name/test_image_processing_your_model_name.py`. Aceste teste ar trebui să fie similare cu cele pentru alte procesoare de imagini și să verifice că procesorul de imagini gestionează corect inputurile de imagini. Dacă procesorul tău de imagini include features sau metode de procesare unice, asigură-te că adaugi teste specifice pentru acelea.
|
||||
|
||||
## Implementarea procesorului
|
||||
|
||||
Dacă modelul tău acceptă modalități multiple, precum text și imagini, trebuie să adaugi un procesor. Procesorul centralizează preprocesarea diferitelor modalități înainte de a le pasa modelului.
|
||||
|
||||
Procesorul ar trebui să apeleze procesoarele specifice modalității corespunzătoare în interiorul funcției `__call__` ca să gestioneze corect fiecare tip de input. Asigură-te că verifici procesoarele existente din librărie ca să înțelegi structura așteptată. Transformers folosește convenția de mai jos în semnătura funcției `__call__`.
|
||||
|
||||
```python
|
||||
def __call__(
|
||||
self,
|
||||
images: ImageInput = None,
|
||||
text: Union[TextInput, PreTokenizedInput, list[TextInput], list[PreTokenizedInput]] = None,
|
||||
audio=None,
|
||||
videos=None,
|
||||
**kwargs: Unpack[YourModelProcessorKwargs],
|
||||
) -> BatchFeature:
|
||||
...
|
||||
```
|
||||
|
||||
`YourModelProcessorKwargs` este un `TypedDict` care include toate argumentele tipice de procesare și orice argumente suplimentare pe care un procesor specific le poate necesita.
|
||||
|
||||
Adaugă teste pentru procesor în `tests/models/your_model_name/test_processor_your_model_name.py`. Aceste teste ar trebui să fie similare cu cele pentru alte procesoare și să verifice că procesorul gestionează corect diferitele modalități.
|
||||
|
||||
## Teste de integrare
|
||||
|
||||
Acum că ai un model și tokenizer, adaugă teste de integrare end-to-end pentru model și tokenizer în `tests/models/brand_new_llama/test_modeling_brand_new_llama.py`.
|
||||
|
||||
Testul ar trebui să furnizeze un exemplu semnificativ text-la-text ca să arate că modelul funcționează conform așteptărilor. De exemplu, poți include o pereche de traducere sursă-țintă, o pereche articol-rezumat sau o pereche întrebare-răspuns.
|
||||
|
||||
Dacă checkpoint-ul nu a fost fine-tuned pe un task downstream, atunci testele de model sunt suficiente.
|
||||
|
||||
În final, încearcă să te asiguri că testele pot rula pe un GPU adăugând instrucțiuni `.to(self.device)` la tensorii interni ai modelului. Dacă nu ai acces la un GPU, ne putem ocupa de asta.
|
||||
|
||||
## Adăugarea documentației
|
||||
|
||||
Modelul tău este util doar dacă utilizatorii știu cum să îl folosească. De aceea este important să adaugi documentație și docstring-uri. Cookiecutter a adăugat un fișier șablon, `docs/source/model_doc/brand_new_llama.md`, pe care îl poți completa cu informații despre modelul tău.
|
||||
|
||||
Aceasta este de obicei prima interacțiune a unui utilizator cu un model, deci documentația ar trebui să fie clară și concisă. Este adesea foarte util să adaugi exemple de cum ar trebui folosit modelul.
|
||||
|
||||
Asigură-te că docstring-urile sunt adăugate la `src/transformers/models/brand_new_llama/modeling_brand_new_llama.py` și includ toate inputurile și ieșirile necesare. Consultă [ghidul](https://github.com/huggingface/transformers/tree/main/docs#writing-documentation---specification) nostru de scriere a documentației și docstring-urilor.
|
||||
|
||||
## Refactorizare
|
||||
|
||||
E timpul să faci ordine și să te asiguri că stilul codului este consistent cu restul librăriei. Rulează comanda de mai jos ca să remediezi automat stilurile incorecte.
|
||||
|
||||
```bash
|
||||
make style
|
||||
```
|
||||
|
||||
Ca să verifici că stilul codului trece verificările de calitate, rulează comanda de mai jos.
|
||||
|
||||
```bash
|
||||
make check-repo
|
||||
```
|
||||
|
||||
Pot exista alte teste sau verificări eșuate (docstring lipsă sau denumire incorectă) pe pull request-ul tău din cauza testelor stricte de design ale Transformers. Putem ajuta cu aceste probleme dacă ești blocat.
|
||||
|
||||
După ce te-ai asigurat că codul rulează corect, poate vrei să îl refactorizezi ca să fie mai lizibil sau mai curat.
|
||||
|
||||
## Încărcarea pe Hub
|
||||
|
||||
Convertește și încarcă toate checkpoint-urile pe [Hub](https://hf.co/models). Adaugă un model card pentru a oferi mai multă transparență și context despre model. Model card-ul ar trebui să evidențieze caracteristici specifice ale unui checkpoint, cum a fost antrenat modelul și exemple de cod pentru cum să îl folosești.
|
||||
|
||||
> [!TIP]
|
||||
> În multe cazuri, adăugarea unui notebook interactiv pe care utilizatorii îl pot rula este o modalitate excelentă de a arăta cum să folosești modelul pentru inferență sau să îl fine-tunezi pe un task downstream. Deși nu este obligatoriu, includerea unui notebook poate duce la o adoptare mai mare a modelului.
|
||||
|
||||
Ar trebui să consulți și echipa Transformers ca să decideți un nume potrivit pentru model și să obții drepturile de acces necesare pentru a încărca modelul.
|
||||
|
||||
Folosește metoda [`~PreTrainedModel.push_to_hub`] ca să încarci modelul.
|
||||
|
||||
```py
|
||||
brand_new_bert.push_to_hub("brand_new_llama")
|
||||
```
|
||||
|
||||
Consultă ghidul [Partajare](./model_sharing) pentru mai multe informații despre încărcarea modelelor pe Hub.
|
||||
|
||||
## Integrarea PR-ului
|
||||
|
||||
Ești în sfârșit gata să integrezi pull request-ul și să adaugi oficial modelul în Transformers! Asigură-te că toate testele trec și că toate comentariile și feedback-ul au fost adresate.
|
||||
|
||||
Felicitări pentru adăugarea unui nou model în Transformers! 🥳
|
||||
|
||||
Aceasta este o contribuție foarte semnificativă. Munca ta face Transformers mai accesibil pentru developeri și cercetători din întreaga lume. Ar trebui să fii mândru de contribuția ta și să îți împartășești realizarea cu comunitatea!
|
||||
|
||||
## Cronologia adăugării de modele
|
||||
|
||||
Există patru cronologii pentru adăugările de modele în funcție de contributorul modelului și cererea comunității pentru o arhitectură.
|
||||
|
||||
- **integrare day-0**: Dacă plănuiești să ai un release Transformers-first, aceasta este o opțiune excelentă deoarece putem asigura că documentația este clară și putem optimiza modelul tău cât mai mult (quantization, FlashAttention, KV-cache etc.). Putem și să te ajutăm să adaugi modelul, să oferim review-uri timpurii și să ne asigurăm că funcționează conform așteptărilor.
|
||||
|
||||
Contactează transformers@huggingface.co cu câteva zile (preferabil săptămâni) în avans, mai ales dacă o arhitectură este deosebit de nouă, ca să asiguri integrarea modelului. Vom lucra împreună pe un fork privat al Transformers până când checkpoint-ul și release-ul tău sunt gata.
|
||||
|
||||
- **integrare în aceeași săptămână**: Modelele cu cereri/cerere semnificativă sunt de obicei adăugate în aceeași săptămână dacă autorul modelului nu ia legătura.
|
||||
|
||||
Folosește [issue tracker-ul](https://github.com/huggingface/transformers/issues/new?assignees=&labels=New+model&projects=&template=new-model-addition.yml) ca să soliciți un model specific de adăugat. Cu cât mai multă activitate pe issue, cu atât mai rapid și mai probabil îl vom integra.
|
||||
|
||||
- **integrare post-release**: Modelele fără cereri/cerere populară sau dacă nu avem banda necesară să le integrăm sunt adăugate post-release.
|
||||
|
||||
Aceasta este o bună oportunitate dacă ești interesat să contribui un model la Transformers. Aruncă o privire la issues deschise cu tag-ul ["New model"](https://github.com/huggingface/transformers/issues?q=is%3Aopen+is%3Aissue+label%3A%22New+model%22). Nu ezita să încerci mai întâi modelele cele mai solicitate ca să multiplici impactul contribuției tale. Vom fi acolo să te ajutăm la fiecare pas!
|
||||
|
||||
- **Release Hub-first**: Feature-ul [remote-code](./models#modele-personalizate) al Transformers permite proiectelor bazate pe Transformers să fie partajate direct pe Hub. Aceasta este o bună opțiune dacă nu ai banda necesară să adaugi un model direct în Transformers.
|
||||
|
||||
Dacă un model devine foarte popular, atunci este foarte probabil că îl vom integra noi înșine în Transformers ca să îi asigurăm un suport mai bun (documentație, întreținere, optimizare etc.). Un release Hub-first este cel mai puțin restrictiv mod de a adăuga un model.
|
||||
|
||||
## Vezi și
|
||||
|
||||
- [Regulile de structură a modelului](./modeling_rules) — reguli statice aplicate pe toate fișierele `modeling_*.py` și `configuration_*.py`. Rulează `make typing` ca să le verifici înainte de a deschide un PR.
|
||||
- [Verificările pentru pull request](./pr_checks) — referință completă pentru ce verificări CI rulează pe PR-ul tău și cum să le treci.
|
||||
224
docs/source/ro/add_new_pipeline.md
Normal file
224
docs/source/ro/add_new_pipeline.md
Normal file
@@ -0,0 +1,224 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Adăugarea unui nou pipeline
|
||||
|
||||
Fă-ți propriul [`Pipeline`] creând o subclasă a acestuia și implementând câteva metode. Partajează codul cu comunitatea pe [Hub](https://hf.co) și înregistrează pipeline-ul în Transformers astfel încât toată lumea să îl poată folosi rapid și ușor.
|
||||
|
||||
Acest ghid te va ghida prin procesul de adăugare a unui nou pipeline în Transformers.
|
||||
|
||||
## Alegeri de design
|
||||
|
||||
La minimum, trebuie doar să oferi [`Pipeline`] un input potrivit pentru un task. Acesta este și punctul de la care ar trebui să începi atunci când îți proiectezi pipeline-ul.
|
||||
|
||||
Decide ce tipuri de input poate accepta [`Pipeline`]. Pot fi string-uri, raw bytes, dicționare și așa mai departe. Încearcă să păstrezi input-urile în Python pur acolo unde este posibil deoarece este mai compatibil. Apoi, decide ce output ar trebui să returneze [`Pipeline`]. Din nou, păstrarea output-ului în Python este opțiunea cea mai simplă și cea mai bună deoarece este mai ușor de lucrat cu el.
|
||||
|
||||
Păstrarea input-urilor și output-urilor simple și, ideal, serializabile în JSON, le face mai ușor utilizatorilor să ruleze [`Pipeline`]-ul tău fără a fi nevoie să învețe tipuri noi de obiecte. De asemenea, este obișnuit să suporți multe tipuri diferite de input pentru o ușurință de utilizare și mai mare. De exemplu, faptul că un fișier audio poate fi acceptat dintr-un nume de fișier, un URL sau raw bytes îi oferă utilizatorului mai multă flexibilitate în modul în care furnizează datele audio.
|
||||
|
||||
## Crearea unui pipeline
|
||||
|
||||
După ce ai decis un input și un output, poți începe să implementezi [`Pipeline`]. Pipeline-ul tău ar trebui să moștenească din clasa de bază [`Pipeline`] și să includă 4 metode.
|
||||
|
||||
```py
|
||||
from transformers import Pipeline
|
||||
|
||||
class MyPipeline(Pipeline):
|
||||
def _sanitize_parameters(self, **kwargs):
|
||||
|
||||
def preprocess(self, inputs, args=2):
|
||||
|
||||
def _forward(self, model_inputs):
|
||||
|
||||
def postprocess(self, model_outputs):
|
||||
```
|
||||
|
||||
1. `preprocess` preia input-urile și le transformă în formatul de input potrivit pentru model.
|
||||
|
||||
```py
|
||||
def preprocess(self, inputs, maybe_arg=2):
|
||||
model_input = Tensor(inputs["input_ids"])
|
||||
return {"model_input": model_input}
|
||||
```
|
||||
|
||||
2. `_forward` nu ar trebui apelată direct. `forward` este metoda preferată deoarece include mecanisme de protecție pentru a se asigura că totul funcționează corect pe device-ul așteptat. Orice este legat de model aparține în `_forward`, iar tot restul aparține fie în `preprocess`, fie în `postprocess`.
|
||||
|
||||
```py
|
||||
def _forward(self, model_inputs):
|
||||
outputs = self.model(**model_inputs)
|
||||
return outputs
|
||||
```
|
||||
|
||||
3. `postprocess` generează output-ul final din output-ul modelului din `_forward`.
|
||||
|
||||
```py
|
||||
def postprocess(self, model_outputs, top_k=5):
|
||||
best_class = model_outputs["logits"].softmax(-1)
|
||||
return best_class
|
||||
```
|
||||
|
||||
4. `_sanitize_parameters` le permite utilizatorilor să transmită parametri suplimentari către [`Pipeline`]. Acest lucru poate avea loc în timpul inițializării sau atunci când [`Pipeline`] este apelat. `_sanitize_parameters` returnează 3 dicts de argumente keyword suplimentare care sunt transmise direct către `preprocess`, `_forward` și `postprocess`. Nu adăuga nimic dacă un utilizator nu a apelat pipeline-ul cu parametri suplimentari. Acest lucru păstrează argumentele implicite în definiția funcției, ceea ce este întotdeauna mai natural.
|
||||
|
||||
De exemplu, adaugă un parametru `top_k` în `postprocess` pentru a returna primele 5 cele mai probabile clase. Apoi, în `_sanitize_parameters`, verifică dacă utilizatorul a transmis `top_k` și adaugă-l la `postprocess_kwargs`.
|
||||
|
||||
```py
|
||||
def _sanitize_parameters(self, **kwargs):
|
||||
preprocess_kwargs = {}
|
||||
if "maybe_arg" in kwargs:
|
||||
preprocess_kwargs["maybe_arg"] = kwargs["maybe_arg"]
|
||||
|
||||
postprocess_kwargs = {}
|
||||
if "top_k" in kwargs:
|
||||
postprocess_kwargs["top_k"] = kwargs["top_k"]
|
||||
return preprocess_kwargs, {}, postprocess_kwargs
|
||||
```
|
||||
|
||||
Acum pipeline-ul poate returna cele mai probabile etichete dacă un utilizator alege acest lucru.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline("my-task")
|
||||
# returnează cele mai probabile 3 etichete
|
||||
pipeline("This is the best meal I've ever had", top_k=3)
|
||||
# returnează implicit cele mai probabile 5 etichete
|
||||
pipeline("This is the best meal I've ever had")
|
||||
```
|
||||
|
||||
## Înregistrarea unui pipeline
|
||||
|
||||
Înregistrează noul task pe care îl suportă pipeline-ul tău în `PIPELINE_REGISTRY`. Registry-ul definește:
|
||||
|
||||
- Clasa de model Pytorch suportată cu `pt_model`
|
||||
- un model implicit care ar trebui să provină dintr-o anumită revizie (branch sau commit hash) unde modelul funcționează conform așteptărilor, cu `default`
|
||||
- input-ul așteptat cu `type`
|
||||
|
||||
```py
|
||||
from transformers.pipelines import PIPELINE_REGISTRY
|
||||
from transformers import AutoModelForSequenceClassification
|
||||
|
||||
PIPELINE_REGISTRY.register_pipeline(
|
||||
"new-task",
|
||||
pipeline_class=MyPipeline,
|
||||
pt_model=AutoModelForSequenceClassification,
|
||||
default={"pt": ("user/awesome-model", "branch-name")},
|
||||
type="text",
|
||||
)
|
||||
```
|
||||
|
||||
## Partajarea pipeline-ului tău
|
||||
|
||||
Partajează pipeline-ul tău cu comunitatea pe [Hub](https://hf.co) sau îl poți adăuga direct în Transformers.
|
||||
|
||||
Este mai rapid să încarci codul pipeline-ului tău pe Hub deoarece nu necesită o revizuire din partea echipei Transformers. Adăugarea pipeline-ului în Transformers poate fi mai lentă deoarece necesită o revizuire și trebuie să adaugi teste pentru a te asigura că [`Pipeline`]-ul tău funcționează.
|
||||
|
||||
### Încărcarea pe Hub
|
||||
|
||||
Adaugă codul pipeline-ului tău pe Hub într-un fișier Python.
|
||||
|
||||
De exemplu, un pipeline personalizat pentru clasificarea perechilor de propoziții ar putea arăta ca în codul de mai jos.
|
||||
|
||||
```py
|
||||
import numpy as np
|
||||
from transformers import Pipeline
|
||||
|
||||
def softmax(outputs):
|
||||
maxes = np.max(outputs, axis=-1, keepdims=True)
|
||||
shifted_exp = np.exp(outputs - maxes)
|
||||
return shifted_exp / shifted_exp.sum(axis=-1, keepdims=True)
|
||||
|
||||
class PairClassificationPipeline(Pipeline):
|
||||
def _sanitize_parameters(self, **kwargs):
|
||||
preprocess_kwargs = {}
|
||||
if "second_text" in kwargs:
|
||||
preprocess_kwargs["second_text"] = kwargs["second_text"]
|
||||
return preprocess_kwargs, {}, {}
|
||||
|
||||
def preprocess(self, text, second_text=None):
|
||||
return self.tokenizer(text, text_pair=second_text, return_tensors=self.framework)
|
||||
|
||||
def _forward(self, model_inputs):
|
||||
return self.model(**model_inputs)
|
||||
|
||||
def postprocess(self, model_outputs):
|
||||
logits = model_outputs.logits[0].numpy()
|
||||
probabilities = softmax(logits)
|
||||
|
||||
best_class = np.argmax(probabilities)
|
||||
label = self.model.config.id2label[best_class]
|
||||
score = probabilities[best_class].item()
|
||||
logits = logits.tolist()
|
||||
return {"label": label, "score": score, "logits": logits}
|
||||
```
|
||||
|
||||
Salvează codul într-un fișier numit `pair_classification.py` și importă-l și înregistrează-l așa cum se arată mai jos.
|
||||
|
||||
```py
|
||||
from pair_classification import PairClassificationPipeline
|
||||
from transformers.pipelines import PIPELINE_REGISTRY
|
||||
from transformers import AutoModelForSequenceClassification
|
||||
|
||||
PIPELINE_REGISTRY.register_pipeline(
|
||||
"pair-classification",
|
||||
pipeline_class=PairClassificationPipeline,
|
||||
pt_model=AutoModelForSequenceClassification,
|
||||
)
|
||||
```
|
||||
|
||||
Funcția [register_pipeline](https://github.com/huggingface/transformers/blob/9feae5fb0164e89d4998e5776897c16f7330d3df/src/transformers/pipelines/base.py#L1387) înregistrează detaliile pipeline-ului (tipul de task, clasa de pipeline, backend-urile suportate) în fișierul `config.json` al unui model.
|
||||
|
||||
```json
|
||||
"custom_pipelines": {
|
||||
"pair-classification": {
|
||||
"impl": "pair_classification.PairClassificationPipeline",
|
||||
"pt": [
|
||||
"AutoModelForSequenceClassification"
|
||||
],
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
Apelează [`~Pipeline.push_to_hub`] pentru a face push pipeline-ului către Hub. Fișierul Python care conține codul este copiat pe Hub, iar modelul și tokenizer-ul pipeline-ului sunt, de asemenea, salvate și trimise (push) către Hub. Pipeline-ul tău ar trebui să fie acum disponibil pe Hub în namespace-ul tău.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline(task="pair-classification", model="sgugger/finetuned-bert-mrpc")
|
||||
pipeline.push_to_hub("pair-classification-pipeline")
|
||||
```
|
||||
|
||||
Pentru a folosi pipeline-ul, adaugă `trust_remote_code=True` atunci când încarci pipeline-ul.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline(task="pair-classification", trust_remote_code=True)
|
||||
```
|
||||
|
||||
### Adăugarea în Transformers
|
||||
|
||||
Adăugarea unui pipeline personalizat în Transformers necesită adăugarea de teste pentru a te asigura că totul funcționează conform așteptărilor și solicitarea unei revizuiri din partea echipei Transformers.
|
||||
|
||||
Adaugă codul pipeline-ului tău ca un nou modul în submodulul [pipelines](https://github.com/huggingface/transformers/tree/main/src/transformers/pipelines) și adaugă-l la lista de task-uri definite în [pipelines/__init__.py](https://github.com/huggingface/transformers/blob/main/src/transformers/pipelines/__init__.py).
|
||||
|
||||
Apoi, adaugă un nou test pentru pipeline în [transformers/tests/pipelines](https://github.com/huggingface/transformers/tree/main/tests/pipelines). Poți să te uiți la celelalte teste pentru exemple despre cum să-ți testezi pipeline-ul.
|
||||
|
||||
Funcția [run_pipeline_test](https://github.com/huggingface/transformers/blob/db70426854fe7850f2c5834d633aff637f14772e/tests/pipelines/test_pipelines_text_classification.py#L186) ar trebui să fie foarte generică și să ruleze pe modelele definite în [model_mapping](https://github.com/huggingface/transformers/blob/db70426854fe7850f2c5834d633aff637f14772e/tests/pipelines/test_pipelines_text_classification.py#L48). Acest lucru este important pentru testarea compatibilității viitoare cu modele noi.
|
||||
|
||||
Vei observa, de asemenea, că `ANY` este folosit pe tot parcursul funcției [run_pipeline_test](https://github.com/huggingface/transformers/blob/db70426854fe7850f2c5834d633aff637f14772e/tests/pipelines/test_pipelines_text_classification.py#L186). Modelele sunt aleatorii, așa că nu poți verifica valorile efective. Folosirea lui `ANY` permite în schimb testului să se potrivească cu output-ul de tipul pipeline-ului.
|
||||
|
||||
În cele din urmă, ar trebui să implementezi și următoarele 4 teste.
|
||||
|
||||
1. [test_small_model_pt](https://github.com/huggingface/transformers/blob/db70426854fe7850f2c5834d633aff637f14772e/tests/pipelines/test_pipelines_text_classification.py#L59), folosește un model mic pentru aceste pipeline-uri pentru a te asigura că returnează output-urile corecte. Rezultatele nu trebuie să aibă sens. Fiecare pipeline ar trebui să returneze același rezultat.
|
||||
1. [test_large_model_pt](https://github.com/huggingface/transformers/blob/db70426854fe7850f2c5834d633aff637f14772e/tests/pipelines/test_pipelines_zero_shot_image_classification.py#L187), folosește un model realist pentru aceste pipeline-uri pentru a te asigura că returnează rezultate semnificative. Aceste teste sunt lente și ar trebui marcate ca fiind lente (slow).
|
||||
233
docs/source/ro/add_vision_processing_components.md
Normal file
233
docs/source/ro/add_vision_processing_components.md
Normal file
@@ -0,0 +1,233 @@
|
||||
<!--Copyright 2026 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Adaugă componente de procesare vizuală
|
||||
|
||||
Adăugarea unui model vizual necesită componente de procesare a imaginilor sau videoclipurilor pe lângă abordarea standard [modulară](./modular_transformers). Modelele exclusiv pentru imagini au nevoie de procesatoare de imagini, iar modelele video au nevoie de un procesator video, ambele accesibile prin punctele de intrare [`AutoImageProcessor`] și [`AutoVideoProcessor`].
|
||||
|
||||
> [!NOTE]
|
||||
> Pentru pașii de modelare și configurare, urmează mai întâi ghidul [modular](./modular_transformers).
|
||||
|
||||
## Procesatoare de imagini
|
||||
|
||||
Creează procesatoare de imagini când modelul consumă imagini. Backend-ul [torchvision](https://docs.pytorch.org/vision/stable/index.html) este varianta implicită și suportă accelerarea GPU. [PIL](https://pillow.readthedocs.io/en/stable/index.html) este varianta de fallback când torchvision nu este disponibil.
|
||||
|
||||
Ambele clase de procesatoare de imagini împart aceeași logică de preprocesare, dar au backend-uri diferite. Semnăturile constructorilor și valorile implicite trebuie să fie identice. [`AutoImageProcessor.from_pretrained`] selectează backend-ul la momentul încărcării și revine la PIL când torchvision nu este disponibil. Semnăturile nepotrivite fac ca același config salvat să se comporte diferit în funcție de mediu.
|
||||
|
||||
### torchvision
|
||||
|
||||
Creează `image_processing_<model_name>.py` cu o clasă care moștenește din [`TorchvisionBackend`]. Dacă procesatorul tău necesită parametri personalizați dincolo de [ImagesKwargs] standard, definește o clasă kwargs.
|
||||
|
||||
```py
|
||||
from ...image_processing_backends import TorchvisionBackend
|
||||
from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, PILImageResampling
|
||||
from ...processing_utils import ImagesKwargs, Unpack
|
||||
from ...utils import auto_docstring
|
||||
|
||||
class MyModelImageProcessorKwargs(ImagesKwargs, total=False):
|
||||
tile_size: int # orice kwargs specifice modelului
|
||||
|
||||
@auto_docstring
|
||||
class MyModelImageProcessor(TorchvisionBackend):
|
||||
resample = PILImageResampling.BICUBIC
|
||||
image_mean = OPENAI_CLIP_MEAN
|
||||
image_std = OPENAI_CLIP_STD
|
||||
size = {"shortest_edge": 224}
|
||||
do_resize = True
|
||||
do_rescale = True
|
||||
do_normalize = True
|
||||
do_convert_rgb = True
|
||||
|
||||
def __init__(self, **kwargs: Unpack[MyModelImageProcessorKwargs]):
|
||||
super().__init__(**kwargs)
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> Vezi [`LlavaOnevisionImageProcessor`] ca referință.
|
||||
|
||||
### PIL
|
||||
|
||||
Creează `image_processing_pil_<model_name>.py` cu o clasă care moștenește din [`PilBackend`]. Duplică clasa kwargs aici în loc s-o importezi din fișierul torchvision, pentru că poate eșua când torchvision nu este instalat. Adaugă un comentariu `# Adapted from` ca cele două să rămână sincronizate. Pentru procesoarele fără parametri personalizați, folosește [`ImagesKwargs`] direct.
|
||||
|
||||
```py
|
||||
from ...image_processing_backends import PilBackend
|
||||
from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, PILImageResampling
|
||||
from ...processing_utils import ImagesKwargs, Unpack
|
||||
from ...utils import auto_docstring
|
||||
|
||||
# Adaptat din transformers.models.my_model.image_processing_my_model.MyModelImageProcessorKwargs
|
||||
class MyModelImageProcessorKwargs(ImagesKwargs, total=False):
|
||||
tile_size: int # orice kwargs specifice modelului
|
||||
|
||||
@auto_docstring
|
||||
class MyModelImageProcessorPil(PilBackend):
|
||||
resample = PILImageResampling.BICUBIC
|
||||
image_mean = OPENAI_CLIP_MEAN
|
||||
image_std = OPENAI_CLIP_STD
|
||||
size = {"shortest_edge": 224}
|
||||
do_resize = True
|
||||
do_rescale = True
|
||||
do_normalize = True
|
||||
do_convert_rgb = True
|
||||
|
||||
def __init__(self, **kwargs: Unpack[MyModelImageProcessorKwargs]):
|
||||
super().__init__(**kwargs)
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> Vezi [`LlavaOnevisionImageProcessorPil`] ca referință.
|
||||
|
||||
## Procesator video
|
||||
|
||||
Adaugă un procesator video când modelul consumă videoclipuri sau cadre video eșantionate.
|
||||
|
||||
Creează `video_processing_<model_name>.py` în folder-ul modelului. [`BaseVideoProcessor`] moștenește din [`TorchvisionBackend`] și furnizează comportament comun de decodare, eșantionare a cadrelor, redimensionare, rescalare, normalizare, salvare și încărcare.
|
||||
|
||||
Atributele de clasă sunt valorile implicite de preprocesare. Utilizatorii le pot suprascrie la inițializare sau la apel. Folosește aceleași nume ca [`VideosKwargs`] când e posibil, cum ar fi `size`, `crop_size`, `do_resize`, `do_sample_frames`, `num_frames` și `fps`.
|
||||
|
||||
Definește o clasă kwargs dacă procesorul tău video necesită parametri personalizați dincolo de [`VideosKwargs`] standard. Seteaz-o ca `valid_kwargs` și folosește-o ca să adnotezi `__init__` atât pentru validarea la rulare, cât și pentru docstring-ul auto-generat.
|
||||
|
||||
```py
|
||||
from ...processing_utils import Unpack, VideosKwargs
|
||||
from ...utils import auto_docstring
|
||||
from ...video_processing_utils import BaseVideoProcessor
|
||||
|
||||
class MyModelVideoProcessorKwargs(VideosKwargs, total=False):
|
||||
min_frames: int
|
||||
max_frames: int
|
||||
|
||||
@auto_docstring
|
||||
class MyModelVideoProcessor(BaseVideoProcessor):
|
||||
size = {"shortest_edge": 224}
|
||||
crop_size = {"height": 224, "width": 224}
|
||||
do_resize = True
|
||||
do_center_crop = True
|
||||
do_normalize = True
|
||||
do_sample_frames = True
|
||||
num_frames = 16
|
||||
model_input_names = ["pixel_values_videos"]
|
||||
valid_kwargs = MyModelVideoProcessorKwargs
|
||||
|
||||
def __init__(self, **kwargs: Unpack[MyModelVideoProcessorKwargs]):
|
||||
super().__init__(**kwargs)
|
||||
```
|
||||
|
||||
Suprascrie [`~BaseVideoProcessor.sample_frames`] doar când modelul necesită o regulă de eșantionare pe care eșantionatorul uniform de bază nu o poate exprima. De exemplu, unele modele impun un număr minim sau maxim de cadre sau eșantionează pe baza unor constrângeri specifice modelului.
|
||||
|
||||
Dacă metoda forward a modelului așteaptă un nume de input legacy, suprascrie `preprocess` și redenumește cheia după apelarea implementării de bază.
|
||||
|
||||
```py
|
||||
class MyModelVideoProcessor(BaseVideoProcessor):
|
||||
model_input_names = ["pixel_values"]
|
||||
|
||||
def preprocess(self, videos, **kwargs):
|
||||
batch = super().preprocess(videos, **kwargs)
|
||||
batch["pixel_values"] = batch.pop("pixel_values_videos")
|
||||
return batch
|
||||
```
|
||||
|
||||
Salvează procesatorul video cu checkpoint-ul instanțiindu-l în scriptul de conversie și apelând [`~BaseVideoProcessor.save_pretrained`]. Dacă un [`ProcessorMixin`] dă wrap procesatorului video, apelează [`~ProcessorMixin.save_pretrained`] în schimb. Nu crea sau edita manual fișierele de configurație pentru preprocesare.
|
||||
|
||||
> [!TIP]
|
||||
> Vezi [`Qwen3VLVideoProcessor`] ca referință.
|
||||
|
||||
## Înregistrarea claselor
|
||||
|
||||
Expune clasele de procesare din `__init__.py`-ul pachetului modelului. Urmează pattern-ul de import lazy folosit de modelele vecine și protejează importurile cu aceleași dependențe opționale necesare fiecărui backend.
|
||||
|
||||
Mapează noile clase la configurația modelului pentru ca clasele `Auto` să le poată încărca. Fișierul de mapare auto generat are un avertisment la început. Nu îl edita manual. Adaugă sau actualizează configurația modelului, apoi rulează:
|
||||
|
||||
```bash
|
||||
python utils/check_auto.py --fix_and_overwrite
|
||||
```
|
||||
|
||||
După generarea mapării, verifică că tipul de model apare în mapările relevante din `src/transformers/models/auto/auto_mappings.py`.
|
||||
|
||||
- `IMAGE_PROCESSOR_MAPPING_NAMES` pentru [`AutoImageProcessor`]
|
||||
- `VIDEO_PROCESSOR_MAPPING_NAMES` pentru [`AutoVideoProcessor`]
|
||||
|
||||
## Testare
|
||||
|
||||
Adaugă teste pentru fiecare componentă de procesare vizuală în directorul de teste al modelului. Testele pentru procesoarele de imagini și video urmează același pattern. Moștenești din mixin-ul comun, indici clasele de procesare fast și slow când descoperirea automată nu este suficientă, furnizezi kwargs de inițializare specifice modelului și suprascrii numele inputului când modelul folosește o cheie de ieșire non-implicită.
|
||||
|
||||
### Teste pentru procesoare de imagini
|
||||
|
||||
Testele pentru procesoarele de imagini se află de obicei în `tests/models/<model_name>/test_image_processing_<model_name>.py` și moștenesc din [`ImageProcessingTestMixin`].
|
||||
|
||||
Mixin-ul de procesare a imaginilor găsește clasele de procesoare de imagini din `IMAGE_PROCESSOR_MAPPING_NAMES`. Expune valorile implicite specifice modelului prin `image_processor_dict`. Adaugă un obiect tester doar când ai nevoie de input-uri dummy reutilizabile sau metode ajutătoare pentru teste focalizate.
|
||||
|
||||
```py
|
||||
from transformers.testing_utils import require_torch, require_vision
|
||||
from ...test_image_processing_common import ImageProcessingTestMixin
|
||||
|
||||
@require_torch
|
||||
@require_vision
|
||||
class MyModelImageProcessingTest(ImageProcessingTestMixin, unittest.TestCase):
|
||||
@property
|
||||
def image_processor_dict(self):
|
||||
return {"size": {"shortest_edge": 224}, "do_resize": True}
|
||||
```
|
||||
|
||||
Adaugă teste focalizate pentru comportamentul pe care mixin-ul nu îl poate deduce, cum ar fi regulile de redimensionare personalizate sau kwargs specifice modelului.
|
||||
|
||||
### Teste pentru procesoare video
|
||||
|
||||
Testele pentru procesoarele video trăiesc de obicei în `tests/models/<model_name>/test_video_processing_<model_name>.py` și moștenesc din [`VideoProcessingTestMixin`]. Setează `fast_video_processing_class`, definește `video_processor_dict` și suprascrie `input_name` dacă modelul folosește o altă cheie decât `pixel_values_videos`.
|
||||
|
||||
```py
|
||||
from transformers.testing_utils import require_torch, require_vision
|
||||
from transformers.utils import is_torchvision_available
|
||||
from ...test_video_processing_common import VideoProcessingTestMixin
|
||||
|
||||
@require_torch
|
||||
@require_vision
|
||||
class MyModelVideoProcessingTest(VideoProcessingTestMixin, unittest.TestCase):
|
||||
fast_video_processing_class = MyModelVideoProcessor if is_torchvision_available() else None
|
||||
input_name = "pixel_values_videos"
|
||||
|
||||
@property
|
||||
def video_processor_dict(self):
|
||||
return {"size": {"shortest_edge": 224}, "num_frames": 16}
|
||||
```
|
||||
|
||||
Adaugă teste video focalizate pentru eșantionarea cadrelor, gestionarea metadatelor, input-urile video decodate, input-urile de tip listă de cadre și formele de ieșire. Dacă procesatorul tău redenumește `pixel_values_videos`, verifică dacă cheia redenumită este returnată.
|
||||
|
||||
Dacă modelul are și un [`ProcessorMixin`] care înfășoară procesatorul de imagini sau video, adaugă `tests/models/<model_name>/test_processing_<model_name>.py` și moștenește din [`ProcessorTesterMixin`]. Setează `processor_class` și suprascrie metodele de clasă `_setup_<component>()` pentru componentele care nu pot fi construite fără argumente. Folosește `_setup_test_attributes()` ca să expui token-urile placeholder folosite de testele comune ale procesatorului.
|
||||
|
||||
```py
|
||||
from ...test_processing_common import ProcessorTesterMixin
|
||||
|
||||
class MyModelProcessorTest(ProcessorTesterMixin, unittest.TestCase):
|
||||
processor_class = MyModelProcessor
|
||||
|
||||
@classmethod
|
||||
def _setup_image_processor(cls):
|
||||
return cls._get_component_class_from_processor("image_processor")(size={"shortest_edge": 224})
|
||||
|
||||
@classmethod
|
||||
def _setup_video_processor(cls):
|
||||
return cls._get_component_class_from_processor("video_processor")(num_frames=2)
|
||||
|
||||
@classmethod
|
||||
def _setup_test_attributes(cls, processor):
|
||||
cls.image_token = getattr(processor, "image_token", "")
|
||||
cls.video_token = getattr(processor, "video_token", "")
|
||||
```
|
||||
|
||||
## Pașii următori
|
||||
|
||||
- Citește ghidul [Auto-generarea docstring-urilor](./auto_docstring) ca să auto-generezi docstring-uri consistente cu `@auto_docstring`.
|
||||
- Citește ghidurile [Procesoare de imagini](./image_processors) și [Procesoare video](./video_processors) pentru comportamentul de preprocesare orientat către utilizator.
|
||||
383
docs/source/ro/auto_docstring.md
Normal file
383
docs/source/ro/auto_docstring.md
Normal file
@@ -0,0 +1,383 @@
|
||||
<!--Copyright 2025 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Auto-generarea docstring-urilor
|
||||
|
||||
Decoratorul `@auto_docstring` generează docstring-uri consistente pentru clasele și metodele de model. Trage automat descrierile standard ale argumentelor, deci scrii documentație doar pentru argumentele noi sau personalizate. Când [adaugi un model nou](./modular_transformers), sari peste boilerplate și concentrează-te pe ce e nou.
|
||||
|
||||
## @auto_docstring
|
||||
|
||||
Importă decoratorul în fișierul tău `modular_model.py` (sau `modeling_model.py` pentru modele mai vechi).
|
||||
|
||||
```python
|
||||
from ...utils import auto_docstring
|
||||
```
|
||||
|
||||
Dacă modelul tău moștenește dintr-un alt model din librărie într-un fișier modular, `@auto_docstring` este deja aplicat în părinte. `make fix-repo` îl copiază în fișierul `modeling_model.py` generat. Aplică decoratorul explicit doar ca să personalizezi comportamentul (modele standalone, intro-uri personalizate sau argumente suprascrise).
|
||||
|
||||
> [!WARNING]
|
||||
> Când suprascrii orice decorator într-un fișier modular, include **toți** decoratorii din funcția sau clasa părinte. Dacă suprascrii doar unii, restul nu vor apărea în fișierul de modelare generat.
|
||||
|
||||
Decoratorul acceptă următoarele argumente opționale:
|
||||
|
||||
| argument | descriere |
|
||||
|---|---|
|
||||
| `custom_intro` | O descriere a clasei sau metodei, inserată înainte de secțiunea Args. Necesară pentru clasele al căror nume nu se termină cu un [sufix recunoscut](#cum-funcționează) precum `ForCausalLM` sau `ForTokenClassification`. |
|
||||
| `custom_args` | Text de docstring pentru parametri specifici. Util când aceleași argumente personalizate apar în mai multe locuri din fișierul de modelare. |
|
||||
| `checkpoint` | Un identificator de checkpoint (`"org/my-model"`) folosit ca să genereze exemple de utilizare. Suprascrie checkpoint-ul dedus automat din clasa de config. Se setează de obicei pe clasele de config. |
|
||||
|
||||
## Utilizare
|
||||
|
||||
Cum funcționează `@auto_docstring` depinde de ce decorezi. Clasele de model trag documentația parametrilor din `__init__`, clasele de config trag din adnotările la nivel de clasă, clasele de procesor auto-generează intro-uri din componentele lor, iar metodele precum `forward` primesc tipuri de returnare și exemple de utilizare.
|
||||
|
||||
### Clase de model
|
||||
|
||||
Pune `@auto_docstring` direct deasupra definiției clasei. Decoratorul derivă descrierile parametrilor din semnătura și docstring-ul metodei `__init__`.
|
||||
|
||||
```python
|
||||
from transformers.modeling_utils import PreTrainedModel
|
||||
from ...utils import auto_docstring
|
||||
|
||||
@auto_docstring
|
||||
class MyAwesomeModel(PreTrainedModel):
|
||||
def __init__(self, config, custom_parameter: int = 10, another_custom_arg: str = "default"):
|
||||
r"""
|
||||
custom_parameter (`int`, *optional*, defaults to 10):
|
||||
Descrierea custom_parameter pentru MyAwesomeModel.
|
||||
another_custom_arg (`str`, *optional*, defaults to "default"):
|
||||
Documentație pentru un alt argument unic.
|
||||
"""
|
||||
super().__init__(config)
|
||||
self.custom_parameter = custom_parameter
|
||||
self.another_custom_arg = another_custom_arg
|
||||
# ... restul init-ului tău
|
||||
|
||||
# ... alte metode
|
||||
```
|
||||
|
||||
Pasează `custom_intro` și `custom_args` pentru mai mult control. Argumentele personalizate pot merge în `custom_args` sau în docstring-ul `__init__`. Folosește `custom_args` când aceleași argumente se repetă în mai multe metode.
|
||||
|
||||
```python
|
||||
@auto_docstring(
|
||||
custom_intro="""Acest model efectuează operații sinergice specifice.
|
||||
Se construiește pe arhitectura standard Transformer cu modificări unice.""",
|
||||
custom_args="""
|
||||
custom_parameter (`type`, *optional*, defaults to `default_value`):
|
||||
O descriere concisă pentru custom_parameter dacă nu este definit sau suprascrie descrierea din `auto_docstring.py`.
|
||||
internal_helper_arg (`type`, *optional*, defaults to `default_value`):
|
||||
O descriere concisă pentru internal_helper_arg dacă nu este definit sau suprascrie descrierea din `auto_docstring.py`.
|
||||
"""
|
||||
)
|
||||
class MySpecialModel(PreTrainedModel):
|
||||
def __init__(self, config: ConfigType, custom_parameter: "type" = "default_value", internal_helper_arg=None):
|
||||
# ...
|
||||
```
|
||||
|
||||
Aplică `@auto_docstring` și la clasele care moștenesc din [`~utils.ModelOutput`].
|
||||
|
||||
```python
|
||||
@auto_docstring(
|
||||
custom_intro="""
|
||||
Ieșiri personalizate ale modelului cu câmpuri suplimentare.
|
||||
"""
|
||||
)
|
||||
@dataclass
|
||||
class MyModelOutput(ImageClassifierOutput):
|
||||
r"""
|
||||
loss (`torch.FloatTensor`, *optional*):
|
||||
Loss-ul modelului.
|
||||
custom_field (`torch.FloatTensor` of shape `(batch_size, hidden_size)`, *optional*):
|
||||
Un câmp de ieșire personalizat specific acestui model.
|
||||
"""
|
||||
|
||||
# Câmpurile standard (hidden_states, logits, attentions, etc.) sunt documentate automat când
|
||||
# descrierea corespunde textului standard. Loss-ul variază de obicei per model, deci documentează-l mai sus.
|
||||
loss: Optional[torch.FloatTensor] = None
|
||||
logits: Optional[torch.FloatTensor] = None
|
||||
hidden_states: Optional[tuple[torch.FloatTensor, ...]] = None
|
||||
attentions: Optional[tuple[torch.FloatTensor, ...]] = None
|
||||
# Câmpurile personalizate trebuie documentate în docstring-ul de mai sus
|
||||
custom_field: Optional[torch.FloatTensor] = None
|
||||
```
|
||||
|
||||
### Clase de config
|
||||
|
||||
Pune `@auto_docstring` direct deasupra unei subclase [`PreTrainedConfig`], alături de decoratorul `@strict`. `@strict` adaugă validarea de tip la runtime și transformă clasa într-un dataclass validat. Parametrii de config sunt *adnotări la nivel de clasă* (nu argumente `__init__`), iar `@auto_docstring` îi citește din corpul clasei ca să genereze docs.
|
||||
|
||||
[`ConfigArgs`] furnizează parametri standard precum `vocab_size`, `hidden_size` și `num_hidden_layers`, deci nu au nevoie de descriere dacă comportamentul nu diferă. Parametrii de bază [`PreTrainedConfig`] sunt excluși automat. Argumentul `checkpoint` generează exemplul de utilizare.
|
||||
|
||||
```python
|
||||
from huggingface_hub.dataclasses import strict
|
||||
from ...configuration_utils import PreTrainedConfig
|
||||
from ...utils import auto_docstring
|
||||
|
||||
@strict
|
||||
@auto_docstring(checkpoint="org/my-model-checkpoint")
|
||||
class MyModelConfig(PreTrainedConfig):
|
||||
r"""
|
||||
custom_param (`int`, *optional*, defaults to 64):
|
||||
Descrierea unui parametru specific acestui model.
|
||||
another_param (`str`, *optional*, defaults to `"gelu"`):
|
||||
Descrierea unui alt parametru specific modelului.
|
||||
|
||||
```python
|
||||
>>> from transformers import MyModelConfig, MyModel
|
||||
|
||||
>>> configuration = MyModelConfig()
|
||||
>>> model = MyModel(configuration)
|
||||
>>> configuration = model.config
|
||||
```
|
||||
"""
|
||||
|
||||
model_type = "my_model"
|
||||
|
||||
# Parametrii standard (vocab_size, hidden_size, etc.) sunt auto-documentați din ConfigArgs.
|
||||
vocab_size: int = 32000
|
||||
hidden_size: int = 768
|
||||
num_hidden_layers: int = 12
|
||||
# Parametrii specifici modelului trebuie documentați în docstring-ul clasei de mai sus.
|
||||
custom_param: int = 64
|
||||
another_param: str = "gelu"
|
||||
```
|
||||
|
||||
### Clase de procesator
|
||||
|
||||
Procesoarele multimodale (subclase [`ProcessorMixin`], `processing_*.py`) folosesc întotdeauna `@auto_docstring` simplu. Intro-ul clasei este auto-generat. Documentează doar parametrii `__init__` care nu sunt deja acoperiți de [`ProcessorArgs`] (`image_processor`, `tokenizer`, `chat_template` și alții).
|
||||
|
||||
Dacă fiecare parametru este standard, omite docstring-ul. Decorează și `__call__` cu `@auto_docstring`. Docstring-ul corpului său conține doar o secțiune `Returns:` plus orice argumente de apel suplimentare specifice modelului. `return_tensors` este adăugat automat.
|
||||
|
||||
```python
|
||||
from ...processing_utils import ProcessorMixin, ProcessingKwargs, Unpack
|
||||
from ...utils import auto_docstring
|
||||
|
||||
class MyModelProcessorKwargs(ProcessingKwargs, total=False):
|
||||
_defaults = {"text_kwargs": {"padding": False}}
|
||||
|
||||
@auto_docstring
|
||||
class MyModelProcessor(ProcessorMixin):
|
||||
def __init__(self, image_processor=None, tokenizer=None, custom_param: int = 4, **kwargs):
|
||||
r"""
|
||||
custom_param (`int`, *optional*, defaults to 4):
|
||||
Un parametru specific acestui procesor, neacoperit de ProcessorArgs standard.
|
||||
"""
|
||||
super().__init__(image_processor, tokenizer)
|
||||
self.custom_param = custom_param
|
||||
|
||||
@auto_docstring
|
||||
def __call__(self, images=None, text=None, **kwargs: Unpack[MyModelProcessorKwargs]):
|
||||
r"""
|
||||
Returns:
|
||||
[`BatchFeature`]: Un [`BatchFeature`] cu următoarele câmpuri:
|
||||
|
||||
- **input_ids** -- Token ids de pasat modelului.
|
||||
- **pixel_values** -- Valori pixel de pasat modelului.
|
||||
"""
|
||||
# ...
|
||||
```
|
||||
|
||||
#### Procesatoare de imagini și video
|
||||
|
||||
Procesatoarele de imagini și video (subclase `BaseImageProcessor`, `image_processing_*.py`) urmează unul din două pattern-uri.
|
||||
|
||||
Dacă procesorul are parametri specifici modelului, definești un `TypedDict` `XxxImageProcessorKwargs(ImagesKwargs, total=False)` cu un docstring pentru acei parametri, setezi `valid_kwargs` pe clasă și folosești `@auto_docstring` simplu. `__init__` nu are docstring.
|
||||
|
||||
```python
|
||||
class MyModelImageProcessorKwargs(ImagesKwargs, total=False):
|
||||
r"""
|
||||
custom_threshold (`float`, *optional*, defaults to `self.custom_threshold`):
|
||||
Un parametru specific acestui procesor de imagini.
|
||||
"""
|
||||
custom_threshold: float | None
|
||||
|
||||
@auto_docstring
|
||||
class MyModelImageProcessor(TorchvisionBackend):
|
||||
valid_kwargs = MyModelImageProcessorKwargs
|
||||
custom_threshold: float = 0.5
|
||||
|
||||
def __init__(self, **kwargs: Unpack[MyModelImageProcessorKwargs]):
|
||||
super().__init__(**kwargs)
|
||||
```
|
||||
|
||||
Dacă clasa setează doar atribute standard la nivel de clasă (`size`, `resample`, `image_mean` etc.) fără kwargs personalizate, folosește `@auto_docstring(custom_intro="Constructs a MyModel image processor.")`.
|
||||
|
||||
```python
|
||||
@auto_docstring(custom_intro="Constructs a MyModel image processor.")
|
||||
class MyModelImageProcessor(TorchvisionBackend):
|
||||
resample = PILImageResampling.BICUBIC
|
||||
image_mean = IMAGENET_STANDARD_MEAN
|
||||
image_std = IMAGENET_STANDARD_STD
|
||||
size = {"height": 224, "width": 224}
|
||||
```
|
||||
|
||||
Când suprascrii `preprocess`, decorează-l cu `@auto_docstring` și documentează doar argumentele care nu sunt în [`ImageProcessorArgs`]. Argumentele standard și `return_tensors` sunt incluse automat.
|
||||
|
||||
### Funcții
|
||||
|
||||
Pune `@auto_docstring` direct deasupra definiției funcției. Decoratorul derivă descrierile parametrilor din semnătura funcției.
|
||||
|
||||
Decoratorul generează textul valorii de returnare din docstring-ul clasei [`ModelOutput`].
|
||||
|
||||
```python
|
||||
class MyModel(PreTrainedModel):
|
||||
# ...
|
||||
@auto_docstring
|
||||
def forward(
|
||||
self,
|
||||
input_ids: Optional[torch.Tensor] = None,
|
||||
attention_mask: Optional[torch.Tensor] = None,
|
||||
new_custom_argument: Optional[torch.Tensor] = None,
|
||||
# ... alte argumente
|
||||
) -> Union[Tuple, ModelOutput]:
|
||||
r"""
|
||||
new_custom_argument (`torch.Tensor`, *optional*):
|
||||
Descrierea acestui argument personalizat nou și forma sau tipul așteptat.
|
||||
"""
|
||||
# ...
|
||||
```
|
||||
|
||||
Pasează `custom_intro` și `custom_args` pentru mai mult control. Folosește `custom_args` ca să definești documentația argumentelor partajate o singură dată când aceiași parametri apar în mai multe metode.
|
||||
|
||||
```python
|
||||
MODEL_COMMON_CUSTOM_ARGS = r"""
|
||||
common_arg_1 (`torch.Tensor`, *optional*, defaults to `default_value`):
|
||||
Descrierea lui common_arg_1
|
||||
common_arg_2 (`torch.Tensor`, *optional*, defaults to `default_value`):
|
||||
Descrierea lui common_arg_2
|
||||
"""
|
||||
|
||||
class MyModel(PreTrainedModel):
|
||||
# ...
|
||||
@auto_docstring(
|
||||
custom_intro="""Acesta este un intro personalizat pentru funcție.""",
|
||||
custom_args=MODEL_COMMON_CUSTOM_ARGS
|
||||
)
|
||||
def forward(self, input_ids=None, common_arg_1=None, common_arg_2=None) -> ModelOutput:
|
||||
r"""argumente specifice metodei merg aici"""
|
||||
# ...
|
||||
```
|
||||
|
||||
Scrie secțiunile `Returns` și `Examples` manual în docstring ca să suprascrii versiunile auto-generate.
|
||||
|
||||
```python
|
||||
def forward(self, input_ids=None) -> torch.Tensor:
|
||||
r"""
|
||||
Returns:
|
||||
`torch.Tensor`: O secțiune Returns personalizată pentru tipuri de returnare non-ModelOutput.
|
||||
|
||||
Example:
|
||||
|
||||
```python
|
||||
>>> model = MyModel.from_pretrained("org/my-model")
|
||||
>>> output = model(input_ids)
|
||||
```
|
||||
"""
|
||||
# ...
|
||||
```
|
||||
|
||||
### Documentarea argumentelor
|
||||
|
||||
Urmează aceste reguli când documentezi tipuri diferite de argumente.
|
||||
|
||||
- `auto_docstring.py` definește argumentele standard (`input_ids`, `attention_mask`, `pixel_values` etc.) și le include automat. Nu le redefini local dacă argumentul se comportă la fel ca în modelul tău.
|
||||
|
||||
Dacă un argument standard se comportă diferit în modelul tău, suprascrie-l local într-un bloc `r""" """`. Definiția locală are prioritate. Argumentul `labels`, de exemplu, este personalizat des per model și necesită să fie suprascris.
|
||||
|
||||
- Argumentele standard de config (`vocab_size`, `hidden_size`, `num_hidden_layers` etc.) urmează același principiu, dar vin din [`ConfigArgs`]. Argumentele standard de procesor (`image_processor`, `tokenizer`, `do_resize`, `return_tensors` etc.) vin din [`ProcessorArgs`] și [`ImageProcessorArgs`]. Documentează un parametru doar dacă este specific modelului sau se comportă diferit față de descrierea standard.
|
||||
|
||||
- Documentează argumentele noi sau personalizate într-un bloc `r""" """`. Pune-le după semnătură pentru funcții, în docstring-ul `__init__` pentru clase de model sau procesor, în docstring-ul corpului clasei pentru clase de config, sau în corpul `TypedDict`-ului `XxxImageProcessorKwargs` pentru procesoare de imagini.
|
||||
|
||||
```py
|
||||
argument_name (`type`, *optional*, defaults to `X`):
|
||||
Descrierea argumentului.
|
||||
Explică scopul, forma/tipul așteptat dacă e complex și comportamentul implicit.
|
||||
Poate fi pe mai multe linii.
|
||||
```
|
||||
|
||||
* Include `type` în backticks.
|
||||
* Adaugă *optional* dacă argumentul nu este obligatoriu sau are o valoare implicită.
|
||||
* Adaugă "defaults to X" dacă are o valoare implicită. Nu trebuie să adaugi "defaults to `None`" dacă valoarea implicită este `None`.
|
||||
* Pasează același bloc în `custom_args` când aceleași argumente se repetă în mai multe metode (vezi [exemplul cu Funcții de mai sus](#funcții)).
|
||||
|
||||
- Decoratorul extrage tipurile din semnăturile funcțiilor automat. Dacă un parametru are o adnotare de tip, nu trebuie să repeți tipul în format string în docstring. Când ambele sunt prezente, tipul semnăturii are prioritate. Tipul din docstring acționează ca fallback pentru parametrii fără adnotare.
|
||||
|
||||
## Verificarea docstring-urilor
|
||||
|
||||
Un script utilitar validează docstring-urile când deschizi un pull request. CI rulează scriptul și verifică următoarele.
|
||||
|
||||
> [!TIP]
|
||||
> Dacă vezi `[ERROR]` în output, adaugă descrierea parametrului în docstring sau în clasa Args corespunzătoare din `auto_docstring.py`.
|
||||
|
||||
* Verifică că `@auto_docstring` este aplicat la clasele de model relevante și metodele publice.
|
||||
* Validează completitudinea și consistența argumentelor: argumentele documentate trebuie să existe în semnătură, iar tipurile și valorile implicite trebuie să corespundă. Argumentele necunoscute fără o descriere locală sunt semnalate.
|
||||
* Semnalează placeholder-urile incomplete precum `<fill_type>` și `<fill_docstring>`.
|
||||
* Verifică că docstring-urile urmează stilul de formatare așteptat.
|
||||
|
||||
Rulează verificarea local înainte de commit.
|
||||
|
||||
```bash
|
||||
make fix-repo
|
||||
```
|
||||
|
||||
`make fix-repo` rulează și alte verificări. Ca să rulezi doar verificările de docstring și auto-docstring, folosește comanda de mai jos.
|
||||
|
||||
```bash
|
||||
# verifică doar fișierele incluse în diff fără să le remedieze
|
||||
python utils/check_docstrings.py
|
||||
# remediază și suprascrie fișierele din diff
|
||||
# python utils/check_docstrings.py --fix_and_overwrite
|
||||
# remediază și suprascrie toate fișierele
|
||||
# python utils/check_docstrings.py --fix_and_overwrite --check_all
|
||||
```
|
||||
|
||||
## Checklist de referință rapidă
|
||||
|
||||
| Fă | Nu face |
|
||||
|---|---|
|
||||
| Aplică `@auto_docstring` la clasele de model, config și procesor și metodele lor principale (`forward`, `__call__`, `preprocess`). | Adaugă `@auto_docstring` la modelele moștenite în fișierele modulare pentru că se transferă automat. |
|
||||
| Documentează doar argumentele noi sau specifice modelului. | Redefinește argumentele standard (`input_ids`, `attention_mask`, `vocab_size` etc.) care se comportă la fel cu descrierile lor implicite. |
|
||||
| Pune parametrii de config în docstring-ul corpului clasei ca adnotări la nivel de clasă. | Pune parametrii de config în `__init__`. |
|
||||
| Pune parametrii procesorului de imagini într-un `TypedDict` `XxxImageProcessorKwargs`. | Pune parametrii procesorului de imagini în `__init__`. |
|
||||
| Rulează `python utils/check_docstrings.py --fix_and_overwrite` înainte de commit. | Ignoră ieșirile `[ERROR]` pentru că înseamnă că un parametru este nedocumentat. |
|
||||
|
||||
## Cum funcționează
|
||||
|
||||
Decoratorul `@auto_docstring` generează docstring-uri prin pașii următori.
|
||||
|
||||
1. Decoratorul inspectează semnătura ca să citească argumentele, tipurile și valorile implicite din `__init__`-ul clasei decorate sau din funcția decorată. Pentru clasele de config, parcurge adnotările la nivel de clasă în sus pe lanțul de moștenire și se oprește înainte de [`PreTrainedConfig`], excluzând câmpurile clasei de bază.
|
||||
|
||||
Filtrează automat parametri precum `self`, `kwargs`, `args`, `deprecated_arguments` și nume cu prefix `_`. Câțiva parametri privați sunt redenumiți la echivalentele lor publice (`_out_features` → `out_features` pentru modele backbone).
|
||||
|
||||
2. Descrierile comune ale argumentelor vin din `auto_docstring.py`: [`ModelArgs`] (inputuri model), [`ModelOutputArgs`] (câmpuri de ieșire precum `hidden_states`), [`ImageProcessorArgs`] (preprocesare imagini), [`ProcessorArgs`] (componente procesor multimodal) și [`ConfigArgs`] (hyperparameteri de config).
|
||||
|
||||
3. Descrierea fiecărui parametru urmează acest lanț de prioritate:
|
||||
|
||||
- Un docstring manual (bloc `r""" """` sau `custom_args`) are prioritate.
|
||||
- Dicționarul de surse predefinit ([`ModelArgs`], [`ConfigArgs`], [`ImageProcessorArgs`], [`ProcessorArgs`], [`ModelOutputArgs`]) este fallback-ul.
|
||||
- Dacă nicio sursă nu are o descriere, parametrul este semnalat cu `[ERROR]` în ieșirea de build.
|
||||
|
||||
4. Pentru clasele de model cu nume standard precum `ModelForCausalLM`, sau clasele care mapează la un pipeline, `@auto_docstring` generează intro-ul. Pentru procesoarele multimodale, intro-ul listează ce componente (tokenizer, procesor de imagini etc.) dau wrap clasei. Vezi [ClassDocstring](https://github.com/huggingface/transformers/blob/main/src/transformers/utils/auto_docstring.py#L2437) pentru lista completă.
|
||||
|
||||
Dacă numele clasei nu este în `ClassDocstring`, setează `custom_intro`.
|
||||
|
||||
5. Docstring-urile predefinite pot face referire la valori dinamice din [auto_modules](https://github.com/huggingface/transformers/tree/main/src/transformers/models/auto) Transformers, cum ar fi `{processor_class}`, `{image_processor_class}` și `{config_class}`. Placeholder-urile se rezolvă automat.
|
||||
|
||||
6. Decoratorul alege exemple de utilizare bazat pe task-ul sau compatibilitatea cu pipeline a modelului. Citește metadatele checkpoint-ului din clasa de configurare ca exemplele să folosească ID-uri reale de model. Argumentul `checkpoint` suprascrie checkpoint-ul dedus din docstring-ul clasei de config. Setează `checkpoint` pe clasele de config sau când deducerea checkpoint-ului eșuează. Dacă vezi o eroare precum `"Config not found for <model_name>"`, adaugă o intrare în `HARDCODED_CONFIG_FOR_MODELS` din `auto_docstring.py`.
|
||||
|
||||
7. Pentru metode precum `forward`, decoratorul scrie secțiunea `Returns` din tipul de returnare al metodei. Când tipul de returnare este o subclasă [`~transformers.utils.ModelOutput`], `@auto_docstring` trage descrierile câmpurilor din docstring-ul acelei clase. Un bloc `Returns` personalizat în docstring-ul funcției are prioritate.
|
||||
|
||||
8. Pentru metodele din `UNROLL_KWARGS_METHODS` și clasele din `UNROLL_KWARGS_CLASSES`, decoratorul expandează `**kwargs` tipizat cu `Unpack[KwargsTypedDict]`. Fiecare cheie din `TypedDict` devine un parametru documentat.
|
||||
|
||||
Aceeași expandare se aplică metodelor `__call__` și `preprocess` pe subclasele [`BaseImageProcessor`] și [`ProcessorMixin`]. Tipurile de bază generice (`TextKwargs`, `ImagesKwargs`, `VideosKwargs`, `AudioKwargs`) sunt sărite. Doar subclasele specifice modelului sunt expandate.
|
||||
155
docs/source/ro/backbones.md
Normal file
155
docs/source/ro/backbones.md
Normal file
@@ -0,0 +1,155 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Backbone-uri
|
||||
|
||||
Task-urile de computer vision de nivel mai ridicat, cum ar fi detecția obiectelor sau segmentarea imaginilor, folosesc mai multe modele împreună ca să genereze o predicție. Un model separat este folosit pentru *backbone*, neck și head. Backbone-ul extrage feature-uri utile dintr-o imagine de intrare într-un feature map, neck-ul combină și procesează feature map-urile, iar head-ul le folosește ca să facă o predicție.
|
||||
|
||||
<div class="flex justify-center">
|
||||
<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/Backbone.png"/>
|
||||
</div>
|
||||
|
||||
Încarcă un backbone cu [`~PreTrainedConfig.from_pretrained`] și folosește parametrul `out_indices` ca să determini din ce layer, dat prin index, să extragi un feature map.
|
||||
|
||||
```py
|
||||
from transformers import AutoBackbone
|
||||
|
||||
model = AutoBackbone.from_pretrained("microsoft/swin-tiny-patch4-window7-224", out_indices=(1,))
|
||||
```
|
||||
|
||||
Acest ghid descrie clasa backbone, backbone-urile din biblioteca [timm](https://hf.co/docs/timm/index) și cum să extragi feature-uri cu ele.
|
||||
|
||||
## Clasele de backbone
|
||||
|
||||
Există două clase de backbone.
|
||||
|
||||
- [`~transformers.utils.BackboneMixin`] îți permite să încarci un backbone și include funcții pentru extragerea feature map-urilor și a indicilor din config.
|
||||
- [`~transformers.utils.BackboneConfigMixin`] îți permite să setezi, aliniezi și verifici feature map-ul și indicii dintr-o configurație de backbone.
|
||||
|
||||
Consultă documentația API [Backbone] ca să verifici ce modele suportă un backbone.
|
||||
|
||||
Există două moduri de a încărca un backbone Transformers: [`AutoBackbone`] și o clasă de backbone specifică modelului.
|
||||
|
||||
<hfoptions id="backbone-classes">
|
||||
<hfoption id="AutoBackbone">
|
||||
|
||||
API-ul [AutoClass] încarcă automat un model de viziune preantrenat cu [`~PreTrainedConfig.from_pretrained`] ca backbone dacă este suportat.
|
||||
|
||||
Setează parametrul `out_indices` la layer-ul din care vrei să obții feature map-ul. Dacă știi numele layer-ului, poți folosi și `out_features`. Acești parametri pot fi folosiți alternativ, dar dacă îi folosești pe amândoi, asigură-te că se referă la același layer.
|
||||
|
||||
Când `out_indices` sau `out_features` nu este folosit, backbone-ul returnează feature map-ul din ultimul layer. Codul de exemplu de mai jos folosește `out_indices=(1,)` ca să obțină feature map-ul din primul layer.
|
||||
|
||||
<div class="flex justify-center">
|
||||
<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/Swin%20Stage%201.png"/>
|
||||
</div>
|
||||
|
||||
```py
|
||||
from transformers import AutoImageProcessor, AutoBackbone
|
||||
|
||||
model = AutoBackbone.from_pretrained("microsoft/swin-tiny-patch4-window7-224", out_indices=(1,))
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="model-specific backbone">
|
||||
|
||||
Când știi că un model suportă un backbone, poți încărca backbone-ul și neck-ul direct în configurația modelului. Pasează configurația modelului ca să îl inițializezi pentru un task.
|
||||
|
||||
Exemplul de mai jos încarcă un backbone [ResNet] și neck pentru un head de segmentare a instanțelor [MaskFormer].
|
||||
|
||||
Reține că inițializarea din config creează modelul cu weights aleatorii. Dacă vrei să încarci un model preantrenat, folosește API-ul `from_pretrained`.
|
||||
|
||||
```py
|
||||
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation
|
||||
|
||||
backbone_config = AutoConfig.from_pretrained("microsoft/resnet-50")
|
||||
config = MaskFormerConfig(backbone_config=backbone_config)
|
||||
model = MaskFormerForInstanceSegmentation(config)
|
||||
```
|
||||
|
||||
O altă opțiune este să încarci configurația backbone-ului separat și apoi să o pasezi la `backbone_config` din configurația modelului.
|
||||
|
||||
```py
|
||||
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation, ResNetConfig
|
||||
|
||||
# instanțiază configurația backbone-ului
|
||||
backbone_config = ResNetConfig()
|
||||
# încarcă backbone-ul în model
|
||||
config = MaskFormerConfig(backbone_config=backbone_config)
|
||||
# atașează backbone-ul la head-ul modelului
|
||||
model = MaskFormerForInstanceSegmentation(config)
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
## Backbone-uri timm
|
||||
|
||||
[timm] este o colecție de modele de viziune pentru antrenare și inferență. Transformers suportă modelele timm ca backbone-uri cu clasele [`TimmBackbone`] și [`TimmBackboneConfig`]. Setează checkpoint-ul de backbone necesar în `backbone` ca să creezi un model cu backbone timm cu weights inițializate aleatoriu.
|
||||
|
||||
```py
|
||||
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation
|
||||
|
||||
backbone_config = TimmBackboneConfig(backbone="resnet50", out_indices=[-1])
|
||||
config = MaskFormerConfig(backbone_config=backbone_config)
|
||||
model = MaskFormerForInstanceSegmentation(config)
|
||||
```
|
||||
|
||||
Poți și să apelezi explicit clasa [`TimmBackboneConfig`] ca să încarci și să creezi un backbone timm preantrenat.
|
||||
|
||||
```py
|
||||
from transformers import TimmBackboneConfig
|
||||
|
||||
backbone_config = TimmBackboneConfig("resnet50")
|
||||
```
|
||||
|
||||
Pasează configurația backbone-ului la configurația modelului și instanțiază head-ul modelului, [`MaskFormerForInstanceSegmentation`], cu backbone-ul.
|
||||
|
||||
```py
|
||||
from transformers import MaskFormerConfig, MaskFormerForInstanceSegmentation
|
||||
|
||||
config = MaskFormerConfig(backbone_config=backbone_config)
|
||||
model = MaskFormerForInstanceSegmentation(config)
|
||||
```
|
||||
|
||||
## Extragerea feature-urilor
|
||||
|
||||
Backbone-ul este folosit ca să extragă feature-uri din imagini. Pasează o imagine prin backbone ca să obții feature map-urile.
|
||||
|
||||
Încarcă și preprocesează o imagine și pasează-o backbone-ului. Exemplul de mai jos extrage feature map-urile din primul layer.
|
||||
|
||||
```py
|
||||
from transformers import AutoImageProcessor, AutoBackbone
|
||||
import torch
|
||||
from PIL import Image
|
||||
import requests
|
||||
|
||||
model = AutoBackbone.from_pretrained("microsoft/swin-tiny-patch4-window7-224", out_indices=(1,))
|
||||
processor = AutoImageProcessor.from_pretrained("microsoft/swin-tiny-patch4-window7-224")
|
||||
|
||||
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
|
||||
image = Image.open(requests.get(url, stream=True).raw)
|
||||
|
||||
inputs = processor(image, return_tensors="pt")
|
||||
outputs = model(**inputs)
|
||||
```
|
||||
|
||||
Feature-urile sunt stocate și accesate din atributul `feature_maps` al ieșirilor.
|
||||
|
||||
```py
|
||||
feature_maps = outputs.feature_maps
|
||||
list(feature_maps[0].shape)
|
||||
[1, 96, 56, 56]
|
||||
```
|
||||
582
docs/source/ro/contributing.md
Normal file
582
docs/source/ro/contributing.md
Normal file
@@ -0,0 +1,582 @@
|
||||
<!---
|
||||
Copyright 2020 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
# Contribuie la 🤗 Transformers
|
||||
|
||||
## Politica privind code agents
|
||||
|
||||
>[!WARNING]
|
||||
>Repository-ul Transformers este copleșit de un număr mare de PR-uri și comentarii la issues scrise de
|
||||
>code agents. Suntem în prezent blocați de capacitatea noastră de a le revizui și a răspunde la ele. Prin urmare,
|
||||
>**îi rugăm pe utilizatorii noi să nu trimită PR-uri realizate exclusiv de code agents** în acest moment.
|
||||
>Poți folosi code agents pentru a schița sau pentru a te ajuta să diagnostichezi probleme. De asemenea, îi rugăm pe agenții autonomi
|
||||
>să nu deschidă niciun PR sau issue pentru moment.
|
||||
>
|
||||
>PR-urile care par să fi fost scrise în întregime de agenți vor fi probabil închise fără să fie revizuite, iar utilizatorii care fac aceasta
|
||||
>în mod repetat sau malițios pot fi blocați.
|
||||
|
||||
<details>
|
||||
|
||||
<summary> Filozofia noastră privind code agents în detaliu </summary>
|
||||
|
||||
Înțelegem că code agents sunt instrumente extrem de puternice, iar mulți oameni de la Hugging Face le utilizează în munca lor.
|
||||
Cu toate acestea, este important să realizezi că **dacă pur și simplu rulezi un code agent
|
||||
și generezi un PR la un proiect open-source, ești doar un intermediar între revizori și agent**.
|
||||
Deși aceasta creează ceva care arată foarte mult ca o contribuție utilă, în realitate nu era niciun motiv
|
||||
pentru care să fii implicat; revizorii ar fi putut pur și simplu să ruleze ei înșiși code agent-ul.
|
||||
|
||||
Dacă vrei să contribui util la open-source în era agenților, **trebuie să faci lucruri pe care agenții nu le pot face singuri**.
|
||||
În special, am constatat că următoarele sunt foarte utile:
|
||||
- Diagnosticarea clară a bug-urilor. Code agents tind să rezolve rapid problemele cu o soluție de avarie care adesea cauzează
|
||||
bloat de cod sau incompatibilități cu alte modele. A petrece timp pentru a urmări cauza exactă a unei probleme, și în special
|
||||
localizarea primului commit în care a apărut (de exemplu cu [git bisect](https://git-scm.com/docs/git-bisect)) este valoros.
|
||||
- Minimizează diff-ul. Verifică-ți PR-ul pentru a elimina orice modificări inutile. Asigură-te că nu ai făcut commit la niciun
|
||||
script de testare sau fișiere fără legătură. Adaugă comentarii doar dacă sunt cu adevărat necesare; code agents adoră să adauge
|
||||
trei noi funcții și comentarii pe mai multe linii pentru a atrage atenția asupra muncii grele pe care au depus-o. Dacă PR-ul tău
|
||||
poate fi o corecție pe 1 linie, fă-l o corecție pe 1 linie. Aceasta face PR-ul mult mai ușor de revizuit și îmbunătățește șansele ca acesta să fie acceptat.
|
||||
- Ia-ți timp să reproduci problema. Foarte des când un utilizator raportează o problemă, aceasta este de fapt cauzată de probleme
|
||||
de mediu pe mașina sa, sau diagnostichează greșit problema și sugerează o soluție invalidă. Mulți code agents au prea multă
|
||||
încredere în comentariile utilizatorilor, ceea ce rezultă în soluții proaste, uneori pentru probleme care
|
||||
nu există! Scrierea unui script simplu de reproducere și rularea lui pentru a te asigura că vezi problema este valoroasă.
|
||||
- Compară cu alte modele. Repository-ul Transformers este foarte mare, iar multe modele fac lucruri similare. Când
|
||||
corectezi un bug, este valoros să verifici dacă bug-ul există și în alte modele. Dacă PR-ul tău spune
|
||||
"rezolvat folosind aceeași abordare ca (alt model)", cu un link la codul relevant, aceasta este foarte utilă pentru maintaineri,
|
||||
deoarece ne spune că corectura este probabil corectă și compatibilă cu restul codebase-ului. Code agents privesc adesea
|
||||
codul "în mod restrâns" și fac o corecție care determină modelele să divergă de la restul codebase-ului.
|
||||
- Evită PR-urile mici sau de tip "busywork". În trecut le acceptam, dar dat fiind actualul aflux, pur și simplu nu
|
||||
avem timp pentru mici modificări de stil sau corectarea typo-urilor din comentarii. Poți oferi valoare dincolo de un code
|
||||
agent pur și simplu prin a avea bun gust în privința a ceea ce este cu adevărat important.
|
||||
- Verifică testele local și în CI. Înainte de a deschide un PR, rulează `make fix-repo` și folosește `utils/tests_fetcher.py` pentru
|
||||
a vedea o listă de teste care acoperă fișierele pe care le-ai modificat în branch-ul PR-ului tău. Rulează acele teste local și asigură-te
|
||||
că trec înainte de a deschide un PR. După ce deschizi PR-ul, verifică că CI-ul este verde și rezolvă orice probleme înainte
|
||||
de a contacta pe cineva pentru revizuire! Aceasta reduce mult spam-ul de notificări, ceea ce menține maintainerii sănătoși.
|
||||
|
||||
Te rugăm să ții cont că aceasta este o eră interesantă, în schimbare rapidă, dar provocatoare pentru dezvoltarea open-source, și într-adevăr
|
||||
pentru industria software în ansamblu. Vom actualiza probabil rapid aceste ghiduri pe măsură ce învățăm mai multe despre
|
||||
gestionarea eficientă a code agents. Ai răbdare cu noi dacă revizuirile sunt mai lente decât de obicei, sau dacă unele
|
||||
PR-uri sunt închise fără revizuire!
|
||||
|
||||
</details>
|
||||
|
||||
## Bine ai venit în comunitatea 🤗 Transformers!
|
||||
|
||||
Toată lumea este binevenită să contribuie, iar noi apreciem contribuția fiecăruia. Contribuțiile de cod
|
||||
nu sunt singura modalitate de a ajuta comunitatea. Răspunsurile la întrebări, ajutorarea altora
|
||||
și îmbunătățirea documentației sunt de asemenea valori imense.
|
||||
|
||||
Ne ajutați și dacă răspândiți vestea! Menționați biblioteca în postările de blog
|
||||
despre proiectele extraordinare pe care le-a făcut posibile, postați pe Twitter de fiecare dată când v-a
|
||||
ajutat, sau pur și simplu acordați o ⭐️ repository-ului pentru a spune mulțumesc.
|
||||
|
||||
Indiferent cum alegi să contribui, te rugăm să fii atent și să respecți
|
||||
[codul nostru de conduită](https://github.com/huggingface/transformers/blob/main/CODE_OF_CONDUCT.md).
|
||||
|
||||
**Acest ghid a fost puternic inspirat de minunatul [ghid scikit-learn pentru contribuții](https://github.com/scikit-learn/scikit-learn/blob/main/CONTRIBUTING.md).**
|
||||
|
||||
## Modalități de a contribui
|
||||
|
||||
Există mai multe moduri în care poți contribui la 🤗 Transformers:
|
||||
|
||||
* Remediază problemele existente în codul curent.
|
||||
* Trimite issues legate de bug-uri sau funcții noi dorite.
|
||||
* Implementează modele noi.
|
||||
* Contribuie la exemple sau la documentație.
|
||||
|
||||
Dacă nu știi de unde să începi, există o listă specială [Good First
|
||||
Issue](https://github.com/huggingface/transformers/contribute). Aceasta îți va oferi o listă de
|
||||
issues deschise prietenoase pentru începători și te va ajuta să începi să contribui la open-source. Cel mai bun mod de a face aceasta este să deschizi un Pull Request și să îl legi de issue-ul la care vrei să lucrezi. Încercăm să acordăm prioritate PR-urilor deschise deoarece putem urmări cu ușurință progresul corecturii, iar dacă contribuitorul nu mai are timp, altcineva poate prelua PR-ul.
|
||||
|
||||
Pentru ceva puțin mai provocator, poți arunca și o privire la lista [Good Second Issue](https://github.com/huggingface/transformers/labels/Good%20Second%20Issue). În general, dacă simți că știi ce faci, mergi înainte și te vom ajuta să ajungi acolo! 🚀
|
||||
|
||||
> Toate contribuțiile sunt la fel de valoroase pentru comunitate. 🥰
|
||||
|
||||
## Remedierea problemelor existente
|
||||
|
||||
Dacă observi o problemă în codul existent și ai o soluție în minte, nu ezita să [începi să contribui](#crearea-unui-pull-request) și deschide un Pull Request!
|
||||
|
||||
## Trimiterea unui issue legat de bug sau a unei cereri de funcție
|
||||
|
||||
Fă tot posibilul să urmezi aceste ghiduri când trimiți un issue legat de bug sau o cerere de funcție. Aceasta ne va face mai ușor să revenim la tine rapid și cu feedback bun.
|
||||
|
||||
### Ai găsit un bug?
|
||||
|
||||
Biblioteca 🤗 Transformers este robustă și fiabilă datorită utilizatorilor care raportează problemele pe care le întâmpină.
|
||||
|
||||
Înainte de a raporta un issue, am aprecia cu adevărat dacă ai putea **să te asiguri că bug-ul nu a fost deja raportat** (folosește bara de căutare pe GitHub la Issues). Issue-ul tău ar trebui să fie legat și de bug-uri din bibliotecă în sine, nu din codul tău. Dacă nu ești sigur dacă bug-ul este în codul tău sau în bibliotecă, te rugăm să întrebi mai întâi în [forum](https://discuss.huggingface.co/) sau pe [Discord-ul](https://discord.com/invite/hugging-face-879548962464493619) nostru. Aceasta ne ajută să răspundem mai rapid la problemele legate de bibliotecă față de întrebările generale.
|
||||
|
||||
> [!TIP]
|
||||
> Avem un [bot de documentație](https://huggingface.co/spaces/huggingchat/hf-docs-chat) și te încurajăm să adresezi toate întrebările acolo. Există întotdeauna posibilitatea ca bug-ul tău să poată fi rezolvat cu un simplu flag 👾🔫
|
||||
|
||||
Odată ce ai confirmat că bug-ul nu a fost deja raportat, te rugăm să incluzi următoarele informații în issue-ul tău pentru ca să îl putem rezolva rapid:
|
||||
|
||||
* **Tipul și versiunea OS**-ului tău, și versiunile **Python** și **PyTorch** când este cazul.
|
||||
* Un snippet de cod scurt, independent, care ne permite să reproducem bug-ul în
|
||||
mai puțin de 30s.
|
||||
* Traceback-ul *complet* dacă este aruncată o excepție.
|
||||
* Atașează orice alte informații suplimentare, precum screenshots, pe care crezi că ar putea ajuta.
|
||||
|
||||
Pentru a obține automat versiunile OS și software, rulează următoarea comandă:
|
||||
|
||||
```bash
|
||||
transformers env
|
||||
```
|
||||
|
||||
Poți rula, de asemenea, aceeași comandă din rădăcina repository-ului:
|
||||
|
||||
```bash
|
||||
python src/transformers/commands/transformers_cli.py env
|
||||
```
|
||||
|
||||
### Vrei o funcție nouă?
|
||||
|
||||
Dacă există o funcție nouă pe care ai dori să o vezi în 🤗 Transformers, te rugăm să deschizi un issue și să descrii:
|
||||
|
||||
1. Care este *motivația* din spatele acestei funcții? Este legată de o problemă sau frustrare cu biblioteca? Este o funcție legată de ceva de care ai nevoie pentru un proiect? Este ceva la care ai lucrat și crezi că ar putea beneficia comunitatea?
|
||||
|
||||
Indiferent ce este, am dori să aflăm despre aceasta!
|
||||
|
||||
2. Descrie funcția solicitată cu cât mai multe detalii posibil. Cu cât poți să ne spui mai multe despre aceasta, cu atât mai bine te putem ajuta.
|
||||
3. Furnizează un *snippet de cod* care demonstrează utilizarea funcției.
|
||||
4. Dacă funcția este legată de un articol, te rugăm să incluzi un link.
|
||||
|
||||
Dacă issue-ul tău este bine scris, suntem deja la 80% din drum până la momentul în care îl creezi.
|
||||
|
||||
Am adăugat [template-uri](https://github.com/huggingface/transformers/tree/main/templates) pentru a te ajuta să începi cu issue-ul tău.
|
||||
|
||||
## Vrei să implementezi un model nou?
|
||||
|
||||
Modele noi sunt lansate constant și dacă vrei să implementezi un model nou, te rugăm să furnizezi următoarele informații:
|
||||
|
||||
* O scurtă descriere a modelului și un link la articol.
|
||||
* Link la implementare dacă este open-source.
|
||||
* Link la model weights dacă sunt disponibile.
|
||||
|
||||
Dacă ești dispus să contribui modelul tu însuți, anunță-ne pentru ca să te putem ajuta să îl adaugi la 🤗 Transformers!
|
||||
|
||||
Avem un ghid tehnic pentru [cum să adaugi un model la 🤗 Transformers](https://huggingface.co/docs/transformers/modular_transformers).
|
||||
|
||||
### Lista de verificare pentru contribuții de modele viziune-limbaj
|
||||
|
||||
Dacă vrei să contribui cu un **model viziune-limbaj** (sau orice model multimodal care procesează imagini/videoclipuri), te rugăm să urmezi această listă de verificare. Maintainerii o vor folosi pentru a revizui PR-ul tău, iar completarea acestor pași va crește semnificativ probabilitatea ca PR-ul tău să fie merged rapid.
|
||||
|
||||
**Listă de verificare obligatorie pentru toate contribuțiile de modele viziune-limbaj:**
|
||||
|
||||
☐ **1. Implementează un fișier modular**
|
||||
|
||||
Toate modelele noi ar trebui să folosească pattern-ul de arhitectură modulară. Creează un fișier `modular_<model_name>.py` folosind convertorul de modele modular:
|
||||
|
||||
- Folosește CLI-ul, [`transformers add-new-model-like`](https://github.com/huggingface/transformers/blob/main/src/transformers/cli/add_new_model_like.py) pentru a genera un schelet modular și a începe
|
||||
- Tot codul ar trebui să fie în fișierul modular dacă este posibil. Modelarea trebuie să fie în acesta, este preferat ca și configurația să fie în acesta. [Ghidul modular](https://huggingface.co/docs/transformers/modular_transformers#implementing-a-modular-file) arată o modalitate rapidă de a configura un fișier modular.
|
||||
- Reutilizează pattern-urile existente din modele similare pe cât posibil
|
||||
- Poți face modelul compatibil cu motoare de inferență precum vLLM sau SGLang și activa integrarea fără efort. Consultă cerințele specifice pentru implementarea modelului în ["Transformers modeling backend"](https://huggingface.co/docs/transformers/transformers_as_backend#multimodal-models)
|
||||
|
||||
Pentru a verifica că fișierul tău modular este corect, rulează:
|
||||
|
||||
```bash
|
||||
python utils/modular_model_converter.py <model_name>
|
||||
```
|
||||
|
||||
Aceasta va genera fișierele separate (`modeling_*.py`, `configuration_*.py`, etc.) din fișierul tău modular. CI-ul va impune că aceste fișiere generate corespund fișierului tău modular.
|
||||
|
||||
☐ **2. Adaugă procesoare de imagini (pentru modele de imagini)**
|
||||
|
||||
Dacă modelul tău procesează imagini, implementează atât un procesor suportat de torchvision (implicit, accelerat GPU) cât și un procesor suportat de PIL (alternativa):
|
||||
|
||||
- Procesorul backend torchvision (`<Model>ImageProcessor`) moștenește din `TorchvisionBackend` și se află în `image_processing_<model>.py`
|
||||
- Procesorul backend PIL (`<Model>ImageProcessorPil`) moștenește din `PilBackend` și se află în `image_processing_pil_<model>.py`
|
||||
- Ambele sunt importate din `image_processing_backends`; clasa PIL kwargs este definită în fișierul torchvision și importată de fișierul PIL
|
||||
- Consultă ghidul detaliat în [IMAGE_PROCESSOR_REFACTORING_GUIDE.md](https://github.com/huggingface/transformers/blob/main/IMAGE_PROCESSOR_REFACTORING_GUIDE.md)
|
||||
- Exemple: `CLIPImageProcessor` / `CLIPImageProcessorPil`, `DonutImageProcessor` / `DonutImageProcessorPil`
|
||||
|
||||
☐ **3. Creează un script de conversie a weights**
|
||||
|
||||
Adaugă un script `convert_<model_name>_to_hf.py` care convertește weights originale ale modelului în formatul HuggingFace:
|
||||
|
||||
- Scriptul ar trebui să gestioneze încărcarea checkpoint-ului, maparea cheilor și salvarea în format HF
|
||||
- Include exemple de utilizare și documentație în script
|
||||
- Exemple: [`convert_llava_onevision_weights_to_hf.py`](https://github.com/huggingface/transformers/blob/main/src/transformers/models/llava_onevision/convert_llava_onevision_weights_to_hf.py), [`convert_idefics2_weights_to_hf.py`](https://github.com/huggingface/transformers/blob/main/src/transformers/models/idefics2/convert_idefics2_weights_to_hf.py)
|
||||
|
||||
☐ **4. Adaugă teste de integrare cu potrivire exactă a output-urilor**
|
||||
|
||||
Cel puțin, adaugă o clasă `IntegrationTest` care testează generarea end-to-end (procesare și modelare) cu potrivire **exactă** a output-urilor:
|
||||
|
||||
- Pentru modele generative: testează că textul generat corespunde exact output-ului așteptat
|
||||
- Pentru modele non-generative: testează că logit-urile de output corespund valorilor așteptate
|
||||
- Testele ar trebui să folosească checkpoint-uri reale (încarcă în 4-bit sau jumătate de precizie dacă checkpoint-ul este prea mare pentru CI runnerii noștri) și input-uri reale
|
||||
- Pattern exemplu:
|
||||
|
||||
```python
|
||||
class MyModelIntegrationTest(unittest.TestCase):
|
||||
@slow
|
||||
def test_model_integration(self):
|
||||
model = MyModelForConditionalGeneration.from_pretrained("org/model-name")
|
||||
processor = AutoProcessor.from_pretrained("org/model-name")
|
||||
|
||||
inputs = processor(images=image, text=prompt, return_tensors="pt")
|
||||
output = model.generate(**inputs, max_new_tokens=20)
|
||||
|
||||
EXPECTED_TEXT = "exact expected output"
|
||||
self.assertEqual(processor.decode(output[0]), EXPECTED_TEXT)
|
||||
```
|
||||
|
||||
Consultă `tests/models/llava_onevision/test_modeling_llava_onevision.py` pentru exemple complete.
|
||||
|
||||
☐ **5. Actualizează documentația**
|
||||
|
||||
Adaugă sau actualizează documentația modelului:
|
||||
|
||||
- Creează dacă CLI-ul nu a creat `docs/source/en/model_doc/<model_name>.md` cu exemple de utilizare
|
||||
- Include descrierea modelului, link la articol și utilizarea de bază cu `Pipeline` și `AutoModel`
|
||||
- Adaugă modelul la fișierele TOC corespunzătoare
|
||||
|
||||
☐ **6. Caută pattern-uri reutilizabile**
|
||||
|
||||
Biblioteca are 400+ modele cu multe pattern-uri stabilite:
|
||||
|
||||
- Caută modele similare (e.g., alte modele viziune-limbaj)
|
||||
- Reutilizează mecanisme de attention, implementări de layers și pattern-uri de procesare
|
||||
- Verifică modele precum LLaVA, Idefics2, Fuyu pentru pattern-uri viziune-limbaj
|
||||
- Folosește decoratorii furnizați precum (`auto_docstring`, `can_return_tuple`, `capture_outputs`, `merge_with_config_defaults` și `_can_record_outputs`) unde este relevant.
|
||||
- Nu reinventa roata
|
||||
|
||||
☐ **7. Rulează verificările de calitate și citește output-ul**
|
||||
|
||||
Înainte de a trimite PR-ul tău, instalează dependencies pentru calitate și rulează suita completă de verificări:
|
||||
|
||||
```bash
|
||||
pip install -e ".[quality]"
|
||||
make style
|
||||
```
|
||||
|
||||
**Important**: Ia-ți timp să citești output-ul `make style`. Acesta va:
|
||||
|
||||
- Linta și formata automat codul tău
|
||||
- Rula verificări de consistență (importuri, docstrings, etc.)
|
||||
- Afișa orice probleme rămase care necesită corecturi manuale
|
||||
|
||||
Toate verificările trebuie să treacă înainte ca PR-ul tău să poată fi merged.
|
||||
|
||||
**Dacă această listă de verificare este completă, PR-ul tău are o probabilitate foarte mare de a fi merged!** Urmarea acestor pași face munca maintainerilor mult mai ușoară și va reduce numărul de iterații de revizuire, ducând munca ta importantă acolo mai repede.
|
||||
|
||||
#### Listă de verificare copiabilă pentru maintaineri
|
||||
|
||||
Iată o versiune condensată pe care maintainerii o pot copia în PR-uri:
|
||||
|
||||
```markdown
|
||||
## Multimodal Model Addition Checklist
|
||||
|
||||
Please ensure your PR completes all following items. See the [full checklist](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md#vision-language-model-contribution-checklist) for details.
|
||||
|
||||
- [ ] **Modular file**: `modular_<model_name>.py` implemented and verified with `python utils/modular_model_converter.py <model_name>`
|
||||
- [ ] **Image processors**: Torchvision backend (`<Model>ImageProcessor` from `TorchvisionBackend`) and PIL backend (`<Model>ImageProcessorPil` from `PilBackend`) both implemented (see [IMAGE_PROCESSOR_REFACTORING_GUIDE.md](https://github.com/huggingface/transformers/blob/main/IMAGE_PROCESSOR_REFACTORING_GUIDE.md))
|
||||
- [ ] **Conversion script**: `convert_<model_name>_to_hf.py` added with usage examples
|
||||
- [ ] **Integration tests**: End-to-end tests with exact output matching (text or logits)
|
||||
- [ ] **Documentation**: Model docs added/updated in `docs/source/en/model_doc/`
|
||||
- [ ] **Pattern reuse**: Verified against similar models (LLaVA, Idefics2, etc.)
|
||||
- [ ] **Quality checks**: `make style` passes with no errors
|
||||
|
||||
```
|
||||
|
||||
## Vrei să adaugi documentație?
|
||||
|
||||
Căutăm mereu îmbunătățiri ale documentației care să o facă mai clară și mai exactă. Te rugăm să ne anunți cum poate fi îmbunătățită documentația, precum typo-uri și orice conținut care lipsește, este neclar sau inexact. Vom fi bucuroși să facem modificările sau să te ajutăm să faci o contribuție dacă ești interesat!
|
||||
|
||||
Pentru mai multe detalii despre cum să generezi, construiești și scrii documentația, aruncă o privire la [README-ul](https://github.com/huggingface/transformers/tree/main/docs) documentației.
|
||||
|
||||
## Programare cu AI agents
|
||||
|
||||
Acest repository păstrează configurația AI agent în `.ai/` și expune fișierele locale de agent prin symlinks.
|
||||
|
||||
Skills-urile pot fi expuse agenților rulând `make codex` sau `make claude`
|
||||
|
||||
Cursor citește `AGENTS.md` și citește skills-urile din căile Claude sau Codex, deci configurarea repository-ului
|
||||
pentru Claude sau Codex va funcționa pentru Claude.
|
||||
|
||||
## Crearea unui Pull Request
|
||||
|
||||
Înainte de a scrie orice cod, îți recomandăm cu tărie să cauți prin PR-urile sau issues existente pentru a te asigura că nimeni nu lucrează deja la același lucru. Dacă nu ești sigur, este întotdeauna o idee bună să deschizi un issue pentru a obține feedback.
|
||||
|
||||
Vei avea nevoie de competențe de bază în `git` pentru a contribui la
|
||||
🤗 Transformers. Deși `git` nu este cel mai ușor instrument de utilizat, are cel mai detaliat
|
||||
manual. Tastează `git --help` într-un shell și bucură-te! Dacă preferi cărțile, [Pro
|
||||
Git](https://git-scm.com/book/en/v2) este o referință foarte bună.
|
||||
|
||||
Vei avea nevoie de **[Python 3.9](https://github.com/huggingface/transformers/blob/main/setup.py#L449)** sau o versiune mai nouă pentru a contribui la 🤗 Transformers. Urmează pașii de mai jos pentru a începe să contribui:
|
||||
|
||||
1. Fă fork la [repository](https://github.com/huggingface/transformers) dând click pe butonul
|
||||
**[Fork](https://github.com/huggingface/transformers/fork)** pe pagina repository-ului. Aceasta creează o copie a codului
|
||||
sub contul tău de utilizator GitHub.
|
||||
|
||||
2. Clonează fork-ul pe discul tău local și adaugă repository-ul de bază ca remote:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:<your Github handle>/transformers.git
|
||||
cd transformers
|
||||
git remote add upstream https://github.com/huggingface/transformers.git
|
||||
```
|
||||
|
||||
3. Creează un nou branch pentru a-ți păstra modificările de dezvoltare:
|
||||
|
||||
```bash
|
||||
git checkout -b a-descriptive-name-for-my-changes
|
||||
```
|
||||
|
||||
🚨 **Nu** lucra pe branch-ul `main`!
|
||||
|
||||
4. Configurează un mediu de dezvoltare rulând următoarea comandă într-un virtual environment:
|
||||
|
||||
```bash
|
||||
pip install -e ".[dev]"
|
||||
```
|
||||
|
||||
Dacă 🤗 Transformers era deja instalat în virtual environment, elimină-l
|
||||
cu `pip uninstall transformers` înainte de a-l reinstala în modul editabil
|
||||
cu flag-ul `-e`.
|
||||
|
||||
În funcție de OS-ul tău, și deoarece numărul de dependencies opționale ale Transformers crește, ai putea întâmpina o eroare cu această comandă. În acest caz, instalează PyTorch și execută:
|
||||
|
||||
```bash
|
||||
pip install -e ".[quality]"
|
||||
```
|
||||
|
||||
ceea ce ar trebui să fie suficient pentru majoritatea cazurilor de utilizare.
|
||||
|
||||
5. Dezvoltă funcțiile în branch-ul tău.
|
||||
|
||||
Pe măsură ce lucrezi la codul tău, ar trebui să te asiguri că suita de teste
|
||||
trece. Rulează testele afectate de modificările tale astfel:
|
||||
|
||||
```bash
|
||||
pytest tests/<TEST_TO_RUN>.py
|
||||
```
|
||||
|
||||
Pentru mai multe informații despre teste, consultă
|
||||
ghidul [Testing](https://huggingface.co/docs/transformers/testing).
|
||||
|
||||
🤗 Transformers se bazează pe `black` și `ruff` pentru a formata codul sursă
|
||||
în mod consistent. După ce faci modificări, aplică corecturi automate de stil și verificări de cod
|
||||
care nu pot fi automatizate dintr-o singură mișcare cu:
|
||||
|
||||
```bash
|
||||
make style
|
||||
```
|
||||
|
||||
🤗 Transformers folosește și `ruff` și câteva scripturi personalizate pentru a verifica greșelile de codare. Controalele de
|
||||
calitate sunt rulate de CI, dar poți rula aceleași verificări cu:
|
||||
|
||||
```bash
|
||||
make check-repo
|
||||
```
|
||||
|
||||
Pentru a afla mai multe despre aceste verificări și cum să rezolvi orice probleme cu ele, consultă
|
||||
ghidul [Checks on a Pull Request](https://huggingface.co/docs/transformers/pr_checks).
|
||||
|
||||
Dacă modifici documente din directorul `docs/source`, asigură-te că documentația poate fi în continuare construită. Această verificare va rula și în CI când deschizi un pull request. Pentru a rula o verificare locală
|
||||
instalează [doc-builder-ul](https://github.com/huggingface/doc-builder).
|
||||
|
||||
```bash
|
||||
pip install ".[docs]"
|
||||
```
|
||||
|
||||
Rulează următoarea comandă din root-ul repository-ului:
|
||||
|
||||
```bash
|
||||
doc-builder build transformers docs/source/en --build_dir ~/tmp/test-build
|
||||
```
|
||||
|
||||
Aceasta va construi documentația în folderul `~/tmp/test-build` unde poți inspecta fișierele
|
||||
Markdown generate cu editorul tău preferat. Poți, de asemenea, previzualiza documentele pe GitHub când deschizi un pull request.
|
||||
|
||||
Dacă adaugi sau editezi exemple rulabile în documentele Markdown, marchează gardurile Python cu `runnable` sau
|
||||
`runnable:<label>` și rulează-le local cu `pytest`:
|
||||
|
||||
```bash
|
||||
pytest -q docs/source/en/my_page.md
|
||||
pytest -q docs/source/en/
|
||||
```
|
||||
|
||||
Pentru sintaxa completă rulabilă, inclusiv blocuri de continuare, `# pytest-decorator:` și
|
||||
`# doc-builder: hide`, consultă
|
||||
[ghidul doc-builder pentru blocuri de cod rulabile](https://github.com/huggingface/doc-builder/blob/main/docs/runnable-code-blocks.md).
|
||||
|
||||
Odată ce ești mulțumit de modificările tale, adaugă fișierele modificate cu `git add` și
|
||||
înregistrează modificările tale local cu `git commit`:
|
||||
|
||||
```bash
|
||||
git add modified_file.py
|
||||
git commit
|
||||
```
|
||||
|
||||
Te rugăm să îți amintești să scrii [mesaje de commit bune](https://chris.beams.io/posts/git-commit/)
|
||||
pentru a comunica clar modificările pe care le-ai făcut!
|
||||
|
||||
Pentru a menține copia ta a codului actualizată cu repository-ul original, dă rebase branch-ului tău pe `upstream/branch` *înainte* de a deschide un pull request sau dacă un maintainer cere asta:
|
||||
|
||||
```bash
|
||||
git fetch upstream
|
||||
git rebase upstream/main
|
||||
```
|
||||
|
||||
Trimite modificările tale pe branch-ul tău:
|
||||
|
||||
```bash
|
||||
git push -u origin a-descriptive-name-for-my-changes
|
||||
```
|
||||
|
||||
Dacă ai deschis deja un pull request, va trebui să forțezi push-ul cu flag-ul `--force`. Altfel, dacă pull request-ul nu a fost încă deschis, poți pur și simplu să trimiți modificările în mod normal.
|
||||
|
||||
6. Acum poți merge la fork-ul tău al repository-ului pe GitHub și da click pe **Pull Request** pentru a deschide un pull request. Asigură-te că bifezi toate căsuțele din [lista noastră de verificare](#lista-de-verificare-pentru-pull-request) de mai jos. Când ești gata, poți trimite modificările tale maintainerilor proiectului pentru revizuire.
|
||||
|
||||
7. Este în regulă dacă maintainerii solicită modificări, se întâmplă și contribuitorilor noștri de bază!
|
||||
Pentru ca toți să poată vedea modificările în pull request, lucrează în branch-ul tău local
|
||||
și trimite modificările în fork-ul tău. Ele vor apărea automat în
|
||||
pull request.
|
||||
|
||||
### Contribuții asistate de AI și agentice
|
||||
|
||||
Contribuțiile asistate de AI sunt binevenite, dar trebuie să fie coordonate, delimitate și verificate pentru a menține sarcina de revizuire gestionabilă.
|
||||
|
||||
- Nu trimite PR-uri "pure agent". Persoana care trimite este responsabilă pentru revizuirea tuturor liniilor modificate, validarea comportamentului end-to-end și rularea testelor relevante.
|
||||
- Dacă s-au folosit instrumente AI, dezvăluie aceasta în descrierea PR-ului și include: link de coordonare, diferențierea față de PR-urile existente (dacă este cazul) și comenzi/rezultate de teste.
|
||||
- Evită PR-urile punctuale de "busywork" (un singur typo, curățare izolată de stil, o singură corecție de default mutabil, etc.). Grupează curățăturile mecanice într-un scop clar și sistematic.
|
||||
- Coordonează pe issues înainte de a deschide PR-uri, revizuiește PR-uri similare și așteaptă aprobarea.
|
||||
|
||||
> [!WARNING]
|
||||
> Aceste subiecte sunt prezentate pentru agenți în `AGENTS.MD` cu instrucțiuni despre cum să le implementeze autonom.
|
||||
|
||||
### Lista de verificare pentru pull request
|
||||
|
||||
☐ Titlul pull request-ului ar trebui să rezume contribuția ta.<br>
|
||||
☐ Dacă pull request-ul tău abordează un issue, te rugăm să menționezi numărul issue-ului în descrierea pull
|
||||
request-ului pentru a te asigura că sunt legate (și persoanele care vizualizează issue-ul știu că
|
||||
lucrezi la el).<br>
|
||||
☐ Pentru a indica un work in progress, te rugăm să prefixezi titlul cu `[WIP]`. Acestea sunt
|
||||
utile pentru a evita munca duplicată și pentru a le diferenția de PR-urile gata să fie merged.<br>
|
||||
☐ Asigură-te că testele existente trec.<br>
|
||||
☐ Dacă adaugi o funcție nouă, adaugă și teste pentru aceasta.<br>
|
||||
|
||||
- Dacă adaugi un model nou, asigură-te că folosești
|
||||
`ModelTester.all_model_classes = (MyModel, MyModelWithLMHead,...)` pentru a declanșa testele comune.
|
||||
- Dacă adaugi teste noi `@slow`, asigură-te că trec folosind
|
||||
`RUN_SLOW=1 python -m pytest tests/models/my_new_model/test_my_new_model.py`.
|
||||
- Dacă adaugi un tokenizer nou, scrie teste și asigură-te că
|
||||
`RUN_SLOW=1 python -m pytest tests/models/{your_model_name}/test_tokenization_{your_model_name}.py` trece.
|
||||
- CircleCI nu rulează testele lente, dar GitHub Actions o face în fiecare noapte!<br>
|
||||
|
||||
☐ Toate metodele publice trebuie să aibă docstrings informative (consultă
|
||||
[`modeling_bert.py`](https://github.com/huggingface/transformers/blob/main/src/transformers/models/bert/modeling_bert.py)
|
||||
pentru un exemplu).<br>
|
||||
☐ Deoarece repository-ul crește rapid, nu adăuga imagini, videoclipuri și alte
|
||||
fișiere non-text care vor îngreuna semnificativ repository-ul. În schimb, folosește un repository Hub
|
||||
precum [`hf-internal-testing`](https://huggingface.co/hf-internal-testing)
|
||||
pentru a găzdui aceste fișiere și a le referencia prin URL. Îți recomandăm să plasezi imaginile legate de documentație în următorul repository:
|
||||
[huggingface/documentation-images](https://huggingface.co/datasets/huggingface/documentation-images).
|
||||
Poți deschide un PR pe acest repository de dataset și cere unui membru Hugging Face să îl îmbine.
|
||||
|
||||
Pentru mai multe informații despre verificările rulate pe un pull request, aruncă o privire la ghidul nostru [Checks on a Pull Request](https://huggingface.co/docs/transformers/pr_checks).
|
||||
|
||||
### Teste
|
||||
|
||||
O suită extinsă de teste este inclusă pentru a testa comportamentul bibliotecii și mai multe exemple. Testele de bibliotecă se găsesc în
|
||||
folder-ul [tests](https://github.com/huggingface/transformers/tree/main/tests) și testele de exemple în
|
||||
folder-ul [examples](https://github.com/huggingface/transformers/tree/main/examples).
|
||||
|
||||
Preferăm `pytest` și `pytest-xdist` deoarece este mai rapid. Din root-ul
|
||||
repository-ului, specifică un *path către un subfolder sau un fișier de test* pentru a rula testul:
|
||||
|
||||
```bash
|
||||
python -m pytest -n auto --dist=loadfile -s -v ./tests/models/my_new_model
|
||||
```
|
||||
|
||||
Similar, pentru directorul `examples`, specifică o *cale către un subfolder sau fișier de test* pentru a rula testul. De exemplu, următoarea comandă testează subfolderul de clasificare text din directorul PyTorch `examples`:
|
||||
|
||||
```bash
|
||||
pip install -r examples/xxx/requirements.txt # necesar doar prima dată
|
||||
python -m pytest -n auto --dist=loadfile -s -v ./examples/pytorch/text-classification
|
||||
```
|
||||
|
||||
De fapt, acesta este modul în care comenzile noastre `make test` și `make test-examples` sunt implementate (fără a include `pip install`)!
|
||||
|
||||
Poți, de asemenea, să specifici un set mai mic de teste pentru a testa doar funcția la care lucrezi.
|
||||
|
||||
În mod implicit, testele lente sunt omise, dar poți seta variabila de mediu `RUN_SLOW` la
|
||||
`yes` pentru a le rula. Aceasta va descărca mulți gigabytes de modele, deci asigură-te că
|
||||
ai suficient spațiu pe disc, o conexiune bună la internet sau multă răbdare!
|
||||
|
||||
<Tip warning={true}>
|
||||
|
||||
Ține minte să specifici un *path către un subfolder sau un fișier de test* pentru a rula testul. Altfel, vei rula toate testele din folderul `tests` sau `examples`, ceea ce va dura foarte mult timp!
|
||||
|
||||
</Tip>
|
||||
|
||||
```bash
|
||||
RUN_SLOW=yes python -m pytest -n auto --dist=loadfile -s -v ./tests/models/my_new_model
|
||||
RUN_SLOW=yes python -m pytest -n auto --dist=loadfile -s -v ./examples/pytorch/text-classification
|
||||
```
|
||||
|
||||
Ca și testele lente, există și alte variabile de mediu disponibile care nu sunt activate implicit în timpul testării:
|
||||
|
||||
- `RUN_CUSTOM_TOKENIZERS`: Activează testele pentru tokenizere personalizate.
|
||||
|
||||
Mai multe variabile de mediu și informații suplimentare se găsesc în [testing_utils.py](https://github.com/huggingface/transformers/blob/main/src/transformers/testing_utils.py).
|
||||
|
||||
🤗 Transformers folosește `pytest` doar ca runner de teste. Nu folosește nicio funcție specifică
|
||||
`pytest` în suita de teste în sine.
|
||||
|
||||
Aceasta înseamnă că `unittest` este suportat în totalitate. Iată cum să rulezi teste cu
|
||||
`unittest`:
|
||||
|
||||
```bash
|
||||
python -m unittest discover -s tests -t . -v
|
||||
python -m unittest discover -s examples -t examples -v
|
||||
```
|
||||
|
||||
### Ghid de stil
|
||||
|
||||
Pentru documentstrings, 🤗 Transformers urmează [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html).
|
||||
Consultă [ghidul nostru de scriere a documentației](https://github.com/huggingface/transformers/tree/main/docs#writing-documentation---specification)
|
||||
pentru mai multe informații.
|
||||
|
||||
### Development pe Windows
|
||||
|
||||
Pe Windows (cu excepția cazului în care lucrezi în [Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/) sau WSL), trebuie să configurezi git pentru a transforma terminările de linie Windows `CRLF` în terminările de linie Linux `LF`:
|
||||
|
||||
```bash
|
||||
git config core.autocrlf input
|
||||
```
|
||||
|
||||
O modalitate de a rula comanda `make` pe Windows este cu MSYS2:
|
||||
|
||||
1. [Descarcă MSYS2](https://www.msys2.org/), și presupunem că este instalat în `C:\msys64`.
|
||||
2. Deschide linia de comandă `C:\msys64\msys2.exe` (ar trebui să fie disponibilă din meniul **Start**).
|
||||
3. Rulează în shell: `pacman -Syu` și instalează `make` cu `pacman -S make`.
|
||||
4. Adaugă `C:\msys64\usr\bin` la variabila de mediu PATH.
|
||||
|
||||
Poți acum folosi `make` din orice terminal (PowerShell, cmd.exe, etc.)! 🎉
|
||||
|
||||
### Sincronizarea unui repository fork cu upstream main (repository-ul Hugging Face)
|
||||
|
||||
Când actualizezi branch-ul main al unui repository fork, te rugăm să urmezi acești pași pentru a evita notificarea repository-ului upstream care adaugă note de referință la fiecare PR upstream și trimite notificări inutile developerilor implicați în aceste PR-uri.
|
||||
|
||||
1. Când este posibil, evită sincronizarea cu upstream-ul prin folosirea unui branch și PR pe repository-ul fork. În schimb, dă merge direct în branch-ul main al fork-ului.
|
||||
2. Dacă un PR este absolut necesar, folosește pașii următori după ce faci checkout pe branch-ul tău:
|
||||
|
||||
```bash
|
||||
git checkout -b your-branch-for-syncing
|
||||
git pull --squash --no-commit upstream main
|
||||
git commit -m '<mesajul tău fără referințe Github>'
|
||||
git push --set-upstream origin your-branch-for-syncing
|
||||
```
|
||||
297
docs/source/ro/custom_models.md
Normal file
297
docs/source/ro/custom_models.md
Normal file
@@ -0,0 +1,297 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Personalizarea modelelor
|
||||
|
||||
Modelele Transformers sunt concepute pentru a fi personalizabile. Codul unui model este complet conținut în subfolderul [model](https://github.com/huggingface/transformers/tree/main/src/transformers/models) al repository-ului Transformers. Fiecare folder conține un fișier `modeling.py` și un fișier `configuration.py`. Copiază aceste fișiere pentru a începe personalizarea unui model.
|
||||
|
||||
> [!TIP]
|
||||
> Poate fi mai ușor să începi de la zero dacă creezi un model complet nou. Pentru modele similare cu unul existent în Transformers, este mai rapid să reutilizezi sau să subclasezi aceeași configurație și clasă de model.
|
||||
|
||||
Acest ghid îți va arăta cum să personalizezi un model ResNet, să activezi suportul [AutoClass](./models#autoclass) și să-l partajezi pe Hub.
|
||||
|
||||
## Configurație
|
||||
|
||||
O configurație, furnizată de clasa de bază [`PreTrainedConfig`], conține toate informațiile necesare pentru a construi un model. Acesta este locul unde vei configura atributele modelului ResNet personalizat. Atribute diferite oferă tipuri diferite de modele ResNet.
|
||||
|
||||
Regulile principale pentru personalizarea unei configurații sunt:
|
||||
|
||||
1. O configurație personalizată trebuie să subclaseze [`PreTrainedConfig`]. Aceasta asigură că un model personalizat are toate funcționalitățile unui model Transformers, precum [`~PreTrainedConfig.from_pretrained`], [`~PreTrainedConfig.save_pretrained`] și [`~PreTrainedConfig.push_to_hub`].
|
||||
2. `__init__`-ul [`PreTrainedConfig`] trebuie să accepte orice `kwargs` și acestea trebuie pasate `__init__`-ului superclasei. [`PreTrainedConfig`] are mai multe câmpuri decât cele setate în configurația ta personalizată, astfel că atunci când încarci o configurație cu [`~PreTrainedConfig.from_pretrained`], acele câmpuri trebuie acceptate de configurația ta și pasate superclasei.
|
||||
|
||||
> [!TIP]
|
||||
> Este util să verifici validitatea unora dintre parametri. În exemplul de mai jos, se implementează o verificare pentru a te asigura că `block_type` și `stem_type` aparțin uneia dintre valorile predefinite.
|
||||
>
|
||||
> Adaugă `model_type` la clasa de configurație pentru a activa suportul [AutoClass](./models#autoclass).
|
||||
|
||||
```py
|
||||
from transformers import PreTrainedConfig
|
||||
from typing import List
|
||||
|
||||
class ResnetConfig(PreTrainedConfig):
|
||||
model_type = "resnet"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
block_type="bottleneck",
|
||||
layers: list[int] = [3, 4, 6, 3],
|
||||
num_classes: int = 1000,
|
||||
input_channels: int = 3,
|
||||
cardinality: int = 1,
|
||||
base_width: int = 64,
|
||||
stem_width: int = 64,
|
||||
stem_type: str = "",
|
||||
avg_down: bool = False,
|
||||
**kwargs,
|
||||
):
|
||||
if block_type not in ["basic", "bottleneck"]:
|
||||
raise ValueError(f"`block_type` must be 'basic' or bottleneck', got {block_type}.")
|
||||
if stem_type not in ["", "deep", "deep-tiered"]:
|
||||
raise ValueError(f"`stem_type` must be '', 'deep' or 'deep-tiered', got {stem_type}.")
|
||||
|
||||
self.block_type = block_type
|
||||
self.layers = layers
|
||||
self.num_classes = num_classes
|
||||
self.input_channels = input_channels
|
||||
self.cardinality = cardinality
|
||||
self.base_width = base_width
|
||||
self.stem_width = stem_width
|
||||
self.stem_type = stem_type
|
||||
self.avg_down = avg_down
|
||||
super().__init__(**kwargs)
|
||||
```
|
||||
|
||||
Salvează configurația într-un fișier JSON în folderul modelului personalizat, `custom-resnet`, cu [`~PreTrainedConfig.save_pretrained`].
|
||||
|
||||
```py
|
||||
resnet50d_config = ResnetConfig(block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True)
|
||||
resnet50d_config.save_pretrained("custom-resnet")
|
||||
```
|
||||
|
||||
## Model
|
||||
|
||||
Cu configurația ResNet personalizată, poți acum crea și personaliza modelul. Modelul subclasează clasa de bază [`PreTrainedModel`]. Ca și [`PreTrainedConfig`], moștenirea din [`PreTrainedModel`] și inițializarea superclasei cu configurația extinde funcționalitățile Transformers, precum salvarea și încărcarea, la modelul personalizat.
|
||||
|
||||
Modelele Transformers urmează convenția de a accepta un obiect `config` în metoda `__init__`. Acesta pasează întregul `config` sublayers modelului, în loc să rupă obiectul `config` în mai multe argumente care sunt pasate individual către sublayers.
|
||||
|
||||
Scrierea modelelor în acest mod produce cod mai simplu cu o sursă clară de adevăr pentru orice hyperparameters. De asemenea, face mai ușoară reutilizarea codului din alte modele Transformers.
|
||||
|
||||
Vei crea două modele ResNet: un model ResNet de bază care returnează hidden states și un model ResNet cu un head de clasificare a imaginilor.
|
||||
|
||||
<hfoptions id="resnet">
|
||||
<hfoption id="ResnetModel">
|
||||
|
||||
Definește o mapare între tipurile de blocuri și clase. Tot restul este creat pasând clasa de configurație clasei modelului ResNet.
|
||||
|
||||
> [!TIP]
|
||||
> Adaugă `config_class` la clasa de model pentru a activa suportul [AutoClass](#autoclass-support).
|
||||
|
||||
```py
|
||||
from transformers import PreTrainedModel
|
||||
from timm.models.resnet import BasicBlock, Bottleneck, ResNet
|
||||
from .configuration_resnet import ResnetConfig
|
||||
|
||||
BLOCK_MAPPING = {"basic": BasicBlock, "bottleneck": Bottleneck}
|
||||
|
||||
class ResnetModel(PreTrainedModel):
|
||||
config_class = ResnetConfig
|
||||
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
block_layer = BLOCK_MAPPING[config.block_type]
|
||||
self.model = ResNet(
|
||||
block_layer,
|
||||
config.layers,
|
||||
num_classes=config.num_classes,
|
||||
in_chans=config.input_channels,
|
||||
cardinality=config.cardinality,
|
||||
base_width=config.base_width,
|
||||
stem_width=config.stem_width,
|
||||
stem_type=config.stem_type,
|
||||
avg_down=config.avg_down,
|
||||
)
|
||||
|
||||
def forward(self, tensor):
|
||||
return self.model.forward_features(tensor)
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="ResnetModelForImageClassification">
|
||||
|
||||
Metoda `forward` trebuie rescrisă pentru a calcula loss-ul pentru fiecare logit dacă sunt disponibile labels. Altfel, clasa modelului ResNet este aceeași.
|
||||
|
||||
> [!TIP]
|
||||
> Adaugă `config_class` la clasa de model pentru a activa suportul [AutoClass](#autoclass-support).
|
||||
|
||||
```py
|
||||
import torch
|
||||
|
||||
class ResnetModelForImageClassification(PreTrainedModel):
|
||||
config_class = ResnetConfig
|
||||
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
block_layer = BLOCK_MAPPING[config.block_type]
|
||||
self.model = ResNet(
|
||||
block_layer,
|
||||
config.layers,
|
||||
num_classes=config.num_classes,
|
||||
in_chans=config.input_channels,
|
||||
cardinality=config.cardinality,
|
||||
base_width=config.base_width,
|
||||
stem_width=config.stem_width,
|
||||
stem_type=config.stem_type,
|
||||
avg_down=config.avg_down,
|
||||
)
|
||||
|
||||
def forward(self, tensor, labels=None):
|
||||
logits = self.model(tensor)
|
||||
if labels is not None:
|
||||
loss = torch.nn.functional.cross_entropy(logits, labels)
|
||||
return {"loss": loss, "logits": logits}
|
||||
return {"logits": logits}
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
Un model poate returna orice format de ieșire. Returnarea unui dicționar (ca `ResnetModelForImageClassification`) cu losses când sunt disponibile labels face modelul personalizat compatibil cu [`Trainer`]. Pentru alte formate de ieșire, vei avea nevoie de propriul loop de antrenare sau de o bibliotecă diferită pentru antrenare.
|
||||
|
||||
Instanțiază clasa modelului personalizat cu configurația.
|
||||
|
||||
```py
|
||||
resnet50d = ResnetModelForImageClassification(resnet50d_config)
|
||||
```
|
||||
|
||||
În acest moment, poți încărca weights pre-antrenate în model sau îl poți antrena de la zero. În acest ghid, vei încărca weights pre-antrenate.
|
||||
|
||||
Încarcă weights pre-antrenate din biblioteca [timm](https://hf.co/docs/timm/index), apoi transferă acele weights modelului personalizat cu [load_state_dict](https://pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module.load_state_dict).
|
||||
|
||||
```py
|
||||
import timm
|
||||
|
||||
pretrained_model = timm.create_model("resnet50d", pretrained=True)
|
||||
resnet50d.model.load_state_dict(pretrained_model.state_dict())
|
||||
```
|
||||
|
||||
## AutoClass
|
||||
|
||||
API-ul [AutoClass](./models#clasele-de-model) este o scurtătură pentru a încărca automat arhitectura corectă pentru un model dat. Este convenabil să activezi aceasta pentru utilizatorii care încarcă modelul tău personalizat.
|
||||
|
||||
Asigură-te că ai atributul `model_type` (trebuie să fie diferit de tipurile de modele existente) în clasa de configurație și atributul `config_class` în clasa de model. Folosește metoda [`~AutoConfig.register`] pentru a adăuga configurația și modelul personalizat la API-ul [AutoClass](./models#clasele-de-model).
|
||||
|
||||
> [!TIP]
|
||||
> Primul argument al [`AutoConfig.register`] trebuie să corespundă atributului `model_type` din clasa de configurație personalizată, iar primul argument al [`AutoModel.register`] trebuie să corespundă `config_class`-ului clasei modelului personalizat.
|
||||
|
||||
```py
|
||||
from transformers import AutoConfig, AutoModel, AutoModelForImageClassification
|
||||
|
||||
AutoConfig.register("resnet", ResnetConfig)
|
||||
AutoModel.register(ResnetConfig, ResnetModel)
|
||||
AutoModelForImageClassification.register(ResnetConfig, ResnetModelForImageClassification)
|
||||
```
|
||||
|
||||
Codul modelului tău personalizat este acum compatibil cu API-ul [AutoClass](./models#autoclass). Utilizatorii pot încărca modelul cu clasele [AutoModel] sau [`AutoModelForImageClassification`].
|
||||
|
||||
## Publicare pe Hub
|
||||
|
||||
Publică un model personalizat pe [Hub](https://hf.co/models) pentru a permite altor utilizatori să îl încarce și utilizeze cu ușurință.
|
||||
|
||||
Asigură-te că directorul modelului este structurat corect, după cum se arată mai jos. Directorul ar trebui să conțină:
|
||||
|
||||
- `modeling.py`: Conține codul pentru `ResnetModel` și `ResnetModelForImageClassification`. Acest fișier poate utiliza importuri relative la alte fișiere atât timp cât se află în același director.
|
||||
|
||||
> [!WARNING]
|
||||
> Când copiezi un fișier de model Transformers, înlocuiește toate importurile relative din partea de sus a fișierului `modeling.py` pentru a importa din Transformers.
|
||||
|
||||
- `configuration.py`: Conține codul pentru `ResnetConfig`.
|
||||
- `__init__.py`: Poate fi gol; acest fișier permite utilizarea `resnet_model` ca modul Python.
|
||||
|
||||
```bash
|
||||
.
|
||||
└── resnet_model
|
||||
├── __init__.py
|
||||
├── configuration_resnet.py
|
||||
└── modeling_resnet.py
|
||||
```
|
||||
|
||||
Pentru a partaja modelul, importă modelul ResNet și configurația.
|
||||
|
||||
```py
|
||||
from resnet_model.configuration_resnet import ResnetConfig
|
||||
from resnet_model.modeling_resnet import ResnetModel, ResnetModelForImageClassification
|
||||
```
|
||||
|
||||
Copiază codul din fișierele de model și configurație. Pentru a te asigura că obiectele AutoClass sunt salvate cu [`~PreTrainedModel.save_pretrained`], apelează metoda [`~PreTrainedConfig.register_for_auto_class`]. Aceasta modifică fișierul JSON de configurație pentru a include obiectele AutoClass și maparea.
|
||||
|
||||
Pentru un model, alege clasa `AutoModelFor` corespunzătoare pe baza task-ului.
|
||||
|
||||
```py
|
||||
ResnetConfig.register_for_auto_class()
|
||||
ResnetModel.register_for_auto_class("AutoModel")
|
||||
ResnetModelForImageClassification.register_for_auto_class("AutoModelForImageClassification")
|
||||
```
|
||||
|
||||
Pentru a mapa mai mult de un task la model, editează `auto_map` direct în fișierul JSON de configurație.
|
||||
|
||||
```json
|
||||
"auto_map": {
|
||||
"AutoConfig": "<your-repo-name>--<config-name>",
|
||||
"AutoModel": "<your-repo-name>--<config-name>",
|
||||
"AutoModelFor<Task>": "<your-repo-name>--<config-name>",
|
||||
},
|
||||
```
|
||||
|
||||
Creează configurația și modelul și încarcă weights pre-antrenate în acesta.
|
||||
|
||||
```py
|
||||
resnet50d_config = ResnetConfig(block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True)
|
||||
resnet50d = ResnetModelForImageClassification(resnet50d_config)
|
||||
|
||||
pretrained_model = timm.create_model("resnet50d", pretrained=True)
|
||||
resnet50d.model.load_state_dict(pretrained_model.state_dict())
|
||||
```
|
||||
|
||||
Modelul este acum gata să fie publicat pe Hub. Autentifică-te în contul tău Hugging Face din linia de comandă sau notebook.
|
||||
|
||||
<hfoptions id="push">
|
||||
<hfoption id="huggingface-CLI">
|
||||
|
||||
```bash
|
||||
hf auth login
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="notebook">
|
||||
|
||||
```py
|
||||
from huggingface_hub import notebook_login
|
||||
|
||||
notebook_login()
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
Apelează [`~PreTrainedModel.push_to_hub`] pe model pentru a-l publica pe Hub.
|
||||
|
||||
```py
|
||||
resnet50d.push_to_hub("custom-resnet50d")
|
||||
```
|
||||
|
||||
Weights pre-antrenate, configurația și fișierele `modeling.py` și `configuration.py` ar trebui acum să fie toate publicate pe Hub într-un [repository](https://hf.co/sgugger/custom-resnet50d) sub namespace-ul tău.
|
||||
|
||||
Deoarece un model personalizat nu utilizează același cod de modelare ca un model Transformers, trebuie să adaugi `trust_remote_code=True` în [`~PreTrainedModel.from_pretrained`] pentru a-l încărca. Consultă secțiunea [modele personalizate](./models#modele-personalizate) pentru mai multe informații.
|
||||
172
docs/source/ro/custom_tokenizers.md
Normal file
172
docs/source/ro/custom_tokenizers.md
Normal file
@@ -0,0 +1,172 @@
|
||||
<!--Copyright 2026 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Personalizarea tokenizerelor
|
||||
|
||||
Tokenizerele sunt decuplate de vocabularele lor învățate. Asta îți permite să inițializezi un tokenizer gol pentru antrenare sau să creezi unul direct cu propriul vocabular. Pipeline-ul de bază pentru tokenization rămâne același (normalizer, pre-tokenizer, algoritmul de tokenization), deci nu trebuie să îl recreezi de la zero.
|
||||
|
||||
Acest ghid îți arată cum să antrenezi și să creezi un tokenizer personalizat.
|
||||
|
||||
## Antrenarea unui tokenizer
|
||||
|
||||
Un tokenizer gol antrenabil înlocuiește vocabularul cu un nou vocabular țintă. Este util pentru adaptarea la un nou domeniu, cum ar fi finanțe, o limbă cu resurse reduse sau cod.
|
||||
|
||||
Creează un tokenizer gol și încarcă un dataset.
|
||||
|
||||
```py
|
||||
from datasets import load_dataset
|
||||
from transformers import GemmaTokenizer
|
||||
|
||||
tokenizer = GemmaTokenizer()
|
||||
dataset = load_dataset("Josephgflowers/Finance-Instruct-500k", split="train")
|
||||
```
|
||||
|
||||
Folosește metoda [`TokenizersBackend.train_new_from_iterator`] ca să antrenezi tokenizerul. Metoda acceptă o funcție generator ca să returneze bucăți de text din dataset în loc să încarce totul în memorie dintr-o dată. Argumentul `vocab_size` setează dimensiunea vocabularului tokenizer-ului.
|
||||
|
||||
```py
|
||||
def batch_iterator(batch_size=1000):
|
||||
for i in range(0, len(dataset), batch_size):
|
||||
yield dataset[i : i + batch_size]["assistant"]
|
||||
|
||||
trained_tokenizer = tokenizer.train_new_from_iterator(
|
||||
batch_iterator(),
|
||||
vocab_size=32000,
|
||||
)
|
||||
encoded = trained_tokenizer("The stock market rallied today.")
|
||||
print(encoded["input_ids"])
|
||||
[5866, 11503, 98, 5885, 8617, 13381, 30]
|
||||
```
|
||||
|
||||
Adaugă token-uri speciale noi cu argumentul `new_special_tokens` sau folosește `special_tokens_map` ca să redenumești token-urile speciale vechi cu cele noi.
|
||||
|
||||
Salvează noul tokenizer de finanțe cu [`~PreTrainedTokenizerBase.save_pretrained`] sau salvează-l și încarcă-l pe Hub cu [`~PreTrainedTokenizerBase.push_to_hub`]. Asta creează un fișier `tokenizer.json` care captează vocabularul nou antrenat, regulile de îmbinare și configurația completă a pipeline-ului.
|
||||
|
||||
```py
|
||||
trained_tokenizer.save_pretrained("./finance-gemma-tokenizer")
|
||||
trained_tokenizer.push_to_hub("finance-gemma-tokenizer")
|
||||
```
|
||||
|
||||
## Vocabular personalizat
|
||||
|
||||
Un tokenizer gol suportă vocabular personalizat cu argumentele `vocab` și `merges`.
|
||||
|
||||
- `vocab` este setul complet de token-uri pe care un tokenizer le cunoaște, iar fiecare intrare mapează un token la input id-ul său.
|
||||
- `merges` definește cum ar trebui algoritmul BPE să combine token-urile adiacente.
|
||||
|
||||
```py
|
||||
from transformers import GemmaTokenizer
|
||||
|
||||
vocab={
|
||||
"<pad>": 0,
|
||||
"</s>": 1,
|
||||
"<s>": 2,
|
||||
"<unk>": 3,
|
||||
"<mask>": 4,
|
||||
"▁the": 5,
|
||||
"▁stock": 6,
|
||||
"▁market": 7,
|
||||
"▁": 8,
|
||||
"r": 9,
|
||||
"a": 10,
|
||||
"l": 11,
|
||||
"i": 12,
|
||||
"e": 13,
|
||||
"d": 14,
|
||||
"ra": 15,
|
||||
"li": 16,
|
||||
"lie": 17,
|
||||
"lied": 18,
|
||||
"ral": 19,
|
||||
"ralli": 20,
|
||||
"rallie": 21,
|
||||
"rallied": 22,
|
||||
}
|
||||
merges=[
|
||||
("r", "a"), # r + a → ra
|
||||
("l", "i"), # l + i → li
|
||||
("li", "e"), # li + e → lie
|
||||
("lie", "d"), # lie + d → lied
|
||||
("ra", "l"), # ra + l → ral
|
||||
("ral", "li"), # ral + li → ralli
|
||||
("ralli", "e"), # ralli + e → rallie
|
||||
("rallie", "d"), # rallie + d → rallied
|
||||
]
|
||||
|
||||
tokenizer = GemmaTokenizer(vocab=vocab, merges=merges)
|
||||
encoded = tokenizer("the stock market rallied")
|
||||
print(encoded["input_ids"])
|
||||
```
|
||||
|
||||
## Subclasarea TokenizersBackend
|
||||
|
||||
Tokenizers suportă patru [backend-uri](./fast_tokenizers#backend-uri) diferite. În general, ar trebui să folosești [`TokenizersBackend`] ca să definești un tokenizer nou deoarece este mai rapid.
|
||||
|
||||
> [!TIP]
|
||||
> [`PythonBackend`] este un tokenizer pur Python care nu depinde de backend-uri ca Rust, SentencePiece sau mistral-common. Folosește [`PythonBackend`] doar dacă construiești un tokenizer foarte specializat care nu poate fi exprimat de backend-ul Rust.
|
||||
|
||||
1. Subclasează [`TokenizersBackend`] cu atribute de clasă precum latura de padding și algoritmul de tokenizare de folosit.
|
||||
2. Definește pipeline-ul de tokenizare în `__init__`. Asta include algoritmul de tokenizare de folosit, cum să împartă textul brut înaintea algoritmului și cum să decodifice token-urile înapoi în text.
|
||||
|
||||
```py
|
||||
from tokenizers import Tokenizer, decoders, pre_tokenizers
|
||||
from tokenizers.models import BPE
|
||||
from transformers import TokenizersBackend
|
||||
|
||||
class NewTokenizer(TokenizersBackend):
|
||||
padding_side = "left"
|
||||
model = BPE
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
vocab=None,
|
||||
merges=None,
|
||||
unk_token="<unk>",
|
||||
bos_token="<s>",
|
||||
eos_token="</s>",
|
||||
pad_token="<pad>",
|
||||
):
|
||||
self._vocab = vocab or {
|
||||
str(unk_token): 0,
|
||||
str(bos_token): 1,
|
||||
str(eos_token): 2,
|
||||
str(pad_token): 3,
|
||||
}
|
||||
self._merges = merges or []
|
||||
|
||||
self._tokenizer = Tokenizer(
|
||||
BPE(vocab=self._vocab, merges=self._merges, fuse_unk=True)
|
||||
)
|
||||
self._tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)
|
||||
self._tokenizer.decoder = decoders.ByteLevel()
|
||||
|
||||
super().__init__(
|
||||
unk_token=unk_token,
|
||||
bos_token=bos_token,
|
||||
eos_token=eos_token,
|
||||
pad_token=pad_token,
|
||||
)
|
||||
```
|
||||
|
||||
Antrenează sau salvează noul tokenizer gol.
|
||||
|
||||
```py
|
||||
tokenizer = NewTokenizer()
|
||||
|
||||
# antrenează pe corpus nou
|
||||
tokenizer.train_new_from_iterator()
|
||||
# salvează tokenizer-ul
|
||||
tokenizer.save_pretrained("./new-tokenizer")
|
||||
```
|
||||
287
docs/source/ro/fast_tokenizers.md
Normal file
287
docs/source/ro/fast_tokenizers.md
Normal file
@@ -0,0 +1,287 @@
|
||||
<!--Copyright 2026 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Tokenizere
|
||||
|
||||
Un tokenizer convertește text în tensori, care sunt input-urile unui model. Acesta normalizează și împarte textul, aplică algoritmul de tokenization, adaugă token-uri speciale și decodifică id-urile de output înapoi în text.
|
||||
|
||||
```py
|
||||
from transformers import AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
|
||||
tokenizer("Sphinx of black quartz, judge my vow.", return_tensors="pt")
|
||||
{
|
||||
'input_ids': tensor([[ 2, 235277, 82913, 576, 2656, 30407, 235269, 11490, 970, 29871, 235265]]),
|
||||
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
|
||||
}
|
||||
```
|
||||
|
||||
Acest ghid acoperă încărcarea, encodarea, decodarea, procesarea în batch și backend-urile disponibile pentru tokenizere.
|
||||
|
||||
## Încarcă un tokenizer
|
||||
|
||||
Încarcă un tokenizer cu clasa [`AutoTokenizer`] sau cu o clasă de tokenizer specifică modelului.
|
||||
|
||||
<hfoptions id="tokenizers">
|
||||
<hfoption id="AutoTokenizer">
|
||||
|
||||
[`AutoTokenizer.from_pretrained`] citește config-ul modelului, rezolvă clasa corectă de tokenizer și returnează o instanță a ei. Nu trebuie să știi clasa de tokenizer dinainte. Majoritatea tokenizere-lor se rezolvă la o subclasă a [`TokenizersBackend`], un tokenizer rapid bazat pe Rust din biblioteca [Tokenizers](https://huggingface.co/docs/tokenizers/index).
|
||||
|
||||
Încărcarea cu [`AutoTokenizer`] este abordarea recomandată.
|
||||
|
||||
```py
|
||||
from transformers import AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="model-specific tokenizer">
|
||||
|
||||
O clasă de tokenization specifică modelului este un [`TokenizersBackend`] pre-configurat care folosește exact configurația de tokenization (normalizator, pre-tokenizator, convenții pentru token-uri speciale etc.) cu care a fost antrenat modelul.
|
||||
|
||||
Folosește o clasă specifică modelului ca să inițializezi un tokenizer gol pentru antrenare sau ca să pasezi argumente specifice modelului precum `vocab` sau `merges` (vezi ghidul [Personalizarea tokenizere-lor](./custom_tokenizers) ca să afli cum). Un tokenizer gol este minimal și conține doar token-urile speciale ale modelului, cum ar fi `<pad>`, `<eos>` sau `<bos>`.
|
||||
|
||||
```py
|
||||
from transformers import GemmaTokenizer
|
||||
|
||||
tokenizer = GemmaTokenizer()
|
||||
corpus = [
|
||||
["Sphinx of black quartz, judge my vow."],
|
||||
["Pack my box with five dozen liquor jugs."],
|
||||
["How vexingly quick daft zebras jump!"],
|
||||
]
|
||||
new_tokenizer = tokenizer.train_new_from_iterator(corpus, vocab_size=1000)
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
## Encodare și decodare
|
||||
|
||||
Metoda [`TokenizersBackend.__call__`] encodează text sau un batch de text în `input_ids`, `attention_mask` și alte input-uri pentru model. Controlează și padding-ul, trunchierea și inserarea token-urilor speciale.
|
||||
|
||||
```py
|
||||
from transformers import AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
|
||||
tokenizer("Sphinx of black quartz, judge my vow.", return_tensors="pt")
|
||||
{
|
||||
'input_ids': tensor([[ 2, 235277, 82913, 576, 2656, 30407, 235269, 11490, 970, 29871, 235265]]),
|
||||
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
|
||||
}
|
||||
```
|
||||
|
||||
[`TokenizersBackend.encode`] este similar, dar returnează doar `input_ids`.
|
||||
|
||||
```py
|
||||
from transformers import AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
|
||||
tokenizer.encode("Sphinx of black quartz, judge my vow.")
|
||||
[2, 235277, 82913, 576, 2656, 30407, 235269, 11490, 970, 29871, 235265]
|
||||
```
|
||||
|
||||
[`TokenizersBackend.decode`] convertește o secvență sau un batch de `input_ids` tokenizate înapoi în text.
|
||||
|
||||
```py
|
||||
tokenizer.decode(outputs["input_ids"])
|
||||
['<bos>Sphinx of black quartz, judge my vow.']
|
||||
```
|
||||
|
||||
[`TokenizersBackend.decode`] păstrează spațierea exactă a operației de tokenization. Setează `clean_up_tokenization_spaces` ca să elimini spațiile de dinaintea punctuației și `skip_special_tokens` ca să scoți token-urile speciale din output.
|
||||
|
||||
```py
|
||||
tokenizer.decode(outputs["input_ids"], skip_special_tokens=True)
|
||||
['Sphinx of black quartz, judge my vow.']
|
||||
```
|
||||
|
||||
## Token-uri speciale
|
||||
|
||||
Token-urile speciale marchează limitele structurale dintr-o secvență, cum ar fi începutul secvenței sau pozițiile de padding. Fiecare model definește propriul set de token-uri speciale. Tokenizer-ul le adaugă când îl apelezi.
|
||||
|
||||
```py
|
||||
tokenizer.encode("Sphinx of black quartz, judge my vow.")
|
||||
[2, 235277, 82913, 576, 2656, 30407, 235269, 11490, 970, 29871, 235265]
|
||||
tokenizer.decode(outputs["input_ids"])
|
||||
['<bos>Sphinx of black quartz, judge my vow.']
|
||||
```
|
||||
|
||||
Înregistrează token-uri speciale cu nume suplimentare folosind argumentul `extra_special_tokens`. Modelele multimodale le folosesc ca placeholders pentru imagini, video sau audio.
|
||||
|
||||
```py
|
||||
from transformers import AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained(
|
||||
"google/gemma-3-4b-pt",
|
||||
extra_special_tokens={"image_token": "<image>"}
|
||||
)
|
||||
```
|
||||
|
||||
## Procesare în batch
|
||||
|
||||
Procesarea în batch tokenizează mai multe secvențe într-un singur apel. [`TokenizersBackend`] gestionează batch-uri mari mai rapid pentru că backend-ul său bazat pe Rust paralelizează munca pe thread-uri.
|
||||
|
||||
```py
|
||||
from transformers import AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
|
||||
tokenizer(
|
||||
[
|
||||
"Sphinx of black quartz, judge my vow.",
|
||||
"Pack my box with five dozen liquor jugs.",
|
||||
"How vexingly quick daft zebras jump!"
|
||||
],
|
||||
return_tensors="pt"
|
||||
)
|
||||
```
|
||||
|
||||
Procesarea în batch presupune că toate secvențele au aceeași lungime. Padding-ul și trunchierea sunt strategii ca să gestionezi secvențe de lungimi diferite.
|
||||
|
||||
### Padding
|
||||
|
||||
Padding-ul adaugă token-uri speciale ca secvențele mai scurte să aibă aceeași lungime cu cea mai lungă din batch. Masca de atenție marchează pozițiile de padding cu `0` pentru ca modelul să le ignore. Setează `padding=True` ca să faci padding până la cea mai lungă secvență sau pasează `max_length` ca să faci padding la o dimensiune fixă.
|
||||
|
||||
```py
|
||||
from transformers import AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
|
||||
tokenizer(
|
||||
[
|
||||
"Sphinx of black quartz, judge my vow.",
|
||||
"Pack my box with five dozen liquor jugs.",
|
||||
"How vexingly quick daft zebras jump!"
|
||||
],
|
||||
return_tensors="pt",
|
||||
padding=True,
|
||||
)
|
||||
{
|
||||
'input_ids': tensor([
|
||||
[ 2, 235277, 82913, 576, 2656, 30407, 235269, 11490, 970, 29871, 235265],
|
||||
[ 0, 2, 6519, 970, 3741, 675, 4105, 25955, 42184, 225789, 235265],
|
||||
[ 0, 2, 2299, 73378, 17844, 4320, 224463, 4949, 48977, 9902, 235341]
|
||||
]),
|
||||
'attention_mask': tensor([
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
])
|
||||
}
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Modelele lingvistice mari fac padding pe partea *stângă* ca să nu perturbe generarea, care prezice token-ul următor din partea *dreaptă*.
|
||||
|
||||
### Trunchiere
|
||||
|
||||
Trunchierea taie token-uri ca o secvență să se încadreze într-o lungime maximă. Setează `truncation=True` și specifică `max_length` ca să o activezi.
|
||||
|
||||
Padding-ul și trunchierea funcționează împreună. Secvențele scurte primesc token-uri de padding, iar cele lungi pierd token-uri de la coadă. Împreună, produc un tensor dreptunghiular compact.
|
||||
|
||||
```py
|
||||
from transformers import AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
|
||||
tokenizer(
|
||||
[
|
||||
"Sphinx of black quartz, judge my vow.",
|
||||
"Pack my box with five dozen liquor jugs.",
|
||||
"How vexingly quick daft zebras jump!"
|
||||
],
|
||||
return_tensors="pt",
|
||||
padding=True,
|
||||
truncation=True,
|
||||
max_length=5
|
||||
)
|
||||
{
|
||||
'input_ids': tensor([
|
||||
[ 2, 235277, 82913, 576, 2656],
|
||||
[ 2, 6519, 970, 3741, 675],
|
||||
[ 2, 2299, 73378, 17844, 4320]
|
||||
]),
|
||||
'attention_mask': tensor([
|
||||
[1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1]
|
||||
])
|
||||
}
|
||||
```
|
||||
|
||||
## Backend-uri
|
||||
|
||||
Fiecare tokenizer de model este definit într-un singur fișier și suportă patru backend-uri de tokenization.
|
||||
|
||||
| backend | implementare | descriere |
|
||||
|---|---|---|
|
||||
| [`TokenizersBackend`] | [Tokenizers](https://huggingface.co/docs/tokenizers) | implicit pentru majoritatea modelelor |
|
||||
| [`SentencePieceBackend`] | [SentencePiece](https://github.com/google/sentencepiece) | modele care necesită SentencePiece |
|
||||
| [`PythonBackend`] | Python | modele care necesită tokenizere personalizate specializate |
|
||||
| [`MistralCommonBackend`] | [mistral-common](https://mistralai.github.io/mistral-common/) | modele Mistral și Pixtral |
|
||||
|
||||
Toate backend-urile moștenesc din [`PreTrainedTokenizerBase`] și împart aceleași API-uri pentru encodare, decodare, padding, trunchiere, salvare și încărcare. Diferența constă în pipeline-ul de tokenization care rulează pe dedesubt.
|
||||
|
||||
[`AutoTokenizer`] selectează cel mai bun backend disponibil când apelezi [`~AutoTokenizer.from_pretrained`].
|
||||
|
||||
1. Citește fișierul `tokenizer_config.json` pentru câmpul `tokenizer_class`.
|
||||
2. Registrul potrivește `tokenizer_class` cu un nume de clasă. Clasa rezolvată moștenește din unul din cele patru backend-uri. De exemplu, [`GemmaTokenizer`] moștenește din [`TokenizersBackend`], iar [`SiglipTokenizer`] moștenește din [`SentencePieceBackend`].
|
||||
|
||||
Unele modele, ca GLM, se mapează direct la [`TokenizersBackend`] pentru că fișierul `tokenizer.json` descrie complet pipeline-ul. [`GemmaTokenizer`] există ca subclasă deoarece definește setări suplimentare specifice modelului în Python pe care `tokenizer.json` nu le captează.
|
||||
|
||||
```py
|
||||
TOKENIZER_MAPPING_NAMES = OrderedDict([
|
||||
("gemma2", "GemmaTokenizer" if is_tokenizers_available() else None),
|
||||
("glm", "TokenizersBackend" if is_tokenizers_available() else None),
|
||||
(
|
||||
"mistral",
|
||||
"MistralCommonBackend"
|
||||
if is_mistral_common_available()
|
||||
else ("TokenizersBackend" if is_tokenizers_available() else None),
|
||||
),
|
||||
("siglip", "SiglipTokenizer" if is_sentencepiece_available() else None),
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
Când un backend ca mistral-common nu este instalat, [`AutoTokenizer`] revine la [`TokenizersBackend`].
|
||||
|
||||
Verifică ce backend folosește un tokenizer cu proprietatea `backend`.
|
||||
|
||||
```py
|
||||
from transformers import AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
|
||||
tokenizer.backend
|
||||
'tokenizers'
|
||||
```
|
||||
|
||||
## Inspectează arhitectura tokenizer-ului
|
||||
|
||||
Inspectează componentele interne ale unui tokenizer (normalizator, pre-tokenizator, model, decoder) cu atributul `_tokenizer`.
|
||||
|
||||
```py
|
||||
from transformers import AutoTokenizer
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
|
||||
print(tokenizer._tokenizer.normalizer)
|
||||
print(tokenizer._tokenizer.pre_tokenizer)
|
||||
print(tokenizer._tokenizer.model)
|
||||
print(tokenizer._tokenizer.decoder)
|
||||
```
|
||||
|
||||
## Resurse
|
||||
|
||||
- Postarea [Tokenization in Transformers v5](https://huggingface.co/blog/tokenizers) discută motivația din spatele noilor backend-uri de tokenization.
|
||||
- Consultă [ghidul de migrare](https://github.com/huggingface/transformers/blob/main/MIGRATION_GUIDE_V5.md#tokenization) pentru o prezentare a schimbărilor de tokenization.
|
||||
200
docs/source/ro/feature_extractors.md
Normal file
200
docs/source/ro/feature_extractors.md
Normal file
@@ -0,0 +1,200 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Feature extractors
|
||||
|
||||
Feature extractors preprocesează datele audio în formatul corect pentru un model dat. Preia semnalul audio brut și îl convertește într-un tensor care poate fi pasat unui model. Forma tensorului depinde de model, dar feature extractor-ul va preprocesa corect datele audio pentru modelul pe care îl folosești. Feature extractors includ și metode pentru padding, trunchiere și resampling.
|
||||
|
||||
Apelează [`~AutoFeatureExtractor.from_pretrained`] ca să încarci un feature extractor și configurația sa de preprocesare de pe Hub-ul Hugging Face sau dintr-un director local. Configurația feature extractor-ului și a preprocesatorului este salvată într-un fișier [preprocessor_config.json](https://hf.co/openai/whisper-tiny/blob/main/preprocessor_config.json).
|
||||
|
||||
Pasează semnalul audio, stocat de obicei în `array`, feature extractor-ului și setează parametrul `sampling_rate` la rata de eșantionare a modelului audio pre-antrenat. Este important ca rata de eșantionare a datelor audio să se potrivească cu rata de eșantionare a datelor pe care a fost antrenat modelul audio pre-antrenat.
|
||||
|
||||
```py
|
||||
from transformers import AutoFeatureExtractor
|
||||
|
||||
feature_extractor = AutoFeatureExtractor.from_pretrained("facebook/wav2vec2-base")
|
||||
dataset = load_dataset("PolyAI/minds14", name="en-US", split="train")
|
||||
processed_sample = feature_extractor(dataset[0]["audio"]["array"], sampling_rate=16000)
|
||||
processed_sample
|
||||
{'input_values': [array([ 9.4472744e-05, 3.0777880e-03, -2.8888427e-03, ...,
|
||||
-2.8888427e-03, 9.4472744e-05, 9.4472744e-05], dtype=float32)]}
|
||||
```
|
||||
|
||||
Feature extractor-ul returnează un input, `input_values`, gata să fie consumat de model.
|
||||
|
||||
Acest ghid te ghidează prin clasele de feature extractor și cum să preprocesezi date audio.
|
||||
|
||||
## Clasele de feature extractor
|
||||
|
||||
Feature extractors din Transformers moștenesc din clasa de bază [`SequenceFeatureExtractor`] care subclasează [`FeatureExtractionMixin`].
|
||||
|
||||
- [`SequenceFeatureExtractor`] furnizează o metodă de [`~SequenceFeatureExtractor.pad`] pentru secvențe la o anumită lungime ca să eviți lungimile inegale ale secvențelor.
|
||||
- [`FeatureExtractionMixin`] furnizează [`~FeatureExtractionMixin.from_pretrained`] și [`~FeatureExtractionMixin.save_pretrained`] ca să încarci și să salvezi un feature extractor.
|
||||
|
||||
Există două moduri de a încărca un feature extractor: [`AutoFeatureExtractor`] și o clasă de feature extractor specifică modelului.
|
||||
|
||||
<hfoptions id="feature-extractor-classes">
|
||||
<hfoption id="AutoFeatureExtractor">
|
||||
|
||||
API-ul [AutoClass] încarcă automat feature extractor-ul corect pentru un model dat.
|
||||
|
||||
Folosește [`~AutoFeatureExtractor.from_pretrained`] ca să încarci un feature extractor.
|
||||
|
||||
```py
|
||||
from transformers import AutoFeatureExtractor
|
||||
|
||||
feature_extractor = AutoFeatureExtractor.from_pretrained("openai/whisper-tiny")
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="model-specific feature extractor">
|
||||
|
||||
Fiecare model audio preantrenat are un feature extractor specific asociat pentru procesarea corectă a datelor audio. Când încarci un feature extractor, acesta preia configurația feature extractor-ului (dimensiunea feature-ului, lungimea chunk-ului etc.) din [preprocessor_config.json](https://hf.co/openai/whisper-tiny/blob/main/preprocessor_config.json).
|
||||
|
||||
Un feature extractor poate fi încărcat direct din clasa sa specifică modelului.
|
||||
|
||||
```py
|
||||
from transformers import WhisperFeatureExtractor
|
||||
|
||||
feature_extractor = WhisperFeatureExtractor.from_pretrained("openai/whisper-tiny")
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
## Preprocesare
|
||||
|
||||
Un feature extractor așteaptă un tensor PyTorch de o anumită formă ca input. Forma exactă a input-ului poate varia în funcție de modelul audio specific pe care îl folosești.
|
||||
|
||||
De exemplu, [Whisper](https://huggingface.co/docs/transformers/model_doc/whisper) se așteaptă ca `input_features` să fie un tensor de forma `(batch_size, feature_size, sequence_length)`, dar [Wav2Vec2](https://hf.co/docs/transformers/model_doc/wav2vec2) se așteaptă ca `input_values` să fie un tensor de forma `(batch_size, sequence_length)`.
|
||||
|
||||
Feature extractor-ul generează forma corectă de input pentru orice model audio folosești.
|
||||
|
||||
Un feature extractor setează și rata de eșantionare (numărul de valori ale semnalului audio preluate pe secundă) ale fișierelor audio. Rata de eșantionare a datelor tale audio trebuie să se potrivească cu rata de eșantionare a dataset-ului pe care a fost antrenat un model preantrenat. Această valoare este dată de obicei în card-ul modelului.
|
||||
|
||||
Încarcă un dataset și un feature extractor cu [`~FeatureExtractionMixin.from_pretrained`].
|
||||
|
||||
```py
|
||||
from datasets import load_dataset, Audio
|
||||
from transformers import AutoFeatureExtractor
|
||||
|
||||
dataset = load_dataset("PolyAI/minds14", name="en-US", split="train")
|
||||
feature_extractor = AutoFeatureExtractor.from_pretrained("facebook/wav2vec2-base")
|
||||
```
|
||||
|
||||
Uită-te la primul exemplu din dataset și accesează coloana `audio` care conține `array`, semnalul audio brut.
|
||||
|
||||
```py
|
||||
dataset[0]["audio"]["array"]
|
||||
array([ 0. , 0.00024414, -0.00024414, ..., -0.00024414,
|
||||
0. , 0. ])
|
||||
```
|
||||
|
||||
Feature extractor-ul preprocesează `array` în formatul de input așteptat pentru un model audio dat. Folosește parametrul `sampling_rate` ca să setezi rata de eșantionare corespunzătoare.
|
||||
|
||||
```py
|
||||
processed_dataset = feature_extractor(dataset[0]["audio"]["array"], sampling_rate=16000)
|
||||
processed_dataset
|
||||
{'input_values': [array([ 9.4472744e-05, 3.0777880e-03, -2.8888427e-03, ...,
|
||||
-2.8888427e-03, 9.4472744e-05, 9.4472744e-05], dtype=float32)]}
|
||||
```
|
||||
|
||||
### Padding
|
||||
|
||||
Lungimile diferite ale secvențelor audio sunt o problemă pentru că Transformers se așteaptă ca toate secvențele să aibă aceeași lungime ca să fie grupate în batch-uri. Secvențele de lungimi inegale nu pot fi grupate în batch-uri.
|
||||
|
||||
```py
|
||||
dataset[0]["audio"]["array"].shape
|
||||
(86699,)
|
||||
|
||||
dataset[1]["audio"]["array"].shape
|
||||
(53248,)
|
||||
```
|
||||
|
||||
Padding-ul adaugă un *token de padding* special ca să se asigure că toate secvențele au aceeași lungime. Feature extractor-ul adaugă un `0` — interpretat ca tăcere — la `array` ca să facă padding. Setează `padding=True` ca să faci padding secvențelor la lungimea celei mai lungi secvențe din batch.
|
||||
|
||||
```py
|
||||
def preprocess_function(examples):
|
||||
audio_arrays = [x["array"] for x in examples["audio"]]
|
||||
inputs = feature_extractor(
|
||||
audio_arrays,
|
||||
sampling_rate=16000,
|
||||
padding=True,
|
||||
)
|
||||
return inputs
|
||||
|
||||
processed_dataset = preprocess_function(dataset[:5])
|
||||
processed_dataset["input_values"][0].shape
|
||||
(86699,)
|
||||
|
||||
processed_dataset["input_values"][1].shape
|
||||
(86699,)
|
||||
```
|
||||
|
||||
### Trunchiere
|
||||
|
||||
Modelele pot procesa secvențe doar până la o anumită lungime înainte să se blocheze.
|
||||
|
||||
Truncherea este o strategie de eliminare a token-urilor în exces dintr-o secvență ca să se asigure că nu depășește lungimea maximă. Setează `truncation=True` ca să trunchiezi o secvență la lungimea din parametrul `max_length`.
|
||||
|
||||
```py
|
||||
def preprocess_function(examples):
|
||||
audio_arrays = [x["array"] for x in examples["audio"]]
|
||||
inputs = feature_extractor(
|
||||
audio_arrays,
|
||||
sampling_rate=16000,
|
||||
max_length=50000,
|
||||
truncation=True,
|
||||
)
|
||||
return inputs
|
||||
|
||||
processed_dataset = preprocess_function(dataset[:5])
|
||||
processed_dataset["input_values"][0].shape
|
||||
(50000,)
|
||||
|
||||
processed_dataset["input_values"][1].shape
|
||||
(50000,)
|
||||
```
|
||||
|
||||
### Resampling
|
||||
|
||||
Biblioteca [Datasets](https://hf.co/docs/datasets/index) poate și să resample datele audio ca să se potrivească cu rata de eșantionare așteptată de un model audio. Metoda asta resamplează datele audio din mers când sunt încărcate, ceea ce poate fi mai rapid decât resamplingul întregului dataset în loc.
|
||||
|
||||
Dataset-ul audio cu care lucrezi are o rată de eșantionare de 8kHz, iar modelul preantrenat se așteaptă la 16kHz.
|
||||
|
||||
```py
|
||||
dataset[0]["audio"]
|
||||
{'path': '/root/.cache/huggingface/datasets/downloads/extracted/f507fdca7f475d961f5bb7093bcc9d544f16f8cab8608e772a2ed4fbeb4d6f50/en-US~JOINT_ACCOUNT/602ba55abb1e6d0fbce92065.wav',
|
||||
'array': array([ 0. , 0.00024414, -0.00024414, ..., -0.00024414,
|
||||
0. , 0. ]),
|
||||
'sampling_rate': 8000}
|
||||
```
|
||||
|
||||
Apelează [`~datasets.Dataset.cast_column`] pe coloana `audio` ca să mărești rata de eșantionare la 16kHz.
|
||||
|
||||
```py
|
||||
dataset = dataset.cast_column("audio", Audio(sampling_rate=16000))
|
||||
```
|
||||
|
||||
Când încarci sample-ul din dataset, acum este resampled la 16kHz.
|
||||
|
||||
```py
|
||||
dataset[0]["audio"]
|
||||
{'path': '/root/.cache/huggingface/datasets/downloads/extracted/f507fdca7f475d961f5bb7093bcc9d544f16f8cab8608e772a2ed4fbeb4d6f50/en-US~JOINT_ACCOUNT/602ba55abb1e6d0fbce92065.wav',
|
||||
'array': array([ 1.70562416e-05, 2.18727451e-04, 2.28099874e-04, ...,
|
||||
3.43842403e-05, -5.96364771e-06, -1.76846661e-05]),
|
||||
'sampling_rate': 16000}
|
||||
```
|
||||
99
docs/source/ro/fusion_mapping.md
Normal file
99
docs/source/ro/fusion_mapping.md
Normal file
@@ -0,0 +1,99 @@
|
||||
<!--Copyright 2026 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Fusion mapping (funcție experimentală)
|
||||
|
||||
Fusion mapping oferă o modalitate opțională de a înlocui sub-modulele modelului la momentul încărcării, păstrând în același timp formatul original al checkpoint-ului.
|
||||
|
||||
Se bazează pe:
|
||||
|
||||
- [Monkey patching](./monkey_patching) pentru a schimba clasele de module înainte de instanțierea modelului.
|
||||
- [Încărcarea dinamică de weights](./weightconverter) pentru a mapa weights între layout-ul de rulare original și cel fuzionat.
|
||||
|
||||
> [!WARNING]
|
||||
> Fusion mapping este o funcție experimentală de încărcare. Schimbă structura modulelor la rulare și poți afecta comportamentul modelului. Folosește-o doar când dorești explicit un layout de rulare fuzionat.
|
||||
|
||||
## Pornire rapidă
|
||||
|
||||
Fusion este activat prin [`~PreTrainedModel.from_pretrained`] cu `fusion_config`:
|
||||
|
||||
```python
|
||||
from transformers import AutoModelForImageTextToText
|
||||
|
||||
|
||||
model = AutoModelForImageTextToText.from_pretrained(
|
||||
"Qwen/Qwen2-VL-2B-Instruct",
|
||||
fusion_config={"patch_embeddings": True},
|
||||
)
|
||||
```
|
||||
|
||||
În mod implicit, nu se aplică niciun fusion.
|
||||
Dacă `fusion_config` este stocat în configurația modelului, `from_pretrained()` îl va reutiliza automat.
|
||||
|
||||
## Cum funcționează
|
||||
|
||||
Înregistrarea fusion are loc înainte de instanțierea modelului:
|
||||
|
||||
1. [`~PreTrainedModel.from_pretrained`] folosește argumentul explicit `fusion_config` sau recurge la `config.fusion_config`.
|
||||
2. Registrul fusion validează numele fusion-urilor solicitate.
|
||||
3. Fiecare fusion activat meta-inițializează clasa modelului țintă, filtrează opțional modulele candidate după nume și folosește `is_fusable(...)` pentru a descoperi clasele de module compatibile.
|
||||
4. Clasele de înlocuire fuzionate sunt înregistrate prin [`~transformers.monkey_patching.register_patch_mapping`].
|
||||
5. Regulile [`~WeightTransform`] corespunzătoare sunt generate din configurație pentru ca încărcarea checkpoint-ului să poată mapa weights în layout-ul de runtime fuzionat.
|
||||
6. În mod implicit, [`~PreTrainedModel.save_pretrained`] folosește calea de conversie inversă pentru a restaura layout-ul original al checkpoint-ului. Pasează `save_original_format=False` pentru a păstra în schimb layout-ul de runtime convertit.
|
||||
|
||||
Aceasta permite unui fusion să folosească o structură de module de runtime diferită, încărcând în continuare din formatul original al checkpoint-ului și salvând înapoi în același format în mod implicit.
|
||||
|
||||
Notă: Cu mecanismul actual de monkey-patching, înregistrarea fusion este la nivel de clasă: o clasă de modul compatibilă se mapează la o clasă de înlocuire fuzionată.
|
||||
|
||||
## Familii de fusion curente
|
||||
|
||||
În prezent, `fusion_config` suportă o familie de fusion:
|
||||
|
||||
- `patch_embeddings`
|
||||
Activează cu:
|
||||
|
||||
```python
|
||||
fusion_config = {"patch_embeddings": True}
|
||||
```
|
||||
|
||||
Efect:
|
||||
Înlocuiește proiecțiile de patch embedding `nn.Conv3d` compatibile cu proiecții `nn.Linear` aplatizate echivalente la runtime.
|
||||
|
||||
## Extinderea fusion mapping
|
||||
|
||||
Pentru a adăuga o nouă familie de fusion:
|
||||
|
||||
1. Adaugă un predicat `is_fusable`.
|
||||
Acesta determină dacă un modul descoperit este compatibil cu fusion-ul.
|
||||
2. Adaugă opțional `target_modules_patterns`.
|
||||
Aceasta face pasul de descoperire mai explicit prin pre-filtrarea numelor modulelor candidate înainte de `is_fusable(...)`.
|
||||
3. Adaugă un factory `make_fused_class`.
|
||||
Acesta returnează clasa de înlocuire de runtime pentru o clasă de modul compatibilă.
|
||||
4. Adaugă un factory `make_transforms` dacă layout-ul fuzionat necesită conversia checkpoint-ului.
|
||||
Acesta returnează regulile [`~WeightTransform`] care mapează weights între layout-urile original și fuzionat pentru o configurație dată.
|
||||
5. Înregistrează noul `ModuleFusionSpec` în [`fusion_mapping.py`](https://github.com/huggingface/transformers/blob/main/src/transformers/fusion_mapping.py).
|
||||
|
||||
Odată înregistrat, noul fusion devine disponibil prin `fusion_config`.
|
||||
|
||||
## API intern
|
||||
|
||||
[[autodoc]] fusion_mapping.ModuleFusionSpec
|
||||
|
||||
[[autodoc]] fusion_mapping.PatchEmbeddingsFusionSpec
|
||||
|
||||
[[autodoc]] fusion_mapping._register_module_fusion
|
||||
|
||||
[[autodoc]] fusion_mapping.register_fusion_patches
|
||||
152
docs/source/ro/how_to_hack_models.md
Normal file
152
docs/source/ro/how_to_hack_models.md
Normal file
@@ -0,0 +1,152 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Personalizarea componentelor modelului
|
||||
|
||||
O altă modalitate de a personaliza un model este să modifici componentele acestuia în loc să scrii un model complet nou, permițându-ți să adaptezi un model la cazul tău specific de utilizare. De exemplu, poți adăuga noi layers sau optimiza mecanismul de attention al unei arhitecturi. Personalizările sunt aplicate direct unui model Transformers, așadar poți continua să folosești funcții precum [`Trainer`], [`PreTrainedModel`] și biblioteca [PEFT](https://huggingface.co/docs/peft/en/index).
|
||||
|
||||
Acest ghid îți va arăta cum să personalizezi mecanismul de attention al unui model pentru a-i aplica [Low-Rank Adaptation (LoRA)](https://huggingface.co/docs/peft/conceptual_guides/adapter#low-rank-adaptation-lora).
|
||||
|
||||
> [!TIP]
|
||||
> Utilitarul [clear_import_cache](https://github.com/huggingface/transformers/blob/9985d06add07a4cc691dc54a7e34f54205c04d40/src/transformers/utils/import_utils.py#L2286) este foarte util când modifici și dezvolți iterativ codul modelului. Acesta elimină toate modulele Transformers din cache și permite Python-ului să reîncarce codul modificat fără a reporni constant mediul tău.
|
||||
>
|
||||
> ```py
|
||||
> from transformers import AutoModel
|
||||
> from transformers.utils.import_utils import clear_import_cache
|
||||
>
|
||||
> model = AutoModel.from_pretrained("bert-base-uncased")
|
||||
> # modificări ale codului modelului
|
||||
> # șterge cache-ul pentru a reîncărca codul modificat
|
||||
> clear_import_cache()
|
||||
> # re-importă pentru a folosi codul actualizat
|
||||
> model = AutoModel.from_pretrained("bert-base-uncased")
|
||||
> ```
|
||||
|
||||
## Clasa attention
|
||||
|
||||
[Segment Anything] este un model de segmentare a imaginilor care combină proiecția query-key-value (`qkv`) în mecanismele sale de attention. Pentru a reduce numărul de parametri antrenabili și overhead-ul computațional, poți aplica LoRA proiecției `qkv`. Aceasta necesită împărțirea proiecției `qkv` astfel că poți targeta separat `q` și `v` cu LoRA.
|
||||
|
||||
1. Creează o clasă de attention personalizată, `SamVisionAttentionSplit`, prin subclasarea clasei originale `SamVisionAttention`. În `__init__`, șterge proiecția combinată `qkv` și creează un layer liniar separat pentru `q`, `k` și `v`.
|
||||
|
||||
```py
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
from transformers.models.sam.modeling_sam import SamVisionAttention
|
||||
|
||||
class SamVisionAttentionSplit(SamVisionAttention, nn.Module):
|
||||
def __init__(self, config, window_size):
|
||||
super().__init__(config, window_size)
|
||||
# elimină proiecția combinată qkv
|
||||
del self.qkv
|
||||
# proiecții separate q, k, v
|
||||
self.q = nn.Linear(config.hidden_size, config.hidden_size, bias=config.qkv_bias)
|
||||
self.k = nn.Linear(config.hidden_size, config.hidden_size, bias=config.qkv_bias)
|
||||
self.v = nn.Linear(config.hidden_size, config.hidden_size, bias=config.qkv_bias)
|
||||
self._register_load_state_dict_pre_hook(self.split_q_k_v_load_hook)
|
||||
```
|
||||
|
||||
2. Funcția `_split_qkv_load_hook` împarte weights pre-antrenate `qkv` în weights separate `q`, `k` și `v` la încărcarea modelului pentru a asigura compatibilitatea cu orice model pre-antrenat.
|
||||
|
||||
```py
|
||||
def split_q_k_v_load_hook(self, state_dict, prefix, *args):
|
||||
keys_to_delete = []
|
||||
for key in list(state_dict.keys()):
|
||||
if "qkv." in key:
|
||||
# împarte q, k, v din proiecția combinată
|
||||
q, k, v = state_dict[key].chunk(3, dim=0)
|
||||
# înlocuiește cu proiecții individuale q, k, v
|
||||
state_dict[key.replace("qkv.", "q.")] = q
|
||||
state_dict[key.replace("qkv.", "k.")] = k
|
||||
state_dict[key.replace("qkv.", "v.")] = v
|
||||
# marchează vechea cheie qkv pentru ștergere
|
||||
keys_to_delete.append(key)
|
||||
|
||||
# elimină cheile qkv vechi
|
||||
for key in keys_to_delete:
|
||||
del state_dict[key]
|
||||
```
|
||||
|
||||
3. În forward pass, `q`, `k` și `v` sunt calculate separat în timp ce restul mecanismului de attention rămâne același.
|
||||
|
||||
```py
|
||||
def forward(self, hidden_states: torch.Tensor, output_attentions=False) -> torch.Tensor:
|
||||
batch_size, height, width, _ = hidden_states.shape
|
||||
qkv_shapes = (batch_size * self.num_attention_heads, height * width, -1)
|
||||
query = self.q(hidden_states).reshape((batch_size, height * width,self.num_attention_heads, -1)).permute(0,2,1,3).reshape(qkv_shapes)
|
||||
key = self.k(hidden_states).reshape((batch_size, height * width,self.num_attention_heads, -1)).permute(0,2,1,3).reshape(qkv_shapes)
|
||||
value = self.v(hidden_states).reshape((batch_size, height * width,self.num_attention_heads, -1)).permute(0,2,1,3).reshape(qkv_shapes)
|
||||
|
||||
attn_weights = (query * self.scale) @ key.transpose(-2, -1)
|
||||
|
||||
attn_weights = torch.nn.functional.softmax(attn_weights, dtype=torch.float32, dim=-1).to(query.dtype)
|
||||
attn_probs = nn.functional.dropout(attn_weights, p=self.dropout, training=self.training)
|
||||
attn_output = (attn_probs @ value).reshape(batch_size, self.num_attention_heads, height, width, -1)
|
||||
attn_output = attn_output.permute(0, 2, 3, 1, 4).reshape(batch_size, height, width, -1)
|
||||
attn_output = self.proj(attn_output)
|
||||
|
||||
if output_attentions:
|
||||
outputs = (attn_output, attn_weights)
|
||||
else:
|
||||
outputs = (attn_output, None)
|
||||
return outputs
|
||||
```
|
||||
|
||||
Atribuie clasa personalizată `SamVisionAttentionSplit` modulului `SamVisionAttention` al modelului original pentru a-l înlocui. Toate instanțele `SamVisionAttention` din model sunt înlocuite cu versiunea de attention împărțită.
|
||||
|
||||
Încarcă modelul cu [`~PreTrainedModel.from_pretrained`].
|
||||
|
||||
```py
|
||||
from transformers import SamModel
|
||||
|
||||
# încarcă modelul SAM pre-antrenat
|
||||
model = SamModel.from_pretrained("facebook/sam-vit-base")
|
||||
|
||||
# înlocuiește clasa de attention în modulul vision_encoder
|
||||
for layer in model.vision_encoder.layers:
|
||||
if hasattr(layer, "attn"):
|
||||
layer.attn = SamVisionAttentionSplit(model.config.vision_config, model.config.vision_config.window_size)
|
||||
```
|
||||
|
||||
## LoRA
|
||||
|
||||
Cu proiecții separate `q`, `k` și `v`, aplică LoRA la `q` și `v`.
|
||||
|
||||
Creează un [LoraConfig](https://huggingface.co/docs/peft/package_reference/config#peft.PeftConfig) și specifică rank-ul `r`, `lora_alpha`, `lora_dropout`, `task_type` și, cel mai important, modulele de targetat.
|
||||
|
||||
```py
|
||||
from peft import LoraConfig, get_peft_model
|
||||
|
||||
config = LoraConfig(
|
||||
r=16,
|
||||
lora_alpha=32,
|
||||
# aplică LoRA la q și v
|
||||
target_modules=["q", "v"],
|
||||
lora_dropout=0.1,
|
||||
task_type="FEATURE_EXTRACTION"
|
||||
)
|
||||
```
|
||||
|
||||
Pasează modelul și [LoraConfig](https://huggingface.co/docs/peft/package_reference/config#peft.PeftConfig) la [get_peft_model](https://huggingface.co/docs/peft/package_reference/peft_model#peft.get_peft_model) pentru a aplica LoRA modelului.
|
||||
|
||||
```py
|
||||
model = get_peft_model(model, config)
|
||||
```
|
||||
|
||||
Apelează [print_trainable_parameters](https://huggingface.co/docs/peft/package_reference/peft_model#peft.PeftMixedModel.print_trainable_parameters) pentru a vizualiza numărul de parametri pe care îi antrenezi ca rezultat față de numărul total de parametri.
|
||||
|
||||
```py
|
||||
model.print_trainable_parameters()
|
||||
"trainable params: 589,824 || all params: 94,274,096 || trainable%: 0.6256"
|
||||
```
|
||||
231
docs/source/ro/image_processors.md
Normal file
231
docs/source/ro/image_processors.md
Normal file
@@ -0,0 +1,231 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Procesatoare de imagini
|
||||
|
||||
Procesatoarele de imagini convertesc imaginile în valori de pixeli, tensori care reprezintă culorile și dimensiunea imaginilor. Valorile de pixeli sunt input-urile unui model de viziune. Ca să se asigure că un model preantrenat primește input-ul corect, un procesator de imagini poate efectua următoarele operații ca imaginea să fie exact ca imaginile pe care modelul a fost preantrenat.
|
||||
|
||||
- decupare centrată sau redimensionare a imaginii
|
||||
- normalizarea sau rescalarea valorilor de pixeli
|
||||
|
||||
Folosește [`~ImageProcessingMixin.from_pretrained`] ca să încarci configurația unui procesator de imagini (dimensiunea imaginii, dacă să normalizeze și rescaleze etc.) de la un model de viziune de pe Hub-ul Hugging Face sau dintr-un director local. Configurația pentru fiecare model preantrenat este salvată într-un fișier [preprocessor_config.json](https://huggingface.co/google/vit-base-patch16-224/blob/main/preprocessor_config.json).
|
||||
|
||||
```py
|
||||
from transformers import AutoImageProcessor
|
||||
|
||||
image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")
|
||||
```
|
||||
|
||||
Pasează o imagine procesatorului de imagini ca să o transformi în valori de pixeli și setează `return_tensors="pt"` ca să returnezi tensori PyTorch. Poți să printezi input-urile ca să vezi cum arată imaginea ca tensor.
|
||||
|
||||
```py
|
||||
from PIL import Image
|
||||
import requests
|
||||
|
||||
url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/image_processor_example.png"
|
||||
image = Image.open(requests.get(url, stream=True).raw).convert("RGB")
|
||||
inputs = image_processor(image, return_tensors="pt")
|
||||
```
|
||||
|
||||
Acest ghid acoperă clasa procesatorului de imagini și cum să preprocesezi imagini pentru modelele de viziune.
|
||||
|
||||
## Clasele de procesatoare de imagini
|
||||
|
||||
Procesatoarele de imagini folosesc o arhitectură bazată pe două backend-uri:
|
||||
|
||||
- [`TorchvisionBackend`] — implementarea implicită bazată pe [torchvision](https://pytorch.org/vision/stable/index.html). Accelerată GPU și de până la 33x mai rapidă decât backend-ul PIL pentru batch-uri de input-uri [torch.Tensor](https://pytorch.org/docs/stable/tensors.html). Toate modelele suportă acest backend; modelele mai noi suportă doar acest backend.
|
||||
- [`PilBackend`] — alternativa PIL/NumPy. Portabilă și doar pe CPU. Disponibilă doar pentru modelele mai vechi, unde este utilă ca să reproduci ieșirile numerice exacte ale implementării originale.
|
||||
|
||||
Backend-ul activ pe un procesator încărcat poate fi inspectat cu atributul `backend` (de ex., `processor.backend == "torchvision"`). Fiecare procesator de imagini subclasează [`ImageProcessingMixin`] care furnizează metodele [`~ImageProcessingMixin.from_pretrained`] și [`~ImageProcessingMixin.save_pretrained`].
|
||||
|
||||
Există două moduri în care poți încărca un procesator de imagini: cu [`AutoImageProcessor`] sau direct dintr-o clasă specifică modelului.
|
||||
|
||||
<hfoptions id="image-processor-classes">
|
||||
<hfoption id="AutoImageProcessor">
|
||||
|
||||
API-ul [AutoClass] furnizează o metodă convenabilă de a încărca un procesator de imagini fără să specifici direct modelul cu care procesatorul de imagini este asociat.
|
||||
|
||||
Folosește [`~AutoImageProcessor.from_pretrained`] cu argumentul `backend` ca să selectezi backend-ul. Când `backend` este omis (implicit), torchvision este ales când este instalat, iar PIL este folosit altfel. Reține că `backend="pil"` este suportat doar pentru modele mai vechi; modelele mai noi expun doar backend-ul torchvision.
|
||||
|
||||
> **Notă:** un set mic de modele mai vechi (Chameleon, Flava, Idefics3, SmolVLM) folosesc interpolarea Lanczos pe care torchvision nu o suportă, deci revin mereu la backend-ul PIL indiferent de disponibilitatea torchvision. Pasează `backend="torchvision"` explicit ca să suprascrii asta.
|
||||
|
||||
```py
|
||||
from transformers import AutoImageProcessor
|
||||
|
||||
# Implicit: alege torchvision dacă este disponibil, altfel pil
|
||||
image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")
|
||||
|
||||
# Solicită explicit backend-ul torchvision
|
||||
image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224", backend="torchvision")
|
||||
|
||||
# Solicită explicit backend-ul PIL (doar pentru modele care îl suportă)
|
||||
image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224", backend="pil")
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="model-specific image processor">
|
||||
|
||||
Fiecare procesator de imagini este asociat cu un model de viziune preantrenat specific, iar configurația sa conține dimensiunea așteptată a modelului și parametrii de normalizare.
|
||||
|
||||
Încarcă procesatorul cu backend-ul torchvision direct din clasa specifică modelului.
|
||||
|
||||
```py
|
||||
from transformers import ViTImageProcessor
|
||||
|
||||
image_processor = ViTImageProcessor.from_pretrained("google/vit-base-patch16-224")
|
||||
```
|
||||
|
||||
Pentru modelele care îl suportă, poți încărca backend-ul PIL cu clasa cu sufixul `Pil`. Util când ai nevoie de paritate numerică exactă cu implementarea originală.
|
||||
|
||||
```py
|
||||
from transformers import ViTImageProcessorPil
|
||||
|
||||
image_processor = ViTImageProcessorPil.from_pretrained("google/vit-base-patch16-224")
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
## Procesatoare cu backend torchvision
|
||||
|
||||
[`TorchvisionBackend`] este backend-ul **implicit**. Asigură-te că [torchvision](https://pytorch.org/get-started/locally/#mac-installation) este instalat, apoi încarcă-l cu `backend="torchvision"` (sau omite pur și simplu `backend`, deoarece torchvision este selectat automat când este disponibil).
|
||||
|
||||
```py
|
||||
from transformers import AutoImageProcessor
|
||||
|
||||
processor = AutoImageProcessor.from_pretrained("facebook/detr-resnet-50", backend="torchvision")
|
||||
```
|
||||
|
||||
Controlează pe ce device se face procesarea cu argumentul `device`. Procesarea se face implicit pe același device ca input-ul dacă input-urile sunt tensori, altfel revine la CPU. Exemplul de mai jos rulează procesarea pe GPU.
|
||||
|
||||
```py
|
||||
from torchvision.io import read_image
|
||||
from transformers import DetrImageProcessor
|
||||
|
||||
images = read_image("image.jpg")
|
||||
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
|
||||
images_processed = processor(images, return_tensors="pt", device="cuda")
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Benchmarks</summary>
|
||||
|
||||
Benchmark-urile sunt obținute de pe o instanță [AWS EC2 g5.2xlarge](https://aws.amazon.com/ec2/instance-types/g5/) cu un GPU NVIDIA A10G Tensor Core.
|
||||
|
||||
<div class="flex">
|
||||
<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/benchmark_results_full_pipeline_detr_fast_padded.png" />
|
||||
</div>
|
||||
<div class="flex">
|
||||
<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/benchmark_results_full_pipeline_detr_fast_batched_compiled.png" />
|
||||
</div>
|
||||
<div class="flex">
|
||||
<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/benchmark_results_full_pipeline_rt_detr_fast_single.png" />
|
||||
</div>
|
||||
<div class="flex">
|
||||
<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/benchmark_results_full_pipeline_rt_detr_fast_batched.png" />
|
||||
</div>
|
||||
</details>
|
||||
|
||||
## Preprocesare
|
||||
|
||||
Modelele de viziune din Transformers se așteaptă la input ca tensori PyTorch de valori de pixeli. Un procesator de imagini gestionează conversia imaginilor în valori de pixeli, reprezentate prin dimensiunea batch-ului, numărul de canale, înălțimea și lățimea. Ca să realizeze asta, o imagine este redimensionată (decupată central) și valorile de pixeli sunt normalizate și rescalate la valorile așteptate de model.
|
||||
|
||||
Preprocesarea imaginilor nu este același lucru cu *augmentarea imaginilor*. Augmentarea imaginilor face modificări (luminozitate, culori, rotație etc.) unei imagini cu scopul de a crea exemple de antrenare noi sau de a preveni overfitting-ul. Preprocesarea imaginilor face modificări unei imagini cu scopul de a se potrivi formatului de input așteptat de un model preantrenat.
|
||||
|
||||
De obicei, imaginile sunt augmentate (ca să crești performanța) și apoi preprocesate înainte de a fi pasate unui model. Poți folosi orice bibliotecă ([Albumentations](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/image_classification_albumentations.ipynb), [Kornia](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/image_classification_kornia.ipynb)) pentru augmentare și un procesator de imagini pentru preprocesare.
|
||||
|
||||
Acest ghid folosește modulul [transforms](https://pytorch.org/vision/stable/transforms.html) din torchvision pentru augmentare.
|
||||
|
||||
Începe prin a încărca un eșantion mic din dataset-ul [food101](https://hf.co/datasets/food101).
|
||||
|
||||
```py
|
||||
from datasets import load_dataset
|
||||
|
||||
dataset = load_dataset("ethz/food101", split="train[:100]")
|
||||
```
|
||||
|
||||
Din modulul [transforms](https://pytorch.org/vision/stable/transforms.html), folosește API-ul [Compose](https://pytorch.org/vision/master/generated/torchvision.transforms.Compose.html) ca să înlănțuiești [RandomResizedCrop](https://pytorch.org/vision/main/generated/torchvision.transforms.RandomResizedCrop.html) și [ColorJitter](https://pytorch.org/vision/main/generated/torchvision.transforms.ColorJitter.html). Transformările astea decupează și redimensionează aleatoriu o imagine și ajustează aleatoriu culorile imaginii.
|
||||
|
||||
Dimensiunea imaginii la care să decupezi aleatoriu poate fi obținută de la procesatorul de imagini. Pentru unele modele se așteaptă valori exacte pentru înălțime și lățime, iar pentru altele este necesar doar `shortest_edge`.
|
||||
|
||||
```py
|
||||
from torchvision.transforms import RandomResizedCrop, ColorJitter, Compose
|
||||
|
||||
size = (
|
||||
image_processor.size["shortest_edge"]
|
||||
if "shortest_edge" in image_processor.size
|
||||
else (image_processor.size["height"], image_processor.size["width"])
|
||||
)
|
||||
_transforms = Compose([RandomResizedCrop(size), ColorJitter(brightness=0.5, hue=0.5)])
|
||||
```
|
||||
|
||||
Aplică transformările pe imagini și convertește-le la formatul RGB. Apoi pasează imaginile augmentate procesatorului de imagini ca să returneze valorile de pixeli.
|
||||
|
||||
Parametrul `do_resize` este setat la `False` pentru că imaginile au fost deja redimensionate în pasul de augmentare de [RandomResizedCrop](https://pytorch.org/vision/main/generated/torchvision.transforms.RandomResizedCrop.html). Dacă nu augmentezi imaginile, procesatorul de imagini le redimensionează și normalizează automat cu valorile `image_mean` și `image_std`. Aceste valori se găsesc în fișierul de configurație al preprocesatorului.
|
||||
|
||||
```py
|
||||
def transforms(examples):
|
||||
images = [_transforms(img.convert("RGB")) for img in examples["image"]]
|
||||
examples["pixel_values"] = image_processor(images, do_resize=False, return_tensors="pt")["pixel_values"]
|
||||
return examples
|
||||
```
|
||||
|
||||
Aplică funcția combinată de augmentare și preprocesare întregului dataset din mers cu [`~datasets.Dataset.set_transform`].
|
||||
|
||||
```py
|
||||
dataset.set_transform(transforms)
|
||||
```
|
||||
|
||||
Convertește valorile de pixeli înapoi într-o imagine ca să vezi cum a fost augmentată și preprocesată imaginea.
|
||||
|
||||
```py
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
img = dataset[0]["pixel_values"]
|
||||
plt.imshow(img.permute(1, 2, 0))
|
||||
```
|
||||
|
||||
<div class="flex gap-4">
|
||||
<div>
|
||||
<img class="rounded-xl" src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/vision-preprocess-tutorial.png" />
|
||||
<figcaption class="mt-2 text-center text-sm text-gray-500">înainte</figcaption>
|
||||
</div>
|
||||
<div>
|
||||
<img class="rounded-xl" src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/preprocessed_image.png" />
|
||||
<figcaption class="mt-2 text-center text-sm text-gray-500">după</figcaption>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Pentru alte task-uri de viziune, cum ar fi detecția obiectelor sau segmentarea, procesatorul de imagini include metode de post-procesare ca să convertească ieșirile brute ale modelului în predicții cu sens, cum ar fi bounding box-uri sau hărți de segmentare.
|
||||
|
||||
### Padding
|
||||
|
||||
Unele modele, ca [DETR], aplică [augmentarea la scară](https://paperswithcode.com/method/image-scale-augmentation) în antrenare, ceea ce poate face ca imaginile dintr-un batch să aibă dimensiuni diferite. Imaginile cu dimensiuni diferite nu pot fi grupate în batch-uri.
|
||||
|
||||
Ca să rezolvi asta, faci padding imaginilor cu token-ul special de padding `0`. Folosește metoda [pad](https://github.com/huggingface/transformers/blob/9578c2597e2d88b6f0b304b5a05864fd613ddcc1/src/transformers/models/detr/image_processing_detr.py#L1151) ca să faci padding imaginilor și definește o funcție de collatare personalizată ca să le grupezi în batch-uri.
|
||||
|
||||
```py
|
||||
def collate_fn(batch):
|
||||
pixel_values = [item["pixel_values"] for item in batch]
|
||||
encoding = image_processor.pad(pixel_values, return_tensors="pt")
|
||||
labels = [item["labels"] for item in batch]
|
||||
batch = {}
|
||||
batch["pixel_values"] = encoding["pixel_values"]
|
||||
batch["pixel_mask"] = encoding["pixel_mask"]
|
||||
batch["labels"] = labels
|
||||
return batch
|
||||
```
|
||||
60
docs/source/ro/index.md
Normal file
60
docs/source/ro/index.md
Normal file
@@ -0,0 +1,60 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
-->
|
||||
|
||||
# Transformers
|
||||
|
||||
<h3 align="center">
|
||||
<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/transformers_as_a_model_definition.png"/>
|
||||
</h3>
|
||||
|
||||
Transformers funcționează ca framework-ul de definire a modelelor pentru tehnologii de ultimă generație în machine learning aplicate pe text, computer vision, audio, video și modele multimodale, atât pentru inferență, cât și pentru antrenare.
|
||||
|
||||
Acesta centralizează definirea modelelor astfel încât această definiție să fie agreată la nivelul întregului ecosistem. `transformers` este pivotul dintre framework-uri: dacă definirea unui model este suportată, acesta va fi compatibil cu majoritatea framework-urilor de antrenare (Axolotl, Unsloth, DeepSpeed, FSDP, PyTorch-Lightning, ...), a motoarelor de inferență (vLLM, SGLang, TGI, ...) și a bibliotecilor de modelare adiacente (llama.cpp, mlx, ...) care utilizează definirea modelului din `transformers`.
|
||||
|
||||
Ne angajăm să ajutăm suportarea noilor modele de ultimă generație și să le democratizăm utilizarea prin oferirea unei definiri a modelului simplă, personalizabilă și eficientă.
|
||||
|
||||
Avem peste 1M de [checkpoint-uri de model](https://huggingface.co/models?library=transformers&sort=trending) Transformers pe [Hub-ul Hugging Face](https://huggingface.co/models) pe care le poți utiliza.
|
||||
|
||||
Explorează [Hub-ul](https://huggingface.co/) chiar azi pentru a găsi un model și folosește Transformers pentru a începe imediat.
|
||||
|
||||
Explorează [Timeline-ul Modelelor](./models_timeline) pentru a descoperi cele mai recente arhitecturi de tip text, vision, audio și model multimodal din Transformers.
|
||||
|
||||
## Funcții
|
||||
|
||||
Transformers oferă tot ce ai nevoie pentru antrenarea sau inferența cu modele pre-antrenate de ultimă generație. Printre funcțiile principale se numără:
|
||||
|
||||
- [Pipeline](./pipeline_tutorial): Clasă de inferență simplă și optimizată pentru multe task-uri de machine learning, precum generarea de text, segmentarea de imagini, recunoașterea vocală automată, răspunsuri la întrebări din documente etc.
|
||||
- [Trainer](./trainer): Un trainer comprehensiv ce suportă funcții precum precizie mixtă, torch.compile și FlashAttention pentru antrenarea simplă și distribuită a modelelor PyTorch.
|
||||
- [generate](./llm_tutorial): Generare de text rapidă cu modele lingvistice mari (LLMs) și modele lingvistice vizuale (VLMs), incluzând suport pentru streaming și mai multe strategii de decodare.
|
||||
|
||||
## Design
|
||||
|
||||
> [!TIP]
|
||||
> Citește [Filozofia](./philosophy) noastră pentru a învăța mai multe despre filozofia de design a Transformers.
|
||||
|
||||
Transformers este construit pentru developeri, ingineri și cercetători în machine learning. Principiile principale de design pentru Transformers sunt:
|
||||
|
||||
1. Rapid și ușor de folosit: Fiecare model este implementat din doar 3 clase principale (configuration, model, și preprocessor) și poate fi utilizat rapid și ușor pentru antrenare sau inferență cu [`Pipeline`] sau [`Trainer`].
|
||||
2. Modele pre-antrenate: Redu-ți amprenta de carbon, costul de calcul și timpul utilizând un model pre-antrenat în loc să antrenezi unul nou. Fiecare model pre-antrenat este reprodus cât mai fidel posibil de modelul original și oferă performanță de ultimă generație.
|
||||
|
||||
<div class="flex justify-center">
|
||||
<a target="_blank" href="https://huggingface.co/support">
|
||||
<img alt="HuggingFace Expert Acceleration Program" src="https://hf.co/datasets/huggingface/documentation-images/resolve/81d7d9201fd4ceb537fc4cebc22c29c37a2ed216/transformers/transformers-index.png" style="width: 100%; max-width: 600px; border: 1px solid #eee; border-radius: 4px; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Învață
|
||||
|
||||
Dacă acum începi să utilizezi Transformers sau vrei să înveți mai multe despre modelele noastre, recomandăm să începi cu [Cursul despre LLMs](https://huggingface.co/learn/llm-course/chapter1/1?fw=pt). Acest curs comprehensiv acoperă tot, de la cunoștințele de bază despre cum funcționează modelele până la aplicații practice ale acestora în diferite task-uri. Vei învăța workflow-ul complet, de la crearea unor seturi de date de calitate înaltă până la manipularea avansată a modelelor lingvistice mari și implementarea capabilităților de raționament. Acest curs conține atât exerciții teoretice, cât și exerciții practice pentru construirea unor cunoștințe de bază despre modelele pe bază de transformers pe parcursul învățării.
|
||||
164
docs/source/ro/installation.md
Normal file
164
docs/source/ro/installation.md
Normal file
@@ -0,0 +1,164 @@
|
||||
<!---
|
||||
Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Instalarea
|
||||
|
||||
Transformers depinde de [PyTorch](https://pytorch.org/get-started/locally/). A fost testat cu Python 3.10+ și PyTorch 2.4+.
|
||||
|
||||
## Virtual environment
|
||||
|
||||
[uv](https://docs.astral.sh/uv/) este un Python Package manager și project manager foarte rapid scris în Rust și necesită un [virtual environment](https://docs.astral.sh/uv/pip/environments/) pentru a gestiona diferite proiecte, evitând conflictele dintre dependencies.
|
||||
|
||||
Poate fi utilizat drept înlocuitor pentru [pip](https://pip.pypa.io/en/stable/), dar, dacă preferi să utilizezi pip, omite `uv` din comenzile de mai jos.
|
||||
|
||||
> [!TIP]
|
||||
> Uită-te la [ghidul de instalare](https://docs.astral.sh/uv/guides/install-python/) uv pentru a instala uv.
|
||||
|
||||
Creează un virtual environment în care să instalezi Transformers.
|
||||
|
||||
```bash
|
||||
uv venv .env
|
||||
source .env/bin/activate
|
||||
```
|
||||
|
||||
## Python
|
||||
|
||||
Instalează Transformers cu următoarea comandă.
|
||||
|
||||
[uv](https://docs.astral.sh/uv/) este un Python Package manager și project manager rapid scris în Rust.
|
||||
|
||||
```bash
|
||||
uv pip install transformers
|
||||
```
|
||||
|
||||
Pentru GPU Acceleration descarcă driverele CUDA pentru [PyTorch](https://pytorch.org/get-started/locally).
|
||||
|
||||
Rulează comanda de mai jos pentru a vedea dacă sistemul tău detectează un GPU NVIDIA.
|
||||
|
||||
```bash
|
||||
nvidia-smi
|
||||
```
|
||||
|
||||
Pentru a instala o versiune doar de CPU a Transformers, rulează comanda de mai jos.
|
||||
|
||||
```bash
|
||||
uv pip install torch --index-url https://download.pytorch.org/whl/cpu
|
||||
uv pip install transformers
|
||||
```
|
||||
|
||||
Testează dacă instalarea s-a realizat cu succes cu următoarea comandă. Ar trebui să returneze un label și un score pentru textul următor.
|
||||
|
||||
```bash
|
||||
python -c "from transformers import pipeline; print(pipeline('sentiment-analysis')('hugging face is the best'))"
|
||||
[{'label': 'POSITIVE', 'score': 0.9998704791069031}]
|
||||
```
|
||||
|
||||
### Instalarea din codul sursă
|
||||
|
||||
Instalând de la sursă se instalează *cea mai recentă* versiune în loc de versiunea *stabilă*. Aceasta asigură cele mai noi schimbări din Transformers și folosește la experimentarea cu cele mai noi funcții sau repararea unui bug care nu a fost încă lansat în versiunea stabilă.
|
||||
|
||||
Dezavantajul este că cea mai recentă versiune ar putea să nu fie stabilă. Dacă întâmpini vreo problemă, te rugăm să deschizi un [GitHub Issue](https://github.com/huggingface/transformers/issues) ca să o putem repara cât de repede posibil.
|
||||
|
||||
Instalează din codul sursă cu următoarea comandă.
|
||||
|
||||
```bash
|
||||
uv pip install git+https://github.com/huggingface/transformers
|
||||
```
|
||||
|
||||
Testează dacă instalarea s-a realizat cu succes cu următoarea comandă. Ar trebui să returneze un label și un score pentru textul următor.
|
||||
|
||||
```bash
|
||||
python -c "from transformers import pipeline; print(pipeline('sentiment-analysis')('hugging face is the best'))"
|
||||
[{'label': 'POSITIVE', 'score': 0.9998704791069031}]
|
||||
```
|
||||
|
||||
### Instalare editabilă
|
||||
|
||||
O [instalare editabilă](https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs) este utilă dacă faci development local cu Transformers. Aceasta conectează copia ta locală a Transformers cu [repository-ul](https://github.com/huggingface/transformers) Transformers în loc să copieze fișierele. Acestea sunt adăugate la path-ul de import Python.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/huggingface/transformers.git
|
||||
cd transformers
|
||||
uv pip install -e .
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> Trebuie să păstrezi folder-ul local Transformers ca să continui utilizarea.
|
||||
|
||||
Actualizează-ți copia locală de Transformers cu cele mai noi schimbări din repository-ul principal cu comanda de mai jos.
|
||||
|
||||
```bash
|
||||
cd ~/transformers/
|
||||
git pull
|
||||
```
|
||||
|
||||
## conda
|
||||
|
||||
[conda](https://docs.conda.io/projects/conda/en/stable/#) este un package manager independent de un limbaj de programare. Instalează Transformers de la canalul [conda-forge](https://anaconda.org/conda-forge/transformers) în noul tău virtual environment.
|
||||
|
||||
```bash
|
||||
conda install conda-forge::transformers
|
||||
```
|
||||
|
||||
## Configurare
|
||||
|
||||
După instalare, poți seta locația cache pentru Transformers sau poți configura biblioteca pentru utilizare offline.
|
||||
|
||||
### Folder-ul cache
|
||||
|
||||
Când încarci un model folosind [`~PreTrainedModel.from_pretrained`], modelul este descărcat de pe Hub și salvat local în cache.
|
||||
|
||||
De fiecare dată când încarci un model se verifică dacă modelul salvat în cache este la cea mai nouă versiune. Dacă da, modelul salvat în cache este încărcat. Dacă nu, modelul mai nou este descărcat și salvat în cache.
|
||||
|
||||
Folder-ul implicit dat de variabila de mediu `HF_HUB_CACHE` este `~/.cache/huggingface/hub`. Pe Windows, folder-ul implicit este `C:\Users\username\.cache\huggingface\hub`.
|
||||
|
||||
Salvează un model în cache într-un alt folder schimbând path-ul în următoarele variabile de mediu (sortate după prioritate).
|
||||
|
||||
1. [HF_HUB_CACHE](https://hf.co/docs/huggingface_hub/package_reference/environment_variables#hfhubcache) (implicit)
|
||||
2. [HF_HOME](https://hf.co/docs/huggingface_hub/package_reference/environment_variables#hfhome)
|
||||
3. [XDG_CACHE_HOME](https://hf.co/docs/huggingface_hub/package_reference/environment_variables#xdgcachehome) + `/huggingface` (doar dacă `HF_HOME` nu este setat)
|
||||
|
||||
### Modul Offline
|
||||
|
||||
Folosirea Transformers într-un mediu offline sau cu firewall necesită fișierele descărcate și salvate în cache. Descarcă un repository de modele folosind metoda [`~huggingface_hub.snapshot_download`] .
|
||||
|
||||
> [!TIP]
|
||||
> Urmează ghidul [Descarcă fișiere de pe Hub](https://hf.co/docs/huggingface_hub/guides/download) pentru mai multe opțiuni de a descărca fișiere de pe Hub. Poți descărca fișiere din revizii specifice, utilizând linia de comandă și poți filtra ce fișiere să descarci din repository.
|
||||
|
||||
```py
|
||||
from huggingface_hub import snapshot_download
|
||||
|
||||
snapshot_download(repo_id="meta-llama/Llama-2-7b-hf", repo_type="model")
|
||||
```
|
||||
|
||||
Setează variabila de mediu `HF_HUB_OFFLINE=1` pentru a preveni HTTP calls către Hub la descărcarea unui model.
|
||||
|
||||
```bash
|
||||
HF_HUB_OFFLINE=1 \
|
||||
python examples/pytorch/language-modeling/run_clm.py --model_name_or_path meta-llama/Llama-2-7b-hf --dataset_name wikitext ...
|
||||
```
|
||||
|
||||
O altă opțiune pentru încărcarea exclusivă a fișierelor salvate în cache este setarea `local_files_only=True` în [`~PreTrainedModel.from_pretrained`].
|
||||
|
||||
```py
|
||||
from transformers import LlamaForCausalLM
|
||||
|
||||
model = LlamaForCausalLM.from_pretrained("./path/to/local/directory", local_files_only=True)
|
||||
```
|
||||
116
docs/source/ro/model_output_tracing.md
Normal file
116
docs/source/ro/model_output_tracing.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# Urmărirea output-urilor intermediare ale modelului
|
||||
|
||||
Metoda `forward()` a fiecărui model obișnuia să rezolve manual flag-uri de tip `None` precum `output_attentions` din valorile implicite din config, să acumuleze attention weights și hidden states per layer în tuples și să convertească dataclasses [`ModelOutput`] în tuple-uri plain când `return_dict=False`. Doi decoratori înlocuiesc tot acel cod boilerplate.
|
||||
|
||||
- `@capture_outputs` rezolvă flag-urile de ieșire, colectează valorile intermediare și gestionează conversia `return_dict`.
|
||||
- `@merge_with_config_defaults` rezolvă `use_cache` din config. Omite-l pentru modelele care nu fac cache, precum [`CLIPModel`].
|
||||
|
||||
Vei întâlni acești decoratori mai ales când integrezi un model nou. Vezi [adăugarea unui model în 🤗 Transformers](./modular_transformers) pentru un ghid pas cu pas.
|
||||
|
||||
## Declară ce submodule să captezi
|
||||
|
||||
Aplică `@capture_outputs` pe metoda `forward()` a modelului de bază. Atașează forward hooks care:
|
||||
|
||||
- Interceptează ieșirile din clasele de submodule specificate în timpul forward pass-ului, fără ca acele submodule să știe că sunt observate.
|
||||
- Colectează attention weights și hidden states per layer în tuple-uri.
|
||||
- Injectează valorile colectate în dataclass-ul [`ModelOutput`] returnat.
|
||||
- Convertesc dataclass-ul într-un tuple plain când `return_dict=False`.
|
||||
- Rezolvă `output_attentions` și `output_hidden_states` din kwargs sau `self.config` când sunt `None`.
|
||||
|
||||
## Mapează câmpurile de ieșire la submodule
|
||||
|
||||
`@capture_outputs` trebuie să știe ce submodul produce ce ieșire. Declară un dicționar `_can_record_outputs` la nivel de clasă pe subclasa ta `PreTrainedModel`. Fiecare cheie este un nume de câmp de ieșire (`"hidden_states"`, `"attentions"`, `"cross_attentions"`), iar fiecare valoare este o clasă de modul sau o instanță `OutputRecorder`.
|
||||
|
||||
## Control detaliat cu OutputRecorder
|
||||
|
||||
`OutputRecorder` acceptă un `target_class` (o subclasă `nn.Module` ale cărei output-uri să le colectezi) și un `index` opțional pentru a selecta ce element din tuple-ul de ieșire al modulului să ia. Pasează `layer_name` ca să atașezi hook-uri doar la modulele cu un nume de atribut specific. Folosește `layer_name` când două layers partajează aceeași clasă, de exemplu self-attention vs. cross-attention.
|
||||
|
||||
Exemplul de mai jos arată ambii decoratori în practică cu diferite niveluri de control al ieșirii. Vezi [LlamaModel](https://github.com/huggingface/transformers/blob/main/src/transformers/models/llama/modeling_llama.py) pentru o referință din lumea reală.
|
||||
|
||||
```python
|
||||
from ...processing_utils import Unpack
|
||||
from ...utils import TransformersKwargs
|
||||
from ...utils.generic import merge_with_config_defaults
|
||||
from ...utils.output_capturing import capture_outputs, OutputRecorder
|
||||
|
||||
class MyPreTrainedModel(PreTrainedModel):
|
||||
_can_record_outputs = {
|
||||
# Capturează hidden_states: hook-ul se declanșează după fiecare forward MyDecoderBlock,
|
||||
# luând prima ieșire (index 0 implicit).
|
||||
"hidden_states": MyDecoderBlock,
|
||||
|
||||
# Capturează self-attention weights: hook-ul se declanșează după fiecare forward MyAttention,
|
||||
# luând a doua ieșire (index=1 implicit).
|
||||
"attentions": MyAttention,
|
||||
|
||||
# Capturează cross-attention weights: aceeași clasă, submodul diferit.
|
||||
# layer_name țintește atributul `self.crossattention` din interiorul block-ului.
|
||||
# Capturează a doua ieșire cum s-a cerut (index=1)
|
||||
"cross_attentions": OutputRecorder(
|
||||
MyAttention, layer_name="crossattention", index=1
|
||||
),
|
||||
}
|
||||
|
||||
# Acum în forward-ul modelului de bază avem nevoie de decoratori și `Unpack` `kwargs`
|
||||
class MyModel(MyPreTrainedModel):
|
||||
|
||||
@merge_with_config_defaults # ← rezolvă use_cache
|
||||
@capture_outputs # ← gestionează colectarea ieșirilor + return_dict
|
||||
def forward(
|
||||
self,
|
||||
input_ids: torch.LongTensor | None = None,
|
||||
past_key_values: Cache = None,
|
||||
**kwargs: Unpack[TransformersKwargs],
|
||||
) -> BaseModelOutputWithPast:
|
||||
|
||||
# Nu e nevoie de colectare manuală. Rulează layers normal.
|
||||
hidden_states = self.embed_tokens(input_ids)
|
||||
for layer in self.layers:
|
||||
hidden_states = layer(hidden_states, **kwargs)
|
||||
|
||||
# Returnează ieșirile primare. Decoratorul va completa automat
|
||||
# hidden_states/attentions/cross_attentions.
|
||||
return BaseModelOutputWithPast(
|
||||
last_hidden_state=hidden_states,
|
||||
past_key_values=past_key_values
|
||||
)
|
||||
```
|
||||
|
||||
## Patch-uiește clasele de layers
|
||||
|
||||
Urmărirea output-urilor depinde de `_can_record_outputs` care pointează la clasele *exacte* pe care layer-urile modelului le instanțiază. Dacă înlocuiești o implementare de layer cu un kernel de attention personalizat, un layer de expert quantized sau o variantă arhitecturală, acei pointeri trebuie să rămână sincronizați. [API-ul de patching](./monkey_patching) oferă un registru global curat pentru a menține `_can_record_outputs` consistent.
|
||||
|
||||
`register_patch_mapping` mapează numele originale ale claselor la subclase `nn.Module` de înlocuire. Cheile pot fi nume exacte de clase sau pattern-uri regex. Potrivirile exacte au prioritate. Pattern-urile sunt testate cu `re.search()`, deci pattern-urile neancorate se potrivesc oriunde în numele clasei. Înregistrarea aceleiași chei de două ori ridică `ValueError` dacă nu pasezi `overwrite=True`.
|
||||
|
||||
Elimină intrările cu `unregister_patch_mapping`.
|
||||
|
||||
```python
|
||||
from transformers.monkey_patching import register_patch_mapping, unregister_patch_mapping
|
||||
|
||||
# Nume exact – înlocuiește doar Qwen2MoeExperts
|
||||
register_patch_mapping({"Qwen2MoeExperts": SequentialExperts})
|
||||
|
||||
# Regex – înlocuiește orice clasă al cărei nume se termină cu "Attention"
|
||||
register_patch_mapping({".*Attention$": FusedAttention})
|
||||
|
||||
# Versiunea ancorată – se potrivește doar cu Llama2Attention, Llama3Attention, …
|
||||
register_patch_mapping({"^Llama\\d+Attention$": CustomLlamaAttention})
|
||||
|
||||
# La fel, cheile personalizate pot fi eliminate din registru pasând numele care a fost înregistrat
|
||||
unregister_patch_mapping(["Qwen2MoeExperts", ".*Attention$"])
|
||||
```
|
||||
|
||||
Odată ce mapările sunt înregistrate, `patch_output_recorders` parcurge fiecare submodul și actualizează fiecare `OutputRecorder.target_class` la înlocuitorul înregistrat.
|
||||
|
||||
> [!TIP]
|
||||
> Metoda [`~PreTrainedModel.from_pretrained`] apelează `patch_output_recorders` automat. Trebuie să o apelezi tu doar când construiești un model direct.
|
||||
|
||||
```python
|
||||
from transformers.monkey_patching import patch_output_recorders
|
||||
# Construit manual, în afara from_pretrained
|
||||
model = Qwen2MoeModel(config)
|
||||
|
||||
# Fără asta, _can_record_outputs tot pointează la clasa originală Qwen2MoeExperts
|
||||
# și hook-urile nu se vor declanșa niciodată pe instanțele CustomExperts.
|
||||
patch_output_recorders(model)
|
||||
```
|
||||
158
docs/source/ro/model_sharing.md
Normal file
158
docs/source/ro/model_sharing.md
Normal file
@@ -0,0 +1,158 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Distribuirea modelelor
|
||||
|
||||
[Hub-ul](https://hf.co/models) Hugging Face este o platformă pentru distribuirea, descoperirea și utilizarea modelelor de toate tipurile și dimensiunile. Îți recomandăm să distribui modelul tău pe Hub pentru a avansa machine learning-ul open-source pentru toți!
|
||||
|
||||
Acest ghid îți va arăta cum să distribui un model pe Hub direct din Transformers.
|
||||
|
||||
## Configurare
|
||||
|
||||
Pentru a partaja un model pe Hub, ai nevoie de un [cont](https://hf.co/join) Hugging Face. Creează un [User Access Token](https://hf.co/docs/hub/security-tokens#user-access-tokens) (stocat în [cache](./installation#folder-ul-cache) în mod implicit) și autentifică-te în contul tău din linia de comandă sau notebook.
|
||||
|
||||
<hfoptions id="share">
|
||||
<hfoption id="huggingface-CLI">
|
||||
|
||||
```bash
|
||||
hf auth login
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="notebook">
|
||||
|
||||
```py
|
||||
from huggingface_hub import notebook_login
|
||||
|
||||
notebook_login()
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
## Funcțiile repository-ului
|
||||
|
||||
<Youtube id="XvSGPZFEjDY"/>
|
||||
|
||||
Fiecare repository de model include versionare, istoricul commit-urilor și vizualizarea diff-urilor.
|
||||
|
||||
<div class="flex justify-center">
|
||||
<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/vis_diff.png"/>
|
||||
</div>
|
||||
|
||||
Versionarea se bazează pe [Git](https://git-scm.com/) și [Git Large File Storage (LFS)](https://git-lfs.github.com/) și permite revizuiri, o modalitate de a specifica o versiune a modelului cu un hash de commit, tag sau branch.
|
||||
|
||||
De exemplu, folosește parametrul `revision` în [`~PreTrainedModel.from_pretrained`] pentru a încărca o versiune specifică a modelului dintr-un hash de commit.
|
||||
|
||||
```py
|
||||
model = AutoModel.from_pretrained(
|
||||
"julien-c/EsperBERTo-small", revision="4c77982"
|
||||
)
|
||||
```
|
||||
|
||||
Repository-urile de modele suportă și [gating](https://hf.co/docs/hub/models-gated) pentru a controla cine poate accesa un model. Gating-ul este comun pentru a permite unui grup selectat de utilizatori să previzualizeze un model de cercetare înainte de a fi făcut public.
|
||||
|
||||
<div class="flex justify-center">
|
||||
<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/gated-model.png"/>
|
||||
</div>
|
||||
|
||||
Un repository de model include și un [widget](https://hf.co/docs/hub/models-widgets) de inferență pentru ca utilizatorii să interacționeze direct cu un model pe Hub.
|
||||
|
||||
Consultă documentația Hub [Models](https://hf.co/docs/hub/models) pentru mai multe informații.
|
||||
|
||||
## Încărcarea unui model pe Hub
|
||||
|
||||
Există mai multe modalități de a încărca un model pe Hub în funcție de preferința ta de workflow. Poți publica un model cu [`Trainer`], apela [`~PreTrainedModel.push_to_hub`] direct pe un model sau folosi interfața web a Hub-ului.
|
||||
|
||||
<Youtube id="Z1-XMy-GNLQ"/>
|
||||
|
||||
### Trainer
|
||||
|
||||
[`Trainer`] poate publica un model direct pe Hub după antrenare. Setează `push_to_hub=True` în [`TrainingArguments`] și pasează-l la [`Trainer`]. Odată ce antrenarea este completă, apelează [`~transformers.Trainer.push_to_hub`] pentru a încărca modelul.
|
||||
|
||||
[`~transformers.Trainer.push_to_hub`] adaugă automat informații utile precum hyperparameters de antrenare și rezultate la model card.
|
||||
|
||||
```py
|
||||
from transformers import TrainingArguments, Trainer
|
||||
|
||||
training_args = TrainingArguments(output_dir="my-awesome-model", push_to_hub=True)
|
||||
trainer = Trainer(
|
||||
model=model,
|
||||
args=training_args,
|
||||
train_dataset=small_train_dataset,
|
||||
eval_dataset=small_eval_dataset,
|
||||
compute_metrics=compute_metrics,
|
||||
)
|
||||
trainer.push_to_hub()
|
||||
```
|
||||
|
||||
### PushToHubMixin
|
||||
|
||||
[`~utils.PushToHubMixin`] oferă funcționalitate pentru publicarea unui model sau tokenizer pe Hub.
|
||||
|
||||
Apelează [`~utils.PushToHubMixin.push_to_hub`] direct pe un model pentru a-l încărca pe Hub. Creează un repository sub namespace-ul tău cu numele modelului specificat în [`~utils.PushToHubMixin.push_to_hub`].
|
||||
|
||||
```py
|
||||
model.push_to_hub("my-awesome-model")
|
||||
```
|
||||
|
||||
Alte obiecte precum un tokenizer sunt publicate pe Hub în același mod.
|
||||
|
||||
```py
|
||||
tokenizer.push_to_hub("my-awesome-model")
|
||||
```
|
||||
|
||||
Profilul tău Hugging Face ar trebui să afișeze acum repository-ul de model nou creat. Navighează la tab-ul **Files** pentru a vedea toate fișierele încărcate.
|
||||
|
||||
Consultă ghidul [Upload files to the Hub](https://hf.co/docs/hub/how-to-upstream) pentru mai multe informații despre publicarea fișierelor pe Hub.
|
||||
|
||||
### Interfața web a Hub-ului
|
||||
|
||||
Interfața web a Hub-ului este o abordare fără cod pentru încărcarea unui model.
|
||||
|
||||
1. Creează un nou repository selectând [**New Model**](https://huggingface.co/new).
|
||||
|
||||
<div class="flex justify-center">
|
||||
<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/new_model_repo.png"/>
|
||||
</div>
|
||||
|
||||
Adaugă câteva informații despre modelul tău:
|
||||
|
||||
- Selectează **owner**-ul repository-ului. Acesta poate fi tu însuți sau oricare dintre organizațiile din care faci parte.
|
||||
- Alege un nume pentru modelul tău, care va fi și numele repository-ului.
|
||||
- Alege dacă modelul tău este public sau privat.
|
||||
- Setează utilizarea licenței.
|
||||
|
||||
2. Click pe **Create model** pentru a crea repository-ul de model.
|
||||
|
||||
3. Selectează tab-ul **Files** și click pe butonul **Add file** pentru a trage și plasa un fișier în repository-ul tău. Adaugă un mesaj de commit și click pe **Commit changes to main** pentru a face commit fișierului.
|
||||
|
||||
<div class="flex justify-center">
|
||||
<img src="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/upload_file.png"/>
|
||||
</div>
|
||||
|
||||
## Model card
|
||||
|
||||
[Model card-urile](https://hf.co/docs/hub/model-cards#model-cards) informează utilizatorii despre performanța, limitările, posibilele biasuri și considerațiile etice ale unui model. Îți recomandăm cu căldură să adaugi un model card la repository-ul tău!
|
||||
|
||||
Un model card este un fișier `README.md` din repository-ul tău. Adaugă acest fișier prin:
|
||||
|
||||
- crearea și încărcarea manuală a unui fișier `README.md`
|
||||
- click pe butonul **Edit model card** din repository
|
||||
|
||||
Aruncă o privire la [model card-ul](https://huggingface.co/meta-llama/Meta-Llama-3.1-8B-Instruct) Llama 3.1 pentru un exemplu de ce să incluzi într-un model card.
|
||||
|
||||
Află mai multe despre metadata model card-ului (emisii de carbon, licență, link la articol, etc.) în ghidul [Model Cards](https://hf.co/docs/hub/model-cards#model-cards).
|
||||
255
docs/source/ro/modeling_rules.md
Normal file
255
docs/source/ro/modeling_rules.md
Normal file
@@ -0,0 +1,255 @@
|
||||
<!--Copyright 2026 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
-->
|
||||
|
||||
# Regulile de structură a modelului
|
||||
|
||||
Transformers aplică un set de reguli statice pe fiecare fișier `modeling_*.py`, `modular_*.py` și `configuration_*.py`. Pachetul [mlinter](https://github.com/huggingface/transformers-mlinter) furnizează motorul de verificare, iar repository-ul păstrează setul activ de reguli în `utils/rules.toml`. Acel fișier TOML local ne permite să activăm, dezactivăm sau ajustăm rapid regulile fără să așteptăm o nouă versiune de `transformers-mlinter`.
|
||||
|
||||
Acestea sunt convențiile pentru modele când adaugi sau modifici cod de modelare. Mențin codul consistent și asigură compatibilitatea cu features precum pipeline parallelism, device maps și weight tying.
|
||||
|
||||
## Rularea checker-ului
|
||||
|
||||
`make typing` rulează `mlinter` alături de type checker-ul `ty` prin wrapper-ul repository-ului, deci preia `utils/rules.toml`. Poți rula același wrapper direct cu comenzile de mai jos.
|
||||
|
||||
```bash
|
||||
python utils/check_modeling_structure.py # verifică toate fișierele de modelare
|
||||
python utils/check_modeling_structure.py --changed-only # verifică doar fișierele modificate față de origin/main
|
||||
python utils/check_modeling_structure.py --list-rules # listează toate regulile și statusul lor de activare
|
||||
python utils/check_modeling_structure.py --rule TRF001 # arată documentația built-in pentru o regulă specifică
|
||||
```
|
||||
|
||||
Flag-ul `--changed-only` este cea mai rapidă opțiune în timpul dezvoltării. Verifică doar fișierele pe care le-ai modificat față de branch-ul main. Dacă invoci `mlinter` direct în loc de wrapper, pasează `--rules-toml utils/rules.toml` ca să fie aplicate override-urile locale.
|
||||
|
||||
## Remedierea unei violări
|
||||
|
||||
Când se detectează o violare a unei reguli, eroarea arată astfel:
|
||||
|
||||
```
|
||||
src/transformers/models/acme/modeling_acme.py:18: TRF013: AcmeModel.__init__ does not call self.post_init().
|
||||
```
|
||||
|
||||
Folosește ID-ul regulii ca să cauți remedierea în [referința regulilor](#referința-regulilor). TRF013 se declanșează când o subclasă [`PreTrainedModel`] nu apelează `self.post_init()`. Metoda respectivă efectuează pași esențiali de finalizare, iar omiterea ei cauzează bug-uri la rulare.
|
||||
|
||||
```diff
|
||||
class AcmeModel(AcmePreTrainedModel):
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
self.layers = nn.ModuleList(
|
||||
[AcmeDecoderLayer(config) for _ in range(config.num_hidden_layers)]
|
||||
)
|
||||
+ self.post_init()
|
||||
```
|
||||
|
||||
## Referința regulilor
|
||||
|
||||
Fiecare regulă de mai jos listează ce impune și un diff care arată remedierea. Rulează `python utils/check_modeling_structure.py --rule TRF001` ca să vezi documentația built-in pentru orice regulă cu setul curent de reguli al repository-ului.
|
||||
|
||||
<!-- BEGIN RULES REFERENCE -->
|
||||
|
||||
### TRF001
|
||||
|
||||
Verifică consistența denumirii între <Model>PreTrainedModel și config_class. Un config_class nepotrivit poate strica încărcarea, clasele auto și așteptările developerilor.
|
||||
|
||||
```diff
|
||||
class AcmePreTrainedModel(PreTrainedModel):
|
||||
- config_class = WileConfig
|
||||
+ config_class = AcmeConfig
|
||||
```
|
||||
|
||||
### TRF002
|
||||
|
||||
Verifică dacă base_model_prefix, când este setat, este un string literal non-gol, fără spații albe. Prefixele invalide pot strica maparea cheilor la încărcarea de weights și pattern-urile de acces la modelul de bază.
|
||||
|
||||
```diff
|
||||
class AcmePreTrainedModel(PreTrainedModel):
|
||||
- base_model_prefix = ""
|
||||
+ base_model_prefix = "model"
|
||||
```
|
||||
|
||||
### TRF003
|
||||
|
||||
Detectează metodele forward care folosesc vechiul pattern 'if not return_dict: return (x,)'. Vechiul pattern de branching return_dict este predispus la erori și verbose. Folosește în schimb decoratorii capture_output sau can_return_tuple.
|
||||
|
||||
```diff
|
||||
-def forward(self, x, return_dict=None):
|
||||
- if not return_dict:
|
||||
- return (x,)
|
||||
- return AcmeModelOutput(last_hidden_state=x)
|
||||
+@can_return_tuple
|
||||
+def forward(self, x):
|
||||
+ return AcmeModelOutput(last_hidden_state=x)
|
||||
```
|
||||
|
||||
### TRF004
|
||||
|
||||
Verifică dacă nicio clasă de model nu definește o metodă tie_weights. Suprascrierea tie_weights duce la consecințe grave pentru încărcare, calculul device_map și salvare. Folosește atributul de clasă _tied_weights_keys ca să declari weights legate.
|
||||
|
||||
```diff
|
||||
-def tie_weights(self):
|
||||
- self.lm_head.weight = self.emb.weight
|
||||
+class AcmeForCausalLM(AcmePreTrainedModel):
|
||||
+ _tied_weights_keys = ["lm_head.weight"]
|
||||
```
|
||||
|
||||
### TRF005
|
||||
|
||||
Verifică forma lui _no_split_modules când este prezent. Valorile malformate pot strica partiționarea device-map și comportamentul de sharding.
|
||||
|
||||
```diff
|
||||
-_no_split_modules = [SomeLayerClass, ""]
|
||||
+_no_split_modules = ["AcmeDecoderLayer", "AcmeAttention"]
|
||||
```
|
||||
|
||||
### TRF006
|
||||
|
||||
Verifică forward signatures care expun argumente de cache pentru utilizarea acelor argumente în corpul metodei. Argumentele de cache neutilizate pot indica suport de caching incomplet și comportament inconsistent al API-ului.
|
||||
|
||||
```diff
|
||||
def forward(self, x, past_key_values=None, use_cache=False):
|
||||
+ if use_cache:
|
||||
+ ...
|
||||
return x
|
||||
```
|
||||
|
||||
### TRF007
|
||||
|
||||
Verifică atribuirile de atribute self după self.post_init() în __init__. Mutarea structurii modelului după post_init poate ocoli logica intenționată de inițializare/finalizare.
|
||||
|
||||
```diff
|
||||
def __init__(self, config):
|
||||
...
|
||||
- self.post_init()
|
||||
- self.proj = nn.Linear(...)
|
||||
+ self.proj = nn.Linear(...)
|
||||
+ self.post_init()
|
||||
```
|
||||
|
||||
### TRF008
|
||||
|
||||
Verifică utilizarea add_start_docstrings pe clasele de modele pentru argumente de docstring non-goale. Utilizarea cu decorator gol produce documentație neclară și slăbește calitatea documentației API generate.
|
||||
|
||||
```diff
|
||||
-@add_start_docstrings("")
|
||||
+@add_start_docstrings("The Acme model.")
|
||||
class AcmeModel(AcmePreTrainedModel):
|
||||
...
|
||||
```
|
||||
|
||||
### TRF009
|
||||
|
||||
Verifică fișierele de modelare pentru importuri cross-model precum transformers.models.other_model.* sau importuri from ..other_model.*. Importurile de implementare cross-model violează politica single-file și fac comportamentul modelului mai greu de inspectat și întreținut.
|
||||
|
||||
```diff
|
||||
-from transformers.models.llama.modeling_llama import LlamaAttention
|
||||
+# Păstrează implementarea locală în acest fișier.
|
||||
+# Dacă refolosești cod, copiază-l cu un comentariu # Copied from.
|
||||
```
|
||||
|
||||
### TRF010
|
||||
|
||||
Verifică subclasele directe PreTrainedConfig/PretrainedConfig din configuration_*.py și modular_*.py pentru un decorator explicit @strict(accept_kwargs=True). Fără strict, noile clase de config ratează contractul de validare de tip runtime al repository-ului și se abat de la standardul de config bazat pe dataclass.
|
||||
|
||||
```diff
|
||||
+@strict(accept_kwargs=True)
|
||||
class AcmeConfig(PreTrainedConfig):
|
||||
...
|
||||
```
|
||||
|
||||
### TRF011
|
||||
|
||||
În metodele forward() ale subclaselor PreTrainedModel, verifică accesele la atribute ale submodulelor care nu ar exista pe torch.nn.Identity. Aceasta include accesele la atribute pe variabilele de loop care iterează peste self.layers și lanțurile self.<submodule>.<attr> unde <attr> nu este un atribut standard al nn.Module. Pipeline parallelism poate înlocui orice submodul cu torch.nn.Identity. Accesarea atributelor personalizate (e.g. decoder_layer.attention_type) pe un modul înlocuit ridică AttributeError la rulare. Metadata per-layer trebuie citită din self.config.
|
||||
|
||||
```diff
|
||||
def forward(self, ...):
|
||||
- for decoder_layer in self.layers:
|
||||
+ for i, decoder_layer in enumerate(self.layers):
|
||||
hidden_states = decoder_layer(
|
||||
hidden_states,
|
||||
- attention_mask=causal_mask_mapping[decoder_layer.attention_type],
|
||||
+ attention_mask=causal_mask_mapping[self.config.layer_types[i]],
|
||||
)
|
||||
```
|
||||
|
||||
### TRF012
|
||||
|
||||
Verifică dacă _init_weights(self, module) nu folosește operații in-place (e.g. .normal_(), .zero_()) direct pe module weights. Ne bazăm pe flag-uri interne setate pe parametri ca să urmărim dacă au nevoie de re-inițializare. Operațiile in-place ocolesc acest mecanism. Folosește în schimb primitivele `init`.
|
||||
|
||||
```diff
|
||||
+from transformers import initialization as init
|
||||
+
|
||||
def _init_weights(self, module):
|
||||
- module.weight.normal_(mean=0.0, std=0.02)
|
||||
+ init.normal_(module.weight, mean=0.0, std=0.02)
|
||||
```
|
||||
|
||||
### TRF013
|
||||
|
||||
Verifică dacă fiecare subclasă PreTrainedModel cu o metodă __init__ apelează self.post_init(). În fișierele modulare, apelarea super().__init__() este de asemenea acceptată deoarece propagă post_init din părinte. post_init efectuează finalizarea esențială (inițializarea weights, configurarea gradient checkpointing-ului etc.). Omiterea lui cauzează bug-uri subtile la runtime.
|
||||
|
||||
```diff
|
||||
class AcmeModel(AcmePreTrainedModel):
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
self.layers = nn.ModuleList(...)
|
||||
+ self.post_init()
|
||||
```
|
||||
|
||||
### TRF014
|
||||
|
||||
Verifică dacă `trust_remote_code` este pasat sau folosit în cod (e.g. ca kwarg) în fișierele de integrare native ale modelului. `trust_remote_code` permite încărcarea arbitrară, inclusiv a binarelor, ceea ce ar trebui să fie o funcționalitate pentru utilizatori avansați, nu un use case standard. Integrările native nu trebuie să depindă de el, deoarece codul remote nu poate fi revizuit sau întreținut în transformers.
|
||||
|
||||
```diff
|
||||
class AcmeModel(AcmePreTrainedModel):
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
- self.model = AutoModel.from_pretrained(..., trust_remote_code=True)
|
||||
+ self.model = AutoModel.from_pretrained(...)
|
||||
```
|
||||
|
||||
### TRF015
|
||||
|
||||
Când o subclasă PreTrainedModel definește _tied_weights_keys ca o colecție non-goală, verifică dacă fișierul de configurare corespunzător declară un câmp tie_word_embeddings. Fără tie_word_embeddings în config, utilizatorii nu pot controla comportamentul de legare a weights-urilor. Modelul leagă weights-urile necondiționat, stricând serialization round-trip-urile și împiedicând fine-tuning-ul cu heads nelegate.
|
||||
|
||||
```diff
|
||||
# configuration_foo.py
|
||||
@strict(accept_kwargs=True)
|
||||
class FooConfig(PreTrainedConfig):
|
||||
hidden_size: int = 768
|
||||
+ tie_word_embeddings: bool = True
|
||||
```
|
||||
|
||||
<!-- END RULES REFERENCE -->
|
||||
|
||||
## Suprimarea violărilor
|
||||
|
||||
Dacă trebuie să suprimezi o violare a unei reguli, folosește una din cele două opțiuni de mai jos.
|
||||
|
||||
### Suprimare inline
|
||||
|
||||
Adaugă un comentariu `# trf-ignore: RULE_ID` pe linia violatoare. Include o explicație ca să înțeleagă reviewerii de ce suprimarea este justificată.
|
||||
|
||||
```py
|
||||
# trf-ignore: TRF011 — masca este derivată din self.config, nu din layer
|
||||
hidden_states = layer(hidden_states, attention_mask=mask_from_config)
|
||||
```
|
||||
|
||||
Nu folosi `trf-ignore` ca să ascunzi violări care ar trebui remediate în cod.
|
||||
|
||||
### `allowlist_models`
|
||||
|
||||
Pentru modelele cu cod legacy care nu poate fi remediat imediat, adaugă numele directorului modelului în lista `allowlist_models` a regulii relevante din [mlinter rules.toml](https://github.com/huggingface/transformers-mlinter/blob/main/mlinter/rules.toml).
|
||||
|
||||
```toml
|
||||
[rules.TRF004]
|
||||
allowlist_models = ["existing_model", "your_model_name"]
|
||||
```
|
||||
238
docs/source/ro/models.md
Normal file
238
docs/source/ro/models.md
Normal file
@@ -0,0 +1,238 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Încărcarea modelelor
|
||||
|
||||
Transformers oferă multe modele pre-antrenate gata de utilizare cu o singură linie de cod. Acestea necesită o clasă de model și metoda [`~PreTrainedModel.from_pretrained`].
|
||||
|
||||
Apelează [`~PreTrainedModel.from_pretrained`] pentru a descărca și încărca weights și configurația unui model stocate pe [Hub-ul Hugging Face](https://hf.co/models).
|
||||
|
||||
> [!TIP]
|
||||
> Metoda [`~PreTrainedModel.from_pretrained`] încarcă weights stocate în formatul de fișier [safetensors](https://hf.co/docs/safetensors/index) dacă sunt disponibile. În mod tradițional, weights modelelor PyTorch sunt serializate cu utilitarul [pickle](https://docs.python.org/3/library/pickle.html) care este cunoscut ca nesecurizat. Fișierele safetensors sunt mai sigure și mai rapid de încărcat.
|
||||
|
||||
```py
|
||||
from transformers import AutoModelForCausalLM
|
||||
|
||||
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf", device_map="auto")
|
||||
```
|
||||
|
||||
Acest ghid explică cum sunt încărcate modelele, diferitele moduri de a încărca un model, cum să depășești problemele de memorie pentru modele foarte mari și cum să încarci modele personalizate.
|
||||
|
||||
## Modele și configurații
|
||||
|
||||
Toate modelele au un fișier `configuration.py` cu atribute specifice precum numărul de hidden layers, dimensiunea vocabularului, funcția de activare și altele. Vei găsi și un fișier `modeling.py` care definește layers și operațiile matematice din interiorul fiecărui strat. Fișierul `modeling.py` preia atributele modelului din `configuration.py` și construiește modelul corespunzător. În acest moment, ai un model cu weights aleatorii care trebuie antrenat pentru a produce rezultate semnificative.
|
||||
|
||||
<!-- insert diagram of model and configuration -->
|
||||
|
||||
> [!TIP]
|
||||
> O *arhitectură* se referă la scheletul modelului, iar un *checkpoint* se referă la weights pentru o anumită arhitectură. De exemplu, [BERT] este o arhitectură, în timp ce [google-bert/bert-base-uncased](https://huggingface.co/google-bert/bert-base-uncased) este un checkpoint. Vei vedea termenul *model* utilizat interschimbabil cu arhitectura și checkpoint-ul.
|
||||
|
||||
Există două tipuri generale de modele pe care le poți încărca:
|
||||
|
||||
1. Un model de bază, precum [`AutoModel`] sau [`LlamaModel`], care returnează hidden states.
|
||||
2. Un model cu un *head* specific atașat, precum [`AutoModelForCausalLM`] sau [`LlamaForCausalLM`], pentru efectuarea unor task-uri specifice.
|
||||
|
||||
## Clasele de model
|
||||
|
||||
Pentru a obține un model pre-antrenat, trebuie să încarci weights în model. Acest lucru se face apelând [`~PreTrainedModel.from_pretrained`] care acceptă weights de pe Hub-ul Hugging Face sau dintr-un folder local.
|
||||
|
||||
Există două clase de model: clasa [AutoModel] și o clasă specifică modelului.
|
||||
|
||||
<hfoptions id="model-classes">
|
||||
<hfoption id="AutoModel">
|
||||
|
||||
<Youtube id="AhChOFRegn4"/>
|
||||
|
||||
Clasa [AutoModel] este o modalitate convenabilă de a încărca o arhitectură fără a fi nevoie să cunoști numele exact al clasei de model, deoarece există multe modele disponibile. Selectează automat clasa de model corectă pe baza fișierului de configurație. Trebuie să știi doar task-ul și checkpoint-ul pe care vrei să le utilizezi.
|
||||
|
||||
Comută ușor între modele sau task-uri, atât timp cât arhitectura este suportată pentru un task dat.
|
||||
|
||||
De exemplu, același model poate fi utilizat pentru task-uri separate.
|
||||
|
||||
```py
|
||||
from transformers import AutoModelForCausalLM, AutoModelForSequenceClassification, AutoModelForQuestionAnswering
|
||||
|
||||
# utilizează același API pentru 3 task-uri diferite
|
||||
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")
|
||||
model = AutoModelForSequenceClassification.from_pretrained("meta-llama/Llama-2-7b-hf")
|
||||
model = AutoModelForQuestionAnswering.from_pretrained("meta-llama/Llama-2-7b-hf")
|
||||
```
|
||||
|
||||
În alte cazuri, ai putea testa rapid mai multe modele diferite pentru un task.
|
||||
|
||||
```py
|
||||
from transformers import AutoModelForCausalLM
|
||||
|
||||
# utilizează același API pentru 3 modele diferite
|
||||
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")
|
||||
model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1")
|
||||
model = AutoModelForCausalLM.from_pretrained("google/gemma-7b")
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="model-specific class">
|
||||
|
||||
Clasa [AutoModel] este construită pe baza claselor specifice modelului. Toate clasele de model care suportă un task specific sunt mapate la clasa de task `AutoModelFor` corespunzătoare.
|
||||
|
||||
Dacă știi deja ce clasă de model vrei să utilizezi, poți folosi direct clasa specifică.
|
||||
|
||||
```py
|
||||
from transformers import LlamaModel, LlamaForCausalLM
|
||||
|
||||
model = LlamaForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf")
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
## Modele mari
|
||||
|
||||
Modelele mari pre-antrenate necesită multă memorie pentru a fi încărcate. Procesul de încărcare implică:
|
||||
|
||||
1. crearea unui model cu weights aleatoare
|
||||
2. încărcarea weights pre-antrenate
|
||||
3. plasarea weights pre-antrenate pe model
|
||||
|
||||
Ai nevoie de suficientă memorie pentru a reține două copii ale weights modelului (aleatoare și pre-antrenate), ceea ce poate să nu fie posibil în funcție de hardware-ul tău. În medii de antrenare distribuită, aceasta este și mai dificilă deoarece fiecare proces încarcă un model pre-antrenat.
|
||||
|
||||
Transformers reduce unele dintre aceste provocări legate de memorie prin inițializare rapidă, checkpoint-uri sharded, funcția [Big Model Inference](https://hf.co/docs/accelerate/usage_guides/big_modeling) din Accelerate și suportul pentru tipuri de date cu mai puțini biți.
|
||||
|
||||
### Checkpoint-uri sharded
|
||||
|
||||
[`~PreTrainedModel.save_pretrained`] shardează automat checkpoint-urile mai mari de 50GB. Aceasta menține numărul de shards redus pentru modelele mari și simplifică gestionarea fișierelor.
|
||||
|
||||
Parametrii se încarcă în paralel și vârful de memorie depinde doar de dimensiunea modelului. Utilizează `max_shard_size` în [`~PreTrainedModel.save_pretrained`] pentru a seta dimensiunea maximă a checkpoint-ului înainte de sharding.
|
||||
|
||||
> [!NOTE]
|
||||
> Utilizarea memoriei pentru modelele care necesită conversie dinamică de weights depinde de dimensiunea modelului și de dimensiunea celor mai mari parametri dintr-o singură conversie. Aceasta se aplică de obicei modelelor mixture-of-experts (MoE) unde utilizarea memoriei este dimensiunea modelului plus numărul de experți de pe un strat. Consultă ghidul [încărcarea dinamică a modelelor](./weightconverter#încărcarea-rapidă-și-eficientă-a-modelelor) pentru a afla mai multe despre cum sunt încărcate modelele.
|
||||
|
||||
[`~PreTrainedModel.save_pretrained`] creează și un fișier index care mapează numele parametrilor la fișierele lor de shard. Index-ul conține două chei, `metadata` și `weight_map`.
|
||||
|
||||
```py
|
||||
import json
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
model.save_pretrained(tmp_dir, max_shard_size="50GB")
|
||||
with open(os.path.join(tmp_dir, "model.safetensors.index.json"), "r") as f:
|
||||
index = json.load(f)
|
||||
|
||||
print(index.keys())
|
||||
```
|
||||
|
||||
`metadata` stochează dimensiunea totală a modelului.
|
||||
|
||||
```py
|
||||
index["metadata"]
|
||||
{'total_size': 28966928384}
|
||||
```
|
||||
|
||||
`weight_map` mapează fiecare parametru la fișierul său de shard.
|
||||
|
||||
```py
|
||||
index["weight_map"]
|
||||
{'lm_head.weight': 'model-00006-of-00006.safetensors',
|
||||
'model.embed_tokens.weight': 'model-00001-of-00006.safetensors',
|
||||
'model.layers.0.input_layernorm.weight': 'model-00001-of-00006.safetensors',
|
||||
'model.layers.0.mlp.down_proj.weight': 'model-00001-of-00006.safetensors',
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Big Model Inference
|
||||
|
||||
> [!TIP]
|
||||
> Asigură-te că ai Accelerate v0.9.0 și PyTorch v1.9.0 sau o versiune mai nouă instalate pentru a utiliza această funcție!
|
||||
|
||||
<Youtube id="MWCSGj9jEAo"/>
|
||||
|
||||
[`~PreTrainedModel.from_pretrained`] este potențat cu funcția [Big Model Inference](https://hf.co/docs/accelerate/usage_guides/big_modeling) din Accelerate.
|
||||
|
||||
Big Model Inference creează un *schelet de model* pe dispozitivul [meta](https://pytorch.org/docs/main/meta.html) PyTorch. Dispozitivul meta nu stochează date reale, doar metadata.
|
||||
|
||||
Weights inițializate aleatoriu sunt create doar când sunt încărcate weights pre-antrenate, pentru a evita menținerea în memorie a două copii ale modelului în același timp. Utilizarea maximă a memoriei este doar dimensiunea modelului.
|
||||
|
||||
> [!TIP]
|
||||
> Află mai multe despre plasarea pe dispozitive în [Designing a device map](https://hf.co/docs/accelerate/v0.33.0/en/concept_guides/big_model_inference#designing-a-device-map).
|
||||
|
||||
A doua funcție a Big Model Inference se referă la modul în care weights sunt încărcate și distribuite în scheletul modelului. Weights modelului sunt distribuite pe toate dispozitivele disponibile, începând cu cel mai rapid dispozitiv (de obicei GPU) și descărcând ulterior weights rămase pe dispozitive mai lente (CPU și hard disk).
|
||||
|
||||
Ambele funcții combinate reduc utilizarea memoriei și timpii de încărcare pentru modelele mari pre-antrenate.
|
||||
|
||||
Setează [device_map](https://github.com/huggingface/transformers/blob/026a173a64372e9602a16523b8fae9de4b0ff428/src/transformers/modeling_utils.py#L3061) la `"auto"` pentru a activa Big Model Inference.
|
||||
|
||||
```py
|
||||
from transformers import AutoModelForCausalLM
|
||||
|
||||
model = AutoModelForCausalLM.from_pretrained("google/gemma-7b", device_map="auto")
|
||||
```
|
||||
|
||||
Poți, de asemenea, să atribui manual straturi unui dispozitiv în `device_map`. Ar trebui să mapeze toți parametrii modelului la un dispozitiv, dar nu trebuie să detaliezi unde merg toate sub-modulele unui strat dacă întregul strat se află pe același dispozitiv.
|
||||
|
||||
Accesează atributul `hf_device_map` pentru a vedea cum este distribuit un model pe dispozitive.
|
||||
|
||||
```py
|
||||
device_map = {"model.layers.1": 0, "model.layers.14": 1, "model.layers.31": "cpu", "lm_head": "disk"}
|
||||
model.hf_device_map
|
||||
```
|
||||
|
||||
### Tipul de date al modelului
|
||||
|
||||
Argumentul `dtype` controlează [dtype-ul](https://pytorch.org/docs/stable/tensor_attributes.html#torch.dtype) PyTorch utilizat pentru a instanția weights modelului. În mod implicit, Transformers încarcă weights cu valoarea `dtype` sau a moștenitorului `torch_dtype` din `config.json`. Dacă `config.json` nu include niciuna dintre aceste valori, Transformers utilizează dtype-ul primului weight în virgulă mobilă din checkpoint.
|
||||
|
||||
Suprascrie valoarea implicită pasând un dtype specific.
|
||||
|
||||
```py
|
||||
import torch
|
||||
from transformers import AutoModelForCausalLM
|
||||
|
||||
# specific dtype
|
||||
model = AutoModelForCausalLM.from_pretrained("google/gemma-3-1b-it", dtype=torch.float16)
|
||||
```
|
||||
|
||||
[`AutoConfig`] acceptă de asemenea `dtype` pentru modelele instanțiate de la zero.
|
||||
|
||||
```py
|
||||
import torch
|
||||
from transformers import AutoConfig, AutoModel
|
||||
|
||||
my_config = AutoConfig.from_pretrained("google/gemma-2b", dtype=torch.float16)
|
||||
model = AutoModel.from_config(my_config)
|
||||
```
|
||||
|
||||
## Modele personalizate
|
||||
|
||||
Modelele personalizate se construiesc pe clasele de configurație și modelare ale Transformers, suportă API-ul [AutoClass](#autoclass) și sunt încărcate cu [`~PreTrainedModel.from_pretrained`]. Diferența este că codul de modelare *nu* provine din Transformers.
|
||||
|
||||
Fii atent la încărcarea unui model personalizat. Deși Hub-ul include [scanare de malware](https://hf.co/docs/hub/security-malware#malware-scanning) pentru fiecare repository, trebuie totuși să fii atent să nu execuți accidental cod malițios.
|
||||
|
||||
Setează `trust_remote_code=True` în [`~PreTrainedModel.from_pretrained`] pentru a încărca un model personalizat.
|
||||
|
||||
```py
|
||||
from transformers import AutoModelForImageClassification
|
||||
|
||||
model = AutoModelForImageClassification.from_pretrained("sgugger/custom-resnet50d", trust_remote_code=True)
|
||||
```
|
||||
|
||||
Ca un nivel suplimentar de securitate, încarcă un model personalizat dintr-o revizuire specifică pentru a evita încărcarea codului de model care ar putea fi schimbat. Hash-ul commit-ului poate fi copiat din [istoricul commit-urilor](https://hf.co/sgugger/custom-resnet50d/commits/main) modelului.
|
||||
|
||||
```py
|
||||
commit_hash = "ed94a7c6247d8aedce4647f00f20de6875b5b292"
|
||||
model = AutoModelForImageClassification.from_pretrained(
|
||||
"sgugger/custom-resnet50d", trust_remote_code=True, revision=commit_hash
|
||||
)
|
||||
```
|
||||
|
||||
Consultă ghidul [Personalizarea modelelor](./custom_models) pentru mai multe informații.
|
||||
500
docs/source/ro/modular_transformers.md
Normal file
500
docs/source/ro/modular_transformers.md
Normal file
@@ -0,0 +1,500 @@
|
||||
<!--Copyright 2025 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
-->
|
||||
|
||||
# Adaugă un model cu transformers modulare
|
||||
|
||||
Transformers modulare reduce codul necesar pentru a adăuga un model, permițând importuri și moștenire, spre deosebire de politica [un model, un fișier](https://huggingface.co/blog/transformers-design-philosophy). În loc să repeți componentele modelului în mai multe fișiere, adaugi un fișier *modular* în folder-ul modelului și moștenește din clasele existente.
|
||||
|
||||
Un convertor generează fișiere standalone din fișierul modular. Utilizatorii primesc aceeași interfață single-file cu care sunt obișnuiți.
|
||||
|
||||
> [!NOTE]
|
||||
> Transformers modulare nu e menit să înlocuiască [codul de modelare legacy](./add_new_model). Dacă modelul tău nu se bazează pe un model existent, adaugă manual un fișier `modeling.py`. Același lucru se aplică fișierelor de configurare, de tokenization sau procesare care nu pot moșteni dintr-un fișier similar.
|
||||
>
|
||||
> Nu există nicio ordine unică corectă. Unii contributori scriu mai întâi fișierul modular și generează din el. Alții încep cu un fișier `modeling.py` scris manual și îl refactorizează ulterior într-un fișier modular. Ambele abordări funcționează.
|
||||
|
||||
## Implementarea unui fișier modular
|
||||
|
||||
Începe prin a găsi un model în Transformers similar cu al tău. Puncte de plecare bune sunt [Mistral], [Qwen2], [Cohere], [Cohere2] și [Llama]. Tabelul de mai jos mapează componentele comune la modele din care poți moșteni.
|
||||
|
||||
| Componentă | Model |
|
||||
|---|---|
|
||||
| Mixture of experts | Mixtral sau Qwen2-MoE |
|
||||
| Interleaved (și/sau parțial) rotary embedding | GLM, Phi |
|
||||
| State space models | Jamba, Bamba, Zamba, Mamba2 |
|
||||
| Recurrent hidden states | Gemma2 |
|
||||
| Sliding window attention/full attention patterns per layer | Gemma2, Cohere2 |
|
||||
| QKV clipping | Olmo |
|
||||
| QK normalization | Olmo2, Cohere |
|
||||
| Fused QKV (nu se recomandă) | Phi3 |
|
||||
|
||||
> [!TIP]
|
||||
> Folosește instrumentul [modular-detector-v2](https://huggingface.co/spaces/Molbap/modular-detector-v2) pentru a găsi implementări existente din care să moștenești. Introdu un snippet de cod și îți returnează cele mai similare metode deja existente în Transformers, ca să identifici cea mai bună clasă părinte înainte să începi să scrii.
|
||||
|
||||
Nu modifica un model existent doar ca să faci moștenirea să funcționeze pentru cel nou. Dacă redenumirea sau subclasarea unei clase părinte este prea incomodă, copiază direct codul relevant.
|
||||
|
||||
Creează `src/transformers/models/<name>/modular_<name>.py`, unde `<name>` corespunde numelui directorului modelului în snake_case. Această secțiune te ghidează prin implementarea [Olmo2] din [Olmo] cu abordarea modulară (consultă fișierul original [modular_olmo2.py](../../../src/transformers/models/olmo2/modular_olmo2)).
|
||||
|
||||
### Config
|
||||
|
||||
Există două puncte în care [`Olmo2Config`] diferă de [`OlmoConfig`].
|
||||
|
||||
1. Există un argument nou, `rms_norm_eps`.
|
||||
2. Argumentul `clip_qkv` nu mai este folosit.
|
||||
|
||||
Declară argumentele noi ca adnotări de tip la nivel de clasă cu o valoare implicită. Pentru argumentele eliminate, atribuie `AttributeError()` ca să suprimi atributul moștenit în fișierul generat (vezi [Eliminarea atributelor](#eliminarea-atributelor)).
|
||||
|
||||
```diff
|
||||
- @auto_docstring(checkpoint="allenai/OLMo-7B-hf")
|
||||
+ @auto_docstring(checkpoint="allenai/Olmo2-7B-1124-hf")
|
||||
+ @strict
|
||||
- class OlmoConfig(PreTrainedConfig):
|
||||
+ class Olmo2Config(OlmoConfig):
|
||||
...
|
||||
- model_type = "olmo"
|
||||
+ model_type = "olmo2"
|
||||
...
|
||||
+ rms_norm_eps: float = 1e-5
|
||||
- clip_qkv: float | None = None
|
||||
+ clip_qkv = AttributeError()
|
||||
```
|
||||
|
||||
`@auto_docstring` generează automat documentația standard pentru argumente (vezi ghidul [@auto_docstring](./auto_docstring)). `@strict` respinge kwargs necunoscute la momentul instanțierii, prinde greșelile de scriere și argumentele depășite din timp. Adaugă ambele la fiecare clasă de config pentru că decoratorii nu sunt moșteniți din părinte. Declară-i explicit chiar dacă config-ul părinte îi are deja.
|
||||
|
||||
Pentru a seta un atribut derivat sau a gestiona logica de compatibilitate înapoi, folosește `__post_init__` în loc de `__init__`. De exemplu, Cohere2 calculează `head_dim` și derivă `layer_types` la momentul inițializării.
|
||||
|
||||
```py
|
||||
def __post_init__(self, **kwargs):
|
||||
if self.num_key_value_heads is None:
|
||||
self.num_key_value_heads = self.num_attention_heads
|
||||
self.head_dim = self.hidden_size // self.num_attention_heads
|
||||
super().__post_init__(**kwargs)
|
||||
```
|
||||
|
||||
Pentru modelele cu suport de tensor sau pipeline parallelism, definește `base_model_tp_plan` și `base_model_pp_plan` ca dicționare la nivel de clasă pe config. Ambele dicționare definesc cum să se facă sharding-ul modelului pe dispozitive. Vezi config-urile existente precum [Olmo2](../../../src/transformers/models/olmo2/modular_olmo2) sau [Cohere2](../../../src/transformers/models/cohere2/modular_cohere2) pentru exemple.
|
||||
|
||||
```py
|
||||
class MyNewModelConfig(PreTrainedConfig):
|
||||
model_type = "my_new_model"
|
||||
|
||||
# Tensor parallelism: mapează pattern-uri de nume de layers la strategii de sharding.
|
||||
# Folosește "colwise" / "rowwise" pentru sharding standard, sau variantele "gather_output" /
|
||||
# "split_input" când o operație suplimentară (e.g. un QK norm) împiedică fuzionarea.
|
||||
base_model_tp_plan = {
|
||||
"layers.*.self_attn.q_proj": "colwise",
|
||||
"layers.*.self_attn.k_proj": "colwise",
|
||||
"layers.*.self_attn.v_proj": "colwise",
|
||||
"layers.*.self_attn.o_proj": "rowwise",
|
||||
"layers.*.mlp.gate_proj": "colwise",
|
||||
"layers.*.mlp.up_proj": "colwise",
|
||||
"layers.*.mlp.down_proj": "rowwise",
|
||||
}
|
||||
|
||||
# Pipeline parallelism: mapează numele submodulelor la numele tensorilor (input, output).
|
||||
base_model_pp_plan = {
|
||||
"embed_tokens": (["input_ids"], ["inputs_embeds"]),
|
||||
"layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
|
||||
"norm": (["hidden_states"], ["hidden_states"]),
|
||||
}
|
||||
```
|
||||
|
||||
### Norm
|
||||
|
||||
Ca să copiezi o clasă părinte fără modificări, moștenește cu `pass`. Linter-ul copiază conținutul părintelui și redenumește toate referințele să corespundă noului model.
|
||||
|
||||
```py
|
||||
from ..olmo.modeling_olmo import OlmoRotaryEmbedding
|
||||
|
||||
class Olmo2RotaryEmbedding(OlmoRotaryEmbedding):
|
||||
pass
|
||||
```
|
||||
|
||||
Ca să schimbi un comportament specific, moștenește și suprascrie doar ce diferă. [`Olmo2RMSNorm`] diferă de [`LlamaRMSNorm`] pe o singură linie. Înmulțirea se face *înainte* de a converti înapoi la input dtype, nu după.
|
||||
|
||||
```diff
|
||||
from ..llama.modeling_llama import LlamaRMSNorm
|
||||
|
||||
class Olmo2RMSNorm(LlamaRMSNorm):
|
||||
def forward(self, hidden_states):
|
||||
input_dtype = hidden_states.dtype
|
||||
hidden_states = hidden_states.to(torch.float32)
|
||||
variance = hidden_states.pow(2).mean(-1, keepdim=True)
|
||||
hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
|
||||
- return self.weight * hidden_states.to(input_dtype)
|
||||
+ return (self.weight * hidden_states).to(input_dtype)
|
||||
```
|
||||
|
||||
### Attention
|
||||
|
||||
Attention-ul lui Olmo2 este identic cu cel al lui Olmo, cu excepția că aplică [`RMSNorm`] la queries și keys și elimină qkv clipping. `super().__init__(...)` copiază corpul părintelui și adaugă cele două linii noi de normalizare. `forward`-ul este redefinit complet pentru că queries și keys trec acum prin norme înainte de proiecție. Linter-ul trage și orice funcții importate în fișierul generat, inclusiv `apply_rotary_pos_emb`, `eager_attention_forward` și dependecies.
|
||||
|
||||
```diff
|
||||
class Olmo2Attention(OlmoAttention):
|
||||
def __init__(self, config: Olmo2Config, layer_idx: int | None = None):
|
||||
super().__init__(config, layer_idx=layer_idx)
|
||||
+ self.q_norm = Olmo2RMSNorm(config.num_attention_heads * self.head_dim, config.rms_norm_eps)
|
||||
+ self.k_norm = Olmo2RMSNorm(config.num_key_value_heads * self.head_dim, config.rms_norm_eps)
|
||||
|
||||
def forward(self, ...):
|
||||
...
|
||||
- query_states = self.q_proj(hidden_states)
|
||||
- key_states = self.k_proj(hidden_states)
|
||||
+ query_states = self.q_norm(self.q_proj(hidden_states))
|
||||
+ key_states = self.k_norm(self.k_proj(hidden_states))
|
||||
value_states = self.v_proj(hidden_states)
|
||||
|
||||
- if self.config.clip_qkv is not None:
|
||||
- query_states.clamp_(min=-self.config.clip_qkv, max=self.config.clip_qkv)
|
||||
- key_states.clamp_(min=-self.config.clip_qkv, max=self.config.clip_qkv)
|
||||
- value_states.clamp_(min=-self.config.clip_qkv, max=self.config.clip_qkv)
|
||||
-
|
||||
...
|
||||
```
|
||||
|
||||
### DecoderLayer
|
||||
|
||||
După `super().__init__(...)`, suprascrie atributele de normalizare cu instanțe `Olmo2RMSNorm` și reatribuie `self.self_attn` la noua clasă `Olmo2Attention`. `del self.input_layernorm` elimină atribuirea `input_layernorm` a părintelui deoarece Olmo2 aplică norma *după* attention, nu înainte. Vezi [Eliminarea atributelor](#eliminarea-atributelor) pentru detalii despre ce face și ce nu face `del`.
|
||||
|
||||
`forward`-ul este rescris pentru a reflecta plasarea normei post-attention. O rescriere a `forward`-ului este necesară doar când un atribut este redenumit, nu când îi schimbi doar tipul.
|
||||
|
||||
```diff
|
||||
class Olmo2DecoderLayer(OlmoDecoderLayer):
|
||||
def __init__(self, config: Olmo2Config, layer_idx: int):
|
||||
super().__init__(config, layer_idx=layer_idx)
|
||||
- self.self_attn = OlmoAttention(config=config, layer_idx=layer_idx)
|
||||
- self.input_layernorm = OlmoLayerNorm(config.hidden_size)
|
||||
- self.post_attention_layernorm = OlmoLayerNorm(config.hidden_size)
|
||||
+ self.self_attn = Olmo2Attention(config=config, layer_idx=layer_idx)
|
||||
+ del self.input_layernorm
|
||||
+ self.post_attention_layernorm = Olmo2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
||||
+ self.post_feedforward_layernorm = Olmo2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
||||
|
||||
def forward(self, ...):
|
||||
residual = hidden_states
|
||||
- hidden_states = self.input_layernorm(hidden_states)
|
||||
# Self Attention
|
||||
hidden_states, _ = self.self_attn(...)
|
||||
- hidden_states = residual + hidden_states
|
||||
+ hidden_states = self.post_attention_layernorm(hidden_states)
|
||||
+ hidden_states = residual + hidden_states
|
||||
|
||||
# Fully Connected
|
||||
residual = hidden_states
|
||||
- hidden_states = self.post_attention_layernorm(hidden_states)
|
||||
hidden_states = self.mlp(hidden_states)
|
||||
- hidden_states = residual + hidden_states
|
||||
+ hidden_states = self.post_feedforward_layernorm(hidden_states)
|
||||
+ hidden_states = residual + hidden_states
|
||||
return hidden_states
|
||||
```
|
||||
|
||||
### Model
|
||||
|
||||
Doar tipul lui `self.norm` se schimbă aici. Metoda `forward` este identică cu cea a părintelui, deci linter-ul o preia automat.
|
||||
|
||||
```diff
|
||||
class Olmo2Model(OlmoModel):
|
||||
def __init__(self, config: Olmo2Config):
|
||||
super().__init__(config)
|
||||
- self.layers = nn.ModuleList(
|
||||
- [OlmoDecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
||||
- )
|
||||
- self.norm = OlmoLayerNorm(config.hidden_size)
|
||||
+ self.norm = Olmo2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
||||
+ self.layers = nn.ModuleList(
|
||||
+ [Olmo2DecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
||||
+ )
|
||||
```
|
||||
|
||||
### Model head
|
||||
|
||||
Logica este identică cu [`OlmoForCausalLM`], deci nu sunt necesare modificări.
|
||||
|
||||
```py
|
||||
from ..olmo.modeling_olmo import OlmoForCausalLM
|
||||
|
||||
class Olmo2ForCausalLM(OlmoForCausalLM):
|
||||
pass
|
||||
```
|
||||
|
||||
### Alte clase
|
||||
|
||||
Fișierul [modeling_olmo2.py](../../../src/transformers/models/olmo2/modeling_olmo2) generat de linter conține și clase ([`Olmo2MLP`], [`Olmo2RotaryEmbedding`], [`Olmo2PreTrainedModel`]) care nu au fost definite explicit în `modular_olmo2.py`.
|
||||
|
||||
Linter-ul trage orice clasă de care depinde o clasă moștenită, dacă nu o redefinești explicit. Funcțiile importate precum `apply_rotary_pos_emb` urmează aceeași regulă.
|
||||
|
||||
De exemplu, [`OlmoDecoderLayer`] are `self.mlp = OlmoMLP(config)`. [`Olmo2MLP`] n-a fost definit niciodată în fișierul modular, deci linter-ul îl creează automat, echivalent cu folosirea `pass`.
|
||||
|
||||
```py
|
||||
from ..olmo.modeling_olmo import OlmoMLP
|
||||
|
||||
class Olmo2MLP(OlmoMLP):
|
||||
pass
|
||||
```
|
||||
|
||||
Dacă vrei ca [`Olmo2MLP`] să moștenească dintr-un model diferit, fii explicit.
|
||||
|
||||
```py
|
||||
# trece la definiția Mistral
|
||||
from ..mistral.modeling_mistral import MistralMLP
|
||||
|
||||
class Olmo2MLP(MistralMLP):
|
||||
pass
|
||||
```
|
||||
|
||||
### Finalizarea fișierului
|
||||
|
||||
Fiecare fișier modular trebuie să declare un `logger` și o listă `__all__` la nivel de modul.
|
||||
|
||||
```py
|
||||
logger = logging.get_logger(__name__)
|
||||
|
||||
__all__ = [
|
||||
"Olmo2Config",
|
||||
"Olmo2ForCausalLM",
|
||||
"Olmo2Model",
|
||||
"Olmo2PreTrainedModel",
|
||||
]
|
||||
```
|
||||
|
||||
`__all__` trebuie să listeze fiecare clasă publică din fișier. Convertorul și importurile din aval depind de aceasta. O clasă lipsă din `__all__` nu va fi exportată corect.
|
||||
|
||||
## Generarea fișierelor de modelare
|
||||
|
||||
Script-ul `modular_model_converter.py` generează fișiere standalone `modeling.py`, `configuration.py` și altele din fișierul tău modular. Pentru fiecare clasă moștenită, copiază corpul părintelui în copil, redenumește toate referințele să corespundă noului model și trage orice funcții sau clase ajutătoare de care depind acei părinți.
|
||||
|
||||
Fișierele de ieșire nu conțin importuri cross-model și nu moștenesc din alte directoare de modele. Linter-ul aplatizează moștenirea la un singur nivel. Dacă [`Olmo2Attention`] moștenește din [`OlmoAttention`], `Olmo2Attention`-ul generat este complet autonom. Dar dacă `OlmoAttention` însuși a moștenit din altceva, linter-ul nu inlinează acel strămoș.
|
||||
|
||||
Rulează comanda de mai jos pentru a genera fișiere dintr-un fișier modular.
|
||||
|
||||
```bash
|
||||
python utils/modular_model_converter.py your_model
|
||||
```
|
||||
|
||||
Nu edita niciodată direct fișierele generate, pentru că orice modificări vor fi suprascrise la următoarea rulare.
|
||||
|
||||
## Tipare pentru fișierele modulare
|
||||
|
||||
Secțiunile de mai jos documentează tipare comune de utilizare, cum ar fi eliminarea atributelor sau suprascrierea metodelor decorate, când lucrezi cu un fișier modular.
|
||||
|
||||
### Eliminarea atributelor
|
||||
|
||||
Eliminarea unui atribut moștenit depinde de dacă lucrezi cu o clasă de config sau o subclasă `nn.Module`.
|
||||
|
||||
Pentru o clasă de config, atribuie `AttributeError()` la atribut la nivel de clasă.
|
||||
|
||||
```py
|
||||
class MyNewConfig(ParentConfig):
|
||||
removed_attr = AttributeError()
|
||||
```
|
||||
|
||||
Linter-ul elimină complet declarația atributului din fișierul de config generat. Clasele de config folosesc un layout de tip dataclass fără `__init__`, deci atribuirea `AttributeError()` la nivel de clasă este abordarea corectă.
|
||||
|
||||
Pentru o subclasă `nn.Module`, folosește `del self.attribute` după `super().__init__(...)`.
|
||||
|
||||
```py
|
||||
class MyNewModel(ParentModel):
|
||||
def __init__(self, config: MyNewConfig):
|
||||
super().__init__(config)
|
||||
del self.attribute
|
||||
```
|
||||
|
||||
`del self.attribute` elimină doar linia de atribuire `self.attribute = ...` din corpul copiat al părintelui. Nu elimină alte linii care fac referire la `self.attribute`. Dacă `forward`-ul părintelui sau alte metode fac referire la atribut, suprascrie și acele metode.
|
||||
|
||||
```py
|
||||
class DummyModel(nn.Module):
|
||||
def __init__(self, config: DummyConfig):
|
||||
super().__init__()
|
||||
self.attribute = config.attribute
|
||||
if self.attribute:
|
||||
# fă mai multe lucruri cu `self.attribute` aici
|
||||
...
|
||||
|
||||
class MyNewDummyModel(DummyModel):
|
||||
def __init__(self, config: MyNewDummyConfig):
|
||||
super().__init__(config)
|
||||
del self.attribute
|
||||
# 'self.attribute = config.attribute' este eliminat, dar blocul 'if self.attribute:' rămâne.
|
||||
# Suprascrie forward() sau orice altă metodă care face referire la self.attribute.
|
||||
```
|
||||
|
||||
### Utilizarea `super()`
|
||||
|
||||
`super().__init__(config)` îi spune convertorului să copieze corpul părintelui în copil. Două tipare îți permit să suprascrii acest comportament.
|
||||
|
||||
- Apelează direct o clasă părinte specifică când ai nevoie ca ieșirea generată să apeleze un strămoș (`nn.Module.__init__`) în loc de părintele modular.
|
||||
- Folosește `**super_kwargs` pentru a moșteni semnătura completă a metodei unui părinte, adăugând în același timp un docstring personalizat sau schimbând un decorator.
|
||||
|
||||
#### Apelarea directă a unui strămoș
|
||||
|
||||
Fii explicit despre ce clasă apelezi când ai nevoie ca `super()` să țintească părintele clasei generate în loc de părintele modular. Exemplul de mai jos apelează direct `nn.Module.__init__(self)`. `DummyModule` este el însuși un `nn.Module`, deci convertorul îl scrie ca `super().__init__()` în `MyNewDummyModule`-ul generat.
|
||||
|
||||
```py
|
||||
class MyNewDummyModule(DummyModule): | class MyNewDummyModule(nn.Module):
|
||||
|
|
||||
def __init__(self): | def __init__(self):
|
||||
nn.Module.__init__(self) | super().__init__()
|
||||
self.foo = config.foo | self.foo = config.foo
|
||||
... | ...
|
||||
```
|
||||
|
||||
#### super_kwargs
|
||||
|
||||
Folosește `**super_kwargs` pentru a moșteni semnătura completă a metodei unui părinte, adăugând în același timp un docstring personalizat sau schimbând un decorator. În semnătura suprascrisă, îi spune linter-ului să expandeze toate argumentele părintelui în ieșirea generată.
|
||||
|
||||
Cel mai comun use case este adăugarea unui docstring specific modelului, cum ar fi documentarea argumentului `labels`, fără a rescrie semnătura completă.
|
||||
|
||||
```py
|
||||
# modular_gemma.py
|
||||
class GemmaForCausalLM(LlamaForCausalLM):
|
||||
def forward(**super_kwargs):
|
||||
r"""
|
||||
Example:
|
||||
|
||||
```python
|
||||
>>> from transformers import AutoTokenizer, GemmaForCausalLM
|
||||
>>> model = GemmaForCausalLM.from_pretrained("google/gemma-7b")
|
||||
...
|
||||
```"""
|
||||
return super().forward(**super_kwargs)
|
||||
```
|
||||
|
||||
`GemmaForCausalLM.forward`-ul generat are semnătura completă a lui `LlamaForCausalLM` fără copiere manuală.
|
||||
|
||||
`**super_kwargs` este o scurtătură pentru cazuri de nișă. Dacă schimbi comportamentul, scrie semnătura completă.
|
||||
|
||||
### Ștergerea metodelor neutilizate
|
||||
|
||||
Elimină o metodă a părintelui suprascriind-o cu o instrucțiune `raise AttributeError("")`. Linter-ul elimină metoda din fișierul generat.
|
||||
|
||||
```py
|
||||
class GemmaTokenizer(LlamaTokenizer):
|
||||
...
|
||||
|
||||
def get_spm_processor(self):
|
||||
raise AttributeError("Not needed for Gemma")
|
||||
|
||||
def unk_token_length(self):
|
||||
raise AttributeError("Not needed for Gemma")
|
||||
```
|
||||
|
||||
### Suprascrierea metodelor decorate
|
||||
|
||||
Când suprascrieți o metodă decorată a părintelui, decoratorul părintelui se transferă automat. Dacă adaugi propriul decorator, acesta îl înlocuiește pe cel al părintelui.
|
||||
|
||||
Două decoratoare apar frecvent în librărie: unul pentru [capturarea ieșirilor intermediare ale modelului](./model_output_tracing) și unul pentru [auto-generarea docstring-urilor](./auto_docstring).
|
||||
|
||||
În exemplul de mai jos, o subclasă suprascrie o metodă decorată a părintelui fără a adăuga propriul decorator. Decoratorul părintelui se transferă.
|
||||
|
||||
```py
|
||||
class NewModel(DummyModel): | class NewModel(nn.Module):
|
||||
... | ...
|
||||
|
|
||||
def forward(...): | @decorator(...)
|
||||
... | def forward(...):
|
||||
| ...
|
||||
```
|
||||
|
||||
Dacă adaugi un decorator nou, decoratorul tău îl înlocuiește pe cel al părintelui.
|
||||
|
||||
```py
|
||||
class NewModel(DummyModel): | class NewModel(nn.Module):
|
||||
... | ...
|
||||
|
|
||||
@my_new_decorator(...) | @my_new_decorator(...)
|
||||
def forward(...): | def forward(...):
|
||||
... | ...
|
||||
```
|
||||
|
||||
### Denumire specială
|
||||
|
||||
Linter-ul redenumește automat totul când moștenești dintr-o clasă. Folosește același prefix de nume de clasă în toate clasele din același fișier.
|
||||
|
||||
Evită amestecarea prefixelor ca în exemplul de mai jos. `MyModelIncredibleMLP` încalcă convențiile de denumire și linter-ul nu va ști dacă să folosească `MyModelIncredible` sau `MyModel` la redenumirea dependențelor de ordin superior.
|
||||
|
||||
```py
|
||||
class MyModelIncredibleMLP(LlamaMLP):
|
||||
...
|
||||
|
||||
class MyModelDecoderLayer(LlamaDecoderLayer):
|
||||
...
|
||||
```
|
||||
|
||||
Fără [dependențe implicite](#alte-clase), poți redenumi o singură clasă local. Redefinește explicit fiecare altă mențiune a acelei clase cu noul tipar de nume. Altfel, linter-ul adaugă o clasă `MyModelMLP` nedorită alături de `MyModelIncredibleMLP`.
|
||||
|
||||
Linter-ul ridică un avertisment când detectează un prefix ambiguu.
|
||||
|
||||
```text
|
||||
We detected multiple prefix names when inheriting from transformers.models.llama.modeling_llama: ('Emu3Text', 'Emu3'). We will only use the most used 'Emu3' prefix when grabbing args and dependencies. Make sure to subclass the intermediate classes with the prefix you want (if different from 'Emu3') or use a single prefix in all the modular (best).
|
||||
```
|
||||
|
||||
Prefixele ambigue sunt cele mai comune în modelele multimodale unde numele claselor includ un calificativ de modalitate precum `Text`. Ca să dai unei dependențe un prefix specific, redenumește-o explicit cu un `pass`.
|
||||
|
||||
```py
|
||||
class Emu3TextMLP(LlamaMLP):
|
||||
pass
|
||||
```
|
||||
|
||||
### Docstring-uri pentru config
|
||||
|
||||
Linter-ul nu suportă încă moștenirea parțială a docstring-urilor. Când adaugi sau elimini atribute de config, adaugă docstring-ul complet direct în fișierul modular sub definiția clasei.
|
||||
|
||||
## Conversia checkpoint-urilor
|
||||
|
||||
Odată ce ai generat fișierele de modelare, verifică că weights-urile reale se încarcă corect. Scrie un script de conversie pentru a traduce formatul checkpoint-ului upstream într-unul compatibil cu Transformers, apoi salvează-l pe Hub.
|
||||
|
||||
### Scrie un script de conversie
|
||||
|
||||
Adaugă un fișier `convert_<model>_to_hf.py` în `src/transformers/models/<model>/`. Scriptul încarcă weights-urile upstream, redenumește și remodelează cheile să corespundă numelor parametrilor modulului tău și salvează rezultatul cu [`~PreTrainedModel.save_pretrained`].
|
||||
|
||||
> [!TIP]
|
||||
> Caută un script existent pe care să îl copiezi și adaptezi. Modelele din `src/transformers/models/` includ un `convert_*_to_hf.py` pe care îl poți folosi ca punct de plecare.
|
||||
|
||||
După rularea scriptului, încarcă checkpoint-ul salvat cu [`~PreTrainedModel.from_pretrained`] și confirmă că fiecare weight s-a încărcat corect. Cheile de checkpoint neutilizate indică nume nepotrivite, deci printează-le ca să detectezi problemele din timp.
|
||||
|
||||
```py
|
||||
model = YourModelForTask.from_pretrained("path/to/output/")
|
||||
```
|
||||
|
||||
Verifică potrivirile de formă și nume când iterezi peste chei. Nepotrivirile de formă indică de obicei că un parametru din config este greșit, că arhitectura diferă de cea originală sau că un weight trebuie transpus.
|
||||
|
||||
```py
|
||||
for key, tensor in original_state_dict.items():
|
||||
hf_tensor = hf_model.state_dict().get(mapped_key)
|
||||
assert hf_tensor.shape == tensor.shape, (
|
||||
f"Shape mismatch for {key}: expected {tensor.shape}, got {hf_tensor.shape}"
|
||||
)
|
||||
```
|
||||
|
||||
Rezolvă orice problemă iterând între fișierul modular, fișierul de modelare generat și scriptul de conversie până când toate weights-urile se încarcă curat.
|
||||
|
||||
Odată ce checkpoint-ul se încarcă curat, publicați-l pe Hub cu [`~PreTrainedModel.push_to_hub`]. Consultă ghidul [distribuirea modelelor](./model_sharing) pentru mai multe detalii.
|
||||
|
||||
```py
|
||||
model.push_to_hub("username/your-model-name")
|
||||
```
|
||||
|
||||
### Maparea conversiei la runtime
|
||||
|
||||
Adaugă o mapare runtime în `src/transformers/conversion_mapping.py` când weights publicate nu corespund layout-ului de parametri al modulului tău. Cazurile comune includ weights fuzionate stocate separat și tensorii de experți MoE care trebuie stivuiți. Maparea permite ca [`~PreTrainedModel.from_pretrained`] să încarce checkpoint-ul de pe Hub fără un pas de export separat.
|
||||
|
||||
Consultă ghidul [încărcarea dinamică de weights](./weightconverter) pentru cum să scrii reguli [`WeightRenaming`] și [`WeightConverter`] și să le înregistrezi pentru `model_type`-ul tău.
|
||||
|
||||
## Pașii următori
|
||||
|
||||
- [Regulile de structură a modelului](./modeling_rules) sunt reguli statice aplicate pe toate fișierele `modeling_*.py`, `modular_*.py` și `configuration_*.py`. Rulează `make typing` să le verifici înainte de a deschide un PR.
|
||||
- [Adaugă componente de procesare vizuală](./add_vision_processing_components) te ghidează prin adăugarea unui procesor de imagini, procesor video și procesor pentru un model multimodal.
|
||||
- [Auto-generarea docstring-urilor](./auto_docstring) arată cum să folosești `@auto_docstring` ca să nu scrii manual documentația pentru argumente la API-uri comune.
|
||||
- [Scrierea testelor pentru modele](./testing) acoperă cum să scrii teste de integrare pentru noul tău model și să le rulezi local.
|
||||
- [Verificările pentru pull request](./pr_checks) explică verificările CI pe care PR-ul tău trebuie să le treacă înainte de a fi integrat și cum să le reproduci și rezolvi local.
|
||||
528
docs/source/ro/monkey_patching.md
Normal file
528
docs/source/ro/monkey_patching.md
Normal file
@@ -0,0 +1,528 @@
|
||||
<!--Copyright 2026 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Monkey patching (funcție experimentală)
|
||||
|
||||
Monkey patching îți permite să înlocuiești componente ale modelului la nivel global fără a modifica codul original al modelului. Odată înregistrate, patch-urile sunt aplicate automat la încărcarea oricărui model cu [`~PreTrainedModel.from_pretrained`] sau [`~PreTrainedModel.from_config`]. Aceasta îți permite să restructurezi modele pentru cerințe specifice precum compatibilitatea cu quantization, să aplici optimizări sau să experimentezi cu variante arhitecturale.
|
||||
|
||||
> [!WARNING]
|
||||
> **Monkey patching ar trebui folosit ca ultimă soluție** atunci când trebuie să schimbi layout-ul și structura unui modul și/sau weights asociate acestuia. Pentru nevoile de personalizare și optimizare, încearcă să folosești în schimb [interfața Attention], [interfața Experts] sau [registrul Kernels]. Folosește monkey patching doar când ai nevoie de schimbări structurale care nu pot fi realizate doar prin implementări forward personalizate (e.g., pentru compatibilitatea cu biblioteci de quantization, fuzionarea layers, sau experimente arhitecturale).
|
||||
|
||||
## Pornire rapidă
|
||||
|
||||
Iată un exemplu simplu care arată cum să înlocuiești o componentă a modelului:
|
||||
|
||||
```python
|
||||
from transformers import AutoModelForCausalLM
|
||||
from transformers.models.llama.modeling_llama import LlamaAttention
|
||||
from transformers.monkey_patching import register_patch_mapping
|
||||
|
||||
|
||||
# Definește clasa ta de înlocuire (trebuie să moștenească din nn.Module)
|
||||
class CustomLlamaAttention(LlamaAttention):
|
||||
def forward(self, *args, **kwargs):
|
||||
# Implementarea ta personalizată
|
||||
print("Using custom attention!")
|
||||
return super().forward(*args, **kwargs)
|
||||
|
||||
|
||||
# Înregistrează patch-ul global (se aplică doar modulelor de modelare transformers)
|
||||
register_patch_mapping(mapping={"LlamaAttention": CustomLlamaAttention})
|
||||
|
||||
# Încarcă un model - patch-ul este aplicat automat în timpul inițializării
|
||||
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-1B")
|
||||
|
||||
# Toate layers LlamaAttention din model sunt acum instanțe CustomLlamaAttention
|
||||
print(type(model.model.layers[0].self_attn)) # <class '__main__.CustomLlamaAttention'>
|
||||
```
|
||||
|
||||
## Cum funcționează
|
||||
|
||||
Monkey patches funcționează printr-un proces în două etape:
|
||||
|
||||
1. **Înregistrare**: Apelează [`register_patch_mapping`] pentru a adăuga mapări la un registru global.
|
||||
|
||||
2. **Aplicare**: Patch-urile sunt aplicate automat în timpul inițializării modelului:
|
||||
- **`from_pretrained` / `from_config`**: Patch-urile sunt aplicate **automat** printr-un context manager intern. Nu este necesară nicio acțiune suplimentară!
|
||||
- **Construcție manuală** (e.g., `Model(config)`): Trebuie să utilizezi manual context manager-ul [`apply_patches`].
|
||||
|
||||
Odată ce patch-urile sunt înregistrate, persistă și afectează toate încărcările ulterioare de modele până când le ștergi cu [`clear_patch_mapping`].
|
||||
|
||||
**Limitări importante**:
|
||||
|
||||
- Doar clasele din modulele de modelare `transformers` pot fi patched (e.g., `LlamaAttention`, `LlamaMLP`).
|
||||
- Cheile mapării pot fi fie nume exacte de clase, fie pattern-uri de expresii regulate (vezi [Potrivirea pattern-urilor](#potrivirea-pattern-urilor) mai jos).
|
||||
|
||||
## Înregistrare globală
|
||||
|
||||
Folosește [`register_patch_mapping`] pentru a înregistra mapări global:
|
||||
|
||||
```python
|
||||
from transformers.monkey_patching import register_patch_mapping
|
||||
|
||||
# Înregistrează un singur patch
|
||||
register_patch_mapping(
|
||||
mapping={"Qwen2MoeExperts": SequentialExperts}
|
||||
)
|
||||
|
||||
# Înregistrează mai multe patch-uri simultan
|
||||
register_patch_mapping(
|
||||
mapping={
|
||||
"Qwen2MoeExperts": SequentialExperts,
|
||||
"Qwen2MoeAttention": CustomAttention,
|
||||
},
|
||||
# Suprascrie patch-urile existente dacă există
|
||||
overwrite=True,
|
||||
)
|
||||
```
|
||||
|
||||
## Potrivirea pattern-urilor
|
||||
|
||||
Poți folosi expresii regulate pentru a potrivi mai multe clase cu un singur pattern:
|
||||
|
||||
```python
|
||||
from transformers.monkey_patching import register_patch_mapping
|
||||
|
||||
# Potrivește toate clasele care conțin "Attention"
|
||||
register_patch_mapping(
|
||||
mapping={".*Attention": CustomAttention}
|
||||
)
|
||||
|
||||
# Mai multe exemple
|
||||
register_patch_mapping(
|
||||
mapping={
|
||||
".*MoeExperts$": CustomExperts, # Se termină cu "MoeExperts"
|
||||
"^Llama\\d+Attention$": CustomAttention, # Llama2Attention, Llama3Attention, etc.
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
**Important**: Potrivirile exacte au prioritate față de pattern-uri. Dacă înregistrezi atât `"LlamaAttention"` cât și `".*Attention"`, clasele numite `LlamaAttention` vor folosi înlocuirea prin potrivire exactă, în timp ce alte clase potrivite vor folosi înlocuirea prin potrivire după pattern.
|
||||
|
||||
> [!WARNING]
|
||||
> **Pattern-urile regex pot strica modelele în tăcere.** Un pattern larg precum `".*Attention"` va potrivi *fiecare* clasă al cărei nume conține "Attention" — inclusiv clasele container care învelesc attention-ul pe care vrei să îl înlocuiești. De exemplu, BERT are trei clase legate de attention: `BertSelfAttention` și `BertCrossAttention` (implementările interioare de attention) și `BertAttention` (un modul exterior care *conține* una dintre acele clase interioare). Patch-uirea tuturor celor trei cu același layer de attention personalizat produce un model stricat deoarece `BertAttention`-ul exterior nu mai învelește cel interior — *este* unul, eliminând sub-modulele așteptate precum `self` și `output`. Preferă pattern-uri înguste (e.g., `".*SelfAttention$"`) sau nume exacte de clase pentru a evita potrivirile neintenționate.
|
||||
|
||||
Pentru a dezînregistra patch-uri, folosește [`unregister_patch_mapping`]:
|
||||
|
||||
```python
|
||||
from transformers.monkey_patching import unregister_patch_mapping
|
||||
|
||||
# Dezînregistrează un singur patch (folosește numele exact sau pattern-ul din înregistrare)
|
||||
unregister_patch_mapping(keys=["Qwen2MoeExperts"])
|
||||
|
||||
# Dezînregistrează mai multe patch-uri simultan
|
||||
unregister_patch_mapping(keys=["Qwen2MoeExperts", "Qwen2MoeAttention"])
|
||||
|
||||
# Dezînregistrează un pattern
|
||||
unregister_patch_mapping(keys=[".*Attention"])
|
||||
```
|
||||
|
||||
Pentru a șterge toate patch-urile înregistrate, folosește [`clear_patch_mapping`]:
|
||||
|
||||
```python
|
||||
from transformers.monkey_patching import clear_patch_mapping
|
||||
|
||||
clear_patch_mapping()
|
||||
```
|
||||
|
||||
Pentru a vizualiza patch-urile înregistrate curent, folosește [`get_patch_mapping`]:
|
||||
|
||||
```python
|
||||
from transformers.monkey_patching import get_patch_mapping
|
||||
|
||||
current_patches = get_patch_mapping()
|
||||
print(current_patches)
|
||||
```
|
||||
|
||||
## Construcția manuală a modelului
|
||||
|
||||
Context manager-ul [`apply_patches`] este necesar doar atunci când construiești modele **manual** (e.g., `Model(config)`) fără a folosi `from_pretrained` sau `from_config`:
|
||||
|
||||
```python
|
||||
from transformers import LlamaModel, LlamaConfig
|
||||
from transformers.monkey_patching import register_patch_mapping, apply_patches
|
||||
|
||||
# Înregistrează patch-ul global
|
||||
register_patch_mapping(mapping={"LlamaAttention": CustomAttention})
|
||||
|
||||
# Pentru construcția manuală, ai nevoie de context manager
|
||||
with apply_patches():
|
||||
model = LlamaModel(LlamaConfig()) # Utilizează CustomAttention
|
||||
|
||||
# Fără context manager, construcția manuală utilizează clasele originale
|
||||
model = LlamaModel(LlamaConfig()) # Utilizează LlamaAttention
|
||||
|
||||
# Dar from_pretrained și from_config vor aplica întotdeauna patch-urile înregistrate
|
||||
model = LlamaModel.from_pretrained("meta-llama/Llama-3.2-1B") # Utilizează CustomAttention
|
||||
```
|
||||
|
||||
## Note importante
|
||||
|
||||
- **Gestionarea weights**: Monkey patching înlocuiește doar clasele, nu și weights. Dacă clasa ta patched are un layout de weights diferit, va trebui să gestionezi [conversiile de weights](./weightconverter) separat pentru a asigura compatibilitatea cu weights pre-antrenate. Vezi [Exemplul complet](#exemplu-complet) de mai jos pentru a combina monkey patches cu mapări de conversie a weights.
|
||||
|
||||
- **Efect global**: Patch-urile înregistrate cu [`register_patch_mapping`] sunt aplicate global tuturor modelelor încărcate după înregistrare. Folosește întotdeauna [`clear_patch_mapping`] pentru a face curățenie când termini, mai ales în teste, notebooks sau aplicații de lungă durată.
|
||||
|
||||
- **Validarea claselor**: API-ul validează automat că clasele de înlocuire sunt subclase `nn.Module`. Dacă pasezi o clasă invalidă, vei primi un mesaj de eroare clar.
|
||||
|
||||
- **Thread safety**: Toate operațiile de patching sunt thread-safe. Poți înregistra, dezînregistra și aplica patch-uri în siguranță din mai multe thread-uri.
|
||||
|
||||
- **Comportamentul de potrivire**: Când folosești nume exacte de clase, acestea trebuie să corespundă exact cu numele claselor originale din codul sursă al modelului (cu distincție între majuscule și minuscule). Când folosești pattern-uri regex, acestea sunt potrivite față de numele claselor folosind `re.search()`.
|
||||
|
||||
## Depanare
|
||||
|
||||
### Patch-ul meu nu se aplică
|
||||
|
||||
**Verifică numele clasei sau pattern-ul**: Asigură-te că numele clasei sau pattern-ul din maparea ta este corect:
|
||||
|
||||
```python
|
||||
# Pentru nume exacte - trebuie să corespundă exact (cu distincție între majuscule și minuscule)
|
||||
register_patch_mapping(mapping={"LlamaAttention": CustomAttention})
|
||||
|
||||
# Pentru pattern-uri - folosește regex valid
|
||||
register_patch_mapping(mapping={".*Attention": CustomAttention})
|
||||
```
|
||||
|
||||
**Verifică înregistrarea**: Folosește [`get_patch_mapping`] pentru a confirma că maparea ta este înregistrată:
|
||||
|
||||
```python
|
||||
print(get_patch_mapping())
|
||||
# Afișează toate mapările înregistrate: {'LlamaAttention': <class 'CustomAttention'>, '.*MLP': <class 'CustomMLP'>}
|
||||
```
|
||||
|
||||
**Verifică sursa modelului**: Găsește numele exact al clasei în sursa modelului:
|
||||
|
||||
```python
|
||||
from transformers.models.llama import modeling_llama
|
||||
print(dir(modeling_llama)) # Caută numele clasei
|
||||
```
|
||||
|
||||
### Cum știu dacă patch-ul meu funcționează?
|
||||
|
||||
Inspectează modelul încărcat pentru a verifica patch-ul:
|
||||
|
||||
```python
|
||||
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-1B")
|
||||
|
||||
# Verifică tipul unui modul specific
|
||||
print(type(model.model.layers[0].self_attn)) # Ar trebui să afișeze clasa ta personalizată
|
||||
|
||||
# Sau iterează prin toate modulele
|
||||
for name, module in model.named_modules():
|
||||
if 'attention' in name.lower():
|
||||
print(f"{name}: {type(module)}")
|
||||
```
|
||||
|
||||
### Erori de nepotrivire a dimensiunilor weights
|
||||
|
||||
Dacă clasa ta patch-uită are dimensiuni de weights diferite, înregistrează o conversie de weights:
|
||||
|
||||
```python
|
||||
from transformers.conversion_mapping import register_checkpoint_conversion_mapping, WeightConverter
|
||||
from transformers.monkey_patching import register_patch_mapping
|
||||
|
||||
register_patch_mapping(
|
||||
mapping={
|
||||
"LlamaAttention": LlamaFusedAttention,
|
||||
}
|
||||
)
|
||||
|
||||
register_checkpoint_conversion_mapping(
|
||||
model_type="llama",
|
||||
mapping=[
|
||||
WeightConverter(
|
||||
source_patterns=["q_proj", "k_proj", "v_proj"],
|
||||
target_patterns=["qkv_proj"],
|
||||
operations=[
|
||||
Concatenate(dim=0),
|
||||
],
|
||||
)
|
||||
],
|
||||
overwrite=True,
|
||||
)
|
||||
```
|
||||
|
||||
### Curățarea patch-urilor
|
||||
|
||||
Curăță întotdeauna patch-urile când termini pentru a evita afectarea altui cod:
|
||||
|
||||
```python
|
||||
from transformers.monkey_patching import register_patch_mapping, clear_patch_mapping
|
||||
|
||||
try:
|
||||
register_patch_mapping(mapping={"LlamaAttention": CustomAttention})
|
||||
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
|
||||
# ... folosește modelul ...
|
||||
finally:
|
||||
clear_patch_mapping() # Curăță întotdeauna
|
||||
```
|
||||
|
||||
## Exemplu complet
|
||||
|
||||
Iată un exemplu cuprinzător care arată cum să restructurezi atât modulele experts cât și cele de attention dintr-un model Mixture-of-Experts (`qwen2_moe`) pentru optimizare și compatibilitate cu quantization. Acesta demonstrează:
|
||||
|
||||
1. Crearea de clase de înlocuire personalizate care mențin aceeași interfață
|
||||
2. Înregistrarea de monkey patches pentru mai multe componente
|
||||
3. Gestionarea conversiilor de weights pentru noua structură
|
||||
|
||||
```python
|
||||
from typing import Unpack
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
from transformers import AutoModelForCausalLM, Concatenate, WeightConverter
|
||||
from transformers.activations import ACT2FN
|
||||
from transformers.cache_utils import Cache
|
||||
from transformers.conversion_mapping import register_checkpoint_conversion_mapping
|
||||
from transformers.integrations.sdpa_attention import sdpa_attention_forward
|
||||
from transformers.models.qwen2_moe.modeling_qwen2_moe import apply_rotary_pos_emb
|
||||
from transformers.monkey_patching import register_patch_mapping
|
||||
from transformers.utils.generic import TransformersKwargs
|
||||
|
||||
|
||||
class MoeMLP(nn.Module):
|
||||
def __init__(self, config):
|
||||
super().__init__()
|
||||
self.config = config
|
||||
self.num_experts = config.num_experts
|
||||
self.hidden_size = config.hidden_size
|
||||
self.intermediate_size = config.moe_intermediate_size
|
||||
self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
||||
self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
||||
self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
|
||||
self.act_fn = ACT2FN[config.hidden_act]
|
||||
|
||||
def forward(self, x):
|
||||
down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
|
||||
return down_proj
|
||||
|
||||
|
||||
# Adaptat din Qwen2MoeExperts original
|
||||
class ModuleListExperts(nn.ModuleList):
|
||||
def __init__(self, config):
|
||||
super().__init__()
|
||||
self.config = config
|
||||
self.num_experts = config.num_experts
|
||||
for _ in range(self.num_experts):
|
||||
self.append(MoeMLP(config))
|
||||
|
||||
def forward(
|
||||
self, hidden_states: torch.Tensor, top_k_index: torch.Tensor, top_k_weights: torch.Tensor
|
||||
) -> torch.Tensor:
|
||||
final_hidden_states = torch.zeros_like(hidden_states)
|
||||
with torch.no_grad():
|
||||
expert_mask = torch.nn.functional.one_hot(top_k_index, num_classes=self.num_experts)
|
||||
expert_mask = expert_mask.permute(2, 1, 0)
|
||||
|
||||
for expert_idx in range(self.num_experts):
|
||||
top_k_pos, token_idx = torch.where(expert_mask[expert_idx])
|
||||
current_state = hidden_states[token_idx]
|
||||
current_hidden_states = self[expert_idx](current_state)
|
||||
current_hidden_states = current_hidden_states * top_k_weights[token_idx, top_k_pos, None]
|
||||
final_hidden_states.index_add_(0, token_idx, current_hidden_states.to(final_hidden_states.dtype))
|
||||
return final_hidden_states
|
||||
|
||||
|
||||
# Adaptat din Qwen2MoeAttention original
|
||||
class FusedQKVAttention(nn.Module):
|
||||
def __init__(self, config, layer_idx: int):
|
||||
super().__init__()
|
||||
self.config = config
|
||||
self.layer_idx = layer_idx
|
||||
self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
|
||||
self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
|
||||
self.scaling = self.head_dim**-0.5
|
||||
self.attention_dropout = config.attention_dropout
|
||||
self.is_causal = True
|
||||
|
||||
self.qkv_proj = nn.Linear(config.hidden_size, 3 * config.num_attention_heads * self.head_dim, bias=True)
|
||||
self.o_proj = nn.Linear(config.num_attention_heads * self.head_dim, config.hidden_size, bias=False)
|
||||
|
||||
if self.config.layer_types[layer_idx] == "sliding_attention":
|
||||
self.sliding_window = config.sliding_window
|
||||
|
||||
def forward(
|
||||
self,
|
||||
hidden_states: torch.Tensor,
|
||||
position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
|
||||
attention_mask: torch.Tensor | None = None,
|
||||
past_key_values: Cache | None = None,
|
||||
**kwargs: Unpack[TransformersKwargs],
|
||||
) -> tuple[torch.Tensor, torch.Tensor]:
|
||||
input_shape = hidden_states.shape[:-1]
|
||||
hidden_shape = (*input_shape, -1, self.head_dim)
|
||||
|
||||
query_states, key_states, value_states = self.qkv_proj(hidden_states).chunk(3, dim=-1)
|
||||
|
||||
query_states = query_states.view(hidden_shape).transpose(1, 2)
|
||||
key_states = key_states.view(hidden_shape).transpose(1, 2)
|
||||
value_states = value_states.view(hidden_shape).transpose(1, 2)
|
||||
|
||||
cos, sin = position_embeddings
|
||||
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
||||
|
||||
if past_key_values is not None:
|
||||
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
|
||||
|
||||
attn_output, attn_weights = sdpa_attention_forward(
|
||||
self,
|
||||
query_states,
|
||||
key_states,
|
||||
value_states,
|
||||
attention_mask,
|
||||
dropout=0.0 if not self.training else self.attention_dropout,
|
||||
scaling=self.scaling,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
||||
attn_output = self.o_proj(attn_output)
|
||||
return attn_output, attn_weights
|
||||
|
||||
|
||||
# Înregistrează monkey patches pentru noile module de attention și experts.
|
||||
register_patch_mapping(
|
||||
mapping={
|
||||
"Qwen2MoeExperts": ModuleListExperts,
|
||||
"Qwen2MoeAttention": FusedQKVAttention,
|
||||
}
|
||||
)
|
||||
|
||||
# Înregistrează mapările de conversie a weights adaptate pentru noile module. Această înregistrare va:
|
||||
# - Suprascrie maparea de conversie originală pentru qwen2_moe care concatena experții într-un format de parametru unic.
|
||||
# - Concatenează weights/biases q_proj, k_proj, v_proj într-un singur weight/bias qkv_proj pentru noul modul de attention fuzionat.
|
||||
register_checkpoint_conversion_mapping(
|
||||
model_type="qwen2_moe",
|
||||
mapping=[
|
||||
WeightConverter(
|
||||
source_patterns=["q_proj", "k_proj", "v_proj"],
|
||||
target_patterns=["qkv_proj"],
|
||||
operations=[Concatenate(dim=0)],
|
||||
),
|
||||
],
|
||||
overwrite=True,
|
||||
)
|
||||
|
||||
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-MoE-A2.7B")
|
||||
```
|
||||
|
||||
## Înregistrarea și reluarea rutării experților MoE
|
||||
|
||||
Fluxurile de antrenare Mixture-of-Experts precum RLHF trebuie să înregistreze la ce experți a fost dirijat fiecare token în timpul generării, apoi să repete exact acea rutare într-un forward pass de antrenare separat. Poți construi aceasta end-to-end cu mecanismele existente de monkey patching și captare a output-urilor — nu sunt necesare modificări ale fișierelor de modelare.
|
||||
|
||||
Pattern-ul are trei componente:
|
||||
|
||||
1. O **subclasă de router reluabilă** care poate citi opțional indici de experți forțați dintr-un atribut de instanță.
|
||||
2. Un **context manager** care setează acele atribute pe fiecare router înainte de un forward pass și le șterge după.
|
||||
3. O intrare în registrul de captare a output-urilor modelului astfel că `output_<name>=True` expune indicii prin calea standard `@capture_outputs`.
|
||||
|
||||
```python
|
||||
from contextlib import contextmanager
|
||||
|
||||
import torch
|
||||
import torch.nn.functional as F
|
||||
|
||||
from transformers import Qwen3MoeConfig, Qwen3MoeForCausalLM
|
||||
from transformers.models.qwen3_moe.modeling_qwen3_moe import Qwen3MoeTopKRouter
|
||||
from transformers.monkey_patching import apply_patches, register_patch_mapping
|
||||
from transformers.utils.output_capturing import _CAN_RECORD_REGISTRY, OutputRecorder
|
||||
|
||||
|
||||
class ReplayableQwen3MoeTopKRouter(Qwen3MoeTopKRouter):
|
||||
_forced_indices: torch.Tensor | None = None
|
||||
|
||||
def forward(self, hidden_states):
|
||||
hidden_states = hidden_states.reshape(-1, self.hidden_dim)
|
||||
router_logits = F.linear(hidden_states, self.weight)
|
||||
router_logits = F.softmax(router_logits, dtype=torch.float, dim=-1)
|
||||
|
||||
if self._forced_indices is not None:
|
||||
router_indices = self._forced_indices.to(router_logits.device).long()
|
||||
# Replay în stil Megatron: păstrează calea expertului, recalculează scorurile curente
|
||||
router_top_value = router_logits.gather(-1, router_indices)
|
||||
else:
|
||||
router_top_value, router_indices = torch.topk(router_logits, self.top_k, dim=-1)
|
||||
|
||||
if self.norm_topk_prob:
|
||||
router_top_value = router_top_value / router_top_value.sum(dim=-1, keepdim=True)
|
||||
return router_logits, router_top_value.to(router_logits.dtype), router_indices
|
||||
|
||||
|
||||
@contextmanager
|
||||
def replay_moe_routing(model, selected_experts_per_layer):
|
||||
routers = [m for m in model.modules() if isinstance(m, ReplayableQwen3MoeTopKRouter)]
|
||||
if len(routers) != len(selected_experts_per_layer):
|
||||
raise ValueError(f"Got {len(routers)} routers but {len(selected_experts_per_layer)} tensors")
|
||||
for r, t in zip(routers, selected_experts_per_layer):
|
||||
r._forced_indices = t
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
for r in routers:
|
||||
r._forced_indices = None
|
||||
|
||||
|
||||
# Înlocuiește clasa router și construiește modelul
|
||||
register_patch_mapping({"Qwen3MoeTopKRouter": ReplayableQwen3MoeTopKRouter})
|
||||
with apply_patches():
|
||||
model = Qwen3MoeForCausalLM(Qwen3MoeConfig(...)).eval()
|
||||
|
||||
# Expune `output_selected_experts=True` pe modelul de bază adăugând un OutputRecorder
|
||||
# la runtime. Indexul 2 din output-ul tuple al router-ului reprezintă indicii experților.
|
||||
inner = model.model
|
||||
existing = _CAN_RECORD_REGISTRY.get(str(inner.__class__), {}) or {}
|
||||
_CAN_RECORD_REGISTRY[str(inner.__class__)] = {
|
||||
**existing,
|
||||
"selected_experts": OutputRecorder(ReplayableQwen3MoeTopKRouter, index=2),
|
||||
}
|
||||
|
||||
# Înregistrează
|
||||
captured = inner(input_ids=input_ids, output_selected_experts=True)
|
||||
selected_experts = captured.selected_experts # tuple de LongTensors (num_tokens, top_k)
|
||||
|
||||
# Replay — aceeași cale a expertului indiferent de weights-urile curente ale router-ului
|
||||
with replay_moe_routing(inner, list(selected_experts)):
|
||||
outputs = inner(input_ids=input_ids)
|
||||
```
|
||||
|
||||
Replay-ul păstrează indicii exacte ai experților și recalculează scorurile de rutare cu weights curente ale router-ului, astfel că gradients curg prin parametrii activi în timp ce selecția experților rămâne fixă. Acesta este contractul minimal de replay utilizat în antrenarea MoE în stil Megatron.
|
||||
|
||||
### Interoperabilitate cu vLLM
|
||||
|
||||
Opțiunea `enable_return_routed_experts=True` din vLLM populează `CompletionOutput.routed_experts` ca un array `np.int32` de forma `(seq_len, num_layers, top_k)`. Convertește-l în lista per-layer pe care o utilizează acest pattern cu o singură expresie:
|
||||
|
||||
```python
|
||||
selected = [
|
||||
torch.from_numpy(routed_experts[:, layer, :].copy()).long()
|
||||
for layer in range(routed_experts.shape[1])
|
||||
]
|
||||
with replay_moe_routing(model, selected):
|
||||
loss = model(input_ids=input_ids, labels=labels).loss
|
||||
```
|
||||
|
||||
Aceeași rețetă se aplică și altor familii MoE — subclasează `*TopKRouter`-ul familiei, potrivește contractul de return original (de obicei `(router_logits, router_scores, router_indices)`) și înregistrează patch-ul. Consultă clasa router a fiecărui model pentru semnătura exactă.
|
||||
|
||||
## Referință API
|
||||
|
||||
[[autodoc]] transformers.monkey_patching.register_patch_mapping
|
||||
|
||||
[[autodoc]] transformers.monkey_patching.unregister_patch_mapping
|
||||
|
||||
[[autodoc]] transformers.monkey_patching.clear_patch_mapping
|
||||
|
||||
[[autodoc]] transformers.monkey_patching.get_patch_mapping
|
||||
|
||||
[[autodoc]] transformers.monkey_patching.apply_patches
|
||||
106
docs/source/ro/multimodal_processing.md
Normal file
106
docs/source/ro/multimodal_processing.md
Normal file
@@ -0,0 +1,106 @@
|
||||
<!--Copyright 2026 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Procesatoare multimodale
|
||||
|
||||
Un procesator combină un tokenizer cu unul sau mai multe procesatoare de modalitate, cum ar fi un procesator de imagini, un procesator video sau un feature extractor. Expune o singură metodă `__call__` care direcționează fiecare input la componenta potrivită și îmbină ieșirile într-un singur dicționar.
|
||||
|
||||
Unele modele multimodale intercalează textul cu imagini, videoclipuri sau audio. Pentru aceste modele, [`ProcessorMixin`] poate înlocui token-urile placeholder precum `<image>`, `<video>` și `<audio>` cu pattern-ul de token pe care îl așteaptă modelul.
|
||||
|
||||
|
||||
## Adăugarea unui procesator nou
|
||||
|
||||
Definești o clasă de procesator creând `src/transformers/models/<model>/processing_<my_model_name>.py` și subclasând `ProcessorMixin`. Asigură-te că definești un obiect `TypedDict` cu valori implicite și îl atribui ca `cls.valid_processor_kwargs`.
|
||||
|
||||
```python
|
||||
from ...processing_utils import ProcessorMixin, ProcessingKwargs, Unpack
|
||||
|
||||
class MyModelProcessorKwargs(ProcessingKwargs, total=False):
|
||||
images_kwargs: MyModelImageProcessorKwargs
|
||||
_defaults = {
|
||||
"text_kwargs": {"padding": True},
|
||||
"images_kwargs": {"do_convert_rgb": True},
|
||||
}
|
||||
|
||||
class MyModelProcessor(ProcessorMixin):
|
||||
valid_processor_kwargs = MyModelProcessorKwargs
|
||||
|
||||
def __init__(self, image_processor, tokenizer, chat_template=None, **kwargs):
|
||||
self.image_token = tokenizer.image_token
|
||||
self.image_token_id = tokenizer.image_token_id
|
||||
super().__init__(
|
||||
image_processor=image_processor,
|
||||
tokenizer=tokenizer,
|
||||
chat_template=chat_template,
|
||||
**kwargs,
|
||||
)
|
||||
```
|
||||
|
||||
Implementează `replace_<modality>_token` dacă e nevoie. Acesta primește dicționarul complet de ieșire de la subprocesator și indexul inputului curent, returnând șirul de înlocuire expandat pentru acel input. Șirul de înlocuire este ceea ce modelul așteaptă în secvența de input.
|
||||
|
||||
Dacă modelul nu folosește deloc repetarea placeholder-ului (fără `image_token` definit), nu trebuie să suprascrii această metodă. Lasă `self.image_token` nesetat și clasa de bază sare peste înlocuire complet.
|
||||
|
||||
```python
|
||||
def replace_image_token(self, image_inputs: dict, image_idx: int) -> str:
|
||||
num_crops = image_inputs["num_crops"][image_idx]
|
||||
return f"{self.boi_token}{self.image_token * self.num_image_tokens * num_crops}{self.eoi_token}"
|
||||
```
|
||||
|
||||
Opțional, suprascrie metodele `prepare_inputs_layout` și `validate_inputs` dacă modelul necesită o structură specifică de input înainte ca procesarea să înceapă, precum reordonarea imaginilor ca o listă imbricată sau o validare specifică modelului pe lângă verificările comune.
|
||||
|
||||
```python
|
||||
def prepare_inputs_layout(self, images=None, text=None, videos=None, audio=None, **kwargs):
|
||||
# Apelează `super()` ca să aplici mai întâi pașii comuni de pregătire
|
||||
images, text, videos, audio = super().prepare_inputs_layout(images, text, videos, audio)
|
||||
if images is not None:
|
||||
images = make_nested_list_of_images(images)
|
||||
return images, text, videos, audio
|
||||
|
||||
def validate_inputs(self, images=None, text=None, videos=None, audio=None, **kwargs):
|
||||
super().validate_inputs(images=images, text=text, **kwargs)
|
||||
if text is not None and images is not None:
|
||||
n_tokens = [s.count(self.image_token) for s in text]
|
||||
n_images = [len(img_list) for img_list in images]
|
||||
if n_tokens != n_images:
|
||||
raise ValueError(
|
||||
f"Number of {self.image_token} tokens in text {n_tokens} does not match "
|
||||
f"number of images {n_images}."
|
||||
)
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> Vezi [`Gemma4Processor`] și [`Qwen2VLProcessor`] ca referință.
|
||||
|
||||
## Testare
|
||||
|
||||
Toate procesatoarele multimodale ar trebui să aibă o clasă de test care moștenește din [`ProcessorTesterMixin`]. Mixin-ul acesta oferă o suită standard care acoperă tokenizarea, procesarea imaginilor, batch-urile și codificarea round-trip.
|
||||
|
||||
```python
|
||||
# tests/models/my_model_name/test_processor_<my_model_name>.py
|
||||
|
||||
from transformers.testing_utils import require_vision
|
||||
from transformers.utils import is_vision_available
|
||||
from ...test_processing_common import ProcessorTesterMixin
|
||||
|
||||
if is_vision_available():
|
||||
from transformers import MyModelProcessor
|
||||
|
||||
@require_vision
|
||||
class MyModelProcessorTest(ProcessorTesterMixin, unittest.TestCase):
|
||||
processor_class = MyModelProcessor
|
||||
|
||||
def get_processor(self):
|
||||
return MyModelProcessor.from_pretrained("hf-internal-testing/my-model-test")
|
||||
```
|
||||
52
docs/source/ro/pipeline_gradio.md
Normal file
52
docs/source/ro/pipeline_gradio.md
Normal file
@@ -0,0 +1,52 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Aplicații de machine learning
|
||||
|
||||
[Gradio](https://www.gradio.app/), o bibliotecă rapidă și ușoară pentru construirea și partajarea de aplicații de machine learning, este integrată cu [`Pipeline`] pentru a crea rapid o interfață simplă pentru inferență.
|
||||
|
||||
Înainte de a începe, asigură-te că Gradio este instalată.
|
||||
|
||||
```py
|
||||
!pip install gradio
|
||||
```
|
||||
|
||||
Creează un pipeline pentru task-ul tău, iar apoi transmite-l funcției [Interface.from_pipeline](https://www.gradio.app/docs/gradio/interface#interface-from_pipeline) din Gradio pentru a crea interfața. Gradio determină automat componentele de input și output potrivite pentru un [`Pipeline`].
|
||||
|
||||
Adaugă [launch](https://www.gradio.app/main/docs/gradio/blocks#blocks-launch) pentru a crea un web server și a porni aplicația.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
import gradio as gr
|
||||
|
||||
pipeline = pipeline("image-classification", model="google/vit-base-patch16-224")
|
||||
gr.Interface.from_pipeline(pipeline).launch()
|
||||
```
|
||||
|
||||
Aplicația web rulează implicit pe un server local. Pentru a partaja aplicația cu alți utilizatori, setează `share=True` în [launch](https://www.gradio.app/main/docs/gradio/blocks#blocks-launch) pentru a genera un link public temporar. Pentru o soluție mai permanentă, găzduiește aplicația pe Hugging Face [Spaces](https://hf.co/spaces).
|
||||
|
||||
```py
|
||||
gr.Interface.from_pipeline(pipeline).launch(share=True)
|
||||
```
|
||||
|
||||
Space-ul de mai jos este creat cu codul de mai sus și găzduit pe Spaces.
|
||||
|
||||
<iframe
|
||||
src="https://stevhliu-gradio-pipeline-demo.hf.space"
|
||||
frameborder="0"
|
||||
width="850"
|
||||
height="850"
|
||||
></iframe>
|
||||
346
docs/source/ro/pipeline_tutorial.md
Normal file
346
docs/source/ro/pipeline_tutorial.md
Normal file
@@ -0,0 +1,346 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Pipeline
|
||||
|
||||
[`Pipeline`] este un API de inferență simplu, dar puternic, disponibil imediat pentru o varietate de task-uri de machine learning cu orice model din Hugging Face [Hub](https://hf.co/models).
|
||||
|
||||
Adaptează [`Pipeline`] la task-ul tău cu parametri specifici task-ului, precum adăugarea de timestamp-uri la un pipeline de automatic speech recognition (ASR) pentru transcrierea notițelor de ședință. [`Pipeline`] suportă GPU-uri, Apple Silicon și weights cu precizie redusă (half-precision) pentru a accelera inferența și a economisi memorie.
|
||||
|
||||
<Youtube id="tiZFewofSLM"/>
|
||||
|
||||
Transformers are două clase de pipeline, un [`Pipeline`] generic și multe pipeline-uri individuale specifice task-ului precum [`TextGenerationPipeline`]. Încarcă aceste pipeline-uri individuale setând identificatorul task-ului în parametrul `task` din [`Pipeline`]. Poți găsi identificatorul task-ului pentru fiecare pipeline în documentația lor API.
|
||||
|
||||
Fiecare task este configurat să folosească un model preantrenat și un preprocesor implicit, dar acest lucru poate fi suprascris cu parametrul `model` dacă vrei să folosești un alt model.
|
||||
|
||||
De exemplu, pentru a folosi [`TextGenerationPipeline`] cu [Gemma 2], setează `task="text-generation"` și `model="google/gemma-2-2b"`.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline(task="text-generation", model="google/gemma-2-2b")
|
||||
pipeline("the secret to baking a really good cake is ")
|
||||
[{'generated_text': 'the secret to baking a really good cake is 1. the right ingredients 2. the'}]
|
||||
```
|
||||
|
||||
Când ai mai mult de un input, transmite-le ca listă.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
from accelerate import Accelerator
|
||||
|
||||
device = Accelerator().device
|
||||
|
||||
pipeline = pipeline(task="text-generation", model="google/gemma-2-2b", device=device)
|
||||
pipeline(["the secret to baking a really good cake is ", "a baguette is "])
|
||||
[[{'generated_text': 'the secret to baking a really good cake is 1. the right ingredients 2. the'}],
|
||||
[{'generated_text': 'a baguette is 100% bread.\n\na baguette is 100%'}]]
|
||||
```
|
||||
|
||||
Acest ghid îți va prezenta [`Pipeline`], îți va demonstra funcționalitățile sale și îți va arăta cum să configurezi diferiții săi parametri.
|
||||
|
||||
## Task-uri
|
||||
|
||||
[`Pipeline`] este compatibil cu multe task-uri de machine learning din diferite modalități. Transmite un input potrivit către pipeline și acesta se va ocupa de restul.
|
||||
|
||||
Iată câteva exemple despre cum să folosești [`Pipeline`] pentru diferite task-uri și modalități.
|
||||
|
||||
<hfoptions id="tasks">
|
||||
<hfoption id="automatic speech recognition">
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline(task="automatic-speech-recognition", model="openai/whisper-large-v3")
|
||||
pipeline("https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac")
|
||||
{'text': ' I have a dream that one day this nation will rise up and live out the true meaning of its creed.'}
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="image classification">
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline(task="image-classification", model="google/vit-base-patch16-224")
|
||||
pipeline(images="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/pipeline-cat-chonk.jpeg")
|
||||
[{'label': 'lynx, catamount', 'score': 0.43350091576576233},
|
||||
{'label': 'cougar, puma, catamount, mountain lion, painter, panther, Felis concolor',
|
||||
'score': 0.034796204417943954},
|
||||
{'label': 'snow leopard, ounce, Panthera uncia',
|
||||
'score': 0.03240183740854263},
|
||||
{'label': 'Egyptian cat', 'score': 0.02394474856555462},
|
||||
{'label': 'tiger cat', 'score': 0.02288915030658245}]
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="visual question answering">
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline(task="visual-question-answering", model="Salesforce/blip-vqa-base")
|
||||
pipeline(
|
||||
image="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/idefics-few-shot.jpg",
|
||||
question="What is in the image?",
|
||||
)
|
||||
[{'answer': 'statue of liberty'}]
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
## Parametri
|
||||
|
||||
La minimum, [`Pipeline`] necesită doar un identificator de task, un model și input-ul potrivit. Dar există mulți parametri disponibili pentru a configura pipeline-ul, de la parametri specifici task-ului până la optimizarea performanței.
|
||||
|
||||
Această secțiune îți prezintă câțiva dintre cei mai importanți parametri.
|
||||
|
||||
### Device
|
||||
|
||||
[`Pipeline`] este compatibil cu multe tipuri de hardware, inclusiv GPU-uri, CPU-uri, Apple Silicon și altele. Configurează tipul de hardware cu parametrul `device`. Implicit, [`Pipeline`] rulează pe un CPU, ceea ce este indicat de `device=-1`.
|
||||
|
||||
<hfoptions id="device">
|
||||
<hfoption id="GPU">
|
||||
|
||||
Pentru a rula [`Pipeline`] pe un GPU, setează `device` la id-ul de device CUDA asociat. De exemplu, `device=0` rulează pe primul GPU.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline(task="text-generation", model="google/gemma-2-2b", device=0)
|
||||
pipeline("the secret to baking a really good cake is ")
|
||||
```
|
||||
|
||||
De asemenea, poți lăsa [Accelerate](https://hf.co/docs/accelerate/index), o bibliotecă pentru antrenare distribuită, să aleagă automat cum să încarce și să stocheze weights modelului pe device-ul potrivit. Acest lucru este util în special dacă ai mai multe device-uri. Accelerate încarcă și stochează weights modelului mai întâi pe cel mai rapid device, iar apoi mută weights pe alte device-uri (CPU, hard drive) după cum este nevoie. Setează `device_map="auto"` pentru a lăsa Accelerate să aleagă device-ul.
|
||||
|
||||
> [!TIP]
|
||||
> Asigură-te că ai instalat [Accelerate](https://hf.co/docs/accelerate/basic_tutorials/install).
|
||||
>
|
||||
> ```py
|
||||
> !pip install -U accelerate
|
||||
> ```
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline(task="text-generation", model="google/gemma-2-2b", device_map="auto")
|
||||
pipeline("the secret to baking a really good cake is ")
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="Apple silicon">
|
||||
|
||||
Pentru a rula [`Pipeline`] pe Apple Silicon, setează `device="mps"`.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline(task="text-generation", model="google/gemma-2-2b", device="mps")
|
||||
pipeline("the secret to baking a really good cake is ")
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
### Inferență în batch-uri
|
||||
|
||||
[`Pipeline`] poate procesa și batch-uri de input-uri cu parametrul `batch_size`. Inferența în batch-uri poate îmbunătăți viteza, în special pe un GPU, dar acest lucru nu este garantat. Alte variabile precum hardware-ul, datele și modelul în sine pot afecta dacă inferența în batch-uri îmbunătățește viteza. Din acest motiv, inferența în batch-uri este dezactivată implicit.
|
||||
|
||||
În exemplul de mai jos, când există 4 input-uri și `batch_size` este setat la 2, [`Pipeline`] transmite modelului câte un batch de 2 input-uri pe rând.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
from accelerate import Accelerator
|
||||
|
||||
device = Accelerator().device
|
||||
|
||||
pipeline = pipeline(task="text-generation", model="google/gemma-2-2b", device=device, batch_size=2)
|
||||
pipeline(["the secret to baking a really good cake is", "a baguette is", "paris is the", "hotdogs are"])
|
||||
[[{'generated_text': 'the secret to baking a really good cake is to use a good cake mix.\n\ni’'}],
|
||||
[{'generated_text': 'a baguette is'}],
|
||||
[{'generated_text': 'paris is the most beautiful city in the world.\n\ni’ve been to paris 3'}],
|
||||
[{'generated_text': 'hotdogs are a staple of the american diet. they are a great source of protein and can'}]]
|
||||
```
|
||||
|
||||
Un alt caz de utilizare bun pentru inferența în batch-uri este transmiterea de date în flux (streaming) în [`Pipeline`].
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
from accelerate import Accelerator
|
||||
from transformers.pipelines.pt_utils import KeyDataset
|
||||
import datasets
|
||||
|
||||
device = Accelerator().device
|
||||
|
||||
# KeyDataset este un utilitar care returnează elementul din dict-ul returnat de dataset
|
||||
dataset = datasets.load_dataset("imdb", name="plain_text", split="unsupervised")
|
||||
pipeline = pipeline(task="text-classification", model="distilbert/distilbert-base-uncased-finetuned-sst-2-english", device=device)
|
||||
for out in pipeline(KeyDataset(dataset, "text"), batch_size=8, truncation="only_first"):
|
||||
print(out)
|
||||
```
|
||||
|
||||
Ține cont de următoarele reguli generale pentru a determina dacă inferența în batch-uri poate ajuta la îmbunătățirea performanței.
|
||||
|
||||
1. Singura modalitate de a ști sigur este să măsori performanța pe modelul, datele și hardware-ul tău.
|
||||
2. Nu folosi inferența în batch-uri dacă ești constrâns de latență (de exemplu, un produs de inferență live).
|
||||
3. Nu folosi inferența în batch-uri dacă folosești un CPU.
|
||||
4. Nu folosi inferența în batch-uri dacă nu cunoști `sequence_length` al datelor tale. Măsoară performanța, crește iterativ `sequence_length` și include verificări out-of-memory (OOM) pentru a te recupera din eșecuri.
|
||||
5. Folosește inferența în batch-uri dacă `sequence_length` este regulat și continuă să îl crești până când ajungi la o eroare OOM. Cu cât GPU-ul este mai mare, cu atât inferența în batch-uri este mai utilă.
|
||||
6. Asigură-te că poți gestiona erorile OOM dacă decizi să folosești inferența în batch-uri.
|
||||
|
||||
### Parametri specifici task-ului
|
||||
|
||||
[`Pipeline`] acceptă orice parametri care sunt suportați de fiecare pipeline individual de task. Asigură-te că verifici fiecare pipeline individual de task pentru a vedea ce tip de parametri sunt disponibili. Dacă nu găsești un parametru util pentru cazul tău de utilizare, nu ezita să deschizi un [issue](https://github.com/huggingface/transformers/issues/new?assignees=&labels=feature&template=feature-request.yml) pe GitHub pentru a-l solicita!
|
||||
|
||||
Exemplele de mai jos demonstrează unii dintre parametrii specifici task-ului disponibili.
|
||||
|
||||
<hfoptions id="task-specific-parameters">
|
||||
<hfoption id="automatic speech recognition">
|
||||
|
||||
Transmite parametrul `return_timestamps="word"` către [`Pipeline`] pentru a returna momentul în care a fost rostit fiecare cuvânt.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline(task="automatic-speech-recognition", model="openai/whisper-large-v3")
|
||||
pipeline(audio="https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac", return_timestamp="word")
|
||||
{'text': ' I have a dream that one day this nation will rise up and live out the true meaning of its creed.',
|
||||
'chunks': [{'text': ' I', 'timestamp': (0.0, 1.1)},
|
||||
{'text': ' have', 'timestamp': (1.1, 1.44)},
|
||||
{'text': ' a', 'timestamp': (1.44, 1.62)},
|
||||
{'text': ' dream', 'timestamp': (1.62, 1.92)},
|
||||
{'text': ' that', 'timestamp': (1.92, 3.7)},
|
||||
{'text': ' one', 'timestamp': (3.7, 3.88)},
|
||||
{'text': ' day', 'timestamp': (3.88, 4.24)},
|
||||
{'text': ' this', 'timestamp': (4.24, 5.82)},
|
||||
{'text': ' nation', 'timestamp': (5.82, 6.78)},
|
||||
{'text': ' will', 'timestamp': (6.78, 7.36)},
|
||||
{'text': ' rise', 'timestamp': (7.36, 7.88)},
|
||||
{'text': ' up', 'timestamp': (7.88, 8.46)},
|
||||
{'text': ' and', 'timestamp': (8.46, 9.2)},
|
||||
{'text': ' live', 'timestamp': (9.2, 10.34)},
|
||||
{'text': ' out', 'timestamp': (10.34, 10.58)},
|
||||
{'text': ' the', 'timestamp': (10.58, 10.8)},
|
||||
{'text': ' true', 'timestamp': (10.8, 11.04)},
|
||||
{'text': ' meaning', 'timestamp': (11.04, 11.4)},
|
||||
{'text': ' of', 'timestamp': (11.4, 11.64)},
|
||||
{'text': ' its', 'timestamp': (11.64, 11.8)},
|
||||
{'text': ' creed.', 'timestamp': (11.8, 12.3)}]}
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="text generation">
|
||||
|
||||
Transmite `return_full_text=False` către [`Pipeline`] pentru a returna doar textul generat în loc de textul complet (prompt-ul și textul generat).
|
||||
|
||||
[`~TextGenerationPipeline.__call__`] suportă, de asemenea, argumente keyword suplimentare din metoda [`~GenerationMixin.generate`]. Pentru a returna mai mult de o secvență generată, setează `num_return_sequences` la o valoare mai mare decât 1.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
|
||||
pipeline = pipeline(task="text-generation", model="openai-community/gpt2")
|
||||
pipeline("the secret to baking a good cake is", num_return_sequences=4, return_full_text=False)
|
||||
[{'generated_text': ' how easy it is for me to do it with my hands. You must not go nuts, or the cake is going to fall out.'},
|
||||
{'generated_text': ' to prepare the cake before baking. The key is to find the right type of icing to use and that icing makes an amazing frosting cake.\n\nFor a good icing cake, we give you the basics'},
|
||||
{'generated_text': " to remember to soak it in enough water and don't worry about it sticking to the wall. In the meantime, you could remove the top of the cake and let it dry out with a paper towel.\n"},
|
||||
{'generated_text': ' the best time to turn off the oven and let it stand 30 minutes. After 30 minutes, stir and bake a cake in a pan until fully moist.\n\nRemove the cake from the heat for about 12'}]
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
## Chunk batching
|
||||
|
||||
Există unele situații în care trebuie să procesezi datele în chunk-uri.
|
||||
|
||||
- pentru unele tipuri de date, un singur input (de exemplu, un fișier audio foarte lung) poate fi nevoie să fie împărțit în mai multe părți (chunk-uri) înainte de a putea fi procesat
|
||||
- pentru unele task-uri, precum clasificarea zero-shot sau question answering, un singur input poate necesita mai multe forward pass-uri, ceea ce poate cauza probleme cu parametrul `batch_size`
|
||||
|
||||
Clasa [ChunkPipeline](https://github.com/huggingface/transformers/blob/99e0ab6ed888136ea4877c6d8ab03690a1478363/src/transformers/pipelines/base.py#L1387) este concepută pentru a gestiona aceste cazuri de utilizare. Ambele clase de pipeline sunt folosite în același mod, dar deoarece [ChunkPipeline](https://github.com/huggingface/transformers/blob/99e0ab6ed888136ea4877c6d8ab03690a1478363/src/transformers/pipelines/base.py#L1387) poate gestiona automat batching-ul, nu trebuie să-ți faci griji cu privire la numărul de forward pass-uri pe care le declanșează input-urile tale. În schimb, poți optimiza `batch_size` independent de input-uri.
|
||||
|
||||
Exemplul de mai jos arată cum diferă de [`Pipeline`].
|
||||
|
||||
```py
|
||||
# ChunkPipeline
|
||||
all_model_outputs = []
|
||||
for preprocessed in pipeline.preprocess(inputs):
|
||||
model_outputs = pipeline.model_forward(preprocessed)
|
||||
all_model_outputs.append(model_outputs)
|
||||
outputs =pipeline.postprocess(all_model_outputs)
|
||||
|
||||
# Pipeline
|
||||
preprocessed = pipeline.preprocess(inputs)
|
||||
model_outputs = pipeline.forward(preprocessed)
|
||||
outputs = pipeline.postprocess(model_outputs)
|
||||
```
|
||||
|
||||
## Seturi de date mari
|
||||
|
||||
Pentru inferență cu seturi de date mari, poți itera direct peste setul de date în sine. Acest lucru evită alocarea imediată de memorie pentru întregul set de date și nu trebuie să-ți faci griji cu privire la crearea de batch-uri manual. Încearcă [Inferența în batch-uri](#inferență-în-batch-uri) cu parametrul `batch_size` pentru a vedea dacă îmbunătățește performanța.
|
||||
|
||||
```py
|
||||
from transformers.pipelines.pt_utils import KeyDataset
|
||||
from transformers import pipeline
|
||||
from accelerate import Accelerator
|
||||
from datasets import load_dataset
|
||||
|
||||
device = Accelerator().device
|
||||
|
||||
dataset = datasets.load_dataset("imdb", name="plain_text", split="unsupervised")
|
||||
pipeline = pipeline(task="text-classification", model="distilbert/distilbert-base-uncased-finetuned-sst-2-english", device=device)
|
||||
for out in pipeline(KeyDataset(dataset, "text"), batch_size=8, truncation="only_first"):
|
||||
print(out)
|
||||
```
|
||||
|
||||
Alte modalități de a rula inferența pe seturi de date mari cu [`Pipeline`] includ folosirea unui iterator sau generator.
|
||||
|
||||
```py
|
||||
def data():
|
||||
for i in range(1000):
|
||||
yield f"My example {i}"
|
||||
|
||||
pipeline = pipeline(model="openai-community/gpt2", device=0)
|
||||
generated_characters = 0
|
||||
for out in pipeline(data()):
|
||||
generated_characters += len(out[0]["generated_text"])
|
||||
```
|
||||
|
||||
## Modele mari
|
||||
|
||||
[Accelerate](https://hf.co/docs/accelerate/index) activează câteva optimizări pentru rularea modelelor mari cu [`Pipeline`]. Asigură-te mai întâi că Accelerate este instalat.
|
||||
|
||||
```py
|
||||
!pip install -U accelerate
|
||||
```
|
||||
|
||||
Setarea `device_map="auto"` este utilă pentru a distribui automat modelul mai întâi pe cele mai rapide device-uri (GPU-uri) înainte de a-l trimite către alte device-uri mai lente, dacă sunt disponibile (CPU, hard drive).
|
||||
|
||||
[`Pipeline`] suportă weights cu precizie redusă (torch.float16), care pot fi semnificativ mai rapide și economisesc memorie. Pierderea de performanță este neglijabilă pentru majoritatea modelelor, în special pentru cele mai mari. Dacă hardware-ul tău suportă acest lucru, poți activa în schimb torch.bfloat16 pentru un interval mai mare.
|
||||
|
||||
> [!TIP]
|
||||
> Input-urile sunt convertite intern la torch.float16 și funcționează doar pentru modele cu un backend PyTorch.
|
||||
|
||||
În cele din urmă, [`Pipeline`] acceptă și modele cuantizate pentru a reduce și mai mult utilizarea memoriei. Asigură-te mai întâi că ai instalată biblioteca [bitsandbytes](https://hf.co/docs/bitsandbytes/installation), iar apoi adaugă `quantization_config` în `model_kwargs` în pipeline.
|
||||
|
||||
```py
|
||||
import torch
|
||||
from transformers import pipeline, BitsAndBytesConfig
|
||||
|
||||
pipeline = pipeline(model="google/gemma-7b", dtype=torch.bfloat16, device_map="auto", model_kwargs={"quantization_config": BitsAndBytesConfig(load_in_8bit=True)})
|
||||
pipeline("the secret to baking a good cake is ")
|
||||
[{'generated_text': 'the secret to baking a good cake is 1. the right ingredients 2. the right'}]
|
||||
```
|
||||
163
docs/source/ro/pipeline_webserver.md
Normal file
163
docs/source/ro/pipeline_webserver.md
Normal file
@@ -0,0 +1,163 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Inferență pe web server
|
||||
|
||||
Un web server este un sistem care așteaptă cereri și le servește pe măsură ce sosesc. Acest lucru înseamnă că poți folosi [`Pipeline`] ca motor de inferență pe un web server, deoarece poți folosi un iterator (similar cu modul în care ai [itera peste un set de date](./pipeline_tutorial#seturi-de-date-mari)) pentru a gestiona fiecare cerere primită.
|
||||
|
||||
Totuși, proiectarea unui web server cu [`Pipeline`] este aparte deoarece sunt fundamental diferite. Web server-ele sunt multiplexate (multithreaded, async etc.) pentru a gestiona simultan mai multe cereri. [`Pipeline`] și modelul său de bază, pe de altă parte, nu sunt concepute pentru paralelism deoarece consumă multă memorie. Cel mai bine este să oferi unui [`Pipeline`] toate resursele disponibile atunci când rulează sau pentru un job intensiv din punct de vedere computațional.
|
||||
|
||||
Acest ghid arată cum să ocolești această diferență folosind un web server pentru a gestiona sarcina mai ușoară de primire și trimitere a cererilor și având un singur thread pentru a gestiona sarcina mai grea de rulare a [`Pipeline`].
|
||||
|
||||
## Crearea unui server
|
||||
|
||||
[Starlette](https://www.starlette.io/) este un framework ușor pentru construirea de web server-e. Poți folosi orice alt framework dorești, dar s-ar putea să fie nevoie să faci câteva modificări la codul de mai jos.
|
||||
|
||||
Înainte de a începe, asigură-te că Starlette și [uvicorn](http://www.uvicorn.org/) sunt instalate.
|
||||
|
||||
```py
|
||||
!pip install starlette uvicorn
|
||||
```
|
||||
|
||||
Acum poți crea un web server simplu într-un fișier `server.py`. Cheia este să încarci modelul **o singură dată** pentru a preveni ca niște copii inutile ale acestuia să consume memorie.
|
||||
|
||||
Creează un pipeline pentru a completa token-ul mascat, `[MASK]`.
|
||||
|
||||
```py
|
||||
from starlette.applications import Starlette
|
||||
from starlette.responses import JSONResponse
|
||||
from starlette.routing import Route
|
||||
from transformers import pipeline
|
||||
import asyncio
|
||||
|
||||
async def homepage(request):
|
||||
payload = await request.body()
|
||||
string = payload.decode("utf-8")
|
||||
response_q = asyncio.Queue()
|
||||
await request.app.model_queue.put((string, response_q))
|
||||
output = await response_q.get()
|
||||
return JSONResponse(output)
|
||||
|
||||
async def server_loop(q):
|
||||
pipe = pipeline(task="fill-mask",model="google-bert/bert-base-uncased")
|
||||
while True:
|
||||
(string, response_q) = await q.get()
|
||||
out = pipe(string)
|
||||
await response_q.put(out)
|
||||
|
||||
app = Starlette(
|
||||
routes=[
|
||||
Route("/", homepage, methods=["POST"]),
|
||||
],
|
||||
)
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
q = asyncio.Queue()
|
||||
app.model_queue = q
|
||||
asyncio.create_task(server_loop(q))
|
||||
```
|
||||
|
||||
Pornește server-ul cu următoarea comandă.
|
||||
|
||||
```bash
|
||||
uvicorn server:app
|
||||
```
|
||||
|
||||
Interoghează server-ul cu o cerere POST.
|
||||
|
||||
```bash
|
||||
curl -X POST -d "Paris is the [MASK] of France." http://localhost:8000/
|
||||
```
|
||||
|
||||
Acest lucru ar trebui să returneze output-ul de mai jos.
|
||||
|
||||
```bash
|
||||
[{'score': 0.9969332218170166,
|
||||
'token': 3007,
|
||||
'token_str': 'capital',
|
||||
'sequence': 'paris is the capital of france.'},
|
||||
{'score': 0.0005914849461987615,
|
||||
'token': 2540,
|
||||
'token_str': 'heart',
|
||||
'sequence': 'paris is the heart of france.'},
|
||||
{'score': 0.00043787318281829357,
|
||||
'token': 2415,
|
||||
'token_str': 'center',
|
||||
'sequence': 'paris is the center of france.'},
|
||||
{'score': 0.0003378340043127537,
|
||||
'token': 2803,
|
||||
'token_str': 'centre',
|
||||
'sequence': 'paris is the centre of france.'},
|
||||
{'score': 0.00026995912776328623,
|
||||
'token': 2103,
|
||||
'token_str': 'city',
|
||||
'sequence': 'paris is the city of france.'}]
|
||||
```
|
||||
|
||||
## Punerea cererilor în queue
|
||||
|
||||
Mecanismul de punere în queue al server-ului poate fi folosit pentru unele aplicații interesante precum dynamic batching. Dynamic batching acumulează mai întâi mai multe cereri înainte de a le procesa cu [`Pipeline`].
|
||||
|
||||
Exemplul de mai jos este scris în pseudocod pentru lizibilitate mai degrabă decât pentru performanță, în special, vei observa că:
|
||||
|
||||
1. Nu există o limită pentru dimensiunea batch-ului.
|
||||
2. Timeout-ul este resetat la fiecare preluare din queue, așa că ai putea ajunge să aștepți mult mai mult decât valoarea `timeout` înainte de a procesa o cerere. Acest lucru ar întârzia și prima cerere de inferență cu acea perioadă de timp. Web server-ul așteaptă mereu 1ms chiar dacă queue-ul este gol, ceea ce este ineficient, deoarece acel timp poate fi folosit pentru a porni inferența. Totuși, ar putea avea sens dacă batching-ul este esențial pentru cazul tău de utilizare.
|
||||
|
||||
Ar fi mai bine să ai un singur deadline de 1ms, în loc să îl resetezi la fiecare preluare, așa cum se arată mai jos.
|
||||
|
||||
```py
|
||||
async def server_loop(q):
|
||||
pipe = pipeline(task="fill-mask", model="google-bert/bert-base-uncased")
|
||||
while True:
|
||||
(string, rq) = await q.get()
|
||||
strings = []
|
||||
queues = []
|
||||
strings.append(string)
|
||||
queues.append(rq)
|
||||
while True:
|
||||
try:
|
||||
(string, rq) = await asyncio.wait_for(q.get(), timeout=1)
|
||||
except asyncio.exceptions.TimeoutError:
|
||||
break
|
||||
strings.append(string)
|
||||
queues.append(rq)
|
||||
outs = pipe(strings, batch_size=len(strings))
|
||||
for rq, out in zip(queues, outs):
|
||||
await rq.put(out)
|
||||
```
|
||||
|
||||
## Verificarea erorilor
|
||||
|
||||
Sunt multe lucruri care pot merge prost în producție. Ai putea rămâne fără memorie (out-of-memory), fără spațiu, ai putea eșua la încărcarea unui model, ai putea avea o configurație incorectă a modelului, o interogare incorectă și multe altele.
|
||||
|
||||
Adăugarea de instrucțiuni `try...except` este utilă pentru a returna aceste erori utilizatorului în scop de debugging. Ține cont că acest lucru ar putea fi un risc de securitate dacă nu ar trebui să dezvălui anumite informații.
|
||||
|
||||
## Circuit breaking
|
||||
|
||||
Încearcă să returnezi o eroare 503 sau 504 atunci când server-ul este suprasolicitat, în loc să forțezi un utilizator să aștepte la nesfârșit.
|
||||
|
||||
Este relativ simplu să implementezi aceste tipuri de erori deoarece este vorba doar de un singur queue. Aruncă o privire la dimensiunea queue-ului pentru a determina când să începi să returnezi erori înainte ca server-ul tău să cedeze sub sarcină.
|
||||
|
||||
## Blocarea thread-ului principal
|
||||
|
||||
PyTorch nu este conștient de async, așa că procesarea va bloca rularea thread-ului principal.
|
||||
|
||||
Din acest motiv, este mai bine să rulezi PyTorch pe propriul său thread sau proces separat. Când inferența unei singure cereri este deosebit de lungă (mai mult de 1s), acest lucru este și mai important deoarece înseamnă că fiecare interogare din timpul inferenței trebuie să aștepte 1s înainte de a primi măcar o eroare.
|
||||
|
||||
## Dynamic batching
|
||||
|
||||
Dynamic batching poate fi foarte eficient atunci când este folosit în contextul potrivit, dar nu este necesar când transmiți doar o cerere pe rând (vezi [inferența în batch-uri](./pipeline_tutorial#inferență-în-batch-uri) pentru mai multe detalii).
|
||||
160
docs/source/ro/pr_checks.md
Normal file
160
docs/source/ro/pr_checks.md
Normal file
@@ -0,0 +1,160 @@
|
||||
<!---
|
||||
Copyright 2020 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Verificările pentru pull request
|
||||
|
||||
Când deschizi un pull request, CI-ul Hugging Face rulează mai multe verificări care trebuie să treacă înainte ca PR-ul tău să poată fi integrat.
|
||||
|
||||
- [Remedierea CI-ului](#remedierea-ci-ului) listează comenzile de rulat local ca să treci verificările.
|
||||
- Secțiunile care urmează descriu ce validează fiecare verificare, cum ar fi [calitatea codului](#calitatea-codului) și [consistența repository-ului](#consistența-repository-ului).
|
||||
- [Teste](#teste) descrie ce teste sunt rulate, categoriile de teste și testele slow.
|
||||
|
||||
## Remedierea CI-ului
|
||||
|
||||
În cele mai multe cazuri, `make style` este suficient pentru a trece verificarea de calitate a codului, care este cel mai comun eșec.
|
||||
|
||||
```bash
|
||||
make style
|
||||
```
|
||||
|
||||
Pentru eșecuri la consistența repository-ului, copii sau fișiere auto-generate, rulează `make fix-repo`. Remediază stilul, copiile, docstring-urile și fișierele auto-generate într-o singură trecere.
|
||||
|
||||
```bash
|
||||
make fix-repo
|
||||
```
|
||||
|
||||
Pentru o modificare mai mare, secvența de trei comenzi de mai jos acoperă fiecare verificare. Este mai grea, dar prinde tot înainte să dai push.
|
||||
|
||||
```bash
|
||||
make fix-repo # auto-remediază tot ce poate fi auto-remediat
|
||||
make typing # verifică tipurile și structura modelului, remediază manual orice erori
|
||||
make check-repo # verifică că toate verificările trec, remediază ce mai rămâne
|
||||
```
|
||||
|
||||
`make typing` prinde erori de tip și violări de structură a modelului pe care le remediezi manual. `make check-repo` face o trecere finală read-only ca să confirmi că totul este pregătit.
|
||||
|
||||
> [!NOTE]
|
||||
> CI-ul este uneori instabil. Dacă o verificare eșuează pe ceva fără legătură cu modificarea ta, contactează un maintainer ca să o reruleze.
|
||||
|
||||
## Calitatea codului
|
||||
|
||||
Verificarea calității codului acoperă formatarea, importurile, type checking-ul și regulile de structură a modelului. Corespunde cu `make fix-repo` și `make typing`.
|
||||
|
||||
`make style` (inclus în `make fix-repo`) auto-remediază linting-ul și formatarea [Ruff](https://docs.astral.sh/ruff/), ordinea importurilor din `__init__.py` și consistența auto-mapărilor.
|
||||
|
||||
`make typing` efectuează type checking cu [ty](https://docs.astral.sh/ty/) și validează regulile TRansFormers (TRF), care acoperă convențiile de denumire ale claselor de config și semnăturile `forward()`. Erorile de tip și violările TRF raportează un număr de regulă specific și trebuie remediate manual. Regulile se găsesc în repository-ul [mlinter](https://github.com/huggingface/transformers-mlinter). Rulează `python -m utils.mlinter --list-rules` ca să vezi fiecare regulă TRF, sau `python -m utils.mlinter --rule TRFXXX` ca să vezi documentația completă pentru o regulă specifică.
|
||||
|
||||
Dacă o regulă TRF necesită o excepție, alege una din aceste opțiuni (vezi [Suprimarea violărilor](./modeling_rules#suprimarea-violărilor) pentru mai multe detalii).
|
||||
|
||||
- Adaugă numele modelului tău în lista `allowlist_models` pentru regula relevantă din `utils/mlinter/rules.toml`. Folosește asta când întregul fișier de model necesită o excepție.
|
||||
- Adaugă `# trf-ignore: TRFXXX` pe aceeași linie cu construcția semnalată, sau pe linia imediat de deasupra. Folosește asta când doar o construcție semnalată necesită o excepție.
|
||||
|
||||
## Consistența repository-ului
|
||||
|
||||
Verificarea consistenței repository-ului este similară cu `make check-repo`, cu excepția că se oprește la primul eșec. Menține repository-ul intern consistent în categoriile de mai jos: obiectele publice rămân importabile, codul copiat rămâne sincronizat cu sursa sa, iar fișierele auto-generate (dummy-uri, doctests, metadate) reflectă starea curentă a codului. Pentru modelele noi, verifică și că fiecare clasă de model nouă este înregistrată în auto-mapări.
|
||||
|
||||
| Categorie | Ce validează | Auto-remediat? |
|
||||
|---|---|---|
|
||||
| Fișiere init | Fiecare obiect public nou trebuie să apară atât în `_import_structure` (lazy loading), cât și în blocul `if TYPE_CHECKING` (importuri pentru type checker) din `__init__.py` | Manual |
|
||||
| Copii și modular | Blocurile `# Copied from` corespund sursei lor și fișierele generate din modular sunt actualizate | `make fix-repo` |
|
||||
| Docstring-uri și docs | Docstring-urile argumentelor corespund semnăturilor funcțiilor și cuprinsului documentației | `make fix-repo` |
|
||||
| Fișiere auto-generate | Dummy-uri, pipeline typing, lista doctest, metadate, tabel de dependențe | `make fix-repo` |
|
||||
| Validarea config | Clasele de config au checkpoint-uri valide în docstring-uri și atributele de config corespund fișierului de modelare | Manual |
|
||||
|
||||
## Teste
|
||||
|
||||
CI rulează un subset țintit de teste bazat pe ce modifică PR-ul tău. CI rulează testele într-o ordine ușor randomizată cu [pytest-random-order](https://github.com/jbasko/pytest-random-order) ca să prindă testele cuplate. Rularea printează seed-ul random la început ca să poți repeta aceeași ordine cu `--random-order-seed=<seed>`.
|
||||
|
||||
Dacă un test trece local pe GPU, dar eșuează în CI, setează `TRANSFORMERS_TEST_DEVICE="cpu"` ca să verifici dacă poți reproduce eșecul pe CPU.
|
||||
|
||||
```bash
|
||||
TRANSFORMERS_TEST_DEVICE="cpu" pytest tests/models/my_model/ -v
|
||||
```
|
||||
|
||||
Secțiunile de mai jos explică cum funcționează selecția testelor, ce job-uri rulează și cum să gestionezi testele slow.
|
||||
|
||||
### Selecția testelor
|
||||
|
||||
CI nu rulează suita completă de teste la fiecare PR. CI sare peste testele decorate cu `@slow` la fiecare PR, iar un maintainer le declanșează pe GPU odată ce PR-ul este în review.
|
||||
|
||||
`utils/tests_fetcher.py` urmărește dependențele de import din fișierele tale modificate ca să identifice testele afectate și le rulează doar pe acelea. Prinde și regresiile în alte modele când atingi utilitare partajate. Fetcher-ul printează ce fișiere s-au modificat și ce teste sunt impactate, apoi scrie lista în `tests_torch_test_list.txt`.
|
||||
|
||||
Folosește fetcher-ul ca să replici exact ce rulează CI.
|
||||
|
||||
```bash
|
||||
python utils/tests_fetcher.py
|
||||
python -m pytest -n 8 --dist=loadfile -rA -s $(cat test_preparation/tests_torch_test_list.txt)
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> Modificarea fișierelor de bază precum `modeling_utils.py` sau `generation/utils.py` declanșează toate testele de model, nu doar subsetul afectat.
|
||||
|
||||
Poți și să rulezi fiecare test pentru modelul tău necondiționat. O rulare directă este o verificare locală mai rapidă, dar nu va prinde regresiile în alte modele cauzate de cod partajat pe care l-ai atins.
|
||||
|
||||
```bash
|
||||
pytest tests/models/my_model/ -v
|
||||
```
|
||||
|
||||
### Categoriile de job-uri de test
|
||||
|
||||
Testele sunt împărțite pe job-uri CI paralele, iar fiecare job preia fișiere după pattern de cale. Job-urile relevante pentru un PR de model sunt:
|
||||
|
||||
- `tests_torch`: teste de modelare (`tests/models/*/test_modeling_*.py`)
|
||||
- `tests_tokenization`: teste pentru tokenizer (`tests/models/*/test_tokenization_*.py`)
|
||||
- `tests_processors`: teste pentru procesatoare și feature extractors (`tests/models/*/test_(processing|image_processing|feature_extractor)_*.py`)
|
||||
- `tests_generate`: teste de generare
|
||||
- `pipelines_torch`: teste de pipeline
|
||||
- `tests_training_ci`: teste pentru loop-ul de antrenare
|
||||
- `tests_tensor_parallel_ci`: teste de tensor parallelism
|
||||
|
||||
### Testele slow
|
||||
|
||||
Rulările regulate CI sar peste testele decorate cu `@slow`. Acestea descarcă checkpoint-uri reale sau necesită resurse de calcul semnificative, deci rulează pe instanțe GPU, iar maintainerii le declanșează odată ce PR-ul tău este în review.
|
||||
|
||||
Testele slow rulează pe un NVIDIA A10, iar rezultatele numerice pot varia ușor între hardware-ul CI și mașina ta locală. Maintainerii ajustează de obicei acele valori în teste dacă e necesar când se adaugă un model nou.
|
||||
|
||||
Rulează testele slow local cu comanda de mai jos.
|
||||
|
||||
```bash
|
||||
RUN_SLOW=1 python -m pytest tests/models/my_model/ -v
|
||||
```
|
||||
|
||||
### Build-ul documentației
|
||||
|
||||
Un job `build_pr_documentation` construiește și generează un preview al documentației. Un bot postează un link de preview în PR-ul tău, iar verificarea trebuie să treacă înainte de integrare. Cele mai multe eșecuri sunt o intrare lipsă în `toctree`. Ca să construiești documentația local, vezi [README.md](https://github.com/huggingface/transformers/tree/main/docs) din folder-ul docs.
|
||||
|
||||
## Sintaxa `# Copied from`
|
||||
|
||||
> [!WARNING]
|
||||
> Pentru modele noi, preferă întotdeauna [workflow-ul modular](modular_transformers) (`modular_*.py`) față de `# Copied from`. Evită `# Copied from` ori de câte ori e posibil.
|
||||
|
||||
Mecanismul `# Copied from` menține codul copiat sincronizat cu sursa sa. Când `make fix-repo` rulează, verifică fiecare bloc `# Copied from` și îl actualizează să corespundă originalului, deci editările din interiorul unui bloc `# Copied from` sunt suprascrise. Editează sursa în schimb și lasă `make fix-repo` să propage modificarea.
|
||||
|
||||
Formele de bază ale `# Copied from` includ următoarele.
|
||||
|
||||
```py
|
||||
# Copied from transformers.models.bert.modeling_bert.BertSelfOutput
|
||||
|
||||
# Copied from transformers.models.bert.modeling_bert.BertAttention with Bert->Roberta
|
||||
|
||||
# Copied from transformers.models.bert.modeling_bert.BertForSequenceClassification with Bert->MobileBert all-casing
|
||||
```
|
||||
|
||||
Sintaxa `with model->newModel` aplică înlocuiri de string-uri după copiere. Separă înlocuirile multiple cu virgule, aplicate de la stânga la dreapta. Opțiunea `all-casing` înlocuiește toate variantele de scriere deodată (`Bert`, `bert`, `BERT` devin `MobileBert`, `mobilebert`, `MOBILEBERT`).
|
||||
131
docs/source/ro/processors.md
Normal file
131
docs/source/ro/processors.md
Normal file
@@ -0,0 +1,131 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Procesatoare
|
||||
|
||||
Modelele multimodale necesită un preprocesator capabil să gestioneze input-uri care combină mai mult de o modalitate. În funcție de modalitatea de input, un procesator trebuie să convertească textul într-un array de tensori, imaginile în valori de pixeli și audio într-un array cu tensori cu rata de eșantionare corectă.
|
||||
|
||||
De exemplu, [PaliGemma] este un model viziune-limbaj care folosește procesatorul de imagini [SigLIP] și tokenizer-ul [Llama]. O clasă [`ProcessorMixin`] înfășoară ambele tipuri de preprocesatoare, furnizând o clasă de procesor unică și unificată pentru un model multimodal.
|
||||
|
||||
Apelează [`~ProcessorMixin.from_pretrained`] ca să încarci un procesator. Pasează tipul de input procesatorului ca să generezi input-urile așteptate de model, input ids și valori de pixeli.
|
||||
|
||||
```py
|
||||
from transformers import AutoProcessor, PaliGemmaForConditionalGeneration
|
||||
from PIL import Image
|
||||
import requests
|
||||
|
||||
processor = AutoProcessor.from_pretrained("google/paligemma-3b-pt-224")
|
||||
|
||||
prompt = "answer en Where is the cat standing?"
|
||||
url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/pipeline-cat-chonk.jpeg"
|
||||
image = Image.open(requests.get(url, stream=True).raw)
|
||||
|
||||
inputs = processor(text=prompt, images=image, return_tensors="pt")
|
||||
inputs
|
||||
```
|
||||
|
||||
Acest ghid descrie clasa de procesor și cum să preprocesezi input-uri multimodale.
|
||||
|
||||
## Clasele de procesatoare
|
||||
|
||||
Toate procesatoarele moștenesc din clasa [`ProcessorMixin`] care furnizează metode precum [`~ProcessorMixin.from_pretrained`], [`~ProcessorMixin.save_pretrained`] și [`~ProcessorMixin.push_to_hub`] pentru încărcarea, salvarea și partajarea procesatoarelor pe Hub.
|
||||
|
||||
Există două moduri de a încărca un procesator: cu un [`AutoProcessor`] sau cu o clasă de procesor specifică modelului.
|
||||
|
||||
<hfoptions id="processor-class">
|
||||
<hfoption id="AutoProcessor">
|
||||
|
||||
API-ul [AutoClass] furnizează o interfață simplă ca să încarci procesatoare fără să specifici direct clasa de model specifică căreia îi aparține.
|
||||
|
||||
Folosește [`~AutoProcessor.from_pretrained`] ca să încarci un procesator.
|
||||
|
||||
```py
|
||||
from transformers import AutoProcessor
|
||||
|
||||
processor = AutoProcessor.from_pretrained("google/paligemma-3b-pt-224")
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="model-specific processor">
|
||||
|
||||
Procesatoarele sunt și ele asociate cu o clasă specifică de model multimodal preantrenat. Poți încărca un procesator direct din clasa de model cu [`~ProcessorMixin.from_pretrained`].
|
||||
|
||||
```py
|
||||
from transformers import WhisperProcessor
|
||||
|
||||
processor = WhisperProcessor.from_pretrained("openai/whisper-tiny")
|
||||
```
|
||||
|
||||
Poți și să încarci separat cele două tipuri de preprocesatoare, [`WhisperTokenizerFast`] și [`WhisperFeatureExtractor`].
|
||||
|
||||
```py
|
||||
from transformers import WhisperTokenizerFast, WhisperFeatureExtractor, WhisperProcessor
|
||||
|
||||
tokenizer = WhisperTokenizerFast.from_pretrained("openai/whisper-tiny")
|
||||
feature_extractor = WhisperFeatureExtractor.from_pretrained("openai/whisper-tiny")
|
||||
processor = WhisperProcessor(feature_extractor=feature_extractor, tokenizer=tokenizer)
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
## Preprocesare
|
||||
|
||||
Procesatoarele preprocesează input-urile multimodale în formatul Transformers așteptat. Există câteva combinații de modalități de input pe care un procesator le poate gestiona, cum ar fi text și audio sau text și imagine.
|
||||
|
||||
Task-urile de recunoaștere automată a vorbirii (ASR) necesită un procesator care poate gestiona input-uri de text și audio. Încarcă un dataset și uită-te la coloanele `audio` și `text` (poți elimina celelalte coloane care nu sunt necesare).
|
||||
|
||||
```py
|
||||
from datasets import load_dataset
|
||||
|
||||
dataset = load_dataset("lj_speech", split="train")
|
||||
dataset = dataset.map(remove_columns=["file", "id", "normalized_text"])
|
||||
dataset[0]["audio"]
|
||||
{'array': array([-7.3242188e-04, -7.6293945e-04, -6.4086914e-04, ...,
|
||||
7.3242188e-04, 2.1362305e-04, 6.1035156e-05], dtype=float32),
|
||||
'path': '/root/.cache/huggingface/datasets/downloads/extracted/917ece08c95cf0c4115e45294e3cd0dee724a1165b7fc11798369308a465bd26/LJSpeech-1.1/wavs/LJ001-0001.wav',
|
||||
'sampling_rate': 22050}
|
||||
|
||||
dataset[0]["text"]
|
||||
'Printing, in the only sense with which we are at present concerned, differs from most if not from all the arts and crafts represented in the Exhibition'
|
||||
```
|
||||
|
||||
Nu uita să dai resample ratei de eșantionare ca să se potrivească cu rata de eșantionare cerută de modelul preantrenat.
|
||||
|
||||
```py
|
||||
from datasets import Audio
|
||||
|
||||
dataset = dataset.cast_column("audio", Audio(sampling_rate=16000))
|
||||
```
|
||||
|
||||
Încarcă un procesator și pasează-i coloanele `array` audio și `text`.
|
||||
|
||||
```py
|
||||
from transformers import AutoProcessor
|
||||
|
||||
processor = AutoProcessor.from_pretrained("openai/whisper-tiny")
|
||||
|
||||
def prepare_dataset(example):
|
||||
audio = example["audio"]
|
||||
example.update(processor(audio=audio["array"], text=example["text"], sampling_rate=16000))
|
||||
return example
|
||||
```
|
||||
|
||||
Aplică funcția `prepare_dataset` ca să preprocesezi dataset-ul. Procesatorul returnează `input_features` pentru coloana `audio` și `labels` pentru coloana de text.
|
||||
|
||||
```py
|
||||
prepare_dataset(dataset[0])
|
||||
```
|
||||
278
docs/source/ro/quicktour.md
Normal file
278
docs/source/ro/quicktour.md
Normal file
@@ -0,0 +1,278 @@
|
||||
<!--Copyright 2024 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Pornire rapidă
|
||||
|
||||
[[open-in-colab]]
|
||||
|
||||
Transformers este construit astfel încât să fie rapid și ușor de folosit pentru ca toată lumea să poată să învețe și să construiască utilizând modele transformers.
|
||||
|
||||
Numărul de abstractizări orientate către utilizator este limitat la trei clase pentru inițializarea unui model și două API-uri pentru antrenare sau inferență. Acest ghid de pornire rapidă te introduce în funcțiile de bază ale Transformers și îți arată cum să:
|
||||
|
||||
- încarci un model pre-antrenat
|
||||
- rulezi inferență cu [`Pipeline`]
|
||||
- ajustezi un model cu [`Trainer`]
|
||||
|
||||
## Configurare
|
||||
|
||||
Pentru început, recomandăm să creezi un [cont](https://hf.co/join) Hugging Face. Un cont îți permite să rulezi și să accesezi modele, seturi de date și [Spaces](https://hf.co/spaces) pe [Hub-ul](https://hf.co/docs/hub/index) Hugging Face, o platformă colaborativă pentru construire și descoperire.
|
||||
|
||||
Creează un [User Access Token](https://hf.co/docs/hub/security-tokens#user-access-tokens) și autentifică-te în contul tău.
|
||||
|
||||
<hfoptions id="authenticate">
|
||||
<hfoption id="notebook">
|
||||
|
||||
Introdu User Access Token-ul în [`~huggingface_hub.notebook_login`] la autentificare.
|
||||
|
||||
```py
|
||||
from huggingface_hub import notebook_login
|
||||
|
||||
notebook_login()
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="CLI">
|
||||
|
||||
Asigură-te că package-ul [huggingface_hub[cli]](https://huggingface.co/docs/huggingface_hub/guides/cli#getting-started) este instalat și rulează comanda de mai jos. Introdu User Access Token-ul la autentificare.
|
||||
|
||||
```bash
|
||||
hf auth login
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
Instalează PyTorch.
|
||||
|
||||
```bash
|
||||
!pip install torch
|
||||
```
|
||||
|
||||
După, instalează o versiune la zi a Transformers și biblioteci adiționale din ecosistemul Hugging Face pentru a accesa seturi de date, modele de vision, și pentru a evalua și optimiza antrenarea modelelor mari.
|
||||
|
||||
```bash
|
||||
!pip install -U transformers datasets evaluate accelerate timm
|
||||
```
|
||||
|
||||
## Modele pre-antrenate
|
||||
|
||||
Fiecare model pre-antrenat moștenește din 3 clase de bază.
|
||||
|
||||
| **Clasă** | **Descriere** |
|
||||
|---|---|
|
||||
| [`PreTrainedConfig`] | Un fișier care specifică atributele modelului, precum numărul de attention heads și dimensiunea vocabularului. |
|
||||
| [`PreTrainedModel`] | Un model (sau o arhitectură) definit(ă) de atributele modelului din fișierul de configurație. Un model pre-antrenat returnează doar raw hidden states. Pentru un task specific, folosește model head-ul potrivit pentru a transforma raw hidden states într-un rezultat relevant (spre exemplu, [`LlamaModel`] versus [`LlamaForCausalLM`]). |
|
||||
| Preprocessor | O clasă pentru transformarea din raw inputs (text, imagini, audio, multimodale) în numerical inputs pentru model. Spre exemplu, [`PreTrainedTokenizer`] transformă text în tensori și [`ImageProcessingMixin`] transformă pixeli în tensori. |
|
||||
|
||||
Recomandăm să utilizezi API-ul [AutoClass](./model_doc/auto) pentru încărcarea modelelor și a preprocesatoarelor pentru că alege automat arhitectura potrivită pentru fiecare task și framework-ul de machine learning în baza numelui sau path-ului pentru model weights și a fișierului de configurație.
|
||||
|
||||
Folosește [`~PreTrainedModel.from_pretrained`] pentru a încărca weights și fișierul de configurație de pe Hub în model și clasa de preprocesare.
|
||||
|
||||
Când încarci un model, configurează parametrii de mai jos pentru ca modelul să fie încărcat optim.
|
||||
|
||||
- `device_map="auto"` alocă automat model weights celui mai rapid dispozitiv.
|
||||
- `dtype="auto"` inițializează din start model weights cu tipul de date în care acestea sunt salvate, ceea ce poate evita încărcarea lor de două ori (PyTorch utilizează implicit tipul `torch.float32`).
|
||||
|
||||
```py
|
||||
from transformers import AutoModelForCausalLM, AutoTokenizer
|
||||
|
||||
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf", dtype="auto", device_map="auto")
|
||||
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
|
||||
```
|
||||
|
||||
Tokenizează textul și returnează tensori PyTorch cu Tokenizatorul. Mută modelul pe un accelerator (dacă unul este disponibil) pentru a accelera inferența.
|
||||
|
||||
```py
|
||||
model_inputs = tokenizer(["The secret to baking a good cake is "], return_tensors="pt").to(model.device)
|
||||
```
|
||||
|
||||
Modelul este pregătit pentru antrenare sau inferență.
|
||||
|
||||
Pentru inferență, introdu input-urile tokenizate în [`~GenerationMixin.generate`] pentru a genera text. Decodează token id-urile înapoi în text utilizând [`~PreTrainedTokenizerBase.batch_decode`].
|
||||
|
||||
```py
|
||||
generated_ids = model.generate(**model_inputs, max_length=30)
|
||||
tokenizer.batch_decode(generated_ids)[0]
|
||||
'<s> The secret to baking a good cake is 100% in the preparation. There are so many recipes out there,'
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> Vezi secțiunea [Trainer](#trainer-api) ca să înveți cum să ajustezi un model.
|
||||
|
||||
## Pipeline
|
||||
|
||||
Clasa [`Pipeline`] este cel mai convenabil mod de a face inferență cu un model pre-antrenat. Suportă multe task-uri, precum generarea de text, segmentarea de imagini, recunoașterea vocală automată, răspunsuri la întrebări din documente și multe altele.
|
||||
|
||||
> [!TIP]
|
||||
> Vezi referința API-ului [Pipeline](./main_classes/pipelines) pentru o listă completă de task-uri disponibile.
|
||||
|
||||
Creează un obiect [`Pipeline`] și selectează un task. [`Pipeline`] descarcă și salvează în cache un model pentru un task dat. Introdu numele modelului în parametrul `model` pentru a alege un model specific.
|
||||
|
||||
<hfoptions id="pipeline-tasks">
|
||||
<hfoption id="text generation">
|
||||
|
||||
Utilizează [`Accelerator`] pentru a detecta automat un accelerator disponibil pentru inferență.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
from accelerate import Accelerator
|
||||
|
||||
device = Accelerator().device
|
||||
|
||||
pipeline = pipeline("text-generation", model="meta-llama/Llama-2-7b-hf", device=device)
|
||||
```
|
||||
|
||||
Introdu text inițial în [`Pipeline`] pentru a genera mai mult text.
|
||||
|
||||
```py
|
||||
pipeline("The secret to baking a good cake is ", max_length=50)
|
||||
[{'generated_text': 'The secret to baking a good cake is 100% in the batter. The secret to a great cake is the icing.\nThis is why we’ve created the best buttercream frosting reci'}]
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="image segmentation">
|
||||
|
||||
Utilizează [`Accelerator`] pentru a detecta automat un accelerator disponibil pentru inferență.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
from accelerate import Accelerator
|
||||
|
||||
device = Accelerator().device
|
||||
|
||||
pipeline = pipeline("image-segmentation", model="facebook/detr-resnet-50-panoptic", device=device)
|
||||
```
|
||||
|
||||
Introdu o imagine - un URL sau un path local - în [`Pipeline`].
|
||||
|
||||
<div class="flex justify-center">
|
||||
<img src="https://huggingface.co/datasets/Narsil/image_dummy/raw/main/parrots.png"/>
|
||||
</div>
|
||||
|
||||
```py
|
||||
segments = pipeline("https://huggingface.co/datasets/Narsil/image_dummy/raw/main/parrots.png")
|
||||
segments[0]["label"]
|
||||
'bird'
|
||||
segments[1]["label"]
|
||||
'bird'
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
<hfoption id="automatic speech recognition">
|
||||
|
||||
Utilizează [`Accelerator`] pentru a detecta automat un accelerator disponibil pentru inferență.
|
||||
|
||||
```py
|
||||
from transformers import pipeline
|
||||
from accelerate import Accelerator
|
||||
|
||||
device = Accelerator().device
|
||||
|
||||
pipeline = pipeline("automatic-speech-recognition", model="openai/whisper-large-v3", device=device)
|
||||
```
|
||||
|
||||
Introdu un fișier audio în [`Pipeline`].
|
||||
|
||||
```py
|
||||
pipeline("https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/1.flac")
|
||||
{'text': ' He hoped there would be stew for dinner, turnips and carrots and bruised potatoes and fat mutton pieces to be ladled out in thick, peppered flour-fatten sauce.'}
|
||||
```
|
||||
|
||||
</hfoption>
|
||||
</hfoptions>
|
||||
|
||||
## Trainer
|
||||
|
||||
[`Trainer`] este un loop complet de antrenare și evaluare pentru modelele PyTorch. Abstractizează mult din codul boilerplate întâlnit la scrierea manuală a unui loop de antrenare, ca să poți începe antrenarea mai rapid și ca să te focusezi pe designul antrenării. Ai nevoie doar de un model, un set de date, un preprocesator și un data collator ca să construiești batch-uri de date din set.
|
||||
|
||||
Utilizează clasa [`TrainingArguments`] pentru a personaliza procesul de antrenare. Dispune de multe opțiuni pentru antrenare, evaluare și multe altele. Experimentează cu hyperparameters de antrenare și funcții precum mărimea batch-ului, rata de învățare, precizia mixtă, torch.compile și multe altele, pentru necesitățile tale la antrenare. Poți folosi și parametrii impliciți de antrenare pentru a produce rapid un baseline.
|
||||
|
||||
Încarcă un model, un set de date și un tokenizer pentru antrenare.
|
||||
|
||||
```py
|
||||
from transformers import AutoModelForSequenceClassification, AutoTokenizer
|
||||
from datasets import load_dataset
|
||||
|
||||
model = AutoModelForSequenceClassification.from_pretrained("distilbert/distilbert-base-uncased")
|
||||
tokenizer = AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased")
|
||||
dataset = load_dataset("rotten_tomatoes")
|
||||
```
|
||||
|
||||
Creează o funcție pentru a tokeniza textul și a-l transforma în tensori PyTorch. Aplică această funcție întregului set de date cu metoda [`~datasets.Dataset.map`].
|
||||
|
||||
```py
|
||||
def tokenize_dataset(dataset):
|
||||
return tokenizer(dataset["text"])
|
||||
dataset = dataset.map(tokenize_dataset, batched=True)
|
||||
```
|
||||
|
||||
Încarcă un data collator pentru a crea batch-uri de date și asociază-i tokenizer-ul.
|
||||
|
||||
```py
|
||||
from transformers import DataCollatorWithPadding
|
||||
|
||||
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
|
||||
```
|
||||
|
||||
După, configurează [`TrainingArguments`] cu features și hyperparameters de antrenare.
|
||||
|
||||
```py
|
||||
from transformers import TrainingArguments
|
||||
|
||||
training_args = TrainingArguments(
|
||||
output_dir="distilbert-rotten-tomatoes",
|
||||
learning_rate=2e-5,
|
||||
per_device_train_batch_size=8,
|
||||
per_device_eval_batch_size=8,
|
||||
num_train_epochs=2,
|
||||
push_to_hub=True,
|
||||
)
|
||||
```
|
||||
|
||||
În final, introdu toate aceste componente în [`Trainer`] și apelează funcția [`~Trainer.train`] pentru a începe.
|
||||
|
||||
```py
|
||||
from transformers import Trainer
|
||||
|
||||
trainer = Trainer(
|
||||
model=model,
|
||||
args=training_args,
|
||||
train_dataset=dataset["train"],
|
||||
eval_dataset=dataset["test"],
|
||||
processing_class=tokenizer,
|
||||
data_collator=data_collator,
|
||||
)
|
||||
|
||||
trainer.train()
|
||||
```
|
||||
|
||||
Distribuie-ți modelul și tokenizer-ul pe Hub cu [`~Trainer.push_to_hub`].
|
||||
|
||||
```py
|
||||
trainer.push_to_hub()
|
||||
```
|
||||
|
||||
Felicitări, ai terminat de antrenat primul tău model cu Transformers!
|
||||
|
||||
## Următorii pași
|
||||
|
||||
Acum că știi mai multe despre Transformers și despre ce are de oferit, continuă să explorezi și să înveți ceea ce te interesează.
|
||||
|
||||
- **Clase de bază**: Învață mai multe despre clasele de configurație, model și procesare. Asta te va ajuta să creezi și personalizezi modele, să procesezi diferite tipuri de input (audio, imagini, multimodale) și cum să-ți partajezi modelul.
|
||||
- **Inferență**: Explorează [`Pipeline`] în detaliu, inferența si conversarea cu LLMs, agenți și cum să optimizezi inferența cu framework-ul de machine learning și hardware-ul tău.
|
||||
- **Antrenare**: Studiază [`Trainer`] în detaliu, antrenarea distribuită și optimizarea antrenării pe diferite configurații hardware.
|
||||
- **Quantization**: Redu cerințele de memorie și stocare cu quantization și mărește viteza de inferență prin reprezentarea model weights în mai puțini biți.
|
||||
- **Resurse**: Cauți ghiduri complete pentru antrenarea și inferența cu un model pentru un task specific? Consultă ghidurile pentru task-uri!
|
||||
111
docs/source/ro/serialization.md
Normal file
111
docs/source/ro/serialization.md
Normal file
@@ -0,0 +1,111 @@
|
||||
<!--Copyright 2020 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Exportarea pentru producție
|
||||
|
||||
Exportă modelele Transformers în diferite formate pentru rulări și dispozitive optimizate. Dă deploy aceluiași model la furnizori de cloud sau rulează-l pe dispozitive mobile și edge. Nu trebuie să rescrii modelul de la zero pentru fiecare mediu de deployment. Dă deploy liber în orice ecosistem de inferență.
|
||||
|
||||
## ExecuTorch
|
||||
|
||||
[ExecuTorch](https://pytorch.org/executorch/stable/index.html) rulează modele PyTorch pe dispozitive mobile și edge. Exportă un model într-un graf de operatori standardizați, compilează graful într-un program ExecuTorch și îl execută pe dispozitivul țintă. Runtime-ul este ușor și calculează planul de execuție în avans.
|
||||
|
||||
Instalează [Optimum ExecuTorch](https://huggingface.co/docs/optimum-executorch/en/index) din codul sursă.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/huggingface/optimum-executorch.git
|
||||
cd optimum-executorch
|
||||
pip install '.[dev]'
|
||||
```
|
||||
|
||||
Exportă un model Transformers la ExecuTorch cu unealta CLI.
|
||||
|
||||
```bash
|
||||
optimum-cli export executorch \
|
||||
--model "Qwen/Qwen3-8B" \
|
||||
--task "text-generation" \
|
||||
--recipe "xnnpack" \
|
||||
--use_custom_sdpa \
|
||||
--use_custom_kv_cache \
|
||||
--qlinear 8da4w \
|
||||
--qembedding 8w \
|
||||
--output_dir="hf_smollm2"
|
||||
```
|
||||
|
||||
Rulează următoarea comandă pentru a vizualiza toate opțiunile de export.
|
||||
|
||||
```bash
|
||||
optimum-cli export executorch --help
|
||||
```
|
||||
|
||||
## ONNX
|
||||
|
||||
[ONNX](http://onnx.ai) este un limbaj comun pentru descrierea modelelor din diferite framework-uri. Reprezintă modelele ca un graf de operatori standardizați cu tipuri, forme și metadate bine definite. Modelele sunt serializate în fișiere protobuf compacte pe care le poți deploya în runtimes și motoare optimizate.
|
||||
|
||||
[Optimum ONNX](https://huggingface.co/docs/optimum-onnx/index) exportă modele la ONNX cu obiecte de configurație. Suportă multe [arhitecturi](https://huggingface.co/docs/optimum-onnx/onnx/overview) și este ușor de extins. Exportă modele prin unealta CLI sau programatic.
|
||||
|
||||
Instalează [Optimum ONNX](https://huggingface.co/docs/optimum-onnx/index).
|
||||
|
||||
```bash
|
||||
uv pip install optimum-onnx
|
||||
```
|
||||
|
||||
### optimum-cli
|
||||
|
||||
Specifică un model de exportat și directorul de output cu argumentul `--model`.
|
||||
|
||||
```bash
|
||||
optimum-cli export onnx --model Qwen/Qwen3-8B Qwen/Qwen3-8b-onnx/
|
||||
```
|
||||
|
||||
Rulează următoarea comandă pentru a vizualiza toate argumentele disponibile sau consultă ghidul [Export a model to ONNX with optimum.exporters.onnx](https://huggingface.co/docs/optimum-onnx/onnx/usage_guides/export_a_model) pentru mai multe detalii.
|
||||
|
||||
```bash
|
||||
optimum cli export onnx --help
|
||||
```
|
||||
|
||||
Pentru a exporta un model local, salvează fișierele de weights și tokenizer în același director. Pasează calea directorului argumentului `--model` și folosește argumentul `--task` pentru a specifica [task-ul](https://huggingface.co/docs/optimum/exporters/task_manager#transformers). Dacă nu furnizezi `--task`, sistemul îl inferează automat din model sau folosește o arhitectură fără un head specific task-ului.
|
||||
|
||||
```bash
|
||||
optimum-cli export onnx --model path/to/local/model --task text-generation Qwen/Qwen3-8b-onnx/
|
||||
```
|
||||
|
||||
Deployează modelul cu orice [runtime](https://onnx.ai/supported-tools.html#deployModel) care suportă ONNX, inclusiv ONNX Runtime.
|
||||
|
||||
```py
|
||||
from transformers import AutoTokenizer
|
||||
from optimum.onnxruntime import ORTModelForCausalLM
|
||||
|
||||
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-8b-onnx")
|
||||
model = ORTModelForCausalLM.from_pretrained("Qwen/Qwen3-8b-onnx")
|
||||
inputs = tokenizer("Plants generate energy through a process known as ", return_tensors="pt")
|
||||
outputs = model.generate(**inputs)
|
||||
print(tokenizer.batch_decode(outputs))
|
||||
```
|
||||
|
||||
### optimum.onnxruntime
|
||||
|
||||
Exportă modelele Transformers programatic cu Optimum ONNX. Instanțiază un [`~optimum.onnxruntime.ORTModel`] cu un model și setează `export=True`. Salvează modelul ONNX cu [`~optimum.onnxruntime.ORTModel.save_pretrained`].
|
||||
|
||||
```py
|
||||
from optimum.onnxruntime import ORTModelForCausalLM
|
||||
from transformers import AutoTokenizer
|
||||
|
||||
ort_model = ORTModelForCausalLM.from_pretrained("Qwen/Qwen3-8b", export=True)
|
||||
tokenizer = AutoTokenizer.from_pretrained("onnx/")
|
||||
|
||||
ort_model.save_pretrained("onnx/")
|
||||
tokenizer.save_pretrained("onnx/")
|
||||
```
|
||||
433
docs/source/ro/testing.md
Normal file
433
docs/source/ro/testing.md
Normal file
@@ -0,0 +1,433 @@
|
||||
<!--Copyright 2020 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Scrierea testelor pentru modele
|
||||
|
||||
Suita de teste Transformers folosește o arhitectură bazată pe mixin-uri ca să auto-genereze 100+ teste din cod minimal. Scrii o cantitate mică de cod specific modelului, iar mixin-urile se ocupă de save/load, generare, pipeline-uri, antrenare și tensor parallelism.
|
||||
|
||||
Rulează testele modelului tău cu comenzile de mai jos.
|
||||
|
||||
```bash
|
||||
# rulează testele modelului tău
|
||||
pytest tests/models/mymodel/test_modeling_mymodel.py -v
|
||||
|
||||
# rulează un test specific
|
||||
pytest tests/models/mymodel/test_modeling_mymodel.py::MyModelTest::test_model
|
||||
|
||||
# rulează testele care se potrivesc cu un pattern de cuvinte cheie (util ca să rulezi toate testele de integrare)
|
||||
pytest tests/models/mymodel/ -k integration -v
|
||||
|
||||
# include testele de integrare slow
|
||||
RUN_SLOW=1 pytest tests/models/mymodel/ -v
|
||||
```
|
||||
|
||||
CI-ul Hugging Face rulează testele de model fără `@slow` la fiecare pull request, iar testele slow rulează pe un program nightly (vezi [Verificările pentru pull request](./pr_checks) pentru ce validează CI-ul).
|
||||
|
||||
## Alege o clasă de test de bază
|
||||
|
||||
Trei clase de bază acoperă cele mai comune familii de modele. Alege-o pe cea care se potrivește cu modalitatea modelului tău.
|
||||
|
||||
| Clasă de bază | Folosit pentru | Mixin-uri |
|
||||
|---|---|---|
|
||||
| `CausalLMModelTest` | Modele cauzale de limbaj | `ModelTesterMixin`, `GenerationTesterMixin`, `PipelineTesterMixin`, `TrainingTesterMixin`, `TensorParallelTesterMixin` |
|
||||
| `VLMModelTest` | Modele vizual-lingvistice | `ModelTesterMixin`, `GenerationTesterMixin`, `PipelineTesterMixin` |
|
||||
| `ALMModelTest` | Modele audio-lingvistice | `ModelTesterMixin`, `GenerationTesterMixin`, `PipelineTesterMixin` |
|
||||
|
||||
`VLMModelTest` și `ALMModelTest` partajează un părinte comun `MultiModalModelTest` care îmbricuiește sub-config-uri într-un config compus de nivel superior și plasează token-uri placeholder de modalitate în `input_ids` alături de features-urile brute de modalitate (audio sau vizuale). `CausalLMModelTest` nu folosește părintele multimodal. Se bazează pe cele trei mixin-uri partajate și adaugă `TrainingTesterMixin` și `TensorParallelTesterMixin` pentru acoperire de antrenare și tensor-parallel.
|
||||
|
||||
Pentru arhitecturi care nu se potrivesc cu niciunul din cele trei (encoder-only, encoder-decoder etc.), construiește infrastructura de test direct din [pattern-ul cu două clase](#modeltester-și-modeltest) și [mixin-urile de test](#mixin-uri-de-test) descrise mai jos.
|
||||
|
||||
## CausalLMModelTest
|
||||
|
||||
`CausalLMModelTest` este clasa de bază recomandată pentru testarea modelelor cauzale de limbaj. Moștenește din cinci [mixin-uri de test](#mixin-uri-de-test) și auto-generează teste pentru save/load, generare, pipeline-uri, antrenare și tensor parallelism.
|
||||
|
||||
```py
|
||||
import unittest
|
||||
|
||||
from transformers.testing_utils import require_torch
|
||||
from transformers import is_torch_available
|
||||
|
||||
from ...causal_lm_tester import CausalLMModelTest, CausalLMModelTester
|
||||
|
||||
if is_torch_available():
|
||||
from transformers import MyModel
|
||||
|
||||
|
||||
class MyModelTester(CausalLMModelTester):
|
||||
if is_torch_available():
|
||||
base_model_class = MyModel
|
||||
|
||||
|
||||
@require_torch
|
||||
class MyModelTest(CausalLMModelTest, unittest.TestCase):
|
||||
model_tester_class = MyModelTester
|
||||
```
|
||||
|
||||
Aceste două clase oferă acoperire completă de teste pentru `MyModel` și toate clasele sale head (`MyModelForCausalLM`, `MyModelForSequenceClassification` etc.). Vezi [tests/models/llama/test_modeling_llama.py](https://github.com/huggingface/transformers/blob/main/tests/models/llama/test_modeling_llama.py) pentru un exemplu real.
|
||||
|
||||
`CausalLMModelTester` necesită doar `base_model_class`. Tester-ul elimină sufixul `Model` ca să obțină un nume de bază (`LlamaModel` devine `Llama`), apoi adaugă sufixe precum `Config` sau `ForCausalLM` ca să descopere clasele conexe. Dacă o clasă nu există în modul, atributul rămâne `None` și tester-ul sare peste testele corespunzătoare.
|
||||
|
||||
### Suprascrierea valorilor implicite în CausalLMTester
|
||||
|
||||
Dacă modelul tău nu urmează denumirea standard, sau trebuie să personalizezi comportamentul, suprascrie atributele pe tester sau pe clasa de test.
|
||||
|
||||
```py
|
||||
class MyModelTester(CausalLMModelTester):
|
||||
if is_torch_available():
|
||||
base_model_class = MyModel
|
||||
# suprascrie dacă numele clasei nu urmează convenția
|
||||
causal_lm_class = MyCustomCausalLM
|
||||
|
||||
|
||||
@require_torch
|
||||
class MyModelTest(CausalLMModelTest, unittest.TestCase):
|
||||
model_tester_class = MyModelTester
|
||||
# dezactivează testele de resize ale embedding-urilor
|
||||
test_resize_embeddings = False
|
||||
```
|
||||
|
||||
Pentru modele care necesită parametri personalizați de constructor pe tester, suprascrie `__init__` și apelează `super().__init__(parent=parent)` înainte de a seta atribute suplimentare. Vezi [tests/models/youtu/test_modeling_youtu.py](https://github.com/huggingface/transformers/blob/main/tests/models/youtu/test_modeling_youtu.py) pentru un exemplu real.
|
||||
|
||||
```py
|
||||
class YoutuModelTester(CausalLMModelTester):
|
||||
if is_torch_available():
|
||||
base_model_class = YoutuModel
|
||||
|
||||
def __init__(self, parent, kv_lora_rank=16, q_lora_rank=32):
|
||||
super().__init__(parent=parent)
|
||||
self.kv_lora_rank = kv_lora_rank
|
||||
self.q_lora_rank = q_lora_rank
|
||||
```
|
||||
|
||||
## VLMModelTest
|
||||
|
||||
`VLMModelTest` este clasa de bază pentru modelele vizual-lingvistice. Moștenește din trei mixin-uri (`ModelTesterMixin`, `GenerationTesterMixin`, `PipelineTesterMixin`) și setează `_is_composite = True` ca să gestioneze mai multe sub-modele.
|
||||
|
||||
```py
|
||||
import unittest
|
||||
|
||||
from transformers.testing_utils import require_torch
|
||||
from transformers import is_torch_available
|
||||
|
||||
from ...vlm_tester import VLMModelTest, VLMModelTester
|
||||
|
||||
if is_torch_available():
|
||||
from transformers import (
|
||||
MyVLMConfig,
|
||||
MyVLMModel,
|
||||
MyVLMTextConfig,
|
||||
MyVLMVisionConfig,
|
||||
MyVLMForConditionalGeneration,
|
||||
)
|
||||
|
||||
|
||||
class MyVLMTester(VLMModelTester):
|
||||
if is_torch_available():
|
||||
base_model_class = MyVLMModel
|
||||
config_class = MyVLMConfig
|
||||
text_config_class = MyVLMTextConfig
|
||||
vision_config_class = MyVLMVisionConfig
|
||||
conditional_generation_class = MyVLMForConditionalGeneration
|
||||
|
||||
|
||||
@require_torch
|
||||
class MyVLMTest(VLMModelTest, unittest.TestCase):
|
||||
model_tester_class = MyVLMTester
|
||||
```
|
||||
|
||||
### Suprascrierea valorilor implicite în VLMModelTester
|
||||
|
||||
Când VLM-ul necesită parametri de viziune personalizați sau valori de config non-implicite, suprascrie `__init__`. Setează valorile implicite cu `setdefault` înainte de a apela `super().__init__(parent, **kwargs)`. Exemplul de mai jos arată primele câteva valori implicite din [tests/models/qianfan_ocr/test_modeling_qianfan_ocr.py](https://github.com/huggingface/transformers/blob/main/tests/models/qianfan_ocr/test_modeling_qianfan_ocr.py).
|
||||
|
||||
```py
|
||||
class QianfanOCRVisionText2TextModelTester(VLMModelTester):
|
||||
base_model_class = QianfanOCRModel
|
||||
config_class = QianfanOCRConfig
|
||||
text_config_class = Qwen3Config
|
||||
vision_config_class = QianfanOCRVisionConfig
|
||||
conditional_generation_class = QianfanOCRForConditionalGeneration
|
||||
|
||||
def __init__(self, parent, **kwargs):
|
||||
kwargs.setdefault("image_token_id", 1)
|
||||
kwargs.setdefault("image_size", 32)
|
||||
kwargs.setdefault("patch_size", 4)
|
||||
kwargs.setdefault("num_channels", 3)
|
||||
# ... mai multe valori implicite
|
||||
super().__init__(parent, **kwargs)
|
||||
```
|
||||
|
||||
Testele VLM diferă de `CausalLMModelTest` în câteva moduri.
|
||||
|
||||
- Trebuie să setezi `config_class`, `text_config_class`, `vision_config_class` și `conditional_generation_class` pe tester.
|
||||
- `VLMModelTest` nu include `TrainingTesterMixin` sau `TensorParallelTesterMixin`.
|
||||
- `__init__`-ul tester-ului acceptă parametri de viziune (`image_size`, `patch_size`, `num_channels`, `num_image_tokens`) din `**kwargs` și `setdefault()`.
|
||||
- `ConfigTester` folosește `has_text_modality=False` pentru că config-ul de nivel superior este un config compus, nu un config de model text.
|
||||
|
||||
## ALMModelTest
|
||||
|
||||
`ALMModelTest` este clasa de bază pentru modelele audio-lingvistice (ALM) precum Qwen2Audio, AudioFlamingo3 și GraniteSpeech. Oglindește pattern-ul VLM cu același părinte `MultiModalModelTest` și auto-descoperirea claselor head. Mecanismul vizual este înlocuit cu features audio, un sub-config audio și o strategie de plasare a token-urilor audio.
|
||||
|
||||
```py
|
||||
class MyALMTester(ALMModelTester):
|
||||
config_class = MyALMConfig
|
||||
text_config_class = MyALMTextConfig
|
||||
audio_config_class = MyALMAudioConfig
|
||||
conditional_generation_class = MyALMForConditionalGeneration
|
||||
audio_mask_key = "feature_attention_mask"
|
||||
|
||||
|
||||
class MyALMTest(ALMModelTest, unittest.TestCase):
|
||||
model_tester_class = MyALMTester
|
||||
```
|
||||
|
||||
### Suprascrierea valorilor implicite în ALMModelTester
|
||||
|
||||
`__init__`-ul tester-ului setează valori implicite specifice ALM (`feat_seq_length=128`, `num_mel_bins=80`, `audio_token_id=0`). Suprascrie-le cu `setdefault` înainte de a apela `super().__init__(parent, **kwargs)`.
|
||||
|
||||
Două atribute de clasă îi spun tester-ului cum sunt denumite lucrurile în modelul tău.
|
||||
|
||||
- `audio_mask_key`: numele kwarg-ului pe care modelul tău îl așteaptă pentru masca audio (`"feature_attention_mask"`, `"input_features_mask"` etc.). Lasă-l `None` dacă modelul tău nu consumă o mască audio separată.
|
||||
- `audio_config_key`: numele atributului pe care config-ul tău de nivel superior îl folosește ca să îmbricuieze sub-config-ul audio. Implicit `"audio_config"`, dar modele precum GraniteSpeech folosesc `"encoder_config"`.
|
||||
|
||||
```py
|
||||
class Qwen2AudioModelTester(ALMModelTester):
|
||||
def __init__(self, parent, **kwargs):
|
||||
kwargs.setdefault("feat_seq_length", 60)
|
||||
kwargs.setdefault("max_source_positions", kwargs["feat_seq_length"] // 2)
|
||||
super().__init__(parent, **kwargs)
|
||||
```
|
||||
|
||||
`ALMModelTester` îți cere să suprascrii un hook, `get_audio_embeds_mask(audio_mask)`, și expune câteva opțiuni pentru personalizare.
|
||||
|
||||
- `get_audio_embeds_mask(audio_mask)`: returnează masca per-batch a pozițiilor de embedding audio după downsampling-ul encoder-ului. Tester-ul folosește suma sa row-wise ca să decidă câte placeholder-uri `audio_token_id` să insereze în `input_ids`, deci numărul trebuie să corespundă cu ce emite encoder-ul tău.
|
||||
- `create_audio_features()`: returnează tensorul de features audio. Forma implicită este `[batch_size, num_mel_bins, feat_seq_length]`. Suprascrie când modelul tău, precum GraniteSpeech, așteaptă features time-first (`[batch_size, feat_seq_length, num_mel_bins]`).
|
||||
- `create_audio_mask()`: returnează masca de attention la nivel audio. Implicit construiește o regiune validă contiguă aleatorie per rând în batch. Suprascrie cu o mască deterministă full-length dacă testele tale compară două invocații `prepare_config_and_inputs_for_common()` una față de alta, sau dacă encoder-ul tău audio se duce la un backend care respinge măști non-null.
|
||||
- `place_audio_tokens(input_ids, config, num_audio_tokens)`: plasează token-urile placeholder audio contiguu după `BOS`. Suprascrie doar dacă modelul tău are nevoie de un layout diferit.
|
||||
- `get_audio_feature_key()`: returnează cheia din dict-ul de inputuri pentru features audio (`"input_features"` implicit).
|
||||
|
||||
Pe lângă testele multimodale moștenite, `ALMModelTest` adaugă `test_mismatching_num_audio_tokens`. Testul afirmă că modelul ridică un `ValueError` clar când numărul de features audio nu corespunde cu numărul de token-uri placeholder audio din `input_ids` și verifică că un prompt cu mai multe segmente audio se face forward cu succes.
|
||||
|
||||
## Scrie teste pentru alte arhitecturi
|
||||
|
||||
Pentru arhitecturi encoder-only, encoder-decoder, audio sau alte arhitecturi non-standard, construiește infrastructura de test direct din pattern-ul cu două clase și mixin-urile de test descrise mai jos.
|
||||
|
||||
### ModelTester și ModelTest
|
||||
|
||||
Fiecare fișier de test pentru modele urmează aceeași structură.
|
||||
|
||||
1. `ModelTester` (clasă simplă) creează config-uri mici și inputuri dummy pentru testare și poate conține și teste mici de regresie specifice modelului.
|
||||
2. `ModelTest` (`unittest.TestCase` + mixin-uri) moștenește testele auto-generate și le rulează pe fiecare variantă de model.
|
||||
|
||||
`ModelTest` apelează `prepare_config_and_inputs_for_common()` pe tester ca să obțină un tuple `(config, inputs_dict)`. Toate mixin-urile se bazează pe `prepare_config_and_inputs_for_common()` pentru datele de test.
|
||||
|
||||
### Mixin-uri de test
|
||||
|
||||
Alege mixin-urile de care are nevoie modelul tău.
|
||||
|
||||
| Mixin | Fișier sursă | Ce testează |
|
||||
|---|---|---|
|
||||
| `ModelTesterMixin` | `tests/test_modeling_common.py` | Save/load, gradient checkpointing, semnătura forward, atribute comune |
|
||||
| `GenerationTesterMixin` | `tests/generation/test_utils.py` | Greedy, sampling, beam search, assisted decoding |
|
||||
| `PipelineTesterMixin` | `tests/test_pipeline_mixin.py` | Un test per task de pipeline |
|
||||
| `TrainingTesterMixin` | `tests/test_training_mixin.py` | Overfitting pe un batch mic |
|
||||
| `TensorParallelTesterMixin` | `tests/test_tensor_parallel_mixin.py` | Tensor parallelism distribuit |
|
||||
|
||||
### Scrierea unui test de model
|
||||
|
||||
Vezi [tests/models/modernbert/test_modeling_modernbert.py](https://github.com/huggingface/transformers/blob/main/tests/models/modernbert/test_modeling_modernbert.py) pentru un exemplu complet funcțional. Pașii cheie sunt subliniați mai jos.
|
||||
|
||||
1. Clasa `ModelTester` construiește config-uri mici și inputuri dummy. Ține dimensiunile mici ca testele să se termine în secunde pe CPU. Folosește cei trei helpers de tensor de mai jos ca să construiești inputuri.
|
||||
|
||||
- `ids_tensor(shape, vocab_size)`: tensor de întregi aleatori în `[0, vocab_size)`. Folosește pentru `input_ids`, `token_type_ids` și tensori de label.
|
||||
- `random_attention_mask(shape)`: tensor binar (0 și 1) unde primul token este întotdeauna 1. Folosește pentru `attention_mask`.
|
||||
- `floats_tensor(shape, scale=1.0)`: tensor de float-uri aleatorii. Folosește pentru inputuri continue precum `pixel_values` sau `inputs_embeds`.
|
||||
|
||||
Tester-ul trebuie să implementeze `get_config()`, `prepare_config_and_inputs()` și `prepare_config_and_inputs_for_common()`. Adaugă metode `create_and_check_*` pentru fiecare head de task (model de bază, clasificare de secvențe, clasificare de token-uri etc.).
|
||||
|
||||
2. Moștenești din mixin-urile de care are nevoie modelul tău, setezi `all_model_classes` și `pipeline_model_mapping` și definești `setUp()`. Scrii metode `test_*` care deleghează la metodele `create_and_check_*` ale tester-ului.
|
||||
|
||||
3. Pentru fiecare head de task, adaugi o metodă `create_and_check_*` pe tester care instanțiază modelul, rulează un forward pass și afirmă formele de ieșire. Apoi adaugi o metodă `test_*` corespunzătoare pe clasa de test.
|
||||
|
||||
### Organizarea fișierelor
|
||||
|
||||
Fișierele de test trăiesc în `tests/models/mymodel/` urmând structura de mai jos.
|
||||
|
||||
```text
|
||||
tests/models/mymodel/
|
||||
├── __init__.py
|
||||
├── test_modeling_mymodel.py # teste de model (obligatoriu)
|
||||
├── test_tokenization_mymodel.py # teste de tokenizer (dacă ai tokenizer personalizat)
|
||||
├── test_image_processing_mymodel.py # teste pentru procesorul de imagini (dacă e model vizual)
|
||||
├── test_feature_extraction_mymodel.py # teste pentru feature extractor (dacă e model audio/speech)
|
||||
└── test_processing_mymodel.py # teste de procesor (dacă e multimodal)
|
||||
```
|
||||
|
||||
Testele pentru tokenizer urmează același pattern. Moștenești `TokenizerTesterMixin` din `tests/test_tokenization_common.py`, setezi câteva atribute și primești teste auto-generate. Vezi [tests/models/llama/test_tokenization_llama.py](https://github.com/huggingface/transformers/blob/main/tests/models/llama/test_tokenization_llama.py) pentru un exemplu.
|
||||
|
||||
## Teste de config
|
||||
|
||||
`ConfigTester` verifică că o clasă de config gestionează serializarea, save/load și proprietățile standard corect. `CausalLMModelTest` și `VLMModelTest` includ testele de config automat. Pentru calea generală cu `ModelTester` și `ModelTest`, definești tester-ul de config manual în `setUp()`.
|
||||
|
||||
```py
|
||||
from tests.test_configuration_common import ConfigTester
|
||||
|
||||
def setUp(self):
|
||||
self.config_tester = ConfigTester(self, config_class=MyModelConfig, hidden_size=32)
|
||||
|
||||
def test_config(self):
|
||||
self.config_tester.run_common_tests()
|
||||
```
|
||||
|
||||
`run_common_tests()` rulează mai multe verificări.
|
||||
|
||||
- Verifică că proprietăți comune precum `hidden_size`, `num_attention_heads` și `num_hidden_layers` există (și `vocab_size` dacă `has_text_modality=True`).
|
||||
- Testează serializarea JSON cu `to_json_string()` și `to_json_file()`.
|
||||
- Face round-trip cu `save_pretrained()` și `from_pretrained()`.
|
||||
- Confirmă consistența `id2label` și `label2id`.
|
||||
- Creează un config fără argumente ca să valideze inițializarea cu valori implicite.
|
||||
- Setează kwargs comune precum `output_hidden_states` și confirmă că sunt stocate corect.
|
||||
|
||||
Pasează `has_text_modality=False` pentru modelele exclusiv vizuale care nu au `vocab_size` și pasează `**kwargs` suplimentar ca să suprascrieți valorile implicite ale config-ului.
|
||||
|
||||
```py
|
||||
self.config_tester = ConfigTester(
|
||||
self, config_class=MyVisionConfig, has_text_modality=False, hidden_size=64
|
||||
)
|
||||
```
|
||||
|
||||
## Teste de integrare și modele mici
|
||||
|
||||
Testele bazate pe mixin-uri folosesc config-uri mici cu weights aleatorii ca să verifice rapid comportamentul modelului. Testele de integrare rulează inferența cu weights preantrenate reale ca să valideze corectitudinea ieșirii. Modelele mici de pe Hub sunt suficient de mici pentru CI rapid, dar structurate ca checkpoint-uri reale.
|
||||
|
||||
### Scrierea testelor de integrare
|
||||
|
||||
Pune testele de integrare într-o clasă de test separată și marcheaz-le cu `@slow`. Fiecare test descarcă weights reale, rulează inferența și verifică ieșirile față de valorile așteptate. Apelează `cleanup(torch_device, gc_collect=False)` în `setUp` și `tearDown` ca să eviți memory leaks.
|
||||
|
||||
```py
|
||||
import torch
|
||||
from transformers import AutoTokenizer
|
||||
from transformers.testing_utils import cleanup, require_torch, slow, torch_device
|
||||
|
||||
class MyModelIntegrationTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
cleanup(torch_device, gc_collect=False)
|
||||
|
||||
def tearDown(self):
|
||||
cleanup(torch_device, gc_collect=False)
|
||||
|
||||
@slow
|
||||
@require_torch
|
||||
def test_inference(self):
|
||||
model = MyModelForCausalLM.from_pretrained("myorg/mymodel-base").to(torch_device)
|
||||
tokenizer = AutoTokenizer.from_pretrained("myorg/mymodel-base")
|
||||
inputs = tokenizer("Hello, world", return_tensors="pt").to(torch_device)
|
||||
|
||||
with torch.no_grad():
|
||||
outputs = model(**inputs)
|
||||
|
||||
# verifică față de valorile așteptate
|
||||
expected_slice = torch.tensor([[-0.1234, 0.5678, -0.9012]])
|
||||
torch.testing.assert_close(outputs.logits[0, :1, :3], expected_slice, atol=1e-4, rtol=1e-4)
|
||||
```
|
||||
|
||||
Marchează orice test cu `@slow` dacă descarcă weights, încarcă un dataset mare sau durează mai mult de câteva secunde. [CI-ul pentru pull request](./pr_checks) sare peste testele slow, dar programul nightly le rulează.
|
||||
|
||||
#### Teste de integrare pentru generare
|
||||
|
||||
Folosește `do_sample=False` în testele de generare ca ieșirea să fie deterministă la rulări și hardware diferite. Pentru modelele Mixture-of-Experts, apelează și `model.set_experts_implementation("eager")` înainte de generare ca să forțezi o cale de dispatching stabilă a experților. Fără asta, diferențe numerice mici în router pot schimba ce expert gestionează un token și pot schimba ieșirea.
|
||||
|
||||
```py
|
||||
@slow
|
||||
@require_torch
|
||||
def test_generate(self):
|
||||
model = MyModelForCausalLM.from_pretrained("myorg/mymodel-base").to(torch_device)
|
||||
tokenizer = AutoTokenizer.from_pretrained("myorg/mymodel-base")
|
||||
inputs = tokenizer("Hello, world", return_tensors="pt").to(torch_device)
|
||||
|
||||
# model.set_experts_implementation("eager") # decomentează pentru modelele MoE
|
||||
generated_ids = model.generate(**inputs, max_new_tokens=20, do_sample=False)
|
||||
output = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)
|
||||
self.assertEqual(output, ["Hello, world! This is the expected continuation..."])
|
||||
```
|
||||
|
||||
#### Așteptări specifice hardware-ului
|
||||
|
||||
CI-ul Transformers rulează testele slow pe un NVIDIA A10. Rezultatele numerice pot varia ușor între generații de GPU, deci testele de integrare folosesc clasa [Expectations](https://github.com/huggingface/transformers/blob/main/src/transformers/testing_utils.py#L3247) ca să înregistreze valori așteptate per dispozitiv. `Expectations` alege cea mai bună potrivire pentru hardware-ul curent pe baza cheilor SM `(device_type, (major, minor))` și revine la un default când nu se potrivește nimic.
|
||||
|
||||
Rulează `torch.cuda.get_device_capability()` ca să printezi versiunea SM locală (e.g. `(8, 6)` pentru A10, `(9, 0)` pentru H100).
|
||||
|
||||
```py
|
||||
from transformers.testing_utils import Expectations
|
||||
|
||||
expected_texts = Expectations(
|
||||
{
|
||||
("cuda", (8, 6)): ["Hello, world! This is the A10 continuation..."],
|
||||
("cuda", (9, 0)): ["Hello, world! This is the H100 continuation..."],
|
||||
}
|
||||
).get_expectation()
|
||||
|
||||
self.assertEqual(output, expected_texts)
|
||||
```
|
||||
|
||||
### Crearea modelelor mici
|
||||
|
||||
Modelele mici cu weights aleatorii trăiesc pe Hub sub organizația [hf-internal-testing](https://huggingface.co/hf-internal-testing). Testele de pipeline se bazează pe modele mici când au nevoie de un checkpoint găzduit pe Hub, dar nu le pasă de calitatea ieșirii. Testele fast smoke încarcă și ele modele mici ca să verifice formele forward pass-ului fără să descarce checkpoint-uri mari.
|
||||
|
||||
Modelele mici sunt ultimul resort pentru testele de integrare. Folosește-le doar când cel mai mic checkpoint disponibil depășește ~24 GB de VRAM. Folosește weights preantrenate originale când e posibil, ca să prinzi regresii numerice reale.
|
||||
|
||||
Scriptul `utils/create_dummy_models.py` generează modele mici din `ModelTester.get_config()`. Scriptul extrage hyperparametri mici din tester-ul tău, construiește un model cu weights aleatorii și încarcă rezultatul pe Hub.
|
||||
|
||||
Generează modele mici local.
|
||||
|
||||
```bash
|
||||
python utils/create_dummy_models.py output_dir -m your_model_type
|
||||
```
|
||||
|
||||
Încarcă-le pe Hub.
|
||||
|
||||
```bash
|
||||
python utils/create_dummy_models.py output_dir -m your_model_type --upload --organization hf-internal-testing
|
||||
```
|
||||
|
||||
Fiecare model folosește numele `hf-internal-testing/tiny-random-{ModelClassName}` și este înregistrat în `tests/utils/tiny_model_summary.json`. Un workflow CI (`.github/workflows/check_tiny_models.yml`) regenerează modelele mici zilnic.
|
||||
|
||||
## Controlează ce se testează
|
||||
|
||||
Flag-urile booleene pe `ModelTesterMixin` comută testele auto-generate. Suprascrie orice flag pe clasa ta de test ca să activezi sau dezactivezi verificări specifice.
|
||||
|
||||
```py
|
||||
class MyModelTest(CausalLMModelTest, unittest.TestCase):
|
||||
model_tester_class = MyModelTester
|
||||
test_resize_embeddings = False
|
||||
test_all_params_have_gradient = False # când nu toți parametrii sunt activați în fiecare forward pass
|
||||
```
|
||||
|
||||
| Flag | Implicit | Ce controlează |
|
||||
|---|---|---|
|
||||
| `test_resize_embeddings` | `True` | Redimensionarea layer-ului de embedding |
|
||||
| `test_resize_position_embeddings` | `False` | Redimensionarea embedding-urilor de poziție |
|
||||
| `test_mismatched_shapes` | `True` | Gestionarea formelor nepotrivite input/output |
|
||||
| `test_missing_keys` | `True` | Avertismente pentru chei lipsă la încărcare |
|
||||
| `test_torch_exportable` | `True` | Compatibilitate `torch.export` |
|
||||
| `test_all_params_have_gradient` | `True` | Toți parametrii primesc gradienți (setează `False` când nu toți parametrii sunt activați în fiecare forward pass, cum ar fi experții MoE) |
|
||||
| `is_encoder_decoder` | `False` | Teste specifice encoder-decoder |
|
||||
| `has_attentions` | `True` | Teste de ieșire attention |
|
||||
| `_is_composite` | `False` | Gestionarea modelelor compuse/multimodale |
|
||||
| `model_split_percents` | `[0.5, 0.7, 0.9]` | Procentaje de split pentru testele de model parallelism |
|
||||
|
||||
## Pașii următori
|
||||
|
||||
- Răsfoiește documentația [pytest](https://docs.pytest.org/en/latest/getting-started.html) pentru mai mult despre selecția testelor, fixtures, logging și altele.
|
||||
159
docs/source/ro/tokenizer_summary.md
Normal file
159
docs/source/ro/tokenizer_summary.md
Normal file
@@ -0,0 +1,159 @@
|
||||
<!--Copyright 2020 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Algoritmi de tokenization
|
||||
|
||||
<Youtube id="zHvTiHr506c"/>
|
||||
|
||||
Transformers suportă trei algoritmi de tokenizare la nivel de subword: Byte pair encoding (BPE), Unigram și WordPiece. Aceștia împart textul în unități între cuvinte și caractere, menținând vocabularul compact, captând în același timp bucăți cu sens. Cuvintele comune rămân intacte ca token-uri unice, iar cuvintele rare sau necunoscute se descompun în subwords.
|
||||
|
||||
De exemplu, `annoyingly` ar putea fi împărțit în `["annoying", "ly"]` sau `["annoy", "ing", "ly"]` în funcție de vocabular. Împărțirea în subwords permite modelului să reprezinte cuvinte nevăzute din subwords cunoscute.
|
||||
|
||||
> [!TIP]
|
||||
> Tokenizarea la nivel de subword este deosebit de utilă pentru limbi ca turca, unde poți forma cuvinte lungi și complexe înlănțuind subword-uri.
|
||||
|
||||
## Byte pair encoding (BPE)
|
||||
|
||||
<Youtube id="HEikzVL-lZU"/>
|
||||
|
||||
[Byte pair encoding](https://huggingface.co/papers/1508.07909) (BPE) este cel mai popular algoritm de tokenizare din Transformers, folosit de modele ca [Llama], [Gemma], [Qwen2] și altele.
|
||||
|
||||
1. Un pre-tokenizator împarte textul pe spații sau alte reguli, producând un set de cuvinte unice și frecvențele lor.
|
||||
|
||||
```text
|
||||
("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)
|
||||
```
|
||||
|
||||
2. Algoritmul BPE creează un vocabular de bază, `["b", "g", "h", "n", "p", "s", "u"]`, din toate caracterele.
|
||||
|
||||
```text
|
||||
("h" "u" "g", 10), ("p" "u" "g", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "u" "g" "s", 5)
|
||||
```
|
||||
|
||||
3. BPE pornește cu caractere individuale și îmbină iterativ perechea adiacentă cea mai frecventă. `"u"` și `"g"` apar împreună cel mai des în `"hug"`, `"pug"` și `"hugs"`, deci BPE le îmbină în `"ug"` și îl adaugă în vocabular.
|
||||
|
||||
```text
|
||||
("h" "ug", 10), ("p" "ug", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "ug" "s", 5)
|
||||
```
|
||||
|
||||
4. Următoarea pereche cea mai comună este `"u"` și `"n"`, care apar în `"pun"` și `"bun"`, deci se îmbină în `"un"`.
|
||||
|
||||
```text
|
||||
("h" "ug", 10), ("p" "ug", 5), ("p" "un", 12), ("b" "un", 4), ("h" "ug" "s", 5)
|
||||
```
|
||||
|
||||
5. Vocabularul este acum `["b", "g", "h", "n", "p", "s", "u", "ug", "un"]`. BPE continuă să învețe reguli de îmbinare până atinge dimensiunea țintă a vocabularului, egală cu dimensiunea vocabularului de bază plus numărul de embeddings. [GPT] folosește BPE cu un vocabular de 40.478 (478 token-uri de bază + 40.000 embeddings).
|
||||
|
||||
Orice caracter care nu se află în vocabularul de bază se mapează la un token necunoscut ca `"<unk>"`. În practică, vocabularul de bază acoperă toate caracterele văzute în antrenare, deci token-urile necunoscute sunt rare.
|
||||
|
||||
### BPE la nivel de byte
|
||||
|
||||
Includerea tuturor caracterelor Unicode ar face vocabularul de bază enorm. BPE la nivel de byte folosește în schimb 256 de valori de byte ca vocabular de bază, asigurând că orice cuvânt poate fi tokenizat fără token-ul `"<unk>"`. [GPT-2] folosește BPE la nivel de byte cu un vocabular de 50.257 (256 token-uri de byte + 50.000 embeddings + un token special de sfârșit de text).
|
||||
|
||||
## Unigram
|
||||
|
||||
<Youtube id="TGZfZVuF9Yc"/>
|
||||
|
||||
[Unigram](https://huggingface.co/papers/1804.10959) este al doilea algoritm de tokenizare ca popularitate din Transformers, folosit de modele precum [T5], [BigBird], [Pegasus] și altele.
|
||||
|
||||
1. Unigram pornește cu un set mare de subword-uri candidate, iar fiecare candidat primește un scor de probabilitate bazat pe frecvența sa.
|
||||
|
||||
```text
|
||||
("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)
|
||||
["b", "g", "h", "n", "p", "s", "u", "hu", "ug", "un", "pu", "bu", "gs", "hug", "pug", "pun", "bun", "ugs", "hugs"]
|
||||
```
|
||||
|
||||
2. Unigram evaluează cât de bine tokenizează vocabularul curent datele de antrenare la fiecare pas.
|
||||
3. Pentru fiecare token, Unigram măsoară cât de mult ar crește pierderea globală dacă token-ul ar fi eliminat. De exemplu, eliminarea `"pu"` afectează puțin pierderea pentru că `"pug"` și `"pun"` pot fi tokenizate în continuare ca `["p", "ug"]` și `["p", "un"]`.
|
||||
|
||||
Dar eliminarea `"ug"` ar crește semnificativ pierderea pentru că `"hug"`, `"pug"` și `"hugs"` depind toate de el.
|
||||
|
||||
4. Unigram elimină token-urile cu cea mai mică creștere a pierderii, de obicei primele 10-20% de jos. Caracterele de bază rămân mereu ca orice cuvânt să poată fi tokenizat. Token-uri ca `"bu"`, `"pu"`, `"gs"`, `"pug"` și `"bun"` sunt eliminate pentru că au contribuit cel mai puțin la probabilitatea globală.
|
||||
|
||||
```text
|
||||
["b", "g", "h", "n", "p", "s", "u", "hu", "ug", "un", "hug", "pun", "ugs", "hugs"]
|
||||
```
|
||||
|
||||
5. Pașii 2-4 se repetă până vocabularul atinge dimensiunea țintă.
|
||||
|
||||
În inferență, Unigram poate tokeniza un cuvânt în mai multe moduri. `"hugs"` ar putea deveni `["hug", "s"]`, `["h", "ug", "s"]` sau `["h", "u", "g", "s"]`. Unigram alege tokenizarea cu cea mai mare probabilitate. Spre deosebire de BPE, care este determinist și bazat pe reguli de îmbinare, Unigram este probabilistic și poate eșantiona tokenizări diferite în antrenare.
|
||||
|
||||
## SentencePiece
|
||||
|
||||
[SentencePiece](https://huggingface.co/papers/1808.06226) este o bibliotecă de tokenizare care aplică BPE sau Unigram direct pe text brut. BPE și Unigram standard presupun că spațiile separă cuvintele, ceea ce nu funcționează pentru limbi ca chineza și japoneza care nu folosesc spații.
|
||||
|
||||
1. SentencePiece tratează textul de intrare ca un flux brut de bytes sau caractere și include caracterul spațiu, reprezentat ca `"▁"`, în vocabular.
|
||||
|
||||
```text
|
||||
("▁hug", 10), ("▁pug", 5), ("▁pun", 12), ("▁bun", 4), ("▁hugs", 5)
|
||||
```
|
||||
|
||||
2. SentencePiece aplică apoi BPE sau Unigram pe text.
|
||||
|
||||
La decodare, SentencePiece concatenează toate token-urile și înlocuiește `"▁"` cu un spațiu.
|
||||
|
||||
## WordPiece
|
||||
|
||||
<Youtube id="qpv6ms_t_1A"/>
|
||||
|
||||
[WordPiece](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37842.pdf) este algoritmul de tokenizare pentru modelele din familia BERT, cum ar fi [DistilBERT] și [Electra].
|
||||
|
||||
Este similar cu [BPE](#byte-pair-encoding-bpe) și îmbină iterativ perechi de jos în sus, dar diferă în modul în care selectează perechile.
|
||||
|
||||
```text
|
||||
("h" "u" "g", 10), ("p" "u" "g", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "u" "g" "s", 5)
|
||||
```
|
||||
|
||||
WordPiece îmbină perechile care maximizează probabilitatea datelor de antrenare.
|
||||
|
||||
```text
|
||||
score("u", "g") = frequency("ug") / (frequency("u") × frequency("g"))
|
||||
```
|
||||
|
||||
| pereche | frecvență | scor |
|
||||
|---|---|---|
|
||||
| `"u"` + `"g"` | 20 | 20 / (36 × 20) = 0.028 |
|
||||
| `"u"` + `"n"` | 16 | 16 / (36 × 16) = 0.028 |
|
||||
| `"h"` + `"u"` | 15 | 15 / (15 × 36) = 0.028 |
|
||||
| `"g"` + `"s"` | 5 | 5 / (20 × 5) = 0.050 |
|
||||
|
||||
Scorul favorizează îmbinarea `"g"` și `"s"` unde token-ul combinat apare mai des decât s-ar aștepta din frecvențele individuale ale token-urilor. BPE îmbină pur și simplu perechea care apare cel mai des. WordPiece măsoară cât de *informativă* este fiecare îmbinare. Două token-uri care apar împreună mult mai des decât prevede probabilitatea sunt îmbinate primele.
|
||||
|
||||
## Tokenization la nivel de cuvânt
|
||||
|
||||
<Youtube id="nhJxYji1aho"/>
|
||||
|
||||
Tokenization-ul la nivel de cuvânt împarte textul în token-uri după spații, punctuație sau reguli specifice limbii.
|
||||
|
||||
```text
|
||||
["Do", "n't", "you", "love", "🤗", "Transformers", "?", "We", "sure", "do", "."]
|
||||
```
|
||||
|
||||
Dimensiunea vocabularului devine extrem de mare pentru că fiecare cuvânt unic necesită propriul token, inclusiv toate variantele (`"love"`, `"loving"`, `"loved"`, `"lovingly"`). Matricea de embeddings rezultată este enormă, crescând memoria și consumul de calcul. Cuvintele care nu se află în vocabular se mapează la un token `"<unk>"`, deci modelul nu poate gestiona cuvinte noi.
|
||||
|
||||
## Tokenization la nivel de caracter
|
||||
|
||||
Tokenization-ul la nivel de caracter împarte textul în caractere individuale.
|
||||
|
||||
```text
|
||||
["D", "o", "n", "'", "t", "y", "o", "u", "l", "o", "v", "e"]
|
||||
```
|
||||
|
||||
Vocabularul este mic și orice cuvânt poate fi reprezentat, deci nu există problema `"<unk>"`. Dar secvențele devin mult mai lungi. Un caracter ca `"l"` poartă mult mai puțin sens decât `"love"`, deci performanța scade.
|
||||
|
||||
## Resurse
|
||||
|
||||
- [Capitolul 6](https://huggingface.co/learn/llm-course/chapter6/1) din cursul LLM te învață cum să antrenezi un tokenizer de la zero și explică diferențele dintre algoritmii BPE, Unigram și WordPiece.
|
||||
48
docs/source/ro/video_processors.md
Normal file
48
docs/source/ro/video_processors.md
Normal file
@@ -0,0 +1,48 @@
|
||||
<!--Copyright 2025 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Procesatoare video
|
||||
|
||||
Un **procesator video** este un utilitar responsabil cu pregătirea feature-urilor de input pentru modelele video, cât și cu post-procesarea output-urilor lor. Furnizează transformări precum redimensionarea, normalizarea și conversia în PyTorch.
|
||||
|
||||
Procesatorul video extinde funcționalitatea procesatoarelor de imagini, permițând modelelor să gestioneze videoclipuri cu un set distinct de argumente față de imagini. Servește drept punte între datele video brute și model, asigurând că feature-urile de input sunt optimizate pentru VLM.
|
||||
|
||||
Folosește [`~BaseVideoProcessor.from_pretrained`] ca să încarci configurația unui procesator video (dimensiunea imaginii, dacă să normalizeze și rescaleze etc.) de la un model video de pe Hub-ul Hugging Face sau dintr-un director local. Configurația pentru fiecare model preantrenat ar trebui salvată într-un fișier [video_preprocessor_config.json], dar modelele mai vechi pot avea configurația salvată în fișierul [preprocessor_config.json](https://huggingface.co/llava-hf/llava-onevision-qwen2-0.5b-ov-hf/blob/main/preprocessor_config.json). Reține că acesta din urmă este mai puțin preferat și va fi eliminat în viitor.
|
||||
|
||||
## Exemplu de utilizare
|
||||
|
||||
Iată un exemplu de cum să încarci un procesator video cu modelul [`llava-hf/llava-onevision-qwen2-0.5b-ov-hf`](https://huggingface.co/llava-hf/llava-onevision-qwen2-0.5b-ov-hf):
|
||||
|
||||
```python
|
||||
from transformers import AutoVideoProcessor
|
||||
|
||||
processor = AutoVideoProcessor.from_pretrained("llava-hf/llava-onevision-qwen2-0.5b-ov-hf")
|
||||
```
|
||||
|
||||
Dacă folosești un procesator de imagini de bază pentru videoclipuri, acesta procesează datele video tratând fiecare cadru ca o imagine individuală și aplică transformările cadru cu cadru. Deși funcțională, această abordare nu este foarte eficientă. Folosind `AutoVideoProcessor` poți să profiți de **procesatoarele video rapide**, care valorifică biblioteca [torchvision](https://pytorch.org/vision/stable/index.html). Procesatoarele rapide gestionează întregul batch de videoclipuri dintr-o dată, fără să itereze pe fiecare video sau cadru. Aceste actualizări introduc accelerarea GPU și cresc semnificativ viteza de procesare, mai ales pentru task-uri care necesită un throughput ridicat.
|
||||
|
||||
Procesatoarele video rapide sunt disponibile pentru toate modelele și sunt încărcate implicit când se inițializează un `AutoVideoProcessor`. Când folosești un procesator video rapid, poți seta și argumentul `device` ca să specifici device-ul pe care se face procesarea. Implicit, procesarea se face pe același device ca input-urile dacă input-urile sunt tensori, altfel pe CPU. Ca să câștigi și mai multă viteză, poți compila procesatorul când folosești `cuda` ca device.
|
||||
|
||||
```python
|
||||
import torch
|
||||
from transformers.video_utils import load_video
|
||||
from transformers import AutoVideoProcessor
|
||||
|
||||
video = load_video("video.mp4")
|
||||
processor = AutoVideoProcessor.from_pretrained("llava-hf/llava-onevision-qwen2-0.5b-ov-hf", device="cuda")
|
||||
processor = torch.compile(processor)
|
||||
processed_video = processor(video, return_tensors="pt")
|
||||
```
|
||||
697
docs/source/ro/weightconverter.md
Normal file
697
docs/source/ro/weightconverter.md
Normal file
@@ -0,0 +1,697 @@
|
||||
<!--Copyright 2025 The HuggingFace Team. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
|
||||
⚠️ Note that this file is in Markdown but contain specific syntax for our doc-builder (similar to MDX) that may not be
|
||||
rendered properly in your Markdown viewer.
|
||||
|
||||
-->
|
||||
|
||||
# Încărcarea dinamică de weights
|
||||
|
||||
Checkpoint-urile sunt des serializate într-un format diferit de cel pe care un model îl așteaptă la rulare. Scenariile comune includ:
|
||||
|
||||
1. **Weights fuzionate**: Checkpoint-urile stochează weights separate `gate_proj` și `up_proj`, dar modelul utilizează un weight fuzionat `gate_up_proj` pentru eficiență.
|
||||
2. **Consolidare expertă MoE**: Weights experte individuale (`experts.0.weight`, `experts.1.weight`, ...) trebuie să fie combinate într-un singur tensor 3D.
|
||||
3. **Denumire veche**: Checkpoint-urile vechi utilizează diferite convenții de numire (e.g., `LayerNorm.gamma` vs `LayerNorm.weight`).
|
||||
4. **Modele compuse**: Un model lingvistic vizual conține două sub-module `PreTrainedModel`, fiecare cu propria convenție pentru checkpoint-uri.
|
||||
5. **Quantization**: Weights ar putea fi stocate în formate quantized care necesită deserializare.
|
||||
|
||||
Încărcarea dinamică de weights rezolvă această problemă prin aplicarea de operații planificate și reversibile asupra tensorilor din checkpoint pe măsură ce sunt încărcați. Transformers expune aceasta prin [`WeightConverter`] și [`WeightRenaming`], care descriu cum una sau mai multe chei de checkpoint se mapează la unul sau mai mulți parametri ai modelului și ce [`ConversionOps`] compozabile ar trebui să ruleze pe tensorii potriviți. Această abordare se adaptează la noi layout-uri de weights, suportă mixture-of-experts (MoE) quantized și se integrează cu tensor parallelism.
|
||||
|
||||
Acest ghid demonstrează cum să utilizezi [`WeightConverter`] pentru a converti tensori. Mapările de conversie se află în [`conversion_mapping.py`](https://github.com/huggingface/transformers/blob/main/src/transformers/conversion_mapping.py); o mapare înregistrată este indexată fie printr-un string `model_type` (e.g. `"mixtral"`) fie printr-un nume de clasă (e.g. `"LlavaModel"`).
|
||||
|
||||
## Pipeline-ul complet de încărcare
|
||||
|
||||
Toate modelele trec prin sistemul de încărcare dinamică de weights. Maparea de conversie este un **pas opțional în cadrul acelui sistem** care se activează doar atunci când modelul are înregistrări pentru numele clasei sale sau `model_type`.
|
||||
|
||||
```
|
||||
Fișier Checkpoint → from_pretrained() → convert_and_load_state_dict_in_model()
|
||||
↓
|
||||
┌───────────────────────────────────────────────────────────┐
|
||||
│ Pentru fiecare weight din checkpoint: │
|
||||
│ 1. Potrivește cheia sursă redenumită/procesată cu │
|
||||
│ parametrul modelului │
|
||||
│ 2. Fragmentează weight-ul și trimite pe dispozitiv │
|
||||
│ (asincron) │
|
||||
│ 3. Colectează tensorii cu același source_pattern │
|
||||
│ împreună (e.g. experți MoE, gate_up_proj) │
|
||||
│ 4. Aplică dequantization/deserializarea (dacă pre-quant) │
|
||||
│ 5. Aplică conversia (dacă este definită) │
|
||||
│ 6. Aplică quantizarea (dacă activată și pasul 4 nu │
|
||||
│ a fost folosit) │
|
||||
│ 7. Setează parametrul pe model │
|
||||
└───────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
| Pas | Când se activează |
|
||||
|-----|-------------------|
|
||||
| Încărcare dinamică | Întotdeauna, pentru toate modelele |
|
||||
| Mapare de conversie | Doar când clasa modelului sau `model_type` este înregistrată în `_MODEL_TO_CONVERSION_PATTERN` |
|
||||
| Sharding TP | Doar când `tp_plan="auto"` și modelul are `base_model_tp_plan` |
|
||||
| Dequantization/deserializare | Doar la încărcarea unui checkpoint pre-quantized |
|
||||
| Quantization | Doar când există o configurație de quantization și weights nu sunt pre-quantized |
|
||||
|
||||
### Modele dense (e.g., Llama)
|
||||
|
||||
Pentru majoritatea modelelor dense, formatul checkpoint-ului corespunde direct formatului modelului, așadar nu este necesară nicio mapare de conversie. Unele modele pot necesita, totuși, redenumire (e.g., convenții de numire vechi). Sharding-ul TP se aplică în continuare când este activat.
|
||||
|
||||
```
|
||||
Checkpoint: Model:
|
||||
model.layers.0.self_attn.q_proj.weight → model.layers.0.self_attn.q_proj.weight
|
||||
model.layers.0.self_attn.k_proj.weight → model.layers.0.self_attn.k_proj.weight
|
||||
model.layers.0.mlp.gate_proj.weight → model.layers.0.mlp.gate_proj.weight
|
||||
model.layers.0.mlp.up_proj.weight → model.layers.0.mlp.up_proj.weight
|
||||
model.layers.0.mlp.down_proj.weight → model.layers.0.mlp.down_proj.weight
|
||||
```
|
||||
|
||||
Checkpoint-urile vechi pot folosi convenții de numire mai vechi care sunt gestionate de redenumiri integrate aplicate tuturor modelelor:
|
||||
|
||||
```
|
||||
Checkpoint: Model:
|
||||
LayerNorm.gamma → LayerNorm.weight
|
||||
LayerNorm.beta → LayerNorm.bias
|
||||
```
|
||||
|
||||
### Modele MoE (e.g., Mixtral)
|
||||
|
||||
Pentru modelele MoE, formatul checkpoint-ului diferă de formatul modelului. Maparea de conversie transformă weights separate ale experților în tensori 3D fuzionați, iar sharding-ul TP se aplică după conversie.
|
||||
|
||||
```
|
||||
Checkpoint: Model:
|
||||
experts.0.w1.weight ─┐
|
||||
experts.1.w1.weight │ MergeModulelist
|
||||
... ├───────────────→ experts.gate_up_proj (8, hidden, 2*intermediate)
|
||||
experts.0.w3.weight │ + Concatenate
|
||||
experts.1.w3.weight ─┘
|
||||
```
|
||||
|
||||
### Modele compuse (e.g., viziune-limbaj)
|
||||
|
||||
Un `PreTrainedModel` poate conține alte sub-module `PreTrainedModel`. Fiecare sub-model poate avea propria sa mapare de conversie, înregistrată fie împotriva numelui clasei sale, fie împotriva `model_type`-ului. Când modelul părinte este încărcat, [`get_model_conversion_mapping`] parcurge sub-modelele în ordine depth-first, colectează mapările lor și **aplică automat scope-ul** fiecărei transformări la calea sub-modulului său prin `scope_prefix`.
|
||||
|
||||
```
|
||||
Model compus: Mapări per-submodel (auto-scoped):
|
||||
LlavaForConditionalGeneration
|
||||
├── vision_model: SiglipVisionModel → mapare SiglipVisionModel (scope="vision_model")
|
||||
└── language_model: LlamaForCausalLM → mapare LlamaForCausalLM (scope="language_model")
|
||||
```
|
||||
|
||||
`scope_prefix` este calea punctată a sub-modulului (`"vision_model"`, `"language_model.model"`, etc.). O transformare cu scope se declanșează doar pentru cheile care încep cu `f"{scope_prefix}."`; prefixul este eliminat înainte de potrivirea pattern-ului și re-atașat după substituire, astfel că maparea fiecărui sub-model este scrisă *relativ la sub-model*, exact ca și cum ar fi root-ul.
|
||||
|
||||
## Arhitectură
|
||||
|
||||
Sistemul este construit în jurul mai multor componente cheie definite în [`core_model_loading.py`](https://github.com/huggingface/transformers/blob/main/src/transformers/core_model_loading.py):
|
||||
|
||||
**Faza 1 — Procesare per-cheie** (iterează peste cheile checkpoint-ului):
|
||||
|
||||
1. **Parcurge lista de transformări** o singură dată. Fiecare [`WeightRenaming`] care se potrivește se declanșează (e.g. `block_sparse_moe` → `mlp`), iar **cel mult un** [`WeightConverter`] poate revendica cheia (e.g. `experts.*.w1.weight`).
|
||||
2. **Sharding (TP) și trimite pe dispozitiv** asincron prin `ThreadPoolExecutor`.
|
||||
3. **Colectează** tensorii cu același `source_pattern` împreună (e.g. toate weights ale experților MoE, proiecțiile gate + up).
|
||||
|
||||
**Faza 2 — Procesare per-mapare** (iterează peste mapările colectate):
|
||||
|
||||
1. **Dequantization/deserializare** (doar pentru checkpoint-uri pre-quantized).
|
||||
2. **Aplică lanțul [`ConversionOps`]**: `Chunk`, `Concatenate`, `MergeModulelist`, `Transpose`, etc.
|
||||
3. **Quantization** din mers (dacă nu este pre-quantized).
|
||||
4. **Setează parametrul** pe model.
|
||||
|
||||
### WeightTransform
|
||||
|
||||
Clasa de bază care gestionează potrivirea pattern-urilor și colectarea tensorilor:
|
||||
|
||||
- **Compilarea pattern-urilor**: Pattern-urile sursă sunt expresii regulate complete potrivite cu `re.search()`. Wildcardul `*` potrivește orice componentă indexabilă și grupează toate potrivirile împreună pentru operații batch.
|
||||
- **Grupuri captante și referințe inverse**: Grupurile captante din pattern-urile sursă pot fi referențiate ca `\1`, `\2`, ... în pattern-urile țintă pentru a păstra subșiruri (e.g. indici de straturi) în cadrul redenumirilor.
|
||||
- **Scoping**: `scope_prefix` (setat automat per sub-model de [`get_model_conversion_mapping`]) restricționează transformarea la cheile de sub acea cale. Prefixul este eliminat înainte de potrivire și re-atașat după substituire.
|
||||
- **Redenumirea cheilor**: `rename_source_key()` aplică regex-ul (cu gestionare de scope) și returnează `(renamed_key, source_pattern)` astfel că loader-ul știe care convertor, dacă există, a revendicat cheia.
|
||||
- **Colectarea tensorilor**: `add_tensor()` acumulează tensorii rezolvați (sau `Future`-uri) sub `source_pattern`-ul lor astfel că toți tensorii necesari pentru o singură conversie (e.g. toate weights ale experților MoE) sunt grupați împreună înainte de rularea lanțului de operații.
|
||||
- **Reversibilitate**: `reverse_transform()` inversează pattern-urile sursă ↔ țintă și inversează fiecare operație, astfel că aceeași listă inversată gestionează salvarea.
|
||||
- **Urmărire**: `was_used()` raportează dacă transformarea a potrivit efectiv vreo cheie la încărcare; aceasta este necesară pentru ca redenumirile non-bijective (e.g. [`PrefixChange`] adăugând un prefix care poate fi deja prezent) să poată fi re-aplicate simetric la salvare.
|
||||
|
||||
### WeightRenaming
|
||||
|
||||
[`WeightRenaming`] este un [`WeightTransform`] specializat pentru redenumiri pure de chei fără operații asupra tensorilor. Spre deosebire de [`WeightConverter`], un `WeightRenaming` nu **revendică** cheia, astfel că mai multe redenumiri pot fi înlănțuite liber. Pe calea de încărcare, toate redenumirile rulează înainte de convertor; pe calea de salvare (lista inversată), toate redenumirile inversate rulează după convertorul inversat — a se vedea regula de ordonare de mai sus.
|
||||
|
||||
```py
|
||||
# Compatibilitate cu checkpoint-uri vechi
|
||||
WeightRenaming("LayerNorm.gamma", "LayerNorm.weight")
|
||||
|
||||
# Modificări ale path-ului modulului
|
||||
WeightRenaming(".block_sparse_moe.", ".mlp.")
|
||||
```
|
||||
|
||||
[`PrefixChange`] este un wrapper de nivel înalt în jurul [`WeightRenaming`] pentru cazul comun de eliminare sau adăugare a unei întregi componente de cale. Opționalul `model_prefix` aplică scope-ul operației la cheile din acel namespace:
|
||||
|
||||
```py
|
||||
# "model.layers.bad_prefix.weight" → "model.layers.weight"
|
||||
PrefixChange(prefix_to_remove="bad_prefix", model_prefix="model.layers")
|
||||
# "layers.0.weight" → "model.layers.0.weight"
|
||||
PrefixChange(prefix_to_add="model")
|
||||
```
|
||||
|
||||
### WeightConverter
|
||||
|
||||
[`WeightConverter`] extinde [`WeightTransform`] cu un lanț de [`ConversionOps`] care acționează asupra tensorilor colectați. Cele patru cardinalități suportate sunt:
|
||||
|
||||
| Cardinalitate | Pattern-uri sursă | Pattern-uri țintă | Operație tipică |
|
||||
|---------------|-------------------|-------------------|-----------------|
|
||||
| unu-la-unu | 1 | 1 | [`Transpose`], [`PermuteForRope`] |
|
||||
| unu-la-mulți | 1 | >1 | [`Chunk`] (e.g. despachetare `qkv_proj`) |
|
||||
| mulți-la-unu | >1 | 1 | [`Concatenate`], [`MergeModulelist`] (e.g. fuzionarea experților) |
|
||||
| mulți-la-mulți | >1 | >1 | doar cu operații care îl suportă explicit (e.g. `ErnieFuseAndSplitTextVisionExperts`) |
|
||||
|
||||
```python
|
||||
WeightConverter(
|
||||
source_patterns=[".experts.*.w1.weight", ".experts.*.w3.weight"],
|
||||
target_patterns=".experts.gate_up_proj",
|
||||
operations=[MergeModulelist(dim=0), Concatenate(dim=1)],
|
||||
)
|
||||
```
|
||||
|
||||
Un `WeightConverter` este de asemenea reversibil: `reverse_transform()` inversează sursă ↔ țintă și înlocuiește fiecare operație cu `reverse_op`-ul său, astfel că o mapare de conversie înregistrată este bidirecțională prin construcție (încărcarea folosește lista ca atare, salvarea o folosește inversată).
|
||||
|
||||
### Ordonarea redenumirilor și convertoarelor
|
||||
|
||||
Listează intrările `WeightRenaming` înaintea intrărilor `WeightConverter` și menține frunzele lor disjuncte: redenumirile normalizează cheile pe care le consumă convertoarele, dar nu țintesc niciodată o frunză pe care un convertor o produce. Calea de salvare se bazează pe aceasta pentru a inversa maparea în două faze (convertoare inverse, apoi redenumiri inverse).
|
||||
|
||||
Lista de transformări este parcursă în ordine, o singură dată per cheie de checkpoint. Pentru fiecare cheie:
|
||||
|
||||
- Fiecare `WeightRenaming` care se potrivește se declanșează; mai multe redenumiri pot fi înlănțuite.
|
||||
- Primul `WeightConverter` care se potrivește **revendică** cheia. Convertoarele ulterioare sunt omise — aceasta garantează că tensorul este direcționat către un singur convertor pentru pasul de merge/split și este motivul pentru care două convertoare cu intenție suprapusă ar reprezenta o configurare greșită.
|
||||
|
||||
```python
|
||||
weight_mapping = [
|
||||
WeightRenaming("^old_prefix", "encoder"), # redenumirea rulează mereu
|
||||
WeightConverter( # convertorul revendică cheia
|
||||
"attn.qkv_proj.weight",
|
||||
["attn.q_proj.weight", "attn.k_proj.weight", "attn.v_proj.weight"],
|
||||
operations=[Chunk(dim=0)],
|
||||
),
|
||||
]
|
||||
# Încărcare: "old_prefix.attn.qkv_proj.weight"
|
||||
# → WeightRenaming → "encoder.attn.qkv_proj.weight"
|
||||
# → WeightConverter → "encoder.attn.{q,k,v}_proj.weight"
|
||||
#
|
||||
# Salvare: lista inversată, fiecare transformare inversată:
|
||||
# → rev(WeightConverter) reîmpachetează QKV → "encoder.attn.qkv_proj.weight"
|
||||
# → rev(WeightRenaming) corectează prefixul → "old_prefix.attn.qkv_proj.weight"
|
||||
```
|
||||
|
||||
## Operații de conversie
|
||||
|
||||
Clasa [`WeightConverter`] are mai multe operații care sunt executate când este apelat [`~PreTrainedModel.from_pretrained`] pentru transformarea tensorilor sursă din checkpoint în tensorii țintă ai modelului.
|
||||
|
||||
Operațiile sunt complet reversibile. Salvarea inversează conversiile și returnează checkpoint-ul original, astfel că poți lucra ușor cu diferite framework-uri.
|
||||
|
||||
| Operație | Inversă |
|
||||
|----------|---------|
|
||||
| [`Chunk(dim)`] | [`Concatenate(dim)`] |
|
||||
| [`Concatenate(dim)`] | [`Chunk(dim)`] |
|
||||
| [`MergeModulelist(dim)`] | [`SplitModulelist(dim)`] |
|
||||
| [`SplitModulelist(dim)`] | [`MergeModulelist(dim)`] |
|
||||
| [`Transpose(d0, d1)`] | [`Transpose(d1, d0)`] |
|
||||
| [`PermuteForRope()`] | [`PermuteForRope()`] |
|
||||
| [`Conv3dToLinear(...)`] | [`LinearToConv3d(...)`] |
|
||||
|
||||
### Chunk
|
||||
|
||||
Operația [`Chunk`] împarte un tensor în părți egale de-a lungul unei dimensiuni. De exemplu, dacă un model se așteaptă ca Q, K și V să fie trei tensori separați în loc de un singur tensor.
|
||||
|
||||
```py
|
||||
WeightConverter(
|
||||
"self_attn.qkv_proj",
|
||||
["self_attn.q_proj", "self_attn.k_proj", "self_attn.v_proj"],
|
||||
operations=[Chunk(dim=0)],
|
||||
)
|
||||
```
|
||||
|
||||
### Concatenate
|
||||
|
||||
Operația [`Concatenate`] fuzionează tensori separați într-un singur tensor. De exemplu, dacă un model se așteaptă ca Q, K și V să fie un singur tensor în loc de tensori separați.
|
||||
|
||||
```py
|
||||
WeightConverter(
|
||||
["self_attn.q_proj", "self_attn.k_proj", "self_attn.v_proj"],
|
||||
"self_attn.qkv_proj",
|
||||
operations=[Concatenate(dim=0)],
|
||||
)
|
||||
```
|
||||
|
||||
### MergeModulelist
|
||||
|
||||
[`MergeModulelist`] îmbină o listă de tensori 2D într-un singur tensor 3D. De exemplu, poți compune [`MergeModulelist`] cu [`Concatenate`] pentru a stiva experții dintr-un MoE și a-i împacheta într-un singur tensor.
|
||||
|
||||
```py
|
||||
WeightConverter(
|
||||
["block_sparse_moe.experts.*.w1.weight", "block_sparse_moe.experts.*.w3.weight"],
|
||||
"mlp.experts.gate_up_proj",
|
||||
operations=[MergeModulelist(dim=0), Concatenate(dim=1)],
|
||||
)
|
||||
```
|
||||
|
||||
### SplitModulelist
|
||||
|
||||
[`SplitModulelist`] împarte un tensor 3D înapoi într-o listă de tensori 2D. De exemplu, poți împărți o stivă de experți înapoi în experți individuali.
|
||||
|
||||
```py
|
||||
WeightConverter(
|
||||
"mlp.experts.down_proj",
|
||||
"block_sparse_moe.experts.*.w2.weight",
|
||||
operations=[SplitModulelist(dim=0)],
|
||||
)
|
||||
```
|
||||
|
||||
### PermuteForRope
|
||||
|
||||
[`PermuteForRope`] convertește weights din formatul intercalat pentru a folosi formatul sin/cos. De exemplu, poți compune [`Chunk`] cu [`PermuteForRope`] pentru a împărți un tensor QKV fuzionat și a aplica permutarea sin/cos RoPE la Q și K.
|
||||
|
||||
```py
|
||||
WeightConverter(
|
||||
["model.layers.*.self_attn.qkv_proj.weight"],
|
||||
[
|
||||
"model.layers.*.self_attn.q_proj.weight",
|
||||
"model.layers.*.self_attn.k_proj.weight",
|
||||
"model.layers.*.self_attn.v_proj.weight",
|
||||
],
|
||||
operations=[Chunk(dim=0), PermuteForRope()],
|
||||
)
|
||||
```
|
||||
|
||||
### Transpose
|
||||
|
||||
[`Transpose`] inversează dimensiunile unui tensor. Util pentru conversia layout-urilor de weights între diferite convenții.
|
||||
|
||||
```py
|
||||
WeightConverter(
|
||||
source_patterns="mlp.gate.weight",
|
||||
target_patterns="mlp.text_moe.gate.weight",
|
||||
operations=[Transpose(dim0=0, dim1=1)],
|
||||
)
|
||||
```
|
||||
|
||||
## Înlănțuirea operațiilor
|
||||
|
||||
Operațiile pot fi înlănțuite pentru a efectua transformări complexe. Operațiile se execută în ordine, ieșirea fiecărei operații devenind intrarea operației următoare.
|
||||
|
||||
### Exemplu: Conversia MoE Mixtral
|
||||
|
||||
```python
|
||||
WeightConverter(
|
||||
source_patterns=[
|
||||
".experts.*.w1.weight", # gate_proj per expert
|
||||
".experts.*.w3.weight", # up_proj per expert
|
||||
],
|
||||
target_patterns=".experts.gate_up_proj",
|
||||
operations=[
|
||||
MergeModulelist(dim=0), # Stivuiește toți experții: (n_experts, in, out)
|
||||
Concatenate(dim=1), # Fuzionează gate+up: (n_experts, in, 2*out)
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
**Fluxul de date:**
|
||||
```
|
||||
Intrare:
|
||||
".experts.*.w1.weight": [tensor_0, tensor_1, ..., tensor_7] # 8 experți
|
||||
".experts.*.w3.weight": [tensor_0, tensor_1, ..., tensor_7] # 8 experți
|
||||
|
||||
După MergeModulelist(dim=0):
|
||||
".experts.*.w1.weight": (8, 4096, 14336) # gate stivuit
|
||||
".experts.*.w3.weight": (8, 4096, 14336) # up stivuit
|
||||
|
||||
După Concatenate(dim=1):
|
||||
".experts.gate_up_proj": (8, 4096, 28672) # gate_up fuzionat
|
||||
```
|
||||
|
||||
### Reguli de potrivire a pattern-urilor
|
||||
|
||||
- Pattern-urile sursă sunt regex-uri complete evaluate cu `re.search()`. `^` ancorează la începutul cheii **cu scope** (după eliminarea `scope_prefix`).
|
||||
- `*` este un wildcard per-index care colectează toți tensorii potriviți sub același pattern sursă (păstrând ordinea checkpoint-ului pentru concatenare corectă).
|
||||
- Grupurile captante din pattern-urile sursă pot fi referențiate ca `\1`, `\2`, ... în pattern-urile țintă pentru a păstra părți ale cheii originale (e.g. indici de straturi).
|
||||
- Transformările cu scope (`scope_prefix` setat) potrivesc doar cheile care încep cu `f"{scope_prefix}."`.
|
||||
|
||||
## Înregistrarea unei mapări de conversie
|
||||
|
||||
O listă de conversie este înregistrată împotriva unei chei string — fie un `model_type` (e.g. `"mixtral"`) fie un nume de clasă (e.g. `"LlavaModel"`):
|
||||
|
||||
```python
|
||||
from transformers.conversion_mapping import register_checkpoint_conversion_mapping
|
||||
|
||||
register_checkpoint_conversion_mapping(
|
||||
"my_model_type",
|
||||
[
|
||||
WeightRenaming(".old.", ".new."),
|
||||
WeightConverter(
|
||||
".experts.*.w1.weight",
|
||||
".experts.gate_proj",
|
||||
operations=[MergeModulelist(dim=0)],
|
||||
),
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
### Reguli de căutare
|
||||
|
||||
Când [`get_model_conversion_mapping`] procesează un `PreTrainedModel`, fiecare sub-`PreTrainedModel` este vizitat în ordine DFS (`nn.Module.named_modules()` filtrat la instanțe `PreTrainedModel`). Pentru fiecare:
|
||||
|
||||
1. **Căutarea după numele clasei este încercată prima**, apoi `model_type`. Dacă ambele sunt înregistrate pentru același modul, **maparea după numele clasei câștigă** și cea `model_type` este ignorată pentru acel modul — aceasta permite unui cap de sarcină (e.g. `LlavaForConditionalGeneration`) să suprascrie baseline-ul `model_type` partajat (`"llava"`).
|
||||
2. Maparea selectată are `scope_prefix` setat la calea punctată a sub-modulului (`""` pentru root).
|
||||
3. **Deduplicarea bazată pe strămoș** decide dacă se păstrează maparea:
|
||||
- Dacă un path **ancestor** a revendicat deja același identificator (numele clasei sau `model_type`), sub-modulul este **omis** — maparea fără scope sau cu scope mai înalt a strămoșului acoperă deja acest subarbore.
|
||||
- Dacă doar un **sibling** l-a revendicat, sub-modulul este **păstrat** cu propriul `scope_prefix`. Fiecare sibling primește propria mapare cu scope.
|
||||
|
||||
Listele văzute pentru numele clasei și `model_type` sunt urmărite separat, cu o subtilitate: când un modul este potrivit **prin numele clasei**, `model_type`-ul său *nu* este adăugat la lista văzută. Aceasta este pentru ca alte module care partajează același `model_type` dar fără o mapare specifică clasei (e.g. `DetrModel` sub `DetrForSegmentation`) să rămână accesibile prin căutarea `model_type`.
|
||||
|
||||
### Mapări bazate pe clasă vs aliasuri `model_type`
|
||||
|
||||
Ambele stiluri coexistă în `_MODEL_TO_CONVERSION_PATTERN`:
|
||||
|
||||
```python
|
||||
_MODEL_TO_CONVERSION_PATTERN = {
|
||||
# aliasuri model_type (căutare după config.model_type)
|
||||
"minimax": "mixtral",
|
||||
"qwen3_moe": "qwen2_moe",
|
||||
"mistral3": "llava",
|
||||
# aliasuri după numele clasei (căutare după type(submodule).__name__)
|
||||
"PaliGemmaModel": "LlavaModel",
|
||||
"MaskFormerDetrDecoder": "DetrModel",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Cheile după numele clasei sunt preferate când `model_type`-ul este partajat, dar o clasă specifică necesită comportament diferit.
|
||||
|
||||
## Integrarea cu tensor parallelism
|
||||
|
||||
Sistemul de încărcare dinamică se integrează cu tensor parallelism (TP) prin ierarhia `TensorParallelLayer` definită în `src/transformers/integrations/tensor_parallel.py`.
|
||||
|
||||
Când TP este activat, tensorii sunt fragmentați **în timpul** materializării, nu după. Aceasta înseamnă că fiecare rang încarcă doar porțiunea de tensor de care are nevoie.
|
||||
|
||||
```python
|
||||
def spawn_tp_materialize(thread_pool, tensor, sharding_method, tensor_idx, device, dtype):
|
||||
def _job():
|
||||
return sharding_method.shard_tensor(tensor, tensor_idx=tensor_idx, device=device, dtype=dtype)
|
||||
return thread_pool.submit(_job)
|
||||
```
|
||||
|
||||
### Stiluri de paralelism disponibile
|
||||
|
||||
| Stil | Dimensiune Fragment Weight | Descriere |
|
||||
|------|---------------------------|-----------|
|
||||
| `colwise` | -2 | Column-wise: caracteristici de ieșire fragmentate |
|
||||
| `rowwise` | -1 | Row-wise: caracteristici de intrare fragmentate |
|
||||
| `packed_colwise` | -2 | Pentru weights fuzionate (gate_up_proj) |
|
||||
| `packed_rowwise` | -1 | Pentru weights fuzionate |
|
||||
| `embedding_rowwise` | 0 | Paralelism vocabular |
|
||||
| `grouped_gemm` | 0 | Paralelism expert pentru MoE |
|
||||
| `sequence_parallel` | None | Fără fragmentare de weights |
|
||||
|
||||
### Gestionarea weights împachetate
|
||||
|
||||
Pentru weights fuzionate precum `gate_up_proj`, este necesară atenție specială pentru fragmentarea corectă:
|
||||
|
||||
```python
|
||||
def get_packed_weights(param, empty_param, device_mesh, rank, dim):
|
||||
"""
|
||||
Interleaves gate and up shards correctly.
|
||||
|
||||
Packed tensor: [G0 G1 G2 G3 | U0 U1 U2 U3]
|
||||
|
||||
With TP=2:
|
||||
- Rank 0 gets: [G0 G1 | U0 U1]
|
||||
- Rank 1 gets: [G2 G3 | U2 U3]
|
||||
"""
|
||||
```
|
||||
|
||||
Operația TP este stocată în [`WeightTransform`] și aplicată după operațiile de conversie:
|
||||
|
||||
```python
|
||||
if matched_tp_pattern := tp_plan_alt.search(renamed_key):
|
||||
tp_layer = ALL_PARALLEL_STYLES[model.tp_plan[matched_tp_pattern]]
|
||||
mapping.distributed_operation = tp_layer(
|
||||
device_mesh=device_mesh,
|
||||
rank=device_mesh.get_local_rank(),
|
||||
empty_param=empty_param.clone()
|
||||
)
|
||||
```
|
||||
|
||||
## Integrarea cu quantization
|
||||
|
||||
Quantization se integrează în pipeline-ul de încărcare în două moduri, în funcție de dacă checkpoint-ul este deja quantized:
|
||||
|
||||
- **Checkpoint-uri pre-quantized**: Quantizer-ul furnizează instanțe [`WeightConverter`] (prin `get_weight_conversions()`) care deserializează tensorii quantizați. Dtype-urile checkpoint-ului sunt păstrate pentru a evita cast-urile nedorite.
|
||||
- **Quantization din mers**: Quantizer-ul furnizează o operație de quantization care este aplicată după operațiile de conversie, aplicând-o pe weights pe măsură ce sunt încărcate.
|
||||
|
||||
Quantizer-ul poate, de asemenea, rescrie întreaga listă de conversie la sfârșitul [`get_model_conversion_mapping`] prin `update_weight_conversions(...)` — de exemplu, dequantizer-ul FP8 adaugă o operație `Fp8Dequantize` la începutul fiecărui convertor existent, astfel că scalele per-bloc sunt aplicate *înainte* ca orice operații de expert-merge/concat să aplatizeze structura per-expert.
|
||||
|
||||
## Încărcarea rapidă și eficientă a modelelor
|
||||
|
||||
Încărcarea unui model este mai rapidă și utilizează mai puțină memorie deoarece loader-ul știe ce tensori sunt necesari pentru operații și le planifică materializarea leneș.
|
||||
|
||||
Loader-ul scanează checkpoint-ul *o singură dată* pentru a descoperi potriviri de pattern și a colecta tensori. Îi stochează ca obiecte `Future` și îi trimite unui pool de thread-uri pentru încărcare asincronă fără a bloca GIL-ul. Un parametru începe să se încarce imediat ce un thread devine disponibil pentru el.
|
||||
|
||||
Dacă sistemul tău rulează alte procese grele, mai multe thread-uri pot încetini încărcarea în loc să o accelereze. În acest caz, setează variabila de mediu `HF_DEACTIVATE_ASYNC_LOAD=1` pentru a încărca weights secvențial.
|
||||
|
||||
> [!NOTE]
|
||||
> Implicit sunt 4 thread-uri pentru încărcarea asincronă a parametrilor. Aceasta oferă cel mai bun compromis pentru scenariile de încărcare și hardware. Munca este în mare parte limitată de I/O, dar în funcție de hardware-ul acceleratorului și de `dtype`-ul necesar la încărcare, poate deveni limitată de CPU/GPU dacă `dtype`-ul diferă de cel serializat (aceasta necesită o operație suplimentară de copiere).
|
||||
|
||||
### Încărcare asincronă vs sincronă
|
||||
|
||||
```python
|
||||
def spawn_materialize(thread_pool, tensor, device, dtype) -> Future | Callable:
|
||||
def _job():
|
||||
return _materialize_copy(tensor, device, dtype)
|
||||
|
||||
if thread_pool is not None:
|
||||
return thread_pool.submit(_job) # Async: returnează Future
|
||||
else:
|
||||
return _job # Sync: returnează Callable (execuție amânată)
|
||||
```
|
||||
|
||||
Încărcarea sincronă este utilizată când:
|
||||
- Variabila de mediu `HF_DEACTIVATE_ASYNC_LOAD=1` este setată.
|
||||
- Descărcarea pe disc este activată (constrângerile de memorie necesită încărcare secvențială).
|
||||
- Quantization din mers este activat (evită thread-urile worker care depășesc pasul de quantization).
|
||||
|
||||
### Fluxul de materializare
|
||||
|
||||
```
|
||||
1. Iterarea checkpoint-ului (Faza 1):
|
||||
- Pentru fiecare cheie, parcurge lista de transformări o singură dată
|
||||
- Trimite job-ul de materializare la ThreadPoolExecutor
|
||||
- Job-ul returnează Future (async) sau Callable (sync)
|
||||
- Colectează în WeightConverter / WeightRenaming potrivit
|
||||
|
||||
2. Procesarea per-mapare (Faza 2, câte o mapare pe rând):
|
||||
- materialize_tensors() așteaptă doar Future-urile acestei mapări
|
||||
- Aplică lanțul de operații de conversie (self.operations)
|
||||
- Aplică operația de quantizare (dacă din mers)
|
||||
- Setează parametrii pe model
|
||||
- Șterge tensorii realizați imediat
|
||||
|
||||
3. Curățare:
|
||||
- Oprirea pool-ului de thread-uri (cu cancel_futures=True pentru întreruperi)
|
||||
```
|
||||
|
||||
### Eficiența memoriei
|
||||
|
||||
La conversia unui weight, convertorul așteaptă ca toți tensorii necesari să se materializeze dacă nu s-au încărcat încă. De exemplu, operația [`MergeModulelist`] necesită ca toate weights din `ModuleList` să fie încărcate înainte de îmbinare.
|
||||
|
||||
Concatenarea tensorilor necesită o copie temporară, astfel că operații precum [`MergeModulelist`] și [`Concatenate`] necesită de 2 ori memoria tensorilor de bază în timpul conversiei. Odată îmbinați, în memorie rămâne doar tensorul rezultat. Vârful teoretic maxim de memorie este dimensiunea modelului plus tensorii necesari pentru cea mai mare operație [`MergeModulelist`] sau [`Concatenate`].
|
||||
|
||||
Acest caz cel mai rău apare doar când toți ceilalți parametri s-au încărcat înainte de rularea conversiei exigente. Două scenarii declanșează aceasta.
|
||||
|
||||
1. Toți parametrii s-au încărcat asincron înainte de intrarea în conversia exigentă (pool-ul de thread-uri a fost mai rapid decât coada de conversie).
|
||||
2. Conversia exigentă este ultima.
|
||||
|
||||
De exemplu, pentru un model MoE care utilizează [`MergeModulelist`] pentru experți pe fiecare strat, vârful teoretic maxim de memorie este dimensiunea modelului plus experții de pe un strat.
|
||||
|
||||
Aceste scenarii de caz cel mai rău sunt neobișnuite. Vârful real de memorie tinde să rămână aproape de dimensiunea modelului.
|
||||
|
||||
## Reversibilitate
|
||||
|
||||
Sistemul suportă salvarea modelelor cu transformările inverse, permițând save/load dus-întors. Salvarea rulează în două faze: convertoare inverse mai întâi (fiecare tensor se potrivește cel mult unuia), apoi redenumiri inverse, conform regulii de ordonare de mai sus.
|
||||
|
||||
```python
|
||||
def revert_weight_conversion(model, state_dict):
|
||||
"""Aplică conversiile inverse pentru salvare."""
|
||||
weight_conversions = getattr(model, "_weight_conversions", None)
|
||||
|
||||
# Inversează toate transformările
|
||||
reverse_weight_conversion = [
|
||||
conversion.reverse_transform() for conversion in weight_conversions
|
||||
]
|
||||
|
||||
# Aplică în ordine inversă
|
||||
for first_param_name, reversed_converter in conversion_mapping.items():
|
||||
realized_value = reversed_converter.convert(first_param_name, model=model)
|
||||
```
|
||||
|
||||
Lista de transformări utilizate la momentul încărcării este cached pe model ca `_weight_conversions` (se păstrează doar intrările care s-au declanșat efectiv, astfel că redenumirile non-bijective precum [`PrefixChange`] sunt re-aplicate corect simetric). Când modelul a fost instanțiat fără `from_pretrained` (și deci nu are `_weight_conversions`), `revert_weight_conversion` recurge la recalcularea mapării prin [`get_model_conversion_mapping`] și elimină orice [`PrefixChange`] din aceasta (nu putem determina dacă checkpoint-ul original avea prefixul).
|
||||
|
||||
Pattern-urile țintă pot conține elemente regex care necesită procesare pentru direcția inversă:
|
||||
|
||||
```python
|
||||
def process_target_pattern(pattern: str) -> tuple[str, str | None]:
|
||||
"""
|
||||
- Removes `^` and `$` anchors
|
||||
- Removes negative lookahead/lookbehind
|
||||
- Detects capturing groups, replaces with \1
|
||||
"""
|
||||
```
|
||||
|
||||
## Exemple reale
|
||||
|
||||
### MoE în stil Mixtral
|
||||
|
||||
**Formatul checkpoint-ului:**
|
||||
```
|
||||
model.layers.0.block_sparse_moe.experts.0.w1.weight # gate per expert
|
||||
model.layers.0.block_sparse_moe.experts.0.w2.weight # down per expert
|
||||
model.layers.0.block_sparse_moe.experts.0.w3.weight # up per expert
|
||||
...
|
||||
model.layers.0.block_sparse_moe.experts.7.w1.weight
|
||||
```
|
||||
|
||||
**Formatul modelului:**
|
||||
```
|
||||
model.layers.0.mlp.experts.gate_up_proj # (8, 4096, 28672)
|
||||
model.layers.0.mlp.experts.down_proj # (8, 14336, 4096)
|
||||
```
|
||||
|
||||
**Maparea de conversie** (din `conversion_mapping.py`):
|
||||
```python
|
||||
"mixtral": [
|
||||
WeightRenaming(".block_sparse_moe.", ".mlp."),
|
||||
WeightConverter(
|
||||
source_patterns=[".experts.*.w1.weight", ".experts.*.w3.weight"],
|
||||
target_patterns=".experts.gate_up_proj",
|
||||
operations=[MergeModulelist(dim=0), Concatenate(dim=1)],
|
||||
),
|
||||
WeightConverter(
|
||||
source_patterns=[".experts.*.w2.weight"],
|
||||
target_patterns=".experts.down_proj",
|
||||
operations=[MergeModulelist(dim=0)],
|
||||
),
|
||||
],
|
||||
```
|
||||
|
||||
### Model compus viziune-limbaj (Gemma3)
|
||||
|
||||
Gemma3 are configurarea canonică "logică de prefix diferită pentru modelul cap față de modelul de bază". Două intrări sunt înregistrate (aici prin aliasuri care indică listele partajate `"llava"` / `"LlavaModel"`):
|
||||
|
||||
```python
|
||||
# model_type: se aplică la Gemma3ForConditionalGeneration / Gemma3ForSequenceClassification
|
||||
"gemma3": "llava" # → adaugă "model." în fața language_model / vision_tower / ...
|
||||
|
||||
# clasă: se aplică la inner Gemma3Model
|
||||
"Gemma3Model": "LlavaModel" # → redenumire minimă în namespace-ul deja prefixat
|
||||
```
|
||||
|
||||
Parcurgere DFS pentru `Gemma3ForConditionalGeneration`:
|
||||
|
||||
1. Root — căutarea după clasă eșuează (`Gemma3ForConditionalGeneration` nu este înregistrată), căutarea după model_type reușește (`"gemma3"`) → transformările de rescriere a prefixului `"llava"` sunt adăugate **fără scope**, punând `language_model`, `vision_tower`, `multi_modal_projector` sub `model.*`.
|
||||
2. `model: Gemma3Model` interior — **căutarea după clasă reușește** (`Gemma3Model` → `LlavaModel`) → doar maparea `LlavaModel` este aplicată, cu scope la `"model"`. Redenumirile de prefix mult mai largi `"gemma3"` (=`"llava"`) **nu** sunt re-aplicate aici, ceea ce este exact ce vrei: modelul interior trăiește într-un namespace unde prefixul este deja corect.
|
||||
|
||||
Aceeași formă de pereche este utilizată de fiecare VLM din familia Llava (`PaliGemma`, `InternVL`, `Mistral3`, ...). Intrarea model_type gestionează chirurgia prefixului modelului cap; intrarea de clasă menține maparea modelului de bază interior minimă.
|
||||
|
||||
### Imbricare mai profundă cu suprascrierea specifică capului (DETR)
|
||||
|
||||
`DetrForSegmentation` arată o suprascrierea specifică capului stratificată pe deasupra a două niveluri imbricate:
|
||||
|
||||
```
|
||||
DetrForSegmentation (clasă înregistrată: redenumiri specifice segmentării)
|
||||
├── detr: DetrForObjectDetection (fără mapare; doar parcurs)
|
||||
│ └── model: DetrModel (clasă înregistrată: transformări de bază partajate)
|
||||
│ └── backbone, encoder, ...
|
||||
└── mask_head, bbox_attention (weights specifice capului)
|
||||
```
|
||||
|
||||
Sunt implicate două mapări (una per cheie înregistrată):
|
||||
|
||||
```python
|
||||
"DetrModel": [WeightRenaming("backbone.conv_encoder", "backbone"), ...] # bază partajată
|
||||
"DetrForSegmentation": [WeightRenaming("mask_head.lay1", "mask_head.conv1.conv"), ...] # specific capului
|
||||
```
|
||||
|
||||
Parcurgere DFS:
|
||||
|
||||
1. Root `DetrForSegmentation` se potrivește după clasă → redenumiri de segmentare adăugate **fără scope**.
|
||||
2. `detr: DetrForObjectDetection` nu este înregistrat → nu se adaugă transformări; DFS continuă în interiorul său.
|
||||
3. `detr.model: DetrModel` se potrivește după clasă → transformări de bază adăugate cu `scope_prefix="detr.model"`.
|
||||
|
||||
De aceea `DetrForObjectDetection` nu necesită propria mapare: singura mapare înregistrată în subarborele său (`DetrModel`) este automat aplicată cu scope la calea corectă.
|
||||
|
||||
Aliasurile cheiate după clasă reutilizează maparea de bază fără înregistrare suplimentară: `"MaskFormerDetrDecoder": "DetrModel"` face ca un decoder `MaskFormer` să preia aceleași transformări sub propriul nume de clasă.
|
||||
|
||||
### Operații personalizate (ERNIE 4.5 VL MoE)
|
||||
|
||||
Când operațiile integrate nu sunt suficiente, poți crea o subclasă [`ConversionOps`] personalizată. De exemplu, ERNIE 4.5 VL MoE trebuie să împartă o listă de experți partajată între modalitățile text și viziune — ceva ce nicio operație integrată singulară nu gestionează. Operația personalizată `ErnieFuseAndSplitTextVisionExperts` împarte și re-stivuiește experții pe două chei țintă:
|
||||
|
||||
```python
|
||||
"ernie4_5_vl_moe": [
|
||||
WeightRenaming("vision_model", "vision_tower"),
|
||||
WeightConverter(
|
||||
source_patterns=["experts.*.down_proj.weight"],
|
||||
target_patterns=[
|
||||
"text_moe.experts.down_proj",
|
||||
"vision_moe.experts.down_proj",
|
||||
],
|
||||
operations=[ErnieFuseAndSplitTextVisionExperts(stack_dim=0, concat_dim=1)],
|
||||
),
|
||||
],
|
||||
```
|
||||
|
||||
Operațiile personalizate trebuie să implementeze `convert()` și proprietatea `reverse_op` pentru a suporta save/load dus-întors.
|
||||
|
||||
### Aliasuri de tip model
|
||||
|
||||
Multe modele partajează pattern-uri de conversie:
|
||||
|
||||
```python
|
||||
_MODEL_TO_CONVERSION_PATTERN = {
|
||||
"mixtral": "mixtral",
|
||||
"minimax": "mixtral",
|
||||
"qwen2_moe": "qwen2_moe",
|
||||
"deepseek_v2": "qwen2_moe",
|
||||
"deepseek_v3": "qwen2_moe",
|
||||
"qwen3_moe": "qwen2_moe",
|
||||
"olmoe": "qwen2_moe",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Reutilizarea blocurilor de construcție ale încărcării dinamice
|
||||
|
||||
Încărcarea dinamică de weights nu se limitează la checkpoint-uri complete ale modelului. Aceleași blocuri de construcție îți permit să încarci *orice* set de weights atâta timp cât poți descrie cum se mapează cheile checkpoint-ului la parametri și te asiguri că modulele țintă există.
|
||||
|
||||
La un nivel înalt, contractul arată astfel:
|
||||
|
||||
1. **Pregătește namespace-ul modelului.** Asigură-te că modulele/parametrii pe care dorești să îi încarci sunt prezenți și numiți în modul în care maparea ta îi va targeta. Pentru adaptori, aceasta înseamnă apelarea `inject_adapter_in_model(...)` pentru ca modulele adaptor să existe înainte de încărcare. Pentru capete personalizate sau module suplimentare, instanțiază-le mai întâi pe model.
|
||||
2. **Descrie cum să mapezi weights.** Construiește o listă de conversie/redenumire (de exemplu, într-un helper precum `_build_peft_weight_mapping(...)`) utilizând [`WeightConverter`] sau [`WeightRenaming`]. Acesta este locul unde exprimi cum trebuie convertite, împărțite, îmbinate sau redenumite cheile checkpoint-ului pentru a se potrivi namespace-ului modelului tău.
|
||||
Poți face în principal 3 lucruri:
|
||||
- adaugă operații la lista de convertoare: acestea vor fi aplicate pe toate weights, cu excepția celor colectate în oricare din `WeightConverter`. În general, acestea ar trebui să fie operații `WeightRenaming`
|
||||
- adaugă operații la lista de operații a fiecărui convertor: aceasta este ceea ce se întâmplă pentru `Quantization`, unde adăugăm o operație de quantization după lista de operații a oricărui `WeightConverter`.
|
||||
- înlocuiește/mapează operații cu operațiile tale personalizate: aceasta este ceea ce se întâmplă cu `peft`. Înlocuim operația `Concatenate` din, să zicem, `mixtral`, cu `PeftConcatenate`. În acest fel, când checkpoint-ul adaptor este citit, weights de concatenat sunt colectate și formatate corespunzător pentru `peft`
|
||||
3. **Încarcă + finalizează + raportează.** Folosește loader-ul de bază pentru a efectua conversia și a popula tensorii, apoi finalizează și înregistrează rezultatele. Concret, acest flux este:
|
||||
- `LoadStateDictConfig(...)` + `_load_pretrained_model(...)` pentru a încărca și converti.
|
||||
- `_finalize_load_state_dict(...)` pentru a muta tensorii lipsă/nepotriviți de pe `meta`, a-i inițializa și a lega weights.
|
||||
- `log_state_dict_report(...)` pentru a raporta cheile lipsă/neașteptate/nepotrivite (și erorile de conversie).
|
||||
|
||||
Aceste API-uri sunt expuse pentru a-ți permite să gestionezi cod personalizat, formate de weights personalizate, dar și pentru a te asigura că beneficiezi de cea mai înaltă și mai eficientă încărcare de weights, fragmentare și calitate a vieții oferite de API-ul `transformers`!
|
||||
|
||||
## Referință fișiere cheie
|
||||
|
||||
| Fișier | Scop |
|
||||
|--------|------|
|
||||
| `src/transformers/core_model_loading.py` | Logica de bază de încărcare, `WeightConverter`, `WeightRenaming`, `ConversionOps` |
|
||||
| `src/transformers/conversion_mapping.py` | Mapări integrate și compoziție per-submodel (`get_model_conversion_mapping`) |
|
||||
| `src/transformers/integrations/tensor_parallel.py` | Clase și utilitare pentru sharding TP |
|
||||
| `src/transformers/quantizers/base.py` | Hook-uri de quantization și clasa de bază |
|
||||
Reference in New Issue
Block a user