Интеграции

AI-модели в Go через AI Gateway — официальный SDK openai-go

github.com/openai/openai-go

AI Gateway совместим с официальным SDK openai-go: весь код — как в документации OpenAI, задаются только базовый URL и ключ через option. Один клиент даёт доступ ко всем моделям каталога — Claude, GPT, Gemini, DeepSeek — сменой параметра модели.

Установка

go get github.com/openai/openai-go

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

package main

import (
	"context"
	"fmt"

	"github.com/openai/openai-go"
	"github.com/openai/openai-go/option"
)

func main() {
	client := openai.NewClient(
		option.WithBaseURL("https://ai-gatewey.ru/v1"),
		option.WithAPIKey("sk-aigate-ваш_ключ"),
	)

	resp, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
		Model: openai.F("deepseek/deepseek-chat"),
		Messages: openai.F([]openai.ChatCompletionMessageParamUnion{
			openai.UserMessage("Привет!"),
		}),
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(resp.Choices[0].Message.Content)
}
Ключ храните в переменной окружения (например, os.Getenv("AIGATE_API_KEY")), а не в коде — так его не утащат из репозитория. option.WithAPIKey принимает любое строковое значение.

Стриминг

Ответ частями через Server-Sent Events — метод NewStreaming возвращает поток ssestream, который перебирают в цикле по Next():

stream := client.Chat.Completions.NewStreaming(context.Background(), openai.ChatCompletionNewParams{
	Model: openai.F("deepseek/deepseek-chat"),
	Messages: openai.F([]openai.ChatCompletionMessageParamUnion{
		openai.UserMessage("Расскажи о токенах"),
	}),
})

for stream.Next() {
	chunk := stream.Current()
	if len(chunk.Choices) > 0 {
		fmt.Print(chunk.Choices[0].Delta.Content)
	}
}
if err := stream.Err(); err != nil {
	panic(err)
}

Function calling

Вызов инструментов работает прозрачно — выбирайте модель с поддержкой function calling (бейдж «инструменты» в каталоге). Инструменты описываются через openai.ChatCompletionToolParam, а модель возвращает ToolCalls:

resp, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
	Model: openai.F("anthropic/claude-sonnet-5"),
	Messages: openai.F([]openai.ChatCompletionMessageParamUnion{
		openai.UserMessage("Какая погода в Москве?"),
	}),
	Tools: openai.F([]openai.ChatCompletionToolParam{{
		Type: openai.F(openai.ChatCompletionToolTypeFunction),
		Function: openai.F(openai.FunctionDefinitionParam{
			Name:        openai.F("get_weather"),
			Description: openai.F("Погода в городе"),
			Parameters: openai.F(openai.FunctionParameters{
				"type": "object",
				"properties": map[string]any{
					"city": map[string]string{"type": "string"},
				},
				"required": []string{"city"},
			}),
		}),
	}}),
})
if err != nil {
	panic(err)
}
fmt.Println(resp.Choices[0].Message.ToolCalls)

Обработка ошибок

  • 401 — неверный или отозванный ключ: проверьте значение и что ключ активен в кабинете.
  • 403 — модель сверх тарифа при пустом балансе: пополните баланс или выберите модель тарифа.
  • 429 — исчерпана квота или RPM-лимит ключа: дождитесь окна, поднимите лимит или тариф.
  • 5xx — сбой апстрима: шлюз сам ретраит и переключает провайдера, но свой retry с экспоненциальной паузой в проде не помешает.
import (
	"errors"

	"github.com/openai/openai-go"
)

_, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
	Model: openai.F("deepseek/deepseek-chat"),
	Messages: openai.F([]openai.ChatCompletionMessageParamUnion{
		openai.UserMessage("Привет!"),
	}),
})

var apiErr *openai.Error
if errors.As(err, &apiErr) {
	// apiErr.StatusCode == 429 → квота/RPM: подождать и повторить
	fmt.Println(apiErr.StatusCode, apiErr.Message)
}

Какую модель выбрать

МодельВвод, ₽/1МВывод, ₽/1МКонтекст
DeepSeek: DeepSeek V331125128K
Anthropic: Claude Sonnet 53141 5681M
OpenAI: GPT-5.4 Mini118705400K
Актуальные цены каталога AI Gateway за 1 млн токенов. Все модели →

Частые вопросы

Какой SDK для Go выбрать?

Официальный github.com/openai/openai-go — он поддерживается OpenAI и совместим с AI Gateway через option.WithBaseURL. Сторонние клиенты вроде go-openai тоже работают, если умеют менять базовый URL.

Как задать таймаут и повторы?

Через option.WithRequestTimeout и option.WithMaxRetries при создании клиента, либо контекстом context.WithTimeout на конкретный запрос.

Можно ли переключать модели без нового клиента?

Да — клиент создаётся один раз, а модель задаётся в каждом запросе полем Model, поэтому один клиент работает со всеми моделями каталога.

Go-сервис с AI — за пять минут

Получить ключ