Как создать голосового ассистента с Whisper и GPT
Пошаговое руководство по созданию голосового ассистента на Python — Whisper для распознавания, GPT для ответов, TTS для озвучки.
Голосовые ассистенты перестали быть монополией крупных корпораций. С помощью трёх компонентов — Whisper для распознавания речи, GPT для генерации ответов и TTS для синтеза голоса — можно собрать собственного ассистента за один вечер. Весь пайплайн работает на Python и может использовать как облачные API, так и локальные модели.
Архитектура
Голосовой ассистент — это цепочка из трёх этапов. Первый — STT (speech-to-text): микрофон записывает голос, Whisper превращает аудио в текст. Второй — LLM: текстовый запрос уходит в GPT или другую языковую модель, возвращается текстовый ответ. Третий — TTS (text-to-speech): текст ответа озвучивается синтезатором речи. Подробнее о технологиях распознавания и синтеза — в нашем обзоре голосового ИИ.
Задержка пайплайна складывается из трёх компонентов. На облачных API: Whisper — 1–2 сек, GPT — 1–3 сек, TTS — 0.5–1 сек. Итого 3–6 секунд от конца фразы до начала ответа. Для диалога — приемлемо, хотя и заметно.
Установка зависимостей
pip install openai pyaudio numpy sounddeviceДля записи с микрофона на Linux может потребоваться portaudio: sudo apt install portaudio19-dev. На macOS: brew install portaudio.
Запись голоса с микрофона
Первый шаг — запись аудио. Используем sounddevice с детекцией тишины для автоматической остановки:
import sounddevice as sd
import numpy as np
import wave
import tempfile
def record_audio(silence_threshold=500, silence_duration=1.5, sample_rate=16000):
"""Записывает речь до паузы в silence_duration секунд."""
print("Говорите...")
frames = []
silent_frames = 0
max_silent = int(silence_duration * sample_rate / 1024)
def callback(indata, frame_count, time_info, status):
nonlocal silent_frames
volume = np.abs(indata).mean() * 10000
frames.append(indata.copy())
if volume < silence_threshold:
silent_frames += 1
else:
silent_frames = 0
with sd.InputStream(samplerate=sample_rate, channels=1,
blocksize=1024, callback=callback):
while silent_frames < max_silent or len(frames) < 10:
sd.sleep(100)
audio = np.concatenate(frames)
tmp = tempfile.NamedTemporaryFile(suffix=".wav", delete=False)
with wave.open(tmp.name, "wb") as wf:
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(sample_rate)
wf.writeframes((audio * 32767).astype(np.int16).tobytes())
return tmp.nameРаспознавание через Whisper API
OpenAI предоставляет Whisper API, который распознаёт русскую речь с высокой точностью:
from openai import OpenAI
client = OpenAI()
def transcribe(audio_path):
with open(audio_path, "rb") as f:
result = client.audio.transcriptions.create(
model="whisper-1",
file=f,
language="ru"
)
return result.textСтоимость — $0.006 за минуту аудио. Для локального варианта установите faster-whisper — он работает в 4 раза быстрее оригинального Whisper и не требует GPU для модели small.
Генерация ответа через GPT
Текст от Whisper отправляется в языковую модель. Системный промпт задаёт характер ассистента:
conversation = []
SYSTEM = """Ты — голосовой ассистент. Отвечай кратко — 1-3 предложения.
Твои ответы будут озвучены, поэтому не используй markdown,
списки и специальные символы."""
def get_response(user_text):
conversation.append({"role": "user", "content": user_text})
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "system", "content": SYSTEM}] + conversation[-10:],
max_tokens=150
)
reply = response.choices[0].message.content
conversation.append({"role": "assistant", "content": reply})
return replyУказание max_tokens=150 ограничивает длину ответа — для голосового ассистента важна краткость. Длинные ответы утомительно слушать. Подробнее о настройке промптов — в гайде по промпт-инжинирингу.
Синтез речи через TTS
OpenAI TTS генерирует реалистичную русскую речь:
import subprocess
def speak(text):
response = client.audio.speech.create(
model="tts-1",
voice="nova", # alloy, echo, fable, onyx, nova, shimmer
input=text
)
tmp = tempfile.NamedTemporaryFile(suffix=".mp3", delete=False)
response.stream_to_file(tmp.name)
subprocess.run(["afplay", tmp.name]) # macOS
# subprocess.run(["mpv", tmp.name]) # LinuxГолос nova хорошо работает с русским текстом. Стоимость — $0.015 за 1000 символов (модель tts-1) или $0.030 (tts-1-hd с улучшенным качеством).
Собираем всё вместе
def main():
print("Голосовой ассистент запущен. Ctrl+C для выхода.")
while True:
try:
audio_path = record_audio()
text = transcribe(audio_path)
print(f"Вы: {text}")
if text.strip().lower() in ["стоп", "выход", "пока"]:
speak("До свидания!")
break
reply = get_response(text)
print(f"Ассистент: {reply}")
speak(reply)
except KeyboardInterrupt:
break
if __name__ == "__main__":
main()Локальный вариант без облака
Для полностью локальной работы замените три компонента: Whisper API → faster-whisper (модель small, 460 МБ), GPT → Ollama с Llama 3.1 8B, TTS → piper-tts (офлайн-синтез на русском). Качество будет ниже, но данные не покидают устройство, и не нужна подписка.
Расширения
Базовый ассистент можно развить: добавить распознавание команд («поставь таймер», «включи музыку»), подключить к умному дому через Home Assistant API, интегрировать с календарём и почтой. Каждое расширение — отдельный инструмент в системном промпте, который GPT вызывает по контексту запроса. Принцип работы таких ИИ-агентов мы разбирали отдельно.
Технический стек голосового ассистента
Современный голосовой ассистент на базе LLM состоит из трёх компонентов: распознавание речи (ASR), языковая модель (LLM), синтез речи (TTS). Комбинация Whisper + GPT-4o + ElevenLabs даёт качество, сопоставимое с коммерческими ассистентами, при полном контроле над данными.
Сравнение ASR-движков
| Движок | WER (русский) | Скорость | Цена | Офлайн |
|---|---|---|---|---|
| Whisper Large v3 | ~5% | ~0.5x realtime | $0.006/мин (API) | Да (self-hosted) |
| Whisper Medium (local) | ~8% | ~2x realtime | Бесплатно | Да |
| Google Speech-to-Text | ~4% | Realtime | $0.009/мин | Нет |
| Яндекс SpeechKit | ~4% (RU) | Realtime | ~0.2 ₽/мин | Нет |
| faster-whisper | ~5% | ~4x realtime | Бесплатно | Да |
Оптимизация латентности
Главная проблема pipeline-ассистентов — задержка. Среднее: Whisper ~500мс + LLM ~800мс + TTS ~300мс = ~1.6 сек до первого звука. Методы снижения:
- Streaming TTS — начинать синтез сразу после первых токенов LLM
- Whisper Turbo — модель tiny/base для ~150мс ASR
- GPT-4o Realtime API — нативный voice-to-voice без цепочки, latency ~300мс
- VAD (Voice Activity Detection) — обрабатывать аудио только когда говорит пользователь
Self-hosted стек для конфиденциальности
Для обработки чувствительных данных: faster-whisper (локальный ASR) + Ollama + Llama 3.1 (локальный LLM) + Silero TTS (локальный TTS). Данные не покидают устройство. Производительность на M2 MacBook Pro: ~2 секунды полного цикла.
Готовые open-source проекты
Home Assistant + Whisper — для умного дома: wake word detection, локальный ASR, локальный LLM, управление устройствами. Полностью офлайн.
LocalAI — единый сервер для LLM, ASR, TTS с OpenAI-совместимым API. Позволяет заменить OpenAI API локальными моделями без изменения кода приложения.
Livekit Agents — фреймворк для production голосовых агентов: pipeline из ASR + LLM + TTS, WebRTC транспорт, масштабирование.