Kurs Python · Moduł 10: AI i modele językowe

API Integration - łączenie z AI

6 min czytania
W tej lekcji6

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 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.

Kod do tej lekcji: main.py
1# ===========================================
2# Safari Lab: OpenAI Chat Completions
3# ===========================================
4# Use the OpenAI API to create a safari guide
5# assistant that answers wildlife questions.
6
7from openai import OpenAI
8
9# --- Initialize the client ---
10client = OpenAI(api_key="your-api-key-here")
11
12# --- Create a chat completion ---
13response = client.chat.completions.create(
14    model="gpt-4",
15    messages=[
16        {
17            "role": "system",
18            "content": "You are a knowledgeable safari guide named Darwin. "
19                       "Answer questions about African wildlife concisely."
20        },
21        {
22            "role": "user",
23            "content": "What is the fastest animal on the savanna?"
24        }
25    ],
26    temperature=0.7,
27    max_tokens=150
28)
29
30# --- Extract the response ---
31answer = response.choices[0].message.content
32print("=== Safari Guide Response ===")
33print(f"Darwin says: {answer}")
34print(f"\nTokens used: {response.usage.total_tokens}")
35
36# TODO: Add a follow-up message to the conversation
37# by extending the messages list
38# messages = [
39#     {"role": "system", "content": "You are safari guide Darwin."},
40#     {"role": "user", "content": "What is the fastest animal?"},
41#     {"role": "assistant", "content": answer},
42#     {"role": "user", "content": "How fast can it run?"}
43# ]
44# follow_up = client.chat.completions.create(
45#     model="gpt-4",
46#     messages=messages,
47#     temperature=0.7
48# )
49# print(f"\nFollow-up: {follow_up.choices[0].message.content}")
50
51# TODO: Try a different temperature (0.0 for deterministic)
52# creative_response = client.chat.completions.create(
53#     model="gpt-4",
54#     messages=[
55#         {"role": "user", "content": "Describe a sunset on the savanna."}
56#     ],
57#     temperature=...
58# )
59# print(f"\nCreative: {creative_response.choices[0].message.content}")
60

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. Jak zainstalować bibliotekę OpenAI w Pythonie?

  2. 2. Do czego służy parametr stream=True w API?

Zadania praktyczne w grze

  • Układanie w poziomie

    Ułóż elementy:

  • Układanie w poziomie

    Ułóż import klienta OpenAI:

  • Edytor kodu

    Utwórz klienta OpenAI i wyślij wiadomość do modelu gpt-4.

  • Układanie w poziomie

    Ułóż elementy:

  • Edytor kodu

    Utwórz klienta Anthropic i wyślij wiadomość do modelu Claude.

  • Klikanie w kolejności

    Kliknij w kolejności:

  • Klikanie w kolejności

    Kliknij w przyciski, aby stworzyć chat completion:

Przydatne artykuły