HoloLens (第 1 代) 和 Azure 303:自然語言理解 (LUIS)
注意
混合實境學院教學課程的設計是以 HoloLens (第 1 代) 和混合實境沉浸式頭戴裝置為準。 因此,對於仍在尋找這些裝置開發指引的開發人員而言,我們覺得這些教學課程很重要。 這些教學課程不會使用用於 HoloLens 2 的最新工具組或互動進行更新。 系統會保留這些資訊,以繼續在支援的裝置上運作。 未來將會張貼一系列新的教學課程,以示範如何為 HoloLens 2 進行開發。 張貼這些教學課程的連結將會更新此通知。
在此課程中,您將瞭解如何使用 Azure 認知服務搭配 Language Understanding API,將 Language Understanding 整合到混合實境應用程式中。
Language Understanding (LUIS) 是一項Microsoft Azure 服務,可讓應用程式以自己的語言擷取人員可能想要的內容,讓應用程式能夠從使用者輸入中產生意義。 這是透過機器學習來達成,其可瞭解並瞭解輸入資訊,然後可以使用詳細、相關的資訊來回復。 如需詳細資訊,請流覽 Azure Language Understanding (LUIS) 頁面。
完成本課程之後,您將會有混合實境沉浸式頭戴式裝置應用程式,其可以執行下列動作:
- 使用附加至沉浸式頭戴式裝置的麥克風來擷取使用者輸入語音。
- 傳送擷取的聽寫 Azure Language Understanding Intelligent Service (LUIS)。
- 將 LUIS 擷取意義從傳送資訊中擷取,這會進行分析,並嘗試判斷使用者的要求意圖。
開發將包含建立應用程式,讓用戶能夠使用語音和/或注視來變更場景中物件的大小和色彩。 不會涵蓋運動控制器的使用。
在您的應用程式中,您應該瞭解如何將結果與設計整合。 本課程旨在教導您如何整合 Azure 服務與 Unity 專案。 使用本課程中取得的知識來增強混合實境應用程式,是您的工作。
請準備好訓練 LUIS 數次,這在第 12 章中涵蓋。 您將會得到更好的結果,LUIS 已定型的次數愈多。
裝置支援
課程 | HoloLens | 沉浸式頭戴裝置 |
---|---|---|
MR 和 Azure 303:自然語言理解 (LUIS) | ✔️ | ✔️ |
注意
雖然本課程主要著重於 Windows Mixed Reality 沉浸式 (VR) 頭戴式裝置,但您也可以將此課程中學到的內容套用至 Microsoft HoloLens。 隨著您遵循課程,您將會看到任何您可能需要採用以支援 HoloLens 變更的附注。 使用 HoloLens 時,您可能會在語音擷取期間注意到一些回應。
必要條件
注意
本教學課程專為具備 Unity 和 C# 基本經驗的開發人員所設計。 另請注意,本檔內的必要條件和書面指示代表在撰寫期間經過測試和驗證的內容(2018 年 5 月)。 您可以自由使用最新的軟體,如安裝工具文章中所列,不過不應該假設本課程中的資訊會完全符合您在較新的軟體中找到的內容,而不是下面所列的內容。
針對此課程,我們建議使用下列硬體和軟體:
- 開發計算機, 與 Windows Mixed Reality 相容以進行沉浸式 (VR) 頭戴式裝置開發
- 已啟用開發人員模式的 Windows 10 Fall Creators Update (或更新版本)
- 最新的 Windows 10 SDK
- Unity 2017.4
- Visual Studio 2017
- 已啟用開發人員模式的 Windows Mixed Reality 沉浸式 (VR) 頭戴式裝置或Microsoft HoloLens
- 一組具有內建麥克風的耳機(如果耳機沒有內建麥克風和喇叭)
- Azure 設定和 LUIS 擷取的因特網存取
在您開始使用 Intune 之前
為了避免建置此專案時發生問題,強烈建議您在根資料夾或近根資料夾中建立本教學課程中所提及的專案(長文件夾路徑在建置時可能會導致問題)。
若要允許您的計算機啟用聽寫,請移至 Windows 設定>隱私權>語音、筆跡和輸入,然後按 [開啟語音服務和輸入建議] 按鈕。
本教學課程中的程式代碼可讓您從計算機上設定的預設 麥克風裝置 錄製。 請確定 [預設麥克風裝置] 已設定為您想要用來擷取語音的麥克風裝置。
如果您的頭戴式裝置有內建麥克風,請確定混合實境入口網站設定中已開啟 [當我戴頭戴頭戴式裝置時,切換至耳機麥克風] 選項。
第 1 章 – 設定 Azure 入口網站
若要在 Azure 中使用 Language Understanding 服務,您必須將服務的實例設定為可供您的應用程式使用。
登入 Azure 入口網站。
注意
如果您還沒有 Azure 帳戶,則必須建立一個帳戶。 如果您在教室或實驗室情況中遵循本教學課程,請洽詢您的講師或其中一名監看員,以協助設定您的新帳戶。
登入之後,按兩下左上角的 [ 新增 ],然後搜尋 Language Understanding,然後按兩下 Enter。
注意
[新增] 一詞可能已取代為在較新的入口網站中建立資源。
右側的新頁面將提供 Language Understanding 服務的描述。 在此頁面左下方,選取 [ 建立] 按鈕,以建立此服務的實例。
按兩下 [建立]:
插入此服務實例所需的 名稱 。
選取 [訂用帳戶]。
選取適合您的定價層,如果這是第一次建立 LUIS 服務,您應該可以使用免費層 (名為 F0) 。 免費配置應該足以供本課程使用。
選擇資源群組或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。 建議將所有與單一專案相關聯的 Azure 服務(例如,例如這些課程)保留在通用資源群組下)。
如果您想要深入瞭解 Azure 資源群組,請 瀏覽資源群組文章。
判斷資源群組的位置(如果您要建立新的資源群組)。 在理想情況下,位置位於應用程式執行所在的區域中。 某些 Azure 資產僅適用於特定區域。
您也必須確認您已瞭解此服務適用的條款和條件。
選取 建立。
按兩下 [ 建立] 之後,您必須等候服務建立,這可能需要一分鐘的時間。
建立服務實例之後,入口網站中就會顯示通知。
按兩下通知以探索新的服務實例。
按兩下通知中的 [ 移至資源 ] 按鈕,以探索新的服務實例。 系統會帶您前往新的 LUIS 服務實例。
在本教學課程中,您的應用程式必須呼叫您的服務,這是透過使用您服務的訂用帳戶密鑰來完成的。
從 LUIS API 服務的 [快速啟動] 頁面,流覽至第一個步驟[擷取金鑰],然後按下 [金鑰] (您也可以按兩下位於服務導覽功能表中的藍色超連結 [金鑰],以機碼圖示表示)。 這會顯示您的服務 金鑰。
擷取其中一個顯示金鑰的複本,因為您稍後會在專案中用到此密鑰。
在 [ 服務 ] 頁面中,按兩下 [Language Understanding 入口網站 ] 以重新導向至您將用來在 LUIS 應用程式內建立新服務的網頁。
第 2 章 – Language Understanding 入口網站
在本節中,您將瞭解如何在 LUIS 入口網站上建立 LUIS 應用程式。
重要
請注意,在本章中設定 實體、 意圖和 語句 只是建置 LUIS 服務的第一個步驟:您也需要重新定型服務數次,以便使其更精確。 本課程的最後一 章 涵蓋重新定型您的服務,因此請確定您已完成。
到達 Language Understanding 入口網站時,如果您尚未使用與 Azure 入口網站 相同的認證,您可能需要登入。
如果這是您第一次使用 LUIS,您必須向下捲動至歡迎頁面底部,才能尋找並按兩下 [建立 LUIS 應用程式 ] 按鈕。
登入后,按兩下 [我的應用程式 ] (如果您目前不在該區段)。 接著,您可以按兩下 [ 建立新的應用程式]。
提供 您的應用程式名稱。
如果您的應用程式應該瞭解與英文不同的語言,您應該將 文化 特性變更為適當的語言。
您也可以在這裡新增 新 LUIS 應用程式的描述 。
按 [完成] 之後,您將輸入新 LUIS 應用程式的 [建置] 頁面。
有一些重要的概念可在這裡瞭解:
- 意圖,表示將在使用者查詢之後呼叫的方法。 意圖可能有一或多個實體。
- Entity 是查詢的元件,描述與 INTENT 相關的資訊。
- 語句是開發人員提供的查詢範例,LUIS 會用來訓練自己。
如果這些概念不完全清楚,別擔心,因為本課程將在本章中進一步釐清這些概念。
您將從建立 本課程所需的實體 開始。
在頁面左側,按兩下 [實體],然後按兩下 [ 建立新實體]。
呼叫新的實體 色彩,將其類型設定為 Simple,然後按 [完成]。
重複此程式,以建立三個 (3) 個名稱為的簡單實體:
- upsize
- 縮小
- 目標
結果看起來應該像下圖:
此時,您可以開始建立 意圖。
警告
請勿刪除 None 意圖。
在頁面左側,按兩下 [ 意圖],然後按兩下 [ 建立新意圖]。
呼叫新的 Intent ChangeObjectColor。
重要
此 意圖 名稱會在本課程稍後的程式代碼內使用,因此為了獲得最佳結果,請完全依照所提供的方式使用此名稱。
確認名稱之後,系統會將您導向至意圖頁面。
您會發現有一個文字框要求您輸入 5 或更多不同的 語句。
注意
LUIS 會將所有語句轉換成小寫。
- 在頂端文字框中插入下列 語句 (目前有大約 5 個範例的文字 類型...), 然後按 Enter:
The color of the cylinder must be red
您會發現新的 語句 會出現在下方的清單中。
遵循相同的程式,插入下列六個 (6) 語句:
make the cube black
make the cylinder color white
change the sphere to red
change it to green
make this yellow
change the color of this object to blue
針對您已建立的每個語句,您必須識別 LUIS 應該使用哪些單字作為實體。 在此範例中,您必須將所有色彩標示為 色彩 實體,並將目標的所有可能參考標示為 目標 實體。
若要這樣做,請嘗試按兩下第一個語句中的文字 圓柱, 然後選取 目標。
現在,按兩下第一個語句中的紅色字,然後選取色彩。
也為下一行加上標籤,其中 Cube 應該是目標,而黑色應該是色彩。 另請注意,我們所提供的 『this』、『it』 和 『this object』 一詞的使用,因此也提供非特定目標類型。
重複上述程式,直到所有語句都標示為 [實體]。 如果您需要協助,請參閱下圖。
提示
選取文字以將其標記為實體時:
- 若為單字,只要按兩下即可。
- 針對一組兩個或多個單字,按兩下開頭,然後在集合結尾。
注意
您可以使用 [令牌檢視] 切換按鈕,在實體/令牌檢視之間切換!
結果應該如下列影像所示,其中顯示 [實體/ 令牌檢視]:
此時,按下頁面右上方的 [ 訓練 ] 按鈕,並等候其上的小圓指標變成綠色。 這表示 LUIS 已成功定型以辨識此意圖。
作為練習,請使用實體目標、向上大小和向下調整,建立名為 ChangeObjectSize 的新意圖。
遵循與上一個意圖相同的程式,針對 Size 變更插入下列八個 (8) 語句:
increase the dimensions of that reduce the size of this i want the sphere smaller make the cylinder bigger size down the sphere size up the cube decrease the size of that object increase the size of this object
結果應該與下圖中的結果類似:
一旦兩個意圖、 ChangeObjectColor 和 ChangeObjectSize 都已建立並定型,請按下頁面頂端的 [ 發佈] 按鈕。
在 [ 發佈 ] 頁面上,您將完成併發佈 LUIS 應用程式,讓程式代碼可以存取它。
將下拉式清單 [發佈至 ] 設定為 [生產環境]。
將 時區 設定為時區。
核取 [包含所有預測意圖分數] 方 塊。
按兩下 [ 發佈至生產位置]。
在 [資源和金鑰] 區段中:
- 選取您在 Azure 入口網站中為服務實例設定的區域。
- 您會注意到下方的 Starter_Key 專案,請予以忽略。
- 按兩下 [ 新增金鑰 ],然後在建立服務實例時插入 您在 Azure 入口網站中取得的密鑰 。 如果您的 Azure 和 LUIS 入口網站登入相同的使用者,系統會提供您要使用的租使用者名稱、訂用帳戶名稱及金鑰的下拉功能表(與您先前在 Azure 入口網站中提供的名稱相同。
重要
在 [端點] 底下,取得對應至您所插入密鑰的端點複本,您很快就會在程式代碼中使用它。
第 3 章 – 設定 Unity 專案
以下是使用混合實境進行開發的典型設定,因此是其他專案的良好範本。
開啟 Unity ,然後按兩下 [ 新增]。
您現在必須提供 Unity 項目名稱,插入 MR_LUIS。 請確定專案類型已設定為 3D。 將 [ 位置 ] 設定為您適當的位置(請記住,更接近根目錄會更好)。 然後按兩下 [ 建立專案]。
在 Unity 開啟時,值得檢查預設 的腳本編輯器 設定為 Visual Studio。 移至 [編輯 > 喜好設定],然後從新視窗流覽至 [外部工具]。 將外部腳本編輯器變更為 Visual Studio 2017。 關閉 [喜好設定] 視窗。
接下來,移至 [檔案>建置設定],然後按兩下 [切換平臺] 按鈕,將平臺切換為 通用 Windows 平台。
移至 [ 檔案 > 建置設定 ],並確定:
目標裝置 設定為 [任何裝置]
針對 Microsoft HoloLens,將 [目標裝置] 設定為 [HoloLens]。
組建類型 設定為 D3D
SDK 設定為 [最新安裝]
Visual Studio 版本 設定為 [最新安裝]
[建置並執行 ] 設定為 [ 本機計算機]
儲存場景並將它新增至組建。
選取 [ 新增開啟場景] 來執行此動作。 隨即會出現儲存視窗。
為此建立新的資料夾,以及任何未來場景,然後選取 [新增資料夾] 按鈕,以建立新的資料夾 ,並將它命名為 Scenes。
開啟新建立 的 Scenes 資料夾,然後在 [檔名:文字] 字段中輸入 MR_LuisScene,然後按 [ 儲存]。
[建置設定] 中的其餘設定現在應該保留為預設值。
在 [建置設定] 視窗中,按兩下 [播放程序設定] 按鈕,這會在 Inspector 所在的空間中開啟相關的面板。
在此面板中,需要驗證一些設定:
在 [ 其他設定] 索引標籤中:
腳本運行時間版本 應該是 穩定 (.NET 3.5 對等專案)。
腳本後端 應該是 .NET
API 相容性層級 應該是 .NET 4.6
在 [發佈設定] 索引標籤的 [功能] 底下,檢查:
InternetClient
麥克風
在面板的下方,在 [XR 設定] 中,勾選 [支援虛擬現實] 中的 [XR 設定],確定已新增 Windows Mixed Reality SDK。
回到 [組建設定] Unity C# 專案不再呈現灰色;勾選此旁邊的複選框。
關閉 [建置設定] 視窗。
儲存場景和專案(檔案 > 儲存場景/檔案 > 儲存專案)。
第 4 章 – 建立場景
重要
如果您想要略過 本課程的 Unity 設定 元件,並繼續直接進入程式碼,請隨意下載此 .unitypackage、將它匯入您的專案做為 自定義套件,然後從 第 5 章繼續進行。
以滑鼠右鍵按兩下階層面板的空白區域,在 [3D 物件] 底下新增平面。
請注意,當您再次以滑鼠右鍵按兩下 [階層] 內以建立更多物件時,如果您仍然選取最後一個物件,選取的物件將會是新物件的父代。 請避免在 [階層] 內的空白空間中按下滑鼠左鍵,然後按下滑鼠右鍵。
重複此程式以新增下列物件:
- 球
- 圓柱體
- 立方體
- 3D 文字
產生的場景 階層 應該與下圖中的階層類似:
按兩下 [主要相機 ] 以選取它,查看 [偵測器面板 ],您會看到 Camera 物件及其所有元件。
按兩下位於偵測器面板底部的 [新增元件] 按鈕。
搜尋稱為 音訊來源的元件,如上所示。
此外,也請確定主相機的 [轉換] 元件設定為 [0,0,0],您可以按相機轉換元件旁的齒輪圖示,然後選取 [重設]。 然後轉換元件看起來應該會像這樣:
- 位置 設定為 0、0、0。
- 旋轉 設定為 0、0、0。
注意
針對 Microsoft HoloLens,您也必須變更下列專案,這是主相機上相機元件的一部分:
- 清除旗標: 純色。
- 背景 'Black, Alpha 0' – 十六進位色彩: #000000000。
按兩下 [平面 ] 以選取它。 在 [ 偵測器面板 ] 中, 使用下列值設定轉換 元件:
X 軸 Y 軸 Z 軸 0 -1 0 按兩下 [Sphere ] 以選取它。 在 [ 偵測器面板 ] 中, 使用下列值設定轉換 元件:
X 軸 Y 軸 Z 軸 2 1 2 按兩下 [圓柱圖 ] 以選取它。 在 [ 偵測器面板 ] 中, 使用下列值設定轉換 元件:
X 軸 Y 軸 Z 軸 -2 1 2 在 Cube 上按兩下滑鼠左鍵以選取它。 在 [ 偵測器面板 ] 中, 使用下列值設定轉換 元件:
轉換 - 位置
X | Y | Z |
---|---|---|
0 | 1 | 4 |
轉換 - 旋轉
X | Y | Z |
---|---|---|
45 | 45 | 0 |
- 按兩下 [新增文字 ] 物件以選取它。 在 [ 偵測器面板 ] 中, 使用下列值設定轉換 元件:
轉換 - 位置
X | Y | Z |
---|---|---|
-2 | 6 | 9 |
轉換 - 調整
X | Y | Z |
---|---|---|
0.1 | 0.1 | 0.1 |
將文字網格元件中的字型大小變更為 50。
將 Text Mesh 物件的名稱變更為聽寫文字。
您的階層面板結構現在看起來應該像這樣:
最後一個場景看起來應該像下圖:
第 5 章 – 建立 MicrophoneManager 類別
您要建立的第一個腳本是 MicrophoneManager 類別。 接下來,您將建立 LuisManager、 Behaviours 類別,最後 建立 Gaze 類別(請放心立即建立所有這些類別,不過在您到達每個章節時會涵蓋它)。
MicrophoneManager 類別負責:
- 偵測連接到頭戴式裝置或機器的錄製裝置(無論預設為哪一部)。
- 擷取音訊(語音),並使用聽寫將其儲存為字串。
- 語音暫停之後,請將聽寫提交至 LuisManager 類別。
若要建立此類別:
以滑鼠右鍵按兩下 [項目面板], [建立 > 資料夾]。 呼叫 [腳稿] 資料夾。
建立 [腳本] 資料夾后,按兩下即可開啟。 然後,在該資料夾中,以滑鼠右鍵按兩下 [ 建立 > C# 腳本]。 將腳本 命名為 MicrophoneManager。
按兩下 MicrophoneManager,以使用 Visual Studio 開啟它。
將下列命名空間新增至檔案頂端:
using UnityEngine; using UnityEngine.Windows.Speech;
然後在 MicrophoneManager 類別內新增下列變數:
public static MicrophoneManager instance; //help to access instance of this object private DictationRecognizer dictationRecognizer; //Component converting speech to text public TextMesh dictationText; //a UI object used to debug dictation result
現在必須新增 Awake() 和 Start() 方法的程式代碼。 當 類別初始化時,將會呼叫下列專案:
private void Awake() { // allows this class instance to behave like a singleton instance = this; } void Start() { if (Microphone.devices.Length > 0) { StartCapturingAudio(); Debug.Log("Mic Detected"); } }
現在,您需要應用程式用來啟動和停止語音擷取的方法,並將它 傳遞給 LuisManager 類別,您很快就會建置該類別。
/// <summary> /// Start microphone capture, by providing the microphone as a continual audio source (looping), /// then initialise the DictationRecognizer, which will capture spoken words /// </summary> public void StartCapturingAudio() { if (dictationRecognizer == null) { dictationRecognizer = new DictationRecognizer { InitialSilenceTimeoutSeconds = 60, AutoSilenceTimeoutSeconds = 5 }; dictationRecognizer.DictationResult += DictationRecognizer_DictationResult; dictationRecognizer.DictationError += DictationRecognizer_DictationError; } dictationRecognizer.Start(); Debug.Log("Capturing Audio..."); } /// <summary> /// Stop microphone capture /// </summary> public void StopCapturingAudio() { dictationRecognizer.Stop(); Debug.Log("Stop Capturing Audio..."); }
新增語音暫停時要叫用的聽寫處理程式。 這個方法會將聽寫文字傳遞至 LuisManager 類別。
/// <summary> /// This handler is called every time the Dictation detects a pause in the speech. /// This method will stop listening for audio, send a request to the LUIS service /// and then start listening again. /// </summary> private void DictationRecognizer_DictationResult(string dictationCaptured, ConfidenceLevel confidence) { StopCapturingAudio(); StartCoroutine(LuisManager.instance.SubmitRequestToLuis(dictationCaptured, StartCapturingAudio)); Debug.Log("Dictation: " + dictationCaptured); dictationText.text = dictationCaptured; } private void DictationRecognizer_DictationError(string error, int hresult) { Debug.Log("Dictation exception: " + error); }
重要
刪除 Update() 方法,因為這個類別不會使用它。
請務必先在Visual Studio中儲存變更,再返回 Unity。
注意
此時,您會注意到 Unity 編輯器主控台面板中出現錯誤。 這是因為程式代碼會參考 您將在下一章中建立的 LuisManager 類別。
第 6 章 – 建立 LUISManager 類別
是時候建立 LuisManager 類別,這會呼叫 Azure LUIS 服務。
此類別的目的是要接收來自 MicrophoneManager 類別的聽寫文字,並將其傳送至要分析的 Azure Language Understanding API。
此類別會還原串行化 JSON 回應,並呼叫 Actionss 類別的適當方法以觸發動作。
若要建立此類別:
按兩下 [文稿] 資料夾,以開啟它。
在 [腳本] 資料夾內按下滑鼠右鍵,按兩下 [建立 > C# 腳本]。 將腳本 命名為 LuisManager。
按兩下腳本,以使用Visual Studio 開啟它。
將下列命名空間新增至檔案頂端:
using System; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Networking;
首先,您會在 LuisManager 類別內建立三個類別(位於 Start() 方法上方的相同腳本檔案中,以代表來自 Azure 的還原串行化 JSON 回應。
[Serializable] //this class represents the LUIS response public class AnalysedQuery { public TopScoringIntentData topScoringIntent; public EntityData[] entities; public string query; } // This class contains the Intent LUIS determines // to be the most likely [Serializable] public class TopScoringIntentData { public string intent; public float score; } // This class contains data for an Entity [Serializable] public class EntityData { public string entity; public string type; public int startIndex; public int endIndex; public float score; }
接下來,在 LuisManager 類別內新增下列變數:
public static LuisManager instance; //Substitute the value of luis Endpoint with your own End Point string luisEndpoint = "https://westus.api.cognitive... add your endpoint from the Luis Portal";
請務必將 LUIS 端點放在現在 (您將會從 LUIS 入口網站取得的端點) 中。
現在必須新增 Awake() 方法的程式代碼。 當 類別初始化時,將會呼叫這個方法:
private void Awake() { // allows this class instance to behave like a singleton instance = this; }
現在,您需要此應用程式用來將從 MicrophoneManager 類別收到的聽寫傳送至 LUIS 的方法,然後接收和還原串行化回應。
一旦判斷意圖和相關聯實體的值之後,它們就會傳遞至 Actionss 類別的實例,以觸發預期的動作。
/// <summary> /// Call LUIS to submit a dictation result. /// The done Action is called at the completion of the method. /// </summary> public IEnumerator SubmitRequestToLuis(string dictationResult, Action done) { string queryString = string.Concat(Uri.EscapeDataString(dictationResult)); using (UnityWebRequest unityWebRequest = UnityWebRequest.Get(luisEndpoint + queryString)) { yield return unityWebRequest.SendWebRequest(); if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError) { Debug.Log(unityWebRequest.error); } else { try { AnalysedQuery analysedQuery = JsonUtility.FromJson<AnalysedQuery>(unityWebRequest.downloadHandler.text); //analyse the elements of the response AnalyseResponseElements(analysedQuery); } catch (Exception exception) { Debug.Log("Luis Request Exception Message: " + exception.Message); } } done(); yield return null; } }
建立名為 分析ResponseElements() 的新方法,以讀取產生的 分析查詢 並判斷實體。 判斷這些實體之後,它們就會傳遞至 Actionss 類別的實例,以用於動作。
private void AnalyseResponseElements(AnalysedQuery aQuery) { string topIntent = aQuery.topScoringIntent.intent; // Create a dictionary of entities associated with their type Dictionary<string, string> entityDic = new Dictionary<string, string>(); foreach (EntityData ed in aQuery.entities) { entityDic.Add(ed.type, ed.entity); } // Depending on the topmost recognized intent, read the entities name switch (aQuery.topScoringIntent.intent) { case "ChangeObjectColor": string targetForColor = null; string color = null; foreach (var pair in entityDic) { if (pair.Key == "target") { targetForColor = pair.Value; } else if (pair.Key == "color") { color = pair.Value; } } Behaviours.instance.ChangeTargetColor(targetForColor, color); break; case "ChangeObjectSize": string targetForSize = null; foreach (var pair in entityDic) { if (pair.Key == "target") { targetForSize = pair.Value; } } if (entityDic.ContainsKey("upsize") == true) { Behaviours.instance.UpSizeTarget(targetForSize); } else if (entityDic.ContainsKey("downsize") == true) { Behaviours.instance.DownSizeTarget(targetForSize); } break; } }
重要
刪除 Start() 和 Update() 方法,因為此類別不會使用這些方法。
請務必先在Visual Studio中儲存變更,再返回 Unity。
注意
此時,您會注意到 Unity 編輯器控制台面板中出現數個錯誤。 這是因為程式代碼會參考 您將在下一章中建立的 Behaviours 類別。
第 7 章 – 建立行為類別
Actionss 類別會使用 LuisManager 類別所提供的實體來觸發動作。
若要建立此類別:
按兩下 [文稿] 資料夾,以開啟它。
在 [腳本] 資料夾內按下滑鼠右鍵,按兩下 [建立 > C# 腳本]。 將腳本 命名為行為。
按兩下腳本,以使用 Visual Studio 開啟它。
然後在 Behaviours 類別內新增下列變數:
public static Behaviours instance; // the following variables are references to possible targets public GameObject sphere; public GameObject cylinder; public GameObject cube; internal GameObject gazedTarget;
新增 Awake() 方法程式代碼。 當 類別初始化時,將會呼叫這個方法:
void Awake() { // allows this class instance to behave like a singleton instance = this; }
LuisManager 類別會呼叫下列方法,以判斷哪個對像是查詢的目標,然後觸發適當的動作。
/// <summary> /// Changes the color of the target GameObject by providing the name of the object /// and the name of the color /// </summary> public void ChangeTargetColor(string targetName, string colorName) { GameObject foundTarget = FindTarget(targetName); if (foundTarget != null) { Debug.Log("Changing color " + colorName + " to target: " + foundTarget.name); switch (colorName) { case "blue": foundTarget.GetComponent<Renderer>().material.color = Color.blue; break; case "red": foundTarget.GetComponent<Renderer>().material.color = Color.red; break; case "yellow": foundTarget.GetComponent<Renderer>().material.color = Color.yellow; break; case "green": foundTarget.GetComponent<Renderer>().material.color = Color.green; break; case "white": foundTarget.GetComponent<Renderer>().material.color = Color.white; break; case "black": foundTarget.GetComponent<Renderer>().material.color = Color.black; break; } } } /// <summary> /// Reduces the size of the target GameObject by providing its name /// </summary> public void DownSizeTarget(string targetName) { GameObject foundTarget = FindTarget(targetName); foundTarget.transform.localScale -= new Vector3(0.5F, 0.5F, 0.5F); } /// <summary> /// Increases the size of the target GameObject by providing its name /// </summary> public void UpSizeTarget(string targetName) { GameObject foundTarget = FindTarget(targetName); foundTarget.transform.localScale += new Vector3(0.5F, 0.5F, 0.5F); }
新增 FindTarget() 方法來判斷哪一個 GameObjects 是目前 Intent 的目標。 如果實體中未定義明確目標,這個方法會將目標預設為 GameObject 「注視」。
/// <summary> /// Determines which object reference is the target GameObject by providing its name /// </summary> private GameObject FindTarget(string name) { GameObject targetAsGO = null; switch (name) { case "sphere": targetAsGO = sphere; break; case "cylinder": targetAsGO = cylinder; break; case "cube": targetAsGO = cube; break; case "this": // as an example of target words that the user may use when looking at an object case "it": // as this is the default, these are not actually needed in this example case "that": default: // if the target name is none of those above, check if the user is looking at something if (gazedTarget != null) { targetAsGO = gazedTarget; } break; } return targetAsGO; }
重要
刪除 Start() 和 Update() 方法,因為此類別不會使用這些方法。
請務必先在Visual Studio中儲存變更,再返回 Unity。
第 8 章 – 建立注視類別
您需要完成此應用程式的最後一個類別是 Gaze 類別。 這個類別會更新目前在用戶視覺焦點中的 GameObject 參考。
若要建立此類別:
按兩下 [文稿] 資料夾,以開啟它。
在 [腳本] 資料夾內按下滑鼠右鍵,按兩下 [建立 > C# 腳本]。 將腳本 命名為 Gaze。
按兩下腳本,以使用 Visual Studio 開啟它。
插入此類別的下列程式代碼:
using UnityEngine; public class Gaze : MonoBehaviour { internal GameObject gazedObject; public float gazeMaxDistance = 300; void Update() { // Uses a raycast from the Main Camera to determine which object is gazed upon. Vector3 fwd = gameObject.transform.TransformDirection(Vector3.forward); Ray ray = new Ray(Camera.main.transform.position, fwd); RaycastHit hit; Debug.DrawRay(Camera.main.transform.position, fwd); if (Physics.Raycast(ray, out hit, gazeMaxDistance) && hit.collider != null) { if (gazedObject == null) { gazedObject = hit.transform.gameObject; // Set the gazedTarget in the Behaviours class Behaviours.instance.gazedTarget = gazedObject; } } else { ResetGaze(); } } // Turn the gaze off, reset the gazeObject in the Behaviours class. public void ResetGaze() { if (gazedObject != null) { Behaviours.instance.gazedTarget = null; gazedObject = null; } } }
請務必先在Visual Studio中儲存變更,再返回 Unity。
第 9 章 – 完成場景設定
若要完成場景的設定,請將您建立的每個腳本從 [腳本資料夾] 拖曳至 [階層面板] 中的 [主要相機] 物件。
選取主要相機並查看偵測器面板,您應該可以看到您已附加的每個腳本,而且您會注意到每個尚未設定的腳本上有參數。
若要正確設定這些參數,請遵循下列指示:
MicrophoneManager:
- 從 [階層面板] 將 [聽寫文字] 物件拖曳到 [聽寫文字] 參數值方塊中。
來自階層面板的行為:
- 將Sphere物件拖曳至 [Sphere 參考目標] 方塊。
- 將 [圓柱圖] 拖曳到 [圓柱圖參考目標] 方塊中。
- 將 Cube 拖曳至 [Cube 參考目標] 方塊。
注視:
- 將 [注視最大距離] 設定為 300 (如果尚未設定)。
結果看起來應該像下圖:
第 10 章 – 在 Unity 編輯器中測試
測試場景設定是否已正確實作。
請確定:
- 所有腳本都會附加至 Main Camera 物件。
- 主要相機偵測器面板中的所有欄位都會正確指派。
在 Unity 編輯器中按下 [播放] 按鈕。 應用程式應該在附加的沉浸式頭戴式裝置內執行。
請嘗試幾個語句,例如:
make the cylinder red change the cube to yellow I want the sphere blue make this to green change it to white
注意
如果您在 Unity 控制台中看到有關預設音訊裝置變更的錯誤,場景可能無法如預期般運作。 這是因為混合實境入口網站處理具有耳機的內建麥克風的方式。 如果您看到此錯誤,只要停止場景並再次啟動它,事情應該如預期般運作。
第 11 章 – 建置和側載 UWP 解決方案
確定應用程式在 Unity 編輯器中運作之後,您就可以開始建置和部署。
若要建置:
按兩下 [檔案>儲存] 以儲存目前的場景。
移至 [ 檔案 > 建置設定]。
勾選稱為 Unity C# 專案的方塊(適用於在建立 UWP 項目 之後查看和偵錯您的程式代碼。
按兩下 [新增開啟場景],然後按兩下 [建置]。
系統會提示您選取您要建置解決方案的資料夾。
建立 BUILDS 資料夾,並在該資料夾中建立另一個具有所選適當名稱的資料夾。
按兩下 [ 選取資料夾 ] 以在該位置開始建置。
一旦 Unity 完成建置(可能需要一些時間),它應該會在組建的位置開啟 檔案總管 視窗。
若要在本機電腦上部署:
在 Visual Studio 中,開啟在上一章中建立的方案檔案。
在 [解決方案平臺] 中,選取 [x86] [本機計算機]。
在 [解決方案組態] 中,選取 [偵錯]。
針對 Microsoft HoloLens,您可能會發現將它設定為 遠端電腦會比較容易,因此您不會繫結到您的電腦。 不過,您也必須執行下列動作:
- 瞭解 HoloLens 的 IP 位址,您可以在 [設定>網络與因特網 > Wi-Fi > 進階選項] 中找到;IPv4 是您應該使用的位址。
- 確定開發人員模式為開啟;請參閱適用於開發人員的設定>更新與安全性>。
移至 [ 建置] 功能表 ,然後按下 [ 部署方案 ] 將應用程式側載至您的電腦。
您的應用程式現在應該會出現在已安裝的應用程式清單中,準備好啟動!
啟動之後,應用程式會提示您授權存取 麥克風。 使用動作控制器、語音輸入或鍵盤按 [是] 按鈕。
第 12 章 – 改善 LUIS 服務
重要
本章非常重要,可能需要數次重新查看,因為它有助於改善 LUIS 服務的精確度:請確定您完成這項作業。
若要改善 LUIS 所提供的了解層級,您需要擷取新的語句,並使用它們重新定型 LUIS 應用程式。
例如,您可能已將 LUIS 定型為瞭解「增加」和「Upsize」,但不想讓應用程式也瞭解「放大」等字組嗎?
一旦您多次使用應用程式,您說的所有項目都會由 LUIS 收集,並在 LUIS 入口網站中提供。
請移至遵循此 連結的入口網站應用程式,然後登入。
使用 MS 認證登入之後,請按下您的應用程式 名稱。
按兩下頁面左側的 [ 檢閱端點語句 ] 按鈕。
您會看到混合實境應用程式已傳送至 LUIS 的語句清單。
您會注意到一些醒目提示的 實體。
藉由將滑鼠暫留在每個醒目提示的單字上,您可以檢閱每個語句,並判斷哪些實體已正確辨識、哪些實體錯誤,以及遺漏哪些實體。
在上述範例中,發現 「spear」 一詞已醒目提示為目標,因此必須更正錯誤,方法是將滑鼠停留在單字上方,然後按兩下 [移除卷標]。
如果您發現語句完全錯誤,您可以使用畫面右側的 [刪除] 按鈕加以刪除。
或者,如果您覺得 LUIS 已正確解譯語句,您可以使用 [ 新增至對齊意圖 ] 按鈕來驗證其瞭解。
排序所有顯示的語句之後,請嘗試重載頁面,以查看是否有更多可用。
請務必盡可能重複此程式,以改善應用程式瞭解。
玩得愉快!
您已完成的 LUIS 整合式應用程式
恭喜,您建置了混合實境應用程式,利用 Azure Language Understanding Intelligence Service,了解使用者所說的內容,並處理該資訊。
額外練習
練習 1
使用此應用程式時,您可能會注意到,如果您注視 Floor 物件並要求變更其色彩,則會這麼做。 您可以瞭解如何阻止應用程式變更 Floor 色彩?
練習 2
請嘗試擴充 LUIS 和應用程式功能,為場景中的物件新增其他功能;例如,根據使用者說的內容,在 Gaze 命中點建立新的物件,然後使用現有的命令,將這些物件與目前的場景物件搭配使用。