Jak połączyć AWS Lambda z AI

You are currently viewing Jak połączyć AWS Lambda z AI

Wstep

Jeszcze kilka lat temu zbudowanie własnego asystenta AI oznaczało serwer, backend i całkiem sporą wiedzę o infrastrukturze. Trzeba było coś postawić, utrzymywać i pilnować, żeby całość się nie wysypała przy większym ruchu. Dzisiaj wygląda to zupełnie inaczej.

Wystarczy jedna funkcja w chmurze, kilkadziesiąt linijek kodu i klucz API do modelu językowego. Resztą zajmuje się AWS.

Połączenie serverless + AI to jedno z tych rozwiązań, które faktycznie obniżają próg wejścia. Nie konfigurujesz maszyn wirtualnych EC2, nie martwisz się o skalowanie i nie płacisz za serwer, który przez większość czasu stoi bezczynnie. Tworzysz funkcję Lambda, podpinasz ją pod publiczny endpoint i gotowe – Twój bot działa w chmurze, dokładnie wtedy, kiedy ktoś go wywoła.

W tym artykule pokażę Ci, jak zrobić to w praktyce. Zbudujemy prostą architekturę, w której klient wysyła zapytanie do AWS Lambda przez Function URL, a Lambda przekazuje je do API OpenAI i zwraca odpowiedź. Bez serwera, bez zbędnej konfiguracji i bez dużych kosztów na start.

Zaczniemy od najprostszej wersji, którą da się uruchomić w kilka minut. Potem przejdziemy przez typowe pułapki, na które bardzo łatwo się nadziać – timeouty, pamięć, zależności. Na końcu pokażę też kierunki dalszej rozbudowy, dzięki którym z prostego endpointu możesz dojść do rozwiązania gotowego na realne użycie.

Dlaczego Serverless + AI to dobre połączenie?

Zanim zaczniemy pisać kod warto się zastanowić dlaczego w ogóle męczyć się z chmurą AWS, zamiast postawić prosty serwer w Pythonie na VPS-ie? Przecież to tylko kilka linijek kodu.

Tutaj wchodzą trzy kluczowe argumenty, które sprawiają, że Serverless (w tym przypadku AWS Lambda) jest dobrym wyborem dla usług AI.

Połączenie między AWS Lamda a AI - Grafika wygenerowana z gemini

Problem „idle time” (czasu bezczynności)

Wyobraź sobie, że stawiasz bota na tradycyjnym serwerze. Płacisz za ten serwer miesięczny abonament. Twój bot jest popularny w godzinach pracy, powiedzmy od 9:00 do 17:00. A co dzieje się w nocy? Co w weekendy? Serwer działa, prąd płynie, a Ty płacisz za… czekanie na zapytanie. W przypadku chatbotów i asystentów AI, ruch jest bardzo nieregularny.

AWS Lambda działa w modelu event-driven. Funkcja „śpi”, dopóki nie nadejdzie żądanie. Budzi się, wykonuje zadanie, zwraca odpowiedź i natychmiast znika. Nie płacisz ani grosza za czas, w którym nikt nie korzysta z Twojego rozwiązania.

Automatyczne skalowanie

To scenariusz marzenie: Twój asystent staje się viralem. W tradycyjnym podejściu Twój serwer pada pod naporem zapytań. Musisz szybko dokupić RAM, CPU, restartować usługi.

W AWS Lambda skalowanie jest (prawie) magiczne. Jeśli w jednej sekundzie przyjdzie 10 zapytań – AWS uruchomi 10 niezależnych instancji Twojej funkcji. Jeśli przyjdzie ich 1000 – AWS postara się uruchomić 1000 instancji (do limitu Twojego konta). Dzieje się to automatycznie, bez Twojej ingerencji. Dla Ciebie obsługa jednego użytkownika i tysiąca wygląda tak samo.

Model kosztowy

AWS Lambda rozlicza się za GB-sekundy. Oznacza to, że płacisz za ilość przydzielonej pamięci RAM pomnożoną przez czas trwania funkcji (z dokładnością do 1 ms).

Biorąc pod uwagę, że „Free Tier” w AWS oferuje 400 000 GB-sekund miesięcznie za darmo, a nasze zapytanie do OpenAI trwa zazwyczaj od kilku do kilkunastu sekund zużywając niewiele pamięci, możesz przeprowadzać tysiące rozmów miesięcznie, nie płacąc Amazonowi absolutnie nic. Twój jedyny realny koszt to tokeny po stronie OpenAI (o czym napisze później).

Jeśli chcesz zagłębić się w model kosztowy AWS, wszystkie dane są publicznie dostępne i bez problemu możesz samodzielnie policzyć, ile będzie kosztowało korzystanie z danej usługi. W przypadku AWS Lambda szczegółowy cennik i przykłady rozliczeń znajdziesz na dedykowanej stronie AWS.

Co potrzebujesz na start

Zanim przejdziemy do tworzenia funkcji Lambda, upewnij się, że masz przygotowane kilka rzeczy.

Konto AWS

