Lunos logoLunos

Generasi Gambar (Image Generation)

Perlu dipahami bahwa image understanding dan image generation adalah dua alur yang berbeda:

  • Image Understanding: Menganalisis gambar yang sudah ada menggunakan POST /v1/chat/completions + image_url.
  • Image Generation: Membuat gambar baru menggunakan POST /v1/chat/completions + modalities.

Halaman ini membahas secara khusus alur image generation bergaya OpenRouter melalui Lunos.

Menemukan Model yang Mendukung Image Generation

Pilih model yang memiliki "image" di dalam properti outputModalities.

Melalui API Model (GET /v1/models)

Gunakan parameter filter output secara langsung:

curl -s "https://api.lunos.tech/v1/models?output=image"

Anda juga bisa menggabungkan beberapa filter sekaligus, misalnya untuk mencari model yang mendukung input teks dengan output gambar:

curl -s "https://api.lunos.tech/v1/models?input=text&output=image"

Melalui Dashboard

Buka halaman Daftar Model, lalu cari model yang memiliki kemampuan output gambar.

Cara Menggunakan API

Gunakan endpoint Chat Completions dengan menambahkan parameter modalities:

  • Model yang bisa menghasilkan teks sekaligus gambar: modalities: ["image", "text"]
  • Model khusus gambar saja: modalities: ["image"]

Endpoint:

POST /v1/chat/completions

Contoh Generasi Gambar Dasar

cURL

curl -X POST "https://api.lunos.tech/v1/chat/completions" \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openrouter/google/gemini-2.5-flash-image",
    "messages": [
      {
        "role": "user",
        "content": "Generate a beautiful sunset over mountains"
      }
    ],
    "modalities": ["image", "text"],
    "stream": false
  }'

Python

import requests

payload = {
    "model": "openrouter/google/gemini-2.5-flash-image",
    "messages": [
        {"role": "user", "content": "Generate a beautiful sunset over mountains"}
    ],
    "modalities": ["image", "text"],
    "stream": False,
}
response = requests.post(
    "https://api.lunos.tech/v1/chat/completions",
    headers={
        "Authorization": "Bearer YOUR_SECRET_KEY",
        "Content-Type": "application/json",
    },
    json=payload,
)
result = response.json()
print(result)
const response = await fetch("https://api.lunos.tech/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_SECRET_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "openrouter/google/gemini-2.5-flash-image",
    messages: [{ role: "user", content: "Generate a beautiful sunset over mountains" }],
    modalities: ["image", "text"],
    stream: false,
  }),
});
const result = await response.json();
console.log(result);

Opsi Konfigurasi Gambar

Beberapa model mendukung pengaturan tambahan melalui parameter image_config.

Aspect Ratio (image_config.aspect_ratio)

Nilai yang umum tersedia:

  • 1:1 (default)
  • 2:3, 3:2, 3:4, 4:3, 4:5, 5:4
  • 9:16, 16:9, 21:9

Beberapa model juga mendukung rasio yang lebih ekstrem seperti 1:4, 4:1, 1:8, 8:1.

Ukuran Gambar (image_config.image_size)

Nilai yang umum tersedia:

  • 1K (default)
  • 2K
  • 4K

Beberapa model juga menyediakan opsi 0.5K.

Contoh Penggunaan Gabungan

cURL

curl -X POST "https://api.lunos.tech/v1/chat/completions" \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openrouter/google/gemini-3-pro-image-preview",
    "messages": [
      {
        "role": "user",
        "content": "Create a high-end restaurant scene with a futuristic nano banana dish"
      }
    ],
    "modalities": ["image", "text"],
    "image_config": {
      "aspect_ratio": "16:9",
      "image_size": "4K"
    }
  }'
import requests

payload = {
    "model": "openrouter/google/gemini-3-pro-image-preview",
    "messages": [
        {"role": "user", "content": "Create a high-end restaurant scene with a futuristic nano banana dish"}
    ],
    "modalities": ["image", "text"],
    "image_config": {
        "aspect_ratio": "16:9",
        "image_size": "4K",
    },
}
response = requests.post(
    "https://api.lunos.tech/v1/chat/completions",
    headers={
        "Authorization": "Bearer YOUR_SECRET_KEY",
        "Content-Type": "application/json",
    },
    json=payload,
)
print(response.json())
const response = await fetch("https://api.lunos.tech/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_SECRET_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "openrouter/google/gemini-3-pro-image-preview",
    messages: [
      {
        role: "user",
        content: "Create a high-end restaurant scene with a futuristic nano banana dish",
      },
    ],
    modalities: ["image", "text"],
    image_config: {
      aspect_ratio: "16:9",
      image_size: "4K",
    },
  }),
});
console.log(await response.json());

