0Pricing
AI Agents · Ders

Sesli Aracılar İçin Gecikme İyileştirmesi

Akış TTS'si, yanıtı parçalara bölme ve ilk sözcük gecikmesini en aza indirme.

Sesli Aracılar İçin Gecikme İyileştirmesi, CoddyKit'te ücretsiz bir AI Agents dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, AI Agents öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. AI Agents kursu toplamda 4 dersten oluşur.

Ses İçin Gecikme Neden Önemlidir

Metin sohbetinde 3 saniyelik bir gecikme kabul edilebilir. Sesli konuşmada 1,5 saniyenin üzerindeki her gecikme doğal olmayan bir his verir ve konuşma akışını bozar.

Ses gecikmesinin üç ana bileşeni vardır: yazıya dökme süresi (STT), LLM işleme süresi (TTFT + üretim) ve TTS sentezleme süresi. Her birini optimize etmek, birleşerek kullanıcı deneyimini büyük ölçüde iyileştirir.

Gecikme Bütçesini Ölçme

Optimizasyondan önce her bileşeni ölçün. Zamanın gerçekten nerede harcandığını görmek için döngüye zamanlama çağrıları ekleyin.

import time

def voice_loop_timed():
    timing = {}

    # 1. Record
    t0 = time.perf_counter()
    audio, sr = record_until_silence()
    timing['record'] = time.perf_counter() - t0

    # 2. Transcribe
    t0 = time.perf_counter()
    audio_path = audio_to_file(audio, sr)
    user_text = transcribe_file(audio_path)
    timing['transcription'] = time.perf_counter() - t0

    # 3. LLM
    t0 = time.perf_counter()
    agent_text = agent.respond(user_text)
    timing['llm'] = time.perf_counter() - t0

    # 4. TTS
    t0 = time.perf_counter()
    say(agent_text)
    timing['tts'] = time.perf_counter() - t0

    print('Latency breakdown:')
    total = sum(timing.values())
    for step, duration in timing.items():
        print(f'  {step:15} {duration*1000:.0f}ms ({duration/total*100:.0f}%)')

TTS Akışı: Üretim Sırasında Oynatma

En büyük tekil gecikme kazanımı TTS akışından gelir. Tüm sesin sentezlenmesini beklemek yerine, geri kalanı eşzamanlı olarak oluşturulurken ilk ses parçasını yaklaşık 200 ms içinde oynatmaya başlayın.

import threading
import queue
import sounddevice as sd
import numpy as np
import io

def stream_tts_and_play(text, voice='nova'):
    audio_queue = queue.Queue()

    def synthesize():
        from openai import OpenAI
        import os
        client = OpenAI(api_key=os.getenv('OPENAI_API_KEY'))
        with client.audio.speech.with_streaming_response.create(
            model='tts-1', voice=voice, input=text
        ) as response:
            for chunk in response.iter_bytes(chunk_size=4096):
                audio_queue.put(chunk)
        audio_queue.put(None)  # sentinel

    synth_thread = threading.Thread(target=synthesize, daemon=True)
    synth_thread.start()

    # Collect and play (buffering first 2 chunks for smooth start)
    audio_buffer = b''
    min_buffer = 8192
    import pygame
    pygame.mixer.init()

    while True:
        chunk = audio_queue.get()
        if chunk is None:
            break
        audio_buffer += chunk
        if len(audio_buffer) >= min_buffer:
            # play buffer ...
            pass  # simplified — real impl streams to sounddevice

    synth_thread.join()

Cümle Cümle TTS Akışı

En pratik akış yaklaşımı, LLM yanıtını cümlelere bölüp bunları tek tek sentezlemek ve oynatmaktır. İlk cümle yaklaşık 300 ms içinde oynatılmaya başlar.

import re
import concurrent.futures

def split_sentences(text):
    return [s.strip() for s in re.split(r'(?<=[.!?])\s+', text) if s.strip()]