Jeśli jeszcze go nie masz, rejestracja jest darmowa i zajmuje kilka minut. AWS oferuje nowym klientom całkiem hojny pakiet startowy – do $200 w kredytach. Przy rejestracji dostajesz $100, a kolejne $100 możesz zdobyć eksplorując kluczowe usługi AWS.

Do tego masz do wyboru dwa plany. Free Plan pozwala korzystać z AWS przez 6 miesięcy bez żadnych opłat (dopóki nie przekroczysz limitów kredytowych). Paid Plan daje dostęp do pełnej oferty ponad 150 usług z modelem pay-as-you-go. Na potrzeby tego poradnika Free Plan w zupełności wystarczy.

Konto założysz na stronie aws.amazon.com/free. Podczas rejestracji będziesz musiał podać kartę płatniczą, ale w ramach Free Plan nic nie zostanie pobrane, dopóki sam nie przełączysz się na Paid Plan.

Konto OpenAI z kluczem API

Tutaj ważna uwaga: samo konto na OpenAI to za mało. Żeby korzystać z API, musisz mieć doładowane kredyty. Bez nich każde zapytanie zwróci błąd.

Klucz API wygenerujesz po zalogowaniu na platform.openai.com w sekcji API Keys. Zapisz go od razu w bezpiecznym miejscu – OpenAI pokazuje klucz tylko raz. Jeśli go zgubisz, musisz wygenerować nowy.

Przed pierwszym użyciem API doładuj konto w sekcji Billing. Kilka dolarów na start wystarczy do eksperymentów – bez kredytów API po prostu nie zadziała. Szczegóły dotyczące dostępnych modeli i cennika znajdziesz na stronie openai.com/api.

Widok na platformę open api keys

Podstawowa znajomość Pythona

Przykłady w tym artykule są napisane w Pythonie. Nie musisz być ekspertem – wystarczy, że rozumiesz podstawy: zmienne, funkcje, słowniki, obsługę JSON-a. Jeśli pisałeś kiedykolwiek skrypt w Pythonie, poradzisz sobie bez problemu.

Dlaczego Python, a nie Java? Mimo tego, że na co dzień sam programuje w Javie, to w przypadku AWS Lambda i szybkich integracji z API Python po prostu lepiej pasuje do tego typu zadań. Kod można edytować bezpośrednio w AWS Console, bez kompilacji i budowania plików JAR. Funkcje w Pythonie mają też krótszy cold start, co ma znaczenie przy rzadkich lub nieregularnych wywołaniach. Przy prostych operacjach w stylu „wywołaj API i zwróć odpowiedź” Python jest zwyczajnie wygodniejszy – mniej kodu, mniej narzutu, szybsze iteracje. Java nadal świetnie sprawdza się w większych, długowiecznych projektach, ale do prototypowania i lekkich funkcji Lambda Python jest bardziej naturalnym wyborem.

Krok 1 – Tworzenie funkcji Lambda

Czas przejść do praktyki. W tym kroku utworzymy funkcję Lambda i skonfigurujemy publiczny endpoint, przez który będzie można ją wywoływać.

Nawigacja w AWS Console

Zaloguj się do AWS Console i w pasku wyszukiwania wpisz „Lambda”. Wybierz usługę Lambda z listy wyników. Zobaczysz dashboard z listą funkcji – jeśli to Twoje pierwsze spotkanie z Lambda, lista będzie pusta.

Kliknij przycisk Create function w prawym górnym rogu. Powinieneś zobaczyć poniższy widok:

Widok na tworzenie funkcji w AWS Lambda

Podstawowa konfiguracja

Na ekranie tworzenia funkcji zostaw zaznaczoną opcję Author from scratch i wypełnij podstawowe dane:

  • Function name – nadaj funkcji sensowną nazwę, np. openai-assistant, gpt-lambda czy jakąkolwiek inną.
  • Runtime – wybierz język, w którym będziesz pisać kod. Dla Pythona wybierz Python 3.13 (lub najnowszą dostępną wersję). Dla Javy wybierz Java 21
  • Architecture – masz do wyboru x86_64 oraz arm64.

Function URL – publiczny endpoint

Teraz najważniejsza rzecz na tym etapie. Rozwiń sekcję Additional configurations i zaznacz opcję Enable function URL.

Function URL to najprostszy sposób na wystawienie funkcji Lambda na zewnątrz. Dostajesz gotowy adres HTTPS, który możesz wywołać z dowolnego miejsca – przeglądarki, curla, Postmana czy własnej aplikacji. Bez konfigurowania API Gateway, bez dodatkowych usług.

Przy Auth type masz dwie opcje:

  • AWS_IAM – Bezpieczna opcja. Tylko autoryzowani użytkownicy/usługi AWS mogą wywołać funkcję.
  • NONE – Opcja publiczna. Każdy, kto zna link, może wywołać Twoją funkcję.

Na potrzeby tego poradnika i łatwego testowania wybierzemy NONE.

Uwaga: W środowisku produkcyjnym nigdy nie zostawiaj otwartego endpointu, który generuje koszty (OpenAI), bez dodatkowego zabezpieczenia! Jeśli ktoś bez twojej wiedzy dostanie się do usługi to zużyje Ci cały portfel w OpenAI. Dodatkowo może zużyć Ci cały limit Free Tier dla AWS Lamba, a nawet je przekroczyć i narazić Cię na dodatkowe koszty. W dalszej części artykułu opisuje, jak to zabezpieczyć – teraz wykorzystujemy ten sposób, aby, szybko zobaczyć efekty. Natomiast jeśli wolisz już od początku mieć zabezpieczony endpoint przejdź od razu do sekcji, gdzie pokazuje jak to zabezpieczyć!

