본문으로 건너뛰기

Gemini (Google AI)

Google Gemini CLI와 Google AI SDK(@google/genai)가 그대로 연결되는 Gemini native 호환 엔드포인트.

POST/v1beta/models/{model}:generateContent
POST/v1beta/models/{model}:streamGenerateContent
POST/v1beta/models/{model}:countTokens
GET/v1beta/models

PleumRouter는 Gemini native 포맷(generateContent / streamGenerateContent)을 그대로 노출합니다. Gemini CLI와 Google AI SDK에 고정된 도구는 OpenAI 호환 base URL로는 붙을 수 없기 때문에, 이 인바운드 경로가 필요합니다. 라우팅·과금·스트리밍은 다른 엔드포인트와 같고, 응답은 Gemini 포맷(candidates[] / usageMetadata)으로 반환됩니다.

연결하기#

Google AI SDK에서 baseUrl(Python은 HttpOptions(base_url=...))를 루트 https://apirouter.pleum.ai로 설정하세요. SDK가 /v1beta/models/{model}:generateContent를 붙입니다.

Google Gen AI SDK (Python)
import os

from google import genai

client = genai.Client(
    api_key=os.environ["PLEUM_API_KEY"],
    http_options=genai.types.HttpOptions(base_url="https://apirouter.pleum.ai"),
)

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="Hello",
)
print(response.text)
Google Gen AI SDK (TypeScript)
import { GoogleGenAI } from "@google/genai";

const client = new GoogleGenAI({
  apiKey: process.env.PLEUM_API_KEY,
  httpOptions: { baseUrl: "https://apirouter.pleum.ai" },
});

const response = await client.models.generateContent({
  model: "gemini-3.8-flash",
  contents: "Hello",
});

console.log(response.text);

Gemini CLI는 GOOGLE_GEMINI_BASE_URL을 루트로, plm_ 키를 GEMINI_API_KEY로 설정하세요.

Gemini CLI
export PLEUM_API_KEY=plm_xxxxxxxxxxxxxxxx
export GEMINI_API_KEY="$PLEUM_API_KEY"
export GOOGLE_GEMINI_BASE_URL="https://apirouter.pleum.ai"
gemini
base URL에 /v1beta를 붙이지 마세요. SDK가 다시 /v1beta/...를 붙여 경로가 중복되어 요청이 실패합니다. 반드시 루트 https://apirouter.pleum.ai만 지정하세요.

인증은 plm_ API 키를 Gemini 표준 헤더 x-goog-api-key 또는 쿼리 ?key=로 전달합니다. Authorization: Bearer 헤더도 함께 받습니다.

콘텐츠 생성#

파라미터타입필수설명
contentsarray필수{role, parts} 배열. role은 user·model. parts는 text·inline_data 블록 배열입니다.
systemInstructionobject | string선택시스템 프롬프트. parts의 text만 추출해 system 메시지로 변환합니다.
generationConfigobject선택camelCase와 snake_case 모두 수용. temperature·maxOutputTokens·topP·stopSequences 등.
toolsarray선택Gemini 형식의 함수 선언(functionDeclarations). 양방향 변환됩니다.
toolConfigobject선택함수 호출 모드(functionCallingConfig).
safetySettingsarray선택받지만 upstream으로 전달되지는 않습니다.
contentsobject[]필수
rolestring선택
partsobject[]선택
textstring선택
inline_dataobject선택

Image input. Works only with models whose input_modalities include image.

file_dataobject선택
functionCallobject선택
functionResponseobject선택
systemInstructionobject | string선택
generationConfigobject선택
toolsobject[]선택
toolConfigobject선택
safetySettingsobject[]선택
request
curl https://apirouter.pleum.ai/v1beta/models/gemini-3.8-flash:generateContent \
  -H "x-goog-api-key: $PLEUM_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "systemInstruction": {"parts": [{"text": "You are a helpful assistant."}]},
    "contents": [{"role": "user", "parts": [{"text": "Hello"}]}],
    "generationConfig": {"temperature": 0.7, "maxOutputTokens": 1024}
  }'

응답은 Gemini 스키마를 따릅니다. candidates[].content.parts에 텍스트가 들어가고, 토큰 사용량은 usageMetadata.promptTokenCount / candidatesTokenCount / totalTokenCount로 반환됩니다. 이미지 입력은 inline_data(base64)로 보낼 수 있으며, input_modalities에 image가 있는 모델에서만 쓸 수 있습니다(비전 참고).

200 OK
{
  "candidates": [
    {
      "content": {
        "parts": [{"text": "Hello! How can I help you?"}],
        "role": "model"
      },
      "finishReason": "STOP",
      "index": 0
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 5,
    "candidatesTokenCount": 7,
    "totalTokenCount": 12
  }
}

스트리밍#

:streamGenerateContent는 ?alt=sse 쿼리로 SSE 포맷을 사용합니다. 각 data: 라인은 GenerateContentResponse 형태의 JSON 청크이며 [DONE] 마커는 없습니다.

stream
curl "https://apirouter.pleum.ai/v1beta/models/gemini-3.8-flash:streamGenerateContent?alt=sse" \
  -H "x-goog-api-key: $PLEUM_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "contents": [{"role": "user", "parts": [{"text": "Hello"}]}]
  }'

# Each SSE data: line is a GenerateContentResponse JSON chunk (no [DONE] marker).
# data: {"candidates":[{"content":{"parts":[{"text":"Hello"}],"role":"model"},"index":0}]}
# data: {"candidates":[{"content":{"parts":[{"text":"! How can I help you?"}],"role":"model"},"index":0}]}
# data: {"candidates":[{"content":null,"finishReason":"STOP","index":0}],"usageMetadata":{"promptTokenCount":5,"candidatesTokenCount":7,"totalTokenCount":12}}

토큰 수 세기#

:countTokens는 generateContent와 같은 본문을 받아 {"totalTokens": <int>}를 반환합니다. 휴리스틱 추정값이며 실제 토크나이저 결과는 아닙니다.

count tokens
curl https://apirouter.pleum.ai/v1beta/models/gemini-3.8-flash:countTokens \
  -H "x-goog-api-key: $PLEUM_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "contents": [{"role": "user", "parts": [{"text": "Hello"}]}]
  }'

# -> {"totalTokens": 5}

모델 목록#

GET /v1beta/models는 Gemini 포맷의 모델 목록을 반환합니다. 같은 공개 가시성 규칙을 GET /v1/models와 공유합니다.

list models
curl https://apirouter.pleum.ai/v1beta/models \
  -H "x-goog-api-key: $PLEUM_API_KEY"

# -> {"models": [{"name": "models/gemini-3.8-flash", "supportedGenerationMethods": [...]}, ...]}
비용은 Gemini 바디를 깨뜨리지 않도록 응답 헤더 X-Cost-Krw(0.1 단위 소수)·X-Cost-Usd(소수)로 노출됩니다(Anthropic 엔드포인트와 동일 패턴). 스트리밍은 종료 시점에야 비용이 확정되므로 헤더가 생략됩니다.