Afiliacja: Uniwersytet im. Adama Mickiewicza w Poznaniu
Temat dużych modeli języka (Large Language Models, LLMs), w szczególności najsłynniejszego ich przedstawiciela, czyli ChataGPT, jest ostatnio bardzo modny. Słyszymy o ich niezwykłych możliwościach, niektórych niepokoją pewne potencjalne zagrożenia z nimi związane.
Ciekawe, że modele języka opierają się na bardzo prostej zasadzie. W gruncie rzeczy są to po prostu uniwersalne ,,autouzupełniacze”, które są w stanie dokończyć dowolny tekst, czasami z lepszym, czasami z gorszym skutkiem. W każdym razie mają ,,nawijkę”, z którą żaden człowiek nie może się równać. Co więcej, zwykle nie planują one wiele kroków w przód, a jedynie przewidują następne słowo.
Prześledźmy działanie modelu języka na prostym przykładzie. Użyjemy otwartoźródłowego modelu Polish GPT-2. Jest to wprawdzie model gorszy niż komercyjny ChatGPT, ale możemy go łatwo uruchomić na swoim komputerze bez płacenia i pytania kogokolwiek o zgodę. Mamy też nad nim pełną kontrolę i możemy zajrzeć do jego ,,wnętrzności”, co jest przydatne w poznawaniu zasady jego działania.
Powiedzmy, że chcielibyśmy poprosić model języka o dokończenie takiego prostego zdania:
Dzisiaj rano poszłem do piekarni i…
Czy właśnie napisałem poszłem?! Prawidłowa polszczyzna wymaga tutaj oczywiście formy poszedłem, ale krótsza forma jest, w gruncie rzeczy, częścią systemu (niestarannej) polszczyzny; dobry model języka powinien sobie radzić nie tylko z językiem pięknym i formalnym, lecz także z potocznym czy niechlujnym.
Zastanów się Czytelniku, jakie słowa mogą wystąpić dalej. Skonfrontujemy to później z przewidywaniami modelu.
Jak już wspomniałem, model w każdym kroku skupia się po prostu na przewidywaniu następnego wyrazu, a mówiąc ściślej, następnego tokenu. Token to taki wyrób wyrazopodobny, częste i krótkie wyrazy są zazwyczaj jednym tokenem, ale dłuższe i rzadsze mogą rozpaść się na dwa lub większą ich liczbę. Podział na tokeny, czyli tokenizacja, jest dość prostą mechaniczną procedurą. Na przykład początek naszego zdania po tokenizacji za pomocą modelu Polish GPT-2 będzie wyglądał tak:
Dzisiaj
rano
posz
łem
do
piekar
ni
i
Jak widać, nasze nieszczęsne poszłem rozpadło się na dwa tokeny, podobnie słowo piekarni. Zwróćmy jeszcze uwagę na to, że spacje doklejają się do następujących po nich wyrazach.
Co się dzieje dalej? Duże modele języka są przykładem szerszej klasy algorytmów nazywanych sieciami neuronowymi. Chwileczkę, czy jeśli mowa o neuronach, to ten artykuł nie powinien pojawić się w dziale biologicznym? Nie, nie, choć sieci neuronowe są luźno inspirowane tym, co wiemy o układzie nerwowym człowieka i innych organizmów, to nie są to żadne mózgi w słoikach. Sieci neuronowe są czysto matematycznym ,,ustrojstwem” – właściwie nie robią nic innego, tylko przemnażają i dodają dużo liczb.
No właśnie, skoro modele języka, będąc sieciami neuronowymi, mogą operować tylko na liczbach, oznacza to, że musimy w jakiś sposób przerzucić most między światem słów a światem liczb. Robimy to, zanurzając słowa (czy właściwie tokeny) w wielowymiarowej przestrzeni, a więc przypisując tokenom wektory, czyli ciągi liczb.
Co się dzieje dalej? Sieć neuronowa przykłada… kątomierz i mierzy kąty między tymi wektorami. Z tym kątomierzem to nawet nie jest bardzo duże uproszczenie i ubarwienie naszej opowieści – rzeczywiście mierzymy kąty między wektorami reprezentującymi słowa, w ten sposób sprawdzając, jak bardzo jedno słowo jest podobne do drugiego. Mierzenie kąta w zasadzie sprowadza się do liczenia iloczynu skalarnego między wektorami.
Karta graficzna to zasadniczo urządzenie służące – jak sama nazwa wskazuje – do rysowania dwu- i trójwymiarowych obrazów. Żeby narysować kosmitę, z którym walczymy w strzelance 3D, trzeba jednak wykonać mnóstwo przemnożeń wektorów i macierzy. Kilkanaście lat temu ktoś wpadł na pomysł, że kart graficznych można użyć właśnie w sztucznej inteligencji!
Tak więc do sieci neuronowej trafiają wektory reprezentujące kolejne tokeny, te wektory są przemnażane w kolejnych warstwach, również przez macierze, czyli ,,tabelki” liczb. Nie wchodząc w szczegóły, karta graficzna musi dokonać miliardów przemnożeń i dodawań.
No dobrze, zobaczmy w końcu, co model języka zrobi z naszym zdaniem. Skrypt w języku programowania Python, który uruchomi nasz model, jest tak krótki, że możemy go tutaj przytoczyć w całości.
Najpierw musimy załadować potrzebne biblioteki, tokenizator i właściwy model (linie 1–6). Jeśli nie mamy karty graficznej, model uruchomi się na zwykłym procesorze (,,cpu”), będzie trwało to wolniej, ale też zadziała.
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
model_name = 'sdadas/polish-gpt2-xl'
tokenizer = AutoTokenizer.from_pretrained(model_name)
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = AutoModelForCausalLM.from_pretrained(model_name).half().to(device)
Następnie tokenizujemy tekst, efekt widzieliśmy już wyżej (linie 7–8).
t = 'Dzisiaj rano poszłem do piekarni i'
tokens = tokenizer.encode(t)
W końcu uruchamiamy nasz model (linie 9–10)…
out = model(torch.tensor(tokens).to(device))
probs = torch.softmax(out[0][-1], 0)
…i wyświetlamy 10 najbardziej prawdopodobnych kontynuacji naszego tekstu (linie 11–14).
k = 10
top_values, top_indices = torch.topk(probs, k)
for p, ix in zip(top_values, top_indices):
print(tokenizer.decode(ix), p.item())
Najciekawsze, że model nie wskazuje po prostu kolejnego słowa, tylko rozkład prawdopodobieństwa na wszystkich możliwych tokenach-kontynuacjach. Oto lista 10 wypisanych tokenów wraz z prawdopodobieństwami:
kupiłem |
0.321533203125 |
nie |
0.0157623291015625 |
zobaczyłem |
0.0263824462890625 |
poprosiłem |
0.014801025390625 |
tam |
0.02154541015625 |
w |
0.011260986328125 |
chciałem |
0.0174407958984375 |
widzę |
0.01025390625 |
wziąłem |
0.017303466796875 |
po |
0.0101776123046875 |
Model zachował się całkiem rozsądnie, chyba Ty też, Czytelniku, przewidziałeś kupiłem jako najbardziej prawdopodobną kontynuację? Ale kolejne propozycje też są zupełnie sensowne.
Zwróćmy uwagę, że model musi mieć ,,zaszytą” gdzieś w sobie, w swoich wektorach i macierzach, całkiem sporą wiedzę, zarówno o języku (na przykład żeby nie zmienił w połowie zdania formy męskiej na żeńską albo pojedynczej na mnogą), jak i o świecie (co się robi w piekarni?).
Od modelu języka oczekujemy jednak, że wygeneruje nam dłuższy tekst, a nie tylko rozkład prawdopodobieństwa… Rozwiązanie jest proste: doklejamy token z najwyższym prawdopodobieństwem (kupiłem) do początkowego wejścia i po prostu uruchamiamy model jeszcze raz. Otrzymamy teraz taki rozkład:
sobie |
0.19384765625 |
dwa |
0.01904296875 |
chleb |
0.08404541015625 |
świeże |
0.0187530517578125 |
bu |
0.031890869140625 |
3 |
0.0170745849609375 |
bułki |
0.031402587890625 |
2 |
0.0161590576171875 |
dwie |
0.020751953125 |
kilka |
0.01425933837890625 |
…więc doklejamy sobie i jeszcze raz:
bu |
0.1282958984375 |
dwie |
0.018768310546875 |
chleb |
0.0789794921875 |
kilka |
0.01861572265625 |
bułki |
0.06201171875 |
dro |
0.0183258056640625 |
pą |
0.033447265625 |
dwa |
0.0176239013671875 |
świeże |
0.0189208984375 |
bagie |
0.016815185546875 |
Dlaczego bu?! A, zapewne to słowo bułkę ucięte w środku. Uruchommy model kolejny raz i sprawdźmy:
łkę |
0.6474609375 |
łek |
0.00867462158203125 |
łeczki |
0.2005615234375 |
ł |
0.004360198974609375 |
łe |
0.10736083984375 |
ły |
0.0034503936767578125 |
łka |
0.011138916015625 |
łki |
0.0014162063598632812 |
łę |
0.00937652587890625 |
lki |
0.0012111663818359375 |
Zwróćmy uwagę – jakże różne rodzaje rozkładów prawdopodobieństwa otrzymujemy z modelu – czasami jest większa liczba kandydatów ze stosunkowo dużymi prawdopodobieństwami, a czasami mamy pewniaka, który bierze więcej niż połowę masy prawdopodobieństwa.
Mieliśmy więc rację. A jak wygląda cały tekst dogenerowany przez model Polish GPT-2? Jeśli wykonamy 20 iteracji, to otrzymamy:
Dzisiaj
rano
posz
łem
do
piekar
ni
i
kupiłem
sobie
bu
łkę
z
szy
nką
i
serem
.
W
róciłem
do
domu
i
zjad
łem
.
Potem
Taki mało ekscytujący tekst. Żeby jednak wiedzieć, jak go wygenerować, korzystając z modelu, potrzeba całkiem sporo matematyki: algebry liniowej, geometrii, teorii prawdopodobieństwa. Nie wspominając o uczeniu modelu, co wymaga ,,wciągnięcia” kolejnych działów matematyki i informatyki.