Tworzenie funkcji

Kliknij Create function. Po chwili AWS przekieruje Cię do widoku funkcji. W sekcji Function URL zobaczysz wygenerowany adres – coś w stylu:

https://abc123xyz.lambda-url.eu-central-1.on.aws/

Zapisz go sobie – za chwilę będziemy go używać do testów.

Na razie funkcja zawiera domyślny kod, który zwraca „Hello from Lambda”. W następnym kroku zastąpimy go kodem wywołującym API OpenAI.

Krok 2 – Kod funkcji wywołującej GPT

Teraz napiszemy właściwy kod, który odbiera zapytanie od użytkownika, wysyła je do API OpenAI i zwraca odpowiedź.

W widoku funkcji Lambda znajdziesz sekcję Code source z wbudowanym edytorem. Zamień domyślny kod na poniższy:

import os
import json
import http.client

def lambda_handler(event, context):
    # 1. Pobieranie danych wejściowych
    # Lambda może dostać dane jako czysty JSON lub jako string w "body" (przy Function URL)
    body = event
    if "body" in event:
        try:
            body = json.loads(event["body"])
        except (TypeError, json.JSONDecodeError):
            # Fallback jeśli body jest już słownikiem lub pustym stringiem
            body = event.get("body", {}) if isinstance(event.get("body"), dict) else {}

    # Pobieramy prompt użytkownika, lub ustawiamy domyślny
    user_prompt = body.get("prompt", "Opowiedz mi krótki żart o programistach.")

    print(f"Otrzymano zapytanie: {user_prompt}") # To trafi do logów CloudWatch

    # 2. Przygotowanie zapytania do OpenAI
    api_key = os.environ.get('OPENAI_API_KEY')
    if not api_key:
        return {
            "statusCode": 500,
            "body": json.dumps("Błąd serwera: Brak klucza API w zmiennych środowiskowych.", ensure_ascii=False)
        }

    # Konfiguracja połączenia
    conn = http.client.HTTPSConnection("api.openai.com")
    
    payload = json.dumps({
        "model": "gpt-5.2",
        "messages": [{"role": "user", "content": user_prompt}],
        "temperature": 0.7
    })

    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {api_key}'
    }

    try:
        # 3. Wysłanie żądania (to tutaj płacimy za czas oczekiwania!)
        conn.request("POST", "/v1/chat/completions", payload, headers)
        res = conn.getresponse()
        data = res.read()
        
        # 4. Obsługa odpowiedzi
        if res.status != 200:
            print(f"Błąd API OpenAI: {res.status} - {data.decode('utf-8')}")
            return {
                "statusCode": res.status,
                "body": f"Błąd OpenAI: {res.status}"
            }

        response_json = json.loads(data.decode("utf-8"))
        ai_reply = response_json['choices'][0]['message']['content']

        return {
            "statusCode": 200,
            "headers": {
                "Content-Type": "application/json"
            },
            "body": json.dumps({
                "question": user_prompt,
                "answer": ai_reply
            }, ensure_ascii=False) # ensure_ascii=False dla polskich znaków
        }

    except Exception as e:
        print(f"Wystąpił wyjątek: {str(e)}")
        return {
            "statusCode": 500,
            "body": json.dumps(f"Wewnętrzny błąd funkcji: {str(e)}", ensure_ascii=False)
        }

Po wklejeniu kodu kliknij Deploy, żeby zapisać zmiany.

Co robi ten kod?

Przejdźmy przez najważniejsze elementy:

Parsowanie danych wejściowych – Lambda może otrzymać dane na różne sposoby w zależności od źródła wywołania. Przy Function URL body przychodzi jako string JSON w polu event["body"]. Kod obsługuje oba przypadki i zabezpiecza się przed błędami parsowania.

Walidacja klucza API – zanim wyślemy cokolwiek do OpenAI, sprawdzamy czy klucz w ogóle istnieje. Jeśli zapomnisz go skonfigurować, dostaniesz czytelny błąd zamiast tajemniczego wyjątku.

Logowanie – instrukcje print() trafiają automatycznie do CloudWatch Logs. To bardzo przydatne przy debugowaniu – możesz zobaczyć dokładnie, jakie zapytanie przyszło i co poszło nie tak.

Obsługa polskich znaków – parametr ensure_ascii=False w json.dumps() sprawia, że polskie znaki zostaną zwrócone poprawnie, a nie jako sekwencje Unicode typu \u0144.

Dlaczego biblioteki standardowe?

Zauważ, że używamy wbudowanego modułu http.client zamiast popularnej biblioteki requests czy oficjalnego SDK od OpenAI.

