DeepSeek Vision and Grok Imagine models are now live on CometAPI →
guide/CometAPI araştırması

Next.js ve CometAPI ile çok modelli yapay zeka sohbet uygulaması nasıl geliştirilir

Tek bir CometAPI anahtarı ve arka uç uç noktası aracılığıyla GPT, Claude ve Gemini modelleri arasında geçiş yapabilen akış destekli bir Next.js yapay zekâ sohbet uygulaması geliştirin.

CometAPI
AnnaAI model ve API araştırma ekibi
Güncellendi Aug 25, 2026 12 dk okuma
Next.js ve CometAPI ile çok modelli yapay zeka sohbet uygulaması nasıl geliştirilir
Bu kalıbı kullanın

İlk API çağrısını yapın.

from openai import OpenAI

client = OpenAI(
    api_key="YOUR_COMETAPI_KEY",
    base_url="https://api.cometapi.com/v1",
)

response = client.chat.completions.create(
    model="gpt-5-mini",
    messages=[{"role": "user", "content": "Build this workflow."}],
)

print(response.choices[0].message.content)

Birden çok model sağlayıcısına ihtiyaç duyan bir Next.js sohbet botu için, kimlik doğrulamayı merkezileştirirken uygulamanın her istekte bir modeli seçmesine izin veren bir arka uç en kullanışlı olandır. CometAPI bu modeli sağlar: sunucu tek bir API anahtarını ve OpenAI uyumlu temel URL’yi https://api.cometapi.com/v1 saklarken, isteğin model alanı kullanılabilir GPT, Claude, Gemini veya diğer sohbet modellerinden birini seçer.

Bu eğitim; sunucu tarafı model izin listesi, akışlı bir Route Handler, tarayıcıda model seçici, korumalı ortam değişkenleri, eksiksiz bir sohbet arayüzü ve dağıtım rehberiyle çalışan bir App Router projesi oluşturur. CometAPI anahtarı asla tarayıcıya ulaşmaz.

Çok Modelli Yapay Zeka Sohbet Uygulaması Nedir?

Çok modelli yapay zeka sohbet mimarisi, kullanıcı arayüzü ile birkaç model sağlayıcı arasında uygulama tarafından kontrol edilen tek bir arka uç katmanı konumlandırır. Bu projede tarayıcı konuşmayı /api/chat adresine gönderir; sunucu CometAPI kimlik bilgisini gizli tutar, istenen model kimliğini doğrular ve isteği uyumlu tek bir API üzerinden iletir.

Next.js’te Model Değiştirme Nasıl Çalışır?

Modelleri değiştirmek bir yönlendirme (routing) kararıdır. Tarayıcı, konuşmayla birlikte onaylanmış bir model kimliğini /api/chat adresine gönderir. Route Handler, CometAPI kimlik bilgisini ekler, POST /v1/chat/completions çağrısını yapar ve seçilen modelin yanıtını akış halinde tarayıcıya iletir.

Paylaşılan uç nokta tüm modelleri aynı yapmaz. Çıktı stili, araç davranışı, desteklenen parametreler, bağlam sınırları ve fiyatlandırma farklı olabilir. Model kimliklerini sunucu tarafındaki bir izin listesinde tutun ve kullanıcıya açmadan önce her yolu aynı uygulama istemleriyle test edin.

Neler Oluşturacaksınız

Tamamlanmış uygulama tek bir Next.js arka ucuna ve üç seçilebilir sohbet rotasına sahiptir:

Model IDÖrnek rolCometAPI fiyatı
gemini-3.7-flashMaliyet duyarlı, yüksek hacimli sohbet$0.60 input / $3.00 output
claude-opus-5Odaklı premium akıl yürütme$4 input / $20 output
gpt-5.6gpt-5.6, GPT-5.6 için genel CometAPI rotasıdır ve şu anda Sol tier ile eşlenir.$3.2 input / $16 output (kısa-bağlam katmanında)

