Tworzenie prostego chatbota z wykorzystaniem API GPT: instrukcja od zera

0
58
Rate this post

Nawigacja:

Po co własny chatbot z GPT i co realnie da się zbudować

Najprostsze, ale już użyteczne przypadki użycia

Najprostszy chatbot z wykorzystaniem API GPT nie musi być skomplikowany, żeby przynosił realną wartość. Kilka praktycznych scenariuszy, które da się zbudować w jeden wieczór, bez dużego doświadczenia:

  • Bot Q&A dla jednej dziedziny – prosty pomocnik odpowiadający na pytania z wybranego obszaru, np. podstawy Excela, zasady RODO, obsługa twojego produktu. Model nie zna twojej firmowej bazy wiedzy, ale potrafi tłumaczyć pojęcia, przepisy i procedury opisane w promptach.
  • Asystent do notatek – narzędzie, które zamienia chaotyczne notatki w uporządkowane punkty, podsumowania spotkań, listy zadań lub szkice dokumentów. Wystarczy, że wprowadzisz tekst i poprosisz bota o konkretną transformację.
  • Prosty support dla klienta – bot, który odpowiada na najczęściej zadawane pytania, podpowiada kroki rozwiązania typowych problemów i dopiero w trudniejszych przypadkach przekazuje sprawę człowiekowi.

W każdym z tych scenariuszy rdzeń jest podobny: użytkownik wpisuje pytanie lub tekst, twoja aplikacja wysyła je do API GPT i prezentuje odpowiedź. Różnica polega na tym, jak skonfigurujesz zachowanie bota, jak zadbasz o kontekst i jak wpleciesz go w realny proces (obsługa klienta, praca z dokumentami, nauka).

Dla wielu zastosowań nie potrzebujesz rozbudowanej logiki biznesowej. Wystarczy rozsądny prompt, prosty interfejs (np. konsola lub mała aplikacja webowa) i minimalne trzymanie historii rozmowy. To dobry punkt startu, który sprawia, że chatbot przestaje być „zabawką” i zaczyna oszczędzać czas.

Zabawka vs narzędzie – gdzie jest granica

Chatbot „dla zabawy” to zwykle jednorazowa wymiana zdań: użytkownik wpisuje losowe pytanie, model odpowiada i na tym koniec. Chatbot jako narzędzie ma kilka dodatkowych cech:

  • ma jasno określony cel (np. pomaga pisać maile, tłumaczy trudne dokumenty, wyjaśnia konfigurację systemu),
  • działa w konkretnym kontekście – np. zna rolę użytkownika (początkujący, klient, administrator) i dopasowuje język,
  • ma ograniczenia – np. nie dotyka tematów prawnych czy medycznych lub zawsze zaleca weryfikację przez specjalistę,
  • ma choć minimalną obsługę błędów – reaguje sensownie, gdy API nie działa lub odpowiedź jest niekompletna.

Przy prostym bocie tworzonym od zera skup się na jednym scenariuszu i doprowadź go do używalnej formy. Zamiast robić „bota do wszystkiego”, lepiej stworzyć asystenta do dwóch, trzech powtarzalnych zadań, które realnie wykonujesz codziennie.

Co zbudujesz bez dużej wiedzy programistycznej

Znając podstawy Pythona, potrafiąc uruchomić skrypt z terminala i zainstalować paczki, jesteś w stanie zbudować:

  • chatbota działającego w konsoli, który prowadzi rozmowę krok po kroku,
  • prostą aplikację webową w Flasku (lub FastAPI) z jednym polem tekstowym i przyciskiem „Wyślij”,
  • wewnętrzne narzędzie, które pomaga twojemu zespołowi w tworzeniu treści, streszczaniu dokumentów czy generowaniu odpowiedzi na maile.

Te projekty wymagają zrozumienia kilku pojęć (request HTTP, JSON, klucze API), ale nie trzeba zostać seniorem back-endu. Dobry punkt startowy to prosty skrypt, który zadaje pytanie do API GPT i wypisuje odpowiedź. Potem dodajesz pętlę rozmowy, a dopiero później myślisz o ładnym interfejsie.

Większego doświadczenia wymagają integracje z systemami firmowymi, prawidłowe indeksowanie własnych dokumentów (np. wektorowe bazy danych) czy zaawansowane zarządzanie kosztami i wydajnością. Do prostego bota, który rozmawia i pomaga w kilku zadaniach, w zupełności wystarczy solidne ogarnięcie Pythona.

Ograniczenia, o których trzeba wiedzieć od początku

API GPT nie widzi twoich dysków, systemów CRM ani dokumentów, dopóki ich świadomie nie prześlesz w treści zapytania lub nie zintegrowałeś ich przez osobny system. Model nie jest „magicznie podłączony” do twojej firmy. To ważne, bo wiele osób zakłada, że wystarczy spytać chatbota o dowolną procedurę i odpowiedź będzie zgodna z wewnętrzną polityką.

Druga sprawa to halucynacje, czyli pewne, ale nieprawdziwe odpowiedzi. Nawet najlepszy model potrafi wymyślić nieistniejący paragraf, API czy funkcję w bibliotece. Przy botach, które mają wpływ na decyzje biznesowe, dodaj zawsze jasny komunikat, że odpowiedzi są wsparciem, a nie ostateczną wyrocznią.

Trzeci aspekt to koszty. API GPT rozlicza się zwykle per token, czyli w uproszczeniu: im więcej tekstu wysyłasz i dostajesz, tym więcej płacisz. Długie rozmowy z dużą historią, ogromne prompty systemowe i generowanie bardzo długich odpowiedzi szybko podnoszą zużycie. Dlatego od początku warto myśleć o limitach długości i sensownym przycinaniu kontekstu.

Podstawy działania API GPT – co trzeba zrozumieć przed pierwszym requestem

API GPT jako prosta usługa: tekst w zamian za tekst

API GPT to usługa działająca przez HTTP. Twoja aplikacja wysyła JSON z tekstem (wiadomościami), a serwer odsyła JSON z wygenerowaną odpowiedzią. Cała „magia” to tak naprawdę zaawansowany model językowy po drugiej stronie; z punktu widzenia programisty wszystko sprowadza się do kilku pól w requestach i umiejętnego budowania promptu.