def tts_and_play_streaming(text, voice='nova'):
    sentences = split_sentences(text)
    if not sentences:
        return

    # Prefetch next sentence while current is playing
    executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)

    # Kick off synthesis of first sentence
    futures = []
    for sentence in sentences:
        futures.append(executor.submit(cached_tts, sentence, voice))

    # Play each sentence as soon as it's ready
    for future in futures:
        audio_path = future.result(timeout=10)
        play_audio_file(audio_path)

    executor.shutdown(wait=False)

# Key insight: while sentence 1 plays (~2 seconds), sentence 2 is being synthesized in parallel

TTFT: İlk Belirtece Kadar Süreyi Optimize Etme

TTFT (İlk Belirtece Kadar Süre), LLM isteğinin gönderilmesiyle yanıtın ilk belirtecinin alınması arasındaki gecikmedir. TTFT'yi optimize etmek, kullanıcıların yanıtın başlangıcını daha erken duymasını sağlar.

Akışlı LLM yanıtlarını kullanın ve bir cümle sınırı algılanır algılanmaz belirteçleri TTS'ye aktarın.

import openai
import os

client = openai.OpenAI(api_key=os.getenv('OPENAI_API_KEY'))

def stream_llm_to_tts(user_text, conversation_history, voice='nova'):
    buffer = ''

    stream = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=conversation_history + [{'role': 'user', 'content': user_text}],
        stream=True  # streaming enabled
    )

    for chunk in stream:
        delta = chunk.choices[0].delta.content or ''
        buffer += delta

        # Check if a sentence is complete
        if buffer.endswith(('.', '!', '?')) and len(buffer) > 20:
            sentence = buffer.strip()
            print(f'Queuing TTS: {sentence[:50]}')
            # Synthesize and play immediately (non-blocking)
            audio_path = cached_tts(sentence, voice)
            play_audio_file(audio_path)
            buffer = ''

    # Flush remaining buffer
    if buffer.strip():
        audio_path = cached_tts(buffer.strip(), voice)
        play_audio_file(audio_path)

Yaygın Yanıtları Önceden Üretme

Bazı ajan yanıtları öngörülebilirdir: karşılama ifadeleri, hata iletileri ve düşünme göstergeleri ("Bunu sizin için kontrol edeyim."). Bunların seslerini başlangıçta önceden üretin; böylece sıfır gecikmeyle oynatılabilirler.

import os

PRE_GENERATED = {
    'greeting':      'Hello! How can I help you today?',
    'thinking':      'Let me look that up for you.',
    'not_found':     'I could not find information on that. Could you rephrase?',
    'error':         'Sorry, something went wrong. Please try again.',
    'goodbye':       'Goodbye! Have a great day.',
    'clarify':       'Could you give me a bit more detail?',
    'working_on_it': 'Working on it, this may take a moment.'
}

pre_gen_cache = {}

def prewarm_responses(voice='nova'):
    for key, text in PRE_GENERATED.items():
        audio_path = cached_tts(text, voice=voice)
        pre_gen_cache[key] = audio_path
    print(f'Pre-generated {len(pre_gen_cache)} common responses')

def instant_response(key):
    path = pre_gen_cache.get(key)
    if path:
        play_audio_file(path)
    else:
        say(PRE_GENERATED.get(key, ''))

# Usage: while LLM is thinking, play a stall message instantly
instant_response('thinking')

Yerel TTS ile Bulut TTS Gecikmesi Karşılaştırması

Bulut TTS, ağa gidiş-dönüş süresi ekler (yaklaşık 100-300 ms). Kısa yanıtlar veya sık kullanılan ifadeler için yerel bir TTS altyapısı daha hızlı olabilir; ancak ses kalitesi düşebilir.

pyttsx3, Python için en basit çevrimdışı TTS seçeneğidir.

import pyttsx3
import time

# Local TTS with pyttsx3
def local_tts(text, voice_index=0, rate=175):
    engine = pyttsx3.init()
    voices = engine.getProperty('voices')
    if voice_index < len(voices):
        engine.setProperty('voice', voices[voice_index].id)
    engine.setProperty('rate', rate)  # words per minute
    t0 = time.perf_counter()
    engine.say(text)
    engine.runAndWait()
    print(f'Local TTS latency: {(time.perf_counter()-t0)*1000:.0f}ms')

