Przewodnik po fine-tuning LLM: LoRA, QLoRA, Unsloth, Axolotl
Tłumaczenie automatyczne Ten artykuł został automatycznie przetłumaczony z angielskiego oryginału.
Większość nieudanych fine-tuningów wynika z błędnych decyzji, a nie z problemów technicznych. Zespół rozpoczyna trening, zanim udowodni, że promptowanie, wyszukiwanie lub ograniczone dekodowanie nie rozwiążą problemu. Innym razem ewaluacja odbywa się na rozkładzie treningowym albo dopiero po treningu okazuje się, że artefakt trudno wdrożyć.
Ten przewodnik traktuje adaptację jako eksperyment z jasno określonym kryterium zakończenia. Zaczyna od granicy decyzyjnej, a następnie przechodzi przez dane, LoRA lub QLoRA, ewaluację zadaniową, eksport i serwowanie.
Skróconą decyzję dotyczącą interwencji znajdziesz w Fine-Tuning vs RAG vs Prompting.
Czy w ogóle wykonywać fine-tuning?
Zanim wydasz godziny na GPU, zdecyduj, czy fine-tuning jest właściwym narzędziem dla danego problemu.
Fine-tuning a RAG
Fine-tuning może zmienić sposób, w jaki model korzysta z języka domenowego, ale słabo nadaje się do aktualizowania faktów, które się zmieniają lub muszą być cytowane. Retrieval i fine-tuning rozwiązują różne części problemu i często powinny należeć do tego samego systemu.
| Cecha | Fine-tuning | RAG (Retrieval-Augmented Generation) |
|---|---|---|
| Główna funkcja | Modyfikuje wewnętrzne wagi, aby nauczyć model umiejętności, stylów lub zachowań | Dostarcza zewnętrzny, aktualny kontekst w czasie inferencji |
| Najlepsze zastosowania | • Określone style konwersacyjne • Złożone wykonywanie instrukcji • Rozumowanie domenowe | • Szybko zmieniające się dane (wiadomości, ceny akcji) • Ograniczanie halucynacji (grounding) • Cytowanie źródeł |
| Obsługa wiedzy | Zmienia zachowanie statystyczne zapisane w wagach; dokładne odtwarzanie nie jest gwarantowane | Wyszukuje rekordy lub fragmenty, które można aktualizować i cytować |
| Częstotliwość aktualizacji | Wymaga ponownego treningu przy aktualizacjach | Aktualizuje się natychmiast po dodaniu nowych dokumentów |
Fine-tuning a prompt engineering
Współczesne LLMs dobrze reagują na jasne prompty i przykłady. Przetestuj te opcje, zanim zainwestujesz w fine-tuning.
| Aspekt | Fine-tuning | Prompt engineering |
|---|---|---|
| Koszt uruchomienia | Wysoki (przygotowanie danych, obliczenia na GPU, iteracje) | Niski (iteracyjne ulepszanie promptu) |
| Elastyczność | Wymaga kolejnego cyklu treningu i wydania | Zmienia się wraz z promptem |
| Format/styl | Może zwiększyć prawdopodobieństwo powtarzalnego zachowania | Często wystarcza do stylu i prostych formatów |
| Opóźnienie | Może skrócić powtarzające się instrukcje | Zależy od długości promptu i cache’owania po stronie providera |
| Najlepsze zastosowania | Złożone zachowania, distillation, skala kosztowa | Szybkie iteracje, zmienne wymagania |
[!TIP] Najpierw wypróbuj promptowanie Zacznij od promptu i reprezentatywnych przykładów. Jeśli problemem jest wyłącznie niestabilna składnia danych wyjściowych, dodaj ograniczone dekodowanie, zanim zmienisz wagi.
Fine-tuning a ograniczone dekodowanie
Biblioteki takie jak xgrammar i outlines ograniczają generowanie do JSON Schema, wyrażenia regularnego lub gramatyki. Zależnie od ograniczenia i backendu kompilują automat lub gramatykę i maskują nieprawidłowe kolejne tokeny. Aktualizacja wag nie jest wymagana.
Gwarantuje to przynależność do obsługiwanego języka wyjściowego. Gwarancja nie mówi nic o tym, czy wartości są prawdziwe, kompletne ani semantycznie właściwe. Syntaktycznie poprawne wywołanie funkcji nadal może zawierać błędny identyfikator klienta.
| Aspekt | Ograniczone dekodowanie | Fine-tuning |
|---|---|---|
| Konfiguracja | Natychmiastowa — definiujesz schemat i wdrażasz | Wymaga przygotowania danych, obliczeń na GPU i iteracji |
| Gwarancja | Poprawna składnia dla obsługiwanego ograniczenia | Wyuczone zachowanie; zgodność ze schematem może się różnić |
| Elastyczność | Możesz zmienić schemat bez ponownego treningu | Ustalona po treningu |
| Opóźnienie | Niewielki narzut (model może „walczyć” ze schematem) | Niższe (model naturalnie generuje format) |
| Najlepsze zastosowania | JSON, wybory, gramatyki, składnia wywołań narzędzi | Powtarzalne zachowanie zadaniowe, którego brakuje modelowi bazowemu |
Praktyczna kolejność:
- Zacznij od promptowania i przykładów few-shot do podstawowego formatowania.
- Dodaj ograniczone dekodowanie (
xgrammarluboutlines), gdy składnia jest niespójna. - Wykonuj fine-tuning tylko wtedy, gdy potrzebujesz zmian zachowania, których nie da się wymusić schematem.
Szybka ściąga: dopasowanie problemów do rozwiązań
| Wyzwanie | Pierwszy mechanizm do przetestowania | Dlaczego? |
|---|---|---|
| Brakująca wiedza | RAG | Modele halucynują fakty. Retrieval dostarcza ugruntowany, aktualny kontekst |
| Błędny format/ton | Prompt engineering | Współczesne modele dobrze stosują instrukcje dotyczące stylu dzięki przykładom few-shot |
| Niepoprawna składnia danych wyjściowych | Ograniczone dekodowanie | Wymusza obsługiwany schemat lub gramatykę podczas generowania |
| Powtarzające się niepowodzenia zadania | Fine-tuning (SFT) | Uczy się na przygotowanych przykładach wejścia/wyjścia |
| Niedopasowanie preferencji parami | Optymalizacja preferencji | Korzysta z przykładów chosen/rejected, gdy zachowanie zadaniowe jest już mierzalne |
| Opóźnienie/koszt w dużej skali | Distillation (SFT) | Trenuje mniejszy model uczniowski na wyjściach większego modelu nauczyciela |
| Zmniejszenie rozmiaru modelu | Kwantyzacja | Bez treningu — kompresuje wagi (FP16→INT4) na potrzeby szybszej inferencji |
Uczyń uzasadnienie biznesowe mierzalnym
Fine-tuning może ograniczyć liczbę powtarzających się tokenów promptu albo pozwolić mniejszemu modelowi osiągnąć docelowy poziom, ale żadna z tych oszczędności nie jest automatyczna. Oblicz próg rentowności na podstawie własnego ruchu i cen:
[ \text{liczba żądań progu rentowności} = \frac{\text{koszt treningu + ewaluacji + wdrożenia}} {\text{koszt żądania baseline’u} - \text{koszt żądania modelu dostrojonego}} ]
Jeśli mianownik jest mały, ujemny lub opiera się na niepotwierdzonym założeniu dotyczącym jakości, projekt nie ma jeszcze uzasadnienia ekonomicznego.
[!TIP] Konfiguracja hybrydowa Częstą architekturą jest mniejszy model dostosowany do zadania oraz retrieval do zmiennych faktów. Traktuj większy model z promptem jako baseline i pozostaw mniejszy model tylko wtedy, gdy spełnia te same zadaniowe i bezpieczeństwa progi jakości.
Typy fine-tuningu
Fine-tuning może przyjmować trzy główne formy. Różnią się rodzajem potrzebnych danych i tym, czego uczą model.
1. Continued pre-training (self-supervised)
Trenujesz model bazowy na dodatkowym surowym tekście, używając kolejnego tokenu w każdej sekwencji jako celu treningowego. To self-supervised learning: tekst dostarcza własne cele, podobnie jak w pierwotnym treningu pre-training.
Kiedy stosować:
- Domena zawiera słownictwo, którego model bazowy nigdy nie widział (medycyna, prawo, wewnętrzne codebase’y).
- Masz duże ilości tekstu domenowego, ale nie masz oznaczonych par (wejście, wyjście).
- Model bazowy radzi sobie słabo ze specjalistyczną terminologią.
Przykład: trening na milionach notatek klinicznych, aby model poznał skróty medyczne, nazwy leków i przebiegi pracy w klinice.
2. Supervised fine-tuning (SFT)
SFT trenuje się na oznaczonych parach (wejście, wyjście). Pokazujesz modelowi dokładne wyjście, którego oczekujesz dla każdego wejścia.
Kiedy stosować:
- Masz konkretne zadanie z czystym formatem wejścia/wyjścia.
- Masz wysokiej jakości dane oznaczone, nawet w niewielkiej ilości.
- Potrzebujesz przewidywalnego zachowania dla znanego kształtu wejścia.
Przykład: trening na parach (opis zapytania SQL, kod SQL) dla text-to-SQL.
{
"input": "Get all users who signed up last month",
"output": "SELECT * FROM users WHERE signup_date >= DATE_SUB(NOW(), INTERVAL 1 MONTH)"
}
3. Instruction tuning
Instruction tuning to szczególny przypadek SFT, którego celem jest nauczenie modeli wykonywania szerokiego zakresu instrukcji w języku naturalnym. Dane treningowe składają się z par (instrukcja, odpowiedź) obejmujących wiele różnych zadań.
Kiedy stosować:
- Chcesz zbudować asystenta ogólnego przeznaczenia (takiego jak ChatGPT lub Claude).
- Model musi obsługiwać różnorodne, otwarte zapytania.
- Budujesz interfejs konwersacyjny.
Przykład: trening na tysiącach różnorodnych instrukcji, takich jak „Podsumuj ten artykuł”, „Napisz wiersz o X” lub „Wyjaśnij Y prostymi słowami”.
Porównanie
| Aspekt | Continued pre-training | SFT | Instruction tuning |
|---|---|---|---|
| Dane | Surowy tekst | Pary (wejście, wyjście) | Pary (instrukcja, odpowiedź) |
| Etykiety | Brak (unsupervised) | Specyficzne dla zadania | Różnorodne zadania |
| Cel | Wiedza domenowa | Konkretne zachowanie zadaniowe | Wykonywanie dowolnej instrukcji |
| Wolumen danych | Zwykle największy korpus | Określany przez zakres zadań i różnorodność błędów | Zwykle szerszy niż SFT specyficzny dla zadania |
[!NOTE] Co faktycznie się robi SFT i instruction tuning korzystają z tego samego celu next-token; różnią się zakresem i konstrukcją datasetu. Continued pre-training jest odrębnym eksperymentem i powinien być uzupełniony testami zarówno wzrostu jakości domenowej, jak i regresji ogólnych możliwości.
Pipeline fine-tuningu w 7 etapach
Fine-tuning to pipeline, a nie pojedyncze polecenie. Każdy etap ma własne tryby awarii, a pominięcie któregoś z nich zwykle ujawnia się później jako problem z modelem.
Każdy etap opiera się na poprzednim:
- Przygotowanie danych — Zdefiniuj jednostkę ewaluacji, podziel dane, a następnie je oczyść i sformatuj
- Wybór modelu — Wybierz właściwy model bazowy i załaduj wagi
- Konfiguracja treningu — Skonfiguruj sprzęt, hiperparametry i strategię optymalizacji
- Fine-tuning — Uruchom trening SFT, DPO lub ORPO
- Ewaluacja — Zmierz wydajność i zweryfikuj jakość
- Wdrożenie — Wyeksportuj i uruchom model
- Monitorowanie — Śledź wydajność, utrzymuj model i iteruj
[!WARNING] Dane są fundamentem Trening odtwarza systematyczne wady obecne w przykładach. Sprawdź etykiety, leakage, pokrycie i zgodność z zasadami, zanim poświęcisz czas na przeszukiwanie przestrzeni konfiguracji optymalizatora.
Etap 1: Przygotowanie danych
Wiele projektów fine-tuningu kończy się niepowodzeniem właśnie tutaj, a nie podczas treningu. Nowoczesne przygotowanie danych to coś więcej niż uruchomienie regexu na CSV.
Pipeline danych w 5 etapach
Narzędzia takie jak DataTrove i Distilabel mogą pomóc w dużej skali. Projekt pipeline’u powinny wyznaczać taksonomia błędów i kontrakt danych; wybór narzędzia wynika z tych wymagań.
1. Ingestia i filtrowanie
- Działanie: odrzuć odmowy („Nie mogę na to odpowiedzieć”), uszkodzone UTF-8 i języki spoza zakresu.
- Narzędzia: Trafilatura do ekstrakcji oraz modele fastText do identyfikacji języka; rozproszone modele
lid.176rozpoznają 176 języków.
2. Zasady dotyczące danych wrażliwych
- Działanie: zdecyduj, czego model może się nauczyć, a następnie zgodnie z wymaganiami zamaskuj, stokenizuj lub wyklucz dane osobowe i poufne.
- Narzędzia: Microsoft Presidio lub scrubadub.
- Dlaczego: detektor jest tylko jednym ze środków kontroli; nadal obowiązują wymagania dotyczące pochodzenia danych, zgody, retencji, dostępu i usuwania.
3. Deduplicacja (MinHash LSH)
- Działanie: usuń near-duplicates, aby model ich nie zapamiętywał.
- Narzędzia: DataTrove dobrze radzi sobie z przetwarzaniem na poziomie terabajtów.
4. Augmentacja syntetyczna, jeśli potrzebna
- Działanie: użyj silniejszego modelu nauczyciela (GPT-4o, DeepSeek-V3), aby przepisać surowe dane do czystych par instrukcja–odpowiedź.
- Narzędzia: Distilabel.
- Walidacja: próbkuj wyjścia nauczyciela, sprawdzaj je według tego samego rubricu co etykiety przygotowane przez ludzi i zachowaj osobne wycinki syntetyczne oraz napisane przez ludzi podczas ewaluacji.
5. Formatowanie
- Działanie: przekształć dane do standardowego formatu (Alpaca lub ShareGPT).
Przykłady formatów danych
Format Alpaca (wykonywanie instrukcji):
{
"instruction": "Summarize the following text.",
"input": "The text to be summarized...",
"output": "This is the summary."
}
Format ShareGPT/ChatML (konwersacyjny):
{
"conversations": [
{ "from": "user", "value": "Hello, who are you?" },
{ "from": "assistant", "value": "I am a helpful AI assistant." }
]
}
Co faktycznie ma znaczenie
- Pokrycie przed wolumenem. Dodawaj przykłady reprezentujące różne tryby awarii, a nie powtórzenia łatwego przypadku większościowego.
- Czystość. Usuń nieistotny tekst, ujednolić białe znaki i zachowaj spójne formatowanie.
- Balans. Zachowaj istotne rzadkie przypadki i raportuj wydajność dla poszczególnych wycinków.
- Separacja. Dziel dane według źródła, użytkownika, dokumentu lub czasu, gdy losowy podział wierszy powodowałby wyciek near-duplicates.
- Pochodzenie. Rejestruj źródło, licencję lub zgodę, historię transformacji i ścieżkę usuwania dla każdej wersji datasetu.
Etap 2: Wybór modelu i sprzętu
Wybór modelu bazowego i zrozumienie minimalnych wymagań GPU decydują o tym, co rzeczywiście możesz wytrenować.
Zacznij od najmniejszego modelu bazowego, który już przechodzi najważniejsze testy baseline’u. Sprawdź:
- warunki licencji i redystrybucji dla planowanego produktu;
- zachowanie językowe, domenowe, dotyczące korzystania z narzędzi i bezpieczeństwa przed adaptacją;
- zgodność tokenizera i chat template’u z datasetem;
- maksymalny kontekst i zachowanie przy obcinaniu potrzebne dla rzeczywistych przykładów;
- obsługę zarówno w frameworku treningowym, jak i docelowym silniku serwującym.
Fine-tuning jest etapem adaptacji, a nie sposobem naprawy nieodpowiedniego modelu bazowego. Jeśli model nie ma możliwości, których dataset nie obejmuje, wybierz inny model bazowy, zanim uruchomisz kolejne epoki.
Szacuj konkretne uruchomienie, nie segment marketingowy
Nie istnieje trwała tabela „rozmiar modelu → GPU”. Szczytowe zużycie pamięci zależy od precyzji wag, optymalizatora, liczby trenowanych parametrów, długości sekwencji, rozmiaru micro-batcha, activation checkpointingu, implementacji attention i narzutu frameworka. Zacznij od oszacowania pamięci, a następnie uruchom krótki smoke test z maksymalną długością na dokładnie tym samym stacku.
| Składnik pamięci | Full fine-tuning | LoRA | QLoRA |
|---|---|---|---|
| Wagi bazowe | Precyzja treningowa | Zamrożone, zwykle BF16/FP16 | Zamrożone, zazwyczaj 4-bit NF4 |
| Gradienty | Wszystkie trenowane wagi | Wagi adaptera | Wagi adaptera |
| Stany optymalizatora | Wszystkie trenowane wagi | Wagi adaptera | Wagi adaptera |
| Aktywacje | Zależą od batcha i długości sekwencji w każdej metodzie | Ta sama zależność | Ta sama zależność |
W oryginalnej pracy o QLoRA model LLaMA 65B zmieścił się na jednym GPU 48 GB w konkretnie opisanej konfiguracji. To użyteczna granica odniesienia, a nie obietnica, że każda współczesna architektura 70B, długość kontekstu, kernel lub trainer zmieści się na tym samym urządzeniu.
Matematyka pamięci
Dla modelu z parametrów same wagi wymagają około bajtów w BF16/FP16 lub bajtów przy czterech bitach, jeszcze przed dodaniem metadanych kwantyzacji i buforów runtime’u. Pełny trening w stylu Adam dodaje gradienty, stany optymalizatora i często wagi master w wyższej precyzji. LoRA eliminuje większość pamięci na stany trenowalne; QLoRA dodatkowo zmniejsza rozmiar zamrożonych wag bazowych. Przy długich sekwencjach dominować mogą jednak aktywacje.
Stosuj następujący workflow:
- Wybierz najdłuższą sekwencję i micro-batch, które musisz obsługiwać.
- Oszacuj wagi i stany trenowalne, zostawiając zapas na aktywacje i kernele.
- Uruchom jeden krok forward/backward przy maksymalnej długości.
- Zarejestruj szczytową pamięć zaalokowaną i zarezerwowaną.
- Dopiero wtedy zwiększaj rozmiar batcha, rank, długość sekwencji lub liczbę GPU.
Etap 3: Metody treningu (PEFT i LoRA)
Full fine-tuning a PEFT
Full fine-tuning (FFT) aktualizuje każdą wagę, więc gradienty i stan optymalizatora skalują się z całym modelem. Szczytowego zużycia nie można wywnioskować wyłącznie z liczby parametrów, ale jest ono znacznie wyższe niż pamięć potrzebna do załadowania wag na potrzeby inferencji.
Parameter-efficient fine-tuning (PEFT) trenuje tylko mały podzbiór parametrów i zamraża pozostałe. Matematyka staje się znacznie prostsza.
LoRA: punkt wyjścia
LoRA (Low-Rank Adaptation) zamraża wstępnie wytrenowaną macierz i reprezentuje jej nauczoną aktualizację za pomocą dwóch mniejszych macierzy. Oryginalna praca uzasadnia to hipotezą, że użyteczne aktualizacje adaptacyjne mają niski intrinsic rank.
Dla zamrożonej macierzy LoRA uczy się:
Dostosowana warstwa ma postać:
Adapter ma trenowalnych parametrów zamiast dla tej macierzy. Dla kwadratowej macierzy o szerokości 4 096 i rank 16 oznacza to redukcję 128× dla tej macierzy, a nie 10 000× dla dowolnego modelu. Nagłówek 10 000× z pracy LoRA dotyczył konkretnej konfiguracji GPT-3 175B, w której dostosowywano wybrane macierze.
Porównanie metod PEFT
| Metoda | Co się zmienia | Wybierz ją, gdy |
|---|---|---|
| LoRA | Zamrożony model bazowy oraz trenowalne aktualizacje niskiego rzędu | Model bazowy mieści się z zapasem i chcesz uzyskać małe artefakty zadaniowe |
| QLoRA | LoRA z bazą zamrożoną w formacie 4-bitowym | Pamięć zajmowana przez wagi bazowe jest czynnikiem ograniczającym |
| DoRA | Oddziela magnitudę wektora wag od kierunku aktualizowanego przez LoRA | Zmierzony baseline LoRA pozostawia lukę jakościową wartą dodatkowej złożoności |
| Full fine-tuning | Wszystkie wagi modelu | PEFT nie osiąga celu, a wzrost jakości uzasadnia trening rozproszony i pełne checkpointy |
Kiedy wybrać którą metodę
- LoRA: zacznij tutaj. Szybka, oszczędna pamięciowo i dobrze obsługiwana.
- QLoRA: gdy ten sam eksperyment LoRA nie mieści się z powodu zamrożonych wag bazowych.
- DoRA: po porównaniu LoRA 1:1, które pokaże użyteczny wzrost jakości.
- Full fine-tuning: dopiero gdy PEFT okaże się zmierzonym wąskim gardłem, a nie założeniem.
DoRA: LoRA z dekompozycją wag
DoRA (Weight-Decomposed Low-Rank Adaptation) oddziela magnitudę każdego wektora wag od jego kierunku. Praca o DoRA stosuje aktualizację LoRA do składowej kierunkowej, ucząc magnitudę osobno.
Jak to działa:
Zamiast traktować wagi jako pojedynczą całość, DoRA dzieli wagi wstępnie wytrenowane na dwa komponenty:
- Magnituda — jedna trenowalna wartość na wektor wag.
- Kierunek — znormalizowany wektor aktualizowany za pomocą macierzy niskiego rzędu.
W zwartej notacji kolumnowej:
gdzie:
m= magnituda (trenowalna)- = zamrożona macierz kierunkowa
- = nauczona aktualizacja kierunkowa niskiego rzędu
- = normalizacja kolumnowa
Co zyskujesz dzięki tej dodatkowej strukturze:
- Więcej stopni swobody niż w standardowym LoRA, ponieważ magnituda może zmieniać się niezależnie.
- Lepsze wyniki niż LoRA w kilku konfiguracjach opisanych przez autorów pracy.
- Dodatkowe parametry i obliczenia, dlatego zysk należy zweryfikować dla własnego zadania i ścieżki serwowania.
Scalanie adapterów na potrzeby uczenia wielozadaniowego
Oddzielne adaptery pozwalają jednej zamrożonej bazie obsługiwać wiele zadań. Możesz kierować żądania do konkretnego adaptera, serwować wiele adapterów z jednego silnika, jeśli jest to obsługiwane, albo utworzyć offline scalonego kandydata. Scalanie może powodować interferencję, dlatego oceń scalony artefakt zamiast zakładać, że adaptery źródłowe połączą się bezproblemowo.
Typowe metody scalania:
- Konkatenacja — łączy parametry adapterów i zwiększa efektywny rank. Szybka i prosta.
- Kombinacja liniowa — ważona suma adapterów. Daje możliwość strojenia.
- SVD — dekompozycja macierzy na potrzeby scalania. Bardziej elastyczna, ale wolniejsza.
Przykład: jeden adapter do podsumowywania, drugi do tłumaczenia, scalone w jeden model wielozadaniowy.
Etap 4: Fine-tuning i alignment preferencji
SFT uczy się demonstracji. Optymalizacja preferencji uczy się natomiast na porównaniach, takich jak „wybrana odpowiedź A jest lepsza niż odrzucona odpowiedź B”. Stosuj ją tylko wtedy, gdy preferencja parami jest właściwą etykietą dla danego błędu; poprawność faktów i zgodność z zasadami często wymagają silniejszych ewaluatorów niż globalna preferencja.
RLHF na bazie PPO
Oryginalny przepis składał się z trzech etapów:
- SFT — nauka zadania.
- Model nagrody — trening na ludzkich preferencjach (chosen kontra rejected).
- PPO (Proximal Policy Optimization) — uczenie ze wzmocnieniem w celu optymalizacji polityki.
Koszt operacyjny wynika z liczby elementów składowych:
- Skomplikowana implementacja i utrzymanie.
- Wysoki koszt — trenujesz wiele modeli.
- Próbkowanie on-policy i optymalizacja nagrody wymagają uważnych kontroli stabilności oraz reward hackingu.
DPO
DPO (Direct Preference Optimization) usuwa jawny model nagrody i pętlę RL. Praca o DPO wyprowadza przeparametryzowany cel maksymalizacji nagrody z ograniczeniem dywergencji KL, dzięki czemu optymalizacja może korzystać z par preferencji zamiast uczenia ze wzmocnieniem:
{
"prompt": "Explain quantum computing",
"chosen": "Quantum computing uses qubits...", # Preferred response
"rejected": "Well, it's complicated..." # Non-preferred response
}
Zmiany operacyjne:
- Prostsza ścieżka kodu (bez osobnego modelu nagrody i pętli RL).
- Cel offline na parach preferencji zamiast uczenia ze wzmocnieniem on-policy.
- Polityka referencyjna lub równoważne referencyjne log-probabilities w standardowym sformułowaniu.
DPO łatwiej prototypować niż pełny pipeline PPO, ale nie jest automatycznym ulepszeniem jakości. Wyniki zależą od polityki początkowej, jakości par, ustawień loss, efektów długości i protokołu ewaluacji. Porównaj DPO z checkpointem SFT na tych samych odłożonych zbiorach preferencji i zadań.
ORPO
ORPO (Odds-Ratio Preference Optimization) łączy loss SFT negative log-likelihood z karą odds-ratio dla odrzuconych odpowiedzi. Usuwa osobny model referencyjny i może łączyć naukę zadania z optymalizacją preferencji w jednym uruchomieniu.
Jak to działa: ORPO używa połączonego loss, który wykonuje jednocześnie dwie rzeczy:
- Maksymalizuje prawdopodobieństwo wybranej odpowiedzi (uczenie zadania).
- Karze odrzuconą odpowiedź składnikiem odds-ratio (uczenie preferencji).
Warto znać następujące hiperparametry:
from trl import ORPOConfig
config = ORPOConfig(
learning_rate=8e-6, # Very low, as recommended by the ORPO paper
beta=0.1, # Controls strength of preference penalty
# ... other params
)
- Learning rate: w pracy użyto niskich wartości w eksperymentach; dostrój go do modelu, batcha i danych, zamiast traktować jedną wartość jako uniwersalną regułę.
- Beta: kontroluje udział składnika preferencji względem składnika SFT.
Kompromis:
- Jeden etap treningu zamiast dwóch.
- Brak modelu nagrody.
- Brak przejścia forward modelu referencyjnego.
- Sprzężone uruchomienie: jeśli uczenie zadania lub zachowanie preferencyjne ulegnie regresji, nie ma pośredniego checkpointu SFT z tego samego pipeline’u do analizy.
Wybierz metodę na podstawie projektu danych i ewaluacji:
- Użyj DPO, gdy masz już satysfakcjonujący checkpoint SFT i chcesz przeprowadzić prostszy offline’owy eksperyment z preferencjami.
- Przetestuj ORPO, gdy do danych i ograniczeń operacyjnych pasuje pozbawiony modelu referencyjnego, jednoetapowy cel.
- Użyj RLHF na bazie PPO, gdy próbkowanie online względem jawnie nauczonej nagrody jest wymaganiem i możesz monitorować wykorzystywanie nagrody.
Żadna z tych metod nie jest domyślna dla wszystkich zadań. Zachowaj baseline wyłącznie z SFT i raportuj zarówno metryki zadaniowe, jak i preferencyjne.
Frameworki do fine-tuningu
Frameworki częściowo się pokrywają i szybko się zmieniają. Wybierz framework na podstawie wymaganej ścieżki wykonania, przypnij wersje i zachowaj konfigurację treningu w formie wystarczająco przenośnej, aby można ją było odtworzyć poza notebookiem.
Unsloth — szybkość i efektywność pamięciowa
Unsloth integruje się z Hugging Face trl i transformers oraz udostępnia zoptymalizowane kernele, checkpointing i ścieżki kwantyzowanego fine-tuningu dla obsługiwanych modeli.
- Niestandardowe kernele GPU w Triton dla attention, RoPE i cross-entropy, które pomijają narzut PyTorch.
- Oszczędne pamięciowo backprop, które ponownie oblicza aktywacje podczas przejścia wstecznego zamiast przechowywać je w pamięci.
- Operacje fused, które łączą wiele kroków (layer norm + linear i podobne) w pojedyncze wywołania GPU.
- Kwantyzacja 4-bitowa zintegrowana bezpośrednio ze ścieżką QLoRA, ze zoptymalizowaną dekwantyzacją.
[!IMPORTANT] Kolejność importów ma znaczenie Stosuj kolejność importów z przykładu Unsloth dla przypiętej wersji. Unsloth nakłada patche podczas importu, dlatego zaimportowanie go przed
trlitransformerspozwala uniknąć braku optymalizacji lub błędów zależnych od wersji.
# Correct order
from unsloth import FastLanguageModel # Must be first!
from trl import SFTTrainer
from transformers import TrainingArguments
# Avoid this order with Unsloth's patched path
from trl import SFTTrainer
from unsloth import FastLanguageModel
Najlepsze zastosowania: trening na jednym GPU, prototypowanie, notebooki Colab i sytuacje, w których kontrolujesz rachunek za GPU.
Opublikowane wartości szybkości i zużycia pamięci różnią się zależnie od modelu, długości sekwencji, batcha, precyzji i sprzętu. Zmierz tokens per second oraz szczytową pamięć podczas własnego uruchomienia, zamiast traktować nagłówkowy współczynnik jako właściwość frameworka.
Axolotl — trening sterowany konfiguracją
# config.yaml - no code required
base_model: meta-llama/Meta-Llama-3-8B
adapter: qlora
lora_r: 32
lora_alpha: 16
datasets:
- path: data/my_data.jsonl
type: alpaca
sample_packing: true
Uruchom za pomocą: accelerate launch -m axolotl.cli.train config.yaml
Najlepsze zastosowania: deklaratywne, powtarzalne uruchomienia oraz wbudowane opcje launcherów do treningu rozproszonego. Konfigurację można przeglądać, wersjonować i ponownie wykorzystywać w uruchomieniach lokalnych oraz rozproszonych.
Porównanie frameworków
| Narzędzie | Przydatne, gdy | Sprawdź przed wyborem |
|---|---|---|
| Unsloth | Chcesz zoptymalizowaną ścieżkę dla obsługiwanego modelu i zwięzłe przykłady | Macierz obsługi modelu, GPU, kwantyzacji i treningu rozproszonego |
| Axolotl | Chcesz deklaratywnych konfiguracji i gotowych przepisów rozproszonych | Dokładny schemat konfiguracji i launcher dla przypiętej wersji |
| TRL | Chcesz bezpośredniego dostępu do trainerów SFT i preferencji w Hugging Face | Format datasetu, chat template, maskowanie loss i integrację z PEFT |
| Torchtune | Chcesz przepisów i komponentów natywnych dla PyTorch | Zakres obsługiwanych przepisów modelowych i zgodność eksportu |
Praktyczne demo: fine-tuning z Unsloth
Oto reprezentatywny fragment treningu z mojego repozytorium unsloth-finetune-demo. Demo wykonuje fine-tuning Nemotron-Nano na potrzeby wywoływania funkcji. Przed tym fragmentem jego src/unsloth_demo/data.py ładuje i formatuje dataset, a ścieżka treningowa tworzy następnie wersjonowane obiekty train_dataset i eval_dataset.
Szybki start
# Clone and setup
git clone https://github.com/slavadubrov/unsloth-finetune-demo.git
cd unsloth-finetune-demo
# Install with uv (recommended)
uv sync
# Run fine-tuning (quick test)
uv run finetune --max-samples 1000
Konfiguracja
Najważniejsze elementy znajdują się w config.py:
# Model & Dataset
MODEL_NAME = "nvidia/Llama-3.1-Nemotron-Nano-4B-v1.1" # 4B params, 128K context
DATASET_NAME = "glaiveai/glaive-function-calling-v2" # 113K examples
# LoRA Configuration
LORA_R = 16 # Adapter capacity; tune against held-out results
LORA_ALPHA = 32 # Update scaling; alpha/r is the classic LoRA scale
MAX_SEQ_LENGTH = 4096
# Candidate modules for this Llama-family model
LORA_TARGET_MODULES = [
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
]
[!NOTE] Stosunek alpha do rank
alpha/rskaluje klasyczną aktualizację LoRA.alpha = 2rto często stosowana heurystyka początkowa w dokumentacji niektórych narzędzi, a nie gwarancja stabilności. Przeszukuj rank, alpha, learning rate i moduły docelowe dopiero po ustaleniu danych i baseline’u.
Główny kod treningu
from unsloth import FastLanguageModel
from trl import SFTConfig, SFTTrainer
# Load model with 4-bit quantization
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="nvidia/Llama-3.1-Nemotron-Nano-4B-v1.1",
max_seq_length=4096,
load_in_4bit=True,
)
# Add LoRA adapters
model = FastLanguageModel.get_peft_model(
model,
r=16,
lora_alpha=32,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
use_gradient_checkpointing="unsloth", # Lower activation memory; extra compute
)
# The preceding data step must create these versioned dataset objects.
# Each row has the chat messages and tool schemas expected by current TRL.
# Train with the current TRL configuration surface.
trainer = SFTTrainer(
model=model,
processing_class=tokenizer,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
args=SFTConfig(
output_dir="outputs/nemotron-function-calling",
max_length=4096,
packing=True,
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
learning_rate=2e-4,
num_train_epochs=3,
bf16=True,
),
)
trainer.train()
Fine-tuning z Axolotl
[!NOTE] Demo w przygotowaniu Pracuję nad praktycznym demo Axolotl. Do tego czasu dobrym źródłem informacji o strategiach treningu multi-GPU jest Accelerate n-D Parallelism Guide od Hugging Face.
W konfiguracjach config-first i rozproszonych Axolotl zapewnia powtarzalność workflow:
# axolotl_config.yaml
base_model: meta-llama/Meta-Llama-3-8B
model_type: LlamaForCausalLM
# QLoRA configuration
load_in_4bit: true
adapter: qlora
lora_r: 32
lora_alpha: 16
lora_dropout: 0.05
lora_target_modules:
- q_proj
- k_proj
- v_proj
- o_proj
- gate_proj
- up_proj
- down_proj
# Dataset
datasets:
- path: data/training_data.jsonl
type: alpaca
# Training settings
sequence_len: 4096
sample_packing: true # Benchmark with your length distribution
micro_batch_size: 2
gradient_accumulation_steps: 4
learning_rate: 0.0002
num_epochs: 3
# Current Axolotl key; verify support on the pinned release
bf16: true
attn_implementation: flash_attention_2
Uruchom trening:
axolotl train axolotl_config.yaml
Etap 5: Ewaluacja
Zamroź kontrakt ewaluacyjny przed pierwszym uruchomieniem. Co najmniej porównuj dostrojony checkpoint z dokładnie tym samym, niedostrojonym modelem bazowym, używając tego samego promptu, ustawień dekodowania i środowiska narzędziowego. Raportuj jakość zagregowaną dopiero po sprawdzeniu wycinków błędów, które projekt miał poprawić.
Śledź cztery grupy:
- Zadanie docelowe: exact match, sukces wykonania, rubryka oceniana przez człowieka lub inny wynik powiązany z przypadkiem użycia.
- Regresja: ogólne możliwości i wcześniej obsługiwane wycinki zadań, które adaptacja może pogorszyć.
- Bezpieczeństwo i zasady: odmowy, wyciek danych, prompt injection lub ograniczenia specyficzne dla domeny.
- Operacje: opóźnienie, przepustowość, pamięć, rozmiar artefaktu i koszt w docelowej konfiguracji serwowania.
Automatyczne benchmarki
Używaj lm-evaluation-harness do odpowiednich standaryzowanych zadań, ale nie traktuj go jako zamiennika ewaluacji produktu:
lm_eval --model hf \
--model_args pretrained=./outputs/merged-model \
--tasks hellaswag,arc_easy,mmlu \
--batch_size 8
LLM-as-judge
W przypadku jakości subiektywnej większy model może pomóc w ocenianiu, ale skalibruj go na przykładach zweryfikowanych przez ludzi i ukryj tożsamość kandydata:
judge_prompt = """
Rate this response from 1-5 on:
- Relevance
- Accuracy
- Formatting
Response: {model_output}
Expected: {ground_truth}
"""
Ewaluacja domenowa
Odłóż rzeczywiste przykłady według źródła, użytkownika, dokumentu lub czasu, aby near-duplicates nie wyciekły między splitami. W przypadku wywoływania funkcji waliduj całą trajektorię: wybór narzędzia, argumenty, wynik wykonania, odzyskiwanie po błędzie i końcową odpowiedź. Przy małej próbie raportuj przedziały ufności lub sparowane liczby zwycięstw/porażek i analizuj każdą regresję w krytycznym wycinku.
Etap 6: Wdrożenie i formaty wyjściowe
Wybierz artefakt na podstawie silnika serwującego i planu rollbacku, a nie tylko rozmiaru pliku:
1. Adapter LoRA
uv run finetune # Saves ~100-500MB adapter
- Rozmiar: proporcjonalny do docelowych modułów, rank, liczby warstw i dtype; często znacznie mniejszy od bazy.
- Najlepsze zastosowania: development, wersjonowane adaptery zadaniowe i silniki obsługujące LoRA bezpośrednio.
- Dodatkowa zaleta: możesz przełączać adaptery bez ponownego pobierania modelu bazowego.
2. Scalone modele
uv run finetune --merge # Creates a standalone full model
- Rozmiar: w przybliżeniu pełny checkpoint bazowy w wybranej precyzji wyjściowej.
- Najlepsze zastosowania: silniki lub ścieżki dystrybucji, które nie obsługują oddzielnego adaptera.
- Kompromis: większy artefakt i wolniejsze wdrażanie, ale prostsze ładowanie pojedynczego modelu.
3. Format GGUF
uv run finetune --gguf q4_k_m # Creates ~2-4GB quantized model
- Rozmiar: zależny od modelu; dla wariantów Q4 jest to w przybliżeniu rozmiar wag czterobitowych plus metadane.
- Najlepsze zastosowania: inferencja na CPU, Ollama, llama.cpp i wdrożenia edge.
- Opcje:
q4_k_m(mniejszy),q5_k_m(lepsza wierność wag),q8_0(większy i wierniejszy). Po konwersji zmierz wpływ na zadanie.
Etap 7: Serwowanie i monitorowanie
Z vLLM
# Serve the base and expose a PEFT adapter as a model name. This parser and
# template pair is for a Llama 3.1-compatible function-calling adapter.
vllm serve nvidia/Llama-3.1-Nemotron-Nano-4B-v1.1 \
--enable-lora \
--lora-modules function-calling=./outputs/adapter \
--enable-auto-tool-choice \
--tool-call-parser llama3_json \
--chat-template examples/tool_chat_template_llama3.1_json.jinja \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 4096
Zapytanie przez API kompatybilne z OpenAI:
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="dummy")
response = client.chat.completions.create(
model="function-calling",
messages=[{"role": "user", "content": "Book a flight to Tokyo"}],
tools=[
{
"type": "function",
"function": {
"name": "book_flight",
"description": "Book a flight to a city.",
"strict": True,
"parameters": {
"type": "object",
"properties": {
"destination": {"type": "string"},
},
"required": ["destination"],
"additionalProperties": False,
},
},
}
],
tool_choice="auto",
)
Przewodnik vLLM po wywoływaniu narzędzi wymaga automatycznego wyboru narzędzi i parsera dopasowanego do modelu; użyj zgodnego chat template’u modelu, gdy konfiguracja tokenizera nie udostępnia własnego. W tool_choice="auto" ograniczone argumenty wymagają także strict: true dla co najmniej jednej funkcji (oraz włączonego ustawienia strict-tool-calling w vLLM, które jest domyślne); użyj schematu parameters zgodnego z trybem strict. Bez tego opt-in vLLM wyodrębnia wywołania z surowego tekstu, więc argumenty mogą być niepoprawne lub naruszać schemat.
Z Ollama (lokalnie)
# Create Modelfile
echo 'FROM ./outputs/unsloth-nemotron-function-calling-gguf/model-q4_k_m.gguf' > Modelfile
# Import to Ollama
ollama create my-function-model -f Modelfile
# Run
ollama run my-function-model
Z llama.cpp (CPU)
./llama-cli -m ./outputs/model-q4_k_m.gguf \
-p "What's the weather in Tokyo?" \
--ctx-size 4096
Monitoruj wdrożony model
Cykl życia nie kończy się na prawidłowym loss treningowym. Zapisz rewizję modelu bazowego, tokenizer i chat template, hash adaptera, wersję datasetu, konfigurację treningu oraz raport ewaluacyjny jako jedną jednostkę wydania. Na produkcji monitoruj sukces zadania, niepoprawne wyjścia, błędy zasad, opóźnienie i drift wejścia według tych samych wycinków, których używano offline. Zachowaj możliwość załadowania poprzedniego artefaktu i zdefiniuj próg rollbacku przed uruchomieniem.
Najważniejsze wnioski
- Wykonuj fine-tuning dopiero wtedy, gdy baseline bez dostrajania i taksonomia błędów pokażą, że adaptacja wag rozwiązuje problem.
- Retrieval zarządza zmiennymi dowodami, a ograniczone dekodowanie zarządza składnią; SFT nie zastępuje żadnego z nich.
- LoRA ogranicza liczbę trenowanych stanów. QLoRA dodatkowo kompresuje zamrożone wagi bazowe. Nie przypisuj wartości zużycia pamięci QLoRA metodzie LoRA.
- Pokrycie danych, integralność splitów, pochodzenie danych i maskowanie loss są ważniejsze niż kopiowanie modnej konfiguracji optymalizatora.
- DPO, ORPO i RLHF na bazie PPO to różne projekty eksperymentalne, a nie szczeble jakości z uniwersalną metodą domyślną.
- Oceniaj zachowanie docelowe, regresje, bezpieczeństwo i operacje względem tego samego modelu bazowego.
- Wybierz wyjście w postaci adaptera, modelu scalonego lub GGUF na podstawie wymagań serwowania i rollbacku przed treningiem.
Referencje
Artykuły i badania
- LoRA: Low-Rank Adaptation of Large Language Models
- QLoRA: Efficient Finetuning of Quantized LLMs
- DoRA: Weight-Decomposed Low-Rank Adaptation
- DPO: Direct Preference Optimization
- ORPO: Odds Ratio Preference Optimization
- PPO: Proximal Policy Optimization Algorithms — OpenAI, 2017
Narzędzia do przetwarzania danych
- DataTrove — przetwarzanie danych Hugging Face na dużą skalę
- Distilabel — generowanie danych syntetycznych (Argilla)
- Trafilatura — ekstrakcja i crawling tekstu internetowego
- Identyfikacja języka fastText — rozproszone modele
lid.176dla 176 języków - Microsoft Presidio — wykrywanie i anonimizacja PII
- scrubadub — biblioteka Python do usuwania PII
Ograniczone dekodowanie
- xgrammar — ograniczone dekodowanie z użyciem FSM
- outlines — generowanie ustrukturyzowanych danych dla LLMs
Frameworki treningowe
- Unsloth — zoptymalizowany framework do fine-tuningu
- Axolotl — trening sterowany konfiguracją i launchery rozproszone
- TRL — biblioteka Hugging Face do SFT i treningu preferencji
- Torchtune — biblioteka do fine-tuningu natywna dla PyTorch
Inferencja i wdrażanie
- Adaptery LoRA w vLLM — serwowanie jednego lub wielu adapterów z modelem bazowym
- Wywoływanie narzędzi w vLLM — dopasowanie automatycznego wyboru narzędzi, parsera, chat template’u i schematu żądania do modelu
- Ollama — lokalny runner LLM dla Mac/Windows/Linux
- llama.cpp — inferencja CPU/GPU w formacie GGUF
Ewaluacja
- lm-evaluation-harness — standaryzowane benchmarki LLMs od EleutherAI
Przewodniki i zasoby
- Demo Repository — praktyczny przykład fine-tuningu
- LLM Fine-Tuning. Theoretical Intuition and Practical Implementation — notebook badawczy NotebookLM
- Accelerate n-D Parallelism Guide — strategie treningu multi-GPU Hugging Face