Najprostszy schemat:

  1. Użytkownik wpisuje wiadomość.
  2. Twój kod buduje strukturę żądania – wybór modelu, treść rozmowy, parametry.
  3. Wysyłasz żądanie HTTP POST do endpointu API.
  4. Odbierasz JSON z odpowiedzią modelu.
  5. Wyciągasz wygenerowany tekst i pokazujesz go użytkownikowi.

Na starcie nie ma potrzeby zgłębiać wszystkich funkcji API. Wystarczy zrozumieć podstawowe pola: nazwę modelu, listę wiadomości (system/user/assistant) i parametry takie jak temperatura.

Kluczowe pojęcia: model, prompt, odpowiedź, tokeny

W pracy z API GPT pojawia się kilka terminów, które trzeba mieć w głowie:

  • Model – konkretna wersja GPT, np. model bardziej wydajny, szybszy, tańszy lub dokładniejszy. Model określa możliwości, cenę i limit kontekstu.
  • Prompt – cała treść wejściowa, którą model dostaje w danym wywołaniu: wiadomości systemowe, pytania użytkownika, historia rozmowy.
  • Odpowiedź – wygenerowany tekst, zwykle w polu typu content w strukturze JSON, który odsyła API.
  • Tokeny – fragmenty tekstu, w które model rozbija komunikaty. Jeden token to średnio 3–4 znaki alfabetu łacińskiego lub krótkie słowo. Rozliczenie kosztów i limity kontekstu liczone są w tokenach, nie w znakach czy „wiadomościach”.
  • Limit kontekstu – maksymalna łączna liczba tokenów w wejściu i wyjściu w jednym wywołaniu. Jeśli przekroczysz limit, API zwróci błąd lub przytnie historię.

Świadomość tokenów pomaga planować architekturę bota. Jeśli każdą wiadomość dodajesz do historii i zawsze wysyłasz całość, przy długich rozmowach łatwo przekroczysz limity i koszty. Lepiej ścinać najstarszą część dialogu lub streszczać ją do krótszej notatki, która zachowuje sens, ale zajmuje mniej miejsca.

Tryb czatu a inne funkcje API

API GPT zwykle oferuje tryb „chat”, w którym struktura konwersacji opiera się na liście wiadomości. Każda wiadomość ma rolę (system, user, assistant) i treść. To najwygodniejszy sposób do tworzenia chatbotów, ponieważ API wewnętrznie rozumie strukturę rozmowy.

Poza tym mogą istnieć inne tryby i funkcje, np.:

  • tryb „completion” – bardziej surowe generowanie tekstu, często zastępowane obecnie trybem „chat”,
  • funkcje dodatkowe, takie jak wywołanie tools/functions (w zależności od dostawcy API),
  • generowanie embeddingów (wektorowych reprezentacji tekstu) do wyszukiwania semantycznego.

Do zbudowania prostego chatbota wystarczy ci tryb czatu. Zaawansowane możliwości, jak narzędzia czy funkcje, mają sens, gdy chcesz, żeby bot wykonywał operacje na danych (np. odpytywał bazę) zamiast jedynie generować tekst.

Jak myśleć o GPT: silnik językowy, nie baza wiedzy

Model GPT to silnik językowy. Uczy się na ogromnych ilościach tekstu i na tej podstawie przewiduje kolejne słowa. Nie ma klasycznej „bazy danych” z faktami, do której możesz wysłać zapytanie SQL. Zamiast tego reaguje na kontekst: to, co mu wyślesz w promptach.

Praktyczne konsekwencje:

  • Im lepiej opiszesz zadanie w promptach (rola bota, ton, format odpowiedzi), tym stabilniejsze wyniki.
  • Jeśli chcesz, by bot znał twoje procedury, musisz mu je przesłać lub przygotować osobny mechanizm wyszukiwania w dokumentach.
  • Model nie ma ciągłego „pamiętania” rozmów użytkowników między wywołaniami – pamięć trzeba budować po stronie twojej aplikacji (np. przechowując historię).

To spojrzenie pomaga unikać rozczarowań i budować chatboty, które działają przewidywalnie. Zamiast pytać „czemu model tego nie wie?”, lepiej zapytać „jak muszę zbudować prompt i kontekst, żeby model wygenerował pożądaną odpowiedź?”.

Programista w niebieskiej koszuli tworzy kod chatbota na iMacu
Źródło: Pexels | Autor: Lee Campbell

Wymagania wstępne i wybór stosu technologicznego

Minimalne umiejętności techniczne

Do stworzenia prostego chatbota z API GPT wystarczą podstawowe umiejętności techniczne:

  • uruchamianie komend w terminalu (PowerShell, cmd, bash),
  • instalacja programów i biblioteki (np. Python, pip, biblioteka klienta API),
  • czytanie prostych logów błędów – komunikaty stack trace, kody HTTP, JSON z błędem,
  • podstawy Pythona: zmienne, funkcje, pętle, import modułów, praca z plikami.

Jeśli te rzeczy nie są obce, reszta będzie kwestią dokładnego przejścia kroków. Nie ma tu skomplikowanych algorytmów ani zawiłych wzorców projektowych.

Wybór języka programowania: Python i alternatywy

Do tworzenia prostego chatbota bardzo dobrze nadaje się Python. Ma czytelną składnię, ogromny ekosystem bibliotek i dużo przykładów integracji z API GPT. Większość tutoriali w sieci używa Pythona właśnie do tego typu zadań.

Alternatywy:

  • JavaScript/TypeScript – gdy tworzysz aplikację webową z front-endem w React/Vue/Angular lub gdy wolisz Node.js na backendzie.
  • PHP – jeśli integrujesz chatbota z istniejącym WordPressem czy aplikacją w Laravelu.
  • C#/.NET – gdy działasz w ekosystemie Microsoft i budujesz rozwiązania dla firm.

