Wprowadzenie
Serverless AI oznacza wykorzystanie technologii serverless do uruchamiania sztucznej inteligencji, takiej jak modele ChatGPT, bez zarządzania serwerami. Innymi słowy, możemy uruchamiać ChatGPT w chmurze (Running ChatGPT in the cloud) jako funkcję bezserwerową reagującą na zdarzenia lub żądania HTTP. W praktyce wygląda to tak, że nasz kod w funkcji (np. AWS Lambda, Google Cloud Function) wywołuje API ChatGPT od OpenAI i zwraca jego odpowiedź. Warto podkreślić, że nie ma możliwości uruchomienia ChatGPT lokalnie – zawsze korzystamy z API OpenAI z kluczem API. Dlatego funkcja serverless pełni rolę „wrappera” – przyjmuje zdarzenie, wywołuje usługę ChatGPT w chmurze i zwraca wynik.
Pisanie własnej funkcji serverless integrującej się z ChatGPT daje nam większą kontrolę i możliwość dostosowania rozwiązania pod nasze potrzeby. Możemy np. filtrować lub wzbogacać dane przed wysłaniem ich do modelu, łączyć odpowiedzi modelu z innymi usługami (bazami danych, kolejkowaniem zadań itp.) oraz ukryć klucz API przed użytkownikami końcowymi. Dzięki temu ChatGPT serverless integruje się bezproblemowo z istniejącymi aplikacjami backendowymi i workflowami chmurowymi, zapewniając automatyzację i inteligencję tam, gdzie dotąd potrzebny był kod pisany ręcznie.
W dalszej części skupimy się na praktycznej implementacji – jak zbudować funkcje zasilane ChatGPT na konkretnych platformach chmurowych. Głównym przykładem będzie AWS Lambda (ze względu na popularność), omówimy też Google Cloud Functions oraz wspomnimy o Azure Functions. Przedstawimy także architekturę AI serverless, kwestie konfiguracji (API Gateway, zmienne środowiskowe, IAM, konta usług, sekrety), aspekty wydajności (zimne starty, limity czasu) oraz rzeczy takie jak obsługa błędów i ograniczeń API. Na koniec pokażemy przykładowe zastosowania – od automatyzacji zadań tekstowych, przez event-driven AI workflows (przepływy sterowane zdarzeniami), po asynchroniczne zadania w tle z ChatGPT. Artykuł ma charakter technicznego przewodnika – skierowany jest do inżynierów chcących wdrożyć serverless automation with ChatGPT w swoich systemach.
Architektura rozwiązania: funkcja serverless + API ChatGPT
Podstawowa architektura jest prosta: funkcja bezserwerowa (np. Lambda) odbiera zdarzenie lub żądanie, a następnie wywołuje API ChatGPT (OpenAI) i otrzymaną odpowiedź zwraca lub dalej przetwarza. Funkcja jest wywoływana na żądanie (np. poprzez API HTTP) lub w reakcji na zdarzenie (np. plik wrzucony do storage, wiadomość w kolejce, zaplanowany czas). Całość jest bezstanowa – każda instancja funkcji działa w izolacji i nie utrzymuje kontekstu między wywołaniami, co oznacza, że jeśli chcemy np. zachować konwersację z ChatGPT, musimy przechować historię poza funkcją (np. w bazie danych).
Dlaczego użyć funkcji serverless jako pośrednika do ChatGPT? Po pierwsze, zwiększa to bezpieczeństwo – klucz API do OpenAI jest przechowywany po stronie serwera (np. w zmiennej środowiskowej funkcji) zamiast na frontendzie, więc użytkownicy nie mają do niego dostępu. Po drugie, zyskujemy możliwość wprowadzenia logiki biznesowej wokół wywołania AI. Jak zauważono, stworzenie własnego publicznego endpointu wywołującego OpenAI daje pełną kontrolę nad przepływem i formatem danych. Możemy np. łączyć odpowiedź modelu z danymi z naszych baz, formatować ją czy filtrować. Po trzecie, dziedziczymy cechy serverless – automatyczne skalowanie, płatność za wywołania i brak potrzeby zarządzania infrastrukturą.
Poniższy diagram ilustruje przykładową architekturę serverless AI workflow na AWS: zaplanowany timer (EventBridge Scheduler) codziennie uruchamia funkcję Lambda, która generuje treść za pomocą ChatGPT, zapisuje wynik w bazie (DynamoDB), a kolejne wyzwalacze generują dodatkowe zasoby (obraz, audio) i wysyłają powiadomienie email do użytkownika:
Przykład architektury serverless generującej historię z użyciem ChatGPT – zaplanowane zdarzenie (EventBridge) wyzwala funkcję Lambda, która korzysta z ChatGPT do wygenerowania treści; wynik jest zapisywany w bazie danych, a równolegle kolejne funkcje tworzą dodatkowe zasoby i wysyłają powiadomienie.
W powyższym przykładzie widzimy, jak event-driven AI workflow może wyglądać w praktyce. O określonej porze harmonogram wyzwala funkcję, która korzysta z ChatGPT do wygenerowania np. unikalnej bajki na dobranoc. Następnie uruchamiane są kolejne procesy (również serverless) reagujące na powstanie nowej historii – generowanie ilustracji, audio oraz powiadomienie użytkownika. Całość działa bezserwerowo, skalując się automatycznie i integrując AI z usługami chmurowymi (baza NoSQL, kolejki, powiadomienia) w modelu zdarzeniowym.
Ogólny przepływ dla prostszych zastosowań (np. API HTTP) wygląda jednak mniej skomplikowanie: klient wysyła żądanie HTTP do naszego endpointu (np. API Gateway + Lambda), żądanie zawiera dane wejściowe (np. pytanie do ChatGPT), funkcja Lambda wywołuje odpowiedni endpoint OpenAI (przekazując prompt i inne parametry), otrzymuje odpowiedź od modelu i odsyła ją klientowi. Ten wzorzec pozwala np. stworzyć własne API „ChatGPT-as-a-service” wewnątrz firmy lub aplikacji, które może być dostosowane do naszych potrzeb (np. zwracać odpowiedź w konkretnym formacie).
Uwaga dot. formatu odpowiedzi: Warto tak zaprojektować funkcję i prompt, by ułatwić odbiór odpowiedzi przez system. Można np. poprosić model o zwrócenie wyniku w formacie JSON o z góry ustalonej strukturze. Dzięki temu kod łatwo sparsuje wynik bez skomplikowanego przetwarzania tekstu naturalnego. Bardziej zaawansowaną opcją jest użycie funkcjonalności function calling API OpenAI (gdzie definiujemy schemat funkcji/odpowiedzi), ale nawet proste polecenie w promptcie typu „podaj odpowiedź jako obiekt JSON z polami X, Y, Z” poprawi integrację. Taki ustrukturyzowany output upraszcza pipeline i czyni go bardziej niezawodnym.
Podsumowując, architektura serverless z ChatGPT składa się z trzech kluczowych elementów:
- Trigger (wyzwalacz) – np. żądanie HTTP, wiadomość w kolejce, harmonogram czasowy itp., który uruchamia naszą funkcję.
- Funkcja (kod) – właściwa logika w funkcji bezserwerowej, która pobiera dane ze zdarzenia, wywołuje API ChatGPT i przetwarza zwróconą odpowiedź.
- Zewnętrzny model AI (ChatGPT) – zarządzany przez OpenAI model dostępny przez API, do którego wysyłamy zapytanie. Wszystkie operacje AI dzieją się po stronie OpenAI – nasza funkcja tylko wysyła prompt i odbiera wynik.
W kolejnych sekcjach przejdziemy przez implementację na poszczególnych platformach chmurowych, zwracając uwagę na specyfikę każdej z nich.
Implementacja na AWS Lambda (Python/Node.js)
AWS Lambda to flagowa usługa serverless od Amazona, idealna do zbudowania funkcji wywołującej ChatGPT. Załóżmy, że chcemy stworzyć prosty endpoint HTTP typu ChatGPT AWS Lambda – np. użytkownik wysyła zapytanie, a nasza Lambda zwraca odpowiedź modelu. Poniżej omawiamy kluczowe kroki i aspekty takiej integracji.
Tworzenie funkcji Lambda i kod wywołujący ChatGPT
W AWS Lambda możemy wykorzystać dowolny obsługiwany runtime, popularne wybory to Python lub Node.js ze względu na szybkość tworzenia i dostępność bibliotek. W przykładzie posłużmy się Pythonem. Nasza funkcja będzie korzystać z oficjalnej biblioteki OpenAI (instalowanej poprzez pip) do wywołania API ChatGPT.
Kod w pliku lambda_function.py (handler) może wyglądać w uproszczeniu tak:
import os
import openai
openai.api_key = os.environ['OPENAI_API_KEY'] # Klucz API pobrany ze zmiennej środowiskowej
def lambda_handler(event, context):
user_input = event.get("query") or "" # Załóżmy, że pytanie przychodzi w polu "query"
# Wywołanie modelu (np. GPT-3.5 Turbo)
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": user_input}]
)
result = response["choices"][0]["message"]["content"]
# Zwrócenie wyniku jako JSON
return {"statusCode": 200, "body": {"answer": result}}
Powyższy kod:
Odczytuje klucz API z zmiennej środowiskowej OPENAI_API_KEY. Przechowywanie klucza w env jest bezpieczniejsze niż wpisywanie go na stałe w kodzie – AWS Lambda przechowuje zmienne środowiskowe zaszyfrowane (szyfrowanie w spoczynku), a podczas wykonania funkcji odszyfrowuje je i udostępnia w os.environ. Dzięki temu możemy trzymać klucz API w konfiguracji funkcji (ew. szyfrowany własnym kluczem KMS, jeśli to wymagane).
Używa OpenAI Python SDK do stworzenia chat completion z modelu gpt-3.5-turbo, przekazując użytkownika wiadomość (prompt). Alternatywnie można użyć endpointu completions z modelami text-davinci-003 itp., ale ChatCompletion z rolami jest zalecane dla ChatGPT.
Zwraca wynik (pierwszą wygenerowaną odpowiedź) w polu answer formatu JSON.
Integracja z API Gateway / HTTP: Aby funkcja była wywoływana przez protokół HTTP, najprościej jest podpiąć ją pod API Gateway. Możemy utworzyć API typu REST lub HTTP API, które na określonej ścieżce przekazuje zapytania do naszej Lambdy. W powyższym kodzie zakładamy, że event zawiera pole query – np. API Gateway mógłby przekazywać ciało żądania POST z JSON zawierającym {„query”: „Twoje pytanie”} do funkcji. API Gateway obsłuży autoryzację, limitowanie i inne aspekty jeśli potrzebujemy. Prostszą alternatywą w AWS jest skorzystanie z Lambda Function URL – każda funkcja może mieć wygenerowany unikalny URL, pod którym jest dostępna (bez konieczności tworzenia osobnego API Gateway). Function URL nadaje się do prostych przypadków użycia (obsługuje CORS i może być zabezpieczony podpisanymi URL lub IAM), natomiast API Gateway daje więcej możliwości (np. plan ruchu, klucze API, integracje z Cognito itp.). Wybór metody zależy od wymagań projektu.
IAM role i uprawnienia: Kiedy tworzymy funkcję Lambda, przypisywana jest jej rola IAM (Execution Role). Należy skonfigurować ją zgodnie z zasadą minimalnych uprawnień. Do samego wywołania zewnętrznego API OpenAI nie są potrzebne żadne specjalne uprawnienia AWS (dostęp do internetu publicznego jest domyślnie włączony, o ile nie przypniemy Lambdy do VPC). Natomiast warto, by rola miała prawo zapisu logów do CloudWatch (AWS automatycznie tworzy politykę AWSLambdaBasicExecutionRole zapewniającą dostęp do logów). Jeśli nasza funkcja miałaby korzystać z innych usług AWS (np. pobierać dane z S3, czytać z SSM/Secrets Manager itp.), musimy dodać odpowiednie policy do roli. Dla bezpieczeństwa nie nadawajmy roli uprawnień, których nie potrzebuje. Zasada least privilege obowiązuje tak samo w serverless – np. GCP zaleca tworzenie dedykowanego service account dla każdej funkcji i ograniczanie jego praw (analogicznie w AWS poprzez role IAM).
W kontekście sekretów: jeżeli nie chcemy przechowywać klucza OpenAI jako zwykłej zmiennej środowiskowej, można skorzystać z AWS Secrets Manager lub Systems Manager Parameter Store. Przykładowo, klucz API mógłby być przechowany jako Secret, a Lambda pobierałaby go przy starcie (lub korzystała z mechanizmu cachingowego). Jednak to wprowadza dodatkowy narzut (czas na pobranie sekretu przy zimnym starcie). Częstą praktyką jest więc ustawienie sekretu w zmiennych środowiskowych Lambdy podczas deploymentu – jest to wygodne, a dzięki szyfrowaniu i kontroli dostępu na poziomie roli ryzyko jest minimalne. Wrażliwe dane w env można dodatkowo zaszyfrować własnym kluczem KMS jeśli wymagana jest większa kontrola.
Wydajność: zimne starty, pamięć, timeouty
Cold start (zimny start) – to częsty temat przy Lambda + AI. Zimny start następuje, gdy funkcja jest uruchamiana w nowej, świeżo tworzonej instancji (np. po okresie bezczynności lub przy skalowaniu). Wiąże się to z jednorazową inicjalizacją środowiska: załadowaniem runtime (Python, Node), kodu funkcji i zależności. Na szczęście dla Pythona czy Node ten narzut jest niewielki – są to języki interpretowane, które inicjują się szybciej niż kompilowane runtime (Java, .NET). Typowy zimny start dla Lambdy Python/Node może trwać kilkadziesiąt, czasem kilkaset milisekund w zależności od rozmiaru paczki i zależności. AWS stale optymalizuje te wartości i statystycznie zimne starty dotyczą <1% wywołań, choć oczywiście jeśli nasza funkcja jest wywoływana bardzo rzadko, to niemal każde wywołanie może być zimnym startem.
W kontekście ChatGPT niewielkie opóźnienie rzędu setek ms zwykle nie jest krytyczne (sam model może generować odpowiedź 1-2 sekundy), ale dla aplikacji latency-sensitive można podjąć działania. AWS Lambda oferuje Provisioned Concurrency – mechanizm utrzymujący określoną liczbę „rozgrzanych” instancji funkcji na stałe, co eliminuje zimny start kosztem dodatkowej opłaty. Jest to przydatne przy interfejsach użytkownika wymagających konsekwentnie niskich czasów odpowiedzi. W większości backendowych zastosowań można jednak polegać na zwykłym on-demand, dbając o minimalizację zimnego startu przez:
Optymalizację wielkości wdrożenia (mniej zależności, mniejsze pliki do załadowania). Unikamy nieużywanych bibliotek – każda dodatkowa zależność zwiększa pakiet i wydłuża inicjalizację.
Inicjalizację obiektów (np. klientów SDK) poza handlerem, aby wykonała się tylko raz przy zimnym starcie, a nie przy każdym wywołaniu.
Wybór szybkiego runtime (Python, Node są szybkie; unikać Javy/.NET dla takich zadań chyba że konieczne).
Ewentualnie wykorzystanie mechanizmów utrzymywania funkcji aktywnej – np. wywoływanie jej co kilka minut (CloudWatch Events/ EventBridge Rule) by nie dopuścić do uśpienia. To jednak hack, lepiej użyć Provisioned Concurrency jeśli naprawdę wymagamy ciągle ciepłych instancji.
Limit czasu (timeout) – domyślnie Lambda ma krótki timeout (3 sekundy, o ile nie zmienimy). Dla integracji z ChatGPT to zdecydowanie za mało, ponieważ odpowiedź modelu może przy skomplikowanym zapytaniu trwać kilka sekund. AWS pozwala ustawić timeout maksymalnie do 15 minut, ale ustawianie tak wysokiego limitu nie jest wskazane, jeśli nie potrzebujemy. Dobrą praktyką jest ustawić timeout nieco powyżej oczekiwanego czasu obsługi żądania. Dla prostego pytania do ChatGPT często wystarczy 5-10 sekund. Jeśli planujemy bardziej złożone operacje (np. sekwencyjne wywołania modelu, lub wywołanie modeli wysokopoziomowych jak GPT-4 które są wolniejsze), można dać więcej. Nie należy jednak ustawiać nadmiernie wysokiego limitu „na zapas”, bo w przypadku zawieszenia się funkcji, będziemy niepotrzebnie długo blokować zasoby. Warto też monitorować metrykę Duration w CloudWatch – jeśli zbliża się do limitu, to sygnał, by zbadać czy nie przekroczyć lub zoptymalizować działanie funkcji.
Pamięć i CPU – AWS Lambda pozwala przydzielić pamięć od 128 MB do 10 GB (10240 MB). Przydział pamięci wiąże się liniowo z przydziałem CPU (oraz sieci) – im więcej pamięci, tym więcej mocy obliczeniowej dostaje funkcja. Minimalna konfiguracja (128 MB) daje mało CPU, co może spowalniać wykonanie (np. przetwarzanie JSON, inicjalizację biblioteki TLS dla requestów itp.). Dla wywołań ChatGPT zwykle 128-256 MB wystarcza, bo sama operacja wysłania zapytania i odebrania odpowiedzi nie zużywa dużo pamięci. Jednak jeśli robimy dodatkowe operacje (np. przetwarzanie dużego tekstu przed wysłaniem do API), może być potrzebne więcej. Zwiększenie pamięci do 512 MB czy 1 GB często poprawia czas wykonania (dostajemy proporcjonalnie więcej CPU) – są nawet narzędzia do strojenia tego parametru. Należy wyważyć wydajność i koszt – Lambda rozlicza GB-sekundy, więc szybsze wykonanie przy większej pamięci może wyjść cenowo podobnie jak dłuższe przy mniejszej.
Obsługa odpowiedzi i błędów API OpenAI
Gdy otrzymujemy odpowiedź od OpenAI API, nasza funkcja może ją zwrócić bez zmian do klienta albo w jakiś sposób post-processingować. Często przydatne jest, jak wspomniano, wymuszenie formatu (np. JSON) już na poziomie prompta. Jeśli jednak model zwraca zwykły tekst, a nasza aplikacja potrzebuje JSON – możemy tu w funkcji dokonać parsowania lub opakowania w JSON (jak w przykładzie, gdzie zwracamy {"answer": "...tekst..."}).
Trzeba też pamiętać o możliwych błędach przy wywołaniu API modelu:
Błędy sieciowe lub serwera – np. tymczasowy problem z dostępem do API OpenAI, błąd DNS, timeout po stronie OpenAI itp. Należy to obsłużyć w kodzie (try/except). Dobrą praktyką jest zaimplementowanie retry z backoff – np. jeśli wywołanie zwraca wyjątek lub kod błędu 429/500, możemy spróbować ponowić po krótkiej przerwie. OpenAI w dokumentacji sugeruje użycie wykładniczego backoff przy kodach błędów wskazujących na przekroczenie limitów. Pamiętajmy jednak, że Lambda ma swój maksymalny czas – nie można w nieskończoność ponawiać. Zazwyczaj 2-3 próby w odstępie np. 1s, 2s są rozsądne.
Błędy limitów (429 Too Many Requests) – OpenAI API ma ograniczenia liczby zapytań na minutę oraz tokenów na minutę, różne w zależności od modelu i naszego konta. W środowisku serverless istnieje ryzyko, że nagły burst wielu równoległych wywołań Lambda spowoduje skokowe wysłanie wielu zapytań do API – co może przekroczyć limit (np. dla darmowego konta to może być tylko kilkadziesiąt zapytań na minutę). Dlatego w przypadku aplikacji o zmiennym obciążeniu warto:
Używać mechanizmów kolejkowania lub ograniczania równoległości. Np. zamiast pozwolić na 1000 równoczesnych wywołań Lambda do OpenAI, można kierować zadania do kolejki (SQS) i mieć jedną/paredziesiąt funkcji pobierających z kolejki z kontrolowaną szybkością. Albo zastosować Concurrency Limit dla funkcji (AWS Lambda pozwala ustawić maks. liczbę jednoczesnych instancji dla danej funkcji).
Monitorować błędy 429 i ewentualnie logować/alertować, by móc podnieść plan OpenAI lub zmniejszyć częstotliwość żądań.
Błędy w danych – np. użytkownik poda prompt powodujący, że odpowiedź przekroczy dopuszczalny kontekst/tokeny. API zwróci błąd (HTTP 400). Takie sytuacje też trzeba obsłużyć – np. zwrócić użytkownikowi komunikat o zbyt długim pytaniu. Można przed wywołaniem sprawdzać długość prompta (tokenizerem) i np. ciąć lub odrzucać nadmierne.
Lambda powinna łapać wyjątki i zwracać sensowny komunikat/stan błędu. W przeciwnym razie błąd spowoduje Function error widoczny tylko w logach, a klient dostanie np. 502 od API Gateway. Lepiej zwrócić np. {"error": "OpenAI API error: ..."} with status 500 w kontrolowany sposób.
Logowanie i monitoring
AWS Lambda integruje się z Amazon CloudWatch Logs – wszystko co wypiszemy na stdout/console.log/print zostanie tam zapisane. Warto logować kluczowe informacje przy debugowaniu, np. parametry wejściowe (uwaga by nie logować poufnych danych jak pełny prompt jeśli zawiera dane osobowe), czasy wywołań (można zmierzyć czas wywołania OpenAI API i logować). CloudWatch Logs pozwala potem wyszukiwać i analizować logi, co przyda się przy troubleshooting.
Dodatkowo Lambda generuje metryki (CloudWatch Metrics) – m.in. liczba wywołań, czas trwania (Duration), błędy, procent błędów, użycie pamięci, liczba zimnych startów (Init Duration metric). Warto ustawić alarmy CloudWatch na niektóre z tych metryk: np. alarm gdy pojawia się błąd (Error count > 0 w ciągu 5 minut) aby szybko się dowiedzieć, jeśli funkcja zacznie zwracać błędy (np. z powodu zmiany w API OpenAI). Można też monitorować sumaryczny czas wykonania i liczbę wywołań, co przyda się do estymacji kosztów.
Jeśli nasza funkcja jest częścią większej aplikacji, można rozważyć użycie AWS X-Ray do śledzenia rozproszonego (distributed tracing) – szczególnie gdy funkcja wywołuje inne usługi AWS. W przypadku wywołania zewnętrznego API, X-Ray co prawda nie prześledzi nas do serwerów OpenAI, ale pokaże np. ile trwało dane podzapytnie, i czy ewentualnie były próby ponawiania. Włączenie X-Ray wymaga dodania uprawnień (i trochę wpływa na wydajność), więc to opcja dodatkowa.
Koszty
Krótko warto wspomnieć o kosztach: korzystając z ChatGPT przez Lambdę ponosimy podwójny koszt – za wykonanie funkcji (czas * RAM * stawka) oraz za użycie API OpenAI (liczba tokenów wejścia/wyjścia). W większości scenariuszy koszt OpenAI będzie dominujący (np. kilka centów za wywołanie modelu na kilkaset słów), bo samo wykonanie Lambdy trwającej 2 sekundy na 256 MB pamięci to ułamek centa. Mimo to, należy mieć to na uwadze – brak limitów w Lambdzie mógłby potencjalnie wygenerować duży rachunek z OpenAI, jeśli np. wpadniemy w pętlę wywołań. W AWS można skonfigurować budżety i alarmy kosztowe. Lambda ma też mechanizm Concurrency Limit wspomniany wcześniej, który nie tylko pomaga z rate limitami, ale i ogranicza maksymalne równoległe wydatki.
Po omówieniu AWS przejdźmy do analogicznej integracji w Google Cloud.
Implementacja na Google Cloud Functions
Google Cloud Functions (GCF) pełnią podobną rolę w ekosystemie GCP co Lambda w AWS. Możemy w nich zrealizować ChatGPT cloud functions obsługujące zapytania do modelu OpenAI. Wiele koncepcji jest podobnych, ale warto podkreślić kilka różnic i najlepszych praktyk specyficznych dla GCP.
Tworzenie funkcji i wyzwalacz HTTP
W GCP najczęstszym przypadkiem użycia dla integracji z ChatGPT będzie funkcja z wyzwalaczem HTTP Trigger. Podczas wdrażania Cloud Function wskazujemy, że będzie ona wyzwalana żądaniami HTTP (HTTPS). Platforma automatycznie przydzieli unikalny URL (można go zabezpieczyć przez Identity-Aware Proxy lub zezwolić na unauthenticated, zależnie od potrzeb). Taka funkcja HTTP jest odpowiednikiem Lambda + API Gateway w jednym – wystawiona jako endpoint, wywoływana przez HTTP i zwraca odpowiedź HTTP.
Kod funkcji w Pythonie mógłby wyglądać tak (korzystając z biblioteki functions_framework, którą GCP używa do obsługi Pythona):
import functions_framework
import os, json
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
@functions_framework.http
def chatgpt_request(request):
data = request.get_json(silent=True)
prompt = data.get("query") if data else ""
try:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role":"user", "content": prompt}]
)
answer = response["choices"][0]["message"]["content"]
return (json.dumps({"answer": answer}), 200, {"Content-Type": "application/json"})
except Exception as e:
return (json.dumps({"error": str(e)}), 500, {"Content-Type": "application/json"})
Tu analogicznie pobieramy klucz API z env, wywołujemy ChatGPT i zwracamy JSON. Wykorzystanie dekoratora @functions_framework.http sprawia, że GCF rozpoznaje tę funkcję jako punkt wejścia dla HTTP.
Uwagi dot. wdrożenia: Cloud Functions 1st gen umożliwiają proste wdrożenie przez komendę gcloud functions deploy nazwa --runtime python310 --trigger-http --allow-unauthenticated --set-env-vars OPENAI_API_KEY=xxx. Druga generacja (GCF 2nd gen) jest oparta o Cloud Run i wymaga nieco innego podejścia (można również użyć gcloud z flagą --gen2). Warto zaznaczyć, że Cloud Functions 2nd gen oferują więcej możliwości konfiguracji (np. concurrency, o czym za chwilę) i lepsze wykorzystanie zasobów, kosztem nieco dłuższego procesu wdrożenia (obraz kontenera budowany w tle).
Różnice w działaniu i parametrach
Czas wykonania (timeout): Dla Cloud Functions (1st gen) maksymalny czas to 9 minut. W 2nd gen funkcje HTTP mogą działać nawet do 60 minut (choć to skrajne przypadki – długie działanie raczej zrealizujemy na Cloud Run lub innej usłudze). Zatem GCP pozwala potencjalnie na dłuższe operacje. W kontekście ChatGPT typowo nie potrzebujemy tak długich czasów, ale jeśli planujemy np. wygenerować bardzo obszerną odpowiedź lub sekwencyjnie przetworzyć wiele danych przez model, musimy pamiętać o tym limicie. Zaletą 2nd gen jest możliwość znacznego wydłużenia czasu, ale takie użycie może wymagać podwyższenia limitów pamięci/CPU.
Pamięć i CPU: W GCF wybieramy pamięć, maksymalnie 16 GB (dla 2nd gen; 1st gen ma do 2GB). Przydział CPU jest zależny od pamięci (podobnie jak w AWS). Jeśli np. planujemy użyć bibliotek do przetwarzania danych przed wysłaniem do ChatGPT (jak np. biblioteka ML do przygotowania prompta), warto dopasować pamięć. Dla czystego wysłania żądania do OpenAI zwykle duża pamięć nie jest potrzebna – 256MB-512MB wystarcza.
Skalowanie i zimny start: Cloud Functions skaluje się automatycznie jak Lambda, ale odmiennie działa kwestia równoległych zapytań. W 1st gen Cloud Function obsługuje pojedynczo żądania – każda instancja przyjmuje jedno naraz (tak jak Lambda). Natomiast 2nd gen domyślnie obsługuje do 80 równoległych żądań na instancję (bo pod spodem jest to Cloud Run) i można to konfigurować do nawet 1000. Oznacza to, że jeśli nasza usługa dostanie burst 100 zapytań, Cloud Functions 2nd gen może teoretycznie uruchomić tylko 2 instancje (po 50 zapytań każda) zamiast 100 instancji.
To redukuje liczbę zimnych startów i może być korzystne dla utrzymania stabilności – oczywiście pod warunkiem, że nasz kod jest bezpieczny pod kątem współbieżności (w Pythonie np. globalny interpreter lock sprawia, że i tak faktycznie obsłuży je sekwencyjnie, ale na zmianę – w Node.js async też radzi sobie z concurrency). Google Cloud Functions jest często chwalone za mniejsze narzuty zimnego startu niż Lambda, zwłaszcza dla funkcji HTTP. W praktyce różnice mogą być niewielkie, ale np. przy prostych funkcjach Node.js GCF potrafi startować bardzo szybko. Tak czy inaczej, optymalizacje typu trzymanie zależności lean (jak w AWS) też tu obowiązują.
Sekrety i konfiguracja: W GCP mamy kilka opcji przekazania klucza API:
Jako zmienna środowiskowa – analogicznie jak w AWS. Jednak, warto wiedzieć, że w GCP do niedawna takie zmienne nie były szyfrowane domyślnie tak jak w AWS. Osoby z rolą Viewer projektu mogły podejrzeć wartości zmiennych w konfiguracji funkcji. Google wprowadziło natywną integrację z Secret Manager żeby rozwiązać ten problem. Zamiast --set-env-vars OPENAI_API_KEY=xyz, możemy użyć --set-secrets OPENAI_API_KEY=my_secret_name:latest podczas deploy. Wtedy Cloud Functions automatycznie pobierze aktualną wartość sekretu z Secret Manager i udostępni ją funkcji w zmiennej o nazwie OPENAI_API_KEY. Dzięki temu tajne klucze nie są zapisane wprost w konfiguracji funkcji, tylko referencje do sekretu, a ich odszyfrowanie następuje w izolowanym środowisku wykonawczym. Zdecydowanie zaleca się tę metodę w środowiskach produkcyjnych.
Alternatywnie, sami możemy w kodzie klienta Secret Managera pobierać sekret (np. przy starcie funkcji), ale skoro istnieje natywna integracja, lepiej z niej skorzystać. W obu przypadkach trzeba dać naszej funkcji uprawnienie do odczytu danego sekretu (można to zrobić przypisując odpowiednią rolę Secret Manager Secret Accessor do service account funkcji).
Service Account – każda funkcja działa z uprawnieniami konta serwisowego (domyślnie PROJECT_ID@appspot.gserviceaccount.com dla 1st gen). Należy rozważyć utworzenie oddzielnego konta serwisowego tylko dla tej funkcji, z minimalnymi uprawnieniami. Np. jeżeli używamy Secret Managera, konto powinno mieć dostęp tylko do konkretnego sekretu, nic więcej. Z definicji, funkcja nie potrzebuje wielu uprawnień do GCP, bo głównie łączy się z zewnętrznym API. Włączenie zasady least privilege podnosi bezpieczeństwo (ograniczy skutki ewentualnego naruszenia funkcji). Google zaleca izolowanie funkcji na osobnych kontach i stosowanie najmniejszych uprawnień.
Monitoring i logi: GCF wysyła logi do Cloud Logging (dawniej Stackdriver). W kodzie Python można normalnie używać print lub loggera – wszystko trafia do centralnych logów GCP. Tam możemy filtrować po funkcji, czasie, poziomie itp. Cloud Functions także raportują metryki do Cloud Monitoring – np. czas wykonania, liczbę wywołań, błędy. Możemy ustawiać alerty podobnie jak w AWS (np. gdy pojawi się więcej niż X błędów w ciągu 5 minut).
Obsługa błędów: Cloud Functions HTTP zwraca kody odpowiedzi jak ustawimy (np. w przykładzie wyżej 500 dla wyjątku). Jeśli funkcja rzuci wyjątek nieobsłużony, GCF domyślnie zwróci 500. W przypadku funkcji wyzwalanych innymi zdarzeniami (np. Pub/Sub, Cloud Storage), niewywowanie niepowodzenia spowoduje ponowne próby (kilkukrotne) zgodnie z wbudowanym mechanizmem retry GCP. Dla ChatGPT typowo używamy HTTP trigger, więc to klient musi ewentualnie ponowić żądanie, ale nic nie stoi na przeszkodzie, by GCF też próbowała (np. jeśli mamy wewnętrzny mechanizm jak Cloud Tasks czy wywołanie z innej funkcji).
Podobnie jak na AWS, warto zaimplementować retry logic przy wywołaniu OpenAI API i uważać na rate limit. W GCP również możemy mieć wiele instancji funkcji wołających równolegle API OpenAI – grozi to przekroczeniem limitów. Z tą różnicą, że w 2nd gen, jak wspomniano, może nastąpić obsłużenie wielu żądań na jednej instancji sekwencyjnie. To trochę zmniejsza wyzwanie, bo nie przyrośnie nam aż tak gwałtownie liczba równoległych połączeń, ale mimo wszystko – projektując pod dużą skalę, lepiej przewidzieć ograniczenia. W razie potrzeby można w GCP wykorzystać Cloud Tasks do kolejkowania żądań HTTP w kontrolowanym tempie.
Azure Functions – wzmianka
Platforma Azure również oferuje uruchamianie kodu serverless poprzez Azure Functions. Konceptualnie jest to zbliżone do AWS Lambda/GCF: tworzymy funkcję (np. w Pythonie lub Node.js), możemy wystawić ją jako HTTP trigger lub reagować na zdarzenia (Service Bus, Event Grid, itp.), a w kodzie wywołujemy API OpenAI.
W przypadku Azure mamy dwie opcje integracji z modelami:
Korzystać z publicznego API OpenAI (tak jak w AWS/GCP) – wówczas działamy identycznie, potrzebujemy klucza OpenAI, wysyłamy zapytanie do endpointu api.openai.com i odbieramy odpowiedź. W Azure Functions warto klucz API przechować w Application Settings (które są odpowiednikiem zmiennych środowiskowych; są one domyślnie ukryte i szyfrowane, szczególnie jeśli włączymy Azure Key Vault references). Można też bezpośrednio zintegrować Key Vault, aby nie trzymać sekretu w konfiguracji jawnie.
Skorzystać z Azure OpenAI Service – czyli usługi Azure, w której Microsoft hostuje modele OpenAI (GPT-3, GPT-4) w obrębie swojej chmury. Jeśli nasza organizacja używa Azure OpenAI, to zamiast łączyć się do publicznego endpointu, będziemy łączyć się do prywatnego endpointu usługi w naszym regionie Azure. Wywołanie z Azure Functions wygląda podobnie, tylko inne URL i klucze (autoryzacja poprzez Azure AD lub klucz usługi). Warto wspomnieć, że artykuł dotyczy bezserwerowego uruchamiania ChatGPT w chmurze publicznej, niezależnie czy to OpenAI czy Azure OpenAI – mechanizmy są podobne, zmienia się dostawca API.
Ze względu na skupienie na AWS i GCP, nie będziemy tutaj wchodzić w szczegóły implementacji Azure (to temat na osobny przewodnik). Wystarczy pamiętać, że Azure Functions umożliwiają to samo: w Pythonie instalujemy openai poprzez requirements.txt, w kodzie pobieramy klucz (np. os.environ["OPENAI_API_KEY"] z konfiguracji funkcji) i wykonujemy openai.ChatCompletion.create(...). Możemy np. stworzyć funkcję HTTP, która przyjmuje parametr zapytania i zwraca wynik modelu w HTML lub JSON.
Przykłady takiego użycia są dostępne – np. krok po kroku opisano stworzenie funkcji Python na Azure do wywoływania ChatGPT API. Konfiguracja timeoutów i pamięci w Azure zależy od planu: w Consumption Plan domyślny timeout to 5 minut, w planie Premium/dedykowanym może być dłuższy. Pamięć i CPU są powiązane z wybranym SKU. Koncepcja zimnego startu też występuje (Consumption Plan funkcje mogą mieć opóźnienie po bezczynności). Azure Functions udostępniają Application Insights do logowania i monitoringu – tam możemy śledzić wywołania i ewentualne błędy.
Podsumowując, Azure oferuje parytet funkcjonalny – wszystko co zrobimy w Lambda czy GCF, da się zrealizować na Azure Functions w bardzo podobny sposób. Dlatego wybór platformy często zależy od środowiska w jakim pracujemy (np. preferencji firmy co do chmury).
Przykładowe zastosowania (Use Cases)
Poniżej przedstawiamy kilka realnych scenariuszy, gdzie połączenie serverless + ChatGPT daje wymierne korzyści. Te event-driven AI workflows i automatyzacje pokazują, jak można praktycznie wykorzystać opisaną technologię.
Automatyzacja zadań tekstowych (Serverless automation with ChatGPT)
Jednym z oczywistych zastosowań jest automatyczne przetwarzanie lub generowanie tekstu. Funkcje serverless z ChatGPT mogą działać jako „mikro-usługi” wykonujące konkretne zadania tekstowe na żądanie:
Transformacja tekstu: Np. funkcja wyzwalana przez wrzucenie pliku tekstowego do bucketu S3 może pobrać ten plik, poprosić ChatGPT o przetłumaczenie go na inny język lub sparafrazowanie, po czym zapisać wynik do innego miejsca. Wszystko to bez serwerów – wrzucamy plik i za chwilę dostajemy przetworzony wynik.
Streszczanie dokumentów: Można zbudować system, gdzie po dodaniu nowego dokumentu (np. PDF-a) do określonej lokalizacji, wywoływana jest Lambda, która ekstraktuje tekst i wysyła do ChatGPT z prośbą o podsumowanie. Skrót dokumentu jest następnie zapisywany np. w bazie lub wysyłany mailem do zainteresowanych. Taki mechanizm mógłby wspomóc analityków lub pracowników, automatycznie przygotowując streszczenia długich raportów.
Klasyfikacja i tagowanie: ChatGPT radzi sobie również z kategoryzowaniem tekstu. Możemy więc wywoływać go, by nadał etykiety/tematy wiadomościom, komentarzom użytkowników itp., i zapisywać te informacje do bazy. Funkcja mogłaby reagować np. na pojawienie się nowego wpisu w bazie (trigger z DynamoDB lub Firestore) i uzupełniać go o pola „kategoria” czy „sentiment” korzystając z AI.
Automatyzacja tego typu odciąża ludzi od żmudnych zadań i może działać 24/7. Przykładem może być wewnętrzny system helpdesk: zgłoszenie od pracownika trafia do kolejki, gdzie Lambda z ChatGPT od razu nadaje priorytet i kategoryzuje zgłoszenie (na podstawie treści określa, czy dotyczy IT, HR, czy innego działu), a nawet proponuje wstępną odpowiedź lub rozwiązanie z bazy wiedzy. Taka funkcja może następnie automatycznie utworzyć rekord w systemie (np. ServiceNow, Jira) i przygotować draft odpowiedzi. To co normalnie wymagałoby manualnej analizy, tutaj dzieje się w sekundach.
Przepływy oparte na zdarzeniach (Event-driven AI workflows)
Serverless świetnie wpisuje się w architekturę zdarzeniową – reaguje na eventy. Dodając do tego ChatGPT, otrzymujemy inteligentne reakcje na zdarzenia. Oto kilka przykładów:
Obsługa e-maili i tickety: Wyobraźmy sobie system supportowy, gdzie przychodzi e-mail od klienta. Zamiast czekać na pracownika, automatycznie uruchamia się funkcja (wyzwolona przez np. usługę pocztową w chmurze), która przekazuje treść maila do ChatGPT i generuje wstępną odpowiedź. Następnie ta odpowiedź jest wysyłana zwrotnie do klienta, a ewentualnie tworzony jest ticket w systemie CRM/Helpdesk. Taki webhook oparty na e-mailu pozwala zautomatyzować prostą korespondencję. Rzeczywiście, istnieją już rozwiązania wykorzystujące Lambdę, Amazon WorkMail i SES do automatycznego odpowiadania na maile za pomocą ChatGPT – przychodzący e-mail wyzwala Lambdę, która generuje odpowiedź (np. z numerem zgłoszenia lub podstawową informacją) i wysyła ją przez Amazon SES. To może odciążyć pierwszy kontakt z klientem i dać mu natychmiastową odpowiedź, zanim człowiek zajmie się sprawą.
Harmonogramy i prace okresowe: Możemy zaplanować cykliczne wywoływanie funkcji z ChatGPT, aby wykonywać pewne zadania o stałej porze. Np. codziennie o 7:00 funkcja zbiera istotne informacje (sprzedaż, metryki z dnia poprzedniego) i prosi ChatGPT o wygenerowanie krótkiego raportu/kokpitu menedżerskiego, który następnie wysyła e-mailem decydentom. Albo wspomniana wcześniej bajka na dobranoc – każdego dnia o 19:15 EventBridge wyzwala pipeline AI generujący nową bajkę dla dziecka. Możliwości są nieograniczone – kluczowe jest, że zdarzeniem może być także określony czas.
Reakcje na zmiany w danych: Przykład: system IoT zbiera duże ilości logów/sensorów, i gdy wykryty zostanie jakiś nietypowy wzorzec (np. wzrost temperatury powyżej progu), wysyła zdarzenie. Funkcja AI mogłaby to zdarzenie przejąć i wygenerować opisową diagnozę lub sugestię działania (np. „Czujnik X prawdopodobnie uległ awarii, zalecana inspekcja”). ChatGPT potrafi analizować opis problemu i formułować rekomendacje – opakowanie tego w serverless pozwala reagować w czasie rzeczywistym na setki urządzeń.
Pipeline wieloetapowe: Architektura zdarzeniowa z AI może obejmować wiele etapów. Np. po wygenerowaniu czegoś przez ChatGPT (historia, e-mail) możemy wyzwolić kolejne funkcje: jedna wygeneruje obraz do tej historii (np. wywołując DALL-E lub Stability AI), inna przetworzy tekst na mowę (AWS Polly) tworząc audiobook, a kolejna wyśle powiadomienie. Wszystkie te komponenty komunikują się eventami i kolejnymi triggerami. Dzięki temu całość jest zdekomponowana na małe funkcje, które skalują się niezależnie i mogą być rozwijane osobno.
Taki event-driven styl idealnie pasuje do serverless i pozwala budować bardzo modularne, skalowalne aplikacje AI. Przykład z AWS pokazuje, że zaawansowane pipelines (z EventBridge, SNS, DynamoDB Streams) mogą orkiestrująco spinać różne usługi AI i klasyczne. ChatGPT może działać jako jeden z „mikroserwisów” w takim ekosystemie, odpowiedzialny np. za generowanie tekstowych wyników, podczas gdy inne zajmują się innymi modalnościami.
Logika backendowa wzbogacona AI
Innym obszarem jest wykorzystanie ChatGPT wewnątrz logiki biznesowej aplikacji – czyli nie jako coś wprost widocznego dla użytkownika końcowego, lecz jako decyzyjny lub wzbogacający moduł w tle:
Walidacja i poprawa danych: Wyobraźmy sobie formularz, gdzie użytkownik opisuje słownie swój problem. Zamiast zapisywać ten chaotyczny tekst bezpośrednio, nasz backend (np. funkcja wyzwalana przez API GraphQL) może przekazać opis do ChatGPT prosząc: „Przeanalizuj zgłoszenie i wyodrębnij kluczowe informacje: czego dotyczy problem, jak pilny, jakiego produktu dotyczy”. Model zwraca ustrukturyzowaną odpowiedź, którą zapisujemy w bazie. W ten sposób dane trafiają do systemu w bardziej uporządkowanej formie – łatwiej je potem przeszukiwać czy raportować. To trochę jak byśmy mieli bardzo bystrego asystenta, który czyta każde zgłoszenie i dopisuje notatki.
Wzbogacanie bazy wiedzy / enrichment: Gdy do systemu wchodzi nowy element (np. artykuł, dokumentacja), funkcja AI może automatycznie wygenerować streszczenie, wyciągnąć najważniejsze słowa kluczowe, zaproponować gdzie to skatalogować. To może działać np. przy publikacji nowego artykułu na intranecie – ChatGPT wygeneruje krótki opis i tagi, co ułatwi potem rekomendacje innym użytkownikom.
Decyzje oparte na opisie: ChatGPT potrafi na podstawie opisu zasugerować rozwiązanie – np. klient pisze: „Mój produkt X zacina się przy robieniu Y”, funkcja może zapytać model: „Do jakiego działu powinno trafić to zgłoszenie? Jakie są potencjalne przyczyny problemu?” i na tej podstawie zdecydować, czy automatycznie otworzyć proces reklamacji, przekazać do działu wsparcia, czy poprosić klienta o więcej informacji. To jest automatyzacja kroków decyzyjnych, które normalnie wykonuje człowiek czy prosty system ekspertowy – tutaj robi to model językowy w bardziej elastyczny sposób.
Przykładem może być automatyzacja w e-commerce: klient zostawia komentarz do zamówienia „Paczka uszkodzona, produkt zepsuty”. Lambda może wykryć takie komentarze w strumieniu zamówień i z pomocą ChatGPT zaklasyfikować to jako roszczenie gwarancyjne oraz automatycznie wygenerować uprzejmą odpowiedź z przeprosinami i instrukcją zwrotu. Takie rzeczy są wdrażane – np. serwisy jak Amazon mają wewnętrzne systemy AI wspomagające obsługę klienta. My, dzięki serverless, możemy tworzyć mniejsze wersje takich rozwiązań, szyte na miarę naszej firmy.
Zadania asynchroniczne i w tle
Nie wszystkie użycia ChatGPT muszą być wywoływane bezpośrednio przez akcje użytkownika. Często chcemy wykonać pewne przetwarzanie wsadowe lub harmonogramowe. Serverless świetnie nadaje się do takich zadań, bo możemy je zaplanować lub uruchamiać na żądanie, płacąc tylko za czas faktycznego działania:
Batch processing: Załóżmy, że co tydzień chcemy wygenerować raport podsumowujący opinie klientów z całego tygodnia. Mamy bazę tysiąca opinii z ostatnich 7 dni. Możemy uruchomić funkcję (np. wyzwoloną z Crona), która pobierze te opinie, podzieli je na grupy i kilkukrotnie wywoła ChatGPT prosząc o syntetyczny raport: najczęściej pojawiające się pochwały, najczęstsze skargi, przykładowe cytaty. Model wygeneruje nam elegancki raport w języku naturalnym, który następnie funkcja np. zapisze do pliku PDF lub wyśle zainteresowanym. Taka czynność jednorazowo może potrwać kilkadziesiąt sekund, ale nie szkodzi – wykona się raz w tygodniu i nie angażuje żadnego człowieka.
Uzupełnianie danych offline: Czasami opłaca się obrabiać dane po fakcie. Np. serwis społecznościowy chce nadać każdemu wpisowi pewien score jakości lub streszczenie – zamiast robić to przy każdym dodaniu (co obciążałoby ścieżkę zapisu), można co godzinę uruchamiać funkcję, która weźmie nowe wpisy z ostatniej godziny i dla każdego wywoła ChatGPT z prośbą o ocenę lub podsumowanie, a wynik zapisze do bazy. Użytkownicy nie potrzebują tego w real-time, a w ten sposób nie blokujemy szybkości dodawania treści, tylko asynchronicznie je wzbogacamy.
Obsługa zadań przekraczających limity pojedynczej funkcji: Jeżeli mamy zadanie zbyt duże jak na pojedyncze wywołanie (np. przetworzenie bardzo długiego tekstu, co mogłoby trwać ponad limit lub wymagać więcej pamięci), możemy zastosować podejście dziel i rządź z kolejkami. Np. Lambda A dzieli dokument na części i wrzuca do kolejki SQS, a wiele instancji Lambdy B pobiera fragmenty i równolegle prosi ChatGPT o streszczenie każdego fragmentu, wyniki składamy w całość. Albo – tak jak w jednym z przykładów AWS – Lambda umieszcza zadanie w kolejce, a dedykowany proces (np. kontener ECS) wykonuje naprawdę ciężkie zadanie ML, po czym funkcja finalizująca zbiera wyniki. W naszym kontekście, jeśli ChatGPT (czy raczej GPT-4) potrzebowałby np. 2 minut na wygenerowanie czegoś, to może lepiej przekazać to zadanie do usługi typu Cloud Run, AWS Fargate czy Azure WebJob, a Lambdę wykorzystać do orkiestracji. Serverless może więc pełnić rolę „kleju” nawet w batch processingu – np. reaguje na plik w blob storage i rozdziela pracę na mniejsze kawałki.
Podsumowując, funkcje bezserwerowe z ChatGPT otwierają wiele scenariuszy zastosowań. Od natychmiastowych odpowiedzi i automatyzacji komunikacji, przez tło i wsparcie dla zespołów (analiza danych, kategoryzacja), po złożone przepływy zdarzeń budujące nowe doświadczenia (generowanie spersonalizowanych treści, storytelling na żądanie itp.). Kluczem jest to, że inżynierowie mogą w prosty sposób wpleść zaawansowaną AI w istniejące ekosystemy chmurowe. Bez potrzeby budowania dedykowanych serwerów czy aplikacji – wykorzystujemy istniejące chmurowe klocki.
Podsumowanie
Integracja ChatGPT z architekturą bezserwerową pozwala tworzyć nowy rodzaj aplikacji – inteligentne, skalowalne i ekonomiczne. W tym artykule skupiliśmy się na praktycznym aspekcie uruchamiania ChatGPT w chmurze poprzez funkcje serverless na AWS, Google Cloud i Azure. Omówiliśmy, jak zbudować taką funkcję, jak bezpiecznie przekazać klucz API, jak obsługiwać odpowiedzi i błędy oraz na co zwrócić uwagę przy konfiguracji (timeouty, pamięć, zimne starty). To wszystko składa się na solidną AI serverless architecture, która łączy zalety chmury (automatyczne skalowanie, brak zarządzania infrastrukturą) z mocą modeli językowych.
Kilka najważniejszych wniosków i rad na koniec:
Zawsze zabezpieczaj tajne klucze i dane konfiguracyjne. Wykorzystaj zmienne środowiskowe zabezpieczone przez dostawcę chmury lub dedykowane usługi do sekretów (AWS Secrets Manager, GCP Secret Manager, Azure Key Vault). Unikaj trzymania kluczy API w kodzie źródłowym czy w logach.
Przemyśl skalowanie i limity. Serverless da Ci niemal nieograniczone skalowanie wywołań – ale upewnij się, że pasuje to do limitów OpenAI. Wprowadzaj mechanizmy kolejkowania lub ograniczania, jeśli istnieje ryzyko zbombardowania API zbyt wieloma żądaniami na raz. Monitoruj błędy 429 i dostosowuj rozwiązanie.
Dbaj o wydajność funkcji. Optymalizuj rozmiar paczek z kodem (usuń zbędne zależności), inicjalizuj zasoby tylko raz (poza głównym handlerem), rozważ wyższe przydziały pamięci dla większej mocy CPU, jeśli to skróci czas działania. Zwróć uwagę na zimne starty – w razie potrzeby użyj rozwiązań typu Provisioned Concurrency na AWS lub odpowiednio ustaw concurrency na GCP, aby sprostać wymaganiom niskich opóźnień.
Testuj i loguj. Zanim wdrożysz produkcyjnie, przetestuj funkcję ze zróżnicowanymi zapytaniami. Sprawdź, jak radzi sobie z dłuższymi promptami, czy poprawnie obsługuje błędy (np. zasymuluj brak internetu lub błędny klucz API). W logach upewnij się, że nie pozostawiasz wrażliwych informacji, a jednocześnie że masz dość danych by diagnozować problemy.
Rozszerzaj stopniowo zakres AI. Często warto zacząć od małego, konkretnego przypadku użycia (np. automatyczna odpowiedź na jedno specyficzne pytanie klienta) i obserwować wyniki. Z czasem możesz dodawać kolejne funkcje AI w innych miejscach systemu. Dzięki serverless, każdy taki dodatek jest niezależny i łatwy do wdrożenia bez wpływu na resztę architektury.
Na koniec, pamiętajmy że modele pokroju ChatGPT ciągle się rozwijają, a ich API może się zmieniać. Trzymaj rękę na pulsie, jeśli chodzi o wersje modeli, nowe parametry (np. function calling, który może jeszcze bardziej ułatwić integrację z backendem) czy zmiany w limitach OpenAI. Serverless AI to obszar, który będzie coraz ważniejszy – pozwala bowiem budować aplikacje reagujące na zdarzenia i podejmujące „inteligentne” działania, co jeszcze niedawno było domeną science fiction. Teraz jest to dostępne dla każdego developera chmurowego – wystarczy kreatywność w wymyślaniu zastosowań i solidne podstawy, które – mamy nadzieję – ten przewodnik pomógł Ci zyskać.

