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.
Zbliżamy się już powoli do końca naszego kursu dotyczącego projektowania promptów.
Z tego powodu, niezależnie od tego czy programujesz czy nie
chciałbym na chwilę zabrać Cię do małej aplikacji, dzięki której pokażę Ci w jaki
sposób może wyglądać praktyczne zastosowanie Twoich promptów
wykraczające poza pracę z ChatGPT .
Oczywiście zaznaczam tutaj, że wszystkie techniki, których do tej pory się
nauczyliśmy, mają zastosowanie w ChatGPT oraz także mogą sprawdzić się w
przypadku innych modeli, z którymi przyjdzie Ci pracować.
Oczywiście mogą tam wystąpić różnego rodzaju różnice dotyczące np.
schematu promptu bądź różnych zachowań modelu,
natomiast ogólne zasady według moich doświadczeń pozostają raczej takie same.
Przechodząc teraz już do głównego tematu
naszej lekcji, będę zakładać, że nie potrafisz programować
w związku z tym postaram się wszystko przedstawiać możliwie jak najłatwiej.
Aplikacja, którą tutaj mamy została stworzona z pomocą frameworka LangChain,
o którym wspominałem już na przestrzeni wcześniejszych lekcji.
Podkreślam tylko, że jest to naprawdę
podstawowe zastosowanie tego frameworka, polegające na tym, aby móc nawiązać
połączenie w tym przypadku z modelem GPT-4 oraz dodatkowo wykorzystać długoterminową
pamięć naszego modelu, którą zapisane w pliku txt.
Jak widzisz, mamy tutaj kilka podstawowych
faktów na mój temat, które stanowią pamięć długoterminową naszego asystenta.
Oznacza to, że będę mógł o nie pytać bez
konieczności samodzielnego podawania ich w prompcie.
O to, aby te informacje pojawiły się
faktycznie w moim prompcie, zadba kod mojej aplikacji.
Zatem teraz po prostu ją sobie uruchomię, a następnie po prostu skontaktuję się z
moją aplikacją i zadam pytanie czy też w tym przypadku po prostu się przywitam.
Zapytanie zostało wykonane i tutaj na dole mamy odpowiedź, która w sposób bezpośredni
potwierdza nawiązanie połączenia z OpenAI.
Dodatkowo tutaj po prawej stronie mamy coś, co przypomina nasz prompt.
Jest to dokładnie treść, którą mogliśmy
spotkać na przestrzeni poprzednich lekcji i dodatkowo mamy tutaj także kontekst
zawierający dokładnie te informacje, które miałem zapisane w zewnętrznym pliku.
Jeżeli teraz zajrzymy sobie do kodu naszej
aplikacji, to w pewnym momencie zauważymy, że faktycznie mamy tutaj zapisany nasz
prompt o treści dokładnie takiej samej, która wyświetla nam się po prawej stronie.
Za napisanie takiego promptu odpowiada
oczywiście osoba, która się w tym specjalizuje, natomiast rolą programisty
jest wykorzystanie go w taki sposób, aby wstrzykiwać do niego dynamiczne
informacje, które w tym przypadku zostały odnalezione wewnątrz pliku przechowującego
wspomnienia, a następnie zostały odpowiednio dołączone.
Rezultat tego jest taki, że po prostu jako
użytkownik zadaję pytanie i tak naprawdę na tym moja interakcja się kończy. I tak
naprawdę to wystarczy do tego, abym uzyskał odpowiedź.
Oczywiście w tej chwili ona wyświetla się
w moim edytorze kodu, natomiast normalnie wyobraźmy sobie okienko czatu, w której
użytkownik przychodzi, wita się i otrzymuje odpowiedź o następującej treści.
Natomiast to co się dzieje pod spodem jest tak naprawdę poza jego wzrokiem.
W tym przypadku jest to konkretnie nadanie
całego promptu, który definiuje zachowanie asystenta
a dodatkowo mamy tutaj mechanizm odpowiedzialny za wspomnienia.
Naturalnie, jeżeli teraz zadam pytanie o
to kim jest Overment, to odpowiedź wykorzysta wszystkie informacje z
kontekstu i tym samym będzie jak najbardziej poprawna.
Jeżeli jednak zadam pytanie, które będzie wykraczało poza ten kontekst, to zgodnie
ze zdefiniowanym promptem nasz asystent odpowie, że nie wie,
a dodatkowo, gdy zobaczymy sobie teraz jak
wygląda nasz wczytany prompt, to wewnątrz niego tym razem kontekst jest pusty.
Wynika to z faktu, że mechanizm
odpowiedzialny za wyszukiwanie odpowiednich wspomnień w tym momencie nie
znalazło niczego, co mogłoby pomóc w udzieleniu odpowiedzi.
Dla Ciebie, jako osoby projektującej prompty
oznacza to mniej więcej tyle, że przy
wczytywane dynamicznie kontekście należy uwzględnić zaprojektowanie instrukcji w
taki sposób, aby była w stanie obsłużyć taką sytuację.
Poza tym musisz mieć także na uwadze fakt,
że wewnątrz tego kontekstu mogą się także pojawić informacje, które nie przekładają
się bezpośrednio na zwiększenie jakości odpowiedzi, a w związku z tym model musi
zostać o tym poinformowany, aby nie doprowadzić do tego, by błędnie odpowiadał
na pytania, wykorzystując niewłaściwy kontekst.
Co więcej, za właściwe dobieranie
kontekstu odpowiadają nie tylko programiści, ale także osoby
przygotowujące zestawy danych, na których pracuje aplikacja.
Osoby projektujące prompty nierzadko będą brały udział w tym procesie albo w ogóle
to one będą odpowiedzialne za jego przeprowadzenie.
To właśnie z tego powodu, niezależnie od tego, czy programujesz, czy nie,
postanowiłem pokazać Ci, jak to wygląda od drugiej strony.
Po prostu zawsze musisz mieć na uwadze fakt, że jeżeli Twoje prompty będą
wychodziły poza ChatGPT i będą integrowane z jakimiś aplikacjami, to z dużym
prawdopodobieństwem będą uwzględniały jakiś rodzaj personalizacji.
W tym przypadku mówimy tutaj o dynamicznie wczytywanym kontekście, a
innym razem mogą być to np.
informacje na temat użytkownika, bądź też w ogóle wczytywanie innych fragmentów
promptu, które będą zmieniały jego zachowanie w zależności od tego np.
gdzie znajduje się użytkownik w ramach naszej aplikacji.
Według moich doświadczeń i praktycznie każdej opinii, z którą spotkałem się w
Internecie, najważniejszym elementem wdrażania narzędzi takich jak GPT-4 do
aplikacji jest odpowiednie przygotowanie danych, które uwzględnia nie tylko ich
opracowanie, ale także odpowiednie otagowanie,
no i oczywiście sam proces wyszukiwania,
który w tym przypadku również nie jest przypadkowy i opiera się o tzw. Embedding
oraz związany z nim tzw.
Similarity Search, czyli wyszukiwanie podobieństw.
Jeżeli chodzi o szczegóły techniczne
dotyczące tego zagadnienia, to wykraczają one poza zakres tego kursu
w związku z tym nie będziemy się nimi zajmować.
Z Twojego punktu widzenia istotne jest to,
że dane wczytywane dynamicznie do kontekstu muszą być jakoś odnalezione, a
Twój prompt musi być zaprojektowany w taki sposób, aby był w stanie z nimi pracować.
Jednym z elementów takiego przygotowania jest wyraźne oddzielenie fragmentów
wczytanego dynamicznie kontekstu od reszty naszego promptu.
W tym konkretnym przypadku zastosowałem takie separatory
natomiast tak jak mówiliśmy w poprzednich lekcjach, to jaki separator wybierzesz
zależy bardzo mocno od zestawu danych, z którymi pracujesz.
Mam nadzieję, że ta lekcja i przykład tej
bardzo prostej aplikacji zarysowały Ci nieco szerszy kontekst, z którym z
pewnością będziesz mieć do czynienia w swojej pracy.
No i oczywiście na koniec dodam, że jeżeli programujesz i znasz środowisko Node.js,
to kod do tej aplikacji, dołączam do materiałów dodatkowych do tej lekcji.
Aby uruchomić ten projekt jedyne co musisz zrobić to zainstalować zależności oraz w
pliku dotenv uzupełnić swój klucz API do OpenAI.
Następnie mając to wszystko przed pierwszym uruchomieniem aplikacji w pliku
context.txt uzupełnij dane, na które chcesz pracować.
Wówczas aplikacja przy pierwszym uruchomieniu je wczyta, a następnie będzie
w stanie wykorzystywać je w dynamicznym kontekście.
Aby zresetować te dane, musisz w pierwszej
kolejności usunąć katalog store.index oraz ponownie uruchomić aplikację.
Jeżeli chodzi o tą lekcję to by było na tyle.
Dziękuję Ci więc za uwagę i do usłyszenia następnym razem.