Logika jest wszędzie podobna: wysłać JSON, odebrać JSON, przeprocesować odpowiedź. Różnice sprowadzają się do składni, bibliotek HTTP i zarządzania środowiskiem.

Niezbędne narzędzia i usługi

Do stworzenia chatbota z API GPT przygotuj:

  • Konto u dostawcy API GPT – np. u OpenAI lub innego dostawcy, który udostępnia model GPT przez REST API.
  • Klucz API – tajny token służący do autoryzacji żądań. Bez niego serwer odrzuci każde zapytanie.
  • Python 3.x – najlepiej aktualna stabilna wersja.
  • Edytor kodu – VS Code, PyCharm, Sublime Text lub nawet prosty edytor tekstu z kolorowaniem składni.
  • Narzędzie do testowania requestów – może to być zwykły curl w terminalu, Postman albo Insomnia, żeby szybciej rozpracować format JSON.

Przydaje się też Git do wersjonowania kodu, nawet jeśli projekt jest mały. Dzięki temu możesz eksperymentować z promptami i zawsze wrócić do poprzedniej wersji.

Przechowywanie klucza API i prosty plik konfiguracyjny

Klucza API nie wolno wpisywać na sztywno w kod (np. w pliku .py, który commitujesz do repozytorium). Bezpieczniejszy sposób to wykorzystanie zmiennych środowiskowych lub pliku konfiguracyjnego .env, który nie trafia do Gita.

Prosty schemat:

  1. Tworzysz plik .env w katalogu projektu.
  2. Wpisujesz w nim np. OPENAI_API_KEY=twoj_klucz.
  3. Konfiguracja środowiska Pythona i instalacja bibliotek

    Skoro jest już wybrany język i ogólne narzędzia, można przejść do konkretów technicznych. Najprościej zorganizować mały, odizolowany projekt w osobnym katalogu z wirtualnym środowiskiem Pythona.

  1. Utwórz katalog projektu, np. gpt-chatbot.
  2. W terminalu przejdź do tego katalogu: cd gpt-chatbot.
  3. Utwórz wirtualne środowisko:
    • Windows: python -m venv venv
    • macOS/Linux: python3 -m venv venv
  4. Aktywuj środowisko:
    • Windows (PowerShell): .venvScriptsActivate.ps1
    • macOS/Linux: source venv/bin/activate
  5. Zainstaluj bibliotekę klienta API i narzędzie do wczytywania zmiennych z pliku .env:
    pip install openai python-dotenv

Od tej pory wszystko, co instalujesz przez pip, trafi do folderu venv, a nie globalnie do systemu. Ułatwia to utrzymanie porządku, szczególnie gdy później pojawi się więcej projektów.

Ładowanie zmiennych środowiskowych z pliku .env

Najwygodniejszy sposób na pracę z kluczem API w małym projekcie to połączenie pliku .env i biblioteki python-dotenv. Cała konfiguracja trwa kilka minut.

  1. W katalogu projektu utwórz plik .env z zawartością:
    OPENAI_API_KEY=tu_wklej_swoj_klucz
  2. Utwórz plik .gitignore (jeśli używasz Gita) i dopisz:
    venv/
    .env
  3. W pliku Pythona (np. main.py) dodaj na samej górze:
    from dotenv import load_dotenv
    import os
    
    load_dotenv()  # wczytuje zmienne z .env
    OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
    
    if not OPENAI_API_KEY:
        raise RuntimeError("Brak zmiennej OPENAI_API_KEY w .env lub środowisku")

Dzięki temu klucza nie widać w kodzie, a aplikacja jasno zakomunikuje problem, jeśli zmienna nie będzie ustawiona.

Założenie konta, zdobycie klucza API i podstawowa konfiguracja

Rejestracja u dostawcy API GPT

Konkretne kroki rejestracji zależą od dostawcy, ale schemat jest podobny:

  1. Wejdź na stronę dostawcy (np. OpenAI).
  2. Załóż konto – najczęściej e-mail + hasło lub logowanie przez konto Google/Microsoft.
  3. Potwierdź adres e-mail.
  4. Przejdź do sekcji z kluczami API lub panelu deweloperskiego.

W niektórych przypadkach konieczne jest podpięcie karty płatniczej albo wybór planu rozliczeniowego, zanim pojawi się możliwość wygenerowania klucza.

Generowanie i zarządzanie kluczem API

Po utworzeniu konta przejdź do zakładki z kluczami (np. „API keys”, „Access tokens”). Typowa procedura wygląda tak:

  1. Kliknij przycisk „Create new key” / „New secret key”.
  2. Nadaj nazwę (np. local-dev-chatbot), żebyś później wiedział, do czego służy.
  3. Skopiuj wygenerowany klucz od razu – zazwyczaj da się go zobaczyć tylko raz.
  4. Wklej go do swojego pliku .env w projekcie.

Bezpieczna praktyka na start:

  • jeden klucz na środowisko (dev, test, ewentualnie produkcja),
  • co jakiś czas rotacja kluczy – usuwasz stary, generujesz nowy, aktualizujesz konfigurację.

Jeśli klucz przypadkiem trafi do repozytorium publicznego, nie próbuj „nadziei”, że nikt go nie zauważy. Od razu wygeneruj nowy, stary usuń, a w aplikacji podmień klucz w .env.

Sprawdzenie limitów, modeli i podstawowych ustawień

Przed pierwszym requestem wygodnie jest zajrzeć do panelu billing/usage i dokumentacji modeli. Pozwala to uniknąć zdziwienia rachunkiem oraz błędów „model not found”.

  • Sprawdź, czy plan obejmuje model, którego chcesz używać (np. konkretną wersję GPT).
  • Zwróć uwagę na limit tokenów w kontekście (np. 4k, 16k, 128k) oraz koszt za 1k tokenów.
  • Zanotuj nazwę modelu dokładnie tak, jak podaje dokumentacja – literówka kończy się błędem 400.

Na początek wystarczy jeden model ogólnego przeznaczenia (np. GPT-4o, GPT-4.1 mini, w zależności od oferty). Dopiero po pierwszych testach ma sens kombinowanie z tańszą lub dokładniejszą wersją.

Minimalny test połączenia z API