# Comparison (rough benchmarks):
# pyttsx3 (local):     ~50ms start, robotic quality
# OpenAI TTS-1:        ~200-400ms, good quality
# ElevenLabs turbo:    ~150-250ms, excellent quality
# OpenAI TTS-1-hd:     ~400-800ms, best quality

# Recommendation:
# Real-time voice agent -> OpenAI TTS-1 or ElevenLabs turbo
# Quality recording     -> OpenAI TTS-1-hd or ElevenLabs standard

Daha Hızlı Bir LLM Modeli Seçme

Model seçimi TTFT'yi büyük ölçüde etkiler. GPT-4o-mini, çoğu ses ajanı görevinde GPT-4o'dan 5-10 kat daha hızlıdır. Kalite gereksinimlerini karşılayan en küçük modeli kullanın.

# Model latency comparison (rough benchmarks for voice agent use case):
MODEL_BENCHMARKS = {
    'gpt-4o-mini':   {'ttft_ms': 300,  'quality': 'good',      'cost': 'very low'},
    'gpt-4o':        {'ttft_ms': 800,  'quality': 'excellent',  'cost': 'medium'},
    'claude-haiku':  {'ttft_ms': 250,  'quality': 'good',       'cost': 'very low'},
    'claude-sonnet': {'ttft_ms': 600,  'quality': 'excellent',  'cost': 'medium'},
    'llama3-8b':     {'ttft_ms': 100,  'quality': 'decent',     'cost': 'free (local)'},
}

# Strategy: use fast model for simple factual queries,
# fall back to powerful model for complex reasoning
def select_model(question):
    # Short, simple questions -> fast model
    if len(question.split()) < 15:
        return 'gpt-4o-mini'
    # Complex, multi-step -> better model
    if any(kw in question.lower() for kw in ['analyze', 'compare', 'explain why', 'write a']):
        return 'gpt-4o'
    return 'gpt-4o-mini'

if __name__ == '__main__':
    for q in ['What time is it in Tokyo?', 'Analyze why sales dropped last quarter and compare to competitors']:
        print(f'{select_model(q)!r} chosen for: "{q}"')

Tekrarlanan Sorular için Yanıtları Önbelleğe Alma

Kullanıcılar genellikle aynı veya benzer soruları tekrar tekrar sorar. Tekrarlanan sorulara anında yanıt verebilmek için aynı sorgulara ait LLM + TTS yanıtlarını önbelleğe alın.

import hashlib
import json

RESPONSE_CACHE = {}  # in production: use Redis with TTL

def get_cache_key(user_text):
    # Normalize: lowercase, strip punctuation
    import re
    normalized = re.sub(r'[^a-z0-9 ]', '', user_text.lower()).strip()
    return hashlib.md5(normalized.encode()).hexdigest()

def cached_agent_respond(user_text, voice='nova'):
    key = get_cache_key(user_text)

    if key in RESPONSE_CACHE:
        print('Response cache hit!')
        entry = RESPONSE_CACHE[key]
        play_audio_file(entry['audio_path'])
        return entry['text']

    # Cache miss
    text = agent.respond(user_text)
    audio_path = cached_tts(text, voice=voice)

    RESPONSE_CACHE[key] = {'text': text, 'audio_path': audio_path}
    play_audio_file(audio_path)
    return text

Uçtan Uca Gecikme Hedefi

Tüm optimizasyonlar uygulandığında, iyi tasarlanmış bir sesli ajan, kullanıcının konuşmasını bitirmesinden ajanın yanıt vermeye başlamasına kadar geçen süreyi 1 saniyenin altında tutmalıdır.

# Target latency budget breakdown (1000ms total):

LATENCY_BUDGET = {
    'silence_detection_end':   0,    # user stops speaking
    'audio_processing':        50,   # RMS check, noise gate
    'transcription_whisper':   400,  # STT API call
    'llm_ttft':                300,  # time to first token (gpt-4o-mini)
    'tts_first_sentence':      200,  # first sentence synthesized
    'playback_start':          1000  # TOTAL: user hears response within 1 second
}

