diff --git a/README.md b/README.md
index aa287e2..18a75c4 100644
--- a/README.md
+++ b/README.md
@@ -1,261 +1,83 @@
+# Alexander Smart Speaker
+
-# ποΈ Alexander Smart Speaker
+ΠΠΎΠ»ΠΎΡΠΎΠ²ΠΎΠΉ Π°ΡΡΠΈΡΡΠ΅Π½Ρ Π΄Π»Ρ Linux: wake word, STT/TTS, AI-Π΄ΠΈΠ°Π»ΠΎΠ³ ΠΈ ΠΏΠΎΠ»Π΅Π·Π½ΡΠ΅ Π³ΠΎΠ»ΠΎΡΠΎΠ²ΡΠ΅ Π½Π°Π²ΡΠΊΠΈ.
-**ΠΠΎΠ»ΠΎΡΠΎΠ²ΠΎΠΉ Π°ΡΡΠΈΡΡΠ΅Π½Ρ Π΄Π»Ρ Linux Ρ wake word, STT/TTS ΠΈ Π½Π°Π±ΠΎΡΠΎΠΌ Π³ΠΎΠ»ΠΎΡΠΎΠ²ΡΡ
Π½Π°Π²ΡΠΊΠΎΠ²**
-
-[](https://www.python.org/downloads/)
-[](https://www.linux.org/)
-[](LICENSE.txt)
+[](https://www.python.org/)
+[](https://www.linux.org/)
+[](LICENSE.txt)
+[](https://picovoice.ai/platform/porcupine/)
+[](https://deepgram.com/)
+[](https://github.com/snakers4/silero-models)
-## β¨ ΠΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈ
+## Π§ΡΠΎ ΡΡΠΎ
-| Π€ΡΠ½ΠΊΡΠΈΡ | ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ |
-|--------|----------|
-| π **ΠΠΊΡΠΈΠ²Π°ΡΠΈΡ ΠΏΠΎ ΠΊΠ»ΡΡΠ΅Π²ΠΎΠΌΡ ΡΠ»ΠΎΠ²Ρ** | ΠΠΊΡΠΈΠ²Π°ΡΠΈΡ ΠΏΠΎ ΠΊΠΎΠΌΠ°Π½Π΄Π΅ `Alexandr` |
-| π§ **ΠΠΈΠ°Π»ΠΎΠ³ Ρ AI** | ΠΠ·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ Ρ Perplexity Ρ ΡΠΎΡ
ΡΠ°Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ° |
-| π **ΠΠ΅ΡΠ΅Π²ΠΎΠ΄** | ΠΠ΅ΡΠ΅Π²ΠΎΠ΄ RU β EN Ρ ΠΎΠ·Π²ΡΡΠΈΠ²Π°Π½ΠΈΠ΅ΠΌ |
-| π€οΈ **ΠΠΎΠ³ΠΎΠ΄Π°** | ΠΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎ ΠΏΠΎΠ³ΠΎΠ΄Π΅ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ ΠΈ ΠΏΠΎ Π½Π°Π·Π²Π°Π½ΠΈΡ Π³ΠΎΡΠΎΠ΄Π° |
-| β° **Π’Π°ΠΉΠΌΠ΅ΡΡ ΠΈ Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊΠΈ** | Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΡΠ°ΠΉΠΌΠ΅ΡΠ°ΠΌΠΈ, Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊΠ°ΠΌΠΈ ΠΈ ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅ΡΠ°ΠΌΠΈ |
-| π **Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π³ΡΠΎΠΌΠΊΠΎΡΡΡΡ** | Π Π΅Π³ΡΠ»ΠΈΡΠΎΠ²ΠΊΠ° ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠΉ Π³ΡΠΎΠΌΠΊΠΎΡΡΠΈ |
-| π΅ **Spotify ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ** | Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ΠΌ (play/pause/next/current track) |
-| π **ΠΠ³ΡΠ° Π² Π³ΠΎΡΠΎΠ΄Π°** | ΠΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠ°Ρ ΠΈΠ³ΡΠ° Π² Π³ΠΎΡΠΎΠ΄Π° |
+`Alexander Smart Speaker` ΡΠ»ΡΡΠ°Π΅Ρ ΠΊΠ»ΡΡΠ΅Π²ΠΎΠ΅ ΡΠ»ΠΎΠ²ΠΎ `Alexandr`, ΡΠ°ΡΠΏΠΎΠ·Π½Π°Π΅Ρ ΡΠ΅ΡΡ, ΠΌΠ°ΡΡΡΡΡΠΈΠ·ΠΈΡΡΠ΅Ρ ΠΊΠΎΠΌΠ°Π½Π΄Ρ Π² Π½ΡΠΆΠ½ΡΠΉ ΠΌΠΎΠ΄ΡΠ»Ρ ΠΈ ΠΎΠ·Π²ΡΡΠΈΠ²Π°Π΅Ρ ΠΎΡΠ²Π΅Ρ.
+ΠΡΠΎΠ΅ΠΊΡ ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΠΎΠ²Π°Π½ ΠΏΠΎΠ΄ ΡΡΡΡΠΊΠΈΠΉ ΡΠ·ΡΠΊ, Π½ΠΎ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ RU/EN ΡΡΠ΅Π½Π°ΡΠΈΠΈ (Π²ΠΊΠ»ΡΡΠ°Ρ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄ ΠΈ mixed-language TTS).
-## ποΈ ΠΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ°
+## ΠΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈ
-### ΠΠΈΠ°Π³ΡΠ°ΠΌΠΌΠ° Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²
+- ΠΠΊΡΠΈΠ²Π°ΡΠΈΡ ΠΏΠΎ wake word `Alexandr` (Porcupine).
+- Π Π°ΡΠΏΠΎΠ·Π½Π°Π²Π°Π½ΠΈΠ΅ ΡΠ΅ΡΠΈ ΡΠ΅ΡΠ΅Π· Deepgram (WebSocket, VAD, fast stop).
+- ΠΠ·Π²ΡΡΠΊΠ° ΡΠ΅ΡΠ΅Π· Silero TTS (RU + EN, Ρ ΠΏΡΠ΅ΡΡΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΏΠΎ wake word).
+- AI-Π΄ΠΈΠ°Π»ΠΎΠ³ ΡΠ΅ΡΠ΅Π· Perplexity API ΡΠΎ streaming-ΠΎΡΠ²Π΅ΡΠΎΠΌ ΠΈ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠΎΠΌ.
+- ΠΠ΅ΡΠ΅Π²ΠΎΠ΄ RU -> EN ΠΈ EN -> RU.
+- ΠΠΎΠ³ΠΎΠ΄Π°: ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΏΡΠΎΠ³Π½ΠΎΠ· ΠΏΠΎ Π³ΠΎΡΠΎΠ΄Ρ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ ΠΈΠ»ΠΈ ΠΏΠΎ Π½Π°Π·Π²Π°Π½ΠΈΡ Π³ΠΎΡΠΎΠ΄Π°.
+- Π’Π°ΠΉΠΌΠ΅ΡΡ, Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊΠΈ (Π²ΠΊΠ»ΡΡΠ°Ρ Π±ΡΠ΄Π½ΠΈ/Π²ΡΡ
ΠΎΠ΄Π½ΡΠ΅), ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅ΡΡ.
+- Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π³ΡΠΎΠΌΠΊΠΎΡΡΡΡ ΡΠΈΡΡΠ΅ΠΌΡ (ΡΠ΅ΡΠ΅Π· `pactl`/`amixer`).
+- Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Spotify (play/pause/next/what's playing).
+- ΠΠΈΠ½ΠΈ-ΠΈΠ³ΡΠ° "ΠΠΎΡΠΎΠ΄Π°".
+
+## ΠΠ°ΠΊ ΡΡΠΎ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ
```mermaid
-graph TB
- subgraph "ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΠΈΠΊΠ»"
- A[main() - ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΠΈΠΊΠ»] --> B{Π Π΅ΠΆΠΈΠΌ Π°ΠΊΡΠΈΠ²Π°ΡΠΈΠΈ}
- B -->|ΠΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ wake word| C[wait_for_wakeword()]
- B -->|Π Π΅ΠΆΠΈΠΌ Π΄ΠΈΠ°Π»ΠΎΠ³Π°| D[listen() Π² ΡΠ΅ΠΆΠΈΠΌΠ΅ follow-up]
- C --> E[ΠΡΠΎΡΠ»ΡΡΠΈΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ]
- D --> E
- E --> F[ΠΠ½Π°Π»ΠΈΠ· ΠΊΠΎΠΌΠ°Π½Π΄Ρ]
- end
-
- subgraph "ΠΡΠ΄ΠΈΠΎ ΠΏΠΎΠ΄ΡΠΈΡΡΠ΅ΠΌΠ°"
- C1[wait_for_wakeword()
wakeword.py
check_wakeword_once()]
- E1[listen()
stt.py
get_recognizer()]
- G1[speak()
tts.py
initialize()]
- H1[parse_volume_text()
sound_level.py
set_volume()]
-
- C1 -.-> E1
- E1 -.-> G1
- H1 -.-> G1
- end
-
- subgraph "Π―Π΄ΡΠΎ"
- F1[is_stop_command()
commands.py
_normalize_text()]
- F2[ask_ai_stream()
ai.py
translate_text()]
- F3[clean_response()
cleaner.py]
- F5[get_smalltalk_response()
smalltalk.py]
-
- F --> F1
- F --> F2
- F --> F3
- F --> F5
- end
-
- subgraph "Π€ΡΠ½ΠΊΡΠΈΠΈ"
- I1[get_weather_report()
weather.py]
- I2[get_timer_manager()
timer.py]
- I3[get_alarm_clock()
alarm.py]
- I4[get_stopwatch_manager()
stopwatch.py]
- I5[get_music_controller()
music.py]
- I6[get_cities_game()
cities_game.py]
-
- F --> I1
- F --> I2
- F --> I3
- F --> I4
- F --> I5
- F --> I6
- end
-
- subgraph "ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΊΠΎΠΌΠ°Π½Π΄"
- F --> J{Π’ΠΈΠΏ ΠΊΠΎΠΌΠ°Π½Π΄Ρ}
- J -->|Small talk| K[get_smalltalk_response()]
- J -->|ΠΠΎΠ²ΡΠΎΡ| L[ΠΠΎΠ²ΡΠΎΡ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π³ΠΎ ΠΎΡΠ²Π΅ΡΠ°]
- J -->|Π‘ΡΠΎΠΏ| M[is_stop_command()]
- J -->|Π’Π°ΠΉΠΌΠ΅Ρ| N[parse_command() timer]
- J -->|ΠΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ| O[parse_command() alarm]
- J -->|Π‘Π΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅Ρ| P[parse_command() stopwatch]
- J -->|ΠΡΠΎΠΌΠΊΠΎΡΡΡ| Q[parse_volume_text() + set_volume()]
- J -->|ΠΠΎΠ³ΠΎΠ΄Π°| R[get_weather_report()]
- J -->|ΠΡΠ·ΡΠΊΠ°| S[parse_command() music]
- J -->|ΠΠ΅ΡΠ΅Π²ΠΎΠ΄| T[parse_translation_request()]
- J -->|ΠΠΎΡΠΎΠ΄Π°| U[handle() cities_game]
- J -->|AI| V[ask_ai_stream()]
- end
-
- subgraph "ΠΡΠ²Π΅Ρ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ"
- K --> W[clean_response()]
- L --> W
- M --> W
- N --> W
- O --> W
- P --> W
- Q --> W
- R --> W
- S --> W
- T --> W
- U --> W
- V --> W
-
- W --> X[speak()]
- X --> Y[ΠΠΎΠ·Π²ΡΠ°Ρ Π² ΡΠ΅ΠΆΠΈΠΌ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ]
- Y --> A
- end
-
- %% Connections
- C1 -.-> A
- E1 -.-> F
- G1 -.-> X
- F2 -.-> V
- F3 -.-> W
- I1 -.-> R
- I2 -.-> N
- I3 -.-> O
- I4 -.-> P
- I5 -.-> S
- I6 -.-> U
-
- style A fill:#e1f5fe
- style F fill:#f3e5f5
- style X fill:#e8f5e8
- style Y fill:#fff3e0
-
+flowchart TD
+ A[Wake Word: Alexandr] --> B[STT: Deepgram]
+ B --> C{ΠΠ°ΡΡΡΡΡΠΈΠ·Π°ΡΠΈΡ ΠΊΠΎΠΌΠ°Π½Π΄Ρ}
+ C --> D[Feature modules]
+ C --> E[AI/Translation]
+ D --> F[TTS: Silero]
+ E --> F
+ F --> G[Follow-up ΡΠ΅ΠΆΠΈΠΌ ΠΈΠ»ΠΈ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ wake word]
```
-### ΠΠΈΠ°Π³ΡΠ°ΠΌΠΌΠ° ΠΏΠΎΡΠΎΠΊΠ° ΠΊΠΎΠΌΠ°Π½Π΄ ΠΎΡ wake word Π΄ΠΎ ΡΡΠ½ΠΊΡΠΈΠΉ
+## ΠΡΡΡΡΡΠΉ ΡΡΠ°ΡΡ
-```mermaid
-graph TD
- subgraph "ΠΠΊΡΠΈΠ²Π°ΡΠΈΡ ΠΈ ΡΠ°ΡΠΏΠΎΠ·Π½Π°Π²Π°Π½ΠΈΠ΅"
- A[wait_for_wakeword()
wakeword.py] --> B[listen()
stt.py]
- B --> C[Π Π°ΡΠΏΠΎΠ·Π½Π°Π½Π½ΡΠΉ ΡΠ΅ΠΊΡΡ]
- end
-
- subgraph "ΠΠ½Π°Π»ΠΈΠ· ΠΊΠΎΠΌΠ°Π½Π΄Ρ"
- C --> D{Π’ΠΈΠΏ ΠΊΠΎΠΌΠ°Π½Π΄Ρ}
- end
-
- subgraph "ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ΅ΡΠΊΠΈΡ
ΠΊΠΎΠΌΠ°Π½Π΄"
- D -->|Small talk| E[get_smalltalk_response()
smalltalk.py]
- D -->|Π‘ΡΠΎΠΏ ΠΊΠΎΠΌΠ°Π½Π΄Π°| F[is_stop_command()
commands.py]
- D -->|Π’Π°ΠΉΠΌΠ΅Ρ| G[parse_command()
timer.py]
- D -->|ΠΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ| H[parse_command()
alarm.py]
- D -->|Π‘Π΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅Ρ| I[parse_command()
stopwatch.py]
- D -->|ΠΡΠΎΠΌΠΊΠΎΡΡΡ| J[parse_volume_text()
sound_level.py
set_volume()]
- D -->|ΠΠΎΠ³ΠΎΠ΄Π°| K[get_weather_report()
weather.py]
- D -->|ΠΡΠ·ΡΠΊΠ°| L[parse_command()
music.py]
- D -->|ΠΠ΅ΡΠ΅Π²ΠΎΠ΄| M[parse_translation_request()
ai.py
translate_text()]
- D -->|ΠΠΎΡΠΎΠ΄Π°| N[handle()
cities_game.py]
- D -->|ΠΠ±ΡΡΠ½ΡΠΉ Π²ΠΎΠΏΡΠΎΡ| O[ask_ai_stream()
ai.py]
- end
-
- subgraph "ΠΡΠ²Π΅Ρ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ"
- E --> P[clean_response()
cleaner.py]
- F --> P
- G --> P
- H --> P
- I --> P
- J --> P
- K --> P
- L --> P
- M --> P
- N --> P
- O --> P
- P --> Q[speak()
tts.py]
- end
-
- subgraph "Π¦ΠΈΠΊΠ» ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ"
- Q --> R{ΠΡΠΎΠ΄ΠΎΠ»ΠΆΠΈΡΡ Π΄ΠΈΠ°Π»ΠΎΠ³?}
- R -->|ΠΠ°| S[ΠΡΡΠ°ΡΡΡΡ Π² ΡΠ΅ΠΆΠΈΠΌΠ΅ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ]
- R -->|ΠΠ΅Ρ| T[ΠΠ΄Π°ΡΡ wake word ΡΠ½ΠΎΠ²Π°]
- S --> B
- T --> A
- end
-
-```
-
-## π οΈ Π’Π΅Ρ
Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ
-
-| ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ | Π’Π΅Ρ
Π½ΠΎΠ»ΠΎΠ³ΠΈΡ |
-|-----------|------------|
-| **Wake word** | `pvporcupine` |
-| **STT** | `deepgram-sdk` |
-| **TTS** | `Silero` (`torch`, `torchaudio`) |
-| **AI** | Perplexity API |
-| **ΠΠΎΠ³ΠΎΠ΄Π°** | Open-Meteo |
-| **ΠΡΠ·ΡΠΊΠ°** | Spotify Web API (`spotipy`) |
-
-## π Π’ΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΡ
-
-- **ΠΠ‘**: Linux
-- **Python**: 3.9+
-- **Π‘ΠΈΡΡΠ΅ΠΌΠ½ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ**:
+### 1) Π‘ΠΈΡΡΠ΅ΠΌΠ½ΡΠ΅ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ (Ubuntu/Debian)
```bash
sudo apt-get update
-sudo apt-get install -y portaudio19-dev libasound2-dev mpg123
+sudo apt-get install -y portaudio19-dev libasound2-dev mpg123 pulseaudio-utils alsa-utils
```
-> π‘ ΠΠ»Ρ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ Π³ΡΠΎΠΌΠΊΠΎΡΡΡΡ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌ `pactl` ΠΈΠ»ΠΈ `amixer` (ΠΎΠ±ΡΡΠ½ΠΎ ΠΈΠ· `pulseaudio-utils`/`alsa-utils`).
+### 2) Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ° Python-Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ
-## π Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°
-
-1. **ΠΠ»ΠΎΠ½ΠΈΡΡΠΉΡΠ΅ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΉ**:
```bash
-git clone https://github.com/your-username/alexander_smart-speaker.git
+git clone
cd alexander_smart-speaker
-```
-
-2. **ΠΠ°ΡΡΡΠΎΠΉΡΠ΅ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΠΎΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΠ΅**:
-```bash
-python -m venv venv
-source venv/bin/activate # ΠΈΠ»ΠΈ venv\Scripts\activate Π½Π° Windows
+python3 -m venv venv
+source venv/bin/activate
pip install -r requirements.txt
```
-## βοΈ ΠΠ°ΡΡΡΠΎΠΉΠΊΠ°
+### 3) ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° `.env`
-1. **Π‘ΠΎΠ·Π΄Π°ΠΉΡΠ΅ ΡΠ°ΠΉΠ» ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ**:
```bash
cp .env.example .env
```
-2. **ΠΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΡΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ**:
+ΠΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΠΎ ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΡΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅:
```ini
-PERPLEXITY_API_KEY=your_perplexity_api_key_here
-DEEPGRAM_API_KEY=your_deepgram_api_key_here
-PORCUPINE_ACCESS_KEY=your_porcupine_access_key_here
+PERPLEXITY_API_KEY=...
+DEEPGRAM_API_KEY=...
+PORCUPINE_ACCESS_KEY=...
```
-3. **ΠΠΎΠ»Π½Π°Ρ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ** (ΠΊΠ°ΠΊ Π² `.env.example`):
-
-```ini
-PERPLEXITY_API_KEY=your_perplexity_api_key_here
-PERPLEXITY_MODEL=llama-3.1-sonar-small-128k-chat
-DEEPGRAM_API_KEY=your_deepgram_api_key_here
-PORCUPINE_ACCESS_KEY=your_porcupine_access_key_here
-PORCUPINE_SENSITIVITY=0.8
-TTS_EN_SPEAKER=en_0
-WEATHER_LAT=63.56
-WEATHER_LON=53.69
-WEATHER_CITY=Π£Ρ
ΡΠ°
-SPOTIFY_CLIENT_ID=your_spotify_client_id
-SPOTIFY_CLIENT_SECRET=your_spotify_client_secret
-SPOTIFY_REDIRECT_URI=http://localhost:8888/callback
-```
-
-## βΆοΈ ΠΠ°ΠΏΡΡΠΊ
+### 4) ΠΠ°ΠΏΡΡΠΊ
```bash
make run
@@ -263,62 +85,76 @@ make run
python run.py
```
-## π£οΈ ΠΡΠΈΠΌΠ΅ΡΡ Π³ΠΎΠ»ΠΎΡΠΎΠ²ΡΡ
ΠΊΠΎΠΌΠ°Π½Π΄
+ΠΠΎΡΠ»Π΅ Π·Π°ΠΏΡΡΠΊΠ° Π°ΡΡΠΈΡΡΠ΅Π½Ρ ΠΏΠ΅ΡΠ΅ΠΉΠ΄Π΅Ρ Π² ΡΠ΅ΠΆΠΈΠΌ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ ΡΡΠ°Π·Ρ `Alexandr`.
-| ΠΠ°ΡΠ΅Π³ΠΎΡΠΈΡ | ΠΠΎΠΌΠ°Π½Π΄Ρ |
-|-----------|---------|
-| **ΠΠΊΡΠΈΠ²Π°ΡΠΈΡ** | `Alexandr` |
-| **ΠΠΈΠ°Π»ΠΎΠ³** | `ΠΠΎΡΠ΅ΠΌΡ Π½Π΅Π±ΠΎ Π³ΠΎΠ»ΡΠ±ΠΎΠ΅?` |
-| **ΠΠΎΠ³ΠΎΠ΄Π°** | `ΠΠ°ΠΊΠ°Ρ ΡΠ΅ΠΉΡΠ°Ρ ΠΏΠΎΠ³ΠΎΠ΄Π°?`, `ΠΠΎΠ³ΠΎΠ΄Π° Π² ΠΠΎΡΠΊΠ²Π΅` |
-| **ΠΠ΅ΡΠ΅Π²ΠΎΠ΄** | `ΠΠ΅ΡΠ΅Π²Π΅Π΄ΠΈ Π½Π° Π°Π½Π³Π»ΠΈΠΉΡΠΊΠΈΠΉ: ΠΊΠ°ΠΊ Π΄Π΅Π»Π°` |
-| **Π’Π°ΠΉΠΌΠ΅Ρ** | `ΠΠΎΡΡΠ°Π²Ρ ΡΠ°ΠΉΠΌΠ΅Ρ Π½Π° 5 ΠΌΠΈΠ½ΡΡ` |
-| **ΠΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ** | `ΠΠΎΡΡΠ°Π²Ρ Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ Π½Π° 7:30`, `ΠΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ ΠΏΠΎ Π±ΡΠ΄Π½ΡΠΌ Π² 8:00` |
-| **Π‘Π΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅Ρ** | `ΠΠ°ΠΏΡΡΡΠΈ ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅Ρ`, `ΠΠΎΠΊΠ°ΠΆΠΈ Π°ΠΊΡΠΈΠ²Π½ΡΠ΅ ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅ΡΡ` |
-| **ΠΡΠΎΠΌΠΊΠΎΡΡΡ** | `ΠΡΠΎΠΌΠΊΠΎΡΡΡ 5` |
-| **Spotify** | `ΠΠΊΠ»ΡΡΠΈ ΠΌΡΠ·ΡΠΊΡ`, `ΠΠ°ΡΠ·Π°`, `Π§ΡΠΎ ΡΠ΅ΠΉΡΠ°Ρ ΠΈΠ³ΡΠ°Π΅Ρ` |
-| **ΠΠ³ΡΠ°** | `ΠΠ°Π²Π°ΠΉ ΡΡΠ³ΡΠ°Π΅ΠΌ Π² Π³ΠΎΡΠΎΠ΄Π°` |
-| **ΠΡΡΠ°Π½ΠΎΠ²ΠΊΠ°** | `Π‘ΡΠΎΠΏ`, `Π₯Π²Π°ΡΠΈΡ`, `ΠΠΎΠ²ΡΠΎΡΠΈ` |
+## ΠΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ `.env`
-## π οΈ ΠΠΎΠ»Π΅Π·Π½ΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ
+| ΠΠ΅ΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ | ΠΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ | ΠΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ | ΠΠ°Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ |
+|---|---|---|---|
+| `PERPLEXITY_API_KEY` | ΠΠ° | - | ΠΠ»ΡΡ Perplexity API |
+| `PERPLEXITY_MODEL` | ΠΠ΅Ρ | `llama-3.1-sonar-small-128k-chat` | ΠΠΎΠ΄Π΅Π»Ρ Perplexity |
+| `DEEPGRAM_API_KEY` | ΠΠ° | - | ΠΠ»ΡΡ Deepgram STT |
+| `PORCUPINE_ACCESS_KEY` | ΠΠ° | - | ΠΠ»ΡΡ PicoVoice Porcupine |
+| `PORCUPINE_SENSITIVITY` | ΠΠ΅Ρ | `0.8` | Π§ΡΠ²ΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ wake word |
+| `TTS_EN_SPEAKER` | ΠΠ΅Ρ | `en_0` | ΠΠ½Π³Π»ΠΈΠΉΡΠΊΠΈΠΉ Π³ΠΎΠ»ΠΎΡ TTS |
+| `WEATHER_LAT` | ΠΠ΅Ρ | - | Π¨ΠΈΡΠΎΡΠ° Π³ΠΎΡΠΎΠ΄Π° ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ |
+| `WEATHER_LON` | ΠΠ΅Ρ | - | ΠΠΎΠ»Π³ΠΎΡΠ° Π³ΠΎΡΠΎΠ΄Π° ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ |
+| `WEATHER_CITY` | ΠΠ΅Ρ | `Π£Ρ
ΡΠ°` | ΠΠΎΡΠΎΠ΄ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ Π΄Π»Ρ ΠΏΠΎΠ³ΠΎΠ΄Ρ |
+| `SPOTIFY_CLIENT_ID` | ΠΠ΅Ρ | - | Spotify OAuth Client ID |
+| `SPOTIFY_CLIENT_SECRET` | ΠΠ΅Ρ | - | Spotify OAuth Client Secret |
+| `SPOTIFY_REDIRECT_URI` | ΠΠ΅Ρ | `http://localhost:8888/callback` | Redirect URI Π΄Π»Ρ Spotify |
-| ΠΠΎΠΌΠ°Π½Π΄Π° | ΠΠ°Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ |
-|---------|------------|
+## ΠΡΠΈΠΌΠ΅ΡΡ Π³ΠΎΠ»ΠΎΡΠΎΠ²ΡΡ
ΠΊΠΎΠΌΠ°Π½Π΄
+
+| ΠΠ°ΡΠ΅Π³ΠΎΡΠΈΡ | ΠΡΠΈΠΌΠ΅ΡΡ |
+|---|---|
+| ΠΠΊΡΠΈΠ²Π°ΡΠΈΡ | `Alexandr` |
+| AI-Π΄ΠΈΠ°Π»ΠΎΠ³ | `ΠΠΎΡΠ΅ΠΌΡ Π½Π΅Π±ΠΎ Π³ΠΎΠ»ΡΠ±ΠΎΠ΅?` |
+| ΠΠ΅ΡΠ΅Π²ΠΎΠ΄ | `ΠΠ΅ΡΠ΅Π²Π΅Π΄ΠΈ Π½Π° Π°Π½Π³Π»ΠΈΠΉΡΠΊΠΈΠΉ: ΠΊΠ°ΠΊ Π΄Π΅Π»Π°` |
+| ΠΠΎΠ³ΠΎΠ΄Π° | `ΠΠ°ΠΊΠ°Ρ ΠΏΠΎΠ³ΠΎΠ΄Π°?`, `ΠΠΎΠ³ΠΎΠ΄Π° Π² ΠΠΎΡΠΊΠ²Π΅` |
+| Π’Π°ΠΉΠΌΠ΅Ρ | `ΠΠΎΡΡΠ°Π²Ρ ΡΠ°ΠΉΠΌΠ΅Ρ Π½Π° 5 ΠΌΠΈΠ½ΡΡ` |
+| ΠΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ | `ΠΠΎΡΡΠ°Π²Ρ Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ Π½Π° 7:30`, `ΠΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ ΠΏΠΎ Π±ΡΠ΄Π½ΡΠΌ Π² 8:00` |
+| Π‘Π΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅Ρ | `ΠΠ°ΠΏΡΡΡΠΈ ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅Ρ`, `ΠΠΎΠΊΠ°ΠΆΠΈ Π°ΠΊΡΠΈΠ²Π½ΡΠ΅ ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅ΡΡ` |
+| ΠΡΠΎΠΌΠΊΠΎΡΡΡ | `ΠΡΠΎΠΌΠΊΠΎΡΡΡ 7` |
+| Spotify | `ΠΠΊΠ»ΡΡΠΈ ΠΌΡΠ·ΡΠΊΡ`, `ΠΠ°ΡΠ·Π°`, `Π§ΡΠΎ ΡΠ΅ΠΉΡΠ°Ρ ΠΈΠ³ΡΠ°Π΅Ρ` |
+| ΠΠ³ΡΠ° | `ΠΠ°Π²Π°ΠΉ ΡΡΠ³ΡΠ°Π΅ΠΌ Π² Π³ΠΎΡΠΎΠ΄Π°` |
+| Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠΌ | `ΠΠΎΠ²ΡΠΎΡΠΈ`, `Π‘ΡΠΎΠΏ`, `Π₯Π²Π°ΡΠΈΡ` |
+
+## ΠΠΎΠ»Π΅Π·Π½ΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ
+
+| ΠΠΎΠΌΠ°Π½Π΄Π° | Π§ΡΠΎ Π΄Π΅Π»Π°Π΅Ρ |
+|---|---|
| `make run` | ΠΠ°ΠΏΡΡΠΊ Π°ΡΡΠΈΡΡΠ΅Π½ΡΠ° |
-| `make check` | ΠΠ°Π·ΠΎΠ²Π°Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ° |
-| `make qwen-context` | Π‘ΠΎΠ±ΡΠ°ΡΡ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ ΠΏΡΠΎΠ΅ΠΊΡΠ° |
+| `make check` | ΠΠΎΠΊΠ°Π»ΡΠ½Π°Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ° (`scripts/qwen-check.sh`) |
+| `make qwen-context` | Π‘Π±ΠΎΡ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ° (`scripts/qwen-context.sh`) |
-## π Π‘ΡΡΡΠΊΡΡΡΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ°
+## Π‘ΡΡΡΠΊΡΡΡΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ°
-```
+```text
alexander_smart-speaker/
-βββ run.py # ΡΠΎΡΠΊΠ° Π²Ρ
ΠΎΠ΄Π°
+βββ run.py
βββ app/
-β βββ main.py # Π³Π»Π°Π²Π½ΡΠΉ ΡΠΈΠΊΠ» Π°ΡΡΠΈΡΡΠ΅Π½ΡΠ°
-β βββ audio/ # wake word, STT, TTS, Π³ΡΠΎΠΌΠΊΠΎΡΡΡ
-β βββ core/ # ΠΊΠΎΠ½ΡΠΈΠ³, AI, ΡΠΎΡΡΠΈΠ½Π³ ΠΊΠΎΠΌΠ°Π½Π΄, ΡΡΠΈΠ»ΠΈΡΡ
-β βββ features/ # ΠΏΠΎΠ³ΠΎΠ΄Π°, Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ, ΡΠ°ΠΉΠΌΠ΅Ρ, ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅Ρ, ΠΌΡΠ·ΡΠΊΠ°, Π³ΠΎΡΠΎΠ΄Π°
-βββ assets/ # ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΈ Π·Π²ΡΠΊΠΈ
-βββ data/ # ΡΠΎΡ
ΡΠ°Π½Π΅Π½Π½ΡΠ΅ Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊΠΈ/ΡΠ°ΠΉΠΌΠ΅ΡΡ/ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅ΡΡ
-βββ scripts/ # ΡΠΊΡΠΈΠΏΡΡ Π΄Π»Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠΈ ΠΈ ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΡ
+β βββ main.py
+β βββ audio/ # wakeword, stt, tts, volume
+β βββ core/ # config, ai, command helpers, cleaner
+β βββ features/ # weather, timer, alarm, stopwatch, music, cities game
+βββ assets/
+β βββ models/ # Porcupine keyword model (.ppn)
+β βββ sounds/ # Π·Π²ΡΠΊΠΈ ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΠΉ ΠΈ Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊΠ°
+βββ data/ # persisted JSON: alarms, timers, stopwatches
+βββ scripts/
```
-## π§ ΠΠΈΠ°Π³Π½ΠΎΡΡΠΈΠΊΠ° ΠΏΡΠΎΠ±Π»Π΅ΠΌ
+## ΠΠΈΠ°Π³Π½ΠΎΡΡΠΈΠΊΠ°
-| ΠΡΠΎΠ±Π»Π΅ΠΌΠ° | Π Π΅ΡΠ΅Π½ΠΈΠ΅ |
-|----------|---------|
-| ΠΡΠΈΠ±ΠΊΠΈ STT/AI | ΠΡΠΎΠ²Π΅ΡΡΡΠ΅ ΠΊΠ»ΡΡΠΈ Π² `.env` |
-| ΠΠ΅Ρ Π·Π²ΡΠΊΠ° | ΠΡΠΎΠ²Π΅ΡΡΡΠ΅ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ΅ ΡΡΡΡΠΎΠΉΡΡΠ²ΠΎ Π²ΡΠ²ΠΎΠ΄Π° ΠΈ ΡΡΠΈΠ»ΠΈΡΡ `pactl`/`amixer` |
-| ΠΠ΅ ΠΈΠ³ΡΠ°Π΅Ρ Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ/ΡΠ°ΠΉΠΌΠ΅Ρ | Π£Π±Π΅Π΄ΠΈΡΠ΅ΡΡ, ΡΡΠΎ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ `mpg123` |
-| Spotify Π½Π΅ ΡΠΏΡΠ°Π²Π»ΡΠ΅ΡΡΡ | ΠΡΠΎΠ²Π΅ΡΡΡΠ΅ `SPOTIFY_*`, Π°Π²ΡΠΎΡΠΈΠ·Π°ΡΠΈΡ ΠΈ Π½Π°Π»ΠΈΡΠΈΠ΅ Π°ΠΊΡΠΈΠ²Π½ΠΎΠ³ΠΎ ΡΡΡΡΠΎΠΉΡΡΠ²Π° |
+| ΠΡΠΎΠ±Π»Π΅ΠΌΠ° | Π§ΡΠΎ ΠΏΡΠΎΠ²Π΅ΡΠΈΡΡ |
+|---|---|
+| ΠΠ΅ ΡΠ΅Π°Π³ΠΈΡΡΠ΅Ρ Π½Π° `Alexandr` | `PORCUPINE_ACCESS_KEY`, ΠΌΠΈΠΊΡΠΎΡΠΎΠ½, ΡΡΠ²ΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ `PORCUPINE_SENSITIVITY` |
+| STT Π½Π΅ ΡΠ°ΡΠΏΠΎΠ·Π½Π°Π΅Ρ ΡΠ΅ΡΡ | `DEEPGRAM_API_KEY`, ΡΠ΅ΡΠ΅Π²ΠΎΠΉ Π΄ΠΎΡΡΡΠΏ, Π²ΡΠ±ΡΠ°Π½Π½ΡΠΉ ΠΌΠΈΠΊΡΠΎΡΠΎΠ½ |
+| ΠΠ΅Ρ Π·Π²ΡΠΊΠ° | ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎΠ΅ Π°ΡΠ΄ΠΈΠΎΡΡΡΡΠΎΠΉΡΡΠ²ΠΎ ΠΈ Π΄ΠΎΡΡΡΠΏΠ½ΠΎΡΡΡ `pactl`/`amixer` |
+| ΠΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ/ΡΠ°ΠΉΠΌΠ΅Ρ Π½Π΅ Π·Π²ΠΎΠ½ΠΈΡ | Π½Π°Π»ΠΈΡΠΈΠ΅ `mpg123` Π² ΡΠΈΡΡΠ΅ΠΌΠ΅ |
+| Spotify Π½Π΅ ΡΠΏΡΠ°Π²Π»ΡΠ΅ΡΡΡ | Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Ρ `SPOTIFY_*`, Π΅ΡΡΡ Π°ΠΊΡΠΈΠ²Π½ΠΎΠ΅ ΡΡΡΡΠΎΠΉΡΡΠ²ΠΎ, Premium-Π°ΠΊΠΊΠ°ΡΠ½Ρ |
-## π ΠΠΈΡΠ΅Π½Π·ΠΈΡ
+## ΠΠΈΡΠ΅Π½Π·ΠΈΡ
-MIT, ΡΠΌ. [LICENSE.txt](LICENSE.txt).
-
----
-
-
-
-**ΠΡΠ»ΠΈ Π²Π°ΠΌ ΠΏΠΎΠ½ΡΠ°Π²ΠΈΠ»ΡΡ ΠΏΡΠΎΠ΅ΠΊΡ, ΠΏΠΎΡΡΠ°Π²ΡΡΠ΅ β Π·Π²Π΅Π·Π΄Ρ!**
-
-
\ No newline at end of file
+ΠΡΠΎΠ΅ΠΊΡ ΡΠ°ΡΠΏΡΠΎΡΡΡΠ°Π½ΡΠ΅ΡΡΡ ΠΏΠΎ Π»ΠΈΡΠ΅Π½Π·ΠΈΠΈ MIT. Π‘ΠΌ. `LICENSE.txt`.