Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

API Integration - łączenie z AI

Z poprzedniej lekcji wiesz już, czym jest LLM, token i okno kontekstu. Kłopot w tym, że taki model nie mieszka na Twoim laptopie - stoi na serwerze dostawcy. Żeby go użyć z Pythona, trzeba wysłać zapytanie HTTP, podpisać je kluczem i rozpakować odpowiedź. Ręcznie to godzina dłubaniny, z oficjalną biblioteką - cztery linie.

Ta lekcja jest właśnie o tych czterech krokach: instalacji, imporcie, wywołaniu i odczycie wyniku. Tropienie modelu przez sieć niewiele różni się od tropienia zwierzyny: liczy się to, czy idziesz właściwą ścieżką, a nie jak szybko biegniesz.

Instalacja: pip, nie npm

Biblioteki Pythona instalujesz menedżerem pip. To pierwsza pułapka, bo w sieci krąży mnóstwo przykładów w JavaScripcie, gdzie ten sam pakiet instaluje się przez

npm install openai
.
npm
to menedżer pakietów Node.js - w Pythonie nie zainstaluje niczego
, w najlepszym razie powie, że nie zna takiej komendy.

Druga pułapka to nazwa pakietu. Firma nazywa się OpenAI, produkt ChatGPT, a rodzina modeli GPT - ale w repozytorium PyPI pakiet nazywa się po prostu

openai
. Polecenia
pip install chatgpt
oraz
pip install gpt4
nie zainstalują oficjalnej biblioteki, bo takich pakietów OpenAI nie wydaje. Analogicznie pakiet Anthropic nazywa się
anthropic
, a nie
claude
.

1pip install openai
2pip install anthropic

Po tych dwóch poleceniach masz w środowisku dwa niezależne pakiety. Żaden nie wysłał jeszcze ani jednego zapytania i żaden nie zna Twojego klucza API - klucz podasz dopiero przy tworzeniu klienta.

Import i klient OpenAI

Kolejność w linii importu jest zawsze taka sama:

from
openai
import
OpenAI
. Najpierw
from
wskazuje pakiet, z którego bierzemy, a dopiero potem
import
wskazuje nazwę, którą chcemy z niego wyciągnąć. Zwróć uwagę na wielkość liter: małymi zapisany jest pakiet (
openai
), wielkimi klasa klienta (
OpenAI
). Zamiana ich miejscami to najczęstszy błąd w tej jednej linii.

1from openai import OpenAI
2
3client = OpenAI(api_key="your-api-key")
4
5response = client.chat.completions.create(
6    model="gpt-4",
7    messages=[
8        {"role": "system", "content": "Jestes przewodnikiem safari o imieniu Darwin."},
9        {"role": "user", "content": "Ktore zwierze sawanny jest najszybsze?"}
10    ],
11    temperature=0.7,
12    max_tokens=500
13)

Samo wywołanie czyta się jak ścieżkę:

client
.chat
.completions
.create(
. Klient grupuje rodziny API,
chat
to rodzina rozmów,
completions
to zasób wewnątrz tej rodziny, a
create
to akcja, którą na nim wykonujesz. Kolejność nie jest umowna - zapis
client.completions.chat
nie istnieje, bo
completions
mieszka w środku
chat
, nie odwrotnie. Rozbita na pojedyncze elementy ta sama ścieżka wygląda tak:
client
,
.
,
chat
,
.
,
completions
,
.
,
create
.

Nazwa modelu to zwykły napis. Tutaj podaliśmy

"gpt-4"
, ale równie dobrze może tam stać
"gpt-5"
- biblioteka niczego nie sprawdza u siebie, tylko przekazuje nazwę dalej. Literówka skończy się błędem z serwera i akurat to jest dobra wiadomość.

Gorzej z parametrem

max_tokens
. Ogranicza on długość odpowiedzi, a nie długość pytania, i kiedy limit się wyczerpie, model po prostu przestaje pisać - w połowie zdania, bez żadnego wyjątku. Kod działa, odpowiedź jest, tylko urwana. Jeśli Twoje wyniki regularnie kończą się w pół myśli, @name, to zwykle nie wina modelu, lecz za niskiego
max_tokens
. Parametr
temperature
steruje z kolei losowością: 0 to odpowiedzi możliwie powtarzalne, 1 - bardziej zróżnicowane.

Odczyt odpowiedzi

W zmiennej

response
nie ma tekstu. Jest obiekt z metadanymi, a właściwa treść leży cztery kroki głębiej.

1answer = response.choices[0].message.content
2print(answer)

Ścieżka to

response
.choices[0]
.message
.content
, dokładnie w tej kolejności.
choices
jest listą, bo API potrafi zwrócić kilka wariantów odpowiedzi naraz, dlatego
[0]
wybiera pierwszy z nich.
message
to obiekt wiadomości, który ma między innymi rolę i treść, a
content
to dopiero czysty tekst. Pominięcie
[0]
da listę zamiast wiadomości, a zatrzymanie się na
.message
da obiekt, którego wydruk jest nieczytelnym zrzutem pól - bez błędu, po prostu nie to, o co chodziło.

Klient Anthropic

Z modelem Claude wygląda to bardzo podobnie, tylko nazwy są inne. Import ma tę samą kolejność:

from
anthropic
import
Anthropic
. Znów pakiet małą literą, klasa wielką. Spotkasz też wariant
import anthropic
, w którym klienta tworzy się przez
anthropic.Anthropic(...)
- działa tak samo, ale polecam wersję z
from
, bo raz wyciągnięta nazwa klasy jest potem krótsza w użyciu.

1from anthropic import Anthropic
2
3client = Anthropic(api_key="your-api-key")
4
5message = client.messages.create(
6    model="claude-sonnet-4-6",
7    max_tokens=1024,
8    system="Jestes ekspertem od jezyka Python.",
9    messages=[
10        {"role": "user", "content": "Jak napisac funkcje sortujaca?"}
11    ]
12)
13
14print(message.content[0].text)

Trzy różnice warto zapamiętać. Ścieżka wywołania jest krótsza -

client.messages.create(
, bez
chat
i bez
completions
. Instrukcja systemowa to osobny parametr
system
, a nie wpis w
messages
, więc wrzucenie tam roli
"system"
skończy się błędem z API. I wreszcie
max_tokens
jest tu obowiązkowy: bez niego zapytanie w ogóle nie przejdzie. Odpowiedź czytasz przez
message.content[0].text
, a nie przez
choices
- to rozgraniczenie łatwo pomylić, gdy w jednym projekcie korzystasz z obu dostawców.

Streaming, czyli stream=True

Domyślnie czekasz na całą odpowiedź i dopiero wtedy cokolwiek widzisz. Przy dłuższym tekście to kilkanaście sekund ciszy. Parametr

stream=True
zmienia jedno: odpowiedź dociera kawałkami, token po tokenie, i możesz ją wypisywać na bieżąco.

1stream = client.chat.completions.create(
2    model="gpt-4",
3    messages=[{"role": "user", "content": "Opowiedz historie o sawannie"}],
4    stream=True
5)
6
7for chunk in stream:
8    content = chunk.choices[0].delta.content
9    if content:
10        print(content, end="", flush=True)

Zamiast jednego obiektu dostajesz strumień fragmentów, po których przechodzisz pętlą. W trybie strumieniowym nie ma

.message
- fragment niesie
.delta
, czyli przyrost treści. Pierwszy i ostatni fragment mają
delta.content
równe
None
i właśnie dlatego stoi tam
if content:
. Bez tego sprawdzenia Python wypisze w środku tekstu słowo "None" i nie zgłosi żadnego błędu.

Warto też wiedzieć, czego

stream=True
nie robi. Nie szyfruje komunikacji - za szyfrowanie odpowiada HTTPS i działa ono identycznie w obu trybach. Nie kompresuje danych - kompresja jest sprawą transportu HTTP i biblioteka załatwia ją niezależnie od tego parametru. Nie zapisuje też odpowiedzi do pliku - jeśli chcesz mieć zapis, musisz sam otworzyć plik i dopisywać do niego kolejne fragmenty. Liczba zużytych tokenów i koszt pozostają takie same jak bez strumienia. Zmienia się wyłącznie moment, w którym tekst pojawia się na ekranie.

Podsumowanie

  • Biblioteki Pythona instalujesz poleceniem
    pip install openai
    . Zapis
    npm install openai
    należy do świata Node.js i w Pythonie nie zadziała.
  • Warianty
    pip install gpt4
    i
    pip install chatgpt
    nie instalują oficjalnej biblioteki - nazwa pakietu na PyPI to
    openai
    .
  • Import klienta OpenAI:
    from
    openai
    import
    OpenAI
    , czyli pakiet małą literą, klasa wielką.
  • Import klienta Anthropic:
    from
    anthropic
    import
    Anthropic
    , według tego samego wzorca.
  • Wywołanie czatu OpenAI:
    client
    .chat
    .completions
    .create(
    , znak po znaku
    client
    .
    chat
    .
    completions
    .
    create
    .
  • Odczyt odpowiedzi:
    response
    .choices[0]
    .message
    .content
    .
  • U Anthropic wywołujesz
    client.messages.create(...)
    ,
    max_tokens
    jest obowiązkowy, instrukcja idzie w parametrze
    system
    , a tekst odczytujesz z
    message.content[0].text
    .
  • stream=True
    służy do otrzymywania odpowiedzi w czasie rzeczywistym, token po tokenie. Nie szyfruje, nie kompresuje i nie zapisuje niczego do pliku.
  • Nazwa modelu to zwykły napis, na przykład
    "gpt-4"
    ,
    "gpt-5"
    albo
    "claude-sonnet-4-6"
    .

W następnej lekcji zajmiemy się treścią samych wiadomości - prompt engineering pokaże, jak formułować polecenia, żeby model trafiał za pierwszym razem. Na razie zapamiętaj jedno: całe API sprowadza się do czterech ruchów - zainstaluj pakiet, zaimportuj klasę klienta, zawołaj

create
i wyłuskaj tekst z końca ścieżki.

Przejdź do CodeWorlds