Praca z modelami GPT-3.5-Turbo i GPT-4

Modele GPT-3.5-Turbo i GPT-4 to modele językowe zoptymalizowane pod kątem interfejsów konwersacyjnych. Modele zachowują się inaczej niż starsze modele GPT-3. Poprzednie modele były tekstowe i tekstowe, co oznacza, że zaakceptowały ciąg monitu i zwróciły ukończenie, aby dołączyć do monitu. Jednak modele GPT-3.5-Turbo i GPT-4 to konwersacja i komunikat-out. Modele oczekują danych wejściowych sformatowanych w określonym formacie transkrypcji przypominającym czat. Zwracają one ukończenie, które reprezentuje wiadomość napisaną przez model w czacie. Ten format został zaprojektowany specjalnie na potrzeby konwersacji wieloeściowych, ale może również działać dobrze w przypadku scenariuszy niechętowych.

W tym artykule przedstawiono wprowadzenie do modeli GPT-3.5-Turbo i GPT-4. Aby uzyskać najlepsze wyniki, skorzystaj z technik opisanych tutaj. Nie próbuj wchodzić w interakcje z modelami w taki sam sposób, jak w przypadku starszej serii modeli, ponieważ modele są często pełne i zapewniają mniej przydatne odpowiedzi.

Praca z modelami GPT-3.5-Turbo i GPT-4

Poniższy fragment kodu przedstawia najbardziej podstawowy sposób używania modeli GPT-3.5-Turbo i GPT-4 z interfejsem API uzupełniania czatu. Jeśli używasz tych modeli po raz pierwszy programowo, zalecamy rozpoczęcie od przewodnika Szybki start GPT-3.5-Turbo i GPT-4.

Uwaga

W dokumentacji usługi Azure OpenAI zamiennie odwołujemy się do GPT-3.5-Turbo i GPT-35-Turbo. Oficjalna nazwa modelu w systemie OpenAI to gpt-3.5-turbo. W przypadku usługi Azure OpenAI z powodu ograniczeń znaków specyficznych dla platformy Azure podstawowa nazwa modelu to gpt-35-turbo.

import os
from openai import AzureOpenAI

client = AzureOpenAI(
  api_key = os.getenv("AZURE_OPENAI_API_KEY"),  
  api_version = "2024-02-01",
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
)

response = client.chat.completions.create(
    model="gpt-35-turbo", # model = "deployment_name".
    messages=[
        {"role": "system", "content": "Assistant is a large language model trained by OpenAI."},
        {"role": "user", "content": "Who were the founders of Microsoft?"}
    ]
)

#print(response)
print(response.model_dump_json(indent=2))
print(response.choices[0].message.content)
{
  "id": "chatcmpl-8GHoQAJ3zN2DJYqOFiVysrMQJfe1P",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "Microsoft was founded by Bill Gates and Paul Allen. They established the company on April 4, 1975. Bill Gates served as the CEO of Microsoft until 2000 and later as Chairman and Chief Software Architect until his retirement in 2008, while Paul Allen left the company in 1983 but remained on the board of directors until 2000.",
        "role": "assistant",
        "function_call": null
      },
      "content_filter_results": {
        "hate": {
          "filtered": false,
          "severity": "safe"
        },
        "self_harm": {
          "filtered": false,
          "severity": "safe"
        },
        "sexual": {
          "filtered": false,
          "severity": "safe"
        },
        "violence": {
          "filtered": false,
          "severity": "safe"
        }
      }
    }
  ],
  "created": 1698892410,
  "model": "gpt-35-turbo",
  "object": "chat.completion",
  "usage": {
    "completion_tokens": 73,
    "prompt_tokens": 29,
    "total_tokens": 102
  },
  "prompt_filter_results": [
    {
      "prompt_index": 0,
      "content_filter_results": {
        "hate": {
          "filtered": false,
          "severity": "safe"
        },
        "self_harm": {
          "filtered": false,
          "severity": "safe"
        },
        "sexual": {
          "filtered": false,
          "severity": "safe"
        },
        "violence": {
          "filtered": false,
          "severity": "safe"
        }
      }
    }
  ]
}
Microsoft was founded by Bill Gates and Paul Allen. They established the company on April 4, 1975. Bill Gates served as the CEO of Microsoft until 2000 and later as Chairman and Chief Software Architect until his retirement in 2008, while Paul Allen left the company in 1983 but remained on the board of directors until 2000.

Uwaga

