Разработка AI API
Удобно использовать чат-инструменты ИИ в веб-интерфейсе, но чтобы по-настоящему интегрировать возможности ИИ в ваши собственные продукты, рабочие процессы и скрипты автоматизации, вам нужен API.
API (Application Programming Interface) — это мост для связи между приложениями. Через API ваш код может напрямую отправлять запросы к модели ИИ и получать ответы без необходимости вручную открывать веб-страницу и копировать-вставлять.
Представьте такие сценарии:
Ваш сайт электронной коммерции автоматически генерирует описательный текст для каждого товара.
-
Ваше приложение для заметок автоматически делает краткое изложение длинных текстов, введённых пользователями.
-
Ваша система поддержки клиентов автоматически классифицирует обращения пользователей и отвечает на них.
-
Все эти возможности можно реализовать через API ИИ.
Цель этого модуля — провести вас от «умения только общаться с ИИ» к «умению заставить ИИ работать в вашем коде».
Базовые концепции API
Прежде чем писать код, сначала разберитесь в нескольких ключевых концепциях.
Что такое API
API — это набор согласованных протоколов взаимодействия. Мы отправляем запросы в определённом формате, а другая сторона возвращает результаты в определённом формате.
Проведём аналогию с заказом еды:
-
Вы заходите в ресторан, получаете меню (документацию API) и понимаете, что можно заказать и как заказать (формат запроса).
-
Вы говорите официанту: «Одну курицу кунг-пао, поменьше острого» (отправка запроса к API).
-
Кухня готовит блюдо и приносит его вам (возврат ответа API).
В этом процессе вам не нужно заходить на кухню и не нужно знать, как готовится блюдо, — в этом и ценность API:инкапсулировать сложные детали, предоставляя только простой интерфейс。
Основы REST API
REST (Representational State Transfer) — в настоящее время самый популярный стиль проектирования API.
Проще говоря, для взаимодействия используется протокол HTTP:
| HTTP-метод | Назначение | Пример в API ИИ |
|---|---|---|
| POST | Создание ресурса | Отправка чат-запросов, генерация изображений |
| GET | Получение ресурса | Запрос списков моделей, получение информации о счетах |
| DELETE | Удаление ресурса | Удаление истории диалога |
Подавляющее большинство API ИИ используют POST-запросы, потому что нам нужно "отправлять контент ИИ для обработки".
Основы формата JSON
JSON (JavaScript Object Notation) — самый распространённый формат данных при взаимодействии с API.
Синтаксис JSON очень прост; это комбинация пар «ключ-значение».
Примеры
"model": "gpt-4",
"messages": [
{
"role": "user",
"content": "Привет, пожалуйста, представь EXAMPLE"
}
],
"temperature": 0.7,
"max_tokens": 1000
}
Это типичное тело запроса к API ИИ.
Несколько основных правил:
-
Для объектов используйте
{ }чтобы обернуть, для массивов используйте[ ]чтобы обернуть. -
В строках используются двойные кавычки
", нельзя использовать одинарные кавычки. -
Пары «ключ-значение» разделяются двоеточием
:для разделения, ключи должны быть строками. -
Несколько пар «ключ-значение» разделяются запятой
,для разделения.
JSON очень похож на словари Python, но есть синтаксические различия; обращайте внимание при написании кода.
Настройка среды разработки
Чтобы хорошо выполнить работу, сначала нужно заточить инструменты.
Установка и настройка Python
Python — самый распространённый язык для вызова API ИИ, со зрелой экосистемой и богатыми библиотеками.
Сначала проверьте, установлен ли Python на вашем компьютере:
# 检查 Python 版本(Windows、macOS、Linux 通用) python --version # 或者 python3 --version
Рекомендуется использовать Python 3.9 или выше.
Если он не установлен, перейдите наpython.orgи скачайте последнюю стабильную версию.
Управление пакетами pip
pip — это менеджер пакетов Python, используемый для установки сторонних библиотек.
# 检查 pip 版本 pip --version # 或者 pip3 --version # 升级 pip 到最新版本 pip install --upgrade pip # 配置国内镜像源(可选,提升下载速度) pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
Выбор редактора кода
Для написания кода для API ИИ мы рекомендуем один из следующих редакторов:
| Редактор | Особенности | Целевые пользователи |
|---|---|---|
| VS Code | Бесплатный, богатая экосистема плагинов, легковесный | Большинство разработчиков |
| Cursor | Встроенная помощь ИИ, может напрямую генерировать код | Для тех, кто хочет, чтобы ИИ помогал писать код |
| PyCharm | Самый многофункциональный, лучшая поддержка Python | Профессиональные Python-разработчики |
Пример кода из этого руководства можно запустить в любом редакторе.
Основы OpenAI API
OpenAI API — это самый классический и устоявшийся API для ИИ, и многие другие поставщики совместимы с его форматом.
Регистрация и получение API-ключа
API-ключ — это ваш пропуск, подтверждающий вашу личность и фиксирующий ваше использование. Шаги для его получения:
-
1. Посетитеplatform.openai.comЗарегистрируйте аккаунт
-
2. Перейдите на страницу API-ключей
-
3. Нажмите "Создать новый секретный ключ"
-
4. Скопируйте и сохраните этот ключ (он показывается только один раз!)
Важно:Никогда не коммитьте свой API-ключ в публичный репозиторий кода. Если он утечёт, другие могут использовать вашу квоту, и вам выставят счёт.
Первый вызов API
Сначала установите официальный OpenAI SDK:
pip install openai
Теперь напишите вашу первую программу вызова API:
Примеры
# Пример первого вызова OpenAI API
from openai import OpenAI
# Инициализация клиента
# Примечание: рекомендуется читать API Key из переменных окружения; не встраивайте его жёстко в код
# Для демонстрационных целей он записан прямо здесь. В реальных проектах используйте переменные окружения.
client = OpenAI(
api_key="your-api-key-here" # Замените на ваш API Key
)
# Отправьте запрос к чату
response = client.chat.completions.create(
model="gpt-3.5-turbo", # Выберите модель
messages=[
{
"role": "user", # Роль: user обозначает пользователя
"content": "Пожалуйста, расскажите в одном предложении о Rookie Tutorial от EXAMPLE." # Содержимое, введённое пользователем
}
]
)
# Выведите полный ответ (посмотрите, что было возвращено)
print("Полный ответ:")
print(response)
print("\n" + "="*50 + "\n")
# Извлечь ответ ИИ
ai_reply = response.choices[0].message.content
print("Ответ ИИ:")
print(ai_reply)
Если у вас нет OpenAI api_key, вы также можете использовать альтернативы от местных провайдеров. Многие местные модели совместимы с OpenAI, например DeepSeek. Вы можете перейти наhttps://platform.deepseek.com/api_keysПодайте заявку на api_key, а затем замените свои значения на следующий кодapi_keyиmodel, DeepSeek поддерживает модели deepseek-v4-flash и deepseek-v4-pro (режим мышления), и вы можете использовать API для вызова больших моделей:
Примеры
# Инициализация клиента
# Примечание: рекомендуется читать API Key из переменной окружения, не прописывайте его жёстко в коде
# Для демонстрации он указан здесь напрямую. В реальных проектах используйте переменные окружения
client = OpenAI(
api_key="sk-xxxx", # Задайте api_key
base_url="https://api.deepseek.com") # Укажите адрес запроса
# Отправьте запрос к чату
response = client.chat.completions.create(
model="deepseek-v4-flash", # Выберите модель
messages=[
{
"role": "user", # Роль: user обозначает пользователя
"content": "Пожалуйста, расскажите в одном предложении о Rookie Tutorial от EXAMPLE." # Содержимое, введённое пользователем
}
]
)
# Выведите полный ответ (посмотрите, что было возвращено)
print("Полный ответ:")
print(response)
print("\n" + "="*50 + "\n")
# Извлечь ответ ИИ
ai_reply = response.choices[0].message.content
print("Ответ ИИ:")
print(ai_reply)
Запустите эту программу:
python first_api_call.py
Если всё работает нормально, вы увидите примерно такой вывод:
完整响应: ChatCompletion( id='chatcmpl-xxx', choices=[Choice(finish_reason='stop', index=0, message=ChatMessage(content='Example是一个专注于提供编程技术教程的学习平台...', role='assistant'))], model='gpt-3.5-turbo', usage=CompletionUsage(completion_tokens=30, prompt_tokens=18, total_tokens=48) ) ================================================== AI 回复: Example是一个专注于提供编程技术教程的学习平台,涵盖多种编程语言和技术领域。
Поздравляем! Вы успешно вызвали AI API.
Пояснение параметров запроса
У OpenAI API есть много параметров, которые можно настроить. Вот наиболее часто используемые из них:
| Название параметра | Type | Обязательный | Описание | Значение по умолчанию |
|---|---|---|---|---|
| model | string | Да | ID модели для использования, например gpt-3.5-turbo, gpt-4 | Отсутствует |
| messages | array | Да | Список сообщений истории диалога | Отсутствует |
| temperature | число | нет | Температура сэмплирования, от 0 до 2. Чем выше она, тем более случайный результат; чем ниже, тем более детерминированный. | 1.0 |
| max_tokens | целое число | нет | Максимальное количество токенов для генерации | Безлимитный |
| top_p | число | нет | Параметр ядерной выборки, между 0-1 | 1.0 |
| stop | строка/массив | нет | Стоп-последовательность; остановить генерацию при обнаружении этих символов | null |
Сосредоточимся на temperature — наиболее часто используемом параметре настройки:
Примеры
# Демонстрация влияния параметра temperature на вывод
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
def ask_ai(temperature_value: float, question: str) -> str:
"""Укажите temperature для вопроса"""
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": question}],
temperature=temperature_value,
max_tokens=200
)
return response.choices[0].message.content
# Задайте один и тот же вопрос три раза с разной температурой
question = "Придумайте слоган для EXAMPLE"
print("--- temperature=0 (наиболее детерминированный, результаты похожи каждый раз) ---")
print(ask_ai(0.0, question))
print("\n--- temperature=0.7 (сбалансированный, рекомендуется для повседневного использования) ---")
print(ask_ai(0.7, question))
print("\n--- temperature=1.8 (наиболее случайный, результаты сильно различаются каждый раз) ---")
print(ask_ai(1.8, question))
Практическое правило:
-
temperature=0: фактологические ответы, генерация кода, сценарии, требующие точных результатов
-
temperature=0.7: повседневное общение, общие задачи
-
temperature>1.0: творческое письмо, мозговой штурм
Anthropic Claude API
Claude — большая языковая модель от Anthropic, известная своей безопасностью и возможностями обработки длинных текстов.
Сходства и различия с OpenAI API
Оба могут генерировать текст, но есть некоторые различия в философии проектирования:
| Пункт сравнения | OpenAI API | Claude API |
|---|---|---|
| Структура сообщений | system, user, assistant чередуются | system задаётся отдельно, user и assistant чередуются |
| Длина контекста | 16k-128k варьируется | Серия Claude 3 поддерживает 200k |
| Проектирование параметров | temperature, top_p и т. д. | temperature, top_p и т. д., схожие концепции |
Структура Claude Messages API
Сначала установите Claude SDK:
pip install anthropic
Базовые вызовы Claude API:
Примеры
# Пример базового вызова Claude API
import anthropic
# Инициализация клиента
client = anthropic.Anthropic(
api_key="your-api-key-here" # Замените на ваш ключ API Claude
)
# Отправить запрос сообщения
response = client.messages.create(
model="claude-3-sonnet-20240229", # Выберите модель Claude
max_tokens=1024, # Claude требует установки max_tokens
messages=[
{
"role": "user",
"content": "Пожалуйста, расскажите о EXAMPLE Rookie Tutorial в трёх предложениях"
}
]
)
# Вывести ответ
print("Полный ответ:")
print(response)
print("\n" + "="*50 + "\n")
# Извлечь ответ
print("Ответ Claude:")
print(response.content[0].text)
Аналогично мы можем заменить его на совместимую отечественную большую модель, например DeepSeek, указавapi_key 、 base_url、modelЭти три параметра:
Примеры
# Инициализировать клиент
client = anthropic.Anthropic(
api_key="sk-xxx", # Замените на свой API-ключ
base_url="https://api.deepseek.com/anthropic" # Базовый URL для Claude API
)
# Отправить запрос сообщения
response = client.messages.create(
model="deepseek-v4-flash", # Выберите модель Claude
max_tokens=1024, # Claude требует установки max_tokens
messages=[
{
"role": "user",
"content": "Пожалуйста, представьте учебник EXAMPLE в трёх предложениях."
}
]
)
# Вывести ответ
print("Полный ответ:")
print(response)
print("\n" + "="*50 + "\n")
# Извлечь ответ
print("Ответ Claude:")
print(response.content[0].thinking)
Настройки системного промпта
В Claude API System Prompt — независимый параметр, он не помещается в массив messages:
Примеры
# Пример использования Claude System Prompt
import anthropic
client = anthropic.Anthropic(api_key="your-api-key-here")
response = client.messages.create(
model="claude-3-sonnet-20240229",
max_tokens=1024,
# Здесь задаётся системный промпт
system="Вы профессиональный редактор технической документации. Отвечайте кратко и точно, при необходимости используйте списки.",
messages=[
{
"role": "user",
"content": "Какие ключевые знания нужно освоить при изучении Python?"
}
]
)
print(response.content[0].text)
Управление многоходовым диалогом
Одноходовые диалоги просты, но действительно полезным приложениям нужно "помнить контекст".
Способы ведения истории диалога
Подход прост:Сохраняйте все предыдущие диалоги и отправляйте их ИИ с каждым запросом。
Примеры
# Пример управления многоходовым диалогом
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
class ChatBot:
"""Простой бот для многоходового диалога"""
def __init__(self, system_prompt: str = "Вы полезный ассистент"):
self.messages = [] # Используйте список для хранения истории диалога
# Сначала добавьте системный промпт
self.messages.append({
"role": "system",
"content": system_prompt
})
def chat(self, user_input: str) -> str:
"""Отправьте сообщение и получите ответ"""
# Добавьте сообщение пользователя в историю
self.messages.append({
"role": "user",
"content": user_input
})
# Вызовите API
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=self.messages
)
# Получите ответ ИИ
ai_reply = response.choices[0].message.content
# Также добавьте ответ ИИ в историю
self.messages.append({
"role": "assistant",
"content": ai_reply
})
return ai_reply
def get_history(self) -> list:
"""Получить историю разговора"""
return self.messages
# Пример использования
if __name__ == "__main__":
bot = ChatBot(system_prompt="Вы — помощник по программированию, специализирующийся на ответах на вопросы об EXAMPLE и Python")
print("=== Демонстрация многоходового диалога ===")
# Первый раунд
r1 = bot.chat("Что такое Python?")
print(Пользователь: Что такое Python?)
print("ИИ:", r1)
print()
# Второй раунд (ИИ может помнить предыдущую тему)
r2 = bot.chat(Каковы его возможности?)
print(Пользователь: Каковы его возможности?)
print("ИИ:", r2)
print()
# Третий раунд
r3 = bot.chat(Есть ли руководства по Python на EXAMPLE?)
print(Пользователь: Есть ли руководства по Python на EXAMPLE?)
print("ИИ:", r3)
Ключевой момент: история диалога представляет собой упорядоченный список, строго чередующийся между пользователем и ассистентом: пользователь-ассистент-пользователь-ассистент. Каждый запрос должен отправлять полную историю, чтобы ИИ мог понимать контекст. История расходует токены, поэтому её нужно регулярно очищать.
Обработка переполнения контекстного окна
У каждой модели есть ограничение контекстного окна, например, gpt-3.5-turbo — 16k, gpt-4 — 8k или 32k.
Когда история диалога слишком длинная, возникает ошибка.
Несколько распространённых стратегий обработки:
Примеры
# Пример стратегий управления контекстным окном
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
class ChatBotWithContextLimit:
"""Чат-бот с ограничением контекста"""
def __init__(self, system_prompt: str, max_messages: int = 10):
self.system_prompt = system_prompt
self.max_messages = max_messages # Сколько сообщений хранить максимум
self.messages = []
def _trim_messages(self):
"""Обрезать список сообщений, оставить самые последние сообщения"""
# Всегда сохранять системный промпт, затем оставлять только последние max_messages
if len(self.messages) > self.max_messages:
# Оставлять N самых последних сообщений
self.messages = self.messages[-self.max_messages:]
def chat(self, user_input: str) -> str:
# Добавить сообщение пользователя
self.messages.append({
"role": "user",
"content": user_input
})
# Сократить историю
self._trim_messages()
# Сформировать полный запрос (системный промпт + история)
full_messages = [
{"role": "system", "content": self.system_prompt}
] + self.messages
try:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=full_messages
)
ai_reply = response.choices[0].message.content
self.messages.append({
"role": "assistant",
"content": ai_reply
})
return ai_reply
except Exception as e:
# Если всё ещё возникают ошибки, может потребоваться более агрессивное сокращение
return f"Ошибка: {str(e)}"
# Стратегия 2: использовать ИИ для суммирования истории разговора
def summarize_conversation(messages: list) -> str:
"""Использовать ИИ для суммирования истории разговора, заменяя исходную историю"""
history_text = "\n".join([
f"{m['role']}: {m['content']}"
for m in messages
])
prompt = f"""Пожалуйста, суммируйте следующий разговор в краткое резюме, сохранив ключевую информацию:
{history_text}
Резюме: """
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}],
temperature=0
)
return response.choices[0].message.content
# Использовать стратегию суммаризации
print("--- Пример резюме истории разговора ---")
sample_history = [
{"role": "user", "content": "Как меня зовут?"},
{"role": "assistant", "content": "Извините, я не знаю вашего имени. Вы можете мне сказать."},
{"role": "user", "content": "Меня зовут Сяо Мин, я изучаю Python на EXAMPLE."},
{"role": "assistant", "content": "Привет, Сяо Мин! Приятно познакомиться. EXAMPLE — отличная обучающая платформа."},
{"role": "user", "content": "Я хочу узнать о списках, можешь меня научить?"},
{"role": "assistant", "content": "Конечно! Списки Python — это..."},
]
summary = summarize_conversation(sample_history)
print("Сводка диалога:", summary)
Обобщите методы управления контекстом:
| Стратегия | Преимущества | Недостатки | Применимые сценарии |
|---|---|---|---|
| Оставлять только последние N записей | Просто, быстро | Может привести к потере важной информации | Короткие разговоры, сценарии непринуждённого общения |
| Использовать ИИ для обобщения истории | Сохраняет семантическую информацию | Требует дополнительных вызовов API | Длинные диалоги, много важной информации |
| Скользящее окно | Сочетает простоту и полноту | Немного сложнее в реализации | Общего назначения для типичных сценариев |
Потоковый вывод
Когда вы общаетесь с ИИ на веб-странице, текст появляется слово за словом — это потоковый вывод.
Что такое потоковый вывод
-
Обычный режим: ИИ возвращает полный ответ сразу после его генерации; возможно, придётся подождать несколько секунд или даже десятки секунд.
-
Потоковый режим: ИИ отправляет каждый токен сразу после его генерации, обеспечивая лучший пользовательский опыт.
Технически потоковый вывод использует протокол SSE (Server-Sent Events), при котором сервер непрерывно отправляет данные.
Реализация эффекта печатной машинки
Примеры
# Демонстрация потокового вывода (эффект печатной машинки)
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
print("=== Демонстрация потокового вывода ===")
print("Вопрос: Напишите введение к EXAMPLE\n")
print("A:", end="", flush=True)
# Ключевой параметр: stream=True
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "user", "content": "Пожалуйста, напишите введение к руководству EXAMPLE"}
],
stream=True # Включить потоковый вывод
)
collected_reply = []
for chunk in response:
# Извлечь содержимое текущего фрагмента
if chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
print(content, end="", flush=True) # Печать в реальном времени без переносов строк
collected_reply.append(content)
print() # Вывести перевод строки в конце
print("\n" + "="*50)
print("Полный ответ:", "".join(collected_reply))
Запустите эту программу, и вы увидите, как текст появляется слово за словом.
Использование потокового вывода Claude аналогично:
Примеры
# Пример потокового вывода Claude
import anthropic
client = anthropic.Anthropic(api_key="your-api-key-here")
print("=== Потоковый вывод Claude ===")
print("Вопрос: Как научиться программировать?"\n")
print("A:", end="", flush=True)
with client.messages.stream(
model="claude-3-sonnet-20240229",
max_tokens=1024,
messages=[{"role": "user", "content": "Как системно изучать программирование?"}]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
print()
Совет по пользовательскому опыту: если сценарий не требует "обязательно дожидаться полного результата", отдавайте приоритет потоковому выводу. Когда пользователи видят прогресс, это может значительно улучшить опыт.
Расчёт и оптимизация затрат на API
API ИИ тарифицируются по использованию; чем больше вы используете, тем больше платите.
Принципы тарификации токенов
API ИИ тарифицируется не по количеству слов или числу разговоров, а потокену,Токенявляется базовой единицей обработки текста ИИ.
Один токен приблизительно равен:
Английский: 0.75 слова (или 4 буквы)
-
Китайский: 1-2 китайских иероглифа
Например:
-
"Hello, World" — приблизительно 3-4 токена
-
"EXAMPLE Rookie Tutorial is great" — приблизительно 6-8 токенов
Способ оплаты:
Prompt tokens(你发给 AI 的) + Completion tokens(AI 返回给你的)= 总 tokens
У разных моделей разные цены, например gpt-3.5-turbo стоит $0.0015/1k токенов промпта, $0.002/1k токенов ответа.
Как контролировать затраты на API
Примеры
# Пример отслеживания и контроля затрат API
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
# Список цен моделей (пример, актуальные цены смотрите в официальной документации)
# Единица измерения: USD / 1k токенов
MODEL_PRICES = {
"gpt-3.5-turbo": {
"prompt": 0.0015,
"completion": 0.002
},
"gpt-4": {
"prompt": 0.03,
"completion": 0.06
}
}
def chat_with_cost_tracking(model: str, messages: list):
"""Чат со статистикой затрат"""
response = client.chat.completions.create(
model=model,
messages=messages
)
# Получаем использование токенов из ответа
usage = response.usage
prompt_tokens = usage.prompt_tokens
completion_tokens = usage.completion_tokens
total_tokens = usage.total_tokens
# Вычисляем стоимость
price = MODEL_PRICES.get(model, {"prompt": 0, "completion": 0})
prompt_cost = (prompt_tokens / 1000) * price["prompt"]
completion_cost = (completion_tokens / 1000) * price["completion"]
total_cost = prompt_cost + completion_cost
return {
"reply": response.choices[0].message.content,
"usage": {
"prompt_tokens": prompt_tokens,
"completion_tokens": completion_tokens,
"total_tokens": total_tokens
},
"cost": {
"prompt_cost": prompt_cost,
"completion_cost": completion_cost,
"total_cost": total_cost
}
}
# Пример использования
if __name__ == "__main__":
result = chat_with_cost_tracking(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "Расскажи о Python"}]
)
print("Ответ ИИ:", result["reply"])
print()
print("Статистика использования:")
print(f" Токены промпта: {result['usage']['prompt_tokens']}")
print(f" Токены ответа: {result['usage']['completion_tokens']}")
print(f" Всего токенов: {result['usage']['total_tokens']}")
print()
print("Статистика стоимости (USD):")
print(f" Стоимость промпта: ${result['cost']['prompt_cost']:.6f}")
print(f" Стоимость ответа: ${result['cost']['completion_cost']:.6f}")
print(f" Общая стоимость: ${result['cost']['total_cost']:.6f}")
Несколько практических советов по оптимизации затрат:
| Совет | Как это сделать | Коэффициент экономии |
|---|---|---|
| Выбирайте подходящую модель | Используйте gpt-3.5-turbo для простых задач, а не gpt-4 | 90%+ |
| Ограничьте max_tokens | Установите разумный верхний предел, чтобы ИИ не говорил слишком много | Зависит от ситуации |
| Сокращайте контекст | Сохраняйте только необходимую историю переписки | 50%+ |
| Делайте промпты краткими | Не делайте системный промпт слишком длинным | Зависит от ситуации |
| Кэширование результатов | Возвращайте кэшированные результаты сразу для идентичных вопросов | Зависит от ситуации |
Стратегии кэширования
Для повторяющихся вопросов кеширование результатов может сэкономить много денег:
Примеры
# Простая реализация кеша ответов
import hashlib
import json
from openai import OpenAI
client = OpenAI(api_key="your-api-key-here")
class SimpleCache:
"""Простой кеш в памяти"""
def __init__(self):
self.cache = {}
def _make_key(self, model: str, messages: list) -> str:
"""Сгенерировать ключ кеша на основе содержимого запроса"""
# Сериализовать информацию о ключе и вычислить хеш
key_data = {
"model": model,
"messages": messages
}
key_str = json.dumps(key_data, sort_keys=True)
return hashlib.md5(key_str.encode()).hexdigest()
def get(self, model: str, messages: list):
"""Получить кэш"""
key = self._make_key(model, messages)
return self.cache.get(key)
def set(self, model: str, messages: list, value: str):
"""Установить кэш"""
key = self._make_key(model, messages)
self.cache[key] = value
# Функция чата с кэшем
cache = SimpleCache()
def chat_with_cache(model: str, messages: list):
# Сначала проверить кэш
cached = cache.get(model, messages)
if cached:
print("(Попадание в кэш, возвращаем сразу)")
return cached
# Промах кэша, вызываем API
response = client.chat.completions.create(
model=model,
messages=messages
)
reply = response.choices[0].message.content
# Сохраняем в кэш
cache.set(model, messages, reply)
return reply
#
if __name__ == "__main__":
messages = [{"role": "user", "content": "Что это за сайт EXAMPLE?"}]
print("Первый вызов...")
r1 = chat_with_cache("gpt-3.5-turbo", messages)
print(r1)
print()
print("Второй вызов (тот же вопрос)...")
r2 = chat_with_cache("gpt-3.5-turbo", messages)
print(r2)
Обработка ошибок и механизмы повторных попыток
Сетевые запросы всегда могут завершиться ошибкой, и API не исключение. Надёжный код должен обрабатывать различные сценарии исключений.
Распространённые типы ошибок
| Тип ошибки | Код состояния HTTP | Причина | Способ обработки |
|---|---|---|---|
| Ошибка аутентификации | 401 | Неверный или истёкший API-ключ | Проверьте API-ключ |
| Недостаточная квота | 402 | На счёте нет средств | Пополните баланс или смените аккаунт |
| Превышен лимит | 429 | Слишком частые запросы или исчерпана квота | Подождите немного и попробуйте снова |
| Ошибка сервера | 5xx | Проблема на стороне сервера ИИ | Повторить |
Повтор с экспоненциальной задержкой
При возникновении временных ошибок (например, 429, 5xx) наиболее распространённая стратегия — повтор с экспоненциальной задержкой:
-
Первая ошибка → подождать 1 секунду → повторить
-
Вторая ошибка → подождать 2 секунды → повторить
-
Третий сбой → подождать 4 секунды → повторить
-
Четвёртый сбой → подождать 8 секунд → повторить
Время ожидания каждый раз удваивается, что даёт сервису шанс восстановиться.
Примеры
# Обработка ошибок и повторные попытки с экспоненциальной задержкой
import time
from openai import OpenAI, APIError, RateLimitError, APIConnectionError
client = OpenAI(api_key="your-api-key-here")
def chat_with_retry(
model: str,
messages: list,
max_retries: int = 3,
initial_wait: float = 1.0
):
"""Функция чата с механизмом повторных попыток"""
retries = 0
while retries <= max_retries:
try:
response = client.chat.completions.create(
model=model,
messages=messages
)
return {
"success": True,
"reply": response.choices[0].message.content
}
except RateLimitError as e:
# Ошибка ограничения скорости: подождите немного и повторите попытку
retries += 1
if retries > max_retries:
return {
"success": False,
"error": f"Попытки повтора исчерпаны: {str(e)}"
}
wait_time = initial_wait * (2 ** (retries - 1))
print(f"Сработало ограничение скорости, ожидание {wait_time} секунд перед повторной попыткой...")
time.sleep(wait_time)
except APIConnectionError as e:
# Ошибка сетевого подключения: повторить
retries += 1
if retries > max_retries:
return {
"success": False,
"error": f"Сбой сетевого подключения: {str(e)}"
}
wait_time = initial_wait * (2 ** (retries - 1))
print(f"Сетевая ошибка, ожидание {wait_time} секунд перед повторной попыткой...")
time.sleep(wait_time)
except APIError as e:
# Ошибка API: повтор в зависимости от ситуации
if e.status_code and 500 <= e.status_code < 600:
retries += 1
if retries > max_retries:
return {
"success": False,
"error": f"Ошибка сервера: {str(e)}"
}
wait_time = initial_wait * (2 ** (retries - 1))
print(f"Ошибка сервера, ожидание {wait_time} секунд перед повторной попыткой...")
time.sleep(wait_time)
else:
# Ошибки, не связанные с 5xx, не повторять
return {
"success": False,
"error": fОшибка API: {str(e)}
}
except Exception as e:
# Прочие ошибки, не повторять
return {
"success": False,
"error": fНеизвестная ошибка: {str(e)}
}
# Пример использования
if __name__ == "__main__":
result = chat_with_retry(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "Привет, EXAMPLE"}]
)
if result["success"]:
print(Успех:, result["ответ"])
else:
print(Ошибка:, result["ошибка"])
Вы также можете использовать существующую библиотеку для упрощения логики повторных попыток, например tenacity, установите её с помощью следующей команды:
pip install tenacity
Примеры
# Используйте библиотеку tenacity для упрощения логики повторных попыток
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
from openai import OpenAI, RateLimitError, APIError
client = OpenAI(api_key="your-api-key-here")
@retry(
stop=stop_after_attempt(3), # Повторять до 3 раз
wait=wait_exponential(multiplier=1, min=1, max=10), # Экспоненциальная задержка: 1, 2, 4... до 10 секунд
retry=retry_if_exception_type((RateLimitError, APIError)) # Повторять только при определённых исключениях
)
def chat_with_tenacity(model: str, messages: list):
"""Использование декоратора tenacity для реализации повторных попыток"""
response = client.chat.completions.create(
model=model,
messages=messages
)
return response.choices[0].message.content
# Использование
try:
reply = chat_with_tenacity(
"gpt-3.5-turbo",
[{"role": "user", "content": "Расскажи о Python"}]
)
print(reply)
except Exception as e:
print(fОкончательная ошибка: {e})
Практический проект: инструмент чата с ИИ в командной строке
Теперь давайте объединим то, что мы изучили ранее, и создадим полноценный инструмент чата в командной строке.
Примеры
# ПРИМЕР ИИ-чат-бота — Полноценный инструмент командной строки
import sys
import json
import os
from datetime import datetime
from openai import OpenAI
class ExampleChatBot:
"""Полнофункциональный чат-бот для командной строки"""
def __init__(self, config_file: str = "config.json"):
# Загрузить конфигурацию
self.config = self._load_config(config_file)
self.client = OpenAI(api_key=self.config["api_key"])
# Состояние диалога
self.messages = []
self.total_tokens = 0
self.total_cost = 0.0
# Инициализировать системную подсказку
self._init_system_prompt()
def _load_config(self, config_file: str) -> dict:
"""Загрузить файл конфигурации"""
default_config = {
"api_key": "ваш-api-ключ-здесь",
"model": "gpt-3.5-turbo",
"system_prompt": "Вы — полезный ИИ-ассистент, работающий на EXAMPLE.",
"max_history": 20,
"stream": True,
"temperature": 0.7
}
if os.path.exists(config_file):
with open(config_file, "r", encoding="utf-8") as f:
user_config = json.load(f)
default_config.update(user_config)
return default_config
def _save_config(self, config_file: str = "config.json"):
"""Сохранить файл конфигурации"""
with open(config_file, "w", encoding="utf-8") as f:
json.dump(self.config, f, indent=2, ensure_ascii=False)
def _init_system_prompt(self):
"""Инициализировать системный промпт"""
self.messages = [
{
"role": "system",
"content": self.config["system_prompt"]
}
]
def _trim_history(self):
"""Обрезать историю диалога"""
# Оставить системный промпт + самые последние N диалогов
max_messages = self.config["max_history"]
if len(self.messages) > max_messages + 1:
self.messages = [self.messages[0]] + self.messages[-max_messages:]
def chat(self, user_input: str) -> str:
"""Отправить сообщение и получить ответ"""
# Добавить сообщение пользователя
self.messages.append({
"role": "user",
"content": user_input
})
# Сократить историю
self._trim_history()
if self.config["stream"]:
return self._chat_stream()
else:
return self._chat_normal()
def _chat_normal(self) -> str:
"""Обычный режим (без потоковой передачи)"""
response = self.client.chat.completions.create(
model=self.config["model"],
messages=self.messages,
temperature=self.config["temperature"]
)
ai_reply = response.choices[0].message.content
# Подсчитать использование
if hasattr(response, "usage"):
self.total_tokens += response.usage.total_tokens
# Приблизительно оценить стоимость (цена gpt-3.5-turbo)
self.total_cost += (response.usage.total_tokens / 1000) * 0.002
self.messages.append({
"role": "assistant",
"content": ai_reply
})
return ai_reply
def _chat_stream(self) -> str:
"""Режим потоковой передачи"""
response = self.client.chat.completions.create(
model=self.config["model"],
messages=self.messages,
temperature=self.config["temperature"],
stream=True
)
collected_chunks = []
print("ИИ:", end="", flush=True)
for chunk in response:
if chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
print(content, end="", flush=True)
collected_chunks.append(content)
print()
ai_reply = "".join(collected_chunks)
self.messages.append({
"role": "assistant",
"content": ai_reply
})
# Подсчёт токенов в потоковом режиме требует дополнительной обработки, здесь упрощено
# В реальных проектах можно вызвать API использования или оценить
self.total_tokens += len(ai_reply) // 2 # Приблизительная оценка
return ai_reply
def save_conversation(self, filename: str = None):
"""Сохранить историю беседы"""
if not filename:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"conversation_{timestamp}.json"
data = {
"model": self.config["model"],
"total_tokens": self.total_tokens,
"estimated_cost": self.total_cost,
"messages": self.messages,
"saved_at": datetime.now().isoformat()
}
with open(filename, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
return filename
def clear_history(self):
"""Очистить историю разговора"""
self._init_system_prompt()
self.total_tokens = 0
self.total_cost = 0.0
def show_stats(self):
"""Показать статистику"""
print("\n" + "="*40)
print(Статистика диалога)
print("="*40)
print(fМодель: {self.config['model']})
print(fКоличество сообщений: {len(self.messages) - 1})
print(fВсего токенов: {self.total_tokens})
print(fПримерная стоимость: ${self.total_cost:.4f})
print("="*40 + "\n")
def print_help():
"""Вывести справочную информацию"""
print("\n" + "="*40)
print(ПРИМЕР AI Chat Tool - Список команд)
print("="*40)
print(/help - Показать справку)
print(/clear - Очистить историю диалога)
print(/stats - Показать статистику)
print(/save - Сохранить историю беседы)
print(/model - Переключить модель)
print(/temp - Настроить температуру)
print(/system - Изменить системный промпт)
print(/quit - Выйти из программы)
print("="*40 + "\n")
def main():
print("="*40)
print(ПРИМЕР Инструмент чата с ИИ)
print("="*40)
print(Введите /help для просмотра команд или введите текст напрямую, чтобы начать чат\n")
bot = ExampleChatBot()
while True:
try:
user_input = input(Вы:).strip()
if not user_input:
continue
# Обработка команд
if user_input.startswith("/"):
cmd = user_input.lower()
if cmd in ["/quit", "/exit", "/q"]:
print(До свидания!)
break
elif cmd == "/help":
print_help()
elif cmd == "/clear":
bot.clear_history()
print(История переписки очищена)
elif cmd == "/stats":
bot.show_stats()
elif cmd == "/save":
filename = bot.save_conversation()
print(fРазговор сохранён в: {filename})
elif cmd.startswith("/model "):
model = user_input[7:].strip()
bot.config["model"] = model
bot._save_config()
print(fМодель переключена на: {model})
elif cmd.startswith("/temp "):
try:
temp = float(user_input[6:].strip())
if 0 <= temp <= 2:
bot.config["temperature"] = temp
bot._save_config()
print(fТемпература установлена на: {temp})
else:
print(Температура должна быть в диапазоне 0-2)
except ValueError:
print(Пожалуйста, введите корректное число)
elif cmd.startswith("/system "):
system_prompt = user_input[8:].strip()
bot.config["system_prompt"] = system_prompt
bot.clear_history()
bot._save_config()
print(Системный промпт обновлён, диалог сброшен)
else:
print(Неизвестная команда, введите /help для справки)
else:
# Обычный чат
if not bot.config["stream"]:
print("ИИ:", end="")
bot.chat(user_input)
print()
except KeyboardInterrupt:
print("\nВведите /quit для выхода или продолжайте общаться)
except Exception as e:
print(fОшибка: {e})
if __name__ == "__main__":
main()
Создайте файл конфигурации:
{
"api_key": "your-api-key-here",
"model": "gpt-3.5-turbo",
"system_prompt": "你是一个乐于助人的 AI 助手,由 EXAMPLE 提供技术支持。",
"max_history": 20,
"stream": true,
"temperature": 0.7
}
Теперь вы можете запустить этот инструмент чата:
python example_chatbot.py
Вы увидите:
======================================== EXAMPLE AI 聊天工具 ======================================== 输入 /help 查看命令,直接输入文字开始聊天 你:你好 AI:你好!很高兴见到你。我是由 EXAMPLE 提供技术支持的 AI 助手,有什么可以帮你的吗? 你:/stats ======================================== 对话统计 ======================================== 模型:gpt-3.5-turbo 消息数:2 总 tokens:50 估算费用:$0.0001 ======================================== 你:/quit 再见!Другие расширения