Pokażę tutaj jak można wykorzystać API OpenAI do utworzenia inteligentnego asystenta domowego. Nasz asystent będzie posiadać zdolności ChatGPT, a jednocześnie będzie w stanie też kontrolować stan świateł (i innych urządzeń) w naszym domu. Asystent będzie rozumieć złożone komendy językowe, nawet będzie w stanie z kontekstu rozmowy wywnioskować w jakim pomieszczeniu jesteśmy i włączyć tam światło. Oprócz tego będzie można było z nim rozmawiać tak jak z ChatGPT, czyli zasadniczo zapytać go o wszystko, czasem z lepszym, a czasem z gorszym skutkiem.
Ten temat skupi się na kwestii wykorzystania API OpenAI oraz dobrania odpowiedniego promptu. W tym temacie pominę kwestie takie jak zamiana mowy na tekst a potem tekstu na mowę.
Pierwszy eksperyment z prompt
ChatGPT może tylko pisać, ale pisać może wiele - zgodnie z naszymi prośbami jest w stanie odgrywać role, odpowiednio się zachowywać i symulować wiele sytuacji.
W związku z tym spróbowałem go 'poprosić', by swe wypowiedzi dzielił na dwie sekcje - sekcja "SAY" (co mówi) oraz "CODE" - co wykonuje.
Oto moje pierwsze próby z promptami:
Ten model językowy jest w stanie jednocześnie pamiętać początkowy prompt (i działać wedle niego) oraz jednocześnie prowadzić ogólną, luźną rozmowę o gotowaniu czy o czymkolwiek co ma wyuczone. W momencie poproszenia o wykonanie operacji na oświetleniu, model poprawnie używa zaoferowanego mu API. Całkiem nieźle, nadaje się na asystenta...
Użyta biblioteka do API ChatGPT
Prototyp napisałem w C#, użyłem do tego biblioteki do API OpenAI:
https://github.com/OkGoDoIt/OpenAI-API-dotnet
To API można zainstalować w Visual Studio poprzez NuGet Packages:
Wpisujemy co trzeba i bingo:
W razie problemów, upewniamy się że mamy odpowiednio wysoką wersję NET framework (sam musiałem doinstalować 4.7.2):
Oczywiście trzeba mieć wykupione API (i klucz do tego API), ale o tym pisałem już jakiś czas temu.
Biblioteka OpenAI_API wszystko ułatwia. Oto najmniejszy przykład:
Kod: C#
To naprawdę tylko trzy linijki! A w sumie dwie...
Pierwsza to uruchomienie API (podanie naszego klucza), można to w sumie zrealizować w kilka sposobów:
Kod: C#
Potem można do woli z niego korzystać. Oto przykłąd prowadzenia rozmowy z ChatGPT:
Kod: C#
Biblioteka też wspiera streaming odpowiedzi, czyli wczytywanie jej na bieżąco, znak po znaku. Wygląda to tak, wersja C# 8.0 async iterator:
Kod: C#
Wersja sprzed C# 8.0:
Kod: C#
Plan działania
W oparciu o zebrane informacje i eksperymenty z promptami powstał plan działania utworzenia asystenta domu. Oto jego skrócona wersja:
1. System uruchamia ChatGPT z promptem o 'SAY' i 'CODE', wraz z listą pokojów
2. Użytkownik może komunikować się z ChatGPT przez naszą aplikację i API ChatGPT, ChatGPT może rozmawiać o wszystkim, nawet zmyślać te swoje historie różne
3. Aplikacja dodatkowo parsuje wiadomości ChatGPT i wyciąga z nich osobno blok CODE i SAY, SAY zostaje wyświetlony a CODE wykonany (np. poprzez wysłanie żądania do odpowiednich świateł)
Podłączenie świateł do systemu
Ten temat skupia się na użyciu modelu językowego, ale i tak dodam, że u mnie światła byłyby kontrolowane np. przez Tasmota HTTP, które wspiera zarówno Tasmota, jak i OpenBeken.
Aby włączyć dane światło wystarczy wysłać do niego zapytanie HTTP:
http://192.168.0.201/cm?cmnd=POWER%20ON
Ale o tym można poczytać chociażby w dokumentacji Tasmoty.
Dzięki takiemu podłączeniu urządzeń mamy też integrację z Home Assistant - a dokładniej, Home Assistant może tez sterować tymi samymi urządzeniami.
Demonstrancja aplikacji
W celu przetestowaniu pomysłu przygotowałem małą aplikację okienkową, która pozwala wpisać odpowiedzi/polecenia dla AI, jak również też pozwala dodać gotowe odpowiedzi z predefiniowanej listy, to w celu przyśpieszenia testowania.
Aplikacja również śledzi stan (na ten moment symulowanych) świateł oraz koloruje odpowiednio fragmenty rozmowy.
Oto krótka demonstracja:
Tak jak zapowiedziane - ChatGPT jest w stanie poprawnie rozumieć luźne polecenia podane w języku naturalnym, nie ma problemu z rozponaniem o co nam chodzi i poprawnie korzysta z udostępnionego mu API do kontroli świateł. To nie jest zwykły bot, który szuka "Turn on kitchen" na sztywno, tu cały zaawansowany model językowy interpretuje nasze wypowiedzi.
Oto test kontekstu rozmowy, z Asystentem Domowym można rozmawiać nawet o gotowaniu w trakcie przebywania w kuchni a on potem sam wywnioskuje gdzie ma włączyć światło:
Oto ciąg dalszy rozmowy powyżej - AI wnioskuje z kontekstu, że trzeba zgasić światło w kuchni i zapalić w jadalni:
Ciąg dalszy - można poprosić AI o wyłączenie wszystkich świateł:
Oto inny przykład, AI potrafi domyśleć się o jaki pokój chodzi bez podawania jego nazwy:
Dodatkowo AI zdaje się rozumieć kolejność włączenia światła - poprawnie zareagowało na prośbę o wyłączenie światła w pierwszym pokoju o którym była mowa...
Inny przykład - AI domyśla się pokoju z kontekstu wypowiedzi:
Inny przykład:
Napotkane problemy
Bardzo ciekawy problem napotkałem w początkowym stadium projektu, gdzie mój prompt korzystał ze słowa "CODE" zamiast z "DO" - wtedy AI upierało się na to, że wykonuje niby kod Pythona i wysypawało się gdy prosiłem o załączenie losowego światła:
Transkrypt rozmowy:
Prompt: You are a Home Assistant. You can only prefix your messages with SAY if you want to say something, and CODE if you want to run code command. You can control lights by writing text command setLightEnabled(room,state), where room can be: Kitchen, Bedroom, Bathroom, Hall, Toilet, Dining Room, and state can be on or off.Do not use any other code commands.Please keep talking with user and use the command when asked to. Please do not ask user to use commands.Please do not use commands without any reason.Now, start conversation with user.
AI raw reply: SAY: Hello there! How can I assist you today?
AI says: Hello there! How can I assist you today?
User: This is just a test. For a testing purpose, pick one room randomly and turn on there light.
AI raw reply: CODE:
import random
room_list = ['Kitchen', 'Bedroom', 'Bathroom', 'Hall', 'Toilet', 'Dining Room']
random_room = random.choice(room_list)
setLightEnabled(random_room, "on")
SAY: I have randomly selected the {random_room} and turned on the light.
Zmodyfikowałem prompt tak, by nie zawierał słowa Code, które kojarzy się z Pythonem, i zastąpiłem je słowem DO:
Ciekawa obserwacja - czy AI włączy losowe światło?
Inną moją ciekawą obserwacją jest to, że AI poproszone o włączenie losowego światła, grzecznie nam odmawia i czasem tłumaczy, że to by mogło zaskoczyć użytkownika i wprowadzić zamieszanie. Aby uzyskać oczekiwany rezultat należy najpierw podkreślić, że włączamy losowe światło w ramach testu. Przykład poniżej:
Przykład numer dwa (prośba o włączenie dwóch losowych świateł):
Ciekawa obserwacja - czy AI włączy światło w pokoju którego nie ma na liście?
Co zrobi model językowy, gdy poprosimy go o zapalenie światła w pokoju którego nie ma na liście? Sprawdźmy:
Model nie zmyśla, poprawnie wykrywa, że attic nie ma na liście i odmawia wykonania operacji. Co więcej, podaje listę znanych mu pokoi.
Potencjalny problem
Jednym z problemów jaki napotkałem w trakcie testów jest tendencja AI do okazjonalnego wysyłania nam linków, które są oczywiście bez sensu w przypadku komunikacji głosowej.
Możliwe, że odpowiednia dopiska w prompcie to naprawi, ale tego już nie sprawdzałem.
Gra ze światłem?
Teraz najciekawszy eksperyment. Zaproponujmy AI grę - AI włącza wszystkie światła i zadaje użytkownikowi pytania z matematyki. Jeśli użytkownik odpowie źle, to gasi jedno światło. Czy AI da radę?
Zaczynamy zabawę:
Cytat:
Let's play a game. First turn on all lights with DO. Then ask me math questions. If I answer correctly, do nothing. If I give wrong answer, use DO to turn off random light.
To serio działa:
Niestety, po chwili pojawia się problem... model językowy się wysypał na mnożeniu:
Liczę, że GPT 4 będzie w tym nieco lepsze.
Podsumowanie
Odpowiedni prompt sprawia, że model językowy ChatGPT jest w stanie sensownie kontrolować oświetleniem na bazie prowadzonej z użytkownikiem rozmowy. Model dość sensownie trzyma kontekst rozmowy oraz posługuje się udostępnionym mu prymitywnym API, przy czym jednocześnie oferuje dalej to wszystko co oferuje w swojej normalnej wersji. Model jest nawet na tyle "zrozumieć" kontekt rozmowy, że potrafi z niego wywnioskować gdzie jesteśmy i jakie światło chcemy zapalić.
Widzę tu potencjał na "inteligentnego" pomocnika dla osób niepełnosprawnych bądź chorych, w zwykłym domu pewnie też niektórym taki gadżet by się spodobał, chociaż nie uważam, by był niezbędny. To tylko zbędny bajer.
Jak na razie wykonałem tylko wstępne testy, ale warto byłoby jeszcze sprawdzić:
- jak radzi sobie ten model przy dłuższej rozmowie (czy gubi wątek, by może soft powinien resetować rozmowę)
- jak radzi sobie system przy większej ilości świateł
- czy system można rozwinąć i np. dać też mu kontrolę nad jasnością światła bądź nad kolorem
- można tez rozważyć podpięcie innych systemów, by AI np. kontrolowało grzanie i rozumiało polecenie "it's too hot in the kitchen", itd.
- zastanawiam się również, czy GPT-4 by sobie tu lepiej jeszcze poradził
W temacie też pokazałem kilka sytuacji, w których model ChatGPT się wysypał. Pierwsza z nich była sytuacja, gdzie użycie słowa "CODE" (zastąpionego potem "DO") do oznaczenia kontroli świateł sprawiło, że model zaczął myśleć, że pisze w Pythonie i po prośbie o zapalenie losowego światła, zamiast po prostu wybrać pomieszczenie to napisał kod losowania pomieszczenia... druga sytuacja to była z grą-zabawą, gdzie poprosiłem model by gasił światła jak odpowiem źle. Tu troszkę się mylił.
Zamieszczam kod demka - napisany na szybko, oczywiście bez exe i bez klucza, trzeba uzupełnić Form1.cs własnym kluczem przed uruchomieniem.
Fajne? Ranking DIY Pomogłem? Kup mi kawę.