Fiyatlandırma notu: Aşağıda gösterilen fiyatlar USD cinsinden milyon token başına olup 21 Ağustos 2026 tarihinde kontrol edilmiştir ve değişebilir. Üretim kullanımı öncesinde model sayfalarındaki güncel oranları her zaman doğrulayın. Tablo bir yönlendirme örneğidir, kalite sıralaması değildir. GPT-5.6, 272.000 token üstünde daha yüksek bir fiyat katmanına geçer. Burada kullanılan tarihlenmiş oranlar için bağlantılı Gemini 3.7 Flash, Claude Opus 5 ve GPT-5.6 model sayfalarına bakın.

CometAPI, modelleri sağlayıcıların resmi API’lerine göre şeffaf biçimde fiyatlandırır. Resmi fiyatlandırması birleşik olan modeller — OpenAI, Claude, Gemini ve benzerleri — resmi fiyata 0.8:1 oranla, yani %20 indirimle token bazında faturalandırılır; resmi API’si olmayan modeller (MidJourney, Kling, Luma) ise CometAPI’nin belirlediği oranlarla çağrı başına faturalandırılır, yine %20 indirimlidir. Model başına oranlar, faturalama birimleri ve fiyatlandırma formülü için CometAPI Fiyatlandırma Kılavuzu’na bakın.

Üç rota farklı ödünleşimleri kapsar. Gemini 3.7 Flash, Google’ın verimli ajans modellerinden olup çoklu ortam girişi ve yüksek hacimli sohbet, kodlama ve bilgi iş akışları için 1.048.576 tokenlık bir bağlam penceresi sunar. Claude Opus 5, Anthropic’in sınırdaki akıl yürütme modeli olup çok adımlı analiz, kod ve dikkatli uzun metin yazımında güçlüdür ve premium fiyatlandırmaya sahiptir. GPT-5.6, OpenAI’nin genel amaçlı modeli olup geniş bir bağlam penceresinde günlük üretim trafiği için akıl yürütme, araç kullanımı ve taslak yazımı arasında denge sağlar.

Başlamadan Önce

Node.js, npm, bir CometAPI hesabı ve CometAPI Quick Start üzerinden alınmış sunucu tarafı bir API anahtarına ihtiyacınız var. Yukarıdaki üç kesin model kimliği 21 Ağustos 2026 itibarıyla canlı katalogda mevcuttu, “yakında” olarak işaretli değildi ve POST /v1/chat/completions uç noktasını sunuyordu.

Eğitim şu ortak ayarları kullanır:

Adım 1: Next.js Uygulamasını Oluşturun

npx create-next-app@latest multi-model-chat --ts --app --eslintcd multi-model-chatnpm run dev

Bu sürüm için bir model sağlayıcı SDK’sı gerekmez. Sunucu yerleşik fetch API’sini kullanır ve yukarı akıştaki Server-Sent Events akışını iletir.

Adım 2: CometAPI Anahtarını Sunucuda Tutun

Proje kökünde .env.local oluşturun:

COMETAPI_API_KEY=replace_with_your_cometapi_keyCOMETAPI_BASE_URL=https://api.cometapi.com/v1

Anahtarı NEXT_PUBLIC_ ile öne eklemeyin. Next.js yalnızca bu öneki taşıyan değişkenleri tarayıcı paketlerine açar; API anahtarı sunucu tarafındaki Route Handler’da kalmalıdır.

Adım 3: Model Politikasını Tanımlayın

İzin verilen kimlikleri yalnızca açılır listede değil, arka uçta tutun. Bir kullanıcı tarayıcı kontrollerini atlayıp rotanızı doğrudan çağırabilir; bu nedenle sunucu bilinmeyen model değerlerini reddetmelidir.

const ALLOWED_MODELS = [  "gemini-3.7-flash",  "claude-opus-5",  "gpt-5.6",] as const;​type ModelId = (typeof ALLOWED_MODELS)[number];

İstemci seçim arayüzünde aynı üç kimliği kullanacaktır; ancak doğruluk kaynağı sunucu olarak kalır.

Adım 4: CometAPI’yi Bir Route Handler Üzerinden Akıtın

app/api/chat/route.ts oluşturun. Rota, yalnızca metin içeren bir sohbet yükünü doğrular, CometAPI’yi stream: true ile çağırır ve kimliği açığa çıkarmadan yukarı akıştaki olay akışını geri döndürür.