W AWS Lambda każda zewnętrzna zależność to dodatkowa komplikacja. Musisz ją spakować razem z kodem albo użyć Lambda Layers (poniżej dokładnie wyjaśniam jak dodać własną warstwę). Natomiast przy prostym wywołaniu API to może się okazać niepotrzebny narzut. Moduł http.client jest częścią standardowej biblioteki Pythona, więc działa od razu bez żadnej konfiguracji. Twoja funkcja pozostaje lekka i szybko się uruchamia.

Krok 3 – Konfiguracja zmiennych środowiskowych

Kod jest gotowy, ale jeśli teraz spróbujesz wywołać funkcję, dostaniesz błąd o braku klucza API.

W kodzie odwołujemy się do OPENAI_API_KEY, musimy go odpowiednio zdefiniować w naszej funkcji AWS Lambda:

  1. W panelu Twojej funkcji przejdź do zakładki Configuration.
  2. W menu po lewej wybierz Environment variables.
  3. Kliknij Edit, a następnie Add environment variable.
  4. W polu Key wpisz: OPENAI_API_KEY.
  5. W polu Value wklej swój klucz zaczynający się od sk-... (wygenerujesz go na platform.openai.com w zakładce API Keys).
  6. Kliknij Save.
Widok na konfiguracje AWS Lambda z dodaniem klucza z OpenAI API

Pamiętaj, że API OpenAI jest płatne i wymaga doładowania konta. W sekcji Billing na platformie OpenAI dodaj metodę płatności i wpłać kilka dolarów na start. Bez kredytów każde zapytanie zwróci błąd 429 (insufficient quota).

Dla kontekstu – pojedyncze zapytanie do GPT-5.2 kosztuje ułamki centa, więc na eksperymenty wystarczy naprawdę niewielka kwota. Dokładne koszty omówię w osobnej sekcji.

Krok 4 – Timeout i pamięć

Funkcja jest już gotowa, ale zanim zaczniesz ją testować, warto zatrzymać się na chwilę przy ustawieniach. Jedno domyślne pole potrafi sprawić, że kod będzie „losowo” się wysypywał, mimo że wszystko wygląda poprawnie.

Domyślny timeout

Nowo utworzona funkcja AWS Lambda ma ustawiony timeout na 3 sekundy. Jeśli kod nie zakończy działania w tym czasie, AWS przerywa jego wykonanie i zwraca błąd.

Dla prostego kodu to zazwyczaj wystarcza. Dla wywołań API OpenAI – już niekoniecznie. Model potrzebuje czasu na wygenerowanie odpowiedzi, szczególnie przy dłuższych promptach albo bardziej złożonych pytaniach. Typowe zapytanie potrafi trwać od kilku do kilkunastu sekund.

Przy domyślnym timeoutcie Twoja funkcja bardzo często będzie kończyć się w połowie generowania odpowiedzi. Efekt? Błędy, brak odpowiedzi i trudne do zdiagnozowania problemy.

Więcej o samych timeoutach można przeczytaj w oficjalnej dokumentacji: link.

Jak zwiększyć timeout

W widoku funkcji Lambda przejdź do Configuration → General configuration i kliknij Edit.

Znajdziesz tam pole Timeout. Zmień jego wartość na coś rozsądnego – dla wywołań OpenAI 30 sekund to bezpieczny punkt startowy. Daje to modelowi wystarczający margines na odpowiedź, nawet przy wolniejszych zapytaniach.

Maksymalny timeout w AWS Lambda wynosi 15 minut, ale w przypadku prostego asystenta AI 30-60 sekund w zupełności wystarczy.

Pamięć RAM

W tym samym miejscu zobaczysz jeszcze ustawienie Memory. Domyślna wartość to 128 MB i jest to absolutne minimum.

Jest tu jeden haczyk, o którym łatwo nie wiedzieć: w AWS Lambda ilość pamięci RAM bezpośrednio wpływa na moc CPU i przepustowość sieci. Więcej pamięci oznacza szybsze wykonanie kodu i szybsze połączenia sieciowe.

Dla funkcji, które wywołują zewnętrzne API, zwiększenie pamięci do 256 MB albo 512 MB często daje zauważalne przyspieszenie. Różnica w kosztach jest niewielka (rozliczenie i tak odbywa się w GB-sekundach), a zysk w responsywności jest bardzo odczuwalny.

Na start 256 MB to dobry balans między wydajnością a kosztami.

Testowanie rozwiązania

Konfiguracja jest gotowa, więc teraz dobrze byłoby sprawdzić, czy wszystko faktycznie działa. Funkcję przetestujemy na cztery sposoby: z poziomu przeglądarki, bezpośrednio w konsoli AWS, przez curl i przez Postmana.

Z poziomu przeglądarki

Najszybszym sposobem na sprawdzenie, czy funkcja AWS Lambda działa, jest wejście na wcześniej wygenerowany Function URL bezpośrednio z poziomu przeglądarki.
Nawet jeśli nie przekażesz żadnych dodatkowych parametrów, kod jest napisany tak, że użyje domyślnego promptu i zwróci wygenerowaną odpowiedź.

{
  "question": "Opowiedz mi krótki żart o programistach.",
  "answer": "Dlaczego programiści nie lubią natury?  \nBo ma za dużo bugów i brak dokumentacji."
}

Test z poziomu AWS Console

