Обращение к моделям в формате OpenAI-compatible -как это сделать?
💡 OpenAI API — программный интерфейс для работы с языковыми моделями (LLM) от компании OpenAI. Сегодня он фактически стал отраслевым стандартом. API упрощает работу разработчиков: не нужно разбираться в особенностях каждого сервиса, доступны многочисленные примеры и интеграции. Yandex AI Studio совместим с OpenAI API. Это означает, что приложения, написанные под OpenAI (например, на базе LangChain или LlamaIndex), можно легко адаптировать — достаточно изменить параметры подключения и названия моделей.В OpenAI-совместимом API доступны два интерфейса для работы с моделями:
- Responses API (
responses) — современный универсальный интерфейс (рекомендуется); - Chat Completions API (
chat.completions) — классический интерфейс для обратной совместимости.
ЛогикаВ этом уроке основной упор сделан на Responses API. Вы узнаете, как подключить OpenAI-совместимый API, выполнять генерацию текста, вызывать функции и работать с эмбеддингами. Приступим!
Начало работы с OpenAI API
Взаимодействовать с OpenAI API можно напрямую, но для удобства лучше использовать официальный набор инструментов OpenAI SDK.Чтобы использовать модели Yandex AI Studio через OpenAI SDK, нужно задать базовый эндпоинт и указать данные для аутентификации в Yandex Cloud: ключ или токен.📚 Процесс получения данных для аутентификации подробно описан в документации.
from openai import OpenAI
YANDEX_CLOUD_FOLDER_ID = "<идентификатор_каталога>"
YANDEX_CLOUD_API_KEY = "<значение_API-ключа>"
YANDEX_CLOUD_MODEL = "<модель_для_выполнения_задачи>"
client = OpenAI(
api_key=YANDEX_CLOUD_API_KEY,
base_url="https://ai.api.cloud.yandex.net/v1",
project=YANDEX_CLOUD_FOLDER_ID,
)
Генерация текста
Основная задача любой языковой модели (LLM) — генерировать текст. Модель получает на вход инструкции с описанием задачи и формирует ответ.Управлять генерацией можно через следующие параметры:
instructions— текстовые инструкции для модели, определяющие её роль, стиль ответа и правила поведения;temperature— регулирует вариативность ответа: значения ближе к 0 делают ответ более предсказуемым, ближе к 1 — более креативным;max_output_tokens— задаёт максимальную длину ответа в токенах;stream— включает потоковую передачу ответа по мере его генерации.
Логика Давайте рассмотрим на примерах, как задавать эти параметры.
from openai import OpenAI
YANDEX_CLOUD_FOLDER_ID = "<идентификатор_каталога>"
YANDEX_CLOUD_API_KEY = "<значение_API-ключа>"
YANDEX_CLOUD_MODEL = "aliceai-llm"
client = OpenAI(
api_key=YANDEX_CLOUD_API_KEY,
base_url="https://ai.api.cloud.yandex.net/v1",
project=YANDEX_CLOUD_FOLDER_ID,
)
response = client.responses.create(
model=f"gpt://{YANDEX_CLOUD_FOLDER_ID}/{YANDEX_CLOUD_MODEL}",
temperature=0.3,
instructions="Ты — полезный ассистент. Отвечай кратко, по делу и без лишних пояснений.",
input="Что умеют большие языковые модели?",
max_output_tokens=500,
stream=True,
)
print("Ответ модели:\n", end="", flush=True)
for event in response:
if event.type == "response.output_text.delta":
# Выведите каждую часть текста по мере генерации
print(event.delta, end="", flush=True)
Ниже представлен один из возможных вариантов ответа модели. Поскольку параметр stream установлен в True, ответ передаётся по мере генерации. Этот режим особенно удобен для интерактивных сценариев:
- текстовые чаты — ответ отображается постепенно, позволяя пользователю начать чтение до завершения генерации;
- голосовые интерфейсы — синтез речи может выполняться параллельно с генерацией текста.
Ответ модели:
— генерировать текст (статьи, рассказы, письма, код и т. д.);
— отвечать на вопросы;
— переводить тексты;
— суммировать информацию;
— поддерживать диалог;
— анализировать тональность текста;
— предлагать идеи и решения;
— выполнять простые логические и арифметические задачи;
— работать с шаблонами и формализованными данными.
В данном случае ответ модели полностью вместился в заданный лимит max_output_tokens. Если установленного значения недостаточно, генерация прекращается сразу после достижения лимита. В результате ответ может оборваться в произвольном месте.Например, если установить max_output_tokens=20, можно получить следующий результат:
Ответ модели:
— генерировать текст;
— отвечать на вопросы;
— переводить языки;
— суммировать
💡 При обращении к моделям Yandex AI Studio необходимо передавать идентификатор вашего каталога как часть URI модели.
Структурированный формат ответа
Во многих сценариях ответ модели нужен не в виде свободного текста, а в заранее заданной структуре. Это удобно, если результат нужно обрабатывать программно: передавать в CRM, извлекать сущности из текста, выполнять классификацию, формировать параметры для вызова API или сохранять данные в бизнес-системах.В OpenAI-совместимом API структурированный ответ можно получить двумя способами:
- явно задать JSON-схему ожидаемого ответа;
- описать структуру данных через Pydantic-модель и получить уже распарсенный результат.
Ниже показан один и тот же пример в обоих вариантах. Модель получает текстовое описание небоскрёба и должна вернуть из него два поля: название и высоту.Пример с JSON-схемой:
from openai import OpenAI
import json
YANDEX_CLOUD_FOLDER_ID = "<идентификатор_каталога>"
YANDEX_CLOUD_API_KEY = "<значение_API-ключа>"
YANDEX_CLOUD_MODEL = "aliceai-llm"
client = OpenAI(
api_key=YANDEX_CLOUD_API_KEY,
base_url="https://ai.api.cloud.yandex.net/v1",
project=YANDEX_CLOUD_FOLDER_ID,
)
json_schema = {
"type": "object",
"properties": {
"skyscraper_name": {
"type": "string",
"description": "Название небоскрёба",
},
"skyscraper_height": {
"type": "integer",
"description": "Высота небоскрёба в метрах",
},
},
"required": ["skyscraper_name", "skyscraper_height"],
"additionalProperties": False,
}
response = client.responses.create(
model=f"gpt://{YANDEX_CLOUD_FOLDER_ID}/{YANDEX_CLOUD_MODEL}",
instructions=f"""Ты извлекаешь информацию о небоскрёбах из текста и структурируешь её согласно следующей JSON схеме:
{json.dumps(json_schema, ensure_ascii=False, indent=2)}
Извлеки все данные из текста и верни результат в формате JSON.""",
input="Шанхайская башня — небоскрёб в Китае. Высота — 632 метра. В здании также 127 этажей.",
text={
"format": {
"type": "json_schema",
"name": "skyscraper",
"schema": json_schema,
}
},
)
if response.status == "completed":
# Поиск элемент с типом 'message'
for output_item in response.output:
if output_item.type == "message" and output_item.content:
result = json.loads(output_item.content[0].text)
print(json.dumps(result, ensure_ascii=False, indent=2))
break
else:
print(f"Ошибка: {response.error.message if response.error else 'Неизвестная ошибка'}")
Ответ модели:
{"skyscraper_name": "Шанхайская башня", "skyscraper_height": 632}
💡 При обращении к моделям Yandex AI Studio рекомендуется дублировать JSON-схему в тексте промпта для повышения качества ответов.Пример с заданием структуры через объект Pydantic
from openai import OpenAI
from pydantic import BaseModel
YANDEX_CLOUD_FOLDER_ID = "<идентификатор_каталога>"
YANDEX_CLOUD_API_KEY = "<значение_API-ключа>"
YANDEX_CLOUD_MODEL = "aliceai-llm"
client = OpenAI(
api_key=YANDEX_CLOUD_API_KEY,
base_url="https://ai.api.cloud.yandex.net/v1",
project=YANDEX_CLOUD_FOLDER_ID,
)
class Skyscraper(BaseModel):
skyscraper_name: str
skyscraper_height: int
response = client.responses.parse(
model=f"gpt://{YANDEX_CLOUD_FOLDER_ID}/{YANDEX_CLOUD_MODEL}",
input="Шанхайская башня — небоскрёб в Китае. Высота — 632 метра. В здании также 127 этажей.",
text_format=Skyscraper,
)
skyscraper_data = response.output_parsed
print(f"Название: {skyscraper_data.skyscraper_name}")
print(f"Высота: {skyscraper_data.skyscraper_height} м")
Ответ:
Название: Шанхайская башня
Высота: 632 м
Как выбрать подход
- JSON Schema — подходит, когда схема задаётся извне или формируется динамически;
- Pydantic — удобен при работе на Python, когда требуется сразу получить типизированный объект.
Вызов функций
💡 Function Calling — механизм, позволяющий модели вызывать внешние функции и использовать их результаты при формировании ответа. Это даёт возможность интегрировать модель с API, базами данных и другими системами.Общий процесс выглядит так:1️⃣ Разработчик описывает набор функций, которые модель может вызывать.2️⃣ Когда поступает запрос, модель выбирает, какую функцию из доступного набора вызвать, и передаёт ей необходимые параметры.3️⃣ Внешняя программа (например, агент) выполняет вызов функции с указанными моделью параметрами и возвращает результат выполнения модели.4️⃣ Модель использует полученные данные для генерации итогового ответа пользователю.Пример вызова функции:
from openai import OpenAI
import json
from typing import Optional
YANDEX_CLOUD_FOLDER_ID = "<идентификатор_каталога>"
YANDEX_CLOUD_API_KEY = "<значение_API-ключа>"
YANDEX_CLOUD_MODEL = "aliceai-llm"
client = OpenAI(
api_key=YANDEX_CLOUD_API_KEY,
base_url="https://ai.api.cloud.yandex.net/v1",
project=YANDEX_CLOUD_FOLDER_ID,
)
def calculator(a: int, b: int) -> int:
"""
Складывает два числа.
Args:
a: Первое число
b: Второе число
Returns:
Сумма двух чисел
"""
result = a + b
print(f"[CALC] Выполнение вычисления: {a} + {b} = {result}")
return result
def extract_text_from_response(response) -> Optional[str]:
"""
Извлекает текстовый ответ из response объекта.
Args:
response: Объект ответа от API
Returns:
Текстовый ответ или None
"""
if hasattr(response, 'output_text'):
return response.output_text
for output_item in response.output:
if (hasattr(output_item, 'content') and
output_item.content and
hasattr(output_item.content[0], 'text')):
return output_item.content[0].text
return None
def run_conversation(user_input: str) -> str:
"""
Обрабатывает сообщение пользователя с поддержкой вызова функций.
Args:
user_input: Сообщение пользователя
Returns:
Ответ модели
"""
try:
selected_model = f"gpt://{YANDEX_CLOUD_FOLDER_ID}/{YANDEX_CLOUD_MODEL}"
# Описание инструмента - калькулятора
tools = [
{
"type": "function",
"name": "calculator",
"description": "Сложить два числа",
"parameters": {
"type": "object",
"properties": {
"a": {"type": "integer", "description": "Первое число"},
"b": {"type": "integer", "description": "Второе число"}
},
"required": ["a", "b"],
"additionalProperties": False
}
}
]
# 1. Создание списка ввода и добавление сообщения пользователя
input_list = [
{"role": "user", "content": user_input}
]
print(f"[DEBUG] Пользователь спросил: {user_input}")
# 2. Запрос к модели с определёнными инструментами
response = client.responses.create(
model=selected_model,
tools=tools,
input=input_list,
)
print(f"[DEBUG] Первый ответ модели получен")
# 3. Сохранение вывода модели для последующих запросов
input_list += response.output
# 4. Обработка вызовов функций
for item in response.output:
if item.type == "function_call":
if item.name == "calculator":
# Извлечение аргументов для калькулятора
arguments_str = item.arguments
print(f"[DEBUG] Модель запросила калькулятор с аргументами: {arguments_str}")
# Парсинг аргументы из JSON-строки
function_args = json.loads(arguments_str)
a = function_args.get("a")
b = function_args.get("b")
# 5. Вызов функции калькулятора
calculation_result = calculator(a, b)
# 6. Добавление результата выполнения функции в список ввода
input_list.append({
"type": "function_call_output",
"call_id": item.call_id,
"output": json.dumps({"result": calculation_result}, ensure_ascii=False)
})
print(f"[DEBUG] Результат вычисления передан модели")
# 7. Отправление результата обратно модели
second_response = client.responses.create(
model=selected_model,
tools=tools,
input=input_list,
)
# 8. Извлечение финального текстового ответа
text_response = extract_text_from_response(second_response)
if text_response:
return text_response
# Если вызовов функций не было, возвращается исходный ответ
text_response = extract_text_from_response(response)
if text_response:
return text_response
return "Не удалось получить ответ от модели"
except json.JSONDecodeError as e:
return f"Ошибка парсинга JSON: {e}"
except Exception as e:
return f"Произошла ошибка: {e}"
if __name__ == "__main__":
# Тестирование работы с калькулятором
result = run_conversation("Сколько будет 15 + 25?")
print(f"\nИтоговый ответ:\n{result}")
Пример ответа:
[DEBUG] Пользователь спросил: Сколько будет 15 + 25?
[DEBUG] Первый ответ модели получен
[DEBUG] Модель запросила калькулятор с аргументами: {"a":15,"b":25}
[CALC] Выполняем вычисление: 15 + 25 = 40
[DEBUG] Результат вычисления передан модели
Итоговый ответ:
15 + 25 = 40
Эмбеддинги
💡 Эмбеддинги (векторные представления) — это способ преобразования нечисловых данных (слов, изображений и т. д.) в числовые векторы. Самый частый сценарий применения эмбеддингов — поиск.Рассмотрите пример использования эмбеддингов для поиска. Требуется выполнить следующие шаги:1️⃣ Перевести поисковый запрос и тексты, по которым идёт поиск, в числовые векторы.2️⃣ Измерить сходство между вектором запроса и векторами текстов с помощью косинусной близости.3️⃣ Текст, вектор которого ближе всего к вектору запроса (имеет наибольшую косинусную близость), и будет лучшим ответом.
Изучите пример💡 В примере для работы с эмбеддингами использовались две разные модели:
emb://<идентификатор_каталога>/text-search-doc— ориентирована на векторизацию больших текстов исходных данных.emb://<идентификатор_каталога>/text-search-query— предназначена для векторизации коротких текстов.
Модели
В OpenAI-совместимом API доступен метод для получения списка моделей, открытых пользователю. Это полезно при работе с фреймворками, поддерживающими OpenAI API, а также при автоматическом выборе модели во время выполнения приложения.
from openai import OpenAI
YANDEX_CLOUD_FOLDER_ID = "<идентификатор_каталога>"
YANDEX_CLOUD_API_KEY = "<значение_API-ключа>"
client = OpenAI(
api_key=YANDEX_CLOUD_API_KEY,
base_url="https://ai.api.cloud.yandex.net/v1",
project=YANDEX_CLOUD_FOLDER_ID,
)
models = client.models.list()
print("Доступные модели:\n")
for model in models.data:
print(f"{model.id} ({model.owned_by})")
Ответ API будет отличаться для каждого пользователя, так как список включает общедоступные и пользовательские модели. Например, дообученные или развёрнутые в каталоге пользователя:
Доступные модели:
gpt://b1gmk1eb91166fgctcjj/aliceai-llm/latest (Yandex)
gpt://b1gmk1eb91166fgctcjj/deepseek-v32/latest (DeepSeek)
gpt://b1gmk1eb91166fgctcjj/gpt-oss-120b/latest (OpenAI)
gpt://b1gmk1eb91166fgctcjj/gpt-oss-20b/latest (OpenAI)
gpt://b1gmk1eb91166fgctcjj/gemma-3-27b-it/latest (Google)
gpt://b1gmk1eb91166fgctcjj/qwen3-235b-a22b-fp8/latest (Alibaba)
gpt://b1gmk1eb91166fgctcjj/qwen3.5-35b-a3b-fp8/latest (Alibaba)
gpt://b1gmk1eb91166fgctcjj/speech-realtime-250923/latest (Yandex)
emb://b1gmk1eb91166fgctcjj/text-search-doc/latest (Yandex)
emb://b1gmk1eb91166fgctcjj/text-search-query/latest (Yandex)
...
📚 Актуальный список общедоступных моделей можно посмотреть в документации.
💻 Практика. Преобразование кулинарного рецепта в JSON
❗️Практическая часть курса предполагает использование облачных ресурсов, которые вы оплачиваете самостоятельно. Курс разработан так, чтобы расходы были минимальными, — часть из них покроет стартовый грант.Чтобы избежать лишних трат:— останавливайте ВМ в перерывах между практиками (это не снизит потребление до нуля, но заметно сократит расходы);— настройте бюджет и уведомления в разделе Биллинг;— удаляйте ресурсы после завершения курса;— необязательно выполнять все практики — сосредоточьтесь на релевантных.
ЛогикаПришло время практики! Напишите скрипт для OpenAI SDK, который преобразует текстовое описание рецепта в JSON с использованием моделей AI Studio. В результате вы получите структурированный ответ в удобном формате. 1️⃣ Установите OpenAI SDK через команду.
pip install openai
2️⃣ Задайте базовый эндпоинт и укажите данные для аутентификации ключа или токена в Yandex Cloud. Также укажите ID каталога для обращения к моделям.
from openai import OpenAI
import json
YANDEX_CLOUD_FOLDER_ID = "<идентификатор_каталога>"
YANDEX_CLOUD_API_KEY = "<значение_API-ключа>"
YANDEX_CLOUD_MODEL = "aliceai-llm"
client = OpenAI(
api_key=YANDEX_CLOUD_API_KEY,
base_url="https://ai.api.cloud.yandex.net/v1",
project=YANDEX_CLOUD_FOLDER_ID,
)
3️⃣ Опишите схему для преобразования рецепта из текста в JSON.
json_schema = {
"type": "object",
"properties": {
"recipe_name": {"type": "string"},
"preparation_time": {"type": "string"},
"difficulty_level": {"type": "string", "enum": ["легкая", "средняя", "сложная"]},
"ingredients": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"amount": {"type": "string"}
},
"required": ["name", "amount"]
}
},
"cooking_steps": {
"type": "array",
"items": {"type": "string"}
}
},
"required": ["recipe_name", "preparation_time", "difficulty_level", "ingredients", "cooking_steps"]
}
4️⃣ Опишите рецепт в отдельной переменной.
recipe_description = """
Название: Шоколадный фондан
Ингредиенты:
- 100 г тёмного шоколада
- 100 г сливочного масла
- 2 яйца
- 60 г сахара
- 30 г муки
Время приготовления: 30 минут
Сложность: легкая
Шаги:
1 Растопить шоколад с маслом на водяной бане
2 Взбить яйца с сахаром до пены
3 Соединить шоколадную массу с яичной смесью
4 Добавить муку и перемешать
5 Разлить по формочкам и выпекать 15 минут при 180°C
"""
5️⃣ Выполните запрос.
response = client.responses.create(
model=f"gpt://{YANDEX_CLOUD_FOLDER_ID}/{YANDEX_CLOUD_MODEL}",
instructions=f"""Ты извлекаешь информацию о рецепте из текста и структурируешь её согласно следующей JSON схеме:
{json.dumps(json_schema, ensure_ascii=False, indent=2)}
Извлеки все данные из текста и верни результат в формате JSON.""",
input=recipe_description,
text={
"format": {
"type": "json_schema",
"name": "recipe",
"schema": json_schema,
}
},
)
if response.status == "completed":
# Поиск элемента с типом 'message'
for output_item in response.output:
if output_item.type == "message" and output_item.content:
result = json.loads(output_item.content[0].text)
print(json.dumps(result, ensure_ascii=False, indent=2))
break
else:
print(f"Ошибка: {response.error.message if response.error else 'Неизвестная ошибка'}")
В результате текстовое описание рецепта преобразуется в JSON-формат:
{
"recipe_name": "Шоколадный фондан",
"preparation_time": "30 минут",
"cooking_steps": [
"Растопить шоколад с маслом на водяной бане",
"Взбить яйца с сахаром до пены",
"Соединить шоколадную массу с яичной смесью",
"Добавить муку и перемешать",
"Разлить по формочкам и выпекать 15 минут при 180°C"
],
"difficulty_level": "легкая",
"ingredients": [
{
"name": "тёмный шоколад",
"amount": "100 г"
},
{
"name": "сливочное масло",
"amount": "100 г"
},
{
"name": "яйца",
"amount": "2"
},
{
"name": "сахар",
"amount": "60 г"
},
{
"name": "мука",
"amount": "30 г"
}
]
}
ЛогикаС практикой справились, значит, можно подводить итоги урока!
Итоги урока
AI Studio обеспечивает совместимость с OpenAI SDK, что позволяет быстро интегрировать существующие решения. Хотя совместимость пока не охватывает весь функционал OpenAI API, уже доступных возможностей достаточно для адаптации большинства приложений.📚 Команда AI Studio постоянно расширяет совместимость API. Уже сейчас вы можете переносить решения, а по мере добавления новых функций — легко обновлять их. Актуальный статус совместимости всегда можно проверить в документации.
0 комментариев