Zanim powstanie chatbot, dobrze jest uruchomić malutki skrypt testowy. Pozwala upewnić się, że klucz działa, biblioteka jest poprawnie zainstalowana i nie ma problemów z siecią.

Przykładowy plik test_connection.py (schematycznie, API może różnić się składnią):

from dotenv import load_dotenv
import os
from openai import OpenAI

load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")

client = OpenAI(api_key=api_key)

response = client.chat.completions.create(
    model="gpt-4.1-mini",
    messages=[
        {"role": "system", "content": "Jesteś prostym asystentem testowym."},
        {"role": "user", "content": "Napisz jedno zdanie po polsku."}
    ],
    max_tokens=50,
)

print(response.choices[0].message.content)

Jeśli po uruchomieniu python test_connection.py pojawi się sensowna odpowiedź, połączenie jest gotowe. W przypadku błędów zwróć uwagę na:

  • brak zmiennej OPENAI_API_KEY,
  • model o podanej nazwie nie istnieje lub konto nie ma do niego dostępu,
  • problemy z siecią lub blokadą ruchu wychodzącego.

Architektura prostego chatbota – jak rozbić problem na elementy

Warstwy logiki w najprostszym bocie

Nawet prosty chatbot z jednym plikiem warto podzielić mentalnie na kilka warstw. Dzięki temu późniejsze rozbudowy nie skończą się kompletnym bałaganem.

Podstawowe elementy:

  • Interfejs użytkownika – sposób, w jaki użytkownik rozmawia z botem (terminal, aplikacja webowa, komunikator).
  • Warstwa konwersacji – logika utrzymywania historii, dodawania nowych wiadomości, przycinania kontekstu.
  • Warstwa API – pojedyncza funkcja (lub kilka funkcji) do wysyłania requestów do GPT i odbierania odpowiedzi.
  • Konfiguracja – klucze, model, parametry (temperatura, limity tokenów, język, rola systemowa).

Na start wszystko może być w jednym pliku, byle fragmenty były sensownie odseparowane funkcjami. Już proste def call_gpt(...) i def run_chat_loop() ułatwiają utrzymanie kodu.

Przepływ danych: od wpisanego pytania do odpowiedzi

Dobry sposób myślenia o bocie to prześledzenie pojedynczej wiadomości użytkownika:

  1. Użytkownik wpisuje tekst (np. w terminalu).
  2. Interfejs przekazuje go do funkcji handle_user_message().
  3. Funkcja:
    • dodaje wiadomość użytkownika do listy messages,
    • w razie potrzeby przycina historię (np. usuwa najstarsze wpisy),
    • wywołuje call_gpt(messages).
  4. call_gpt buduje request do API, wysyła go i odbiera odpowiedź.
  5. Odpowiedź modelu jest dopisywana do historii jako rola assistant.
  6. Interfejs wyświetla użytkownikowi treść odpowiedzi.

Ten prosty przepływ da się potem rozszerzać o logowanie, metryki, integracje z bazą danych czy kolejkami zadań. Punktem wyjścia pozostaje jednak lista wiadomości przekazywana do modelu.

Format historii rozmowy w aplikacji

Najprostsza reprezentacja historii to lista słowników, która niemal 1:1 odpowiada strukturze API:

messages = [
    {"role": "system", "content": "Jesteś pomocnym chatbotem dla użytkowników sklepu z elektroniką."},
    {"role": "user", "content": "Czy ten laptop nada się do programowania?"},
    {"role": "assistant", "content": "Tak, model X jest dobry do programowania, ponieważ..."},
    {"role": "user", "content": "A jak z czasem pracy na baterii?"}
]

Praca na takiej strukturze jest intuicyjna:

  • nowa wiadomość użytkownika to messages.append({"role": "user", "content": tekst}),
  • odpowiedź modelu dopisujesz po odebraniu JSON-a,
  • przycinanie historii polega na usuwaniu najstarszych elementów z listy.

W miarę rozwoju projektu tę strukturę można trzymać w pamięci (prosty bot), w pliku (np. JSON per użytkownik) albo w bazie danych (gdy botów i użytkowników jest więcej).

Decyzje projektowe na start

Przed pierwszą linijką kodu sensownie jest odpowiedzieć sobie na kilka krótkich pytań:

  • Gdzie użytkownik będzie rozmawiał z botem? – CLI, strona WWW, komunikator.
  • Czy potrzebna jest historia rozmów między sesjami? – jeśli tak, trzeba od razu zaplanować prosty mechanizm zapisu.
  • Jaki jest główny cel bota? – np. wsparcie klienta, asystent nauki, pomoc programistyczna. To potem wpływa na prompt systemowy.
  • Jakie ograniczenia czasowe i kosztowe obowiązują? – od tego zależy wybór modelu i strategia przycinania kontekstu.

Prosty przykład: jeśli chatbot ma służyć wyłącznie do nauki języka dla jednej osoby i działa w terminalu, nie trzeba budować od razu bazy danych i systemu logowania. Wystarczy historia w pamięci procesu.

Programista piszący kod chatbota przy biurku w nowoczesnym biurze
Źródło: Pexels | Autor: cottonbro studio

Pierwszy działający chatbot w Pythonie – krok po kroku

Struktura pliku z prostą pętlą czatu

Na początek wystarczy jeden plik, np. chatbot.py, z trzema głównymi częściami:

  1. Inicjalizacja klienta API i konfiguracji (klucz, model, prompt systemowy).
  2. Funkcja wywołująca API (call_gpt).
  3. Pętla czatu w terminalu (run_chat).

Przykładowy szkielet (schematycznie, z użyciem aktualnego klienta):

from dotenv import load_dotenv
import os
from openai import OpenAI

load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")

if not api_key:
    raise RuntimeError("Brak OPENAI_API_KEY")

client = OpenAI(api_key=api_key)

MODEL_NAME = "gpt-4.1-mini"

def call_gpt(messages):
    response = client.chat.completions.create(
        model=MODEL_NAME,
        messages=messages,
        max_tokens=300,
        temperature=0.5,
    )
    return response.choices[0].message.content

