Trang này chưa được dịch sang Tiếng Việt. Đang hiển thị bản gốc tiếng Anh.

Vercel AI SDK

Connecting through `@ai-sdk/openai-compatible`

The Vercel AI SDK ships a dedicated provider for OpenAI-compatible endpoints. Our gateway implements that shape, so @ai-sdk/openai-compatible is the cleanest way in.

bash
npm install ai @ai-sdk/openai-compatible zod
export MYIP_API_KEY="sk-mo-v1-..."

Setting up the provider

Create the provider once — say in lib/myip.ts — and reuse it across the app.

typescript
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';

export const myip = createOpenAICompatible({
  name: 'myip-openrouter',
  baseURL: 'https://openrouter.myip.co.kr/api/v1',
  apiKey: process.env.MYIP_API_KEY,
  headers: {
    // Optional; used to break usage down per app (/docs/app-attribution).
    'HTTP-Referer': 'https://example.com',
    'X-Title': 'My Example App',
  },
});

One-shot — generateText

typescript
import { generateText } from 'ai';
import { myip } from '@/lib/myip';

const result = await generateText({
  model: myip('google/gemma-4-26b-a4b'),
  system: 'You are a concise assistant.',
  prompt: 'What is the capital of South Korea?',
  temperature: 0.7,
});

console.log(result.text);
console.log(result.usage);

Streaming — streamText

typescript
import { streamText } from 'ai';
import { myip } from '@/lib/myip';

const result = streamText({
  model: myip('lgai/exaone-4.0-32b'),
  prompt: 'Write a short poem.',
});

for await (const chunk of result.textStream) {
  process.stdout.write(chunk);
}

console.log('\n', await result.usage);

You do not need to set stream_options.include_usage; we always request usage from the upstream, so the usage promise resolves once the stream ends.

Next.js route handler

Drop this at app/api/chat/route.ts and the front-end useChat hook connects directly.

typescript
import { streamText, convertToModelMessages, type UIMessage } from 'ai';
import { myip } from '@/lib/myip';

export const runtime = 'nodejs';
export const maxDuration = 60;

export async function POST(req: Request) {
  const { messages }: { messages: UIMessage[] } = await req.json();

  const result = streamText({
    model: myip('google/gemma-4-26b-a4b'),
    messages: convertToModelMessages(messages),
  });

  return result.toUIMessageStreamResponse();
}

Getting the cost

The AI SDK standardises token counts but leaves cost to the provider. We expose it two ways.

1. Response headers (non-streaming)

typescript
const result = await generateText({
  model: myip('google/gemma-4-26b-a4b'),
  prompt: 'Hello',
});

const headers = result.response.headers ?? {};
console.log(headers['x-myip-cost-krw'], headers['x-myip-currency']);
console.log(headers['x-myip-generation-id']);

2. Generation lookup (works for streaming too)

Take the id from X-MyIP-Generation-Id and query it once settlement is done.

typescript
async function costKrw(generationId: string): Promise<number> {
  const res = await fetch(
    `https://openrouter.myip.co.kr/api/v1/generation?id=${generationId}`,
    { headers: { Authorization: `Bearer ${process.env.MYIP_API_KEY}` } },
  );
  const body = await res.json();
  return body.data.total_cost; // KRW
}

total_cost matches the amount written to the credit ledger exactly. The arithmetic is in How costs are calculated.

Tool calling

typescript
import { generateText, tool } from 'ai';
import { z } from 'zod';
import { myip } from '@/lib/myip';

const result = await generateText({
  model: myip('google/gemma-4-26b-a4b'),
  prompt: 'What is the weather in Seoul?',
  tools: {
    weather: tool({
      description: 'Look up the current weather for a city',
      inputSchema: z.object({ city: z.string() }),
      execute: async ({ city }) => ({ city, tempC: 21 }),
    }),
  },
});

console.log(result.text);

Tool support varies by model. Check that supported_parameters in the GET /api/v1/models response contains tools. See Tool calling.

Model fallbacks

The models array is our extension rather than a standard AI SDK option, so pass it through provider options.

typescript
const result = await generateText({
  model: myip('lgai/exaone-4.0-32b'),
  prompt: 'Hello',
  providerOptions: {
    'myip-openrouter': {
      models: ['lgai/exaone-4.0-32b', 'google/gemma-4-26b-a4b'],
    },
  },
});

The key must match the name you gave createOpenAICompatible. See Model fallbacks.

What you cannot use

  • embed, embedMany — there is no embeddings endpoint
  • generateImage, transcribe, generateSpeech — there are no image or audio endpoints

Calling them returns 404 not_supported; see Unsupported endpoints.

We also do not implement the Responses API, so use @ai-sdk/openai-compatible, or explicitly select the Chat Completions path if you use @ai-sdk/openai.

Cập nhật lần cuối 5 thg 9, 2026