Połącz możliwości GPT-3 i automatyzacji
2 godz. 3 min · OpenAI · Biznes i Automatyzacje
Adam GospodarczykWykorzystanie API OpenAI nie różni się w żaden sposób od innych. Przesyłając dane i parametry na wskazany endpoint, otrzymujemy odpowiedź wygenerowaną przez model (np. text-da-vinci-003). Na tym jednak możliwości tego API się nie kończą. Przykładem z którego skorzystamy będzie zamiana danych na tzw. embedding (listę wektorów). Dane zapisane w takiej formie będą wstępem do "pamięci" bota i tym samym pierwszym punktem procesu nauki.
Prompt Engineering to rozwijająca się dziedzina skupiona na projektowaniu systemów zdolnych do skutecznego reagowania na dane wprowadzone przez użytkownika. W przypadku tworzonego przez nas bota, wykorzystamy pewne elementy tego procesu aby zmodyfikować jego domyślne zachowanie oraz przygotowywanie odpowiedzi na podstawie wyłącznie wcześniejszych danych. W przypadku braku wiedzy na jakiś temat, bot będzie nas o tym informował w sarkastyczny sposób lub nawet zwracał informacje w podanym przez nas formacie.
Wysyłając zapytanie do API OpenAI, jesteśmy ograniczeni liczbą znaków. Tworząc bota chcemy uwzględniać nie tylko to aby odpowiadał na nasze pytania ale także uwzględniał przekazany przez nas kontekst, składający się z informacji jakie zapamiętał bot. Problemem jest tutaj wybór, które dane ma brać pod uwagę. Rozwiązanie po które sięgamy w tym warsztacie polega na wykorzystaniu bazy wektorowej (Pinecone), która pełni rolę pamięci oraz bazy lokalnej w której przechowujemy faktyczne informacje. Ich połączenie pozwala na wybranie najbardziej istotnych danych i uwzględnienie ich w kontekście, który pozwoli GPT-3 przygotować odpowiedź.
Temat wykorzystania AI w codziennym życiu nie jest nowy ale nabrał szczególnego znaczenia po pojawieniu się ChatGPT. Wiele osób zaczęło wykorzystywać AI do rozwiązywania bieżących problemów i ułatwiania sobie różnych zadań. W tym warsztacie znajdziesz kilka inspiracji, które nakierują Cię na to jak możesz rozwijać swojego własnego, inteligentnego i uczącego się bota.
Warsztat został stworzony z myślą o osobach znających JavaScript i Node.js, chcących postawić pierwsze kroki w praktycznym wykorzystaniu GPT-3 oraz API OpenAI. Poza znajomością JavaScript, konieczne będzie minimum doświadczenia w pracy z API oraz bazami danych (SQL). Po ukończeniu tego warsztatu zyskasz ogólne zrozumienie możliwości GPT-3 oraz umiejętności umożliwiające wpływ na jego zachowanie i generowane odpowiedzi.
W tej lekcji zajmiemy się jednym z dwóch
najważniejszych elementów logiki naszego avatara.
Mowa o zapamiętywaniu.
Wykorzystamy w tym celu wspomniane już
przeze mnie rozwiązanie Picecone, czyli tak zwaną bazę vectorową.
Wewnątrz niej będziemy zapisywać wszystkie informacje, które musi zapamiętać nasz
avatar i aby to zrobić musimy zamienić je na postać vectorową.
Czyli w dużym uproszczeniu na zestaw liczb.
Takie liczby zostaną osadzone w przestrzeni trójwymiarowej tej bazy i
dzięki temu w późniejszym czasie, gdy będziemy chcieli, aby nasz avatar
odpowiadał na jakieś pytania, będziemy mogli skorzystać z Pinecone
po to, aby odnaleźć najważniejsze
informacje, które są niezbędne do tego, aby udzielić odpowiedzi.
Dobra wiadomość jest tutaj taka, że na tym
etapie nie musisz do końca wiedzieć jak działa Pinecone oraz czym są bazy vectorowe.
W praktyce będziemy korzystać z bardzo prostych poleceń, takich jak np.
Upsert, czyli możliwość wgrania nowego old recordu albo zaktualizowania istniejącego.
Poza tym będzie nam jeszcze potrzebne
usuwanie oraz wyszukiwanie recordów na podstawie bieżącego zapytania.
Przez wszystko będziemy tutaj przechodzić.
Natomiast chciałbym tylko, aby stało się dla Ciebie jasne, że zawsze w momencie,
gdy jako użytkownicy będziemy chcieli, aby avatar zapamiętał jakieś informacje
pochodzące od nas, to te informacje w formie tekstowej zostaną zapisane w Airtabel.
Następnie z pomocą API OpenAI zamienimy je na tzw.
embedding, czyli listę vectorów.
Inaczej mówiąc, zapiszemy je w postaci liczbowej i umieścimy w bazie Pinecone
cały schemat, który widać teraz na ekranie, zrealizujemy w tej lekcji.
Przejdźmy więc teraz do naszego głównego scenariusza.
Wiemy już, że dolna ścieżka zostanie
zrealizowana w chwili zapisywania informacji do Airtable, a następnie Airtable
uruchomi ten scenariusz ponownie przepuszczając scenariusz
górną ścieżką, wewnątrz niej będziemy
chcieli zrealizować trzy dodatkowe ścieżki.
Jedną z nich będzie zapamiętywanie, czyli
dokładnie schemat, który omówiliśmy przed chwilą.
Drugą będzie odpowiadanie, a trzecią zapominanie.
Zatem w tym momencie skupimy się na tym pierwszym.
Ta ścieżka zostanie zrealizowana w
momencie, gdy zostanie spełniony następujący warunek.
Mianowicie właściwość type musi być ustawiona na remember.
W związku z tym, że na tym etapie
informacja jaką dysponujemy to record Airtable, musimy w pierwszej kolejności
połączyć się z naszą bazą, a następnie pobrać przesłany tutaj record.
W moim przypadku będzie to 4 kropka Record ID.
Domyślam się, że jeżeli tworzysz
scenariusz od podstaw, pierwszy moduł będzie miał identyfikator 1.
W związku z tym, chcąc odwołać się do tej
wartości, musisz zapisać ją w następującej formie.
Aby dowiedzieć się szybko, której identyfikator posiada nasz pierwszy moduł,
możesz zwrócić uwagę na liczbę znajdującą się w tym miejscu.
Teraz zapisuję zmiany, więc na tym etapie
będę już dysponował informacjami w formie tekstowej, które muszę zamienić na liczbę.
Aby to zrobić muszę w pierwszej kolejności
wyszukać modułu JSON i tutaj wybrać akcję Create JSON.
W tym momencie musimy utworzyć tutaj nową strukturę danych i będzie nią Avatar Embedding.
Zamiast wyklikiwać całą specyfikację, skorzystamy tutaj z opcji generowania, do
której wklejamy następujące obiekt JSON.
Strukturę tego obiektu dołączam do
materiałów tej lekcji, które powinny właśnie wyświetlać się na ekranie.
Po zapisaniu zmian mamy tutaj gotową
strukturę i tylko zaznaczę, że te pola są wymagane oraz ustawi wartość domyślną dla
pola Model na nazwę modelu, którym będziemy się posługiwać.
W tym przypadku będzie to Text Embedding ada 002.
Aczkolwiek w momencie oglądania tego filmu
sprawdź proszę czy nie pojawiła się jakaś nowsza wersja.
Zapisuję więc zmiany i teraz pojawia się
nasza struktura, wewnątrz której musimy przekazać content oraz dodatkowo tagi.
W tym momencie same tagi będą pustym
polem, ale zajmiemy się nimi w następnej lekcji.
Teraz kolejnym krokiem będzie nawiązanie
połączenia z API OpenAI poprzez moduł HTTP oraz akcję Make a Request.
Tutaj jako URL przekazujemy następującą wartość, a następnie ustawiamy metodę na
post i nagłówek authorization ustawiony na Bearer, a następnie nasz klucz OpenAI.
Teraz musimy określić rodzaj przesyłanych informacji i w naszym przypadku będzie to
przed chwilą utworzony obiekt JSON, który przekazujemy w następujący sposób.
Ostatnim ustawieniem, o które chcemy tutaj
zadbać będzie sparsowanie naszej odpowiedzi tak, aby od razu była dla nas dostępna.
I teraz tylko zadbam o odpowiednie nazwy naszych modułów i możemy przetestować
sobie naszą automatyzację uruchamiając ją w tryb nasłuchiwania.
Teraz tylko przejdę do Airtabel, wewnątrz
którego zapiszę jakąś informację, a następnie wcisnę Sync.
Nasz scenariusz powinien w tym momencie
zostać uruchomiony no i faktycznie tak się stało.
Na nasz webhook został przesłany typ
wykonywanej w danej chwili operacji oraz identyfikator recordu Airtable, który
wykorzystaliśmy dokładnie w tym miejscu, aby pobrać sobie
treść naszego wpisu.
Tą treści możemy teraz wykorzystać do
utworzenia obiektu JSON, a następnie wysłania zapytania do naszego API.
Jeżeli zobaczymy tutaj na odpowiedź,
wewnątrz jej znajdziemy właściwość Data, a następnie listę naszych vectorów.
Zwróć uwagę, że tekst jestem Overment został zapisany w takiej oto formie.
No i teraz to, co musimy zrobić, to
wykorzystać dokładnie tą informację po to, aby przekazać ją do Pinecone.
Przechodzę więc do kolejnego modułu, z
pomocą którego utworzymy sobie kolejny obiekt JSON, który będzie reprezentował
strukturę potrzebną do tego, aby zapisać nowe dane w Pinecone.
Tutaj również skorzystamy z generatora
oraz obiektu JSON, który dołączam do zasobów tej lekcji.
Po zapisaniu zmian ponownie musimy tutaj oznaczyć wymagane pola i w tym przypadku
będzie to zarówno identyfikator jak i sama tablica wartości.
No i teraz zapisujemy te zmiany i dodajemy nowy vector. Jako identyfikator
musimy podać tutaj identyfikator recordu
Airtable i dokładnie to samo zapisujemy w sekcji Meta data.
Poza tym musimy uzupełnić także tagi.
Jeżeli chodzi o taką formę zapisywania informacji, jest ona szczególnie istotna w
kontekście późniejszej pracy z naszym avatarem.
Mianowicie, tak jak już powiedziałem,
wewnątrz Pinecone będziemy zapisywać listę vectorów.
Możemy to zrobić poprzez ten przełącznik,
a następnie przekazanie tutaj całej tablicy Embedding.
Oczywiście możesz zmienić to, w jaki sposób przechowujesz dane w Pinecone,
Natomiast najważniejsze jest tutaj to, aby metadane służyły temu, aby móc powiązać
recordy znajdujące się w Airtable z informacjami, które zapisaliśmy w Pinecone
po prostu na podstawie liczb nie będziemy
w stanie tego zrobić, a metadane sprawdzą się w tym celu idealnie.
Tym bardziej, że będziemy w stanie
wykorzystać funkcję Pinecone po to, aby wybierać tylko te vectory, których
metadane spełniają określone przez nas warunki.
Zapisuję więc teraz nasz obiekt JSON i
wykorzystuje kolejny moduł HTTP po to, aby przesłać informację do Pinecone.
Zanim to jednak będzie możliwe, musimy
podać tutaj adres URL kierujący do naszej bazy.
W związku z tym przechodzimy do panelu Pinecone, a następnie logujemy się na swoje konto.
Tutaj Ja już przeszedłem przez ten proces i nie będę go teraz powtarzał.
Natomiast w Twoim przypadku kliknij
przycisk Create index, a następnie wpisz nazwę np.
Avatar. Jeżeli chodzi o liczbę recordów wpisujemy
tutaj 1536 i jest to informacja pochodząca bezpośrednio z dokumentacji OpenAI,
ponieważ dokładnie tyle wymiarów generowane jest przez ich API.
Tutaj wybieramy także Pod Type i w moim przypadku niemal zawsze korzystam
dokładnie z tej opcji, a następnie wybieramy Create Index.
Ja oczywiście nie mogę tego zrobić na bezpłatnym koncie, natomiast po utworzeniu
indeksu po chwili pojawi się tutaj ten adres, który musimy skopiować do make.
Zatem zapisuję tutaj https, a następnie wklejam ten adres.
Potem umieszczam slash i zapisuję vectors, a następnie slash
upsert, czyli dokładnie tak jak wspominałem, akcja upsert służy temu, aby
albo zaktualizować istniejący record, bądź też utworzyć nowy.
Tutaj również musimy ustawić na wartość, którą zapisaliśmy w zmiennej wcześniej.
Ostatnim krokiem będzie przesłanie ciała zapytania.
I tutaj również mamy do czynienia z
obiektem JSON, który utworzyliśmy przed chwilą.
Zaznaczam więc jeszcze parsowanie odpowiedzi no i zapisuję zmiany.
W tym momencie nasz scenariusz powinien
zadziałać już tak, że przy synchronizacji recordu jego wartość powinna zostać
pobrana zamieniona na Embedding, a następnie zapisana w Pinecone.
W momencie, gdy to się wydarzy, powinniśmy zaktualizować record, który właśnie
synchronizujemy i oznaczyć go jako synchronizowany.
Czyli dokładnie wybieram tutaj
identyfikator recordu, na którym pracujemy i oznaczam jego opcję sync na nie.
Dzięki temu efekt będzie taki, że jeżeli
zapiszę scenariusz i uruchomię go w tryb nasłuchiwania, a następnie wrócę do Airtable,
to jeżeli oznacze synchronizację tego recordu, scenariusz zostanie
uruchomiony, a dane zostaną synchronizowane z Pinecone.
Wygląda na to, że mamy tutaj jakiś błąd.
Record nie został odnaleziony i
prawdopodobnie wynika to z faktu, że wkradła nam się tutaj spacja.
Zatem wracam teraz do Airtable do zakładki
Automatyzacja i tutaj sprawdzamy, że rzeczywiście spacja tutaj jest.
W związku z tym usuwałem ją, zapisuję
zmiany, aktualizuje scenariusz i raz jeszcze synchronizuje record.
Przy czym muszę upewnić się, że scenariusz czeka na jakieś informacje.
Oznaczam więc to pole, czekam chwilę i zaznaczam ponownie.
Teraz scenariusz powinien zostać wykonany poprawnie, no i wygląda na to, że wszystko
poszło tutaj w porządku, aczkolwiek musimy to zweryfikować.
Możemy to zrobić patrząc tutaj na status odpowiedzi.
Jeżeli jest ustawiony na 200 bądź 201, to wszystko powinno być w porządku.
Jednak w tym przypadku mamy tutaj odpowiedź 400,
jeżeli zobaczymy o co tutaj chodzi, mamy tutaj wiadomość not supported value type.
Oznacza to, że przy przesyłanych danych coś poszło nie tak.
Prawdopodobnie przyczyną naszego problemu jest fakt, że nie posiadamy tagów, a
konkretnie ustawione są one na wartość Null.
W związku z tym wrócimy do tworzenia Embeddingu,
a następnie zapiszemy tutaj warunek if, czyli pisze if
otwieram nawias, a następnie sprawdzam czy
pole tags istnieje oraz tym samym czy posiada jakąkolwiek wartość.
Jeżeli tak, to umieszczamy tutaj to pole.
W przeciwnym razie pomijamy je.
Dokładnie ten sam schemat musimy
wykorzystać w tym module na etapie przekazywania tagów.
W tym przypadku nie możemy jednak zostawić pustej wartości.
W związku z tym zapiszemy no value.
I teraz, po zapisaniu zmian i uruchomieniu scenariusza ponownie powinniśmy móc
dokonać jeszcze jednej synchronizacji recordu.
Zwróć uwagę, że pole sync w tym przypadku
zostało odznaczone, więc wykonuje je ponownie, ale co więcej, stało się to
nawet pomimo tego, że w tym module wystąpił błąd.
Oczywiście możesz zmodyfikować ten scenariusz w taki sposób, aby obsługiwać
sobie błędy, natomiast my nie będziemy się w tym momencie tym zajmować.
Na ten moment najważniejsze jest to, że mamy tutaj status 200, a dodatkowo
informacja o tym, że record został umieszczony w naszym indeksie.
Jeżeli teraz przejdziemy do Pinecone, to
zobaczymy, że w naszym panelu wewnątrz indeksu, na którym właśnie pracujemy
powinna pojawić się informacja o tym, że mamy zapisane jeden vector.
Pamiętaj proszę o tym, że wczytanie tej danej zajmuje chwilę i początkowo mylnie
może wskazywać na to, że żadne dane nie pojawiły się w naszym indeksie.
Na szczęście wystarczy tylko chwilę poczekać i wszystko będzie w porządku.
Wygląda więc na to, że podstawowy scenariusz zapamiętywania mamy już gotowe.
Jak widzisz, dotychczasowy schemat polega
na tym, że za każdym razem, gdy chcemy zaktualizować bądź dodać nowe informacje,
przesyłamy je na Webhook z typem ustawionym na save.
Dane zostają zapisane w Airtable, a
następnie z pomocą automatyzacji wykonywane jest zapamiętywanie i
scenariusz wykonuje się ścieżką, która odpowiada za synchronizację informacji
znajdujących się w Airtable z vectorami zapisanymi bezpośrednio w Pinecone.
Na koniec oznaczamy record jako
zaktualizowany i cały mechanizm jest gotowy.
Teoretycznie moglibyśmy zostawić ten schemat dokładnie tak, jak jest teraz,
natomiast pokażę Ci jeden z możliwych sposobów na to, aby zwiększyć szanse na
to, że nasz avatar odnajdzie pożądaną przez nas informacja.
Tym jednak zajmiemy się w kolejnej lekcji.