def run_chat():
    messages = [
        {
            "role": "system",
            "content": "Jesteś pomocnym asystentem, odpowiadasz po polsku, zwięźle i konkretnie."
        }
    ]

    print("GPT Chatbot. Napisz 'quit' aby zakończyć.n")

    while True:
        user_input = input("Ty: ")
        if user_input.lower() in ("quit", "exit", "q"):
            print("Koniec rozmowy.")
            break

        messages.append({"role": "user", "content": user_input})

        try:
            assistant_reply = call_gpt(messages)
        except Exception as e:
            print(f"Błąd API: {e}")
            continue

        messages.append({"role": "assistant", "content": assistant_reply})

        print(f"Bot: {assistant_reply}n")

if __name__ == "__main__":
    run_chat()

Taki skrypt tworzy już pełnoprawnego chatbota w terminalu. Jest prosty, ale pokazuje cały przepływ: wejście –> historia –> API –> odpowiedź.

Obsługa podstawowych błędów i przerwanie rozmowy

Kod powyżej zawiera minimalną obsługę błędów w bloku try/except. To chroni pętlę przed twardym wywaleniem się przy chwilowym problemie z siecią czy limitem API. W praktyce dobrze jest dodać kilka usprawnień:

  • prosty retry – np. jedna dodatkowa próba po krótkim opóźnieniu,
  • lepsze komunikaty dla użytkownika, gdy API odrzuca żądania (limity, brak środków),
  • czysty sposób na zakończenie – komenda quit lub puste wejście.

Prosty przykład z retry:

Retry, timeouty i proste ograniczanie liczby zapytań

API potrafi czasem odpowiedzieć błędem mimo poprawnego kodu. Krótkie „auto-uzdrawianie” aplikacji oszczędza nerwów – wystarczy kilka linijek.

Rozszerzona wersja call_gpt z retry i timeoutem może wyglądać tak:

import time
from openai import APIConnectionError, RateLimitError, OpenAIError

MAX_RETRIES = 2
REQUEST_TIMEOUT = 20  # sekundy

def call_gpt(messages):
    for attempt in range(1, MAX_RETRIES + 1):
        try:
            response = client.chat.completions.create(
                model=MODEL_NAME,
                messages=messages,
                max_tokens=300,
                temperature=0.5,
                timeout=REQUEST_TIMEOUT,
            )
            return response.choices[0].message.content
        except RateLimitError:
            # za dużo requestów lub limit konta
            wait_time = 2 * attempt
            print(f"Przekroczono limit żądań. Czekam {wait_time}s i próbuję ponownie...")
            time.sleep(wait_time)
        except APIConnectionError:
            # problem z siecią
            wait_time = 2 * attempt
            print(f"Problem z połączeniem. Próba {attempt}/{MAX_RETRIES}. "
                  f"Czekam {wait_time}s...")
            time.sleep(wait_time)
        except OpenAIError as e:
            # inne błędy API – raczej nie ma sensu retry
            print(f"Błąd API: {e}")
            break

    raise RuntimeError("Nie udało się uzyskać odpowiedzi od API po kilku próbach.")

To nadal jest prosta funkcja, ale:

  • nie wywala całego programu przy chwilowej utracie internetu,
  • łagodniej reaguje na limity (krótkie odczekanie),
  • daje użytkownikowi czytelny komunikat, co się dzieje.

Przy bota używanego przez kilka osób w firmie proste ograniczenie liczby zapytań na minutę zapobiega niespodziewanym kosztom. W najprostszym wariancie można:

import time
from collections import deque

MAX_CALLS_PER_MINUTE = 20
_call_timestamps = deque()

def throttle():
    now = time.time()
    _call_timestamps.append(now)

    # usuwamy wywołania starsze niż 60 sekund
    while _call_timestamps and now - _call_timestamps[0] > 60:
        _call_timestamps.popleft()

    if len(_call_timestamps) > MAX_CALLS_PER_MINUTE:
        # proste blokowanie – czekamy do końca minuty
        sleep_time = 60 - (now - _call_timestamps[0])
        print(f"Zbyt wiele zapytań, pauza {sleep_time:.1f}s...")
        time.sleep(sleep_time)

Następnie wywołujesz throttle() na początku call_gpt. To nie jest superprecyzyjny limiter, ale dla małego narzędzia wewnętrznego całkowicie wystarcza.

Dodanie prostych komend specjalnych w czacie

Sam tekst od użytkownika to za mało. Przydaje się kilka komend sterujących, które nie trafiają do GPT, tylko zmieniają zachowanie bota.

Typowe przykłady:

  • /reset – wyczyszczenie historii i start nowej rozmowy,
  • /save – zapis aktualnej historii do pliku,
  • /help – krótkie przypomnienie dostępnych komend.

Prosty mechanizm można zbudować tak:

def print_help():
    print("Dostępne komendy:")
    print("  /reset  - rozpocznij nową rozmowę")
    print("  /save   - zapisz obecną historię do pliku chat_history.txt")
    print("  /help   - pokaż tę pomoc")
    print("  quit    - zakończ programn")

def save_history(messages, filename="chat_history.txt"):
    with open(filename, "w", encoding="utf-8") as f:
        for msg in messages:
            role = msg["role"]
            content = msg["content"]
            f.write(f"{role.upper()}: {content}nn")
    print(f"Historia zapisana do {filename}n")

def run_chat():
    base_system_message = {
        "role": "system",
        "content": "Jesteś pomocnym asystentem, odpowiadasz po polsku, zwięźle i konkretnie."
    }

    messages = [base_system_message]

    print("GPT Chatbot. Napisz 'quit' aby zakończyć, '/help' po listę komend.n")

    while True:
        user_input = input("Ty: ").strip()
        if not user_input:
            continue

        # komendy specjalne
        if user_input.lower() in ("quit", "exit", "q"):
            print("Koniec rozmowy.")
            break
        if user_input == "/help":
            print_help()
            continue
        if user_input == "/reset":
            messages = [base_system_message]
            print("Nowa rozmowa rozpoczęta.n")
            continue
        if user_input == "/save":
            save_history(messages)
            continue

        # normalna rozmowa
        messages.append({"role": "user", "content": user_input})

        try:
            assistant_reply = call_gpt(messages)
        except Exception as e:
            print(f"Błąd API: {e}")
            continue

        messages.append({"role": "assistant", "content": assistant_reply})
        print(f"Bot: {assistant_reply}n")

