Menu
O mnie Kontakt

Jakub 'unknow' Mrugalski z UW-TEAM.org przedstawia w swoim wideo, że korzystanie z baz wektorowych nie wymaga zaawansowanej wiedzy technicznej. Podkreśla, że wystarczy umiejętność uruchomienia kontenera Docker oraz komunikacja za pomocą prostego API JSON. W ciągu kilku minut może pokazać, jak skutecznie wykorzystać lokalną bazę QUADRANT, cojest szczególnie istotne dla rozwoju aplikacji. Rozpoczynają od uruchomienia kontenera Dockerowego z bazą danych QUADRANT, gdzie ważne jest najpierw przygotowanie katalogu do przechowywania danych.

Po uruchomieniu kontenera i upewnieniu się, że wszystko działa prawidłowo, Jakub przechodzi do interfejsu użytkownika, gdzie prezentuje kluczowe funkcje bazy. Zaczyna od założenia nowej kolekcji bazy danych metodą PUT, co jest intuicyjne, i wyjaśnia, jak dodawać nowe wektory do bazy. Wytłumacza także różnicę między różnymi metodami i ich zastosowaniem, a także podkreśla znaczenie poprawnego formatu dla dodawanych wektorów. To wszystko dzieje się w kontekście użycia najpopularniejszych algorytmów porównawczych.

Jakub kontynuuje, pokazując jak stworzyć pierwszą kolekcję i jak dodawać dane do kwadrantu z pliku tekstowego. Odcinek zawiera istotne informacje na temat konwersji tekstu na wektory oraz jak obsługiwać odpowiedzi API w PHP. Dzięki bibliotekom KWADRANT.PHP i EMBEDDING.PHP, widzowie mogą łatwo implementować funkcjonalność w ich własnych projektach. Jakub wyjaśnia również, skąd wziąć odpowiednie parametry dla modeli AI, które będą używane do generowania embeddingów, co jest kluczowym aspektem w pracy z bazami wektorowymi.

Kończąc prezentację, Jakub pokazuje, jak wykonać zapytania do bazy danych przy użyciu naturalnego języka. To ważny krok, ponieważ umożliwia interakcję z bazą tak, jakby rozmawiało się z człowiekiem, eliminując potrzeby skomplikowanych zapytań. Zauważa, że nawet gdy występują błędy w gramatyce lub literówki, baza nadal rozumie zapytanie i dostarcza odpowiedzi. To ukazuje potęgę baz wektorowych, które odpowiadają semantycznie, a nie tylko na podstawie dosłownego wyszukiwania.

Na koniec, Jakub zaprasza widzów do uczestnictwa w szkoleniu AIDevs, gdzie nauczy się nie tylko komunikacji z bazami wektorowymi, ale także inne praktyczne techniki programistyczne. W chwili pisania tego artykułu, wideo ma 9011 wyświetleń i 391 polubień, co świadczy o dużym zainteresowaniu tym tematem. Jakub łączy teorię z praktycznymi przykładami, co zdecydowanie ułatwia zrozumienie złożonych zagadnień związanych z nowoczesnymi bazami danych.

Toggle timeline summary

  • 00:00 Wprowadzenie do baz danych wektorowych i ich użyteczności bez głębokiego zrozumienia.
  • 00:05 Porównanie używania baz danych wektorowych do używania baz danych SQL bez znajomości ich wewnętrznego działania.
  • 00:11 Proces uczenia się wymaga dwóch kluczowych umiejętności: uruchamiania kontenera Docker i interakcji z API JSON.
  • 00:19 Obiecana demonstracja konfiguracji lokalnej bazy danych w QUADRANT przy użyciu Dockera.
  • 00:27 Tworzenie katalogu dla bazy danych QUADRANT w celu przechowywania danych.
  • 00:41 Polecenie Docker run z opcjami do uruchomienia QUADRANT w tle.
  • 01:16 Sprawdzanie, czy baza danych QUADRANT działa i jest dostępna przez zdefiniowany port.
  • 01:31 Eksploracja interfejsu internetowego QUADRANT, obserwacja kolekcji i danych wektorowych.
  • 01:47 Instrukcje dotyczące tworzenia nowej kolekcji za pomocą metody PUT.
  • 02:04 Dodawanie nowych wektorów do bazy danych za pomocą strukturalnego wywołania API.
  • 02:41 Ustawienie operacji wyszukiwania przy użyciu metody POST z parametrami do dopasowania wektorów.
  • 03:18 Tworzenie nowej kolekcji o nazwie 'Wiedza' z określonymi parametrami.
  • 04:08 Użycie PHP do obsługi żądań w celu tworzenia i zarządzania kolekcjami.
  • 06:11 Wstawianie rekordów do bazy danych wektorowej z przygotowanego pliku tekstowego.
  • 10:12 Pomyślnie zapytano bazę danych w języku naturalnym i otrzymano odpowiednie odpowiedzi.
  • 13:15 Podkreślenie semantycznej natury baz danych wektorowych w porównaniu do wyszukiwania leksykalnego.
  • 13:27 Zaproszenie na program szkoleniowy dotyczący pracy z bazami danych wektorowymi i budowania agentów.

