|
|
<!--
|
|
|
CO_OP_TRANSLATOR_METADATA:
|
|
|
{
|
|
|
"original_hash": "6f4ba69d77f16c4a5110623a96a215c3",
|
|
|
"translation_date": "2025-08-28T12:33:55+00:00",
|
|
|
"source_file": "6-consumer/lessons/2-language-understanding/README.md",
|
|
|
"language_code": "sr"
|
|
|
}
|
|
|
-->
|
|
|
# Разумевање језика
|
|
|
|
|
|

|
|
|
|
|
|
> Скица коју је направила [Нитија Нарасимхан](https://github.com/nitya). Кликните на слику за већу верзију.
|
|
|
|
|
|
## Квиз пре предавања
|
|
|
|
|
|
[Квиз пре предавања](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/43)
|
|
|
|
|
|
## Увод
|
|
|
|
|
|
У претходној лекцији сте претварали говор у текст. Да би се то искористило за програмирање паметног тајмера, ваш код ће морати да разуме шта је речено. Могли бисте претпоставити да ће корисник изговорити фиксну фразу, као што је „Подеси тајмер на 3 минута“, и анализирати тај израз да бисте добили трајање тајмера, али то није баш кориснички пријатно. Ако би корисник рекао „Подеси тајмер за 3 минута“, ви или ја бисмо разумели шта то значи, али ваш код не би, јер би очекивао фиксну фразу.
|
|
|
|
|
|
Овде на сцену ступа разумевање језика, користећи AI моделе за тумачење текста и враћање потребних детаља, на пример могућност да се разумеју и „Подеси тајмер на 3 минута“ и „Подеси тајмер за 3 минута“ као захтев за тајмер од 3 минута.
|
|
|
|
|
|
У овој лекцији ћете научити о моделима за разумевање језика, како их креирати, обучити и користити у вашем коду.
|
|
|
|
|
|
У овој лекцији ћемо обрадити:
|
|
|
|
|
|
* [Разумевање језика](../../../../../6-consumer/lessons/2-language-understanding)
|
|
|
* [Креирање модела за разумевање језика](../../../../../6-consumer/lessons/2-language-understanding)
|
|
|
* [Намере и ентитети](../../../../../6-consumer/lessons/2-language-understanding)
|
|
|
* [Коришћење модела за разумевање језика](../../../../../6-consumer/lessons/2-language-understanding)
|
|
|
|
|
|
## Разумевање језика
|
|
|
|
|
|
Људи користе језик за комуникацију стотинама хиљада година. Комуницирамо речима, звуковима или акцијама и разумемо шта је речено, како значење речи, звукова или акција, тако и њихов контекст. Разумемо искреност и сарказам, што омогућава да исте речи значе различите ствари у зависности од тона нашег гласа.
|
|
|
|
|
|
✅ Размислите о неким разговорима које сте недавно водили. Колико би било тешко за рачунар да разуме те разговоре због потребе за контекстом?
|
|
|
|
|
|
Разумевање језика, такође познато као природно разумевање језика, је део области вештачке интелигенције која се зове обрада природног језика (или NLP) и бави се читањем и разумевањем текста, покушавајући да разуме детаље речи или реченица. Ако користите гласовног асистента као што су Алекса или Сири, већ сте користили услуге за разумевање језика. То су AI услуге које иза сцене претварају „Алекса, пусти најновији албум Тејлор Свифт“ у моју ћерку која игра у дневној соби уз своје омиљене песме.
|
|
|
|
|
|
> 💁 Рачунари, упркос свим својим напрецима, и даље имају дуг пут до истинског разумевања текста. Када говоримо о разумевању језика код рачунара, не мислимо на нешто ни приближно напредно као људска комуникација, већ на узимање речи и извлачење кључних детаља.
|
|
|
|
|
|
Као људи, разумемо језик без много размишљања. Ако бих замолио другу особу да „пусти најновији албум Тејлор Свифт“, она би инстинктивно знала шта мислим. За рачунар, ово је теже. Он би морао да узме речи, претворене из говора у текст, и утврди следеће информације:
|
|
|
|
|
|
* Потребно је пустити музику
|
|
|
* Музика је од извођача Тејлор Свифт
|
|
|
* Конкретна музика је цео албум са више песама у одређеном редоследу
|
|
|
* Тејлор Свифт има много албума, па их треба сортирати хронолошки и изабрати најновији
|
|
|
|
|
|
✅ Размислите о неким другим реченицама које сте изговорили приликом упућивања захтева, као што је наручивање кафе или тражење од члана породице да вам нешто дода. Покушајте да их разложите на делове информација које би рачунар морао да извуче да би разумео реченицу.
|
|
|
|
|
|
Модели за разумевање језика су AI модели који су обучени да извлаче одређене детаље из језика, а затим се обучавају за специфичне задатке користећи трансфер учење, на исти начин на који сте обучавали модел за прилагођену визију користећи мали сет слика. Можете узети модел, а затим га обучити користећи текст који желите да разуме.
|
|
|
|
|
|
## Креирање модела за разумевање језика
|
|
|
|
|
|

|
|
|
|
|
|
Моделе за разумевање језика можете креирати користећи LUIS, услугу за разумевање језика компаније Microsoft која је део Cognitive Services.
|
|
|
|
|
|
### Задатак - креирање ресурса за ауторство
|
|
|
|
|
|
Да бисте користили LUIS, потребно је да креирате ресурс за ауторство.
|
|
|
|
|
|
1. Користите следећу команду да креирате ресурс за ауторство у вашој `smart-timer` ресурсној групи:
|
|
|
|
|
|
```python
|
|
|
az cognitiveservices account create --name smart-timer-luis-authoring \
|
|
|
--resource-group smart-timer \
|
|
|
--kind LUIS.Authoring \
|
|
|
--sku F0 \
|
|
|
--yes \
|
|
|
--location <location>
|
|
|
```
|
|
|
|
|
|
Замените `<location>` локацијом коју сте користили приликом креирања ресурсне групе.
|
|
|
|
|
|
> ⚠️ LUIS није доступан у свим регионима, па ако добијете следећу грешку:
|
|
|
>
|
|
|
> ```output
|
|
|
> InvalidApiSetId: The account type 'LUIS.Authoring' is either invalid or unavailable in given region.
|
|
|
> ```
|
|
|
>
|
|
|
> изаберите други регион.
|
|
|
|
|
|
Ово ће креирати бесплатан ресурс за ауторство у LUIS-у.
|
|
|
|
|
|
### Задатак - креирање апликације за разумевање језика
|
|
|
|
|
|
1. Отворите LUIS портал на [luis.ai](https://luis.ai?WT.mc_id=academic-17441-jabenn) у вашем претраживачу и пријавите се са истим налогом који сте користили за Azure.
|
|
|
|
|
|
1. Пратите упутства у дијалогу да изаберете вашу Azure претплату, а затим изаберите ресурс `smart-timer-luis-authoring` који сте управо креирали.
|
|
|
|
|
|
1. Са листе *Conversation apps*, изаберите дугме **New app** да креирате нову апликацију. Назовите нову апликацију `smart-timer` и подесите *Culture* на ваш језик.
|
|
|
|
|
|
> 💁 Постоји поље за ресурс за предвиђање. Можете креирати други ресурс само за предвиђање, али бесплатан ресурс за ауторство омогућава 1.000 предвиђања месечно, што би требало да буде довољно за развој, тако да ово поље можете оставити празно.
|
|
|
|
|
|
1. Прочитајте водич који се појављује након што креирате апликацију да бисте разумели кораке које треба предузети за обуку модела за разумевање језика. Затворите овај водич када завршите.
|
|
|
|
|
|
## Намере и ентитети
|
|
|
|
|
|
Разумевање језика се заснива на *намерaма* и *ентитетима*. Намере представљају шта је намера речи, на пример пуштање музике, подешавање тајмера или наручивање хране. Ентитети представљају на шта се намера односи, као што су албум, трајање тајмера или врста хране. Свака реченица коју модел интерпретира треба да има најмање једну намеру и опционално један или више ентитета.
|
|
|
|
|
|
Неколико примера:
|
|
|
|
|
|
| Реченица | Намера | Ентитети |
|
|
|
| -------------------------------------------------- | ---------------- | ------------------------------------------ |
|
|
|
| „Пусти најновији албум Тејлор Свифт“ | *пусти музику* | *најновији албум Тејлор Свифт* |
|
|
|
| „Подеси тајмер на 3 минута“ | *подеси тајмер* | *3 минута* |
|
|
|
| „Откажи мој тајмер“ | *откажи тајмер* | Нема |
|
|
|
| „Наручи 3 велике пице са ананасом и Цезар салату“ | *наручи храну* | *3 велике пице са ананасом*, *Цезар салата* |
|
|
|
|
|
|
✅ Са реченицама о којима сте раније размишљали, која би била намера и који ентитети у тој реченици?
|
|
|
|
|
|
Да бисте обучили LUIS, прво подешавате ентитете. Они могу бити фиксна листа термина или научени из текста. На пример, могли бисте обезбедити фиксну листу хране доступне у вашем менију, са варијацијама (или синонимима) за сваку реч, као што су *патлиџан* и *меланжана* као варијације за *патлиџан*. LUIS такође има унапред дефинисане ентитете који се могу користити, као што су бројеви и локације.
|
|
|
|
|
|
За подешавање тајмера, могли бисте имати један ентитет који користи унапред дефинисане бројеве за време и други за јединице, као што су минути и секунде. Свака јединица би имала више варијација да покрије једнину и множину - као што су минут и минути.
|
|
|
|
|
|
Када се ентитети дефинишу, креирате намере. Оне се уче од стране модела на основу примера реченица које обезбедите (познатих као изјаве). На пример, за намеру *подеси тајмер*, могли бисте обезбедити следеће реченице:
|
|
|
|
|
|
* `подеси тајмер на 1 секунду`
|
|
|
* `подеси тајмер на 1 минут и 12 секунди`
|
|
|
* `подеси тајмер на 3 минута`
|
|
|
* `подеси тајмер на 9 минута и 30 секунди`
|
|
|
|
|
|
Затим кажете LUIS-у који делови ових реченица одговарају ентитетима:
|
|
|
|
|
|

|
|
|
|
|
|
Реченица `подеси тајмер на 1 минут и 12 секунди` има намеру `подеси тајмер`. Такође има 2 ентитета са по 2 вредности:
|
|
|
|
|
|
| | време | јединица |
|
|
|
| ---------- | ---: | ---------- |
|
|
|
| 1 минут | 1 | минут |
|
|
|
| 12 секунди | 12 | секунда |
|
|
|
|
|
|
Да бисте обучили добар модел, потребан вам је низ различитих примера реченица који покривају многе различите начине на које неко може тражити исту ствар.
|
|
|
|
|
|
> 💁 Као и код било ког AI модела, што више података и што су подаци прецизнији, то ће модел бити бољи.
|
|
|
|
|
|
✅ Размислите о различитим начинима на које бисте могли тражити исту ствар и очекивати да вас човек разуме.
|
|
|
|
|
|
### Задатак - додавање ентитета у моделе за разумевање језика
|
|
|
|
|
|
За тајмер, потребно је додати 2 ентитета - један за јединицу времена (минути или секунде) и један за број минута или секунди.
|
|
|
|
|
|
Упутства за коришћење LUIS портала можете пронаћи у [Quickstart: Build your app in LUIS portal документацији на Microsoft Docs](https://docs.microsoft.com/azure/cognitive-services/luis/luis-get-started-create-app?WT.mc_id=academic-17441-jabenn).
|
|
|
|
|
|
1. Са LUIS портала, изаберите картицу *Entities* и додајте унапред дефинисани ентитет *number* кликом на дугме **Add prebuilt entity**, а затим изаберите *number* са листе.
|
|
|
|
|
|
1. Креирајте нови ентитет за јединицу времена користећи дугме **Create**. Назовите ентитет `time unit` и подесите тип на *List*. Додајте вредности за `minute` и `second` у листу *Normalized values*, додајући једнину и множину у листу *synonyms*. Притисните `return` након додавања сваког синонима да бисте га додали у листу.
|
|
|
|
|
|
| Нормализована вредност | Синоними |
|
|
|
| ----------------------- | --------------- |
|
|
|
| минут | минут, минути |
|
|
|
| секунда | секунда, секунде|
|
|
|
|
|
|
### Задатак - додавање намера у моделе за разумевање језика
|
|
|
|
|
|
1. Са картице *Intents*, изаберите дугме **Create** да креирате нову намеру. Назовите ову намеру `set timer`.
|
|
|
|
|
|
1. У примерима, унесите различите начине за подешавање тајмера користећи и минуте, секунде и комбинацију минута и секунди. Примери могу бити:
|
|
|
|
|
|
* `подеси тајмер на 1 секунду`
|
|
|
* `подеси тајмер на 4 минута`
|
|
|
* `подеси тајмер на четири минута и шест секунди`
|
|
|
* `подеси тајмер на 9 минута и 30 секунди`
|
|
|
* `подеси тајмер на 1 минут и 12 секунди`
|
|
|
* `подеси тајмер на 3 минута`
|
|
|
* `подеси тајмер на 3 минута и 1 секунду`
|
|
|
* `подеси тајмер на три минута и једну секунду`
|
|
|
* `подеси тајмер на 1 минут и 1 секунду`
|
|
|
* `подеси тајмер на 30 секунди`
|
|
|
* `подеси тајмер на 1 секунду`
|
|
|
|
|
|
Мешајте бројеве као речи и бројеве како би модел научио да обрађује оба.
|
|
|
|
|
|
1. Како уносите сваки пример, LUIS ће почети да детектује ентитете и подвлачиће и означавати све које пронађе.
|
|
|
|
|
|

|
|
|
|
|
|
### Задатак - обука и тестирање модела
|
|
|
|
|
|
1. Када су ентитети и намере конфигурисани, можете обучити модел користећи дугме **Train** у горњем менију. Изаберите ово дугме, и модел би требало да се обучи за неколико секунди. Дугме ће бити онемогућено током обуке, и поново ће бити омогућено када се заврши.
|
|
|
|
|
|
1. Изаберите дугме **Test** из горњег менија да тестирате модел за разумевање језика. Унесите текст као што је `подеси тајмер на 5 минута и 4 секунде` и притисните `return`. Реченица ће се појавити у оквиру испод текстуалног поља у које сте је унели, а испод тога ће бити *најбоља намера*, односно намера која је детектована са највишом вероватноћом. Ово би требало да буде `set timer`. Назив намере ће бити праћен вероватноћом да је детектована намера исправна.
|
|
|
|
|
|
1. Изаберите опцију **Inspect** да видите детаљан преглед резултата. Видећете намеру са највишим резултатом и њену процентуалну вероватноћу, заједно са листама детектованих ентитета.
|
|
|
|
|
|
1. Затворите панел *Test* када завршите тестирање.
|
|
|
|
|
|
### Задатак - објављивање модела
|
|
|
|
|
|
Да бисте користили овај модел из кода, потребно је да га објавите. Када објављујете из LUIS-а, можете објавити у окружење за тестирање (staging) или у продукцијско окружење. У овој лекцији, окружење за тестирање је довољно.
|
|
|
|
|
|
1. Са LUIS портала, изаберите дугме **Publish** из горњег менија.
|
|
|
|
|
|
1. Уверите се да је изабран *Staging slot*, а затим изаб
|
|
|
1. Из секције *Azure Resources* изаберите *Authoring Resource* и копирајте *Primary Key* и *Endpoint URL*.
|
|
|
|
|
|
1. Покрените следећу curl команду у вашем командном прозору или терминалу:
|
|
|
|
|
|
```sh
|
|
|
curl "<endpoint url>/luis/prediction/v3.0/apps/<app id>/slots/staging/predict" \
|
|
|
--request GET \
|
|
|
--get \
|
|
|
--data "subscription-key=<primary key>" \
|
|
|
--data "verbose=false" \
|
|
|
--data "show-all-intents=true" \
|
|
|
--data-urlencode "query=<sentence>"
|
|
|
```
|
|
|
|
|
|
Замените `<endpoint url>` са Endpoint URL из секције *Azure Resources*.
|
|
|
|
|
|
Замените `<app id>` са App ID из секције *Settings*.
|
|
|
|
|
|
Замените `<primary key>` са Primary Key из секције *Azure Resources*.
|
|
|
|
|
|
Замените `<sentence>` са реченицом коју желите да тестирате.
|
|
|
|
|
|
1. Излаз ове команде биће JSON документ који детаљно описује упит, главну намеру и листу ентитета разложених по типу.
|
|
|
|
|
|
```JSON
|
|
|
{
|
|
|
"query": "set a timer for 45 minutes and 12 seconds",
|
|
|
"prediction": {
|
|
|
"topIntent": "set timer",
|
|
|
"intents": {
|
|
|
"set timer": {
|
|
|
"score": 0.97031575
|
|
|
},
|
|
|
"None": {
|
|
|
"score": 0.02205793
|
|
|
}
|
|
|
},
|
|
|
"entities": {
|
|
|
"number": [
|
|
|
45,
|
|
|
12
|
|
|
],
|
|
|
"time-unit": [
|
|
|
[
|
|
|
"minute"
|
|
|
],
|
|
|
[
|
|
|
"second"
|
|
|
]
|
|
|
]
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
JSON изнад је добијен упитом са `set a timer for 45 minutes and 12 seconds`:
|
|
|
|
|
|
* `set timer` је била главна намера са вероватноћом од 97%.
|
|
|
* Детектована су два ентитета типа *number*, `45` и `12`.
|
|
|
* Детектована су два ентитета типа *time-unit*, `minute` и `second`.
|
|
|
|
|
|
## Коришћење модела за разумевање језика
|
|
|
|
|
|
Када се објави, LUIS модел може се позивати из кода. У претходним лекцијама користили сте IoT Hub за комуникацију са cloud сервисима, слање телеметрије и примање команди. Ово је веома асинхроно - када пошаљете телеметрију, ваш код не чека одговор, а ако cloud сервис није доступан, нећете знати.
|
|
|
|
|
|
За паметни тајмер, желимо одговор одмах, како бисмо кориснику могли рећи да је тајмер подешен или га упозорити да cloud сервиси нису доступни. Да бисмо то урадили, наш IoT уређај ће директно позивати веб endpoint, уместо да се ослања на IoT Hub.
|
|
|
|
|
|
Уместо да позивате LUIS директно са IoT уређаја, можете користити serverless код са другачијим типом тригера - HTTP тригер. Ово омогућава вашој функцији да слуша REST захтеве и одговара на њих. Ова функција ће бити REST endpoint који ваш уређај може позвати.
|
|
|
|
|
|
> 💁 Иако можете директно позивати LUIS са вашег IoT уређаја, боље је користити нешто попут serverless кода. На овај начин, када желите да промените LUIS апликацију коју позивате, на пример када обучите бољи модел или модел на другом језику, потребно је само да ажурирате cloud код, а не да поново дистрибуирате код на потенцијално хиљаде или милионе IoT уређаја.
|
|
|
|
|
|
### Задатак - креирање serverless функције
|
|
|
|
|
|
1. Креирајте Azure Functions апликацију под називом `smart-timer-trigger` и отворите је у VS Code.
|
|
|
|
|
|
1. Додајте HTTP тригер овој апликацији под називом `speech-trigger` користећи следећу команду из VS Code терминала:
|
|
|
|
|
|
```sh
|
|
|
func new --name text-to-timer --template "HTTP trigger"
|
|
|
```
|
|
|
|
|
|
Ово ће креирати HTTP тригер под називом `text-to-timer`.
|
|
|
|
|
|
1. Тестирајте HTTP тригер покретањем функције. Када се покрене, видећете endpoint у излазу:
|
|
|
|
|
|
```output
|
|
|
Functions:
|
|
|
|
|
|
text-to-timer: [GET,POST] http://localhost:7071/api/text-to-timer
|
|
|
```
|
|
|
|
|
|
Тестирајте ово учитавањем [http://localhost:7071/api/text-to-timer](http://localhost:7071/api/text-to-timer) URL-а у вашем претраживачу.
|
|
|
|
|
|
```output
|
|
|
This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.
|
|
|
```
|
|
|
|
|
|
### Задатак - коришћење модела за разумевање језика
|
|
|
|
|
|
1. SDK за LUIS је доступан преко Pip пакета. Додајте следећу линију у `requirements.txt` фајл како бисте додали зависност од овог пакета:
|
|
|
|
|
|
```sh
|
|
|
azure-cognitiveservices-language-luis
|
|
|
```
|
|
|
|
|
|
1. Уверите се да је виртуелно окружење активирано у VS Code терминалу и покрените следећу команду за инсталацију Pip пакета:
|
|
|
|
|
|
```sh
|
|
|
pip install -r requirements.txt
|
|
|
```
|
|
|
|
|
|
> 💁 Ако добијете грешке, можда ћете морати да ажурирате pip помоћу следеће команде:
|
|
|
>
|
|
|
> ```sh
|
|
|
> pip install --upgrade pip
|
|
|
> ```
|
|
|
|
|
|
1. Додајте нове уносе у `local.settings.json` фајл за ваш LUIS API Key, Endpoint URL и App ID из **MANAGE** таба LUIS портала:
|
|
|
|
|
|
```JSON
|
|
|
"LUIS_KEY": "<primary key>",
|
|
|
"LUIS_ENDPOINT_URL": "<endpoint url>",
|
|
|
"LUIS_APP_ID": "<app id>"
|
|
|
```
|
|
|
|
|
|
Замените `<endpoint url>` са Endpoint URL из секције *Azure Resources* у **MANAGE** табу. Ово ће бити `https://<location>.api.cognitive.microsoft.com/`.
|
|
|
|
|
|
Замените `<app id>` са App ID из секције *Settings* у **MANAGE** табу.
|
|
|
|
|
|
Замените `<primary key>` са Primary Key из секције *Azure Resources* у **MANAGE** табу.
|
|
|
|
|
|
1. Додајте следеће увозе у `__init__.py` фајл:
|
|
|
|
|
|
```python
|
|
|
import json
|
|
|
import os
|
|
|
from azure.cognitiveservices.language.luis.runtime import LUISRuntimeClient
|
|
|
from msrest.authentication import CognitiveServicesCredentials
|
|
|
```
|
|
|
|
|
|
Ово увози неке системске библиотеке, као и библиотеке за интеракцију са LUIS-ом.
|
|
|
|
|
|
1. Обришите садржај `main` методе и додајте следећи код:
|
|
|
|
|
|
```python
|
|
|
luis_key = os.environ['LUIS_KEY']
|
|
|
endpoint_url = os.environ['LUIS_ENDPOINT_URL']
|
|
|
app_id = os.environ['LUIS_APP_ID']
|
|
|
|
|
|
credentials = CognitiveServicesCredentials(luis_key)
|
|
|
client = LUISRuntimeClient(endpoint=endpoint_url, credentials=credentials)
|
|
|
```
|
|
|
|
|
|
Ово учитава вредности које сте додали у `local.settings.json` фајл за вашу LUIS апликацију, креира објекат са акредитивима користећи ваш API кључ, а затим креира LUIS клијент објекат за интеракцију са вашом LUIS апликацијом.
|
|
|
|
|
|
1. Овај HTTP тригер ће бити позван са текстом за разумевање као JSON, са текстом у својству под називом `text`. Следећи код екстрахује вредност из тела HTTP захтева и бележи је у конзолу. Додајте овај код у `main` функцију:
|
|
|
|
|
|
```python
|
|
|
req_body = req.get_json()
|
|
|
text = req_body['text']
|
|
|
logging.info(f'Request - {text}')
|
|
|
```
|
|
|
|
|
|
1. Предвиђања се траже од LUIS-а слањем захтева за предвиђање - JSON документа који садржи текст за предвиђање. Креирајте ово помоћу следећег кода:
|
|
|
|
|
|
```python
|
|
|
prediction_request = { 'query' : text }
|
|
|
```
|
|
|
|
|
|
1. Овај захтев се затим може послати LUIS-у, користећи staging слот на који је ваша апликација објављена:
|
|
|
|
|
|
```python
|
|
|
prediction_response = client.prediction.get_slot_prediction(app_id, 'Staging', prediction_request)
|
|
|
```
|
|
|
|
|
|
1. Одговор на предвиђање садржи главну намеру - намеру са највишим резултатом предвиђања, заједно са ентитетима. Ако је главна намера `set timer`, ентитети се могу прочитати како би се добило време потребно за тајмер:
|
|
|
|
|
|
```python
|
|
|
if prediction_response.prediction.top_intent == 'set timer':
|
|
|
numbers = prediction_response.prediction.entities['number']
|
|
|
time_units = prediction_response.prediction.entities['time unit']
|
|
|
total_seconds = 0
|
|
|
```
|
|
|
|
|
|
Ентитети типа `number` биће низ бројева. На пример, ако кажете *"Set a four minute 17 second timer."*, низ `number` ће садржати 2 цела броја - 4 и 17.
|
|
|
|
|
|
Ентитети типа `time unit` биће низ низова стрингова, са сваком временском јединицом као низом стрингова унутар низа. На пример, ако кажете *"Set a four minute 17 second timer."*, низ `time unit` ће садржати 2 низа са по једном вредношћу - `['minute']` и `['second']`.
|
|
|
|
|
|
JSON верзија ових ентитета за *"Set a four minute 17 second timer."* је:
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
"number": [4, 17],
|
|
|
"time unit": [
|
|
|
["minute"],
|
|
|
["second"]
|
|
|
]
|
|
|
}
|
|
|
```
|
|
|
|
|
|
Овај код такође дефинише бројач за укупно време за тајмер у секундама. Ово ће бити попуњено вредностима из ентитета.
|
|
|
|
|
|
1. Ентитети нису повезани, али можемо направити неке претпоставке о њима. Они ће бити у редоследу којим су изговорени, тако да се позиција у низу може користити за одређивање који број одговара којој временској јединици. На пример:
|
|
|
|
|
|
* *"Set a 30 second timer"* - ово ће имати један број, `30`, и једну временску јединицу, `second`, тако да ће један број одговарати једној временској јединици.
|
|
|
* *"Set a 2 minute and 30 second timer"* - ово ће имати два броја, `2` и `30`, и две временске јединице, `minute` и `second`, тако да ће први број бити за прву временску јединицу (2 минута), а други број за другу временску јединицу (30 секунди).
|
|
|
|
|
|
Следећи код добија број ставки у ентитетима типа `number` и користи то за екстракцију прве ставке из сваког низа, затим друге и тако даље. Додајте ово унутар `if` блока.
|
|
|
|
|
|
```python
|
|
|
for i in range(0, len(numbers)):
|
|
|
number = numbers[i]
|
|
|
time_unit = time_units[i][0]
|
|
|
```
|
|
|
|
|
|
За *"Set a four minute 17 second timer."*, ово ће се петљати два пута, дајући следеће вредности:
|
|
|
|
|
|
| број петље | `number` | `time_unit` |
|
|
|
| ---------: | -------: | ----------- |
|
|
|
| 0 | 4 | minute |
|
|
|
| 1 | 17 | second |
|
|
|
|
|
|
1. Унутар ове петље, користите број и временску јединицу за израчунавање укупног времена за тајмер, додајући 60 секунди за сваки минут и број секунди за било које секунде.
|
|
|
|
|
|
```python
|
|
|
if time_unit == 'minute':
|
|
|
total_seconds += number * 60
|
|
|
else:
|
|
|
total_seconds += number
|
|
|
```
|
|
|
|
|
|
1. Изван ове петље кроз ентитете, забележите укупно време за тајмер:
|
|
|
|
|
|
```python
|
|
|
logging.info(f'Timer required for {total_seconds} seconds')
|
|
|
```
|
|
|
|
|
|
1. Број секунди треба вратити из функције као HTTP одговор. На крају `if` блока, додајте следеће:
|
|
|
|
|
|
```python
|
|
|
payload = {
|
|
|
'seconds': total_seconds
|
|
|
}
|
|
|
return func.HttpResponse(json.dumps(payload), status_code=200)
|
|
|
```
|
|
|
|
|
|
Овај код креира payload који садржи укупан број секунди за тајмер, конвертује га у JSON стринг и враћа као HTTP резултат са статусним кодом 200, што значи да је позив био успешан.
|
|
|
|
|
|
1. На крају, изван `if` блока, обрадите случај када намера није препозната враћањем кода грешке:
|
|
|
|
|
|
```python
|
|
|
return func.HttpResponse(status_code=404)
|
|
|
```
|
|
|
|
|
|
404 је статусни код за *not found*.
|
|
|
|
|
|
1. Покрените функцију и тестирајте је помоћу curl-а.
|
|
|
|
|
|
```sh
|
|
|
curl --request POST 'http://localhost:7071/api/text-to-timer' \
|
|
|
--header 'Content-Type: application/json' \
|
|
|
--include \
|
|
|
--data '{"text":"<text>"}'
|
|
|
```
|
|
|
|
|
|
Замените `<text>` са текстом вашег захтева, на пример `set a 2 minutes 27 second timer`.
|
|
|
|
|
|
Видећете следећи излаз из функције:
|
|
|
|
|
|
```output
|
|
|
Functions:
|
|
|
|
|
|
text-to-timer: [GET,POST] http://localhost:7071/api/text-to-timer
|
|
|
|
|
|
For detailed output, run func with --verbose flag.
|
|
|
[2021-06-26T19:45:14.502Z] Worker process started and initialized.
|
|
|
[2021-06-26T19:45:19.338Z] Host lock lease acquired by instance ID '000000000000000000000000951CAE4E'.
|
|
|
[2021-06-26T19:45:52.059Z] Executing 'Functions.text-to-timer' (Reason='This function was programmatically called via the host APIs.', Id=f68bfb90-30e4-47a5-99da-126b66218e81)
|
|
|
[2021-06-26T19:45:53.577Z] Timer required for 147 seconds
|
|
|
[2021-06-26T19:45:53.746Z] Executed 'Functions.text-to-timer' (Succeeded, Id=f68bfb90-30e4-47a5-99da-126b66218e81, Duration=1750ms)
|
|
|
```
|
|
|
|
|
|
Позив curl-а ће вратити следеће:
|
|
|
|
|
|
```output
|
|
|
HTTP/1.1 200 OK
|
|
|
Date: Tue, 29 Jun 2021 01:14:11 GMT
|
|
|
Content-Type: text/plain; charset=utf-8
|
|
|
Server: Kestrel
|
|
|
Transfer-Encoding: chunked
|
|
|
|
|
|
{"seconds": 147}
|
|
|
```
|
|
|
|
|
|
Број секунди за тајмер је у вредности `"seconds"`.
|
|
|
|
|
|
> 💁 Овај код можете пронаћи у [code/functions](../../../../../6-consumer/lessons/2-language-understanding/code/functions) фасцикли.
|
|
|
|
|
|
### Задатак - учините вашу функцију доступном вашем IoT уређају
|
|
|
|
|
|
1. Да би ваш IoT уређај позвао ваш REST endpoint, потребно је да зна URL. Када сте му приступили раније, користили сте `localhost`, што је пречица за приступ REST endpoint-има на вашем локалном рачунару. Да бисте омогућили вашем IoT уређају приступ, потребно је или да објавите функцију у cloud-у или да добијете вашу IP адресу за локални приступ.
|
|
|
|
|
|
> ⚠️ Ако користите Wio Terminal, лакше је покренути функцију локално, јер ће постојати зависност од библиотека која значи да не можете дистрибуирати функцију на исти начин као раније. Покрените функцију локално и приступите јој преко IP адресе вашег рачунара. Ако ипак желите да је објавите у cloud-у, информације ће бити обезбеђене у каснијој лекцији о томе како то урадити.
|
|
|
|
|
|
* Објавите Functions апликацију - пратите упутства из претходних лекција за објављивање ваше функције у cloud-у. Када се објави, URL ће бити `https://<APP_NAME>.azurewebsites.net/api/text-to-timer`, где `<APP_NAME>` представља име ваше функције. Уверите се да сте такође објавили ваша локална подешавања.
|
|
|
|
|
|
Када радите са HTTP тригерима, они су подразумевано обезбеђени функцијским кључем. Да бисте добили овај кључ, покрените следећу команду:
|
|
|
|
|
|
```sh
|
|
|
az functionapp keys list --resource-group smart-timer \
|
|
|
--name <APP_NAME>
|
|
|
```
|
|
|
|
|
|
Копирајте вредност `default` уноса из секције `functionKeys`.
|
|
|
|
|
|
```output
|
|
|
{
|
|
|
"functionKeys": {
|
|
|
"default": "sQO1LQaeK9N1qYD6SXeb/TctCmwQEkToLJU6Dw8TthNeUH8VA45hlA=="
|
|
|
},
|
|
|
"masterKey": "RSKOAIlyvvQEQt9dfpabJT018scaLpQu9p1poHIMCxx5LYrIQZyQ/g==",
|
|
|
"systemKeys": {}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
Овај кључ ће бити потребно додати као query параметар у URL, тако да ће коначни URL бити `https://<APP_NAME>.azurewebsites.net/api/text-to-timer?code=<FUNCTION_KEY>`, где `<APP_NAME>` представља име ваше функције, а `<FUNCTION_KEY>` ваш подразумевани функцијски кључ.
|
|
|
|
|
|
> 💁 Можете променити тип ауторизације HTTP тригера користећи `authlevel` подешавање у `function.json` фајлу. Више о овоме можете прочитати у [секцији о конфигурацији Azure Functions HTTP тригера у Microsoft документацији](https://docs.microsoft.com/azure/azure-functions/functions-bindings-http-webhook-trigger?WT.mc_id=academic-17441-jabenn&tabs=python#configuration).
|
|
|
|
|
|
* Покрените функцију локално и приступите јој користећи IP адресу - можете добити IP адресу вашег рачунара на локалној мрежи и користити је за изградњу URL-а.
|
|
|
|
|
|
Пронађите вашу IP адресу:
|
|
|
|
|
|
* На Windows 10, пратите [упутство за проналажење IP адресе](https://support.microsoft.com/windows/find-your-ip-address-f21a9bbc-c582-55cd-35e0-73431160a1b9?WT.mc_id=academic-17441-jabenn)
|
|
|
* На macOS, пратите [упутство за проналажење IP адресе на Mac-у](https://www.hellotech.com/guide/for/how-to-find-ip-address-on-mac)
|
|
|
* На Linux-у, пратите секцију о проналажењу приватне IP адресе у [упутству за проналажење IP адресе у Linux-у](https://opensource.com/article/18/5/how-find-ip-address-linux)
|
|
|
|
|
|
Када добијете вашу IP адресу, моћи ћете да приступите функцији на `http://`.
|
|
|
|
|
|
:7071/api/text-to-timer`, где је `<IP_ADDRESS>` ваша IP адреса, на пример `http://192.168.1.10:7071/api/text-to-timer`.
|
|
|
|
|
|
> 💁 Имајте у виду да се користи порт 7071, тако да након IP адресе треба да додате `:7071`.
|
|
|
|
|
|
> 💁 Ово ће радити само ако је ваш IoT уређај на истој мрежи као и ваш рачунар.
|
|
|
|
|
|
1. Тестирајте крајњу тачку приступајући јој помоћу curl-а.
|
|
|
|
|
|
---
|
|
|
|
|
|
## 🚀 Изазов
|
|
|
|
|
|
Постоји много начина да се затражи иста ствар, као што је подешавање тајмера. Размислите о различитим начинима да то урадите и користите их као примере у вашој LUIS апликацији. Тестирајте их да видите колико добро ваш модел може да се носи са различитим начинима тражења тајмера.
|
|
|
|
|
|
## Квиз након предавања
|
|
|
|
|
|
[Квиз након предавања](https://black-meadow-040d15503.1.azurestaticapps.net/quiz/44)
|
|
|
|
|
|
## Преглед и самостално учење
|
|
|
|
|
|
* Прочитајте више о LUIS-у и његовим могућностима на [страници документације о Language Understanding (LUIS) на Microsoft docs](https://docs.microsoft.com/azure/cognitive-services/luis/?WT.mc_id=academic-17441-jabenn)
|
|
|
* Прочитајте више о разумевању језика на [страници о природном разумевању језика на Википедији](https://wikipedia.org/wiki/Natural-language_understanding)
|
|
|
* Прочитајте више о HTTP окидачима у [документацији о Azure Functions HTTP окидачима на Microsoft docs](https://docs.microsoft.com/azure/azure-functions/functions-bindings-http-webhook-trigger?WT.mc_id=academic-17441-jabenn&tabs=python)
|
|
|
|
|
|
## Задатак
|
|
|
|
|
|
[Откажите тајмер](assignment.md)
|
|
|
|
|
|
---
|
|
|
|
|
|
**Одрицање од одговорности**:
|
|
|
Овај документ је преведен коришћењем услуге за превођење помоћу вештачке интелигенције [Co-op Translator](https://github.com/Azure/co-op-translator). Иако се трудимо да обезбедимо тачност, молимо вас да имате у виду да аутоматски преводи могу садржати грешке или нетачности. Оригинални документ на његовом изворном језику треба сматрати меродавним извором. За критичне информације препоручује се професионални превод од стране људи. Не преузимамо одговорност за било каква погрешна тумачења или неспоразуме који могу настати услед коришћења овог превода. |