Taki „mikro-shell” wokół bota bardzo ułatwia codzienną pracę – szczególnie podczas testów, gdy często trzeba czyścić kontekst i porównywać różne zachowania.

Projektowanie promptów i roli chatbota – jak „ustawić” jego zachowanie

Rola systemowa jako kontrakt z botem

Wiadomość z rolą system to główne miejsce, w którym definiujesz charakter i zadania chatbota. Dobrze przygotowany system prompt działa jak instrukcja stanowiskowa dla pracownika: mówi, co ma robić, czego ma unikać, jak odpowiadać.

Przykładowe role systemowe dla różnych zastosowań:

# 1. Bot wsparcia klienta sklepu z elektroniką
"Jesteś asystentem sklepu z elektroniką. Odpowiadasz po polsku, krótko i konkretnie. 
Jeśli czegoś nie wiesz, mów wprost, że nie wiesz, i sugerujesz kontakt z obsługą."

# 2. Nauczyciel programowania
"Jesteś cierpliwym nauczycielem Pythona. Tłumaczysz prosto, z przykładami z życia. 
Unikasz zaawansowanej matematyki, chyba że użytkownik o nią poprosi. 
Zawsze podawaj krótkie przykłady kodu."

# 3. Asystent pisania maili
"Pomagasz pisać maile po polsku w stylu biznesowym, ale ludzkim. 
Unikasz przesadnie oficjalnego języka. Proponujesz gotowe treści maili, 
które użytkownik może skopiować do Outlooka."

W praktyce przydają się trzy cechy takiego opisu:

  • Konkretny cel – np. „asystent sklepu z elektroniką”, a nie „pomocny asystent”.
  • Styl wypowiedzi – język, długość, ton.
  • Ograniczenia – czego bot ma nie robić, kiedy ma odmówić.

Szablony promptów dla powtarzalnych zadań

Jeśli bot ma wykonywać określone typy akcji (np. streszczanie tekstu, generowanie maili, podpowiedzi do kodu), wygodnie jest zdefiniować proste szablony promptów. Potem wystarczy wstrzyknąć dane użytkownika.

Przykład – bot, który streszcza długi tekst w ustalonej formie:

SUMMARY_PROMPT = """
Streść poniższy tekst po polsku w maksymalnie 5 punktach wypunktowania.
Pisz zwięźle i rzeczowo, unikaj ogólników.

Tekst:
{tekst}
"""

Fragment kodu, który używa szablonu:

def build_summary_prompt(user_text: str) -> list[dict]:
    return [
        {
            "role": "system",
            "content": "Jesteś asystentem, który streszcza teksty po polsku w punktach."
        },
        {
            "role": "user",
            "content": SUMMARY_PROMPT.format(tekst=user_text)
        }
    ]

W typowym czacie, gdzie użytkownik zadaje różne pytania, szablony przydają się głównie do „podzadań” – np. gdy w tle każesz botowi najpierw oczyścić dane, a dopiero potem odpowiedzieć użytkownikowi.

Unikanie zbyt ogólnych i zbyt długich instrukcji

Ogólny prompt typu „Bądź jak najlepszy ekspert we wszystkim” daje nieprzewidywalne wyniki. Zbyt długi, wielostronicowy opis też nie pomaga – użytkownik pisze jedno zdanie, a model musi „przetrawić” wielki regulamin.

Praktyczny kompromis:

  • system prompt na 5–15 zdań, klarowny, bez dygresji,
  • krótkie, jawne zasady np. „Jeśli pytanie jest niejednoznaczne, zadaj maksymalnie 2 pytania doprecyzowujące.”,
  • jasny styl odpowiedzi: „najpierw 1–2 zdania odpowiedzi, potem szczegóły w punktach”.

Przykład poprawionego promptu dla bota sklepowego:

"Jesteś asystentem sklepu z elektroniką. 
Odpowiadasz wyłącznie po polsku.
Zadania:
1) Pomagasz dobrać sprzęt (laptopy, telefony, monitory, akcesoria).
2) Tłumaczysz różnice między modelami prostym językiem.
3) Gdy brakuje danych (np. nie znasz konkretnego modelu), mów szczerze, że nie wiesz.

Styl:
- najpierw krótka odpowiedź 1–2 zdania,
- potem opcjonalnie szczegóły w punktach,
- unikaj żargonu technicznego, chyba że użytkownik go używa."

Dopasowanie tonu do kanału: terminal vs aplikacja webowa

Ten sam bot może brzmieć inaczej w konsoli dewelopera i inaczej na stronie sklepu. Zamiast pisać dwa różne boty, wystarczy lekko zmodyfikować prompt systemowy.

Przykładowe dwa warianty stylistyczne tego samego asystenta technicznego:

# Wersja „developerska” (terminal)
"Jesteś technicznym asystentem dla programisty. Możesz używać skrótów typu CPU, RAM, GPU.
Odpowiadasz konkretnie, możesz omijać podstawowe definicje."

# Wersja „sklepowa” (klient końcowy)
"Pomagasz klientom sklepu, którzy nie znają się na technologii. 
Unikasz skrótów technicznych albo od razu je objaśniasz jednym zdaniem."

W kodzie możesz trzymać kilka predefiniowanych profili i wybierać je parametrem przy starcie programu, np. --mode dev lub --mode customer.

Utrzymanie kontekstu rozmowy i praca z historią czatu

Przycinanie historii, zanim zrobi to limit tokenów

Modele mają limity długości kontekstu (łączna długość promptu + odpowiedzi). Zamiast czekać na błąd z API, lepiej samemu pilnować, żeby lista messages nie rozrosła się za bardzo.

Bardzo prosty sposób to ograniczenie liczby wiadomości. Np. trzymasz tylko ostatnie 10 wypowiedzi użytkownika i asystenta, plus stały system prompt.

