🎙️

Własna Alexa offline na Raspberry Pi – asystent głosowy AI bez internetu

📅 6 maja 2026 ⏱ 18 min czytania 🏷️ Raspberry Pi 👁 3 odsłon
← Raspberry Pi

Dlaczego własny asystent?

Alexa słucha 24/7 i wysyła nagrania na serwery Amazon. Google Home robi to samo dla Alphabet. Każde Twoje „OK Google" trafia do chmury, jest analizowane, profilowane i może być odsłuchane przez pracowników.

Rozwiązanie: własny asystent głosowy działający całkowicie offline, na Raspberry Pi 4, który rozumie polecenia i odpowiada naturalnym głosem – bez żadnego połączenia z internetem.

🔒 Stos technologiczny (100% open source):
openWakeWord → Whisper STT → Ollama LLM → Piper TTS

Wymagany sprzęt

ElementRekomendacjaCena
KomputerRaspberry Pi 4 8 GB RAM (min. 4 GB)~420 zł
Karta pamięcimicroSD 32 GB lub SSD USB 3.0~50 zł
MikrofonMikrofon USB (np. Fifine K053 lub ReSpeaker 2-Mic HAT)~50–130 zł
GłośnikAktywny głośnik 3.5 mm lub Bluetooth~30–80 zł
ZasilaczPi 4 USB-C 3A~60 zł

Łącznie: ok. 610–740 zł jednorazowo (brak abonamentów).

1. System bazowy

# Raspberry Pi OS Lite (64-bit) – zalecane
# Po flashowaniu i SSH:
sudo apt update && sudo apt upgrade -y
sudo apt install -y python3-pip python3-venv portaudio19-dev \
     alsa-utils ffmpeg git libffi-dev
# Test mikrofonu
arecord -l          # wyświetl urządzenia
arecord -D plughw:1,0 -f S16_LE -r 16000 -c 1 test.wav
aplay test.wav

2. Ollama – lokalny model językowy

curl -fsSL https://ollama.com/install.sh | sh

# Pobierz lekki model (Llama 3.2:3b – 2.0 GB)
ollama pull llama3.2:3b

# Test modelu
ollama run llama3.2:3b "Odpowiedz krótko po polsku: co to jest Arduino?"
💡 Na Pi 4 z 4 GB RAM użyj modelu tinyllama:1.1b (637 MB). Na Pi 4 z 8 GB możesz wygodnie używać llama3.2:3b.

3. Piper TTS – naturalny głos

cd ~
wget https://github.com/rhasspy/piper/releases/download/2023.11.14-2/piper_arm64.tar.gz
tar xzf piper_arm64.tar.gz

# Pobierz głos polski (Gosia)
mkdir -p ~/piper-voices
wget -P ~/piper-voices \
  https://huggingface.co/rhasspy/piper-voices/resolve/main/pl/pl_PL/gosia/medium/pl_PL-gosia-medium.onnx \
  https://huggingface.co/rhasspy/piper-voices/resolve/main/pl/pl_PL/gosia/medium/pl_PL-gosia-medium.onnx.json

# Test głosu
echo "Cześć, jestem Twoim asystentem." | \
  ./piper/piper --model ~/piper-voices/pl_PL-gosia-medium.onnx --output_file /tmp/test.wav
aplay /tmp/test.wav

4. Whisper – rozpoznawanie mowy

python3 -m venv ~/asystent
source ~/asystent/bin/activate
pip install openai-whisper sounddevice numpy

5. openWakeWord – słowo wywoławcze

pip install openwakeword pyaudio

6. Główny skrypt asystenta

cat > ~/asystent/asystent.py << 'EOF'
import io, os, subprocess, tempfile, time, threading
import numpy as np
import sounddevice as sd
import whisper
import requests
from openwakeword.model import Model

# ── Konfiguracja ──────────────────────────────────────────
WAKE_WORD_MODEL = "hey_mycroft"   # najbliższe "Hej Komputer"
WHISPER_MODEL   = "small"         # tiny/base/small/medium
OLLAMA_MODEL    = "llama3.2:3b"
PIPER_BIN       = os.path.expanduser("~/piper/piper")
PIPER_MODEL     = os.path.expanduser("~/piper-voices/pl_PL-gosia-medium.onnx")
SAMPLE_RATE     = 16000
CHUNK           = 1280            # 80 ms przy 16 kHz

