Strona główna / Artykuły

Przenoszenie pętli czatu z OpenAI do Claude w Pythonie: jedna strona zmian

Przenieś bezstanowy pętlę wiadomości do API Messages firmy Anthropic: parametr systemu najwyższego poziomu, wymagane max_tokens, bloki treści oraz ścisła rotacja ról.

Wydawca: REACTAPP.TOP4 min czytania867 słów

Źródła: Part 3 — Call the Claude API in Python (same messages, system on the side)

Każdy, kto napisał pętlę czatową dla OpenAI, może przenieść ją do Claude od Anthropic przy około jednej stronie zmian. Obie usługi mają podobną strukturę: listę messages z tagami ról jest wysyłana w całości przy każdym wezwaniu, a odpowiedź dodawana jest później. Zmienia się tylko jeden element, więc ważne jest, aby dokładnie wiedzieć który.

Ta sama lista, inny system poza nią

API Messages w Claude akceptuje format rozmowy, który już znasz: listę słowników zawierających role i content, która nie przechowuje stanu na serwerze i jest wysyłana w całości za każdym razem. Nazwy i znaczenia ról są identyczne – user i assistant.

Jedyna różnica strukturalna polega na tym, że system nie jest wiadomością. OpenAI umieszcza instrukcje w pierwszym wierszu listy. Anthropic przenosi je do parametru system= najwyższego poziomu, który towarzyszy liście. Lista zawiera jedynie rzeczywistą rozmowę – kolejne kroki użytkownika i asystenta, które naprzemiennie się zmieniają.

import anthropic

client = anthropic.Anthropic()  # key from env

resp = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=300,
    system="You are a concise Python assistant.",
    messages=[
        {
            "role": "user",
            "content": "Why is system a parameter "
                       "here, not a message?",
        },
    ],
)
print(resp.content[0].text)

Dwie mniejsze różnice pojawiają się przed uruchomieniem żadnej z tych operacji:

  • max_tokens musi być ustawiony. OpenAI pozwala wysłać żądanie bez ograniczenia liczby tokenów. Claude wymaga takiego ustawienia przy każdym wywołaniu, co jest nieco irytujące, ale pomaga kontrolować koszty, ponieważ żądanie nie może zostać wysłane, dopóki nie zdecydujesz, jak długo ma trwać odpowiedź.
  • Odpowiedzi przychodzą w postaci bloków treści. Zamiast jednej ciągłej wartości otrzymujesz listę, a tekst prosty znajduje się w resp.content[0].text. Dziś może to wydawać się zbędne, ale później wywołania narzędzi również przychodzą w tej samej strukturze, więc to ma sens.

Ustawienia i jedna tura

Zainstaluj SDK za pomocą pip install anthropic, a następnie wyeksportuj klucz z konsoli Anthropic (zaczyna się od sk-ant-) jako ANTHROPIC_API_KEY. Klient sam go pobierze.

Umieść to obok wywołania OpenAI – cała różnica polega na czterech modyfikacjach. Metoda client.chat.completions.create zmienia się na client.messages.create, wiersz systemowy przenosi się do pola system=, konieczne staje się ograniczenie ilości wyjść, a tekst jest odczytywany z content[0].text zamiast z choices[0].message.content. Uwaga dotycząca SDK: obecny pakiet anthropic nie akceptuje parametru temperature= w metodzie messages.create, więc starsze przykłady, które go zawierają, będą wywoływać błędy. Stosuje się standardowe metody próbkowania, co jest w porządku dla tych przykładów.

Liczba tokenów znajduje się w polach resp.usage.input_tokens i resp.usage.output_tokens. Są to te same wskaźniki z nieco innymi nazwami pól, dlatego warto je rejestrować za każdym razem.

Pętla historii w Claude

Oto przeniesiona funkcja ask() z wersji OpenAI. Logika dodawania i ponownego wysyłania nie uległa zmianie. Zmieniła się tylko funkcja wywoływana w środku.

msgs = []

def ask(text: str) -> str:
    msgs.append(
        {"role": "user", "content": text}
    )
    resp = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=300,
        system="You are a concise assistant.",
        messages=msgs,  # full history
    )
    reply = resp.content[0].text
    msgs.append(
        {"role": "assistant", "content": reply}
    )
    return reply

print(ask("Define a context window."))
print(ask("Now for a five-year-old."))
print(ask("Which answer was shorter?"))

Trzecie pytanie w rozmowie nadal potwierdza ten błąd, ponieważ działa tylko wtedy, gdy obie wcześniejsze odpowiedzi znajdują się w msgs i są wysyłane ponownie. Obowiązują tu te same zasady ekonomiczne – liczba tokenów wejściowych rośnie przy każdej kolejności, więc długie rozmowy są droższe za jedną próbę połączenia.

Claude jest również bardziej wymagający co do kolejności przekazywania wiadomości – muszą one naprzemiennie pochodzić od użytkownika i asystenta. Dwie wiadomości od użytkownika z rzędu, co często się zdarza przy ponownej próbie nieudanej prośby, powodują odrzucenie połączenia przez Claude’a, podczas gdy OpenAI to toleruje. Uznaj to za darmową zasadę weryfikacyjną dla mechanizmu zarządzającego historią rozmów.

Rozruch

Skrypt uruchamia jedną rundę rozmowy, a następnie trzy rundy, rejestrując tokeny wejściowe i wyjściowe po każdej próbie połączenia. Jeśli brakuje ANTHROPIC_API_KEY, zatrzymuje się wcześniej i wyświetla jasną informację. Ponadto wysyła żądania w czasie rzeczywistym, które są opłacane, więc nie należy go używać podczas żadnych procesów CI.

pip install -r requirements.txt
export ANTHROPIC_API_KEY="sk-ant..."
python examples/part03_claude.py

Dlaczego przeniesienie było proste i co z tego wynika

Była to niewielka zmiana, ponieważ oba dostawcy oferują ten sam interfejs: bezstanowy punkt końcowy, który przy każdym wezwaniu przetwarza całą rozmowę i odpowiada raz. Różnice dotyczą szczegółów implementacji, takich jak lokalizacja komendy systemowej, wygląd obiektu odpowiedzi oraz wymagane parametry. LangChain abstrahuje tę warstwę, a jego klasy ChatOpenAI i ChatAnthropic służą do obsługi różnic, które wcześniej musiało się ręcznie wpisywać. Znajomość tego, co ukrywa abstrakcja, decyduje o tym, czy będzie się jej używać efektywnie, czy też da się przez nią uwięzić.

Istnieje również praktyczna korzyść. Dwa dostawcy w ramach jednej struktury ask() umożliwiają przeprowadzanie testów A/B modeli, przechodzenie na alternatywny źródło w przypadku problemów z API lub kierowanie prostych pytań do jednego, a trudnych do drugiego, wszystko to bez konieczności modyfikacji kodu aplikacji. API Gemini od Google stosuje tę samą strukturę rozmowy, z jedyną zmianą w nazwie roli – asystent nazywa się teraz model.