Opsi Khusus Sourceful

Untuk model dari Sourceful, terdapat beberapa opsi lanjutan tambahan yang mungkin tersedia:

  • image_config.font_inputs — untuk merender teks menggunakan font kustom.
  • image_config.super_resolution_references — untuk meningkatkan kualitas gambar berbasis referensi.

Ketersediaan opsi ini bergantung pada provider dan model, serta mungkin menambah biaya penggunaan.

Streaming Image Generation

Anda dapat menggunakan mode streaming dan membaca chunk data gambar dari properti choices[].delta.images.

cURL

curl -N -X POST "https://api.lunos.tech/v1/chat/completions" \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openrouter/google/gemini-2.5-flash-image",
    "messages": [{"role": "user", "content": "Create an image of a futuristic city"}],
    "modalities": ["image", "text"],
    "stream": true
  }'
import json
import requests

payload = {
    "model": "openrouter/google/gemini-2.5-flash-image",
    "messages": [{"role": "user", "content": "Create an image of a futuristic city"}],
    "modalities": ["image", "text"],
    "stream": True,
}
response = requests.post(
    "https://api.lunos.tech/v1/chat/completions",
    headers={
        "Authorization": "Bearer YOUR_SECRET_KEY",
        "Content-Type": "application/json",
    },
    json=payload,
    stream=True,
)

for line in response.iter_lines():
    if not line:
        continue
    data_line = line.decode("utf-8")
    if not data_line.startswith("data: "):
        continue
    data = data_line[6:]
    if data == "[DONE]":
        break
    try:
        chunk = json.loads(data)
        images = (chunk.get("choices", [{}])[0].get("delta", {}) or {}).get("images", [])
        for image in images:
            print(image.get("image_url", {}).get("url", "")[:50])
    except json.JSONDecodeError:
        pass

TypeScript

const response = await fetch("https://api.lunos.tech/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_SECRET_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "openrouter/google/gemini-2.5-flash-image",
    messages: [{ role: "user", content: "Create an image of a futuristic city" }],
    modalities: ["image", "text"],
    stream: true,
  }),
});

const reader = response.body?.getReader();
const decoder = new TextDecoder();

if (reader) {
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    const chunk = decoder.decode(value);
    for (const line of chunk.split("\n")) {
      if (!line.startsWith("data: ")) continue;
      const data = line.slice(6);
      if (data === "[DONE]") continue;
      try {
        const parsed = JSON.parse(data);
        const images = parsed?.choices?.[0]?.delta?.images ?? [];
        images.forEach((img: any) => console.log(img?.image_url?.url?.slice(0, 50)));
      } catch {}
    }
  }
}

Format Response

Gambar hasil generasi biasanya akan muncul di dalam properti choices[].message.images:

{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "I generated an image for you.",
        "images": [
          {
            "type": "image_url",
            "image_url": {
              "url": "data:image/png;base64,iVBORw0KGgoAAA..."
            }
          }
        ]
      }
    }
  ]
}

Checklist Kompatibilitas Model

  1. Pastikan model memiliki "image" di properti outputModalities.
  2. Parameter modalities sudah diatur dengan benar (["image"] atau ["image", "text"]).
  3. Prompt teks Anda memang secara eksplisit meminta model untuk menghasilkan gambar.

Panduan Penanganan Masalah (Troubleshooting)

Tidak Ada Gambar di dalam Response

  • Pastikan model yang Anda gunakan memang mendukung output gambar.
  • Pastikan parameter modalities sudah disertakan dan diisi dengan benar.
  • Pastikan prompt Anda secara jelas meminta output berupa gambar.

Model Tidak Ditemukan atau Ditolak

  • Periksa kembali ID model menggunakan GET /v1/models.
  • Pastikan model tersebut aktif di lingkungan Lunos Anda.

Kualitas Gambar Kurang Memuaskan atau Biaya Terlalu Tinggi

  • Perjelas dan perdetail prompt teks Anda.
  • Turunkan nilai image_size jika resolusi tinggi tidak diperlukan.
  • Pilih model yang tepat sesuai prioritas Anda (kecepatan vs kualitas).

Checklist Panduan Lunos

  • Manfaatkan filter outputModalities pada GET /v1/models untuk menemukan model yang mampu menghasilkan gambar.
  • Tambahkan validasi prompt dan kontrol penyalahgunaan (abuse control) di sisi backend Anda.
  • Pastikan aplikasi Anda mampu menangani response baik dalam mode sync maupun streaming.
  • Simpan output Base64 dengan aman (atau lakukan konversi dan upload ke CDN untuk akses yang lebih efisien).