Oczywiście funkcję możemy przetestować również bezpośrednio z poziomu AWS Console. W takim przypadku nie musimy nawet wystawiać Function URL – to najszybszy sposób, żeby sprawdzić, czy sama logika Lambdy działa poprawnie.

W widoku funkcji przejdź do zakładki Test. Jeśli robisz to pierwszy raz, zobaczysz formularz tworzenia nowego zdarzenia testowego. Nadaj mu nazwę (np. test-prompt) i w polu JSON wklej:

{
  "body": "{\"prompt\": \"Czym jest AWS Lambda w jednym zdaniu?\"}"
}

Zwróć uwagę na strukturę – body jest stringiem JSON, a nie obiektem. Tak dokładnie wyglądają requesty, które przychodzą do funkcji przez Function URL.

Kliknij Test. Po kilku sekundach powinieneś zobaczyć wynik. Jeśli wszystko jest skonfigurowane poprawnie, Lambda zwróci status 200 oraz odpowiedź wygenerowaną przez model w polu body.

Przykład odpowiedzi z AWS Console

Test przez curl

Jeśli natomiast chcemy przetestować zapytanie, w którym przekazujemy własny prompt na wejściu, najprościej zrobić to za pomocą curl.

curl -X POST https://twoja-funkcja.lambda-url.eu-central-1.on.aws/ \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Czym jest AWS Lambda w jednym zdaniu?"}'

W odpowiedzi powinieneś dostać JSON-a z wygenerowaną treścią. Jeśli tu działa – znaczy, że endpoint jest poprawnie wystawiony i dostępny z zewnątrz.

Test przez Postman

Jeśli wolisz interfejs graficzny, Postman sprawdzi się równie dobrze.

Utwórz nowy request i ustaw:

  • Method: POST
  • URL: Twój Function URL
  • Body: rawJSON
Wywołanie AWS Lambda z poziomu Postmana

Co jeśli coś nie działa?

Jeśli zamiast odpowiedzi dostajesz błąd, zajrzyj do logów.
W widoku funkcji Lambda przejdź do Monitor → View CloudWatch logs. Znajdziesz tam dokładne informacje o tym, co się wydarzyło – włącznie z komunikatami z print().

Najczęstsze problemy na tym etapie to:

  • Timeout – zwiększ limit czasu w konfiguracji funkcji
  • 401 od OpenAI – sprawdź, czy klucz API jest poprawny
  • 429 od OpenAI – brak środków na koncie OpenAI
  • Błąd o braku klucza – upewnij się, że zmienna środowiskowa nazywa się dokładnie OPENAI_API_KEY

Rozszerzenia

Podstawowa wersja działa i do prostych zastosowań pewnie by wystarczyła. Ale jeśli myślisz o tym rozwiązaniu poważniej – na przykład chcesz to wpiąć w jakąś aplikację produkcyjną – to warto zadbać o kilka dodatkowych rzeczy.

Lambda Layers i biblioteka OpenAI

Do tej pory korzystaliśmy z wbudowanego modułu http.client. To dobre rozwiązanie na start – brak zależności i minimum konfiguracji. Ma jednak swoje ograniczenia: ręczne składanie requestów, brak retry przy błędach sieciowych i bardzo podstawową obsługę odpowiedzi.

Oficjalne SDK OpenAI rozwiązuje te problemy i daje dostęp do dodatkowych funkcji, takich jak streaming odpowiedzi, asystenci czy function calling.

Jeśli spróbujesz dodać import openai bez żadnych zmian w konfiguracji, Lambda zwróci błąd (ImportError: No module named openai). Środowisko wykonawcze zawiera wyłącznie standardową bibliotekę Pythona – wszystkie zewnętrzne pakiety musisz dostarczyć samodzielnie.

Lambda Layers to mechanizm AWS do współdzielenia kodu i zależności między funkcjami. Zamiast pakować bibliotekę z każdą Lambdą osobno, tworzysz warstwę raz i podpinasz ją tam, gdzie jest potrzebna.

Aby utworzyć warstwę z biblioteką OpenAI:

1. Z poziomu AWS CloudShell utwórz katalog i zainstaluj pakiet (można też to zrobić lokalnie na swoim komputerze jeśli masz zainstalowanego pythona):

mkdir python

pip3 install openai \
    --target python/ \
    --platform manylinux2014_x86_64 \
    --only-binary=:all: \
    --implementation cp \
    --python-version 3.13

zip -r openai-layer.zip python

Pobierz plik: Actions (prawy górny róg terminala) -> Download file -> wpisz openai-layer.zip

2. W AWS Console przejdź do Lambda → Layers → Create layer

3. Wgraj plik openai-layer.zip, wybierz kompatybilny runtime (np. Python 3.13) i zapisz

Widok na dodawanie warstwy do AWS Lambda

4. Wróć do swojej funkcji, w zakładce Code przewiń do sekcji Layers i kliknij Add a layer

5. Wybierz utworzoną warstwę i zapisz zmiany

Widok na dodawania warstwy do AWS Lambda

Od tego momentu możesz normalnie używać import openai w kodzie.

Wtedy nasz kod zaktualizowany o bibliotekę openai mógłby tak wyglądać:

import os
import json
from openai import OpenAI  # Wymaga dodania Warstwy (Layer) w AWS

# Inicjalizacja klienta POZA handlerem.
# Dzięki temu, jeśli Lambda jest "rozgrzana" (warm start), nie tworzymy obiektu klienta od nowa.
client = OpenAI(api_key=os.environ.get('OPENAI_API_KEY'))

def lambda_handler(event, context):
    # 1. Pobieranie danych wejściowych
    # (Ten fragment zostawiamy bez zmian - świetnie radzi sobie z różnymi formatami z Function URL)
    body = event
    if "body" in event:
        try:
            body = json.loads(event["body"])
        except (TypeError, json.JSONDecodeError):
            body = event.get("body", {}) if isinstance(event.get("body"), dict) else {}

    user_prompt = body.get("prompt", "Opowiedz mi krótki żart o programistach.")
    print(f"Otrzymano zapytanie: {user_prompt}")

    # Szybkie sprawdzenie czy klucz istnieje
    if not client.api_key:
        return {
            "statusCode": 500,
            "body": json.dumps("Błąd serwera: Brak klucza API w zmiennych środowiskowych.", ensure_ascii=False)
        }

    try:
        # 2. Wysłanie żądania przy użyciu SDK OpenAI
        # Nie musimy ręcznie ustawiać nagłówków ani serializować JSON-a do 'payload'
        response = client.chat.completions.create(
            model="gpt-5.2",  # Model zgodny z Twoim przykładem
            messages=[
                {"role": "user", "content": user_prompt}
            ],
            temperature=0.7
        )

        # 3. Obsługa odpowiedzi
        # Uwaga: Biblioteka zwraca obiekt, a nie słownik! Używamy kropki, nie nawiasów [].
        ai_reply = response.choices[0].message.content

        return {
            "statusCode": 200,
            "headers": {
                "Content-Type": "application/json"
            },
            "body": json.dumps({
                "question": user_prompt,
                "answer": ai_reply
            }, ensure_ascii=False)
        }

    except Exception as e:
        print(f"Wystąpił wyjątek: {str(e)}")
        # Tutaj wpadną też błędy specyficzne dla OpenAI (np. RateLimitError, APIError)
        return {
            "statusCode": 500,
            "body": json.dumps(f"Wewnętrzny błąd funkcji: {str(e)}", ensure_ascii=False)
        }

Pamięć konwersacji z DynamoDB

Obecna funkcja jest bezstanowa – każde wywołanie to nowy, niezależny kontekst. Model nie pamięta, o czym rozmawialiście wcześniej. Dla prostego Q&A to wystarczy, ale do chatbota zapamiętującego kontekst potrzebujesz pamięci.

Problem z AWS Lambda jest taki, że nie przechowuje stanu. Każde wywołanie Lambdy może trafić na inną instancję. Nawet jeśli AWS ponownie użyje tego samego środowiska (tzw. warm start), nie mamy żadnej gwarancji, że zmienne z poprzedniego wywołania przetrwają. A nie da się też opierać się na zmiennych globalnych ani plikach lokalnych.

Najprostszą opcją jest wykorzystać usługę Amazon DynamoDB – w pełni zarządzana baza NoSQL, która bardzo dobrze integruje się z Lambdą.

Ogólny schemat wygląda tak:

  • klient wysyła zapytanie z identyfikatorem sesji (np. session_id),
  • AWS Lambda pobiera z DynamoDB historię rozmowy dla tej sesji,
  • buduje payload do OpenAI z pełną historią w polu messages,
  • zapisuje nową odpowiedź z powrotem do DynamoDB,
  • zwraca odpowiedź klientowi.

Dzięki temu model „widzi” poprzednie wiadomości i może zachować kontekst rozmowy.

W ramach Free Tier DynamoDB oferuje 25 GB storage oraz jednostki odczytu i zapisu, co w zupełności wystarczy do eksperymentów i mniejszych projektów.

Jeśli interesuje Cię taki większy projekt z wykorzystaniem AWS Lambda, AI, DynamoDB i innych usług AWS to daj znać w komentarzu (może uda się nawet filmik z tego nagrać)!

Bezpieczeństwo endpointu

Jeśli podczas tworzenia funkcji ustawiłeś Auth type: NONE, Twój endpoint jest publiczny. Każdy, kto zna URL, może wysyłać zapytania i generować koszty na Twoim koncie OpenAI. Jeśli chcesz używać tego w dłuższej perspektywie, warto się w jakiś sposób zabezpieczyć na to, aby osoby nieautoryzowane nie mogłyby z niego korzystać.

Autoryzacja AWS_IAM

Najsolidniejszą opcją wbudowaną w Function URL jest ustawienie Auth type: AWS_IAM. Zmienisz to w Configuration → Function URL → Edit.

W tym trybie każdy request musi być podpisany za pomocą AWS Signature Version 4. Oznacza to, że wywołujący musi mieć:

  • poświadczenia AWS (Access Key ID i Secret Access Key),
  • uprawnienia lambda:InvokeFunctionUrl dla danej funkcji.

Bez tego request zostanie odrzucony z błędem 403. To skutecznie blokuje przypadkowe wywołania.