export const runtime = "nodejs";export const dynamic = "force-dynamic";​const ALLOWED_MODELS = [  "gemini-3.7-flash",  "claude-opus-5",  "gpt-5.6",] as const;​type ModelId = (typeof ALLOWED_MODELS)[number];type ChatMessage = {  role: "system" | "user" | "assistant";  content: string;};​function isModelId(value: unknown): value is ModelId {  return (    typeof value === "string" &&    (ALLOWED_MODELS as readonly string[]).includes(value)  );}​function isChatMessage(value: unknown): value is ChatMessage {  if (typeof value !== "object" || value === null) return false;​  const message = value as Record<string, unknown>;  return (    ["system", "user", "assistant"].includes(String(message.role)) &&    typeof message.content === "string" &&    message.content.length > 0 &&    message.content.length <= 20_000  );}​export async function POST(request: Request) {  const apiKey = process.env.COMETAPI_API_KEY;  const baseUrl = (    process.env.COMETAPI_BASE_URL || "https://api.cometapi.com/v1"  ).replace(/\/$/, "");​  if (!apiKey) {    return Response.json(      { error: "COMETAPI_API_KEY is not configured." },      { status: 500 },    );  }​  let payload: { model?: unknown; messages?: unknown };​  try {    payload = await request.json();  } catch {    return Response.json({ error: "Invalid JSON body." }, { status: 400 });  }​  if (!isModelId(payload.model)) {    return Response.json({ error: "Unsupported model ID." }, { status: 400 });  }​  if (    !Array.isArray(payload.messages) ||    payload.messages.length === 0 ||    payload.messages.length > 50 ||    !payload.messages.every(isChatMessage)  ) {    return Response.json(      { error: "messages must contain 1 to 50 valid text messages." },      { status: 400 },    );  }​  const upstream = await fetch(`${baseUrl}/chat/completions`, {    method: "POST",    headers: {      Authorization: `Bearer ${apiKey}`,      "Content-Type": "application/json",    },    body: JSON.stringify({      model: payload.model,      messages: payload.messages,      stream: true,    }),    cache: "no-store",    signal: request.signal,  });​  if (!upstream.ok) {    const requestId = upstream.headers.get("x-request-id");​    console.error("CometAPI request failed", {      status: upstream.status,      requestId,    });​    return Response.json(      {        error: "The selected model request failed.",        status: upstream.status,        requestId,      },      { status: upstream.status },    );  }​  if (!upstream.body) {    return Response.json(      { error: "The model returned no response body." },      { status: 502 },    );  }​  return new Response(upstream.body, {    status: 200,    headers: {      "Content-Type": "text/event-stream; charset=utf-8",      "Cache-Control": "no-cache, no-transform",    },  });}

İşleyici, tarayıcının bağlantıyı kesme sinyalini yukarı akışa geçirir; böylece isteğin kapatılması gereksiz üretimi durdurabilir. Ayrıca tanılama ayrıntılarını sunucu günlüklerinde tutarken istemciye temizlenmiş bir hata döndürür.

Adım 5: Model Seçimi ve Akış Ayrıştırmayı Ekleyin

app/page.tsx içinde bir istemci bileşeni oluşturun. Seçilen modeli konuşmayla birlikte gönderir, her data: olayını ayrıştırır ve artımlı delta.content metnini son asistan mesajına ekler.

Tarayıcı CometAPI’yi asla doğrudan çağırmaz. Tek hedefi, anahtarı gizli tutan ve izin listesini zorlayan kendi /api/chat rotanızdır.

Çekirdek Proje Kodu

Yukarıdaki Route Handler, app/api/chat/route.ts dosyasının tamamıdır. Çalıştırılabilir projeyi tamamlamak için aşağıdaki sayfa, yerleşim ve stil dosyasını ekleyin.

app/page.tsx

