Nowoczesny klasyfikator komend w aplikacji mobilnej

W ostatnich tygodniach pracowałem nad modułem rozpoznawania i klasyfikacji komend głosowych w mojej aplikacji mobilnej Jokes Portal. Celem było stworzenie interfejsu, który umożliwia pełną, bezdotykową interakcję z aplikacją – od przeszukiwania żartów po ich odtwarzanie na głos. Taka funkcja nie tylko zwiększa komfort użytkowania, ale wnosi też poczucie nowoczesności i może dotrzeć do nowych odbiorców: kierowców, uczestników spotkań towarzyskich czy użytkowników z ograniczoną sprawnością. Co szczególnie ważne, rozwiązanie to wpisuje się w zasady budowania nowoczesnych produktów opartych na AI – wspierając inkluzywność. Osoby niewidome czy nieumiejące czytać i pisać zyskują pełny dostęp do treści aplikacji, czyli żartów.

Jakie miałem opcje? Krótki przegląd dostępnych rozwiązań

Ponieważ Jokes Portal to pierwsza aplikacja mobilna, którą rozwijam, a technologie AI rozwijają się w zawrotnym tempie, wybór odpowiedniego rozwiązania do klasyfikacji komend nie był oczywisty. Z wiedzą, którą miałem w tamtym momencie, znalazłem trzy i pół realnej możliwości wdrożenia klasyfikatora w środowisku .NET MAUI:

  1. Wykorzystanie dużego modelu językowego (LLM) – np. GPT-4o mini od OpenAI, z przygotowanym promptem klasyfikacyjnym.

  2. Zainstalowanie małego modelu językowego (SLM) bezpośrednio w aplikacji mobilnej, dostrojonego do komend.

    • 2.5: Osadzenie takiego samego klasyfikatora w API hostowanym na Azure
  3. Użycie klasycznego rozwiązania TF-IDF (Term Frequency – Inverse Document Frequency), działającego lokalnie na telefonie użytkownika.

Czego naprawdę wymaga dobra obsługa komend głosowych?

Tworząc aplikację B2C (business to consumer), musiałem pogodzić możliwości techniczne z oczekiwaniami użytkowników. Decyzja o wyborze podejścia do klasyfikatora była podyktowana kilkoma kluczowymi czynnikami:

  • Szybkość reakcji – chociaż użytkownicy są przyzwyczajeni do tego, że na rezultaty generowane przez AI trzeba chwilę poczekać, w przypadku komend oczekują działania natychmiastowego. Rozpoznawanie powinno odbywać się bez zauważalnych opóźnień, najlepiej w czasie rzeczywistym.

  • Koszt operacyjny – w aplikacji konsumenckiej każde zapytanie do zewnętrznego API (np. OpenAI) generuje koszt. Co więcej, liczba komend sterujących aplikacją (np. „pokaż ulubione”, „podoba mi się”) może być znacznie większa niż zapytań, które faktycznie wyświetlają treść. To oznacza, że ich obsługa musi być jak najtańsza, aby nie wymuszać na użytkowniku oglądania większej liczby reklam.

  • Możliwość działania offline – aplikacja mobilna powinna działać także przy ograniczonym dostępie do Internetu, np. w podróży. To naturalne oczekiwanie użytkowników, szczególnie w kontekście aplikacji rozrywkowej.

  • Rozmiar modelu – artefakt nie może ważyć setek megabajtów, bo użytkownicy niechętnie pobierają ciężkie aplikacje. Dodatkowo, gdy zaczyna brakować miejsca w pamięci telefonu, duże aplikacje są pierwsze do usunięcia.

  • Obsługa wielu języków – już na starcie aplikacja wspierała polski i angielski, więc każde rozwiązanie musiało działać równie dobrze dla obu języków. To kluczowe dla komfortu użytkownika i możliwości rozwoju aplikacji.

TF-IDF jako model ONNX

TF-IDF (Term Frequency – Inverse Document Frequency) to klasyczna technika przetwarzania języka naturalnego, która pozwala przekształcić tekst na wektor liczbowy. W tym podejściu każda komenda zostaje reprezentowana jako wektor ważonych słów, gdzie wagi odzwierciedlają znaczenie danego słowa w kontekście całego zbioru komend.

W praktyce przygotowuję zestaw reprezentatywnych komend (np. „pokaż ulubione”, „powiedz żart o zwierzętach”) i przypisuję im etykiety klas (intencji). Następnie trenuję model, który potrafi przypisać nową wypowiedź użytkownika do jednej z wcześniej zdefiniowanych intencji. Całość eksportuję do formatu ONNX, co pozwala używać tego modelu lokalnie na urządzeniu mobilnym w środowisku .Net.