Minusem jest większa złożoność po stronie klienta. Dla komunikacji między usługami AWS to naturalne rozwiązanie. Dla przeglądarki lub aplikacji mobilnej – często zbyt ciężkie.

Własny token w kodzie

Prostsze podejście to własna autoryzacja po stronie Lambdy. Dodajesz zmienną środowiskową API_TOKEN z losową wartością i weryfikujesz nagłówek w kodzie:

expected_token = os.environ.get("API_TOKEN")
auth_header = event.get("headers", {}).get("authorization", "")

if auth_header != f"Bearer {expected_token}":
    return {
        "statusCode": 401,
        "body": json.dumps({"error": "Unauthorized"})
    }

Klient wysyła request z nagłówkiem:

Authorization: Bearer twoj-sekretny-token

To nie jest rozwiązanie enterprise-grade, ale skutecznie odcina przypadkowe wywołania i jest bardzo proste po stronie klienta. Zawsze to lepsze, niż mieć w całości publiczny endpoint 🙂

API Gateway dla większej kontroli

Jeśli potrzebujesz:

  • rate limitingu,
  • wielu kluczy API dla różnych klientów,
  • custom domain,
  • dokładniejszych logów,

warto postawić API Gateway przed Lambdą. Daje on znacznie większą kontrolę niż Function URL: throttling, usage plans, różne metody autoryzacji i własne domeny z certyfikatami SSL.

AWS Secrets Manager zamiast zmiennych środowiskowych

Zmienne środowiskowe są szyfrowane w spoczynku, ale widoczne dla każdego, kto ma dostęp do konfiguracji funkcji w konsoli AWS. W środowisku produkcyjnym lepszym miejscem na klucze API jest AWS Secrets Manager.

Lambda może pobierać sekrety w runtime za pomocą AWS SDK, a Ty zyskujesz pełną kontrolę nad tym, kto i kiedy ma dostęp do sekretów, audyt każdego odczytu w CloudTrail oraz automatyczną rotację kluczy. To dodatkowa warstwa złożoności, ale przy produkcyjnych wdrożeniach warta rozważenia.

Ile to kosztuje?

Jedną z największych zalet tego podejścia jest model kosztowy. Nie utrzymujesz serwera, który czeka na zapytania – płacisz wyłącznie za realne użycie. Ale jak to dokładnie wygląda?

koszy aws lambda i OpenAi API - Grafika wygenerowana z gemini

Koszty AWS Lambda

Lambda rozlicza się w dwóch wymiarach: liczba wywołań i czas wykonania (w GB-sekundach).

W ramach Free Tier (niezależnie czy Free Plan czy Paid Plan) dostajesz miesięcznie:

  • 1 milion darmowych wywołań
  • 400 000 GB-sekund czasu obliczeniowego

Co to oznacza w praktyce? Załóżmy, że Twoja funkcja:

  • Używa 256 MB pamięci
  • Wykonuje się średnio 5 sekund (oczekiwanie na odpowiedź z OpenAI)

Jedno wywołanie zużywa: 0.25 GB × 5 sekund = 1.25 GB-sekundy

Z darmowej puli 400 000 GB-sekund możesz wykonać: 400 000 / 1.25 = 320 000 wywołań miesięcznie – za darmo.

Po przekroczeniu darmowego limitu stawki są minimalne (oczywiście stawki mogą różnić się od regionu i konfiguracji funkcji, szczegółowe dane znajdziesz pod tym linkiem):

  • $0.20 za milion wywołań
  • $0.0000166667 za GB-sekundę

Dla większości eksperymentalnych projektów i małych aplikacji rachunek od AWS będzie wynosił dosłownie nic lub ewentualnie jakieś grosze.

Koszty OpenAI

Tu sprawa wygląda inaczej – każde zapytanie kosztuje, bez darmowej puli. OpenAI rozlicza się za tokeny, czyli fragmenty tekstu (mniej więcej 1 token to 4 znaki w języku angielskim, w polskim nieco mniej).

Płacisz osobno za tokeny wejściowe (Twój prompt) i wyjściowe (odpowiedź modelu). Stawki zależą od wybranego modelu:

ModelInput (za 1M tokenów)Output (za 1M tokenów)Charakterystyka
GPT-5 mini$0.25$2.00Szybki i tani, dobry do prostych zadań
GPT-5.2$1.75$14.00Flagship – najlepsza jakość dla kodu i agentów
GPT-5.2 Pro$21.00$168.00Maksymalna inteligencja, głębokie rozumowanie
Dane aktualne na styczeń 2026

Różnica między najtańszym a najdroższym modelem jest ogromna – GPT-5.2 Pro kosztuje prawie 100 razy więcej niż GPT-5 mini. Ale to nie znaczy, że zawsze musisz sięgać po najdroższy.