MAX_HISTORY_MESSAGES = 20  # bez system message

def trim_history(messages: list[dict]) -> list[dict]:
    system_messages = [m for m in messages if m["role"] == "system"]
    other_messages = [m for m in messages if m["role"] != "system"]

    if len(other_messages) <= MAX_HISTORY_MESSAGES:
        return system_messages + other_messages

    # odcinamy najstarsze
    other_messages = other_messages[-MAX_HISTORY_MESSAGES:]
    return system_messages + other_messages

Teraz wystarczy wywoływać messages = trim_history(messages) tuż przed przekazaniem historii do call_gpt:

messages.append({"role": "user", "content": user_input})
messages = trim_history(messages)
assistant_reply = call_gpt(messages)

To bardzo prymitywne podejście, ale w wielu prostych chatbotach działa zaskakująco dobrze – ostatnie kilka wymian to zwykle wszystko, czego potrzeba do sensownej odpowiedzi.

Liczenie tokenów i bardziej świadome zarządzanie kontekstem

Jeśli czat ma być dłuższy lub „gęstszy” (dużo treści), lepiej posługiwać się nie liczbą wiadomości, tylko przybliżoną liczbą tokenów. Do orientacyjnych obliczeń można użyć zewnętrznej biblioteki do tokenizacji (np. tiktoken), ale na start wystarczy prosta estymacja.

Przybliżenie: 1 token ≈ 4 znaki tekstu łacińskiego. Czyli limit 4000 tokenów to ok. 16 000 znaków. Można wprowadzić maksymalną łączną długość treści w znakach i ciąć najstarsze wiadomości, gdy przekroczysz limit.

MAX_CHARS_IN_CONTEXT = 8000

def trim_history_by_chars(messages: list[dict]) -> list[dict]:
    system_messages = [m for m in messages if m["role"] == "system"]
    other_messages = [m for m in messages if m["role"] != "system"]

    # liczymy od końca (od najnowszych)
    total_chars = 0
    kept = []

    for msg in reversed(other_messages):
        content_len = len(msg.get("content", ""))
        if total_chars + content_len > MAX_CHARS_IN_CONTEXT:
            break
        kept.append(msg)
        total_chars += content_len

    kept.reverse()
    return system_messages + kept

Takie „cięcie po znakach” nie jest idealne, ale szybko zabezpiecza przed przekręceniem limitu modelu, szczególnie gdy użytkownicy wklejają długie fragmenty tekstu.

Zapisywanie i wznawianie rozmów między sesjami

Jeśli użytkownik ma wracać do tej samej rozmowy po godzinie lub jutro, historia musi przetrwać zamknięcie programu. Najprostsza droga: zapis do pliku JSON.

Przykład prostych funkcji do zapisu i wczytania:

import json
from pathlib import Path

HISTORY_FILE = Path("chat_history.json")

def load_history() -> list[dict]:
    if not HISTORY_FILE.exists():
        return []
    with open(HISTORY_FILE, "r", encoding="utf-8") as f:
        return json.load(f)

def save_history_json(messages: list[dict]):
    with open(HISTORY_FILE, "w", encoding="utf-8") as f:
        json.dump(messages, f, ensure_ascii=False, indent=2)

W pętli czatu można dodać opcję ładowania istniejącej historii przy starcie:

Najczęściej zadawane pytania (FAQ)

Jakiego najprostszego chatbota mogę zbudować z API GPT w jeden wieczór?

Najprościej zacząć od bota Q&A dla jednej dziedziny, np. „podstawy Excela” albo „FAQ mojego produktu”. Bot przyjmuje pytanie w konsoli lub prostym formularzu webowym, wysyła je do API GPT i wyświetla odpowiedź.

Technicznie potrzebujesz tylko skryptu, który:

  • pobiera tekst od użytkownika,
  • wysyła go do API GPT jako wiadomość użytkownika,
  • odbiera JSON z odpowiedzią,
  • wypisuje wygenerowany tekst.

Taki bot nie ma jeszcze zaawansowanej logiki ani integracji z bazami danych, ale już potrafi realnie odciążyć w prostych pytaniach.

Czy do stworzenia prostego chatbota z GPT muszę umieć dobrze programować?

Nie. Wystarczą podstawy Pythona: uruchamianie skryptu z terminala, instalacja paczek (pip) i ogólne obycie z prostymi funkcjami oraz pętlami. Dodatkowo przyda się rozumienie, czym jest żądanie HTTP, JSON i klucz API.

Realnie, przy takim poziomie wiedzy zbudujesz:

  • chatbota w konsoli, który prowadzi rozmowę krok po kroku,
  • prostą aplikację webową (Flask/FastAPI) z jednym polem tekstowym i przyciskiem „Wyślij”,
  • wewnętrzne narzędzie do streszczania dokumentów czy generowania odpowiedzi na maile.

Bardziej skomplikowane rzeczy, jak integracja z CRM czy wektorowe bazy danych, możesz odłożyć na później.

Czym różni się „chatbot do zabawy” od chatbota będącego realnym narzędziem?

Chatbot „dla zabawy” to zazwyczaj jedna, dwie losowe wiadomości i koniec. Nie ma spójnego celu, kontekstu ani zasad działania. Ot, pogadanka z modelem.

Narzędzie to już coś innego. Taki bot:

  • ma konkretny cel, np. pomoc w pisaniu maili albo tłumaczenie fragmentów dokumentów,
  • działa w określonym kontekście – zna rolę użytkownika i dopasowuje język,
  • ma jasno opisane ograniczenia (np. nie udziela porad prawnych),
  • reaguje sensownie na błędy API i niekompletne odpowiedzi.

Przy pierwszym własnym bocie skup się na jednym scenariuszu, który faktycznie realizujesz codziennie, zamiast próbować „bota do wszystkiego”.

Czy chatbot z API GPT ma dostęp do moich plików i systemów firmowych?

