Opisane rozwiązanie korzysta z ChatGPT poprzez interfejs OpenAI API w języku Python. Daje to ogromne możliwości dalszych eksperymentów z projektem, np. sterowanie głosem asystenta. Projekt korzysta także z Azure Speech Services, czyli narzędzia w chmurze, które dostarcza konwersji tekstu na mowę, jak i mowy na tekst. Dzięki temu możemy z systemem normalnie konwersować, a działający skrypt, napisany w Pythonie, odpowiada za przekazywanie głosowych komend do ChatGPT i odczytywanie jego odpowiedzi.
Dzięki wykorzystaniu bardzo elastycznego silnika głosowego można bawić się postawą i głosem asystenta. Rejestrując się w Microsoft Azure Speech, można wypróbować różne głosy i wybrać ten, który nam się podoba. Następnie, w programie można opisać postawę, jaką chcemy, aby rozmówca przyjął. Można ustawić "złego szefa", "zrzędliwego staruszka" czy "miłą nauczycielkę z podstawówki". Dokładniej opisane jest to w dalszej części artykułu.
Potrzebne elementy
Do zbudowania tego urządzenia potrzebne są:
- komputerek Raspberry Pi - autor proponuję wersję 4 z dowolną ilością pamięci RAM,
- karta SD o pojemności min. 8 GB,
- moduł wzmacniacza audio z wejściem I²S o mocy 3 W (np. na układzie MAX98357A).
- głośnik,
- opornik 100 kΩ,
- minimikrofon na USB,
- elementy z druku 3D (górna część obudowy, dolna część obudowy, uchwyt na głośnik),
- cztery śrubki i nakrętki M2.5 i dodatkowe, mniejsze wkręty do mocowania głośnika,
- przewody do połączenia ze sobą elementów w obudowie,
- taśma dwustronna lub klej na ciepło.
Budowa urządzenia
Montaż układu jest dość łatwy. Wymaga zamocowania tylko kilku przewodów. Zacząć należy od od 7 przewodów o długości około 120...150 mm. Jeden koniec musi mieć żeńskie złącze do podłączenia do szpilek GPIO w Raspberry Pi. Z drugiego końca odcinamy złącze i zdejmujemy fragment izolacji, aby móc przylutować przewody do wzmacniacza i przycisków.
Przewody będą podłączone w następujący sposób (fotografia 1):
- żółty z BCLK na wzmacniaczu do GPIO 18 na Raspberry Pi,
- zielony z LRC na wzmacniaczu do GPIO 19 na Raspberry Pi,
- niebieski z DIN na wzmacniaczu do GPIO 21 na Raspberry Pi,
- czerwony 1 z Vin na wzmacniaczu do 3,3 V na Raspberry Pi,
- czarny 1 z GND na wzmacniaczu do masy na Raspberry Pi,
- czerwony 2 z jednej strony przycisku do GPIO 16 na Raspberry Pi,
- czarny 2 z drugiej strony przycisku do masy na Raspberry Pi.
Najpierw należy przylutować przewody głośnikowe do punktów lutowniczych oznaczonych jako "+" i "-" u góry płytki wzmacniacza. Po podłączeniu przewodów do Raspberry Pi i umieszczeniu go w dolnej części obudowy można podłączyć mikrofon USB do dowolnego z portów USB na Raspberry Pi.
Finalnie zabezpieczamy górną część obudowy, mocując ją do dolnej za pomocą śrub M2.5 o długości 28 mm. Jeśli nie mamy takich śrub, możemy po prostu ścisnąć obie połowy obudowy razem, a ponieważ są one dosyć ciasno do siebie dopasowanie, śruby można dodać później lub w ogóle. Tak zmontowany układ jest już gotowy do załadowania oprogramowania.
Zasada działania układu
Zasada działania systemu jest bardzo prosta. Program zapisany w pythonowym skrypcie komunikuje się z API ChatGPT i API Azure. Przyjrzymy się detalom tego skryptu w dalszej części artykułu.
Za wyjście dźwięku odpowiada moduł, który zawiera scalony wzmacniacz z wejściem I²S - układ MAX98357 - do którego podłączony jest głośnik. Można też po prostu podłączyć zestaw słuchawkowy czy inny odbiornik audio do wyjścia audio z gniazdem jack 3,5 mm w Raspberry Pi. Wejście głosowe realizowane jest przez mikrofon cyfrowy dołączony do portu USB.
Następnym krokiem jest dodanie do systemu obudowy (autor zaadaptował obudowę z projektu Gund Bear) i dostosowanie jej do płytki Raspberry Pi bez dodatkowego HAT, jaki jest w oryginalnym projekcie, ale z wystarczającą ilością miejsca, aby pomieścić przewody bezpośrednio podłączone do szpilek GPIO w Raspberry Pi.
System jest gotowy, gdziekolwiek jesteśmy, o ile mamy połączenie z siecią - nawet przez hotspot z sieci GSM, możemy podłączyć swoje urządzenie do chmurowej sztucznej inteligencji i zapytać ChatGPT o cokolwiek chcemy. Oczywiście ważne jest też mobilne zasilanie układu, ale tutaj wystarczy mocny powerbank i zasilanie całego systemu przez port USB w Raspberry Pi.
Instalacja systemu operacyjnego i innego potrzebnego oprogramowania
Przed uruchomieniem systemu musimy zainstalować na Raspberry Pi zestaw potrzebnego oprogramowania, rozpoczynając od systemu operacyjnego. Finalnie musimy załadować do komputera odpowiedni skrypt w Pythonie, jaki udostępnia autor projektu.
Należy pamiętać, że w projekcie będziemy potrzebować kluczy API od OpenAI i Azure Speech Services, aby korzystać z ChatGPT. Korzystanie z interfejsu OpenAI API nie jest darmowe, ale nie jest też drogie i powinno kosztować poniżej 5 dolarów za miesiąc, nawet przy intensywnym użytkowaniu (przy użytku prywatnym). Usługi Azure Speech od Microsoftu są bezpłatne.
Głos generowany na wyjściu może być wybrany spośród różnych dostępnych bezpłatnie od Microsoft (co jednak wymaga rejestracji). Osobowość głosu jest ustawiana już w programie czatu, jak wspomniano powyżej.
Raspberry Pi OS (Bullseye - Legacy version)
Instalując system, musimy upewnić się, że używamy systemu operacyjnego Raspberry Pi OS Bullseye - to tak zwana wersja Legacy. Jeśli potrzebujemy w systemie pulpitu (środowisko graficzne), instalujemy pełną wersję. Jeśli nie potrzebujemy go, należy zainstalować wersję lite. Obie wersje będą działać z ChatGPT i opisywanym tutaj oprogramowaniem.
Używamy narzędzia Raspberry Pi Imager (https://www.raspberrypi.com/software/), aby zainstalować Raspberry Pi Bullseye (nie Bookworm czy inną wersję) na karcie microSD o pojemności 8 GB lub większej, a następie:
- klikamy Choose OS, aby wybrać wersję systemu operacyjnego, jaka jest nam potrzebna,
- wybieramy Raspberry Pi OS (other), a następnie przewijamy do do Raspberry Pi OS (Legacy, 64bit) (pełna lub lite),
- wybieramy Raspberry Pi OS (Legacy, 64-bit) - dowolną z 3 wersji,
- klikamy Choose Storage i wybieramy kartę SD, na której zainstalowany ma zostać system operacyjny,
- upewniamy się, że klikamy przycisk Settings, gdzie musimy wpisać następujące informacje: nazwa sieci domowej; hasło do sieci domowej; preferowane imię użytkownika; często po prostu "pi"; preferowana nazwa komputera (zwykłą nazwą jest "raspberrypi", ale może nią być cokolwiek, np. "mypi"),
- klikamy Write.
Gdy narzędzie skończy, wyciągamy z komputera kartę SD i wkładamy ją do Raspberry Pi, a następnie podłączamy zasilanie do portu USB-C. Musimy poczekać minutę, aż system uruchomi się i możemy rozpocząć sesję SSH do naszego Raspberry Pi z terminala uruchomionego na komputerze PC lub macu. Należy się upewnić, że nasz komputer jest w tej samej sieci co Raspberry Pi. W tym celu w linii komend wpisujemy:
Podczas pierwszego uruchomienia prawdopodobnie otrzymamy błąd:
Jeśli nie, przejdź do kolejnego kroku - instalacji modułu PIP. Jeśli tak, należy otworzyć plik known_hosts na swoim komputerze PC lub macu i usunąć całą jego zawartość.
Aby usunąć zawartość pliku known_hosts, wystarczy uruchomić preferowany edytor i wpisać ścieżkę podaną w komunikacie o błędzie, a następnie usunąć linie, które się tam znajdują. Można na przykład, użyć edytora nano, wpisując w linii komend:
W nano klikamy CTRL-K, aby usunąć każdą linię, a po zakończeniu naciskamy CTRL-X następnie y, i finalnie Enter, aby zapisać zmiany. Ponownie wpisujemy ssh, klikamy yes, aby kontynuować, a następnie wprowadzamy swoje hasło. Aby umożliwić Pi połączenie z internetem za pośrednictwem np. hotspotu z telefonu, trzeba dodać jego ssid i hasło do pliku wpa_supplicant:
dodaj poniższe linie poniżej nawiasu zamykającego, który już tam jest:
ssid="ssid_hotspotu"
psk="hasło"
id_str="nazwa_hotspotu"
}
Jak zwykle, zapisujemy edycje i zamykamy plik za pomocą: CTRL-X, następnie y i potwierdzamy klawiszem Enter.
Instalacja menedżera pakietów do Pythona (PIP) i aktualizacja systemu operacyjnego
W terminalu wpisujemy po kolei komendy, jak na listingu 1. To konkluduje instalację narzędzi do zarządzania bibliotekami dla środowiska Pythonowego. Pozwoli nam to zainstalować w dalszej kolejności potrzebne nam biblioteki.
sudo apt install python3-pyaudio build-essential libssl-dev libasound2 wget
sudo apt update
sudo apt upgrade (if you get an alert, press q to quit)
sudo apt-get install python3-pip
sudo apt install --upgrade python3-setuptools
Instalacja Adafruit Blinka
W konsoli wpisujemy po kolei komendy, jak na listingu 2. Naciskamy Y, aby zresetować komputer.
sudo pip3 install adafruit-python-shell
wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/raspi-blinka.py
sudo python3 raspi-blinka.py
Instalacja PulseAudio
W konsoli wpisujemy:
Poprawność instalacji sprawdzamy, wpisując:
Jeśli komunikat poinformuje nas, że demon nie działa, należy wpisać polecenie, aby go uruchomić i ponowić sprawdzenie poprawności instalacji:
Jeśli demon jest uruchomiony, to komenda z parametrem --check -v poda nam komplet informacji na temat jego kondycji.
Instalacja modułu rozpoznawania głosu (SpeechRecognition), OpenAI oraz Azure Speech Services
W terminalu wpisujemy po kolei polecenia instalacji każdego z wspomnianych pakietów:
pip3 install --upgrade openai
pip3 install --upgrade azure-cognitiveservices-speech
Każde polecenie powinno nam zwrócić informację o powodzeniu instalacji, jeśli nie wystąpiły żadne błędy.
Rejestracja w OpenAI i w Microsoft Azure Speech Services
W tym kroku wygenerowane zostaną klucze do API potrzebne do dostępu do funkcji usług, z których korzysta system, za pomocą skryptu napisanego w Pythonie. Aby ukończyć rejestrację w OpenAI, trzeba użyć karty kredytowej, ale nie ma się co martwić - opłata nie jest wysoka, w przypadku typowego użytkowania osobistego nie będzie wyższa niż kilka dolarów miesięcznie. Rejestracja w usłudze Azure Speech jest bezpłatna.
Uzyskane klucze należy dodać do pliku środowiskowego (/etc/environment) lub wprowadzić na stałe w skrypcie z czatem, który pokazano w dalszej części artykułu.
- Aby zarejestrować się w OpenAi, najprościej skorzystać z tutoriala dostępnego na stronie Adafruit: https://learn.adafruit.com/robotic-ai-bear-using-chatgpt/create-an-account-with-openai, o ile potrzebujemy w ogóle takiego poradnika, gdyż sama procedura jest intuicyjna i dobrze opisana na stronie openAI.
- Aby zarejestrować się w usługach Azure Speech Microsoft Azure, postępujemy zgodnie z krokami opisanymi w kolejnym tutorialu Adafruit, dostępnym na ich stronie: https://learn.adafruit.com/robotic-ai-bear-using-chatgpt/create-an-account-with-azure
- Po rejestracji tworzymy lub aktualizujemy plik środowiskowy w /etc i dodajemy do niego swoje klucze i region:
SPEECH_KEY="TWÓJ_KLUCZ_AZURE_SPEECH_TUTAJ"
SPEECH_REGION="eastus"
Do edycji możemy wykorzystać edytor nano, pamiętając, aby wejść w folder z plikiem środowiskowym (cd /etc) i uruchomić nano jako administrator (sudo nano environment). Po wprowadzeniu powyższych trzech linii, zamieniając tekst w cudzysłowach na nasze wartości kluczy, należy zamknąć i zapisać plik.
Włączenie obsługi audio przez Adafruit Blinka
Aby dźwięk mógł być odtwarzany na podłączonym głośniku, musimy zaktualizować wersję CircuitPython od Adafruit, zwaną Blinka, i włączyć wzmacniacz MAX98357A, który obsługuje głośnik.
- Zaktualizuj Adafruit Blinka i usuń potencjalne konflikty:
- Zainstaluj obsługę I²S DAC dla MAX98357:
Naciśnij y, aby kontynuować, następnie n, aby aktywować w tle, a następnie y, aby zrestartować.
Skopiuj skrypt - Chat.py - na Raspberry Pi
Skopiuj program chat.py z komputera PC lub mac na działający katalog Raspberry Pi (/home/pi):
- Otwórz terminal na swoim PC lub macu i przejdź do katalogu, w którym znajduje się plik chat.py.
- Skopiuj plik bezpiecznie na swoje Raspberry Pi (zamień pi i raspberrypi na swoją nazwę użytkownika i nazwę komputera):
Wprowadź hasło do swojego Raspberry Pi, aby rozpocząć kopiowanie.
Teraz można dokonywać dowolnych zmian w programie Python. Na przykład, zmienić można postać/charakter asystenta - jest on ustawiony w parametrze SYSTEM_ROLE w programie ChatGPT:
"Jesteś pomocnym asystentem głosowym w formie miłej nauczycielki przedszkolnej,"
"odpowiadającej na pytania i udzielającej informacji"
)
Powitanie, które usłyszysz, jest ustawione w głównej procedurze programu chat.py (listing 3):
Na listingu 3 zamieszczono kluczowe fragmenty skryptu - pętlę główną, raz z inicjalizacją, jakie znajdują się w funkcji main(). Kompletny skrypt pobrać może ze strony z projektem. Znaleźć tam można dwie klasy - Listener oraz Chat, które odpowiadają za obsługę, odpowiednio, nasłuchiwania oraz przetwarzania dźwięku (w obie strony) i odtwarzania komunikatów.
def main():
listener = Listener()
chat = Chat(speech_config)
transcription = [““]
chat.speak(
“Cześć! Nazywam się Lilly i jestem twoim osobistym asystentem. Możesz zapytać mnie o cokolwiek. Po prostu naciśnij czerwony przycisk, kiedy chcesz ze mną porozmawiać”
)
W tym momencie program chat.py będzie już działał, używając mikrofonu USB podłączonego do Raspberry Pi oraz głośnika zainstalowanego w obudowie Pi. Aby uruchomić program, wystarczy wpisać w linii komend następujące polecenie:
Jeśli przy uruchamianiu Python zwraca następujący błąd: Speech synthesis canceled: CancellationReason.Error oraz WebSocket upgrade failed: Authentication error (401), konieczne jest edytowanie pliku chat.py i zmiana zmiennej speech_key na rzeczywisty klucz. Zmień linię wskazaną na listingu 4. Ustaw nasz rzeczywisty klucz zamiast ciągu znaków 5d61xxxxxxxxxxxxxxxxxxacbd916029.
# Parametry ChatGPT
SYSTEM_ROLE = (
“You are a helpful voice assistant in the form of a sweet kindergarten teacher”
“ that answers questions and gives information”)
CHATGPT_MODEL = “gpt-3.5-turbo”
WHISPER_MODEL = “whisper-1”
# Parametry Azure Speech
AZURE_SPEECH_VOICE = “en-GB-HollieNeural”
DEVICE_ID = None
# Parametry rozpoznawania głosu
ENERGY_THRESHOLD = 1000 # Poziom dźwięku do wykrywania
PHRASE_TIMEOUT = 3.0 # Czas pomiędzy nagraniami do separacji fraz
RECORD_TIMEOUT = 0
# Import kluczy ze zmiennych środowiskowych
openai.api_key = os.environ.get(“OPENAI_API_KEY”)
speech_key = os.environ.get(“SPEECH_KEY”)
service_region = os.environ.get(“SPEECH_REGION”)
if openai.api_key is None or speech_key is None or service_region is None:
print(“Please set the OPENAI_API_KEY, SPEECH_KEY, and SPEECH_REGION environment variables first.”)
sys.exit(1)
speech_config = speechsdk.SpeechConfig(subscription=speech_key, region=service_region)
speech_config.speech_synthesis_voice_name = AZURE_SPEECH_VOICE
def sendchat(prompt): # Wyślij tekst od ChatGPT i zwróc rezultat
completion = openai.ChatCompletion.create(
model=CHATGPT_MODEL,
messages=[
{“role”: “system”, “content”: SYSTEM_ROLE},
{“role”: “user”, “content”: prompt},
],
)
return completion.choices[0].message.content
def transcribe(wav_data): # Odczytaj transkrypcję
print(“Transcribing...”)
attempts = 0
while attempts < 3:
try:
with NamedTemporaryFile(suffix=”.wav”) as temp_file:
result = openai.Audio.translate_raw(
WHISPER_MODEL, wav_data, temp_file.name
)
return result[“text”].strip()
except (openai.error.ServiceUnavailableError, openai.error.APIError):
time.sleep(3)
attempts += 1
return “I wasn’t able to understand you. Please repeat that.”
def main():
listener = Listener()
chat = Chat(speech_config)
transcription = [““]
chat.speak(“Hello! My name is Lilly and I’m you personal assistant. You can ask me anything. Just press the red button whenever you would like to talk to me”)
while True:
try:
if chat.button_pressed(): # Jeśli naciśnięto przycisk, rozpocznij nasłuchiwanie
chat.speak(“How may I help you?”)
listener.listen()
if listener.speech_waiting(): # Pobierz surowe nagranie z kolejki
audio_data = listener.get_audio_data()
chat.speak(“let me think about that”)
text = transcribe(audio_data.get_wav_data())
if text:
if listener.phrase_complete:
transcription.append(text)
print(f”Phrase Complete. Sent ‘{text}’ to ChatGPT.”)
chat_response = sendchat(text)
transcription.append(f”> {chat_response}”)
print(“Got response from ChatGPT. Beginning speech synthesis.”)
chat.speak(chat_response)
else:
print(“Partial Phrase...”)
transcription[-1] = text
os.system(“clear”)
for line in transcription:
print(line)
print(““, end=””, flush=True)
time.sleep(0.25)
except KeyboardInterrupt:
break
chat.deinit()
Konfiguracja programu do automatycznego uruchamiania przy starcie systemu
Aby to zrobić, musimy utworzyć usługę, która to umożliwi. Należy postępować zgodnie z poniższymi instrukcjami:
- Utwórz plik usługi za pomocą poniższego polecenia:
Wprowadź tekst z listingu 5, Następnie zamknij sesję nano i zapisz plik.
Linię:
speech_config = speechsdk.SpeechConfig(subscription=speech_key, region=service_region)
zamieniamy na:
speech_config = speechsdk.SpeechConfig(subscription=”5d61xxxxxxxxxxxxxxxxxxacbd916029”, region=service_region)
Trzeba teraz poinformować system o nowej usłudze:
Aby przetestować działanie nowej usługi, wpisujemy w terminalu:
Aplikacja chat.py powinna się uruchomić.
Włączamy nową usługę, aby działała podczas uruchamiania systemu. W terminalu wpisujemy:
sudo reboot
Po ponownym włączeniu Raspberry Pi powinniśmy usłyszeć powitanie swojego osobistego asystenta w ciągu około 30 sekund. Aby zatrzymać chat.py, gdy uruchamiany jest za pomocą polecenia python3, wystarczy nacisnąć CTRL-C. Aby zatrzymać chat.py, gdy działa z chat.service, trzeba zabić instancję python3, która go uruchamia. W tym celu w terminalu ustalamy najpierw numer procesu (PID) chata. Wpisujemy:
Co zwróci szereg numerów, na przykład
Cokolwiek jest pierwszą liczbą, jest to identyfikatorem procesu (PID). Teraz możemy zabić ten proces, wpisując w terminalu (zamieniając oczywiście 787 na nasz PID):
[Unit]
Description=Asystent ChatGPT
Wants=network-online.target
After=network-online.target
After=multi-user.target
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi
ExecStartPre=/bin/sh -c ‘until ping -c1 google.com; do sleep 1; done;’
ExecStart=/usr/bin/python3 /home/pi/chat.py
[Install]
WantedBy=multi-user.target
Odtwarzanie muzyki
Finalnie, na koniec, można skonfigurować kilka dodatkowych opcji w komputerze. Aby uzyskać więcej korzyści z asystenta w Raspberry Pi, można umożliwić mu odtwarzanie muzyki z Internetu. W tym celu instalujemy odtwarzacz, wpisując w terminalu komendę:
mpg123 http://ice1.somafm.com/u80s-128-mp3
Regulacja głośności:
Następnie używając strzałek, można regulować głośność (w górę i w dół) lub wpisać np. 5, aby ustawić głośność na 50%, 6 dla 60%, itd.
Pixel Desktop
Pełna wersja systemu w wersji Bullseye obejmuje pulpit Pixel, aby Raspberry Pi stało się komputerem ogólnego przeznaczenia, korzystając z wyświetlacza HDMI, klawiatury (fizycznej lub wirtualnej) i myszy. Jeśli zainstalowana została wersja lite systemu Raspberry Pi OS Bullseye, można jednak doinstalować pulpit graficzny. Oto jak to zrobić.
Będzie potrzebna w tym celu mysz USB i klawiatura. Fizyczna klawiatura jest przydatna, ale niekonieczna, ponieważ możesz używać wirtualnej klawiatury na ekranie. W terminalu wpisujemy:
sudo apt install raspberrypi-ui-mods
sudo apt-get install onboard
Aby uruchomić pulpit przy starcie systemu (niezależnie od tego, czy chcemy go używać, czy nie), w terminalu wpisujemy:
Następnie wybieramy opcje Systemowe, a potem Uruchamianie/Automatyczne Logowanie. Ustaw start na Pulpit. Następnie należy zainstalować Pi-Apps (sklep z darmowymi aplikacjami dla Raspberry Pi):
I zrestartować komputer:
Po załadowaniu systemu ikona Pi-Apps pojawi się na pulpicie. należy w nią dwukrotnie kliknąć i wybrać opcję execute. Jest dostępnych tam wiele aplikacji, więc warto przejrzeć je i wypróbować różne aplikacje. Dobrze jest np. zacząć od Chromium, w sekcji Internet. To bardzo lekka i nowoczesna przeglądarka sieci web.
Nikodem Czechowski, EP
Źródło: https://t.ly/gbm20