Dla każdego języka (np. polski, angielski) tworzony jest oddzielny model. Przetwarzanie działa błyskawicznie (inferencja poniżej 10 ms), nie wymaga dostępu do Internetu i ma minimalny rozmiar (mniejszy niż 0.5 MB), co sprawia że można osadzić modele wewnątrz pakietu aplikacji.

Minusem rozwiązania jest to, że klasyfikator nie zwraca prawdopodobieństw – tylko etykietę intencji. Dlatego trzeba osobno zadbać o sytuację, w której użytkownik powie coś zupełnie niespodziewanego. W tym celu dodaję do zbioru treningowego specjalną klasę „unknown” z przykładami losowych, niezwiązanych komend (np. „jaka jest pogoda”, „co to jest JSON”), by model mógł nauczyć się odrzucać niepasujące zapytania.

Dodatkowym ograniczeniem TF-IDF jest brak rozumienia semantyki. Model opiera się wyłącznie na częstości występowania słów i ich wagach, bez rozpoznawania znaczenia kontekstu. Oznacza to, że rozwiązanie może mieć trudności z rozróżnieniem podobnych, ale znaczeniowo różnych komend, takich jak:

  • „opowiedz losowy żart” (czyli: jakikolwiek)

  • „opowiedz żart o losowości liczb” (czyli: na temat teorii prawdopodobieństwa)

Tego typu przypadki brzegowe trzeba odpowiednio obsłużyć na etapie trenowania – np. dodając więcej przykładów, które rozbijają podobnie brzmiące intencje na osobne klasy.

Small Language Model (SLM) lokalnie (ONNX)

Małe modele językowe (Small Language Models – SLM), takie jak MobileBERT, pozwalają na znacznie lepsze rozumienie kontekstu niż klasyczne podejścia oparte na słownikach. W nich trening odbywa się na przykładach komend użytkowników, a rozwiązanie wyeksportowane do formatu ONNX umożliwia lokalne uruchamianie na urządzeniu mobilnym w środowisku .Net.

SLM rozpoznaje nie tylko dokładne sformułowania, ale też różne wariacje językowe, np.:

  • „powiedz coś o lekarzu”

  • „opowiedz żart, w którym jest doktor”

Model działa w pełni offline, co spełnia jeden z kluczowych wymogów. Inferencja trwa zwykle 20–50 ms. Minusem tego podejścia jest rozmiar modelu co najmniej 70mb, co wpływa znacząco na wielkość paczki aplikacji. Aby zredukować ten problem, można rozważyć pobieranie modelu jako pakietu językowego na żądanie – z blob storage, który wykorzystywany jest już do dostarczania żartów w postaci audio.

W tym podejściu każdy język wymaga osobnego modelu – w moim przypadku oznacza to przetrenowanie wersji polskiej i angielskiej. W praktyce okazuje się to sporym ograniczeniem. Zdecydowana większość dostępnych modeli typu SLM została wytrenowana na języku angielskim. Dla języka polskiego istnieją modele takie jak PolBERT czy HerBERT, ale ważą one ponad 300 MB. Są zbyt ciężkie dla urządzeń mobilnych bez agresywnej optymalizacji lub ograniczania funkcji, co utrudniałoby implementację lub nawet okazało się niemożliwe do rozwiązania. Jeśli udałoby się sprostać wyzwanią, można spodziewać się, że efekt końcowy oferuje znacznie większą odporność na przypadki brzegowe, nieoczywiste sformułowania oraz błędy rozpoznania tekstu mówionego niż TF-IDF.

Warto również wspomnieć, że modele BERT w formacie ONNX nie zawierają wbudowanej logiki tokenizacji. Przed wywołaniem modelu tekst musi zostać odpowiednio przetworzony – podzielony na tokeny zgodnie z oryginalną architekturą. W przypadku .NET można skorzystać z BertTokenizer, który jest gotowym tokenizerem zgodnym z BERT-em. To dodatkowy krok, który należy zaimplementować ręcznie przed wykonaniem inferencji.

SLM jako mikroserwis w API

Zamiast osadzać model językowy bezpośrednio w aplikacji mobilnej, można uruchomić go jako mikroserwis w API. W tym podejściu model (np. MobileBERT wytrenowany i wyeksportowany do formatu ONNX) zostaje osadzony w aplikacji serwerowej – ASP.NET Core API działającym na Azure App Service, które już teraz obsługuje backend aplikacji mobilnej. Artefakty ONNX o rozmiarze 100–200 MB, a nawet większym, mogą być bez problemu ładowane do pamięci przy starcie serwera.

