Перейти к содержимому
Форматы API

OpenAI Chat Completions

Подключение OpenAI SDK и любых OpenAI-совместимых клиентов к Veda AI Gateway. Потоковая передача, инструменты, структурированный вывод, рассуждения и изображения.

Veda AI Gateway реализует формат OpenAI Chat Completions. Существующий код на OpenAI SDK, AI SDK или любом OpenAI-совместимом клиенте начинает работать с моделями Veda после смены адреса и ключа.

Адрес и аутентификация

ПараметрЗначение
Базовый адрес$VEDA_BASE_URL/v1
МаршрутPOST /v1/chat/completions
АутентификацияAuthorization: Bearer $VEDA_API_KEY

Первый запрос

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.VEDA_API_KEY,
  baseURL: `${process.env.VEDA_BASE_URL}/v1`,
});

const completion = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-5.5",
  messages: [
    { role: "system", content: "Отвечай кратко." },
    { role: "user", content: "Почему небо голубое?" },
  ],
});

console.log(completion.choices[0].message.content);

Ответ приходит в стандартном формате: текст в choices[0].message.content, причина остановки в choices[0].finish_reason, расход токенов в usage.

Потоковая передача

С "stream": true ответ приходит частями по Server-Sent Events. Каждое событие содержит объект chat.completion.chunk с фрагментом текста в choices[0].delta.content, поток заканчивается строкой data: [DONE].

const stream = await client.chat.completions.create({
  model: "openai/gpt-6.1-sol",
  messages: [{ role: "user", content: "Напиши короткое стихотворение о море." }],
  stream: true,
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}

Если клиент закрывает соединение, Veda прекращает чтение ответа модели.

Вызов инструментов

Опишите функции в tools. Если модель решит вызвать функцию, ответ придёт с finish_reason: "tool_calls" и списком message.tool_calls. Выполните функцию у себя и отправьте результат сообщением с ролью tool и тем же tool_call_id.

const tools = [
  {
    type: "function" as const,
    function: {
      name: "getWeather",
      description: "Текущая погода в городе",
      parameters: {
        type: "object",
        properties: { location: { type: "string", description: "Город и страна" } },
        required: ["location"],
      },
    },
  },
];

const messages: OpenAI.ChatCompletionMessageParam[] = [
  { role: "user", content: "Какая погода в Казани?" },
];

const first = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-5.5",
  messages,
  tools,
});

const assistant = first.choices[0].message;
messages.push(assistant);

for (const call of assistant.tool_calls ?? []) {
  if (call.type !== "function") continue;
  const { location } = JSON.parse(call.function.arguments);
  const result = { location, temperatureC: 18 }; // здесь ваш код
  messages.push({ role: "tool", tool_call_id: call.id, content: JSON.stringify(result) });
}

const second = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-5.5",
  messages,
  tools,
});

console.log(second.choices[0].message.content);

tool_choice управляет выбором: "auto" (по умолчанию), "none", "required" или конкретная функция. Вызов инструментов работает, если модель его поддерживает; это указано на её странице в каталоге.

Структурированный вывод

Чтобы получить JSON по схеме, передайте response_format с типом json_schema. Вариант { "type": "json_object" } просит любой корректный JSON без схемы.

const completion = await client.chat.completions.create({
  model: "openai/gpt-6.1-sol",
  messages: [{ role: "user", content: "Извлеки данные: Анна, 34 года, Новосибирск." }],
  response_format: {
    type: "json_schema",
    json_schema: {
      name: "person",
      strict: true,
      schema: {
        type: "object",
        properties: {
          name: { type: "string" },
          age: { type: "integer" },
          city: { type: "string" },
        },
        required: ["name", "age", "city"],
        additionalProperties: false,
      },
    },
  },
});

const person = JSON.parse(completion.choices[0].message.content ?? "{}");

Структурированный вывод работает, если модель поддерживает response_format. Проверяйте результат на своей модели перед тем, как полагаться на строгое соответствие схеме.

Рассуждения

Для моделей с рассуждениями глубина задаётся объектом reasoning. Используйте одно из полей:

ПолеПримерНазначение
effort{ "effort": "high" }Уровень усилий, если модель поддерживает уровни
max_tokens{ "max_tokens": 2048 }Бюджет токенов на рассуждение
enabled{ "enabled": true }Включить рассуждение с настройками модели
curl "$VEDA_BASE_URL/v1/chat/completions" \
  -H "Authorization: Bearer $VEDA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-6.1-sol",
    "messages": [{ "role": "user", "content": "Объясни парадокс Монти Холла по шагам." }],
    "reasoning": { "effort": "high" }
  }'

Какие уровни поддерживает модель, видно на её странице в каталоге: там приведён готовый пример запроса.

Изображения на входе

Моделям, которые принимают изображения, передайте content массивом частей: текст и image_url. Адрес может быть публичным URL или data URL с base64.

const completion = await client.chat.completions.create({
  model: "google/gemini-3.8-flash",
  messages: [
    {
      role: "user",
      content: [
        { type: "text", text: "Опиши это изображение." },
        { type: "image_url", image_url: { url: "https://example.com/photo.jpg" } },
      ],
    },
  ],
});

В журнале запросов встроенные данные (base64 и длинные data URL) заменяются пометкой с размером, само изображение не сохраняется.

Параметры

Veda передаёт тело запроса модели без изменений. Ниже основные параметры формата; поддержку необязательных параметров определяет модель.

ПараметрТипОписание
modelstringОбязательный. Идентификатор модели, например openai/gpt-6.1-sol
messagesarrayОбязательный. Сообщения с ролями system, user, assistant, tool
streambooleanПотоковая передача. По умолчанию false
max_tokens, max_completion_tokensintegerОграничение длины ответа
temperaturenumberСлучайность ответа
top_pnumberЯдерная выборка
stopstring или arrayПоследовательности остановки
seedintegerЗерно для воспроизводимости, если модель его учитывает
tools, tool_choice, parallel_tool_callsarray, string или object, booleanВызов инструментов
response_formatobjectСтруктурированный вывод
reasoningobjectНастройки рассуждений

Ошибки

Ошибки проверки ключа и лимитов приходят в формате { "error": { "code": ..., "message": ... } }:

{ "error": { "code": 429, "message": "Rate limit exceeded" } }
КодКогда
401Ключ неверен, отключён, удалён или истёк
402Достигнут лимит расходов ключа
429Больше 60 запросов в минуту на один ключ

Полный список кодов приведён в обзоре API. OpenAI SDK выбрасывает для них исключения AuthenticationError, RateLimitError и другие подклассы APIError.

Атрибуция приложения

Чтобы разделять статистику нескольких приложений, передавайте заголовки X-Veda-App-*. В OpenAI SDK это делается через defaultHeaders:

const client = new OpenAI({
  apiKey: process.env.VEDA_API_KEY,
  baseURL: `${process.env.VEDA_BASE_URL}/v1`,
  defaultHeaders: { "X-Veda-App-Id": "my-assistant", "X-Veda-App-Name": "My Assistant" },
});

Подробнее: Статистика приложений.

На этой странице