Podstawy
2 godz. 43 min · OpenAI · Full-stack i Programowanie
Adam GospodarczykChociaż dokładne działanie dużych modeli językowych nie jest zrozumiałe nawet dla twórców tych narzędzi, to i tak istnieje szereg dobrze znanych faktów. Zapoznanie się z nimi pozwoli Ci lepiej wyobrazić sobie sposób działania LLM bez konieczności wchodzenia w głębokie detale techniczne. To z kolei w sposób bezpośredni przełoży się na skuteczność projektowanych promptów. W pierwszej części kursu skupiamy na wysokopoziomowym spojrzeniu na modele firmy OpenAI, uwzględniając ich aktualne możliwości oraz aktualne ograniczenia.
Instrukcje kierowane do modeli takich jak GPT-3.5-Turbo czy GPT-4, mogą realizować najróżniejsze zadania. Pomimo tego ich ogólna struktura uwzględnia pewne schematy z których możemy korzystać. W zależności od celu jaki chcemy osiągnąć, możemy uwzględniać lub pomijać poszczególne elementy promptu. I chociaż wspomniane modele są w stanie świetnie radzić sobie z nieustrukturyzowanymi danymi, to w przypadku projektowania instrukcji, bardzo istotne jest zachowanie precyzji oraz wyraźne oddzielenie jej fragmentów. Na praktycznych przykładach zobaczysz, jak łatwo niewłaściwe formatowanie może negatywnie wpływać na generowaną odpowiedź. Poznasz także ogólne zasady, które pomogą Ci kształtować instrukcje w sposób, który zwiększy prawdopodobieństwo wygenerowania odpowiedzi, której oczekujesz.
Zero-shot, Few-shot, Chain of Thought czy Tree of Thoughts — to techniki projektowania promptów, dzięki którym znacząco zwiększysz ich skuteczność. I choć każda z nich zwykle opiera się o bardzo proste koncepcje, tak ich praktyczne wykorzystanie nie zawsze jest oczywiste. W tym kursie nie tylko poznasz przykłady ich zastosowania, ale także będziesz w stanie połączyć je z ogólnymi zasadami tworzenia promptów, co jeszcze bardziej ulepszy tworzone przez Ciebie instrukcje. Ciekawostka: Technika Tree of Thoughts w niektórych przypadkach zwiększa skuteczność GPT-4 z 4% do nawet 74%.
Ostatnia część kursu uwzględnia kilka przykładów, których celem jest pokazanie Ci szerokiego kontekstu w którym umiejętność projektowania promptów, umożliwia wyjście daleko poza zwykłe odpowiadanie na pytania i generowanie tekstu. Zobaczysz, jak tworzone przez Ciebie instrukcje mogą zostać wykorzystane w aplikacjach webowych oraz systemach uwzględniających realizujących złożone zadania z pomocą dużych modeli językowych. Mowa tutaj o pamięci długoterminowej, embeddingu danych oraz nawet autonomicznych agentach, zdolnych do posługiwania się narzędziami. Pamiętaj jednak, że wszystkie z wymienionych tematów zostały omówione tylko z szerokiej perspektywy, ponieważ ich faktyczna implementacja, wykracza poza zakres tego kursu.
Ten kurs został zaprojektowany z myślą o osobach chcących rozpocząć naukę projektowania promptów dla dużych modeli językowych, takich jak GPT-3.5-Turbo czy GPT-4. Wcześniejsze doświadczenie oraz zaawansowane umiejętności techniczne czy programistyczne nie są wymagane. Wiedza z tego kursu da Ci podstawy do dalszej nauki projektowania promptów oraz pozwoli Ci uzyskać szerszą perspektywę na temat roli promptów przy codziennej pracy z narzędziami takimi jak ChatGPT czy integracjami dużych modeli językowych z aplikacjami.
Myślę, że nadszedł czas, abyśmy skupili naszą uwagę na projektowaniu promptów.
Przejdziemy teraz przez ogólne zasady, z których część z nich będziesz
wykorzystywać w większości promptów, a inne tylko w niektórych sytuacjach.
Tego, że do projektowania promptów można,
a w zasadzie nawet trzeba, podejść bardzo kreatywnie.
Co więcej, do osiągnięcia konkretnych
rezultatów mogą prowadzić nas różne ścieżki.
Im bardziej kreatywna ścieżka, tym większe prawdopodobieństwo, że nasz prompt będzie
działał znacznie bardziej efektywnie, zachowując jednocześnie zwięzłą formę.
Przykładem tego, o czym mówię, może być nadawanie roli na czas bieżącej dyskusji.
W sieci można znaleźć różnego rodzaju
przykłady, które pełnią rolę raczej rozrywkową, np.
odpowiadaj w stylu Joe Rogana.
Wówczas rzeczywiście wypowiedzi modelu
bardzo przypominają sposób wypowiedzi znanego podcastera.
Co więcej, fakt, że modele takie jak GPT są świetnymi kameleonami możemy wykorzystać
także po to, aby jednocześnie bardzo precyzyjnie oraz zwięźle z góry definiować
ich zachowanie, a także dostęp do konkretnej wiedzy.
Dobrym przykładem są tutaj słowa, które
posiadają różne znaczenie w zależności od kontekstu.
Takim słowem może być np.
port, który może być rozumiany chociażby
jako miejsce nad morzem, bądź też jako fizyczne złącze w naszym komputerze.
To, którą z definicji otrzymamy przy
generowaniu odpowiedzi, będzie zależało m.in. od nadanej roli.
Z tego powodu myślę, że dobrze jest
zastanowić się nad tym, jaką rolę chcemy nadać do realizacji konkretnego zadania.
Oczywiście nie jest to niezbędny krok, aczkolwiek często okazuje się przydatny.
Idąc dalej mamy instrukcję, która może być
powiązana z rolą i jej zadaniem będzie rozszerzenie bądź doprecyzowanie tego, w
jaki sposób mają zostać generowane odpowiedzi.
Sama instrukcja nie jest dokładnie pytaniem, które zadaje użytkownik, tylko
raczej informacją o tym, jak mamy reagować na pytania użytkownika.
Za chwilę stanie się to nieco bardziej
zrozumiałe, gdy uchwycimy całą strukturę naszego promptu.
Idąc dalej mamy kolejny opcjonalny element w postaci kontekstu.
Jest to miejsce, w którym jesteśmy w stanie przekazać dodatkowe informacje,
które mogą zostać wykorzystane przy generowaniu odpowiedzi.
Takim kontekstem może być np.
baza wiedzy na temat jakiegoś produktu bądź informacje dynamicznie wczytane np.
z Internetu.
W ten sposób jesteśmy w stanie nie tylko zwiększać skuteczność modelu i poszerzać
jego zakres pamięci, ale także pozytywnie wpływamy na efekt znany jako halucynacja.
Czyli przykładowo jeżeli domyślnie
zapytamy ChatGPT o jakieś informacje, które wykraczają poza jego bazową wiedzę, to
jest szansa na to, że wygenerowana odpowiedź nie będzie prawdziwa.
Jednak w przypadku, gdy będziemy posiadać prompt, który będzie posiadać swój własny
kontekst, na podstawie którego będą generowane odpowiedzi, to ich jakość
będzie zależała w bardzo dużym stopniu od jakości wiedzy zawartej w kontekście.
Przekładając to teraz jeszcze bardziej na praktykę,
jeżeli w tym momencie przyszedł bym do ChatGPT i zadał pytanie np.
o moją osobę, to z dużym
prawdopodobieństwem nie otrzymam poprawnej odpowiedzi.
Jeżeli jednak w ramach kontekstu dostarczył bym dodatkowych informacji na
swój temat, to wówczas odpowiedzi byłyby znacznie wyższej jakości i mógłbym tak
jakby prowadzić rozmowę z dostarczonymi informacjami.
Poza samym kontekstem możemy mieć także
przykłady, które będą pokazywały możliwe rozwiązania.
Podawanie przykładów jest niesamowicie
skuteczną techniką, ponieważ model nawet na jednym bądź kilku przykładach jest w
stanie wychwytywać różnego rodzaju wzorce i dostosować odpowiednio swoje zachowanie.
W niektórych przypadkach może się nawet
okazać tak, że łatwiej będzie podać kilka dobrych przykładów, zamiast pisać
rozbudowany opis tego, w jaki sposób dane zadanie ma zostać wykonane.
Tutaj jednak warto brać pod uwagę, że same
przykłady muszą być w odpowiedni sposób dobrane, tak aby możliwie poprowadzić
model do poprawnego rozwiązania, ale jednocześnie nie sugerować mu czegoś, co
może być niezgodne z naszymi oczekiwaniami.
Taka sytuacja może mieć miejsce np.
wtedy, jeżeli podane przykłady będą
wchodziły w bezpośredni konflikt z tym, co zostało podane w kontekście.
Wówczas model może pomylić zarówno
kontekst, jak i przykłady i udzielać odpowiedzi na podstawie danych
dostarczanych tutaj, a nie na podstawie faktycznego kontekstu, który powinien
zostać wykorzystany do udzielenia odpowiedzi.
Warto o tym pamiętać i także pokażę kilka sposobów, jak można sobie z tym radzić.
I teraz jeżeli chodzi o następny element
naszego promptu, to mamy pytanie użytkownika.
Tutaj zwykle mówimy albo o krótkim pytaniu, albo nawet jakiejś wypowiedzi
uwzględniającej dodatkowy kontekst, na podstawie którego użytkownik oczekuje
rozwiązania zadania w bardzo konkretny sposób.
Oznacza to, że teoretycznie może dojść do
sytuacji, w której będziemy posiadali kontekst w tym miejscu,
przykłady tutaj, a także sam użytkownik
może dostarczyć nam dodatkowych kontekst oraz dodatkowe przykłady.
Z tego powodu bardzo istotne jest to, aby przy planowaniu promptu uwzględnić fakt,
że możemy mieć tutaj do czynienia z naprawdę różnego rodzaju
zestawami informacji.
Co więcej, czasem może zdarzyć się tak, że użytkownik będzie chciał złamać nasz
prompt i doprowadzić do sytuacji, w której ten powyższy blok nie będzie miał
znaczenia i tym samym w generowanych odpowiedziach będzie widoczne zupełnie
inne zachowanie niż to, które pierwotnie planowaliśmy.
Coś takiego nazywamy mianem Adversarial Prompting, bądź też tzw.
Prompt Injection, czyli niczym innym jak po prostu atakiem na nasz prompt.
Na dzień nagrywania tego materiału istnieją co prawda pewne techniki, które
zmniejszają prawdopodobieństwo wystąpienia takiej sytuacji, natomiast równolegle
pojawiają się także techniki, które są w stanie łamać takie zabezpieczenia.
Ostatecznie to wszystko sprawia, że
zaprojektowanie promptu, który w pełni oraz zawsze będzie realizował założone
zadania jest aktualnie niezwykle trudne i wymaga tutaj wysiłku zarówno po stronie
projektowania samego promptu, ale także mechanizmów programistycznych.
Idąc jednak dalej ze strukturą promptu,
ostatnią rzeczą, którą również musimy brać tutaj pod uwagę jest samo
dopełnienie, czyli zasadniczo jest to tekst wygenerowany przez model.
On także odgrywa tutaj niesamowicie istotną rolę, ponieważ całość stanowi tak
zwany Context Window bądź też Token window.
Konkretnie mówimy tutaj o wspominanym
przeze mnie już ograniczeniu przetwarzanych tokenów dla pojedynczego zapytania.
Przypominam, że dla modelu GPT-3,5-Turbo mówimy o 4 tysiącach tokenów, dla GPT-4 są
to odpowiednio 8 bądź 32 tysiące tokenów w zależności od wersji,
no i jako ciekawostkę dodam, że pojawił się także dodatkowy model od firmy Anthropic,
który jest w stanie obsługiwać nawet 100 tysięcy tokenów, aczkolwiek sam osobiście
nie miałem tego okazji jeszcze przetestować.
Tak czy inaczej wiele wskazuje na to, że w przyszłości ograniczenie w postaci liczby
tokenów nie będzie już dla nas tak istotne pod kątem samego ograniczenia,
aczkolwiek podejrzewam, że jeżeli chodzi o
model rozliczeń, nadal będzie opierał się o tokeny
a to może oznaczać, że w dalszym ciągu
będzie nam zależało na zachowaniu zwięzłości.
Zatem podsumowując sama struktura promptu
może wyglądać w taki oto sposób, aczkolwiek zaznaczam, że poszczególne
bloki są tutaj raczej opcjonalne. No bo przykładowo bardzo często może zdarzyć się
nawet tak, że będziemy mieć tylko pytanie oraz wygenerowany odpowiedź.
Samo nadawanie roli, instrukcji, kontekstów czy przykładów jest w
niektórych przypadkach po prostu zbędne. Innym razem bez ich obecności rozwiązanie
konkretnego zadania w skuteczny sposób jest zwyczajnie niemożliwe.
Proponuję więc, abyśmy zakończyli sobie teraz tą lekcję, a następnie przeszli do
przeanalizowania tej struktury promptu na rzeczywistym przykładzie.