Repozytorium zawiera przykłady z lekcji kursu AI_devs 3. Więcej informacji znajdziesz na aidevs.pl.
Wszystkie przykłady zostały napisane w JavaScript / TypeScript i większość z nich zawiera kod backendowy do którego uruchomienia potrzebny jest Node.js oraz Bun.
Upewnij się, że posiadasz najnowsze wersje Node.js oraz Bun zainstalowane na swoim komputerze.
Pobierz repozytorium:
git clone git@github.com:i-am-alice/3rd-devs.git cd 3rd-devsZainstaluj zależności:
bun install
Skopiuj plik
.env.exampledo.envi wypełnij go kluczami API (na początek wystarczy klucz OpenAI).Uruchom dostępne przykłady z pliku
package.json, według poniższej instrukcji.
Jeśli posiadasz w swoim systemie możliwość uruchamiania kontenerów Dockera (na Windows użyj np. WSL/WSL2), możesz wykorzystać skrypt, który zbuduje i uruchomi dla Ciebie kontener ze środowiskiem gotowym do pracy.
Wejdź do katalogu, w którym chcesz przetrzymywać pliki środowiska i wydaj następujące polecenia:
curl -fsSL https://env.ag3nts.org -o setup.sh bash setup.sh
Powyższy skrypt NIE zmienia niczego w systemie. Wykonuje on następujące czynności:
- klonowanie repozytorium do katalogu "3rd-devs" (poza kontenerem, w aktualnym katalogu)
- przygotowanie pliku Dockerfile
- usunięcie starego obrazu Dockera o nazwie "aidevs" (jeśli istnieje)
- uruchomienie procesu budowy obrazu Dockera
- instalacja wymaganych paczek wewnątrz zdokeryzowanego środowiska
Po pomyślnym zbudowaniu obrazu możesz uruchomić go poleceniem (jeśli port 3000 masz zajęty, wybierz inny):
docker run --rm -it -p 3000:3000 --name aidevs -v ${PWD}/3rd-devs:/app aidevs3Pliki w katalogu "3rd-devs" możesz modyfikować w dowolnym IDE. Będą one bezpośrednio widoczne wewnątrz kontenera
Będąc już wewnątrz kontenera, skopiuj plik
.env.exampledo.envi wypełnij go wymaganymi kluczami API (na początek wystarczy klucz OpenAI).Twoje środowisko jest gotowe do pracy.
Przykład przedstawia konwersację między użytkownikiem i asystentem, w której działa mechanizm podsumowania konwersacji.
- Uruchomienie serwera:
bun run thread - Interakcja demo:
curl -X POST http://localhost:3000/api/demo - Interakcja chat:
curl -X POST http://localhost:3000/api/chat -H "Content-Type: application/json" -d '{"message": { "role": "user", "content": "Hi"}}'
Wywołanie powyższego endpointu uruchomi trzy niezależne zapytania do OpenAI, jednak w wiadomości systemowej zostanie przekazane podsumowanie poprzedniej interakcji, dzięki czemu model będzie miał możliwość odwołać się do ich treści.
W przykładzie uwzględniony jest także endpoint /api/chat na który można przesłać obiekt { "message": "..." } zawierający treść wiadomości do modelu. Wątek zostanie zresetowany dopiero po ponownym uruchomieniu serwera (wciśnij CMD + C / Control + C i ponownie bun run thread).
UWAGA: przykład wymaga zainstalowania promptfoo w przypadku którego prawdopodobnie musisz to zrobić poleceniem npm install promptfoo ponieważ bun install promptfoo nie działa poprawnie w każdej sytuacji.
- Uruchomienie skryptu:
bun use_search
Rezultatem działania skryptu jest tablica zawierająca kilkanaście przykładowych testów dla promptu decydującego o tym, czy skorzystanie z wyszukiwarki jest potrzebne.
- Uruchomienie skryptu:
bun pick_domains
Rezultatem działania skryptu jest tablica zawierająca kilkanaście przykładowych testów dla promptu generującego zapytania do wyszukiwarki Internetowej, wskazując także odpowiednie domeny.
- Uruchomienie skryptu:
bun rate
Rezultatem działania skryptu jest tablica zawierająca kilkanaście przykładowych testów dla promptu oceniającego, czy odpowiedź modelu zawiera odpowiednie informacje.
Przykład ten korzysta z Firecrawl do przeszukiwania Internetu oraz pobierania treści stron www. Konieczne jest więc uzupełnienie pliku .env wartości FIRECRAWL_API_KEY ustawionej na klucz API.
(Firecrawl oferuje bezpłatny plan).
- Uruchomienie serwera:
bun websearch - Interakcja:
curl -X POST http://localhost:3000/api/chat \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Search wiki for 'John Wick'"}]}'
Ważne: w pliku websearch/app.ts można zmienić listę domen, które są dopuszczalne do przeszukiwania i pobierania treści.
Uruchomienie tego przykładu wymaga uzupełnienia pliku .env i wartości LINEAR_API_KEY oraz LINEAR_WEBHOOK_SECRET.
Obie wartości można znaleźć w ustawieniach API. Dodatkowo Twój localhost musi być dostępny z poza Twojej sieci lokalnej, np. za pomocą ngrok. Publiczny adres URL należy także wskazać w panelu Linear w sekcji Webhooks, np.: https://<ngrok-url>/api/linear/watch-issue (pamiętaj o dodaniu właściwego endpointu do adresu).
WAŻNE: w pliku linear/prompts.ts znajduje się prompt w którym zostały opisane moje projekty w Linear.
Aby skrypt działał poprawnie, musisz zmodyfikować ten prompt, tak aby zawierał identyfikatory oraz opisy Twoich projektów.
Listę projektów i ich identyfikatory możesz pobrać korzystając z endpointu /api/linear/projects.
- Uruchomienie serwera:
bun linear - Pobranie listy projektów:
curl http://localhost:3000/api/linear/projects - Po dodaniu nowego wpisu w Twoim linearze, zostanie on automatycznie przypisany do projektu zgodnie z zasadami w promptach, o ile nie został przypisany przez Ciebie ręcznie.
- Uruchomienie serwera:
bun files - Interakcja:
curl -X POST http://localhost:3000/api/chat \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Hey there, what\'s up?"}], "conversation_id": "d7582176-bc52-4ef3-980a-047b868f9f49"}'
Przykład ten pokazuje mechanizm podejmowania decyzji o zapamiętywaniu informacji na podstawie kontekstu rozmowy.
Dodatkowo w przypadku podania conversation_id w obiekcie żądania, do rozmowy zostaną wczytane wszystkie wiadomości dotyczące konkretnej rozmowy.
Wszystkie pliki zapisywane są w folderze files/context, a sam katalog można otworzyć w aplikacji Obsidian aby zobaczyć powiązania pomiędzy wspomnieniami.
Ten przykład wymaga uzupełnienia pliku .env o wartości LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY oraz LANGFUSE_HOST. Można je uzyskać zakładając bezpłatne konto na Langfuse.
UWAGA: Aby uruchomić ten przykład, musisz w panelu Langfuse utworzyć nowy prompt o nazwie Answer, którego wartość możesz ustawić na np. 'Odpowiadaj pisząc wyłącznie wielkimi literami'.
- Uruchomienie serwera:
bun langfuse - Interakcja:
curl -X POST http://localhost:3000/api/chat \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Hey there, what\'s up?"}]}'
Po wykonaniu zapytania, zostanie ono automatycznie zalogowane do Langfuse, a wynik wyświetlony w panelu.
- Uruchomienie serwera:
bun tiktokenizer - Interakcja:
curl -X POST http://localhost:3000/api/chat \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Hey there, what\'s up?"}], "model": "gpt-4o"}'
Przykład ten pokazuje mechanizm liczenia tokenów w zapytaniach do modeli OpenAI (np. gpt-4o).
Przykład ten pokazuje jeden mechanizm pozwalający na kontynuowanie wypowiedzi modelu, pomimo osiągnięcia maksymalnej liczby tokenów wyjściowych (output tokens).
- Uruchomienie serwera:
bun max_tokens - Interakcja:
curl -X POST http://localhost:3000/api/chat \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Write ten sentences about apples and put them in order."}]}'
Przykład ten przedstawia mechanizm blokowania zapytań, które nie spełniają warunków określonych w prompcie /constitution/prompts.ts.
- Uruchomienie serwera:
bun constitution - Interakcja:
curl -X POST http://localhost:3000/api/chat \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Hello!"}]}'
Ten przykład po uruchomieniu tworzy katalog memories w którym zapisywane są pliki markdown, pełniące rolę pamięci modelu. Nie jest to przykład nadający się na produkcję, lecz przedstawia ogólne mechaniki pamięci długoterminowej, które będziemy rozwijać w dalszych lekcjach.
- Uruchomienie serwera:
bun memory - Interakcja:
curl -X POST http://localhost:3000/api/chat \
-H "Content-Type: application/json" \
-d '{"messages": [{"role": "user", "content": "Hello!"}]}'Ten przykład zawiera standardową logikę interakcji z modelem, ale wymaga podania klucza API w nagłówku Authorization w formacie Bearer <klucz>. Wartość klucza zostaje wczytana z pliku .env jako PERSONAL_API_KEY. Dodatkowo zostały dodane mechanizmy ograniczania liczby zapytań, więc po kilku próbach ponowne wywołanie zapytania zwróci błąd 429.
- Uruchomienie serwera:
bun external - Interakcja:
curl -X POST http://localhost:3000/api/chat \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Hello!"}]}'
UWAGA: Aby uruchomić ten przykład konieczne jest nawiązanie połączenie z Langfuse poprzez uzupełnienie pliku .env o wartości LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY oraz LANGFUSE_HOST. Dodatkowo na Twoim koncie musisz utworzyć nowy prompt o nazwie Answer, którego wartość możesz ustawić na np. 'Odpowiadaj pisząc wyłącznie wielkimi literami', aby tylko sprawdzić działanie mechanizmu. Dodatkowo prompt "Answer" należy dodać w ustawieniu "Chat", a nie "Text" (tryb można zmienić z pomocą zakładek w Langfuse)
- Uruchomienie serwera:
bun prompts - Interakcja:
curl -X POST http://localhost:3000/api/chat \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Hello!"}]}'
Ten przykład nie dotyczy bezpośrednio działania LLM, lecz przedstawia sposób organizacji informacji w bazie danych, takich jak konwersacje czy historia wiadomości.
- Uruchomienie serwera:
bun database - Interakcja:
curl -X POST http://localhost:3000/api/chat \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Hello!"}]}'
Przykład ten przedstawia absolutnie podstawowe połączenie z bazą wektorową Qdrant. Jego zadaniem jest zapisywanie historii wiadomości, a następnie wyszukiwanie i wczytywanie do kontekstu rozmowy najbardziej podobnych wiadomości. Przykład ten będziemy rozbudowywać w dalszych lekcjach, łącząc się z Qdrant w bardziej złożonych konfiguracjach.
UWAGA: Aby uruchomić ten przykład, musisz w panelu Langfuse utworzyć nowy prompt o nazwie Answer, którego wartość możesz ustawić na np. 'Odpowiadaj pisząc wyłącznie wielkimi literami'. Powodem jest fakt, że w ten przykład został powiązany z przykładem langfuse.
- Uruchomienie serwera:
bun qdrant - Interakcja:
curl -X POST http://localhost:3000/api/chat \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Hello!"}]}'
UWAGA: Ten przykład wymaga uruchomienia frontendu w folderze audio-frontend oraz backendu w folderze audio-backend. W związku z tym przykład trzeba uruchomić na własnym komputerze.
- Uruchomienie frontendu:
bun audio:dev - Uruchomienie backendu:
bun audio - Interakcja: Otwórz w przeglądarce stronę http://localhost:5173
WAŻNE: Jakość działania tego przykładu zależy głównie od jakości mikrofonu oraz dźwięków otoczenia. Upewnij się więc, że jakość nagrania jest dobra i że nie ma zakłóceń uniemożliwiających wykrywanie końca wypowiedzi.
- Uruchomienie kodu:
bun vision
- Uruchomienie kodu:
bun recognize
Do uruchomienia tego przykładu należy uzupełnić plik .env o wartość MISTRAL_API_KEY. Można go pobrać tutaj na Mistral.ai
- Uruchomienie kodu:
bun recognize_pixtral
- Uruchomienie kodu:
bun vision - Interakcja: przykład wykonuje się automatycznie na pliku
vision/lessons.png
- Uruchomienie kodu:
bun recognize - Interakcja: przykład wykonuje się automatycznie na plikach z katalogu
recognize/avatars
- Uruchomienie kodu:
bun recognize_pixtral - Interakcja: przykład wykonuje się automatycznie na plikach z katalogu
recognize_pixtral/avatars
--- brak przykładów ---
- Uruchomienie kodu:
bun captions - Interakcja: przykład wykonuje się automatycznie na pliku
captions/article.md
- Uruchomienie kodu:
bun summary - Interakcja: skrypt wykonuje się automatycznie na pliku
summary/article.md
Do uruchomienia tego przykładu należy uzupełnić plik .env o wartość GOOGLE_AI_STUDIO_API_KEY, który można pobrać z Google AI Studio.
- Uruchomienie kodu:
bun video - Interakcja: przykład wykonuje się automatycznie na pliku
video/test.mp3
UWAGA: Ten przykład może zużywać duże ilości kredytów na ElevenLabs, więc jeśli chcesz zobaczyć rezultat jego działania, to w katalogu narration znajdują się dwa przykładowe pliki audio, które możesz odtworzyć bez uruchamiania kodu.
Do uruchomienia tego przykładu należy uzupełnić plik .env o wartość GOOGLE_AI_STUDIO_API_KEY, który można pobrać z Google AI Studio oraz ELEVEN_LABS_API_KEY, który można pobrać z ElevenLabs.
- Uruchomienie kodu:
bun narration - Interakcja: przykład wykonuje się automatycznie na treści wiadomości użytkownika przekazanej w funkcji
generateNarrationw plikunarration/app.ts
- Uruchomienie kodu:
bun read - Interakcja: przykład wykonuje się automatycznie na pliku
read/article.mdi generuje plik audio w folderze read/summary.wav
Ten przykład wymaga uruchomienia frontendu w folderze audio-map-frontend oraz backendu w folderze audio-map. W związku z tym przykład trzeba uruchomić na własnym komputerze.
- Uruchomienie frontendu:
bun map:dev - Uruchomienie backendu:
bun audio-map - Interakcja: Otwórz w przeglądarce stronę http://localhost:5173
- Uruchomienie kodu:
bun notes - Interakcja: przykład wykonuje się automatycznie na wiadomości wpisanej w treść pliku
notes/app.ts(jest tam kilka przykładów innych wiadomości, które można podmienić).
- Uruchomienie kodu:
bun text-splitter - Interakcja: przykład wykonuje się automatycznie na plikach markdown z katalogu "text-splitter"
- Uruchomienie kodu:
bun unstructured - Interakcja: przykład wykonuje się automatycznie na pliku source.md z katalogu "unstructured"
Uruchomienie tego przykładu wymaga uzupełnienia pliku .env o wartości "QDRANT_URL" oraz "QDRANT_API_KEY".
Wartości te można znaleźć w panelu Qdrant po zalogowaniu na bezpłatne konto na stronie Qdrant Cloud.
Natomiast klucz API można pobrać w zakładce "Data Access Control".
- Uruchomienie kodu:
bun embedding - Interakcja: przykład wykonuje się automatycznie na danych osadzonych w pliku embedding/app.ts
- Uruchomienie kodu:
bun rerank - Interakcja: przykład wykonuje się automatycznie na danych osadzonych w pliku rerank/app.ts
- Uruchomienie kodu:
bun naive-rag - Interakcja: przykład wykonuje się automatycznie na danych osadzonych w pliku naive-rag/app.ts
- Uruchomienie kodu:
bun better-rag - Interakcja: przykład wykonuje się automatycznie na danych osadzonych w pliku better-rag/app.ts
- Uruchomienie kodu:
bun semantic - Interakcja: przykład wykonuje się automatycznie na danych osadzonych w pliku semantic/app.ts
Do uruchomienia tego przykładu konieczne jest uzupełnienie ALGOLIA_APP_ID oraz ALGOLIA_API_KEY w pliku .env.
UWAGA: przy pierwszym uruchomieniu przykładu pojawi się błąd ale spowoduje to utworzenie indeksu w Algolia. Wówczas należy przejść do panelu Algolia i w zakładce "Facets" dodać nowy facet o nazwie author.
- Uruchomienie kodu:
bun algolia - Interakcja: przykład wykonuje się automatycznie na danych osadzonych w pliku algolia/app.ts
UWAGA: Do uruchomienia tego przykładu konieczne jest uzupełnienie ALGOLIA_APP_ID oraz ALGOLIA_API_KEY w pliku .env.
Wymagane jest bezpłatne konto na Algolia.
Dodatkowo jeśli wyniki wyszukiwania nie są poprawnie zwracane, należy sprawdzić czy pole text zostało poprawnie ustawione w panelu Algolia jako searchableAttributes.
- Uruchomienie kodu:
bun sync - Interakcja: przykład wykonuje się automatycznie na danych osadzonych w pliku sync/app.ts
UWAGA: Do uruchomienia tego przykładu konieczne jest uzupełnienie QDRANT_URL oraz QDRANT_API_KEY w pliku .env.
Konieczne jest także połączenie z Algolia podobnie jak w przypadku przykładu sync.
- Uruchomienie kodu:
bun hybrid - Interakcja: przykład wykonuje się automatycznie na danych osadzonych w pliku hybrid/app.ts
Do uruchomienia tego przykładu konieczne jest połączenie z bazą Neo4j. Można ją zainstalować lokalnie, a następnie uzupełnić plik .env o wartości NEO4J_URI, NEO4J_USER oraz NEO4J_PASSWORD.
- Uruchomienie kodu:
bun neo4j-101 - Interakcja: przykład wykonuje się automatycznie na danych osadzonych w pliku neo4j-101/app.ts
- Uruchomienie kodu:
bun neo4j - Interakcja: przykład wykonuje się automatycznie na danych osadzonych w pliku neo4j/app.ts