# Optimizations applied:
# - Streaming LLM responses (saves 200-500ms vs waiting for full response)
# - Sentence-by-sentence TTS (play while rest generates)
# - gpt-4o-mini instead of gpt-4o (saves 500ms TTFT)
# - TTS cache for common phrases (saves 200ms on cached phrases)
# - Pre-generated stall messages ('Let me check...' plays instantly)

print('Target: < 1000ms from speech end to first audio byte played')
print('Typical with optimizations: 600-900ms')

Eşzamansız Metne Dönüştürme Çakışması

Ajan yanıtını oluşturup seslendirirken bir sonraki kullanıcı girdisini kaydetmeye hemen başlayın. İşlem hattı aşamalarını üst üste yürütmek, konuşma turları arasındaki boşta geçen süreyi azaltır.

import threading
import time

class PipelineOverlapAgent:
    def __init__(self):
        self.next_audio = None
        self.recording_thread = None

    def start_background_recording(self):
        def record():
            self.next_audio = record_until_silence()
        self.recording_thread = threading.Thread(target=record, daemon=True)
        self.recording_thread.start()

    def get_recorded_audio(self, timeout=30):
        if self.recording_thread:
            self.recording_thread.join(timeout=timeout)
        audio = self.next_audio
        self.next_audio = None
        return audio

    def conversation_turn(self, audio, sr):
        # Transcribe and run agent
        text = transcribe_file(audio_to_file(audio, sr))
        if not text.strip():
            return

        # Start recording NEXT turn BEFORE speaking
        # (user can start speaking as soon as agent starts)
        response = agent.respond(text)

        # Start next recording while speaking
        self.start_background_recording()

        # Speak current response
        speak_with_interrupt(response)

        # Next audio is already being captured in background
        return self.get_recorded_audio()

Bilgi Kontrolü

Sesli ajanlarda genellikle en büyük gecikme azalmasını hangi tek optimizasyon sağlar?

Özet: Sesli Ajanlar için Gecikme Optimizasyonu

Ses gecikmesi optimizasyonu katmanları: LLM yanıtlarını akış halinde alma (belirteçler geldikçe cümle sınırlarında TTS'yi başlatma), cümle cümle TTS oynatma (sentezleme sürerken oynatma), TTS önbelleğe alma (tekrarlanan ifadeleri anında yeniden oynatma), yaygın yanıtları önceden oluşturma (selamlamalar, zaman kazandıran ifadeler) ve hızlı LLM modeli seçimi (basit sorgular için gpt-4o-mini).

Hedef: Kullanıcının konuşmasını bitirmesinden ilk ses baytına kadar 1 saniyenin altında bir süre. Her bileşeni ölçün — yazıya dönüştürme, toplam gecikmenin çoğu zaman %40'ını oluşturur. Yerel TTS, hız karşılığında kaliteden ödün verir; cümleleri akış halinde sunan bulut TTS, çoğu ajan için daha iyi bir dengedir.

Sıkça Sorulan Sorular

“Sesli Aracılar İçin Gecikme İyileştirmesi” dersi ücretsiz mi?

Evet — “Sesli Aracılar İçin Gecikme İyileştirmesi” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve AI Agents kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. AI Agents kursu toplamda 4 dersten oluşur.

“Sesli Aracılar İçin Gecikme İyileştirmesi” dersinde ne öğreneceğim?

Akış TTS'si, yanıtı parçalara bölme ve ilk sözcük gecikmesini en aza indirme. AI Agents ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

AI Agents öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te AI Agents, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.

“Sesli Aracılar İçin Gecikme İyileştirmesi” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu AI Agents dersinde kod yazıp çalıştırabilir miyim?

Evet. Her AI Agents dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Whisper ve Deepgram ile Konuşmadan Metne
  2. Aracı Yanıtlarında Metinden Sese
  3. Sesli Konuşma Döngüsü Oluşturma
  4. Sesli Aracılar İçin Gecikme İyileştirmesi
← AI Agents Sayfasına Dön