Następujące parametry nie są dostępne w nowych modelach GPT-35-Turbo i GPT-4: logprobs, best_ofi echo. Jeśli ustawisz dowolny z tych parametrów, zostanie wyświetlony błąd.

Każda odpowiedź zawiera finish_reason. Możliwe wartości właściwości finish_reason:

  • stop: interfejs API zwrócił pełne dane wyjściowe modelu.
  • length: Niekompletne dane wyjściowe modelu z powodu parametru max_tokens lub limitu tokenu.
  • content_filter: pominięto zawartość z powodu flagi z filtrów zawartości.
  • null: odpowiedź interfejsu API jest nadal w toku lub niekompletna.

Rozważ ustawienie max_tokens nieco wyższej wartości niż zwykle, na przykład 300 lub 500. Wyższa wartość gwarantuje, że model nie przestaje generować tekstu, zanim osiągnie koniec komunikatu.

Wersje modelu danych

Uwaga

Wersja gpt-35-turbo jest równoważna modelowi z interfejsu gpt-3.5-turbo OpenAI.

W przeciwieństwie do poprzednich modeli gpt-35-turbo GPT-3 i GPT-3.5 model i gpt-4gpt-4-32k będą nadal aktualizowane. Podczas tworzenia wdrożenia tych modeli należy również określić wersję modelu.

Daty wycofania modelu dla tych modeli można znaleźć na stronie modeli .

Praca z interfejsem API uzupełniania czatu

OpenAI wytrenował modele GPT-35-Turbo i GPT-4 w celu akceptowania danych wejściowych sformatowanych jako konwersacja. Parametr messages przyjmuje tablicę obiektów komunikatów z konwersacją zorganizowaną według roli. W przypadku korzystania z interfejsu API języka Python jest używana lista słowników.

Format podstawowego ukończenia czatu to:

{"role": "system", "content": "Provide some context and/or instructions to the model"},
{"role": "user", "content": "The users messages goes here"}

Rozmowa z jedną przykładową odpowiedzią, po której następuje pytanie, wygląda następująco:

{"role": "system", "content": "Provide some context and/or instructions to the model."},
{"role": "user", "content": "Example question goes here."},
{"role": "assistant", "content": "Example answer goes here."},
{"role": "user", "content": "First question/message for the model to actually respond to."}

Rola systemu

Rola systemu, znana również jako komunikat systemowy, jest uwzględniana na początku tablicy. Ten komunikat zawiera początkowe instrukcje dotyczące modelu. Możesz podać różne informacje w roli systemu, takie jak:

  • Krótki opis asystenta.
  • Cechy osobowości asystenta.
  • Instrukcje lub reguły, które mają być przestrzegane przez asystenta.
  • Dane lub informacje potrzebne do modelu, takie jak istotne pytania z często zadawanych pytań.

Rolę systemu można dostosować dla danego przypadku użycia lub dołączyć podstawowe instrukcje. Rola/komunikat systemu jest opcjonalny, ale zalecamy uwzględnienie co najmniej podstawowego, aby uzyskać najlepsze wyniki.

Wiadomości

Po roli systemowej można uwzględnić szereg komunikatów między elementami userassistanti .

 {"role": "user", "content": "What is thermodynamics?"}

Aby wyzwolić odpowiedź z modelu, zakończ się komunikatem użytkownika, aby wskazać, że asystent odpowiada. Możesz również dołączyć serię przykładowych komunikatów między użytkownikiem a asystentem jako sposób na naukę kilku zdjęć.

Przykłady monitów o komunikat

W poniższej sekcji przedstawiono przykłady różnych stylów monitów, których można używać z modelami GPT-35-Turbo i GPT-4. Te przykłady są tylko punktem wyjścia. Możesz eksperymentować z różnymi monitami, aby dostosować zachowanie dla własnych przypadków użycia.

Przykład podstawowy

Jeśli chcesz, aby model GPT-35-Turbo zachowywał się podobnie do chat.openai.com, możesz użyć podstawowego komunikatu systemowego, takiego jak Assistant is a large language model trained by OpenAI.

{"role": "system", "content": "Assistant is a large language model trained by OpenAI."},
{"role": "user", "content": "Who were the founders of Microsoft?"}

Przykład z instrukcjami

W przypadku niektórych scenariuszy możesz podać więcej instrukcji do modelu, aby zdefiniować bariery ochronne dla tego, co może zrobić model.

