Vercel AI SDK
Подключите Vercel AI SDK к Mixen — оплата с баланса в рублях, каталог из 105+ моделей через пакет @ai-sdk/openai.
Установка
Заголовок раздела «Установка»npm install ai @ai-sdk/openaiДля интерфейсных хуков (useChat) дополнительно:
npm install @ai-sdk/reactКонфигурация
Заголовок раздела «Конфигурация»Создайте провайдера с нашим base URL и ключом:
import { createOpenAI } from '@ai-sdk/openai'import { generateText } from 'ai'
const mixen = createOpenAI({ baseURL: 'https://api.mixen.ai/v1', apiKey: process.env.MIXEN_API_KEY,})
const { text } = await generateText({ model: mixen('openai/gpt-5.6-sol'), prompt: 'Придумай слоган для сервиса доставки книг',})Стриминг:
import { streamText } from 'ai'
const result = streamText({ model: mixen('z-ai/glm-5.3'), prompt: 'Напиши короткий пост для блога о кофе',})
for await (const chunk of result.textStream) { process.stdout.write(chunk)}Ключевые моменты:
- Провайдер — это функция:
mixen('<ID модели>')возвращает модель дляgenerateText,streamTextи остальных вызовов AI SDK. - Опции называются именно
baseURLиapiKey. Без них провайдер уйдёт на дефолтhttps://api.openai.com/v1(или на переменныеOPENAI_BASE_URL/OPENAI_API_KEY). - Ключ
mxn-…выпускается в кабинете;process.envчитается при старте процесса — после правки.envперезапустите dev-сервер.
Сценарий: чат-интерфейс со стримингом
Заголовок раздела «Сценарий: чат-интерфейс со стримингом»Типовая связка: серверный роут стримит ответ модели, клиент на useChat рисует его по мере поступления токенов.
Сервер — app/api/chat/route.ts в Next.js:
import { createOpenAI } from '@ai-sdk/openai'import { streamText, convertToModelMessages, createUIMessageStreamResponse, toUIMessageStream, type UIMessage,} from 'ai'
const mixen = createOpenAI({ baseURL: 'https://api.mixen.ai/v1', apiKey: process.env.MIXEN_API_KEY,})
export async function POST(req: Request) { const { messages }: { messages: UIMessage[] } = await req.json()
const result = streamText({ model: mixen('z-ai/glm-5.3'), system: 'Ты — консультант книжного магазина. Отвечай коротко и по делу.', messages: await convertToModelMessages(messages), })
return createUIMessageStreamResponse({ stream: toUIMessageStream({ stream: result.stream }), })}Клиент — компонент чата:
'use client'
import { useChat } from '@ai-sdk/react'import { DefaultChatTransport } from 'ai'import { useState } from 'react'
export default function Chat() { const [input, setInput] = useState('') const { messages, sendMessage } = useChat({ transport: new DefaultChatTransport({ api: '/api/chat' }), })
return ( <div> <input value={input} onChange={(e) => setInput(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') { sendMessage({ parts: [{ type: 'text', text: input }] }) setInput('') } }} /> {messages.map((message) => ( <div key={message.id}> {message.parts.map((part, i) => part.type === 'text' ? <p key={i}>{part.text}</p> : null, )} </div> ))} </div> )}Что здесь происходит:
- Клиент шлёт массив UIMessage на
/api/chat;convertToModelMessagesпревращает их в сообщения модели. streamTextвозвращает поток,toUIMessageStream+createUIMessageStreamResponseупаковывают его в протокол UI-стрима —useChatчитает его из коробки.systemвstreamTextзадаёт системную инструкцию — держите её постоянной, стабильный префикс попадает в промпт-кэш.- Стриминг настоящий: дельты приходят из модели по мере генерации, интерфейс печатает ответ сразу, не дождавшись его конца.
Выбор модели и экономика
Заголовок раздела «Выбор модели и экономика»| Задача | Модель | Цена за 1M токенов |
|---|---|---|
| Массовые вызовы: черновики, подсказки, классификация | z-ai/glm-5.3-flash |
8.4 ₽ вход / 27.9 ₽ выход |
| Сложные задачи, длинный контекст, аккуратный код | anthropic/claude-sonnet-5 |
213.9 / 1069.5 ₽ |
Диалоговый чат — идеальный кандидат на промпт-кэш: каждый ход повторяет системную инструкцию и историю, и повторяющийся префикс считается по ~10% цены входа (у claude-sonnet-5 — 21.4 ₽ за 1M вместо 213.9 ₽, у glm-5.3-flash — 1.7 ₽). Окно кэша — 5 минут с продлением от каждого попадания, так что живой диалог дешевле, чем те же вопросы по одному. Практика: системный промпт в system не пересобирать, переменные данные — в сообщения.
Глубина рассуждения задаётся reasoning_effort API (значения off, low, medium, high, xhigh, max; поддерживаемые уровни — в GET /v1/models → capabilities.reasoning_efforts). Учитывайте, что рассуждение расходует лимит ответа: под длинный вывод задавайте maxOutputTokens с запасом.
Рекомендуемые модели
Заголовок раздела «Рекомендуемые модели»| Модель | ID |
|---|---|
| GPT-5.6 Sol | openai/gpt-5.6-sol |
| Claude Opus 5 | anthropic/claude-opus-5 |
| GLM 5.3 | z-ai/glm-5.3 |
| DeepSeek V4 Pro | deepseek/deepseek-v4-pro |
| Kimi K3 | moonshotai/kimi-k3 |
Актуальный список — в каталоге.
Типичные проблемы
Заголовок раздела «Типичные проблемы»- 401 / Invalid API Key — переменная
MIXEN_API_KEYне задана в окружении процесса или ключ скопирован не целиком; после правки.envперезапустите приложение. - Запросы уходят на api.openai.com — опечатка в имени опции:
baseUrlвместоbaseURLв JavaScript молча игнорируется, и провайдер использует дефолтный адрес (TypeScript подсветит ошибку). - «model not found» — ID модели передавайте посимвольно из каталога, включая префикс вендора (
openai/…,anthropic/…). - useChat молчит, ответ не появляется — проверьте, что роут возвращает
createUIMessageStreamResponseиapiвDefaultChatTransportуказывает на него;useChatничего не знает о провайдере — он общается только с вашим роутом. - Роут возвращает текст, но не стримит — убедитесь, что возвращается стрим-ответ, а не
result.text: ожидание этого свойства отдаёт ответ целиком, уже без потока.