Bir öğleden sonra tek bir yanıtı stream (akış) olarak veren bir yapay zeka sohbet botu oluşturabilirsiniz. Onu ilk 429 hatasından sonra hayatta tutmak ise asıl iştir. SSE akışı, sunucu tarafı sohbet belleği ve model izin listesi (allowlist) içeren küçük bir FastAPI servisini, tek bir TokenLab anahtarı arkasında inşa ediyoruz. Hedefimiz, gerçek bir ürün arayüzünün arkasına koyabileceğiniz ve entegrasyonu yeniden yazmadan modelleri değiştirebileceğiniz bir backend oluşturmaktır. Eğer henüz base URL değişimini yapmadıysanız, önce geçiş kılavuzunu okuyun. Eğer temel endişeniz yük altındaki backoff (bekleme) süreciyse, bu kılavuzu AI API hız sınırlama kılavuzu ile birlikte kullanın.
Önemli Çıkarımlar
- Üretime hazır bir sohbet botu altı parçaya ihtiyaç duyar: bir senkron endpoint, bir stream endpoint, sunucu tarafı sohbet durumu, bir model izin listesi, gerçek hata yönetimi ve bir depolama yükseltme yolu.
- Anahtarı her işlemde
TOKENLAB_API_KEYüzerinden yükleyin ve sunucuda tutun. Kimlik Doğrulama belgeleri (2026-10-03 tarihinde incelenmiştir), anahtarları asla istemci tarafı kodunda ifşa etmemenizi veya commit etmemenizi belirtir. GET /v1/modelsherkese açıktır, bu nedenle başarılı bir yanıt anahtarınızın çalıştığını kanıtlamaz. Bunu gerçek bir sohbet isteği ile kanıtlayın (Hızlı Başlangıç, 2026-10-03 tarihinde incelenmiştir).- SSE çoğu sohbet ürünü için yeterlidir. Çıktı geldikten sonra kesilen bir akışı tamamlanmış bir yanıt olarak değil, eksik bir yanıt olarak değerlendirin.
- Bu kılavuzdaki izin listesi, katmanları
deepseek-v4-flash,gpt-5.5,claude-sonnet-5vegemini-3.5-flashmodelleriyle eşleştirir. Her biri kabul edilen bir format olarakopenai_chat_completionslisteler (2026-10-03 tarihinde incelenmiştir). - Aşağıdaki fiyatlardan yapılan tahmine göre, 2.000 giriş ve 500 çıkış token'lık bir sohbet turu, modele bağlı olarak yaklaşık 0,0006$ ile 0,0075$ arasında bir maliyete sahiptir.
Yapay Zeka Sohbet Botu Oluşturma: Kurulum ve Temel Servis
Tamamlanmış servis altı hareketli parçaya sahiptir:
- Duman testleri (smoke tests) için senkron bir
/chatendpoint'i. - Gerçek kullanıcı arayüzü için stream (akış) sağlayan bir
/chat/streamendpoint'i. conversation_idile anahtarlanmış sohbet durumu.- Frontend'in rastgele ID'ler talep etmesini önlemek için bir model izin listesi.
- İlk 429 hatasında çökmeyen hata yönetimi.
- Bellek içi prototipten Redis veya PostgreSQL'e geçiş yolu.
Bu, bir destek botu, dahili bir asistan veya gömülü bir sohbet widget'ının ilk sürümü için yeterlidir. Aşağıdaki her kod bloğu, gösterilen sırayla main.py adlı tek bir dosyaya eklenir.
Adım 1: Anahtarı ayarlayın ve yığını kurun
Çalışma alanınızdaki API Anahtarları altında bir anahtar oluşturun. Tam değer yalnızca bir kez gösterilir ve anahtar listesindeki önek, isteklerin kimliğini doğrulayamaz. Tüm TokenLab anahtarları sk- ile başlar. Ayrıca Faturalandırma kısmından bakiyenizi kontrol edin, çünkü ilk istek modelin güncel fiyatı üzerinden ücretlendirilir (Hızlı Başlangıç, 2026-10-03 tarihinde incelenmiştir).
Anahtarı kaynak kodda değil, bir ortam değişkeninde saklayın. Aşağıdaki komut onu komut satırı ve kabuk geçmişinden uzak tutar ve yalnızca mevcut terminal ile alt süreçleri için geçerlidir. Dağıtılan uygulamalar için bir secret manager kullanın. Hızlı Başlangıç kılavuzunda PowerShell sürümü de mevcuttur.
printf 'TokenLab API key: '
read -r -s TOKENLAB_API_KEY
printf '\n'
export TOKENLAB_API_KEY
pip install fastapi uvicorn openai pydantic
TokenLab'e özel bir SDK'ya ihtiyacınız yoktur. Anahtarı ve base URL'yi değiştirdiğinizde resmi OpenAI SDK'sı çalışır (SDK'lar kılavuzu, 2026-10-03 tarihinde incelenmiştir).
Adım 2: Şemayı, izin listesini ve belleği tanımlayın
Paylaşılan parçalarla başlıyoruz. İstek şeması ham bir model dizisi yerine tier (katman) kullanır ve bu kılavuzdaki her curl örneği aynı alanları gönderir.
İlk sohbet botu demosu genellikle transkripti tarayıcıda tutar ve her turda yeniden gönderir. Bu, bir prototip için işe yarar. Ancak yeniden denemeler, devam ettirilebilir oturumlar veya sunucu tarafı araçlara ihtiyaç duyduğunuzda işler karmaşıklaşır. Bu yüzden geçmişin sahibi en başından itibaren sunucudur.
import json
import logging
import os
import time
import uuid
from collections import defaultdict
from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse
from openai import APIConnectionError, APIStatusError, OpenAI, RateLimitError
from pydantic import BaseModel, Field
log = logging.getLogger("chatbot")
app = FastAPI()
client = OpenAI(
api_key=os.environ["TOKENLAB_API_KEY"],
base_url="https://api.tokenlab.sh/v1",
timeout=30.0,
max_retries=0,
)
ALLOWED_MODELS = {
"default": "deepseek-v4-flash",
"flagship": "gpt-5.5",
"balanced": "claude-sonnet-5",
"budget": "gemini-3.5-flash",
}
SYSTEM_PROMPT = "You are a helpful assistant. Be concise and direct."
MAX_HISTORY = 20 # her sohbet için tutulan mesaj sayısı (tercihinize göre)
MAX_REPLY_TOKENS = 1000 # her tur için çıktı sınırı (tercihinize göre)
class ChatRequest(BaseModel):
message: str = Field(min_length=1, max_length=4000)
tier: str = "default"
conversation_id: str | None = None
def resolve_model(tier: str) -> str:
model = ALLOWED_MODELS.get(tier)
if model is None:
raise HTTPException(status_code=400, detail=f"unknown tier: {tier}")
return model
conversations: dict[str, list[dict]] = defaultdict(list)
def build_messages(conv_id: str, user_msg: str) -> list[dict]:
history = conversations[conv_id][-MAX_HISTORY:]
return [
{"role": "system", "content": SYSTEM_PROMPT},
*history,
{"role": "user", "content": user_msg},
]
def remember(conv_id: str, user_msg: str, reply: str) -> None:
conversations[conv_id].append({"role": "user", "content": user_msg})
conversations[conv_id].append({"role": "assistant", "content": reply})
İstemci, Hızlı Başlangıç kılavuzuna uygun olarak max_retries=0 ve 30 saniyelik bir zaman aşımı ayarlar. Yeniden deneme kararlarını kendimiz veriyoruz, çünkü stream edilen bir turda SDK'nın körü körüne yeniden deneme yapması ücreti tekrarlayabilir.
Adım 3: Hataları eşleyin ve senkron endpoint'i ekleyin
Herhangi bir SDK istisnasını bir durum koduna ve kullanıcı için güvenli bir mesaja dönüştüren küçük bir fonksiyon tutuyoruz. Detaylar kullanıcıya değil, loglarınıza gider.
def describe_error(exc: Exception) -> tuple[int, str]:
if isinstance(exc, RateLimitError): # önce kontrol edin: APIStatusError'dan türetilmiştir
return 429, "The assistant is busy. Please retry shortly."
if isinstance(exc, APIConnectionError):
return 502, "Connection problem. Please retry."
if isinstance(exc, APIStatusError):
log.error("upstream status=%s code=%s", exc.status_code, exc.code)
if exc.status_code in (401, 402, 403): # anahtar, bakiye veya izin: operatör sorunu
return 503, "The assistant is unavailable right now."
if exc.status_code in (400, 404): # hatalı alan veya model ID: bizim hatamız
return 500, "Something went wrong on our side."
return 502, "The assistant is unavailable right now."
return 500, "Something went wrong."
def retry_delay(exc: RateLimitError) -> float:
try:
return min(float(exc.response.headers.get("retry-after", "2")), 10.0)
except ValueError:
return 2.0
def create_with_one_retry(**kwargs):
try:
return client.chat.completions.create(**kwargs)
except RateLimitError as exc:
time.sleep(retry_delay(exc))
return client.chat.completions.create(**kwargs)
@app.post("/chat")
def chat(req: ChatRequest):
model = resolve_model(req.tier)
conv_id = req.conversation_id or str(uuid.uuid4())
messages = build_messages(conv_id, req.message)
try:
response = create_with_one_retry(
model=model, messages=messages, max_tokens=MAX_REPLY_TOKENS
)
except (APIConnectionError, APIStatusError) as exc:
status, message = describe_error(exc)
raise HTTPException(status_code=status, detail=message)
reply = response.choices[0].message.content or ""
log.info("model=%s usage=%s", model, response.usage)
remember(conv_id, req.message, reply)
return {"conversation_id": conv_id, "reply": reply}
Başka bir şey inşa etmeden önce bir istek çalıştırın. Eğer bu başarısız olursa, üzerine inşa etmeye devam etmeyin.
Yanıtları Stream Edin ve Yapay Zeka Sohbet Botunu Duyarlı Tutun
Çoğu sohbet botu ürünü, model yavaş olduğu için değil, kullanıcı arayüzü tam yanıt gelene kadar boş kaldığı için yavaş hissettirir. SSE'yi ekliyoruz çünkü çoğu sohbet ürününü kapsıyor ve websocket'lerden daha az operasyonel yük getiriyor. Eğer ürününüz zaten düz HTTP üzerinden bir tarayıcı istemcisi çalıştırıyorsa, SSE mimariyi daha basit tutar.
Adım 4: Stream endpoint'ini ekleyin
Stream belgeleri (Akış kılavuzu, 2026-10-03 tarihinde incelenmiştir), /v1/chat/completions üzerinden SSE parçaları bekleyen çerçeveler için Chat Completions akışını geçerli tutar. İzin listesindeki dört modelin de bunu kabul etmesi nedeniyle bu yolda kalıyoruz. Her olayı JSON olarak kodluyoruz, böylece yanıt içindeki satır sonları çerçevelemeyi bozamaz.
def sse(payload: dict) -> str:
return f"data: {json.dumps(payload)}\n\n"
@app.post("/chat/stream")
def chat_stream(req: ChatRequest):
model = resolve_model(req.tier)
conv_id = req.conversation_id or str(uuid.uuid4())
messages = build_messages(conv_id, req.message)
def generate():
parts: list[str] = []
finish_reason = None
try:
with client.chat.completions.create(
model=model,
messages=messages,
max_tokens=MAX_REPLY_TOKENS,
stream=True,
stream_options={"include_usage": True},
) as stream:
for chunk in stream:
if chunk.usage:
log.info("model=%s usage=%s", model, chunk.usage)
if not chunk.choices:
continue
choice = chunk.choices[0]
if choice.delta.content:
parts.append(choice.delta.content)
yield sse({"delta": choice.delta.content})
if choice.finish_reason:
finish_reason = choice.finish_reason
except (APIConnectionError, APIStatusError) as exc:
_, message = describe_error(exc)
yield sse({"error": message})
return
if finish_reason != "stop":
yield sse({"error": f"Reply incomplete ({finish_reason})."})
return
remember(conv_id, req.message, "".join(parts))
yield sse({"done": True, "conversation_id": conv_id})
return StreamingResponse(generate(), media_type="text/event-stream")
Burada iki detay önemlidir. Birincisi, include_usage: true akış parçalarına token kullanımını ekler ve son kullanım parçası choices içermez, bu yüzden döngü onu atlar. İkincisi, turu yalnızca finish_reason değeri stop olduğunda kaydederiz. length ile bitiş, token sınırının yanıtı kestiği anlamına gelir ve belgeler her ikisini de normal bitiş koşulları olarak listeler.
Hatalar jeneratör içinde ortaya çıktığı için, bir hata oluştuğunda HTTP durumu zaten 200'dür. İstemci error olayını okumalıdır. with bloğu, jeneratör çıktığında yukarı akışı (upstream) kapatır. Belgeler, kullanıcı durduğunda veya bağlantıyı kestiğinde yukarı akışı iptal etmeyi önerir, bu yüzden ASGI sunucunuzun bağlantı kesildiğinde jeneratörü gerçekten durdurduğunu test edin.
Adım 5: Akışı tarayıcıda okuyun
Tarayıcı kendi kimliği doğrulanmış backend'inizi çağırmalı ve TokenLab'i asla doğrudan çağırmamalıdır. Olay sınırına göre ayrıştırın, çünkü bir ağ parçası mutlaka tam bir SSE olayı değildir.
async function sendMessage(payload, onDelta) {
const response = await fetch('/chat/stream', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload), // { message, tier, conversation_id }
});
if (!response.ok || !response.body) throw new Error(`HTTP ${response.status}`);
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const events = buffer.split('\n\n');
buffer = events.pop();
for (const raw of events) {
if (!raw.startsWith('data: ')) continue;
const event = JSON.parse(raw.slice(6));
if (event.error) throw new Error(event.error);
if (event.delta) onDelta(event.delta);
}
}
}
İhtiyaç duyduğunuzda belleği Redis'e yükseltin
Bellek içi sözlük tek bir işlem için iyidir. Sohbetlerin bir TTL'ye, devam ettirilebilirliğe veya birden fazla örneğe ihtiyacı olduğunda Redis'e geçin. Transkript sorgulamanız, denetlemeniz veya raporlamanız gereken ürün verisi olduğunda PostgreSQL'e geçin. Redis değişikliği bir depolama tesisatıdır, mantık değişikliği değildir. pip install redis komutunu çalıştırın, ardından build_messages ve remember fonksiyonlarının bu yardımcılar aracılığıyla okuma ve yazma yapmasını sağlayın.
import redis
redis_client = redis.Redis(
host=os.environ.get("REDIS_HOST", "127.0.0.1"), port=6379, decode_responses=True
)
def load_history(conv_id: str) -> list:
raw = redis_client.get(f"chat:{conv_id}")
return json.loads(raw) if raw else []
def save_history(conv_id: str, history: list) -> None:
redis_client.setex(f"chat:{conv_id}", 60 * 60 * 24, json.dumps(history))
Üretim İçin Yapay Zeka Sohbet Botu Oluştururken Hataları Yönetin
Müşteri tarafındaki bir kullanıcı, hatanın hız sınırlamasından, boş bakiyeden veya yukarı akış kesintisinden kaynaklanıp kaynaklanmadığını önemsemez. Kullanıcı arayüzünün donup donmadığını önemser. Akışı kırk kelimeden sonra ölen bir destek widget'ı hayal edin. TokenLab belgeleri, çıktı geldikten sonra kesilen bir akışın tamamlanmış bir yanıt olmadığını ve bunu tekrarlamanın farklı bir çıktı ve ikinci bir ücret oluşturabileceğini belirtir (API hatalarını yönetme, 2026-10-03 tarihinde incelenmiştir). Adım 4'ün asla tamamlanmamış bir turu kaydetmemesinin nedeni budur.
Adım 6: Yeniden deneme kurallarını uygulayın
Hataları, haber verilmeksizin değişebilen insan tarafından okunabilir message ile değil, HTTP durumu ve code ile yönetin. Tablo, belgeleri servisimizin yaptıklarıyla birleştirir.
| Durum | Anlamı (belgelere göre) | Bu servis ne yapıyor |
|---|---|---|
400 |
Alan, model ID veya giriş geçersiz | 500 döndür, logla, asla yeniden deneme |
401 |
Anahtar eksik, geçersiz, süresi dolmuş veya iptal edilmiş | 503 döndür, operatörü uyar |
402 |
Bakiye veya API anahtarı limiti çok düşük (insufficient_balance, quota_exceeded) |
503 döndür, operatörü uyar |
403 |
Anahtar bu modeli kullanamaz | 503 döndür, anahtarın model listesini kontrol et |
404 |
Kaynak veya model bulunamadı | 500 döndür, ID'yi /v1/models ile karşılaştır |
429 |
İstek limitine ulaşıldı | Retry-After süresini bekle, bir kez yeniden dene (sadece senkron) |
500–504 |
Servis kullanılamıyor veya ağ hatası | Sadece retryable değeri true olduğunda yeniden dene; retry_after süresine uy |
Belgelerden iki uyarı. Bir 503 all_channels_failed her zaman geçici bir kesinti anlamına gelmez. Eğer retryable değeri false ise, aynı isteği tekrarlamayın ve başka bir model seçmeden önce GET /v1/models kontrolü yapın. Ayrıca, Chat Completions ve Responses OpenAI tarzı bir error nesnesi kullanır, ancak Anthropic Messages ve Gemini kendi formatlarını korur. Servisimiz izin listesindeki her modelde Chat Completions'ı çağırır, bu nedenle bir ayrıştırıcı çalışır. Eğer bir katmanı yerel bir formata taşırsanız, ikinci bir ayrıştırıcıya ihtiyacınız olur.
Yanıt başlıklarından İstek ID'sini endpoint, model, zaman ve kendi kullanıcı veya iş ID'nizle birlikte kaydedin. Belgeler kullandığımız sayfalarda başlığı isimlendirmez, bu yüzden loglarınızı bağlamadan önce sorun giderme yolu ile doğrulayın.
Üretim kontrol listesinin geri kalanı kısadır:
- Frontend hatalarını backend loglarına bağlayabilmek için kendi istek ID'lerinizi ekleyin.
- Kullanıcı başına eşzamanlılığı ve istek boyutunu sınırlayın.
messageüzerindekimax_length=4000, ayarlamanız gereken bir başlangıç noktasıdır. - Geçmişi,
MAX_HISTORY'nin yaptığı gibi mesaj sayısına göre sınırlayın. Faturalandırma belgeleri, tokenlaştırmanın modele, dile ve medya girişine göre değiştiğini söyler, bu nedenle karakter sayısı formülü güvenilir bir faturalandırma tahmini değildir. - Her turda modeli, gecikmeyi, kullanımı ve bitiş nedenini loglayın.
- Kullanıcı tarafından görülebilen mesajları dahili hata detaylarından ayrı tutun.
- Alternatif bir katmana bir test turu gönderin, böylece ilk gerçek kesintiden önce yedeklemenin çalıştığını bilirsiniz.
Yapay Zeka Sohbet Botunuz İçin Modelleri Seçin ve Maliyeti Tahmin Edin
Frontend'in API'ye rastgele bir model dizisi geçmesine asla izin vermeyin. Serbest metin alanı yazım hatalarına, emekli olmuş modellere ve ifşa etmek istemediğiniz modellere davetiye çıkarır. ALLOWED_MODELS haritası, bir sağlayıcı bir modeli kullanımdan kaldırdığında istemci güncellemesi olmadan modeli değiştirmeniz için size tek bir yer sağlar. Bilinmeyen model ID'leri model_not_found döndürür ve belgeler sizi güncel bir ID için /v1/models adresine yönlendirir. İzin listesini kilitlemeden önce model dizinini kontrol edin.
1M token başına güncel fiyatlar
Bunlar, 2026-10-03 tarihinde incelenen, her modelin canlı API girişinden alınan USD cinsinden TokenLab fiyatlarıdır. Fiyatlandırma en son 2026-10-02T16:53:30.068Z tarihinde güncellenmiştir. Dört modelin tamamı active yaşam döngüsü aşamasını göstermiştir.
| Katman | Model ID | Giriş / 1M | Çıkış / 1M | Önbellek okuma / 1M | Kaynak |
|---|---|---|---|---|---|
| default | deepseek-v4-flash (yoğun olmayan) |
$0.15 | $0.60 | $0.003 | model API |
| default | deepseek-v4-flash (yoğun) |
$0.30 | $1.20 | $0.006 | model API |
| flagship | gpt-5.5 |
$1.50 | $9.00 | $0.15 | model API |
| balanced | claude-sonnet-5 |
$0.90 | $4.50 | $0.09 | model API |
| budget | gemini-3.5-flash |
$0.75 | $4.50 | $0.075 | model API |
deepseek-v4-flash için giriş, Çin resmi tatilleri hariç hafta içi günlerde yoğun dönemleri listeler. Yoğun olmayan dönemler hafta sonlarını ve bu tatilleri içerir. claude-sonnet-5 ayrıca 1M token başına 1,125$ önbellek yazma fiyatı listeler.
Bir çalışılmış istek
2.000 giriş token'ı ve 500 çıkış token'ı olan bir tur varsayalım. Bu boyut bir ölçüm değil, varsayımımızdır. gpt-5.5 için:
- Giriş: 2.000 × $1.50 / 1.000.000 = $0.0030
- Çıkış: 500 × $9.00 / 1.000.000 = $0.0045
- Toplam: Tur başına $0.0075 (tahmini, önbellek isabeti yok)
Aynı aritmetiği kullanarak şu tahminleri elde ederiz: deepseek-v4-flash yoğun olmayan saatlerde $0.0006 ve yoğun saatlerde $0.0012, claude-sonnet-5 $0.00405 ve gemini-3.5-flash $0.00375 maliyetindedir. 1.000 tur boyunca, bu gpt-5.5 üzerinde yaklaşık $7.50, deepseek-v4-flash üzerinde ise $0.60 ile $1.20 arasındadır. Gerçek turlar geçmiş biriktikçe büyür, bu yüzden bu boyutlandırmaya güvenmek yerine yanıttan veya son akış parçasından usage değerini okuyun.
Uygulamada, çoğu sohbeti varsayılan katmana yönlendiriyoruz ve gpt-5.5 veya claude-sonnet-5 modellerini ihtiyaç duyan turlar için ayırıyoruz. Faturalandırma belgeleri, token başına en düşük fiyatın her zaman tamamlanan görev başına en düşük maliyet olmadığını uyarır. Aynı istemleri iki katman üzerinden çalıştırın ve Kullanım kısmından nihai maliyeti karşılaştırın.
Yayına almadan önce iki kontrol. Faturalandırma belgeleri kopyalanmış bir fiyat tablosunu kodunuza gömmemenizi söyler, bu yüzden uygulamanız maliyetleri gösteriyorsa GET /v1/models/:model/pricing adresini okuyun (Faturalandırma ve fiyatlandırma, 2026-10-03 tarihinde incelenmiştir). Ayrıca, deepseek-v4-flash girişi json-mode, prompt-cache ve tool-use özelliklerini listeler ancak vision özelliğini listelemez. Sohbet botunuz görselleri kabul ediyorsa, bu turları vision özelliğini listeleyen bir katmana yönlendirin.
Duman Testi Yapın ve Yapay Zeka Sohbet Botunuzu Yayına Alın
Adım 7: Uçtan uca çalıştırın
Sunucuyu TOKENLAB_API_KEY değerinin dışa aktarıldığı bir terminalde başlatın. Curl yükleri, ChatRequest ile aynı message, tier ve conversation_id alanlarını kullanır.
uvicorn main:app --reload --port 8000
# 1. Senkron endpoint: kısa bir yanıt ve bir conversation_id bekleyin
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"message": "Reply only with OK.", "tier": "default"}'
# 2. Akış: data: {"delta": ...} satırlarını, ardından {"done": true, ...} bekleyin
curl -N -X POST http://localhost:8000/chat/stream \
-H "Content-Type: application/json" \
-d '{"message": "Hello!", "tier": "default"}'
# 3. Bellek: yukarıda döndürülen bir conversation_id'yi yeniden kullanın
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"message": "What did I just say?", "tier": "default", "conversation_id": "PASTE_ID_FROM_STEP_1"}'
# 4. Zorunlu hata: HTTP 400 ve "unknown tier: nope" bekleyin
curl -i -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"message": "Hello!", "tier": "nope"}'
Yukarı akış hatasını zorlamak için sunucuyu yanlış bir TOKENLAB_API_KEY ile yeniden başlatın. İstemciniz temiz bir 503 mesajı almalı ve loglarınız invalid_api_key ile yukarı akış 401 hatasını göstermelidir. Ardından başarılı çağrıların modelini, durumunu ve kullanımını doğrulamak için İstekler kısmını açın. Eğer bir turu stream edebiliyor, bir sohbeti koruyabiliyor ve zorunlu bir hatada temiz bir hata döndürebiliyorsanız, doğru temele sahipsiniz demektir.
Bundan sonraki yükseltmeler, daha fazla yapay zekadan ziyade sıkıcı altyapı işleridir:
- Kimlik doğrulama, böylece bir kullanıcı diğerinin sohbetini okuyamaz.
- Kalıcılık, böylece oturumlar dağıtımlardan sonra hayatta kalır.
- Kullanıcı başına hız sınırlama, böylece gürültülü bir kullanıcı kotanızı tüketemez.
- Kullanım ilişkilendirme, eğer sohbet botu müşteri odaklıysa.
- Arka plan özetleme, eğer sohbetlerin uzun vadeli belleğe ihtiyacı varsa.
Base URL geçişi geride kaldığında, bir model değişikliği ALLOWED_MODELS üzerinde bir yapılandırma düzenlemesidir.
SSS
Yapay zeka sohbet botu oluşturmak için websocket'lere ihtiyacım var mı?
Hayır. Adım 4'te gösterilen SSE, çoğu sohbet ürününü kapsar. Websocket'ler, canlı işbirliği veya sunucu tarafından başlatılan olaylar gibi istek ve yanıt dışında çift yönlü push'a ihtiyaç duyduğunuzda değer katar. Standart bir sohbet arayüzü için SSE'nin dağıtımı ve hata ayıklaması daha kolaydır.
Sohbet botum varsayılan olarak hangi modeli kullanmalı?
deepseek-v4-flash gibi düşük fiyatlı bir katmanla başlayın ve daha zor turlar için izin listesinin arkasına claude-sonnet-5 veya gpt-5.5 ekleyin. 2026-10-03 tarihinde incelenen yukarıdaki fiyatlar aradaki farkı gösterir. Ardından kendi istemlerinizi iki katman üzerinde test edin ve Kullanım kısmından nihai maliyeti karşılaştırın. Taahhüt etmeden önce model dizinini kontrol edin, çünkü kadrolar değişir.
Sohbet botum neden 402 veya 429 döndürüyor?
402, hesap bakiyesinin veya anahtarın kendi kullanım limitinin çok düşük olduğu anlamına gelir. Kodlar insufficient_balance ve quota_exceeded şeklindedir ve isteği tekrarlamak yardımcı olmaz. 429, bir istek limitine ulaştığınız anlamına gelir, bu yüzden Retry-After süresini bekleyin ve ardından yeniden deneyin. Senkron endpoint'imiz bir kez yeniden dener ve akış endpoint'imiz hatayı istemciye bildirir.
Tarayıcı TokenLab'i doğrudan çağırabilir mi?
Güvenli bir şekilde değil. Kimlik Doğrulama belgeleri, API anahtarlarını istemci tarafı kodunda asla ifşa etmemenizi söyler. Anahtarı sunucu ortamında tutun ve frontend örneğinin yaptığı gibi tarayıcının kendi kimliği doğrulanmış backend'inizi çağırmasını sağlayın.
tokenlab.sh adresinden bir API anahtarı oluşturun, bakiye ekleyin ve yukarıdaki duman testini çalıştırın.
Kaynaklar
Fiyat 2026-10-03 tarihinde gözlendi
- TokenLab Docs: Quickstart2026-10-03 tarihinde gözlendi
- TokenLab Docs: Authentication2026-10-03 tarihinde gözlendi
- TokenLab Docs: Streaming2026-10-03 tarihinde gözlendi
- TokenLab Docs: Handle API errors2026-10-03 tarihinde gözlendi
- TokenLab Docs: Billing and pricing2026-10-03 tarihinde gözlendi
- TokenLab Docs: SDKs & Libraries2026-10-03 tarihinde gözlendi
- TokenLab Docs: Create Chat Completion2026-10-03 tarihinde gözlendi
- TokenLab Docs: List Models2026-10-03 tarihinde gözlendi