"use client";​import { FormEvent, useState } from "react";​const MODEL_OPTIONS = [  { id: "gemini-3.7-flash", label: "Gemini 3.7 Flash" },  { id: "claude-opus-5", label: "Claude Opus 5" },  { id: "gpt-5.6", label: "GPT-5.6" },] as const;​type Role = "user" | "assistant";type Message = { role: Role; content: string };​function textFromSseLine(line: string): string {  const trimmed = line.trim();  if (!trimmed.startsWith("data:")) return "";​  const data = trimmed.slice(5).trim();  if (!data || data === "[DONE]") return "";​  try {    const event = JSON.parse(data);    return event.choices?.[0]?.delta?.content ?? "";  } catch {    return "";  }}​export default function Home() {  const [model, setModel] = useState("gemini-3.7-flash");  const [messages, setMessages] = useState<Message[]>([]);  const [input, setInput] = useState("");  const [loading, setLoading] = useState(false);  const [error, setError] = useState("");​  function appendAssistantText(text: string) {    if (!text) return;​    setMessages((current) => {      const next = [...current];      const lastIndex = next.length - 1;​      if (lastIndex >= 0 && next[lastIndex].role === "assistant") {        next[lastIndex] = {          ...next[lastIndex],          content: next[lastIndex].content + text,        };      }​      return next;    });  }​  async function sendMessage(event: FormEvent<HTMLFormElement>) {    event.preventDefault();​    const content = input.trim();    if (!content || loading) return;​    const outgoing: Message[] = [...messages, { role: "user", content }];    setMessages([...outgoing, { role: "assistant", content: "" }]);    setInput("");    setError("");    setLoading(true);​    try {      const response = await fetch("/api/chat", {        method: "POST",        headers: { "Content-Type": "application/json" },        body: JSON.stringify({ model, messages: outgoing }),      });​      if (!response.ok) {        const body = await response.json().catch(() => ({}));        throw new Error(body.error || `Request failed with ${response.status}`);      }​      if (!response.body) throw new Error("Streaming is not available.");​      const reader = response.body.getReader();      const decoder = new TextDecoder();      let buffer = "";​      while (true) {        const { value, done } = await reader.read();        buffer += decoder.decode(value, { stream: !done });​        const lines = buffer.split("\n");        buffer = lines.pop() ?? "";​        for (const line of lines) {          appendAssistantText(textFromSseLine(line));        }​        if (done) {          appendAssistantText(textFromSseLine(buffer));          break;        }      }    } catch (requestError) {      setError(        requestError instanceof Error ? requestError.message : "Request failed.",      );    } finally {      setLoading(false);    }  }​  return (    <main className="shell">      <section className="chat">        <header>          <p className="eyebrow">Next.js + CometAPI</p>          <h1>Multi-model chat</h1>          <label>            Model            <select              value={model}              onChange={(event) => setModel(event.target.value)}              disabled={loading}            >              {MODEL_OPTIONS.map((option) => (                <option key={option.id} value={option.id}>                  {option.label}                </option>              ))}            </select>          </label>        </header>​        <div className="messages" aria-live="polite">          {messages.length === 0 ? (            <p className="empty">Choose a model and send a message.</p>          ) : (            messages.map((message, index) => (              <article className={message.role} key={`${message.role}-${index}`}>                <b>{message.role === "user" ? "You" : "Assistant"}</b>                <p>{message.content || "…"}</p>              </article>            ))          )}        </div>​        <form onSubmit={sendMessage}>          <textarea            value={input}            onChange={(event) => setInput(event.target.value)}            placeholder="Ask something…"            rows={3}            maxLength={20_000}          />          <button disabled={loading || !input.trim()} type="submit">            {loading ? "Streaming…" : "Send"}          </button>        </form>​        {error ? <p className="error">{error}</p> : null}      </section>    </main>  );}

app/layout.tsx

import type { Metadata } from "next";import "./globals.css";​export const metadata: Metadata = {  title: "Multi-Model Chat",  description: "A streaming Next.js chat app powered by CometAPI.",};​export default function RootLayout({  children,}: Readonly<{ children: React.ReactNode }>) {  return (    <html lang="en">      <body>{children}</body>    </html>  );}

app/globals.css