Nie. Model nie widzi twoich dysków, CRM, maili ani dokumentów, dopóki sam ich nie wyślesz w treści zapytania albo nie zbudujesz osobnej integracji. Bez świadomego podania danych chatbot operuje wyłącznie na tym, co dostanie w promptach plus wiedza ogólna modelu.

Jeśli chcesz, żeby bot odpowiadał zgodnie z procedurami firmy, masz trzy główne opcje:

  • wkleić istotne fragmenty procedur do promptu (dobre dla małych zakresów),
  • zbudować prosty moduł wyszukiwania w dokumentach i przekazywać wybrane fragmenty do API,
  • połączyć bota z wewnętrznymi systemami przez dodatkową warstwę kodu.

Bez tego chatbot będzie „zgadywał” polityki firmy na podstawie wiedzy ogólnej, co bywa ryzykowne.

Co to są tokeny w API GPT i jak wpływają na koszty chatbota?

Tokeny to małe fragmenty tekstu, na które model rozbija wiadomości. Jeden token to średnio 3–4 znaki lub bardzo krótkie słowo. API rozlicza cię za liczbę tokenów w wejściu (prompt) i wyjściu (odpowiedź), nie za liczbę znaków.

Im dłuższa historia rozmowy, większy prompt systemowy i bardziej rozbudowane odpowiedzi, tym więcej tokenów i wyższy koszt. Prosty sposób na kontrolę wydatków:

  • ogranicz maksymalną długość odpowiedzi,
  • przycinaj najstarsze wiadomości z historii rozmowy,
  • zamiast pełnej historii przechowuj krótkie streszczenie poprzednich etapów.

Dodatkowo każdy model ma limit kontekstu (maksymalna liczba tokenów na jedno wywołanie). Po przekroczeniu albo dostaniesz błąd, albo przyciętą historię.

Jak zabezpieczyć się przed „halucynacjami” i błędnymi odpowiedziami chatbota?

Model GPT potrafi generować pewne, ale nieprawdziwe odpowiedzi – np. wymyślony paragraf ustawy czy nieistniejącą funkcję w bibliotece. Dlatego przy botach, które wspierają decyzje biznesowe, wprowadź kilka prostych zabezpieczeń:

  • jasny komunikat dla użytkownika, że odpowiedzi są wsparciem, a nie ostatecznym źródłem prawdy,
  • prompty, które każą modelowi zaznaczać niepewność i podawać, gdy czegoś „nie wie”,
  • ręczną weryfikację odpowiedzi w obszarach wrażliwych (prawo, medycyna, finanse),
  • ograniczenie zakresu bota do prostych zadań tam, gdzie pełna weryfikacja jest trudna.

Prosty przykład: bot supportowy może generować wstępne odpowiedzi dla klienta, ale zgłoszenia oznaczone jako „wysokie ryzyko” przekazujesz człowiekowi do sprawdzenia.

Jakie są kluczowe elementy requestu do API GPT przy budowie chatbota?

Do prostego bota wystarczy kilka pól w zapytaniu HTTP POST. Najważniejsze to:

  • nazwa modelu (np. konkretna wersja GPT),
  • lista wiadomości z rolami: system (instrukcje dla bota), user (pytania użytkownika), assistant (dotychczasowe odpowiedzi),
  • parametry generowania, np. temperatura (kreatywność) czy maksymalna liczba tokenów odpowiedzi.

Twoja aplikacja buduje z tego JSON, wysyła go na endpoint API, a potem wyciąga wygenerowany tekst z odpowiedzi i pokazuje go użytkownikowi. Na start nie musisz dotykać trybów zaawansowanych, takich jak narzędzia czy embeddingi.

Najważniejsze wnioski

  • Prosty chatbot na API GPT już w podstawowej wersji może realnie pomagać, np. jako wyspecjalizowany bot Q&A, asystent do porządkowania notatek czy pierwszy poziom supportu dla klientów.
  • Różnica między „zabawką” a narzędziem polega na jasnym celu, osadzeniu w konkretnym kontekście (rola użytkownika, język), zdefiniowanych ograniczeniach oraz podstawowej obsłudze błędów.
  • Na start lepiej skupić się na jednym, dwóch powtarzalnych scenariuszach (np. streszczanie dokumentów, pomoc w mailach) i doprowadzić je do używalnego stanu, zamiast próbować zbudować „bota do wszystkiego”.
  • Znając podstawy Pythona i HTTP, można samodzielnie zbudować bota w konsoli, prostą aplikację webową (Flask/FastAPI) lub wewnętrzne narzędzie do pracy z treściami – bez zaawansowanego zaplecza programistycznego.
  • API GPT nie ma dostępu do Twoich systemów ani plików, dopóki ich świadomie nie prześlesz lub nie zintegrować; nie da się „zapytać o procedurę firmową”, jeśli treść tej procedury nie trafiła wcześniej do modelu.
  • Model potrafi halucynować, czyli generować przekonujące, ale fałszywe informacje, więc przy zastosowaniach biznesowych trzeba jasno komunikować, że odpowiedzi są wsparciem, a nie ostateczną podstawą decyzji.
  • Koszt działania bota rośnie wraz z liczbą tokenów, więc od początku trzeba pilnować długości promptów, historii rozmowy i generowanych odpowiedzi, a także wdrożyć sensowne limity i przycinanie kontekstu.
Poprzedni artykułJak historia informatyki uczy nas dziś projektować bezpieczne systemy
Następny artykułCzy kopia zapasowa oprogramowania jest legalna i jak ją poprawnie wykonać
Jadwiga Stępień
Jadwiga Stępień zajmuje się popularyzacją wiedzy o nowych technologiach wśród osób, które na co dzień nie pracują w IT. Od lat prowadzi warsztaty z obsługi komputera, bezpieczeństwa w sieci i korzystania z usług online. Na blogu tworzy poradniki krok po kroku, tłumacząc techniczne pojęcia prostym językiem, bez uproszczeń prowadzących do błędów. Każdy materiał testuje z grupą użytkowników o różnym poziomie zaawansowania, a ich uwagi wykorzystuje do dopracowania treści. Jej priorytetem jest, by czytelnik po lekturze potrafił samodzielnie zastosować opisane rozwiązania w praktyce.