SPRAWOZDANIE Z ĆWICZENIA LABORATORYJNEGO NR 5
Przedmiot: Systemy dialogowe
Prowadzący: dr inż. Andrzej Wiśniewski
Wykonał: Wojciech Węgrecki
Grupa: I9G2S1
Sporządzić schemat strukturalny (elementy i powiązania - rysunek) oraz opisać działanie portalu głosowego.
Użytkownik po wybraniu numeru telefonu łączy się z serwisem, a dokładniej z serwerem VXML (interpreter VXML) i otrzymuje wiadomość powitalną. Następnie serwer z kodu VXML pobiera informację co ma dalej zrobić i odtwarza opcję jaką chcemy zaproponować użytkownikowi. Użytkownik wypowiada opcję i dalej sprawdzany jest kod. Jest to realizowane do zakończenia rozmowy lub zakończenia programu. Aby serwer rozpoznał plik VXML musi być podany Tag <vxml></vxml>. Dokumenty VXML i inne związane z nimi pliki mogą być przechowywane na hoście udostępnianym przez portal głosowy lub na innym zewnętrznym serwerze.
Interpreter może wykonywać następujące zadania:
wysyłanie do użytkownika podpowiedzi głosowych, wiadomości lub innych materiałów audio (jak muzyka i efekty dźwiękowe);
przyjmowanie wejść numerycznych, które wprowadza użytkownik za pomocą sygnałów DTMF (telefon tonowy);
przyjmowanie wejść głosowych i rozpoznawanie słów;
przyjmowanie i nagrywanie wejść głosowych (bez rozpoznawania słów);
przesyłanie informacji użytkownika na strony sieciowe lub inne serwery internetowe;
otrzymywanie informacji z Internetu i przekazywanie jej do użytkownika.
Dodatkowo w VXML można wykonywać operacje arytmetyczne, logiczne oraz operacje na tekście. Rozmowa użytkownika z programem nie musi przebiegać za każdym razem tak samo, stosuje się do tego np. dyrektywy if-then-else. Testowanie aplikacji odbywa się przez połączenie z odpowiednim numerem telefonicznym i interakcję z nią.
rys. 1 Schemat portalu głosowego
Zaprojektować prostą aplikację głosową (temat aplikacji wybiera student):
identyfikacja aplikacji (przykładowe dialogi);
opracowanie modelu (scenariusza) dialogu w postaci schematu blokowego;
opis dostępu użytkownika do aplikacji.
Wybraną przeze mnie aplikacją jest obsługa pizzerii.
identyfikacja aplikacji (przykładowe dialogi);
Przykładowy Dialog 1:
Aplikacja: Welcome in pizzeria Ghost. Choose your pizza. Bacon, ham, salami, vegetarian or end.
Użytkownik: Bacon
A: your choice is bacon. Would you like any drink? Say yes or no.
U: yes
A: What drink do you prefer? Cola, fanta, sprite?
U: fanta.
A: Would you like any sauce? Say yes or no.
U: no
A: Would you like eat in our local or home? Say home or local.
U: local.
A: Thank you for order and we invite to Wall Street 25. Good bye.
Przykładowy Dialog 2:
A: Welcome in pizzeria Ghost. Choose your pizza. Bacon, ham, salami, vegetarian or end.
U: Ham
A: Your choice is ham. Would you like any drink? Say yes or no.
U: Yes
A: What drink do you prefer? Cola, fanta, sprite?
U: Sprite.
A: Would you like any sauce? Say yes or no.
U: Yes
A: What sauce do you prefer? Tomato or garlic?
U: Garlic
A: Would you like eat in our local or home? Say home or local.
U: Home.
A: Where deliver the order? Wall Street, Ghost Street, Police Street or School Street?
U: Wall Street.
A: You chose Wall Street. We'll send order. Please wait. Thank you and invite again. Goodbye.
opracowanie modelu (scenariusza) dialogu w postaci schematu blokowego;
Prompt `Welcome in pizzeria Ghost. Choose your pizza. Bacon, ham, salami, vegetarian or end.'
|
||||
bacon |
ham |
salami |
vegetarian |
end |
Prompt 'your choice is bacon' |
Prompt `your choice is ham' |
Prompt `your choice is salami' |
Prompt `your choice is vegetarian' |
Prompt 'your choice is End. Thank you and invite again. Goodbye' |
Prompt `Would you like any drink? Say yes or no.' |
|
yes |
no |
Prompt `What drink do you prefer? Cola, fanta, sprite?' |
||||
cola |
fanta |
sprite |
||
Prompt `Would you like any sauce? Say yes or no.' |
||||
no |
yes |
Prompt `What sauce do you prefer? Tomato or garlic?' |
|
tomato |
garlic |
Prompt `Would you like eat in our local or home? Say home or local.' |
|
home |
local |
|
||||
Prompt `Where deliver the order? Wall Street, Ghost Street, Police Street or School Street?' |
||||
|
Ghost Street |
Police Street |
School Street |
You chose Wall Street. We'll send order. Please wait. Thank you and invite again. Goodbye. |
You chose Ghost Street. We'll send order. Please wait. Thank you and invite again. Goodbye. |
You chose Police Street. We'll send order. Please wait. Thank you and invite again. Goodbye. |
You chose School Street. We'll send order. Please wait. Thank you and invite again. Goodbye. |
opis dostępu użytkownika do aplikacji
Użytkownik może w wieloraki sposób skorzystać z aplikacji. Portal voxeo umożliwia połączenie z aplikacją z różnych krańców świata generując numery telefonów poszczególnych krajów oraz dodatkowym atutem jest dostępność bezpłatnego (dla użytkowników) numeru skype. Poniżej przedstawiam zrzut ekranu przedstawiający numery telefonów, dzięki którym można połączyć się z moją aplikacją.
Utworzenie aplikacji w postaci dokumentu VXML:
opatrzyć komentarzem wszystkie jej znaczniki.
testowanie (iteracyjne) w celu udoskonalenia interfejsu.
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.1"> <!-- -->
Na początku programu deklaruje sobie jak będzie się on zachowywał jeśli nie zrozumie danego słowa lub jeśli użytkownik go nie poda.
<!--Kwestia wypowiadana jeśli program błędnie dopasował wypowiedziane słowo-->
<nomatch><!--Brak dopasowania-->
Please repeat, i did't understand.
<reprompt/><!--Wypowiedzenie ponowne po ponownej wizycie-->
</nomatch>
<!--Kwestia wypowiadana jeśli program nie wykrył wypowiedzianego słowa-->
<noinput><!--brak wypowiedzi-->
Please repeat, i didn't hear.
<reprompt/>
</noinput>
Kolejnym krokiem było przejście już do sedna naszego programu, czyli kwestii wypowiadanych przez aplikację oraz możliwe odpowiedzi klienta naszej pizzerii. Na początku klient mógł wybrać pizzę z czterech podanych w podpowiedzi lub zakończyć program.
<!--Deklaracja formularza odpowiadającego za wybór pizzy-->
<form id="pizzeria"><!--prezentacja dialogu do wydobycia informacji od użytkownika. atrybuty: id(nazwa) scope(zasięg)-->
<property name="input" value="voice"/>
<field name="Menu"> <!--definiowanie pola. atrybuty: name(nazwa), expr(wypowiedz), cond(warunek), type(typ), slot(nazwa gramatyki), modal-->
<!--Wiadomość powitalna-->
<prompt><!--wypowiadanie kwestii-->
Welcome in pizzeria Ghost. Choose your pizza. Bacon, ham, salami, vegetarian or end.
</prompt>
Użytkownik dokonuje wyboru w oparciu o następującą gramatykę.
<!--Definiowanie słów jakie mogą zostać wypowiedziane przez użytkownika-->
<grammar mode="voice" root="Choice"> <!--specyfikacja rozpoznawania mowy. atrybuty: mode, root, version, xml:lang, tag-format, xml:base -->
<rule id="Choice" scope="public"> <!--definicja zasad. atrybuty: id(nazwa), scope(zasięg)-->
<one-of> <!-- jeden z-->
<item>bacon</item>
<item>ham</item>
<item>salami</item>
<item>vegetarian</item>
<item>end</item>
</one-of>
</rule>
</grammar>
Następnie sprawdzane jest jakie słowo zostało wypowiedziane i co w danym przypadku zrobić. W moim przypadku wypowiadany jest wybór pizzy i przechodzenie do menu pytającego o chęć zamówienia napoju. W przypadku wybrania „end ” użytkownik otrzymuje komunikat i program kończy działanie.
<!-- Deklarowanie co będzie wykonywane po rozpoznaniu danego słowa -->
<filled namelist="Menu"> <!--akcja wykonywana kiedy pola są wypełnione. atrybuty: mode, namelist(nazwa)-->
<if cond="Menu == 'bacon'"> <!--warunek-->
<prompt>your choice is bacon </prompt>
<goto next="#czy_chcesz_napoj"/> <!-- miejsce następnego kroku w naszym przypadku formularz czy_chcesz_napoj,
atrybuty: expr(wypowiedź)-->
<elseif cond="Menu == 'ham'"/>
<prompt>your choice is ham.</prompt>
<goto next="#czy_chcesz_napoj"/>
<elseif cond="Menu == 'salami'"/>
<prompt>your choice is salami.</prompt>
<goto next="#czy_chcesz_napoj"/>
<elseif cond="Menu == 'vegetarian'"/>
<prompt>your choice is vegetarian</prompt>
<goto next="#czy_chcesz_napoj"/>
<elseif cond="Menu == 'end'"/>
<prompt>your choice is End. Thank you and invite again. Goodbye.</prompt>
</if>
</filled>
</field>
</form>
Kolejne kroki to po prostu następne pytania, jakie zadaje aplikacja. Wykonane jest to analogicznie do pierwszego formularza. Co wykonuje dany formularz napisałem w komentarzach przed każdym z nich.
<!-- Formularz sprawdzajacy, czy klient chce napoj -->
<form id ="czy_chcesz_napoj">
<field name="Menu_drink">
<prompt>
Would you like any drink? Say yes or no.
</prompt>
<grammar mode="voice" root="drink">
<rule id="drink" scope="public">
<one-of>
<item>yes</item>
<item>no</item>
</one-of>
</rule>
</grammar>
<filled namelist="Menu_drink">
<if cond="Menu_drink == 'yes'">
<goto next="#wybor_napoju"/>
<elseif cond="Menu_drink == 'no'"/>
<goto next="#czy_chcesz_sos"/>
</if>
</filled>
</field>
</form>
<!-- Formularz sprawdzajacy jaki klient chce napoj -->
<form id ="wybor_napoju">
<field name="Choice_drink">
<prompt>
What drink do you prefer? Cola, fanta, sprite?
</prompt>
<grammar mode="voice" root="drink_choice">
<rule id="drink_choice" scope="public">
<one-of>
<item>cola</item>
<item>fanta</item>
<item>sprite</item>
</one-of>
</rule>
</grammar>
<filled namelist="Choice_drink">
<if cond="Choice_drink == 'cola'">
<prompt>You chose cola.</prompt>
<goto next="#czy_chcesz_sos"/>
<elseif cond="Choice_drink == 'fanta'"/>
<prompt>You chose fanta</prompt>.
<goto next="#czy_chcesz_sos"/>
<elseif cond="Choice_drink == 'sprite'"/>
<prompt>You chose sprite</prompt>.
<goto next="#czy_chcesz_sos"/>
</if>
</filled>
</field>
</form>
<!-- Formularz sprawdzajacy, czy klient chce sos -->
<form id ="czy_chcesz_sos">
<field name="Menu_sauce">
<prompt>
Would you like any sauce? Say yes or no.
</prompt>
<grammar mode="voice" root="sauce">
<rule id="sauce" scope="public">
<one-of>
<item>yes</item>
<item>no</item>
</one-of>
</rule>
</grammar>
<filled namelist="Menu_sauce">
<if cond="Menu_sauce == 'yes'">
<goto next="#wybor_sosu"/>
<elseif cond="Menu_sauce == 'no'"/>
<goto next="#czy_dostawa"/>
</if>
</filled>
</field>
</form>
<!-- Formularz sprawdzajacy jaki klient chce sos -->
<form id ="wybor_sosu">
<field name="Choice_sauce">
<prompt>
What sauce do you prefer? Tomato or garlic?
</prompt>
<grammar mode="voice" root="sauce_choice">
<rule id="sauce_choice" scope="public">
<one-of>
<item>tomato</item>
<item>garlic</item>
</one-of>
</rule>
</grammar>
<filled namelist="Choice_sauce">
<if cond="Choice_sauce == 'tomato'">
<prompt>You chose tomato.</prompt>
<goto next="#czy_dostawa"/>
<elseif cond="Choice_sauce == 'garlic'"/>
<prompt>You chose garlic</prompt>.
<goto next="#czy_dostawa"/>
</if>
</filled>
</field>
</form>
<!-- Formularz sprawdzajacy, czy klient chce zjesc w lokalu, czy w domu -->
<form id ="czy_dostawa">
<field name="Menu_czy_dostawa">
<prompt>
Would you like eat in our local or home? Say home or local.
</prompt>
<grammar mode="voice" root="dostawa">
<rule id="dostawa" scope="public">
<one-of>
<item>home</item>
<item>local</item>
</one-of>
</rule>
</grammar>
<filled namelist="Menu_czy_dostawa">
<if cond="Menu_czy_dostawa == 'home'">
<goto next="#gdzie_dostawa"/>
<elseif cond="Menu_czy_dostawa == 'local'"/>
<prompt>Thank you for order. We invite to Wall Street 25. Good bye.</prompt>
</if>
</filled>
</field>
</form>
<!-- Formularz sprawdzajacy gdzie klient chce otrzymac dostawe -->
<form id ="gdzie_dostawa">
<field name="Choice_dostawa">
<prompt>
Where deliver the order? Wall Street, Ghost Street, Police Street or School Street?
</prompt>
<grammar mode="voice" root="dostawa_choice">
<rule id="dostawa_choice" scope="public">
<one-of>
<item>Wall Street</item>
<item>Ghost Street</item>
<item>Police Street</item>
<item>School Street</item>
</one-of>
</rule>
</grammar>
<filled namelist="Choice_dostawa">
<if cond="Choice_dostawa == 'Wall Street'">
<prompt>You chose Wall Street. We'll send order. Please wait. Thank you and invite again. Goodbye.</prompt>
<elseif cond="Choice_dostawa == 'Ghost Street'"/>
<prompt>You chose Ghost Street. We'll send order. Please wait. Thank you and invite again. Goodbye.</prompt>
<elseif cond="Choice_dostawa == 'Police Street'"/>
<prompt>You chose Police Street. We'll send order. Please wait. Thank you and invite again. Goodbye.</prompt>
<elseif cond="Choice_dostawa == 'School Street'"/>
<prompt>You chose School Street. We'll send order. Please wait. Thank you and invite again. Goodbye.</prompt>
</if>
</filled>
</field>
</form>
</vxml>
Wydaje mi się, że mój program po kilku poprawkach i rozbudowaniu go mógłby być w pełni funkcjonalną aplikacją dla pizzerii. Na pewno usprawniłoby to funkcjonowanie takiej placówki i mogłoby zmniejszyć koszty utrzymania, gdyż nie byłaby potrzebna osoba do odbierania zamówień. W moim programie nie ma dodatkowych podpowiedzi gdy użytkownik błędnie wypowie zdanie. Po prostu w każdej dyrektywie „prompt” podaje użytkownikowi konkretnie co ma powiedzieć i od razu nakierowuje go na odpowiedź jaka jest rozpoznawalna przez program. Mimo niezbyt skomplikowanego rozwiązania wydaje mi się, że jest to funkcjonalne i nie powinno przysparzać klientowi zbyt dużo kłopotów, gdyż wypowiadałby bardzo krótkie frazy. Po kilkukrotnym przetestowaniu programu mogę stwierdzić, ze nie trzeba bardzo wyraźnie wypowiadać słów, żeby zostały one poprawnie rozpoznane, co jest dodatkowym atutem. Główną wadą mojego rozwiązania jest to, że wykonana jest w języku angielskim, jednak istnieją portale (w tym także voxeo), które obsługują język polski i przy większej ilości czasu to też nie stanowiłoby problemu. Podsumowując, uważam że wykonanie takiego portalu głosowego było ciekawym doświadczeniem i w dzisiejszych czasach, w których dużą uwagę skupia się na zautomatyzowaniu wszelkich działań będzie to bardzo przydatna umiejętność.