{"role": "system", "content": "Assistant is an intelligent chatbot designed to help users answer their tax related questions.
Instructions: 
- Only answer questions related to taxes. 
- If you're unsure of an answer, you can say "I don't know" or "I'm not sure" and recommend users go to the IRS website for more information. "},
{"role": "user", "content": "When are my taxes due?"}

Używanie danych do uziemienia

Możesz również uwzględnić odpowiednie dane lub informacje w komunikacie systemowym, aby nadać modelowi dodatkowy kontekst konwersacji. Jeśli musisz uwzględnić tylko niewielką ilość informacji, możesz go zakodować w komunikacie systemowym. Jeśli masz dużą ilość danych, o których powinien wiedzieć model, możesz użyć osadzania lub produktu, takiego jak usługa Azure AI Search , aby pobrać najbardziej istotne informacje w czasie wykonywania zapytania.

{"role": "system", "content": "Assistant is an intelligent chatbot designed to help users answer technical questions about Azure OpenAI Serivce. Only answer questions using the context below and if you're not sure of an answer, you can say 'I don't know'.

Context:
- Azure OpenAI Service provides REST API access to OpenAI's powerful language models including the GPT-3, Codex and Embeddings model series.
- Azure OpenAI Service gives customers advanced language AI with OpenAI GPT-3, Codex, and DALL-E models with the security and enterprise promise of Azure. Azure OpenAI co-develops the APIs with OpenAI, ensuring compatibility and a smooth transition from one to the other.
- At Microsoft, we're committed to the advancement of AI driven by principles that put people first. Microsoft has made significant investments to help guard against abuse and unintended harm, which includes requiring applicants to show well-defined use cases, incorporating Microsoft’s principles for responsible AI use."
},
{"role": "user", "content": "What is Azure OpenAI Service?"}

Nauka z kilkoma strzałami z ukończeniem czatu

Możesz również podać kilka przykładów do modelu. Podejście do uczenia kilku strzałów nieco się zmieniło z powodu nowego formatu monitu. Teraz możesz dołączyć serię komunikatów między użytkownikiem a asystentem w wierszu polecenia jako przykłady z kilkoma zrzutami. Korzystając z tych przykładów, można zainicjować odpowiedzi na często zadawane pytania, aby zastosować model lub nauczyć określone zachowania modelu.

W tym przykładzie pokazano, jak korzystać z uczenia kilku strzałów z GPT-35-Turbo i GPT-4. Możesz eksperymentować z różnymi podejściami, aby zobaczyć, co działa najlepiej w przypadku użycia.

{"role": "system", "content": "Assistant is an intelligent chatbot designed to help users answer their tax related questions. "},
{"role": "user", "content": "When do I need to file my taxes by?"},
{"role": "assistant", "content": "In 2023, you will need to file your taxes by April 18th. The date falls after the usual April 15th deadline because April 15th falls on a Saturday in 2023. For more details, see https://www.irs.gov/filing/individuals/when-to-file."},
{"role": "user", "content": "How can I check the status of my tax refund?"},
{"role": "assistant", "content": "You can check the status of your tax refund by visiting https://www.irs.gov/refunds"}

Korzystanie z uzupełniania czatu w scenariuszach niechętowych

Interfejs API uzupełniania czatu jest przeznaczony do pracy z konwersacjami wieloeściowymi, ale działa również dobrze w scenariuszach niechętowych.

Na przykład w scenariuszu wyodrębniania jednostek można użyć następującego monitu:

{"role": "system", "content": "You are an assistant designed to extract entities from text. Users will paste in a string of text and you will respond with entities you've extracted from the text as a JSON object. Here's an example of your output format:
{
   "name": "",
   "company": "",
   "phone_number": ""
}"},
{"role": "user", "content": "Hello. My name is Robert Smith. I'm calling from Contoso Insurance, Delaware. My colleague mentioned that you are interested in learning about our comprehensive benefits policy. Could you give me a call back at (555) 346-9322 when you get a chance so we can go over the benefits?"}

Tworzenie podstawowej pętli konwersacji

W przykładach pokazano do tej pory podstawową mechanikę interakcji z interfejsem API uzupełniania czatu. W tym przykładzie pokazano, jak utworzyć pętlę konwersacji, która wykonuje następujące akcje:

  • Stale pobiera dane wejściowe konsoli i prawidłowo formatuje je jako część listy komunikatów jako zawartość roli użytkownika.
  • Zwraca odpowiedzi, które są drukowane w konsoli i sformatowane i dodane do listy komunikatów jako zawartość roli asystenta.

Za każdym razem, gdy zostanie zadane nowe pytanie, jest wysyłana bieżąca transkrypcja konwersacji do tej pory wraz z najnowszym pytaniem. Ponieważ model nie ma pamięci, musisz wysłać zaktualizowaną transkrypcję z każdym nowym pytaniem lub model utraci kontekst poprzednich pytań i odpowiedzi.

import os
from openai import AzureOpenAI

client = AzureOpenAI(
  api_key = os.getenv("AZURE_OPENAI_API_KEY"),  
  api_version = "2024-02-01",
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")  # Your Azure OpenAI resource's endpoint value.
)

conversation=[{"role": "system", "content": "You are a helpful assistant."}]

while True:
    user_input = input("Q:")      
    conversation.append({"role": "user", "content": user_input})

    response = client.chat.completions.create(
        model="gpt-35-turbo", # model = "deployment_name".
        messages=conversation
    )

    conversation.append({"role": "assistant", "content": response.choices[0].message.content})
    print("\n" + response.choices[0].message.content + "\n")

Po uruchomieniu poprzedniego kodu zostanie wyświetlone puste okno konsoli. Wprowadź pierwsze pytanie w oknie, a następnie wybierz Enter klucz. Po powrocie odpowiedzi możesz powtórzyć proces i zadawać pytania.

Zarządzanie konwersacjami

Poprzedni przykład jest uruchamiany do momentu przekroczenia limitu tokenu modelu. Po każdym z zadawanych pytań i otrzymaniu messages odpowiedzi lista rośnie rozmiar. Limit tokenu dla gpt-35-turbo wynosi 4096 tokenów. Limity tokenów dla gpt-4 wartości i gpt-4-32k są odpowiednio 8192 i 32 768. Te limity obejmują liczbę tokenów zarówno z listy komunikatów wysłanych, jak i odpowiedzi modelu. Liczba tokenów na liście komunikatów w połączeniu z wartością max_tokens parametru musi pozostać w ramach tych limitów lub występuje błąd.

Twoim zadaniem jest upewnienie się, że monit i ukończenie mieszczą się w limicie tokenu. W przypadku dłuższych konwersacji należy śledzić liczbę tokenów i wysyłać tylko modelowi monit, który mieści się w limicie.

Uwaga

Zdecydowanie zalecamy pozostanie w udokumentowanych limitach tokenów wejściowych dla wszystkich modeli, nawet jeśli okaże się, że można przekroczyć ten limit.

Poniższy przykładowy kod przedstawia prosty przykład pętli czatu z techniką obsługi liczby tokenów 4096 przy użyciu biblioteki tiktoken interfejsu OpenAI.

Kod używa tiktoken 0.5.1. Jeśli masz starszą wersję, uruchom polecenie pip install tiktoken --upgrade.

import tiktoken
import os
from openai import AzureOpenAI

client = AzureOpenAI(
  api_key = os.getenv("AZURE_OPENAI_API_KEY"),  
  api_version = "2024-02-01",
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")  # Your Azure OpenAI resource's endpoint value.
)

system_message = {"role": "system", "content": "You are a helpful assistant."}
max_response_tokens = 250
token_limit = 4096
conversation = []
conversation.append(system_message)

def num_tokens_from_messages(messages, model="gpt-3.5-turbo-0613"):
    """Return the number of tokens used by a list of messages."""
    try:
        encoding = tiktoken.encoding_for_model(model)
    except KeyError:
        print("Warning: model not found. Using cl100k_base encoding.")
        encoding = tiktoken.get_encoding("cl100k_base")
    if model in {
        "gpt-3.5-turbo-0613",
        "gpt-3.5-turbo-16k-0613",
        "gpt-4-0314",
        "gpt-4-32k-0314",
        "gpt-4-0613",
        "gpt-4-32k-0613",
        }:
        tokens_per_message = 3
        tokens_per_name = 1
    elif model == "gpt-3.5-turbo-0301":
        tokens_per_message = 4  # every message follows <|start|>{role/name}\n{content}<|end|>\n
        tokens_per_name = -1  # if there's a name, the role is omitted
    elif "gpt-3.5-turbo" in model:
        print("Warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613.")
        return num_tokens_from_messages(messages, model="gpt-3.5-turbo-0613")
    elif "gpt-4" in model:
        print("Warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613.")
        return num_tokens_from_messages(messages, model="gpt-4-0613")
    else:
        raise NotImplementedError(
            f"""num_tokens_from_messages() is not implemented for model {model}."""
        )
    num_tokens = 0
    for message in messages:
        num_tokens += tokens_per_message
        for key, value in message.items():
            num_tokens += len(encoding.encode(value))
            if key == "name":
                num_tokens += tokens_per_name
    num_tokens += 3  # every reply is primed with <|start|>assistant<|message|>
    return num_tokens
while True:
    user_input = input("Q:")      
    conversation.append({"role": "user", "content": user_input})
    conv_history_tokens = num_tokens_from_messages(conversation)

    while conv_history_tokens + max_response_tokens >= token_limit:
        del conversation[1] 
        conv_history_tokens = num_tokens_from_messages(conversation)

    response = client.chat.completions.create(
        model="gpt-35-turbo", # model = "deployment_name".
        messages=conversation,
        temperature=0.7,
        max_tokens=max_response_tokens
    )


    conversation.append({"role": "assistant", "content": response.choices[0].message.content})
    print("\n" + response.choices[0].message.content + "\n")

W tym przykładzie po osiągnięciu liczby tokenów najstarsze wiadomości w transkrypcji konwersacji zostaną usunięte. W celu zwiększenia wydajności del jest używana wartość zamiast pop(). Zaczynamy od indeksu 1, aby zawsze zachowywać komunikat systemowy i usuwać tylko komunikaty użytkownika lub asystenta. Z czasem ta metoda zarządzania konwersacją może spowodować obniżenie jakości konwersacji, ponieważ model stopniowo traci kontekst wcześniejszych części konwersacji.

Alternatywną metodą jest ograniczenie czasu trwania konwersacji do maksymalnej długości tokenu lub określonej liczby zakrętów. Po osiągnięciu maksymalnego limitu tokenów model utraci kontekst, gdyby zezwolić konwersacji na kontynuowanie. Możesz poprosić użytkownika o rozpoczęcie nowej konwersacji i wyczyszczenie listy wiadomości, aby rozpocząć nową konwersację z dostępnym pełnym limitem tokenów.

Pokazana wcześniej część zliczania tokenów w kodzie jest uproszczoną wersją jednego z przykładów książki kucharskiej openAI.

Rozwiązywanie problemów

Oto porada dotycząca rozwiązywania problemów.

Nie używaj składni ChatML ani specjalnych tokenów z punktem końcowym uzupełniania czatu

Niektórzy klienci próbują użyć starszej składni ChatML z punktami końcowymi uzupełniania czatu i nowszymi modelami. ChatML to funkcja w wersji zapoznawczej, która pracowała tylko z starszym punktem końcowym uzupełniania z modelem gpt-35-turbo wersji 0301. Ten model ma zostać przeniesiony na emeryturę. Jeśli spróbujesz użyć składni ChatML z nowszymi modelami i punktem końcowym ukończenia czatu, może to spowodować błędy i nieoczekiwane zachowanie odpowiedzi modelu. Nie zalecamy tego użycia. Ten sam problem może wystąpić podczas korzystania z typowych tokenów specjalnych.

Kod błędu Komunikat o błędzie Rozwiązanie
400 400 — "Nie można wygenerować danych wyjściowych ze względu na specjalne tokeny w danych wejściowych". Monit zawiera specjalne tokeny lub starsze tokeny ChatML, które nie są rozpoznawane lub obsługiwane przez model/punkt końcowy. Upewnij się, że tablica monitów/komunikatów nie zawiera żadnych starszych tokenów ChatML/tokenów specjalnych. W przypadku uaktualniania ze starszego modelu wyklucz wszystkie tokeny specjalne przed przesłaniem żądania interfejsu API do modelu.

Nie można utworzyć ukończenia, ponieważ model wygenerował nieprawidłowe dane wyjściowe Unicode

Kod błędu Komunikat o błędzie Rozwiązanie
500 500 — InternalServerError: Kod błędu: 500 — {'error': {'message': "Nie można utworzyć ukończenia, ponieważ model wygenerował nieprawidłowe dane wyjściowe Unicode}}. Możesz zminimalizować występowanie tych błędów, zmniejszając temperaturę monitów do mniej niż 1 i upewniając się, że używasz klienta z logiką ponawiania prób. Ponowne przytłaczanie żądania często skutkuje pomyślną odpowiedzią.

Następne kroki