Który model wybrać?

  • GPT-5 mini – Dobry wybór na start i do prostych zastosowań. Sprawdzi się przy FAQ, generowaniu krótkich tekstów czy klasyfikacji. Niski koszt wejścia pozwala swobodnie eksperymentować bez stresu o rachunek.
  • GPT-5.2 – Rozsądny wybór, jeśli budujesz coś bardziej wymagającego. Asystent do kodowania, analiza dokumentów, chatbot prowadzący dłuższe rozmowy i rozumiejący kontekst. To model, którego używaliśmy w przykładach w tym artykule.
  • GPT-5.2 Pro – Opcja do zadań, gdzie liczy się maksymalna jakość i głębsze rozumowanie. Analiza złożonych problemów, zadania wieloetapowe, praca z trudnym kontekstem. Koszt jest wyraźnie wyższy, więc warto sięgać po niego tylko tam, gdzie ta dodatkowa jakość faktycznie ma znaczenie.

Przykładowa kalkulacja

Załóżmy, że budujesz prostego asystenta, który obsługuje 1000 zapytań miesięcznie, każde ze średnio 250 tokenów input i 400 tokenów output. Zobaczmy jak koszty się prezentują dla różnych modeli:

ModelKoszt InputKoszt OutputRazem OpenAI+ AWS LambdaSuma
GPT-5 mini$0.06$0.80$0.86$0.00~$1/mies.
GPT-5.2$0.44$5.60$6.04$0.00~$6/mies.
GPT-5.2 Pro$5.25$67.20$72.45$0.00~$72/mies.
Dane aktualne na styczeń 2026

Przy tym samym użyciu różnica między GPT-5 mini a GPT-5.2 Pro to prawie 70 dolarów miesięcznie. Dlatego warto zacząć od tańszego modelu i przeskoczyć wyżej tylko wtedy, gdy jakość odpowiedzi rzeczywiście tego wymaga.

Kiedy to rozwiązanie ma sens?

Na koniec zastanówmy się jeszcze kiedy połączenie AWS Lambda z OpenAI API, które zbudowaliśmy w tym wpisie ma sens.

  • Prototypy i eksperymenty – Jeśli chcesz szybko sprawdzić pomysł na asystenta AI, bez stawiania serwera i całej infrastruktury, Lambda jest bardzo wygodnym wyborem. W ciągu godziny możesz postawić działający endpoint, przetestować pomysł i zdecydować, czy w ogóle warto iść dalej.
  • Aplikacje o nieregularnym ruchu – Chatbot, który obsługuje kilkadziesiąt zapytań dziennie z peakami w godzinach pracy. Automat uruchamiany raz na jakiś czas. W takich przypadkach serverless sprawdza się idealnie – płacisz wyłącznie za faktyczne wywołania, a nie za serwer, który przez większość czasu nic nie robi.
  • Proste backendy i integracje – Endpoint do generowania tekstów, tłumaczeń czy podsumowań. Bot na Slacka albo Discorda. Automatyzacja wywoływana przez upload pliku do S3. Wszędzie tam, gdzie potrzebujesz cienkiej warstwy „kleju” między zdarzeniem a wywołaniem AI, Lambda robi robotę.
  • Własne narzędzia i automatyzacje – Prywatny asystent pod konkretne potrzeby, z którego korzystasz tylko Ty lub mały zespół. Skrypt generujący poranne podsumowanie newsów. Narzędzie do analizy CV uruchamiane tylko w okresie rekrutacji. Automat przetwarzający faktury raz w miesiącu. To są idealne przypadki użycia dla Lambdy – brak kosztów między wywołaniami, pełna kontrola i minimum utrzymania.

Podsumowanie

Przeszliśmy przez cały proces – od pustej konsoli AWS do działającego endpointu z AI. Dla porządku zbierzmy najważniejsze elementy w jednym miejscu:

  • utworzenie funkcji AWS Lambda z Function URL jako publicznym endpointem,
  • wdrożenie kodu wywołującego OpenAI API z użyciem standardowych bibliotek Pythona,
  • konfiguracja zmiennych środowiskowych z kluczem API,
  • dostosowanie timeoutu i pamięci – bez tego funkcja będzie losowo kończyć się błędem,
  • testowanie z poziomu AWS Console, przez curl i Postmana.

To jest najprostsza sensowna wersja całości: jedna funkcja, kilkadziesiąt linijek kodu i zero infrastruktury do utrzymania.

Co dalej?

Jeśli chcesz pójść krok dalej, masz kilka naturalnych kierunków rozbudowy:

  • Pamięć konwersacji – dołóż DynamoDB i zamień prosty endpoint w chatbota, który pamięta kontekst rozmowy.
  • Integracja ze Slackiem lub Discordem – Lambda świetnie sprawdza się jako backend dla botów komunikatorów.
  • Analiza dokumentów – połącz funkcję z S3 i zbuduj asystenta odpowiadającego na pytania o zawartość plików.
  • Własny frontend – prosta strona (nawet statyczna na S3) wystarczy, żeby mieć pełnoprawną aplikację AI.

Połączenie serverless + AI faktycznie obniża barierę wejścia. Nie musisz być ekspertem od infrastruktury, żeby zbudować coś działającego – wystarczy pomysł, trochę kodu i kilka dolarów na tokeny.

Jeśli masz pytania albo zbudowałeś coś ciekawego na bazie tego wpisu, daj znać w komentarzu.

Subskrybuj
Powiadom o
guest
0 komentarzy
Najstarsze
Najnowsze Najwięcej głosów
Opinie w linii
Zobacz wszystkie komentarze