Transcription

Jest jedna dobra wiadomość, wcale nie musisz wiedzieć, jak bazy wektorowe działają pod spodem, aby z nich korzystać. Podobnie jak, nie wiesz na przykład, jak działają algorytmy, załóżmy, w Postgresie, MySQL-u czy Oracle-u. W takim razie, jak się tego nauczyć? Potrzebujesz tylko znaleźć dwie rzeczy. Pierwsza rzecz to jest, jak odpalić kontener dockerowy, a druga rzecz, jak porozumiewać się z prostym API JSON-owym. I jeżeli to upanujesz, to w zasadzie jesteś w stanie korzystać z baz wektorowych. A ja chcę Ci pokazać, jak to zrobić dosłownie w kilka minut. To co? Idziemy do terminala. Wykorzystamy do tego celu lokalną bazę danych, zwaną QUADRANT. Pisze się to QUDRANT. QUADRANT-a uruchomimy jako obraz dockerowy i gdzieś on musi trzymać dane. Chciałbym, aby trzymał to w katalogu, więc założę sobie tutaj katalog mkdir QUADRANT, podaję ENTER, a następnie uruchamiam dockera. Standardowo DOCKER RUN. Chcę, żeby to działało w tle, więc MINUS D. A następnie wystawiam porty. PORT 6333, to jest standardowy port QUADRANT-a. I następnie podaję, co chcę zamontować jako volumen. Aktualny katalog, łamany przez QUADRANT. I jest to ten katalog, który przed chwilą właśnie założyłem. Tam będą trzymane dane. Muszę to podmontować do aplikacji, do SLASH QUADRANT, łamane przez STORAGE. Tam po prostu ta nasza baza danych trzyma swoje dane związane z wektorami. I teraz podaję nazwę obrazu, czyli to jest QUADRANT, łamane przez QUADRANT. To powinno być OK, jeżeli się nie pomyliłem. Naciskam tylko ENTER i rozpoczyna się ściąganie obrazu, ponieważ nie mam go lokalnie na dysku zainstalowanego. Poczekamy chwilę. I mamy swoją bazę danych uruchomioną. Sprawdźmy tylko, czy na pewno wszystko działa. DOCKER PS, tak mamy wystawione, jest OK. I widzę tutaj PORT 633. Jest on jak najbardziej dostępny, a znajduje się na nim WEB UI do zarządzania bazą danych. Będziemy tu widzieć wszystkie nasze kolekcje, czyli bazę danych, jak i wektory, czyli rekordy w nich znajdujące się. Jest tam też mini dokumentacja do API, która pomoże nam rozpocząć pracę z QUADRANTem. Klikamy na QUICK START i widzimy tutaj kilka możliwości. Na początku musimy założyć kolekcję, czyli bazę danych. I robić to bardzo prosto metodą PUT. Wysyłamy sobie do SLASH COLLECTIONS. I ta nazwa na końcu, TEST COLLECTION, to jest po prostu nazwa bazy danych. Rozmiar kolekcji, co to jest, potem powiem. Oraz metoda porównywania dystansów. Tutaj domyślna jest DOT, my użyjemy czegoś innego. Mamy tutaj już dodawanie nowych wektorów, a więc nowych rekordów do bazy. To podobnie jak przed chwilą, realizuje się metodą PUT. I wysyłamy tutaj zapytanie do takiego ENDPOINTA. Tutaj co jest ważne. SLASH COLLECTIONS i następnie nazwa kolekcji oraz ENDPOINT POINTS. Tam dodajemy nowe punkty. Ten nowy punkt musi mieć IDK, to jest dowolny ciąg znaków. Musi mieć wektor, ten właściwy, co tam przechowujemy w bazie danych. Oraz może mieć, a nie musi, payloada. Tam na końcu jest podane. Zwróć uwagę, że tutaj mamy 4. I tutaj też jest wektor o rozmiarze 4. Więc to się musi wszystko zgadzać. Te payloady to są po prostu dane tekstowe, które opisują to coś, co gromadzisz w bazie danych. Nie musi to być wcale wypełnione. I na końcu mamy wysługiwanie danych. To się robi trochę inaczej, ale tutaj używamy metody POST. I mamy nowego endpointa, który bardzo podobnie wygląda. Czyli SLASH COLLECTIONS, nazwa kolekcji, a następnie SLASH POINTS, SEARCH. Łatwo to zapamiętać, nie jest to jakoś skomplikowane. I po czym szukamy? Po wektorze. Tu jest bardzo ważne, żeby ten wektor miał dokładnie taki rozmiar, taki zdefiniowany. I limit, ile rekordów chcemy dostać i czy chcemy pobrać payloada, czy też nie. Bo nie zawsze te payloady są potrzebne. To jest ten payload, on będzie zwrócony w ramach wyszukiwania, jeśli ustawimy sobie WITH PAYLOAD na TRUE. No to co? Wiemy wszystko, jak powinno działać. Kolekcji aktualnie nie mamy, są puste. Więc utwórzmy sobie nową kolekcję. Mam nadzieję, że wybaczysz mi, ale posłuchę się językiem PHP, dlatego że wiele, wiele, naście lat pracowałem jako programista tego języka. Więc z tym jest najprościej. Mam tutaj dwie biblioteki. KWADRANT.PHP oraz EMBEDDING.PHP. KWADRANT.PHP, zobaczmy sobie jak to wygląda. To jest bardzo, bardzo prosty klient HTTP, który na lokalny host, w ramach funkcji REQUEST, za pomocą KURLA, zwanego CURL, do lokalnego serwera poznawanego na dockerze, wysyła REQUESTY do API. Do slash collection, slash wiedza. Wiedza to jest nazwa mojej kolekcji. I tam dodatkowe parametry, np. endpoint jest doklejany na końcu. Wołając więc tą funkcję, definiujemy jaką metodę chcemy użyć. Czy to jest POST, czy to jest PUT. Jakie dane chcemy wysłać. Te dane oczywiście pakowane są w JSON-a. Ja to piszę w PHP, ale ty sobie to przepiszesz np. na PYTHON-a, na JS-a, na cokolwiek tam chcesz. I ta funkcja zwraca po prostu obiekt, który jest zwrócony przez serwer KWADRANTA, który jest też JSON-em. Tak to wygląda. Pora na założenie pierwszej kolekcji. Oczywiście zrobimy to za pomocą funkcji REQUEST. I jej wynik zapiszemy do zmiennej RET. Funkcja REQUEST, metoda PUT, tak jak w dokumentacji. To co widzisz tutaj, to są podpowiedzi z Copilota. Czasami będą one słuszne, czasami niesłuszne. Tutaj napiszemy sobie ręcznie po prostu metoda PUT. A następnie nasza tablica, która będzie zawierała dane, jakie chcemy przesłać. Ta tablica będzie zamieniona na JSON-a, więc mogę sobie to tak zapisać. Musi tam być takie coś jak VECTORS. I w ramach VECTORS podajemy, jakie parametry chcemy mieć w ramach tej bazy danych. Dwa parametry są obowiązkowe. Przede wszystkim rozmiar. Czyli jakiego rozmiaru, ilu wymiarowy wektor będzie tutaj wsadzany domyślnie. Oraz jaką funkcję do porównywania wektorów będziemy używać. I skąd mamy wziąć te informacje? SIZE. SIZE to jest rozmiar wektora. I jest on zależny od tego, z jakiego modelu AI korzystasz do generowania embeddingów. Ja wykorzystuję text Embedding Ada 2 od OpenAI. I to jest zawsze 1536 wymiarów. Jeżeli chodzi o funkcję dystansu, to nie musisz tego szczególnie rozumieć. Wystarczy zapamiętać, że pracując z LLM-ami, zwykle stosujemy jedną funkcję porównania. Jest to funkcja cosinusa, cosin. I tak też użyjemy i tym razem. I teraz uruchommy sobie to. Tylko wcześniej zdefiniuję tutaj, aby wyprintowało mi z formatowanej wersji, wynik działania tej funkcji. Abym wiedział, co tam się potem stało. Uruchamiam. I widzę tutaj, no wszystko się udało. Czy mamy RESULT TRUE, status OK. Sprawdźmy w webowym interfejsie, czy naprawdę jest OK. Odświeżam. I widzę, że tak. Pojawiła się nowa kolekcja o nazwie Wiedza. I mamy tutaj pustą kolekcję. Tylko skąd on wiedział, że trzeba Wiedzę akurat założyć? Przypomnę Ci, jak wyglądał ten nasz kod rant.php. I tutaj mamy tą nazwę kolekcji zdefiniowaną na stałe w kodzie. Oczywiście warto byłoby to sparametryzować, no ale ja to wpisałem na stałe. OK. Sprawdzamy tutaj jeszcze informacje. Punktów nie ma żadnych, dlatego że żadnych nowych wektorów nie dodaliśmy. Dodajmy zatem coś do naszej bazy. Mam przygotowany specjalny plik z informacjami, które chciałbym zaindeksować. Nazywa się on Baza.txt. Otworzę go teraz. Tab Edit Baza.txt. I tu mamy kilka informacji. Mamy informacje np. jak ma na imię pies Adama, gdzie ja mieszkam, co Mateusz lubi robić i informacje na temat różnych. Są też wpisy, które mają tylko zaśmiecić bazę danych i chciałbym je wszystkie zaindeksować. Oczywiście na początku muszę w php odczytać sobie ten plik. Skasuję to, co tutaj zakładam na bazę danych, bo nie jest nam to do niczego potrzebne. A następnie do zmiennej data załaduję plik o nazwie Baza.txt i tutaj Copilot podpowiada nam, że powinniśmy użyć jeszcze przełączników dodatkowych, żeby było bardziej dobrze. Niech tak będzie. I wyprintuję sobie, co tu ciekawego się wczytało. Te dodatkowe przełączniki to jest ignorowanie nowych linii na końcu wpisu oraz ignorowanie pustych znaków. Wczytały się wszystkie rekordy. Mamy tutaj 8 rekordów od 0 do 7. No i teraz chcemy przez nie przejść. No to zastosuję pętlę ForEach, czyli ForEach Data As, załóżmy, rekord. Teraz co ja chcę zrobić z tymi rekordami? Chcę je zamienić na wektory. I do tego służy funkcja o nazwie Embed, która jest z tego pakietu embeddings.php. Pokażę Ci najpierw, jak to się robi. Na początku tutaj mamy Embedding, równa się, Embed, i tu podajemy nasz rekord. To nam zamienia proste zdanie na 1536-wymiarowy wektor. Wyprintujemy sobie go, aby wiedzieć w ogóle, o czym mówimy. I tutaj damy sobie die, żeby po pierwszym rekordzie już wyłączyła się nasza pętla, bo to jest tylko w ramach testów na razie. Ten embedding, jak to dokładnie wygląda? Pokażę Ci. Otwieram sobie ten plik, php, i widzimy tutaj, że jest funkcja Embed, która znowu przez curla odwołuje się do apip od OpenAI i wysyła taką strukturę danych, czyli jakiego modelu używamy oraz jaki jest input, czyli tekst. No i to, skąd wziąłem, z dokumentacji. Po prostu. Dobrze. W takim razie wracamy tutaj i uruchamiamy ten kod. Powinno nam to wyprintować w tym miejscu, jaki wektor powstał. Uruchamiam i co się dzieje? Trwa wykonywanie, bo to oblicza się po stronie API zewnętrznego. I widzę, że coś się wyprintowało. I mamy tu mnóstwo, mnóstwo jakichś dziwnych cyferek. To jest właśnie ten wektor. Pamiętasz, ile miał mieć wymiarów? Tu mamy ostatni rekord. 1535. Dlaczego? Bo są numerowane od zera. Więc pierwszy będzie zerowy, czyli mamy dokładnie 1536 wymiarów wektora w ramach takiej struktury JSON-a. I tu mamy coś takiego jak obiekt data. Tu mamy tablicę o zerowym rekordzie i tu mamy embedding. I to musimy wyciągnąć. W takim razie do tego, co tutaj wyprintowuję, dopiszę namiary na to, co przed chwilą powiedziałem. W takim razie daję tutaj strzałkę, data, rekord zerowy i tu mamy embedding. Sprawdzamy, czy to na pewno działa, czy wyciągnę to, co trzeba. Tak tu jest sam wektor. Czyli mamy zamieniony konkretny wpis na wektora. W takim razie chcemy zamienić je wszystkie. Nie będzie nam już ten DAJ potrzebny oczywiście. Możemy go sobie skasować. Zamiast tego printa do debugowania damy tu jakąś zmienną. Niech ona nazywa się tak samo. Przepisujemy to. Czyli tu mamy embedding. Dajemy w ten sposób. I to jest zapisane. Dobrze. I teraz musimy na tym wywołać funkcję o nazwie request. Dajemy tu oczywiście metodę put, po to, żeby wsadzić dane do bazy. Tu będzie nasz obiekt do wsadzenia. A następnie musimy zdefiniować oddzielnego endpointa. Bo już nie jest to ten sam endpoint API, który jest przy zakładaniu kolekcji. Jest to slash points. I skąd ja to wiem, że tu jest slash points, a nie coś innego? No wiem to oczywiście z dokumentacji. Pamiętasz? Jest tutaj na dole quick start. I szukamy dodawania rekordów. I widzimy, jaką metodą do jakiego endpointa należy wysłać jakie dane. Metoda put do endpointa slash points. A niżej jest struktura. Ja ją znam na pamięć. Widzimy na razie, że baza jest pusta i nie ma żadnych punktów. A my zaraz zmienimy ten stan. W takim razie definiujemy, co konkretnie chcemy dodać. W ramach jednego inserta możemy wsadzić więcej niż jeden punkt. Więc musimy wysłać tablicę punktów, a więc points. I tu otwieramy sobie nawias. I teraz zwróć uwagę. Copilot nam podpowiada, jaka jest struktura. Możemy ją zaakceptować. Mi się ona podoba. I widzimy tu kilka elementów, które muszą być obecne. Czyli mamy ID-ka. On po prostu wyliczył sumę MD5 dla tego rekordu. I to będzie jego ID unikalny. Następnie do payloada wrzucił po prostu ten rekord. A jako wektor użył embeddinga, który wcześniej obliczyłem. Czyli wszystko jest idealnie napisane. I na pierwszy rzut oka powinno to działać. Pytanie tylko, czy na pewno tak będzie. Sprawdźmy to. Uruchomimy ten fragment kodu. Czekamy chwilę. Czekamy, czekamy. Każdy z tych rekordów jest wyliczany i rzucany do bazy danych. A następnie sprawdzimy w interfejsie webowym, czy naprawdę one zostały dodane. Odświeżam. I jak najbardziej. Mamy tu dodane. Pies Adama ma na imię Alexa. Jest tu point o tym haszu. Wszystko się zgadza. Sprawdzimy sobie, czy na pewno wszystkie dane są tutaj zebrane. Możemy to sprawdzić i tu mamy 8 rekordów, w zasadzie wektorów zaindeksowanych. Świetnie. Czyli umiemy już tworzyć kolekcję. Umiemy dodawać nowe wektory. Wypadałoby coś znaleźć w tych wektorach. Do tego momentu wszystko wygląda tak jak w standardowych bazach danych. Czy to SQL, czy NoSQL. Gdzie tu jest więc magia? No właśnie chcę Ci to pokazać. Będziemy odpytywać naszą bazę danych za pomocą normalnego języka naturalnego. Bez żadnej składni, bez niczego. Po prostu napiszemy zwykłe zdanie. Nasze query będzie tutaj zapisane. Tylko na początku musimy przypomnieć sobie, co mamy w bazie danych. W bazie danych mamy na przykład pierwszą informację na temat psa Adama ma na imię Alexa. Sprawdźmy w takim razie, czy możemy wyciągnąć tą informację. Musimy z niej zrobić embeddinga, a więc embed i tu piszemy normalnym językiem jak ma na imię pies Adama i znak zapytania. Nasz embedding jest gotowy. Ma 1536 wymiarów i nim będziemy odpytywać bazę danych kwadrantów. W takim razie request i metodą post, dlatego że postem się to szuka. Jest to w dokumentacji zdefiniowane. Następnie jest obiekt i points łamane przez search. To jest nasz endpoint do wyszukiwania danych. Co chcemy teraz wysłać? Chcemy wysłać wektor do wyszukiwania i naszym wektorem jest nasz embedding wyliczony wcześniej, czyli to jest query oraz limit. Interesuje nas tylko jedna odpowiedź na nasze pytanie. Mogłoby ich być więcej, gdyby baza była większa, ale my chcemy jedną. I oczywiście with payload, bo w payload jest informacja na temat całego zdania. Na pewno nam się to przyda. Logika wyszukiwania jest naprawdę bardzo prosta, to znaczy szukasz wektorów za pomocą wektora, więc na początku musisz co? Zbudować tego wektora. I ten limit ustawiasz na tyle rekordów, ile chcesz wyciągnąć. Ten with payload czasami się przyda, czasami nie. Wyprintujemy na ekran efekt działania tej funkcji, aby zobaczyć, czy naprawdę ona działa i uruchamiam to. Co się teraz dzieje? No coś jest nie tak. JSON jest źle zbudowany. Nie jest to taka struktura, jak ja się spodziewałem. Dlaczego? Pamiętam, jak wcześniej odwoływałem się do obiektu? To nie może być po prostu cały obiekt query, tylko tu będzie data, tu mamy rekord zerowy i następnie jest embeddings i w ten sposób teraz co widzimy? Pies Adama ma na imię Aleksa. No dobra, tylko ty teraz mi powiesz, każda baza danych na świecie jest w stanie coś takiego zrobić. To popatrz w takim razie na to. Zmienimy sobie zapytanie na inne. Na przykład imię psiny Adasia. O, tyle literówki. Spoko. I teraz zwróć uwagę, imię się nie zgadza, psina się nie zgadza z psem, a on dalej wie, że pytasz o psa Adama. No to to jest całkiem niezłe, prawda? Zapytajmy o coś innego. Na przykład piesek Adasia jakiego ma nejma. Niech to będzie I co? I mamy tutaj informację, że pies Adama ma na imię Aleksa, czyli znowu dostajemy ten sam rekord, który chcieliśmy, pomimo tego, że źle napisaliśmy zapytanie. Nie tymi słowami, którymi powinniśmy tutaj to opisać. Zapytamy teraz o tą drugą informację. Gdzie mieszka Kuba? Tylko tam była informacja, gdzie mieszka Jakub. A on co? I jest w stanie to skojarzyć. Wie, że o Jakuba chodzi. Świetnie. Zapytajmy w takim razie o Mateusza. Niech tutaj będzie kto robi najlepsze memy. Odpowiedź na to pytanie jest znana nawet bez przeszukiwania bazy danych. To jest Mateusz. I jak najbardziej Mateusz lubi produkować memy. I w ten sposób widzisz, na czym polega magia tych baz wektorowych. Są to bazy, które szukają pod względem semantycznym co masz na myśli i o czym mówisz, a nie pod względem leksykalnym, czy popełniłeś literówki, czy też nie. Jeśli takie tematy jak ten Cię interesują, to zapraszam na szkolenie AIDevs. Linka masz w opisie. I tam uczymy między innymi tego jak porozumiewać się z bazami wektorowymi, w jaki sposób lepiej wyszukiwać informacje, jak pracować z własnymi danymi, w jaki sposób rozmawiać z tymi danymi. No i co najważniejsze w tej edycji, jak budować tak zwane agenty. To co? Zapraszam na stronę i do zobaczenia w kolejnym filmie. Cześć.