Работа с моделями завершения чата
Модели серии GPT-3.5-Turbo, GPT-4 и GPT-4o — это языковые модели, оптимизированные для интерфейсов диалога. Модели ведут себя не так, как старые модели GPT-3. Предыдущие модели работали по принципу "ввод текста — вывод текста", что означает, что они принимали строку запроса и возвращали завершение, чтобы добавить его к запросу. Однако последние модели созданы для ввода разговоров и вывода сообщений. Модели ожидают данные в определённом формате транскрипции чата. Они возвращают результат, который представляет собой сообщение, написанное моделью в чате. Этот формат был разработан специально для многоэтапных бесед, но он также может работать хорошо для сценариев, отличных от чата.
В этой статье описано, как приступить к работе с моделями завершения чата. Чтобы получить лучшие результаты, используйте описанные здесь методы. Не пытайтесь взаимодействовать с моделями так же, как с более старой серией моделей, потому что модели часто многословны и дают менее полезные ответы.
Работа с моделями завершения чата
В следующем фрагменте кода показан самый простой способ взаимодействия с моделями, используюющими API завершения чата. Если вы впервые используете эти модели программным способом, рекомендуем начать с инструкции по быстрому началу завершений чата.
import os
from openai import AzureOpenAI
client = AzureOpenAI(
api_key = os.getenv("AZURE_OPENAI_API_KEY"),
api_version = "2024-10-21",
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
)
response = client.chat.completions.create(
model="gpt-4o", # 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-4o",
"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.
Каждый ответ включает в себя finish_reason
. Возможные значения для finish_reason
:
- stop: API вернул полные выходные данные модели.
-
длина: неполный вывод модели из-за
max_tokens
параметра или предела токенов. - content_filter: Пропущенное содержимое из-за пометки нашими фильтрами содержимого.
- null: ответ API по-прежнему выполняется или неполный.
Рассмотрите возможность установки max_tokens
на немного более высокое значение, чем обычно. Более высокое значение гарантирует, что модель не перестает создавать текст, прежде чем он достигнет конца сообщения.
Работа с API завершения чата
OpenAI обучил модели для завершения чатов принимать входные данные в формате беседы. Параметр сообщений принимает массив объектов сообщений, где беседа организована по ролям. При использовании API Python используется список словарей.
Формат базового завершения чата:
{"role": "system", "content": "Provide some context and/or instructions to the model"},
{"role": "user", "content": "The users messages goes here"}
Беседа с одним примером ответа, за которым следует вопрос, будет выглядеть следующим образом:
{"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."}
Системная роль
Системная роль, также известная как системное сообщение, включается в начало массива. Это сообщение содержит начальные инструкции для модели. Вы можете предоставить различные сведения в системной роли, например:
- Краткое описание помощника.
- Черты личности помощника.
- Инструкции или правила, которые требуется выполнить помощнику.
- Данные или сведения, необходимые для модели, например соответствующие вопросы из часто задаваемых вопросов.
Вы можете настроить системную роль для вашего варианта использования или включить основные инструкции. Системная роль или сообщение являются необязательными, но мы рекомендуем добавить хотя бы базовый вариант, чтобы добиться лучших результатов.
Сообщения
После системной роли можно включить ряд сообщений между user
и assistant
.
{"role": "user", "content": "What is thermodynamics?"}
Чтобы активировать ответ от модели, завершите сообщение пользователем, указав, что теперь очередь помощника отвечать. Кроме того, можно включить ряд примеров сообщений между пользователем и помощником в качестве способа для обучения с малым количеством примеров.
Примеры запроса сообщения
В следующем разделе показаны примеры различных стилей запросов, которые можно использовать с моделями завершения чата. Эти примеры являются лишь отправной точкой. Вы можете экспериментировать с различными запросами на настройку поведения для собственных вариантов использования.
Простой пример
Если вы хотите, чтобы модель завершения чата выглядела аналогично chatgpt.com, можно использовать базовое системное сообщение, например 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?"}
Пример с инструкциями
Для некоторых сценариев может потребоваться предоставить модели дополнительные инструкции, чтобы определить ограничения для безопасности того, что модель может выполнять.
{"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?"}
Использование данных для заземления
Вы также можете включить соответствующие данные или сведения в системное сообщение, чтобы предоставить модели дополнительный контекст для беседы. Если необходимо включить только небольшое количество сведений, его можно жестко закодировать в системном сообщении. Если у вас есть большой объем данных, о которых должна знать модель, можно использовать внедрение или продукт, такой как поиск ИИ Azure, для получения наиболее важных сведений во время запроса.
{"role": "system", "content": "Assistant is an intelligent chatbot designed to help users answer technical questions about Azure OpenAI Service. 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?"}
Обучение с использованием малых выборок с завершением диалога
Вы также можете предоставить модели примеры с малым количеством данных (few-shot examples). Подход к обучению с малым количеством примеров немного изменился из-за нового формата подсказок. Теперь вы можете включить ряд сообщений между пользователем и помощником в запрос в качестве нескольких примеров. Используя эти примеры, вы можете заполнить ответы на распространенные вопросы, чтобы подготовить модель или научить её конкретному поведению.
В этом примере показано, как использовать обучение с несколькими примерами с GPT-35-Turbo и GPT-4. Вы можете поэкспериментировать с различными подходами, чтобы увидеть, что лучше всего подходит для вашего варианта использования.
{"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"}
Использование завершения чата для сценариев, отличных от чата
API завершения чата предназначен для работы с несколькими беседами, но он также хорошо подходит для сценариев, отличных от чата.
Например, для сценария извлечения сущностей можно использовать следующий запрос:
{"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?"}
Создание базового цикла беседы
В примерах до сих пор показана базовая механика взаимодействия с API завершения чата. В этом примере показано, как создать цикл беседы, выполняющий следующие действия:
- Непрерывно принимает входные данные консоли и правильно форматирует его как часть списка сообщений в качестве содержимого роли пользователя.
- Выводит ответы, которые печатаются в консоли, форматируются и добавляются в список сообщений как содержимое роли помощника.
Каждый раз, когда задают новый вопрос, вместе с ним отправляется запись беседы до сих пор. Так как у модели нет памяти, необходимо отправить обновленную расшифровку с каждым новым вопросом или модель потеряет контекст предыдущих вопросов и ответов.
import os
from openai import AzureOpenAI
client = AzureOpenAI(
api_key = os.getenv("AZURE_OPENAI_API_KEY"),
api_version = "2024-10-21",
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-4o", # model = "deployment_name".
messages=conversation
)
conversation.append({"role": "assistant", "content": response.choices[0].message.content})
print("\n" + response.choices[0].message.content + "\n")
При запуске предыдущего кода вы получите пустое окно консоли. Введите первый вопрос в окне и выберите Enter
ключ. После возврата ответа можно повторить процесс и задать вопросы.
Управление беседами
Предыдущий пример выполняется до тех пор, пока не будет достигнут предел количества токенов модели. При получении каждого вопроса и ответа messages
, список увеличивается. Лимит токенов для моделей завершения чата варьируется в зависимости от моделей и версий. Лимиты токенов для gpt-4
и gpt-4-32k
составляют соответственно 8 192 и 32 768. К этим ограничениям относится число токенов как из отправляемого списка сообщений, так и из ответа модели. Количество маркеров в списке сообщений в сочетании со значением параметра max_tokens
должно оставаться в пределах этих ограничений, иначе вы получите ошибку. Ознакомьтесь со страницей моделей, чтобы узнать об ограничениях на количество токенов и контекстных окнах для каждой модели.
Вы несете ответственность за то, чтобы запрос и завершение укладывались в лимиты токенов. Для длительных бесед необходимо отслеживать количество токенов и отправлять модели только такой запрос, который укладывается в лимит. Кроме того, при использовании API ответов вы можете поручить API усечение/управление журналом бесед.
Примечание.
Настоятельно рекомендуется оставаться в пределах задокументированного ограничения маркера ввода для всех моделей, даже если вы обнаружите, что это ограничение можно превысить.
В следующем примере кода показан простой пример цикла чата с методом обработки количества токенов 4096 с помощью библиотеки tiktoken OpenAI.
В коде используется tiktoken 0.5.1
. Если у вас более ранняя версия, выполните команду 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-10-21",
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")
В этом примере после достижения установленного количества токенов удаляются самые старые сообщения в транскрипте беседы. Для повышения эффективности del
используется вместо pop()
. Мы начинаем с индекса 1, чтобы всегда сохранять системное сообщение и удалять только сообщения пользователя или помощника. С течением времени этот метод управления беседой может привести к снижению качества беседы, так как модель постепенно теряет контекст предыдущих частей беседы.
Альтернативный подход — ограничить длительность беседы максимальной длиной токенов или определённым числом ходов. После того как будет достигнут максимальный лимит токенов, модель потеряет контекст, если вы продолжите беседу. Вы можете предложить пользователю начать новый разговор и очистить список сообщений, чтобы начать беседу с доступным полным лимитом токенов.
Ранее демонстрированная часть кода, отвечающая за подсчет токенов, является упрощенной версией одного из примеров из "кулинарной книги" OpenAI.
Устранение неполадок
Не используйте синтаксис ChatML или специальные маркеры с конечной точкой завершения чата
Некоторые клиенты пытаются использовать устаревший синтаксис ChatML с конечными точками завершения чата и более новыми моделями. ChatML — это функция предварительного просмотра, которая работала только с устаревшим конечным пунктом завершения с моделью gpt-35-turbo
0301. Эта модель назначена на снятие с производства. Если вы пытаетесь использовать синтаксис ChatML с более новыми моделями и конечной точкой завершения чата, это может привести к ошибкам и непредвиденному поведению ответа модели. Мы не рекомендуем использовать это. Эта же проблема может возникать при использовании общих специальных маркеров.
Код ошибки | Сообщение об ошибке | Решение |
---|---|---|
400 | 400 — "Не удалось создать выходные данные из-за специальных маркеров во входных данных". | Запрос содержит специальные маркеры или устаревшие токены ChatML, не распознанные или поддерживаемые моделью или конечной точкой. Убедитесь, что ваш массив запросов и сообщений не содержит устаревшие токены ChatML или специальные токены. Если вы обновляете устаревшую модель, исключите все специальные маркеры перед отправкой запроса API в модель. |
Не удалось создать завершение, так как модель сгенерировала недопустимые Юникод-символы.
Код ошибки | Сообщение об ошибке | Обходное решение |
---|---|---|
500 | 500 — Внутренняя Ошибка Сервера: код ошибки: 500 - {'error': {'message': 'Не удалось создать результат, так как модель сгенерировала недопустимый Юникодный вывод'}}. | Вы можете свести к минимуму возникновение этих ошибок, уменьшая температуру запросов до менее 1 и обеспечивая использование клиента с логикой повторных попыток. Повторная попытка выполнить запрос часто приводит к успешному ответу. |
Следующие шаги
- Дополнительные сведения о службе Azure OpenAI.
- Начало работы с моделями завершения чата в кратком руководстве по завершению чата с.
- Чтобы увидеть больше примеров, посетите репозиторий GitHub Azure OpenAI Samples.