# System prompt po polsku
SYSTEM_PROMPT = """Jesteś pomocnym asystentem domowym.
Odpowiadaj KRÓTKO (1-3 zdania), po polsku.
Nie używaj emoji ani markdown."""

# ── Inicjalizacja ─────────────────────────────────────────
print("Ładuję modele…")
oww    = Model(wakeword_models=[WAKE_WORD_MODEL], inference_framework="onnx")
asr    = whisper.load_model(WHISPER_MODEL)
print("Gotowy! Powiedz 'Hej Mycroft' aby aktywować.")

def nagraj_polecenie(sek=5) -> np.ndarray:
    """Nagrywa audio przez 'sek' sekund po aktywacji."""
    print("🎙 Słucham…")
    audio = sd.rec(int(sek * SAMPLE_RATE), samplerate=SAMPLE_RATE,
                   channels=1, dtype="float32")
    sd.wait()
    return audio.flatten()

def transkrybuj(audio: np.ndarray) -> str:
    wynik = asr.transcribe(audio, language="pl", fp16=False)
    return wynik["text"].strip()

def zapytaj_llm(tekst: str) -> str:
    r = requests.post("http://localhost:11434/api/generate", json={
        "model": OLLAMA_MODEL,
        "prompt": tekst,
        "system": SYSTEM_PROMPT,
        "stream": False,
    }, timeout=60)
    return r.json().get("response", "Przepraszam, nie rozumiem.").strip()

def synteza_i_odtwarzanie(tekst: str):
    with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as f:
        wav_path = f.name
    subprocess.run([PIPER_BIN, "--model", PIPER_MODEL,
                    "--output_file", wav_path],
                   input=tekst.encode(), capture_output=True)
    subprocess.run(["aplay", "-q", wav_path])
    os.unlink(wav_path)

# ── Główna pętla ──────────────────────────────────────────
buffer = np.zeros(CHUNK * 30, dtype=np.float32)

def callback(indata, frames, time_info, status):
    global buffer
    buffer = np.roll(buffer, -frames)
    buffer[-frames:] = indata[:, 0]
    prediction = oww.predict(buffer[-CHUNK:])
    if prediction.get(WAKE_WORD_MODEL, 0) > 0.5:
        threading.Thread(target=obsluz_polecenie, daemon=True).start()

aktywny = False
def obsluz_polecenie():
    global aktywny
    if aktywny:
        return
    aktywny = True
    synteza_i_odtwarzanie("Słucham.")
    audio   = nagraj_polecenie(5)
    pytanie = transkrybuj(audio)
    print(f"Pytanie: {pytanie}")
    if pytanie:
        odpowiedz = zapytaj_llm(pytanie)
        print(f"Odpowiedź: {odpowiedz}")
        synteza_i_odtwarzanie(odpowiedz)
    aktywny = False

with sd.InputStream(callback=callback, channels=1, samplerate=SAMPLE_RATE,
                    blocksize=CHUNK, dtype="float32"):
    while True:
        time.sleep(0.1)
EOF
source ~/asystent/bin/activate
python ~/asystent/asystent.py

Autostart po uruchomieniu Pi

sudo nano /etc/systemd/system/asystent.service
[Unit]
Description=Asystent głosowy AI
After=network.target ollama.service

[Service]
User=pi
WorkingDirectory=/home/pi
ExecStart=/home/pi/asystent/bin/python /home/pi/asystent/asystent.py
Restart=always
RestartSec=5
Environment=PYTHONUNBUFFERED=1

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable asystent
sudo systemctl start asystent
sudo journalctl -u asystent -f   # podgląd logów

Wydajność na Raspberry Pi 4

EtapPi 4 (4 GB)Pi 4 (8 GB)Pi 5 (8 GB)
Wake word (latencja)<100 ms<100 ms<100 ms
Whisper small (5 sek.)~8 sek.~8 sek.~4 sek.
Ollama tinyllama (odpowiedź)~6 sek.~4 sek.~2 sek.
Piper TTS<1 sek.<1 sek.<0.5 sek.
Łączny czas odpowiedzi~15 sek.~13 sek.~7 sek.
⚡ Używaj modelu whisper tiny zamiast small aby skrócić transkrypcję o połowę kosztem niewielkiej dokładności.

Dostosowania i pomysły na rozbudowę

Ten projekt kosztuje jednorazowo ~650 zł i zapewnia pełną prywatność. Żaden gigant technologiczny nie dowie się, co pytasz swojego asystenta.

Tagi: ai asystent głosowy lokalna AI Ollama Python raspberry-pi TTS wake word Whisper