Największą zaletą tego podejścia jest brak wpływu na rozmiar aplikacji mobilnej – klient nie musi pobierać dużych modeli, a przetwarzanie odbywa się po stronie backendu. Łatwiejsze jest również wersjonowanie i aktualizacja modeli – nie wymaga to publikacji nowej wersji aplikacji w Google Play.

Jeśli budżet na infrastrukturę na to pozwala, mikroserwis można uruchomić na dedykowanej instancji lub w osobnym kontenerze, co zwiększa jego skalowalność i pozwala izolować komponent odpowiedzialny za przetwarzanie języka.

W porównaniu do podejścia lokalnego tracimy możliwość działania offline. Dochodzą też koszty związane z transferem danych i utrzymaniem backendu. Zyskujemy natomiast minimalny rozmiar aplikacji oraz elastyczność zarządzania modelem.

OpenAI / GPT jako klasyfikator intencji

Podejście oparte o GPT (np. OpenAI GPT-4o mini) oferuje najwyższą jakość klasyfikacji i największą elastyczność językową. Użytkownik może powiedzieć „coś śmiesznego o lekarzach i chomikach” i model z dużym prawdopodobieństwem rozpozna kontekst i przekaże go dalej jako intencję.

Największą zaletą tego podejścia jest błyskawiczne wdrożenie – nie trzeba trenować własnego modelu, wystarczy przygotować odpowiedni prompt. Dodatkowo każde zapytanie może być logowane i analizowane, co pozwala na stopniowe zbieranie danych do późniejszego trenowania własnego rozwiązania dostrojonego do aplikacji. Z drugiej strony, zastosowanie wymaga aktywnego połączenia z Internetem, a każde wywołanie generuje koszt.

Porównanie wszystkich podejść

Poniższa tabela porównuje pięć podejść do klasyfikacji komend głosowych dla przypadku użycia w aplikacji Jokes Portal. Oceny zostały przyznane w skali od 0 (najgorzej) do 3 (najlepiej). Wartość 0 oznacza, że dane podejście w tej chwili zupełnie nie spełnia wymagań – jest "show stopperem".

Co wybrałem i dlaczego

Po porównaniu wszystkich podejść i skonfrontowaniu ich z rzeczywistymi wymaganiami aplikacji mobilnej Jokes Portal, wybór padł na klasyczny model TF-IDF wytrenowany i zapisany jako artefakt ONNX. Choć nie oferuje on zaawansowanego rozumienia języka, okazał się najbardziej opłacalny i praktyczny. Działa błyskawicznie, nie wymaga połączenia z Internetem, ma śladowy rozmiar i może być łatwo wdrażany oddzielnie dla każdego języka.

Rozwiązania oparte o modele językowe (SLM) lokalnie lub przez blob storage zapewniają większą elastyczność, ale obecnie są zbyt ciężkie (zwłaszcza dla języka polskiego). SLM jako mikroserwis był rozważany jako potencjalne rozwiązanie, jednak przegrywa z modelem dostarczanym przez blob storage pod względem kosztów, elastyczności i prostoty wdrożenia. Dodatkowo nie spełnia kluczowego wymagania działania offline. Z kolei OpenAI, mimo świetnych rezultatów i najwyższej jakości rozpoznawania języka, nie działa bez połączenia z internetem i generuje koszt przy każdym zapytaniu. W kontekście aplikacji opartej na modelu reklamowym jest to zbyt drogie do zastosowania na większą skalę.

TF-IDF (Term Frequency – Inverse Document Frequency) nie jest rozwiązaniem doskonałym, ale w połączeniu z odpowiednim zestawem treningowym spełnia wszystkie kluczowe wymagania użytkowe i techniczne. Na tym etapie rozwoju aplikacji i otaczających nas technologii uważam, że jest to po prostu najlepszy możliwy wybór.

Temat klasyfikacji komend jest innowacyjny i jak każde rozwiązania oparte o AI szybko się rozwija. Jeśli widzisz inne podejścia, masz doświadczenia z podobnymi problemami albo po prostu chcesz podyskutować, wspólnie przemyśleć podobne rozwiązanie – śmiało napisz do mnie lub zostaw komentarz.

0
Subscribe to my newsletter

Read articles from Beniamin Lenarcik directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Beniamin Lenarcik
Beniamin Lenarcik