Samochód wyścigowy to wymagające środowisko, w którym występują duże prędkości, wysokie temperatury i ograniczenia telemetryczne. Jak agent na urządzeniu może pomóc w przetwarzaniu danych o pojeździe w czasie rzeczywistym na potrzeby aplikacji sportowych i inżynieryjnych?
Ta sesja techniczna dotyczy eksperymentalnej architektury hybrydowej łączącej sprzęt brzegowy i agenty w chmurze. Przedstawimy badawczy dowód koncepcji, w którym wykorzystujemy Raspberry Pi do strumieniowego przesyłania danych telemetrycznych z magistrali CAN, telefon Pixel z agentem konwersacyjnym na urządzeniu opartym na ML Kit i Gemini Nano oraz połączenie z chmurą między agentami (A2A) na potrzeby procesów po wyścigu.
Transkrypcja
Cześć.
Nazywam się Alastair i chętnie opowiem Wam o projekcie, który zrealizowaliśmy w zeszłym roku we współpracy z Formułą E.
Jest dziś z nami Oli, który opowie o naszej współpracy.
Pracuję w Google Cloud w biurze dyrektora ds. technologii. Często staramy się przesuwać granice tego, co jest możliwe na urządzeniach mobilnych i w chmurze, oraz tego, jak te technologie mogą ze sobą współpracować.
Pokażę Wam krótki film, który wprowadzi Was w to, co robiliśmy.
Samochód Gen 4 to wyścigowa bestia o mocy 600 kW.
Napęd elektryczny, stały napęd na wszystkie koła.
Opisałbym go jako niesamowicie szybki.
Czy możemy użyć agenta na telefonie Pixel, który jest połączony z danymi telemetrycznymi pochodzącymi z samochodu?
Gdy kierowca będzie wjeżdżał na wzgórze w Goodwood, będzie mógł rozmawiać z samochodem.
To świetna funkcja.
Cześć Gemma, jak tam moje opony?
Ciśnienie w oponach jest prawidłowe, wynosi około 1,4 bara.
Telefon jest podłączony bezpośrednio do ECU i odczytuje wiele punktów danych dotyczących tego, co robię jako kierowca.
To pierwszy raz, kiedy coś takiego zdarzyło się w samochodzie wyścigowym.
Myślę, że nie ma lepszego miejsca do zaprezentowania tego.
Gemma, jesteśmy gotowi?
Zawsze gotowy.
W tym projekcie chcieliśmy spróbować wprowadzić do kokpitu agenta, który byłby pilotem kierowcy.
Zasadniczo staramy się przesuwać granice tego, co jest możliwe w przypadku agentów na brzegu sieci, ponieważ jest to świetny przykład naprawdę trudnego wyzwania.
Wyzwania, z jakimi trzeba się mierzyć w samochodzie wyścigowym, to oczywiście wysoka temperatura.
Samochody wyścigowe bardzo się nagrzewają i jest to jedno z największych wyzwań.
Niestabilne połączenie.
Robimy to na Goodwood Festival of Speed, gdzie gromadzą się setki tysięcy fanów sportów motorowych, aby oglądać wyścigi samochodowe.
Jak można się domyślić, gdy na polu jest kilkaset tysięcy osób, połączenie może być dość trudne.
Bluetooth.
Na przykład ten samochód jest w zasadzie klatką Faradaya, więc można sobie wyobrazić, jak trudno jest połączyć się z kaskiem kierowcy wyścigowego.
Ostatni aspekt to wymagania dotyczące małych opóźnień.
Kierowca jedzie z prędkością ponad 200 km/h, więc bardzo ważne jest, aby odpowiedzi, które otrzymuje od agenta, były naprawdę szybkie i krótkie.
Zasadniczo jesteśmy tym bardzo zainteresowani, ponieważ uważamy, że agenci staną się powszechni.
Już teraz zaczynamy to dostrzegać.
Nie są już tylko w naszych komputerach.
Są w naszych telefonach, zegarkach, okularach, inteligentnych domach, a nawet w samochodach.
Chcieliśmy więc sprawdzić, co możemy osiągnąć w tak trudnym scenariuszu.
Podczas burzy mózgów nad tym, jak to zbudować, zastanawialiśmy się, czy nie stworzyć mikrokomputera z małym akceleratorem, który zawierałby model.
Nagle zdaliśmy sobie sprawę, że wszystkie potrzebne składniki już istnieją i jest to Android.
Android jest idealnym środowiskiem, ponieważ zawiera ADK, czyli nasz pakiet Agent Development Kit.
To bardzo dobra biblioteka, która umożliwia tworzenie agentów bezpośrednio w aplikacji.
Są miliardy użytkowników i różne formaty, na których możemy łatwo uruchamiać aplikacje, więc testowanie i rozpowszechnianie kodu jest bardzo proste.
Narzędzia dla programistów, które umożliwiają debugowanie, testowanie różnych rozwiązań i znajdowanie błędów.
AI na urządzeniu – telefony Google Pixel są teraz dostarczane z TPU wbudowanym bezpośrednio w telefon, zoptymalizowanym pod kątem modelu na urządzeniu, który znajduje się bezpośrednio w telefonie. Dzięki temu można bardzo łatwo uzyskać dostęp do naprawdę zaawansowanego modelu za pomocą interfejsów API, takich jak ML Kit.
Mamy też takie funkcje jak zamiana tekstu na mowę i rozpoznawanie mowy, czyli interfejsy API działające w pełni offline, które umożliwiają prowadzenie rozmów.
I wreszcie, oczywiście, łączność.
Telefony są zaprojektowane z myślą o łączności, czy to przez sieci komórkowe, Wi-Fi czy inne środki.
Jednym z wyzwań jest jednak to, że agenty na brzegu sieci nie mogą robić wszystkiego. Jak więc mogą współpracować z agentami w chmurze?
A co, jeśli rozwiązanie jest hybrydowe?
Co, jeśli agent na telefonie może rozmawiać bezpośrednio z agentem w chmurze, aby wykonywać bardziej skomplikowane działania?
Wyobraźmy sobie na przykład, że kierowca chce wiedzieć, na której pozycji w wyścigu się znajduje.
Samochód nie będzie wiedział, na której pozycji znajduje się w wyścigu, ale może to wiedzieć agent w chmurze.
Mamy też protokół agent-to-agent, który umożliwia tworzenie agentów na urządzeniach brzegowych i w chmurze oraz ich wzajemną komunikację w celu wykonywania bardziej złożonych działań.
Jak go stworzyliśmy?
Przedstawię Wam elementy tego systemu.
Zacznij od uprzęży.
Teraz środowisko testowe jest w zasadzie aplikacją na Androida, która uruchamia pakiet Agent Development Kit na Androida.
Druga część to model.
Potrzebujesz modelu, który będzie go obsługiwał. My użyliśmy Gemini Nano przez ML Kit, czyli bardzo wydajnego modelu działającego na urządzeniu, który jest na wyciągnięcie ręki.
Następnie dane.
Oli za chwilę o tym opowie, ale mamy dane z samochodu, a potencjalnie także rozpoznawanie mowy kierowcy.
Na koniec mamy działania, które agent może wykonać.
Może to być zamiana tekstu na mowę, aby móc odpowiadać kierowcy i zadawać dodatkowe pytania lub przekazywać wymagane informacje, albo, jak wspomniano wcześniej, komunikacja między agentami, czyli komunikacja z agentem w chmurze w celu wykonywania bardziej złożonych działań.
Teraz chciałbym zaprosić na scenę Oli, który opowie trochę o tym, jak udało nam się to osiągnąć w przypadku Formuły E.
Dziękuję, Alastair.
Mamy już wszystkie składniki, teraz czas na najtrudniejszą część: jak zintegrować agenta AI z bolidem Formuły E?
Zaczyna się tutaj, w jednostce sterującej pojazdu (VCU).
Teraz każdy czujnik i każdy komponent samochodu przesyła informacje do komputera za pomocą magistrali CAN.
Samochód generuje tysiące punktów telemetrycznych na sekundę, takich jak prędkość, przyspieszenie, przepustnica, hamowanie i inne.
Aby odczytać te dane telemetryczne, zdecydowaliśmy się podłączyć Raspberry Pi bezpośrednio do VCU samochodu przez połączenie CAN.
Raspberry Pi wykonuje kilka różnych zadań.
Najpierw dekoduje nieprzetworzone sygnały, przekształca je i zmniejsza ich częstotliwość próbkowania do około 10 Hz, co jest wystarczającą ilością informacji dla pilota.
Następnie Raspberry Pi publikuje te przetworzone dane przez MQTT na Pixelu 10 Pro znajdującym się w kokpicie samochodu.
Jest to jeden z rodzajów danych wejściowych, które może akceptować aplikacja hostująca naszą aplikację agenta.
Drugi to rozpoznawanie mowy na Androidzie.
Gdy kierowca mówi, aplikacja konwertuje dane wejściowe na tekst, a Gemini Nano może analizować oba te rodzaje danych.
Teraz agent może podjąć 2 decyzje: po pierwsze, może użyć silnika zamiany tekstu na mowę na Androidzie, aby odpowiedzieć kierowcy.
Po drugie, jak wspomniał wcześniej Alastair, może komunikować się z agentem w chmurze za pomocą protokołu A2A.
Przepływ agenta jest dość prosty: powiedz słowo-klucz, w tym przypadku „Cześć, Gemma”, zadaj pytanie i uzyskaj odpowiedź.
Agent będzie słuchać przez około 5 sekund, dzięki czemu możesz zadać dodatkowe pytanie bez konieczności zaczynania od początku, tak jakbyś rozmawiał z prawdziwym inżynierem wyścigowym.
Aplikacja jest też agentem wieloetapowym, co oznacza, że może uzyskiwać dostęp do historii rozmów, aby prowadzić bardziej naturalne rozmowy.
Można by się spodziewać, że kod będzie dość skomplikowany, prawda?
Okazuje się, że to całkiem proste.
Pierwsze kilka wierszy wywołuje onDeviceModel za pomocą ML Kit i opakowuje go jako Gemini Nano.
val generativeModel: GenerativeModel = Generation.getClient()
val onDeviceModel = GenaiPrompt.create(
generativeModel = generativeModel,
name = "gemini-nano",
)
val agent = LlmAgent(
name = "race_engineer",
model = onDeviceModel,
staticInstruction = /* System prompt */,
instruction = Instruction {
/* Dynamic context */
},
tools = listOf(
/* Custom tools */
)
)Następnie definiujemy agenta za pomocą pakietu ADK.
Nadaj mu nazwę i podaj 2 rodzaje instrukcji: pierwszy to instrukcja statyczna, która określa jego osobowość i to, kim jest.
Może to obejmować takie informacje jak sposób, w jaki odpowiada kierowcy, oraz informacje o torze wyścigowym.
Druga to instrukcja dynamiczna.
Teraz jest on generowany przy każdym zapytaniu z najnowszym podsumowaniem telemetrii, dzięki czemu agent zawsze wie, co kierowca robi w danym momencie.
Obejmuje też historię bieżącej rozmowy, jak wspomniano wcześniej.
Oprócz tego definiujemy też pewne narzędzia, na przykład umożliwiające komunikację z danymi z poprzedniej sesji, z agentem w chmurze oraz z kierowcą za pomocą zamiany tekstu na mowę.
Teraz zobaczmy krótką demonstrację agenta w działaniu na naszych symulatorach w biurze Formuły E.
Cześć Gemma, jak agresywny jest mój styl jazdy?
Płynnie i z wyczuciem.
Maksymalny kąt skrętu wynosił 48 stopni, a kierownica była obracana średnio o 11 stopni na sekundę.
Cześć Gemma, jakie jest moje maksymalne przeciążenie?
Maksymalne przeciążenie na zakrętach wynosiło 2, 2 G.
Cześć Gemma, jak mi poszło podczas biegu?
Świetny bieg, Dan.
Prędkość maksymalna 306 km/h, średnia 186 km/h przez 35 sekund.
Przez 58% czasu jechałeś z maksymalną prędkością, a najwyższe przeciążenie wyniosło 2,2 G.
A więc to już.
To Gemini Nano na telefonie rozmawiający z kierowcą i odpowiadający na jego pytania w czasie rzeczywistym.
Symulator to jedno, ale bolid Formuły E to zupełnie inna sprawa.
Jak to wszystko połączyliśmy?
Najpierw musieliśmy udać się do Spark Racing Technology w Paryżu, gdzie powstają nasze samochody.
Po lewej stronie widać mnie, gdy podłączam Raspberry Pi do VCU bolidu Formuły E.
Wszystko, co do tej pory stworzyliśmy, działało na emulowanych danych i było odtwarzane z sesji testowej, więc nie wiedzieliśmy, czy będzie działać w rzeczywistości.
Podłączyliśmy go, włączyliśmy, poczekaliśmy chwilę i wreszcie zaczęliśmy otrzymywać dane telemetryczne na urządzeniu, co potwierdziło, że dane przepływają przez system zgodnie z oczekiwaniami.
Po prawej stronie widać gotowy system i telefon umieszczony w kokpicie, tuż obok miejsca, w którym będzie siedział kierowca.
Byliśmy więc gotowi na Goodwood.
Co się właściwie wydarzyło tego dnia?
Pamiętasz 4 wyzwania, o których Alastair mówił wcześniej?
Goodwood really tested two of them.
Pierwszym z nich był upał.
W Wielkiej Brytanii zwykle przygotowujemy się na każdą pogodę, z wyjątkiem słońca.
W rezultacie trafiliśmy na jeden z najgorętszych tygodni w historii, w samym środku fali upałów.
To idealny moment, aby umieścić komputer w samochodzie Formuły E.
Ale jest pewien haczyk.
Telefon był w porządku.
Android nie ucierpiał.
Okazało się, że Raspberry Pi miał największe problemy.
Nie mogliśmy podłączyć go bezpośrednio do samochodu, więc musieliśmy użyć zasilacza UPS, który wygląda jak zestaw baterii przyczepionych do spodu Raspberry Pi.
Na szczęście udało nam się to naprawić, doładowując go od czasu do czasu w ciągu dnia. Bez tego samochód prawdopodobnie nie wjechałby na to wzgórze bez agenta AI.
Następny był Bluetooth.
W tym momencie nie przetestowaliśmy jeszcze kasku kierowcy, który łączy się z aplikacją przez Bluetooth.
To było dla nas pewnym wyzwaniem.
Aby to sprawdzić, usiedliśmy na trawie i wygląda na to, że świetnie się bawimy, prawda?
Wyciągnęliśmy laptopy i rozmawiamy.
W rzeczywistości był to prawdopodobnie jeden z najbardziej stresujących okresów w mojej dotychczasowej karierze.
Próbowaliśmy za wszelką cenę zmusić kod do współpracy i połączyć kask Bluetooth z aplikacją przed popołudniowym przejazdem pod górę.
Jednak dzięki poprawkom wprowadzonym w ostatniej chwili i świetnym narzędziom do debugowania na Androidzie udało nam się rozwiązać problem na czas i samochód wjechał na wzgórze, a agent AI działał bez zarzutu.
Teraz oddam głos Alastairowi, który opowie nam trochę więcej o tym, czego nauczyliśmy się podczas realizacji projektu.
Dziękujemy.
Dziękuję, Oli.
Czego się nauczyliśmy podczas tego projektu?
Po pierwsze, Android jest idealnym środowiskiem dla agentów.
Zachęcam do korzystania z wszechstronności Androida, dostępnych interfejsów API, modeli na urządzeniu i ADK.
Wypróbuj je, bo zaskoczy Cię, jak wiele może dać tak prosta rzecz.
Piekło integracji nadal istnieje.
Większość osób w tym pokoju prawdopodobnie doświadczyła tego w pewnym momencie swojej kariery.
Tworzy się wszystkie podzespoły osobno, a gdy przychodzi czas na ich połączenie, coś nie działa.
Kask kierowcy rajdowego był właśnie taki.
Na szczęście udało nam się rozwiązać ten problem tego samego dnia, co dowodzi, że testowanie jest nadal bardzo ważne.
I wreszcie Gemini Nano.
Gemini Nano był tu prawdziwym bohaterem.
Jest to bardzo skuteczny model, który działa bardzo szybko na urządzeniu i może wykonywać naprawdę skomplikowane zadania, ale nie od razu.
To naprawdę przemyślana decyzja.
Musisz zastosować inżynierię promptów.
Musisz to przetestować.
Musisz zastanowić się, jak chcesz przekazywać instrukcje dynamiczne, a jak statyczne.
Musisz zastanowić się, jakie narzędzia mu udostępnisz i jak najlepiej poinstruować go, aby wykonał zadanie.
Jednak dzięki odpowiednim testom i ocenom możesz uzyskać wiele korzyści z modelu takiego jak Gemini Nano bezpośrednio na urządzeniu.
Dziękuję wszystkim.
Będziemy później w budce, więc możesz przyjść i zadać nam kilka pytań.
val generativeModel: GenerativeModel = Generation.getClient()
val onDeviceModel = GenaiPrompt.create(
generativeModel = generativeModel,
name = "gemini-nano",
)
val agent = LlmAgent(
name = "race_engineer",
model = onDeviceModel,
staticInstruction = /* System prompt */,
instruction = Instruction {
/* Dynamic context */
},
tools = listOf(
/* Custom tools */
)
)