:root {  color-scheme: dark;  font-family: Arial, sans-serif;  background: #07111f;  color: #eef4ff;}* { box-sizing: border-box; }body { margin: 0; }button, select, textarea { font: inherit; }​/* Layout shell and chat card */.shell { min-height: 100vh; display: grid; place-items: center; padding: 32px 16px; }.chat { width: min(820px, 100%); background: #0d1b2e; border: 1px solid #223957; border-radius: 20px; padding: 24px; }​/* Message list and bubbles */.messages { min-height: 360px; display: grid; align-content: start; gap: 12px; margin: 24px 0; }.messages article { max-width: 85%; padding: 12px 14px; border-radius: 14px; white-space: pre-wrap; }.user { justify-self: end; background: #164f8f; }.assistant { justify-self: start; background: #182a42; }​/* Form controls, buttons, and error states follow the same dark theme. */

Adım 6: Uygulamayı Çalıştırın ve Dağıtın

npm run dev

http://localhost:3000 adresini açın, bir model seçin ve bir mesaj gönderin. Üretim Node.js dağıtımı için ana makinenin sunucu tarafı ortam ayarlarına COMETAPI_API_KEY ve COMETAPI_BASE_URL ekleyin ve ardından şunları çalıştırın:

npm run buildnpm run start

Akış yanıtlarını destekleyen bir barındırma yolu kullanın. Statik dışa aktarma, /api/chat Route Handler’ını çalıştıramaz.

Akışlı Rotayı Test Edin

Geliştirme sunucusu çalışırken arka ucunuzu doğrudan çağırın:

curl -N http://localhost:3000/api/chat \  -H "Content-Type: application/json" \  -d '{    "model": "gemini-3.7-flash",    "messages": [      {"role": "user", "content": "Explain model routing in two sentences."}    ]  }'

Başarılı bir istek Sunucu Tarafından Gönderilen Olayları döndürür. Tam kimlikler ve metin değişebilir, ancak akış şu biçimi izler:

data: {"choices":[{"delta":{"content":"Model"}}]}​data: {"choices":[{"delta":{"content":" routing"}}]}​data: [DONE]

Tarayıcı ayrıştırıcısı her SSE olayını okur, choices[0].delta.content değerini çıkarır ve parça parça gelen metni asistan mesajına ekler.

Yaygın Entegrasyon Hataları

BelirtiNedenÇözüm
401 kimlik doğrulama hatasıEksik veya geçersiz sunucu tarafı anahtarıCOMETAPI_API_KEY ayarlayın; anahtarı NEXT_PUBLIC_ ile açığa çıkarmayın.
404 veya yanlış rotaBase URL’de /v1 eksikhttps://api.cometapi.com/v1 kullanın.
400 desteklenmeyen modelKimlik arka uç izin listesinde değilCanlı, birebir metin model kimliği kullanın ve her iki seçiciyi de güncelleyin.
Yanıt bir anda görünüyorAna makine veya proxy olay akışını arabellekliyorYanıt dönüşümünü devre dışı bırakın ve akışa uygun bir Node.js dağıtımı kullanın.

Sohbet Arka Ucunu Üretime Hazırlayın

  • Kendi kullanıcılarınızı kimlik doğrulayın. Anonim trafiğin kredi harcamasına izin veren genel bir rota yayımlamayın.
  • Kullanıcı ve IP bazında hız sınırlaması uygulayın. Eşzamanlı akışları, dakika başına istekleri, mesaj sayısını ve mesaj uzunluğunu sınırlandırın.
  • Model izin listesini sunucu tarafında tutun. Tarayıcıdaki seçici bir kolaylıktır, güvenlik sınırı değildir.
  • Dağıtım sırasında canlı kataloğu doğrulayın. GET https://api.cometapi.com/api/models sorgulayın ve yapılandırılan bir kimlik “yakında”, kullanılamaz veya sohbet-tamamlama uç noktasından yoksunsa sürümü başarısız sayın.
  • Rotalara göre maliyeti izleyin. Seçilen modeli, istek kimliğini, gecikmeyi, token kullanımını ve kullanıcı kimliğini kaydedin. Uygun yerlerde CometAPI panosunda anahtar kotaları veya harcama sınırları belirleyin.
  • Bağlantı kesilmelerini ve zaman aşımı durumlarını yönetin. request.signal değerini koruyun, bir uygulama zaman aşımı ayarlayın ve istemci ayrıldığında işi durdurun.
  • Yapılandırma hatalarını yedekle (fallback) ile gizlemeyin. 400 ve 401 yanıtlarını yüzeye çıkarın. Yalnızca sınırlı bir yeniden denenebilir hata kümesi için ve yalnızca istek şeması uyumluysa başka bir modeli kullanın; iki katmanlı geri dönüş zinciri (CometAPI birincil → CometAPI yedek model → resmi sağlayıcı) için CometAPI Model Geri Dönüş Kılavuzu’na bakın.
  • Günlükleri maskeleyin. API anahtarlarını, tam istemleri ve hassas model çıktısını üretim hata günlüklerinden uzak tutun.

Tek Bir Next.js Arka Ucu, Birden Fazla Model Seçeneği

Model anahtarı, ayrı sağlayıcı hesaplarında değil sunucu politikanızda yer almalıdır. Bir Next.js Route Handler, tek bir CometAPI anahtarını gizli tutabilir, her istek için onaylı bir model kimliği kabul edebilir ve seçilen modeli tek bir OpenAI uyumlu uç nokta üzerinden akıtabilir. Ön uç basit kalırken, arka uç erişim, doğrulama, gözlemlenebilirlik ve maliyet üzerinde kontrolü elinde tutar. Aynı hesap ve anahtar, CometAPI’nin Flux gibi görüntü üretimi ve Kling gibi video üretimi için yerel görüntü ve video API’lerine de erişir; böylece bu sohbet arka ucu, ikinci bir entegrasyona gerek kalmadan çoklu ortam iş akışlarına genişletilebilir.

Model keşfi için CometAPI genel model dizinini ve otomatik yönlendirme doğrulaması için GET https://api.cometapi.com/api/models uç noktasını kullanın.

Sıkça Sorulan Sorular

Tek bir Next.js uygulamasında birden çok yapay zeka modeli kullanabilir miyim?

Evet. Tek bir sunucu tarafı rota tutun ve her istekle birlikte izin listesinde yer alan bir model kimliği geçin. Tarayıcı arayüzü model seçenekleri sunabilir, sunucu ise hangi kimliklerin kabul edileceğini kontrol eder.

GPT, Claude ve Gemini arasında nasıl geçiş yaparım?

Seçilen model kimliğini istek gövdesine gönderin. Sunucu bunu bir izin listesine karşı doğrular ve aynı sohbet yükünü OpenAI uyumlu uç nokta üzerinden seçilen modele iletir.

CometAPI API anahtarımı nerede saklamalıyım?

COMETAPI_API_KEY gibi sunucu tarafı bir ortam değişkeninde saklayın. Bunu hiçbir zaman bir NEXT_PUBLIC_ değişkeni veya istemci tarafı kod üzerinden açığa çıkarmayın.

OpenAI uyumlu bir API tüm modelleri birbirinin yerine geçebilir hale getirir mi?

Hayır. İstek biçimi taşınabilirdir, ancak modeller desteklenen parametreler, bağlam sınırları, araç davranışı, çıktı stili, gecikme ve fiyat bakımından farklılık gösterebilir. İzin listesine eklediğiniz her modeli üretim istemlerinizle test edin.

Next.js Route Handler’ları yapay zeka yanıtlarını akış halinde iletebilir mi?

Evet. Dağıtım platformu ve önündeki proxy yanıtı arabelleklemezse, bir Route Handler text/event-stream içerik türüyle yukarı akıştaki Sunucu Tarafından Gönderilen Olaylar akışını döndürebilir.

Bu uygulamayı statik bir Next.js sitesi olarak dağıtabilir miyim?

Hayır. Statik dışa aktarma, sunucu tarafındaki /api/chat Route Handler’ını çalıştıramaz veya API anahtarını koruyamaz. Akış yanıtlarını destekleyen bir Node.js veya başka uyumlu sunucu çalışma zamanı kullanın.

Öğrenmeye devam et

Bu makaleyi sonraki karara bağlayın.

Tüm konuları gör
Yayınlanma tarihi Aug 25, 2026
Son güncelleme Aug 25, 2026
0 görüntülenme
Netlik, kaynak ataması ve güncel API terminolojisi açısından gözden geçirildi.

Yapay zeka geliştirme maliyetlerinizi %20 azaltmaya hazır mısınız?

Dakikalar içinde ücretsiz başlayın. Ücretsiz deneme kredileri dahildir. Kredi kartı gerekmez.

Devamını Oku