Entegrasyon rehberi
Konuşmayı yazıya çevirin, metin üretin ve klonlanmış seslerle konuşma sentezleyin. Tüm yüzeylerde aynı API anahtarını ve yalnızca Rakita model adlarını kullanın.
Kimlik doğrulama
REST/SSE isteklerinde Bearer header kullanın. Node.js WebSocket istemcileri aynı header’ı gönderebilir. Tarayıcı WebSocket istemcileri ise `rakita` ve API anahtarını alt protokoller olarak iletir; sunucu yalnızca `rakita` protokolünü geri seçer.
Authorization: Bearer rk_live_••••••••••••Anahtarı istemci paketine veya herkese açık kaynak koda gömmeyin. Web uygulamalarında mümkünse bağlantıyı kendi sunucunuzdan kurun.
Hangi streaming biçimi?
STTWebSocketİkili ses gönderin; geçici ve final token olayları alın.
LLMSSE veya WebSocketOpenAI uyumlu SSE ya da JSON WebSocket parçaları kullanın.
TTSSSE veya WebSocketSSE’de base64, WebSocket’te doğrudan binary ses alın.
rakita-stt
İlk mesaj oturum yapılandırmasıdır. Sonraki binary frame’ler ses parçasıdır. {"type":"finalize"} bekleyen tokenları finalleştirir. Otomatik bitiş algılama açıktır ve konuşmacının sözünü tamamladığı an final bir <end> tokenı gönderilir. Kullanım socket’in açık kaldığı süre üzerinden ölçülür.
Dil Türkçe, ses biçimi WAV ve kanal sayısı mono olarak sunucu tarafından sabitlenir. Konuşmacı ayrıştırma kapalıdır; bu seçenekler istemci tarafından değiştirilemez.
/v1/realtime/transcriptionsimport fs from "node:fs";
import WebSocket from "ws";
const ws = new WebSocket(
"wss://rakitaapi.ceyberdigital.com/v1/realtime/transcriptions",
{ headers: { Authorization: `Bearer ${process.env.RAKITA_API_KEY}` } }
);
ws.on("open", () => {
ws.send(JSON.stringify({
model: "rakita-stt",
terms: ["CeyberDigital", "Rakita", "KVKK"]
}));
const audio = fs.createReadStream("ornek.wav", { highWaterMark: 3200 });
audio.on("data", chunk => ws.send(chunk));
audio.on("end", () => ws.send(JSON.stringify({ type: "finalize" })));
});
ws.on("message", raw => {
const event = JSON.parse(raw.toString());
if (event.tokens) {
const text = event.tokens
.filter(token => !token.text.startsWith("<"))
.map(token => token.text)
.join("");
console.log(event.tokens.some(token => !token.is_final) ? "geçici" : "final", text);
if (event.tokens.some(token => token.is_final && token.text === "<end>")) {
console.log("Konuşmacı sözünü tamamladı");
}
// finalize oturumu kapatmaz. Tek seferlik kullanımda <fin>
// final tokenı geldikten sonra bağlantıyı normal biçimde kapatın.
if (event.tokens.some(token => token.is_final && token.text === "<fin>")) {
ws.close(1000);
}
}
});Oturum yapılandırması
modelgereklirakita-stt
termsisteğe bağlıBeklenen marka, kişi, ürün veya teknik terimler. En fazla 100 terim; her terim en fazla 100, toplam en fazla 5000 karakter.
{
"model": "rakita-stt",
"terms": ["CeyberDigital", "Rakita", "KVKK"]
}Yanıt olayları
`tokens[].text` metni, `tokens[].is_final` kesinleşme durumunu, `final_audio_proc_ms` ise işlenen final ses süresini bildirir. Final <end> tokenı otomatik olarak algılanan konuşma sırası bitişidir ve LLM çağrısını tetiklemek için kullanılabilir. `finalize` yalnızca bekleyen tokenları kesinleştirir ve bağlantıyı açık tutar. Tek seferlik kullanımda final <fin> tokenından sonra socket’i `1000` koduyla kapatın.
rakita-llm
Chat completions gövdesi OpenAI istemci biçimiyle uyumludur. `stream:false` tek JSON, `stream:true` SSE döndürür. Giriş ve çıkış tokenları ayrı ölçülür. Yalnızca nihai yanıt içeriği ve varsa tool-call alanları sunulur; thinking/reasoning alanları JSON, SSE veya WebSocket yanıtlarına dahil edilmez.
/v1/chat/completionsconst response = await fetch(
"https://rakitaapi.ceyberdigital.com/v1/chat/completions",
{
method: "POST",
headers: {
Authorization: `Bearer ${RAKITA_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "rakita-llm",
messages: [{ role: "user", content: "Üç maddelik bir özet yaz." }],
stream: true,
temperature: 0.4
})
}
);
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const events = buffer.split("\n\n");
buffer = events.pop() ?? "";
for (const event of events) {
const data = event.split("\n")
.find(line => line.startsWith("data:"))?.slice(5).trim();
if (!data || data === "[DONE]") continue;
const chunk = JSON.parse(data);
process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "");
}
}LLM WebSocket
/v1/realtime/chatconst ws = new WebSocket(
"wss://rakitaapi.ceyberdigital.com/v1/realtime/chat",
["rakita", RAKITA_API_KEY]
);
ws.onmessage = event => {
const message = JSON.parse(event.data);
if (message.type === "session.ready") {
ws.send(JSON.stringify({
type: "response.create",
model: "rakita-llm",
messages: [{ role: "user", content: "Merhaba!" }],
temperature: 0.5
}));
}
if (message.type === "response.chunk") {
const text = message.data.choices?.[0]?.delta?.content;
if (text) console.log(text);
}
};Olay sırası `session.ready` → `response.start` → `response.chunk` → `response.done` şeklindedir. Aynı bağlantıda yanıt tamamlandıktan sonra yeni istek gönderebilirsiniz.
rakita-tts
Varsayılan sesi veya hesabınıza yüklediğiniz `voice_...` kimliğini kullanın. Kullanım NFC-normalize Unicode karakter sayısına göre ölçülür.
/v1/audio/speechcurl https://rakitaapi.ceyberdigital.com/v1/audio/speech \
-H "Authorization: Bearer $RAKITA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "rakita-tts",
"input": "Siparişiniz hazır. İyi günlerde kullanın.",
"voice": "voice_xxxxxxxxx",
"response_format": "wav",
"stream": false
}' --output yanit.wavSSE ses akışı
const response = await fetch(
"https://rakitaapi.ceyberdigital.com/v1/audio/speech",
{
method: "POST",
headers: {
Authorization: `Bearer ${RAKITA_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "rakita-tts",
input: "Bu ses parça parça iletilir.",
voice: "rakita-default",
response_format: "pcm",
speed: 1,
stream: true
})
}
);
// text/event-stream içindeki speech.audio.delta olaylarında
// audio alanı base64 kodlu PCM ses parçasıdır.
// speech.audio.done olayı akışın tamamlandığını bildirir.Streaming isteklerinde `response_format` yalnızca `pcm`, `speed` ise `1` olmalıdır. Tek dosyalık yanıtta WAV, MP3 veya PCM seçebilirsiniz.
TTS WebSocket
/v1/realtime/speechconst ws = new WebSocket(
"wss://rakitaapi.ceyberdigital.com/v1/realtime/speech",
["rakita", RAKITA_API_KEY]
);
ws.binaryType = "arraybuffer";
const audioChunks = [];
ws.onmessage = event => {
if (event.data instanceof ArrayBuffer) {
audioChunks.push(event.data); // PCM binary ses parçası
return;
}
const message = JSON.parse(event.data);
if (message.type === "session.ready") {
ws.send(JSON.stringify({
type: "session.config",
model: "rakita-tts",
voice: "voice_xxxxxxxxx",
response_format: "pcm"
}));
ws.send(JSON.stringify({ type: "input.text", text: "Merhaba, " }));
ws.send(JSON.stringify({ type: "input.text", text: "size nasıl yardımcı olabilirim?" }));
ws.send(JSON.stringify({ type: "input.done" }));
}
if (message.type === "audio.done") console.log("Ses tamamlandı");
};Metni birden fazla `input.text` mesajıyla ekleyin ve `input.done` ile üretimi başlatın. `audio.start` sonrasında binary frame’ler, sonunda `audio.done` gelir.
Ses klonlama
WAV, MP3, M4A, OGG veya WebM referans kaydı yükleyin. En fazla 15 MB kabul edilir. Referans metnini vermek devamlılık ve telaffuz kalitesini artırır. Yalnızca kullanma yetkiniz olan sesleri yükleyin ve `consent=true` gönderin.
/v1/voicescurl https://rakitaapi.ceyberdigital.com/v1/voices \
-H "Authorization: Bearer $RAKITA_API_KEY" \
-F "name=Marka Sesi" \
-F "consent=true" \
-F "reference_text=Merhaba, bugün size nasıl yardımcı olabilirim?" \
-F "sample=@ornek.wav"GET /v1/voiceslisteleVarsayılan ve özel ses kimliklerini döndürür.
DELETE /v1/voices/:idsilYalnızca aynı çalışma alanına ait özel sesi siler.
Hatalar ve istek kimliği
REST hataları kararlı bir `code`, güvenli mesaj ve `request_id` döndürür. Aynı kimlik `x-request-id` header’ında bulunur. WebSocket hataları `type:error` olayıyla aynı alanları taşır.
{
"error": {
"code": "invalid_api_key",
"message": "API anahtarı geçersiz veya etkin değil.",
"request_id": "01J..."
}
}