您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何使用nodejs BOT SDK開發問答類技能模板,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
問答技能模板是針對問答類技能設計的模板,如知識問答、生活常識問題等。本文從問答類技能交互、部署講述如何快速搭建問答類技能。
問答類技能與用戶的交互方式是技能從題庫列表中選出一道題,并提供四個選項,其中有一個選項是正確的。用戶通過說出正確選項的順序來答題。
下面以古詩問答
技能為例,描述問答類技能與用戶交互過程。技能從古詩列表中選取一首詩讓用戶說出詩的作者,并依次讀出四個作者選項。用戶說出正確的作者的選項順序,回答正確后技能會記錄用戶得分。技能交互過程如下:
用戶:打開古詩問答
技能:[技能歡迎語]。開始答題。第一題:離離原上草 一歲一枯榮的作者是誰。 1,李白 2,白居易 3,杜甫 4,柳宗元
用戶:第二個
技能:回答正確,得一分。目前的積分是1分。第二題。。。
技能從題庫中選取問題,可以杜絕題目重復和答案排列順序重復的問題。開發者只需要更新題目列表和相應的技能配置信息,即可生成新的技能并在DuerOS DBP平臺上發布。題庫的存儲方式如下,其中正確答案需要放在答案的第一個位置,格式如下。
{ '題目': [ '正確答案', '錯誤答案', '錯誤答案', '錯誤答案', ], },
上面古詩問答的例子在題庫中的展現形式是:
{ '第一題:離離原上草 一歲一枯榮的作者是誰。': [ '白居易', '李白', '杜甫', '柳宗元', ], '第二題:白日依山盡,黃河入海流,出自那首詩。': [ '登鸛雀樓', '...', '...', '...', ], },
其中正確答案“白居易”和“登鸛雀樓”放在第一個位置,但是在給用戶出題時,選項的順序會調整。
模板的使用說明:
答案中必須有一個正確答案。
每道題的答案選項可以是3個,4個,5個,選項總數不收限制。
每個題目必須通過選項序號來作答,如用戶必須說“第一個”、“第二個”,不能使用“是”、“對”、“錯”、“不是”等進行回答。
請注意,下面的新建技能和配置意圖過程可以通過在技能平臺-->創建技能-->引用技能-->導入技能頁面導入 http://dbp-cfc.cdn.bcebos.com/download/trivia.zip 實現。
新建技能詳情請參閱自定義技能創建
意圖配置詳情請參閱意圖、常用表達和槽位
問答技能模板需要創建兩個意圖,分別是回答問題意圖和重新開始問答意圖。 回答問題意圖如下圖所示:
重新開始問答意圖如下圖所示:
問答技能模板使用CFC部署技能服務。使用CFC部署技能服務詳情請參閱 百度云CFC
問答技能模板使用questions.js配置題庫。開發者需要下載技能CFC函數完整zip程序包到本地進行開發,開發完成后上傳函數zip包進行發布。具體流程如下:
在CFC控制臺通過模板創建函數, 選擇node.js DuerOS Bot SDK模板
函數生成后,在函數控制臺點擊點擊下載完整 ZIP 程序包
鏈接下載程序包
在本地解壓程序包
將https://github.com/dueros/bot-sdk-node.js/blob/master/samples/trivia/questions.js文件拷貝到程序包文件夾中
使用https://github.com/dueros/bot-sdk-node.js/blob/master/samples/trivia/index.js替換程序包文件夾中的index.js文件
將程序包文件夾中的所有文件重新打包成zip文件
在函數控制臺上傳zip程序包并保存
CFC操作說明請參閱函數計算 CFC
const Bot = require('bot-sdk'); const privateKey = require("./rsaKeys.js").privateKey; const question_list = [ { '遠上還山石徑斜,白云深處有人家': [ '正確的', '杜甫', '白居易', '李白', ], }, { '離離原上草,一歲一枯榮': [ '正確的', '杜甫', '白居易', '李白', ], }, { '舉頭望明月,低頭思故鄉': [ '正確的', '杜甫', '白居易', '李白', ], }, { '鋤禾日當午 汗滴禾下土': [ '正確的', '杜甫', '白居易', '李白', ], }, { '白日依山盡,黃河入海流': [ '正確的', '杜甫', '白居易', '李白', ], }, { '李白乘舟將欲行,忽聞岸上踏歌聲': [ '正確的', '杜甫', '白居易', '李白', ], }, { '橫看成嶺側成峰,遠近高低各不同': [ '正確的', '杜甫', '白居易', '李白', ], }, { '人生自古誰無死,留取丹心照汗青': [ '文天祥', '杜甫', '白居易', '李白', ], } ]; //定義一輪問答中的問題數量 const GAME_LENGTH = 5; //定義每個問題的答案數量 const ANSWER_COUNT = 3; class InquiryBot extends Bot { constructor(postData) { super(postData); this.addLaunchHandler(() => { this.waitAnswer(); let speechOutput = '歡迎來到古詩問答。我將念兩句古詩并給你三個詩人的名字。需要你告訴我哪一個是正確的作者。'; //初始化一輪中的問題列表和第一題的話術 let repromptText = this.startNewGame(); let card = new Bot.Card.TextCard(repromptText); return { card: card, outputSpeech: speechOutput + repromptText }; }); this.addSessionEndedHandler(() => { this.endSession(); return { outputSpeech: '謝謝使用!' }; }); this.addIntentHandler('answer_intent', () => { this.waitAnswer(); //確保獲取到了用戶的回答 let theAnswer = this.getSlot('theAnswer'); if (!theAnswer) { this.nlu.ask('theAnswer'); return { outputSpeech: '您的答案是哪個?' }; } //獲取session中相關信息 let questionsList = this.getSessionAttribute('questionsList'); let score = this.getSessionAttribute('score'); let currentQuestionIndex = this.getSessionAttribute('currentQuestionIndex'); let correctAnswerIndex = this.getSessionAttribute('correctAnswerIndex'); let gameQuestions = this.getSessionAttribute('gameQuestions'); let correctAnswerText = this.getSessionAttribute('correctAnswerText'); let speechOutput = ''; if (theAnswer == correctAnswerIndex){ score += 1; speechOutput = '回答正確,得一分。目前得分:' + score + '分。'; }else{ speechOutput = '很遺憾,回答錯誤。正確答案是' + correctAnswerText + '.目前得分:' + score + '分。'; } //到達最后一題,用戶選擇重新開始一輪或者退出技能 if (currentQuestionIndex == GAME_LENGTH - 1){ speechOutput += '已經是最后一題了。您可以說重新開始來繼續答題,或者說退出來退出技能。' return { outputSpeech: speechOutput }; } //獲取下一題信息 currentQuestionIndex += 1; correctAnswerIndex = Math.floor(Math.random() * (ANSWER_COUNT)); let spokenQuestion = Object.keys(questionsList[gameQuestions[currentQuestionIndex]])[0]; let roundAnswers = this.populateRoundAnswers(gameQuestions, currentQuestionIndex,correctAnswerIndex,questionsList); let questionIndexForSpeech = currentQuestionIndex + 1; let repromptText = '第' + questionIndexForSpeech + '題:\n' + spokenQuestion + '\n'; for (let i = 0; i < ANSWER_COUNT; i += 1) { repromptText += `${i + 1}. ${roundAnswers[i]}. `; } speechOutput += repromptText; let currentQuestion = questionsList[gameQuestions[currentQuestionIndex]]; this.setSessionAttribute('speechOutput',speechOutput); this.setSessionAttribute('currentQuestionIndex',currentQuestionIndex); this.setSessionAttribute('correctAnswerIndex',correctAnswerIndex + 1); this.setSessionAttribute('gameQuestions',gameQuestions); this.setSessionAttribute('questionsList',questionsList); this.setSessionAttribute('score',score); this.setSessionAttribute('correctAnswerText',currentQuestion[Object.keys(currentQuestion)[0]][0]); let card = new Bot.Card.TextCard(repromptText); return { card: card, outputSpeech: speechOutput }; }); //重新開始答題,得分清零 this.addIntentHandler('newGame_intent', () => { this.waitAnswer(); //初始化一輪中的問題列表和第一題的話術 let repromptText = this.startNewGame(); let card = new Bot.Card.TextCard(repromptText); return { card: card, outputSpeech: '好的,重新開始。' + repromptText }; }); /* * 獲取沒有被意圖解析的用戶輸入,并進行相關處理 * 缺省意圖 https://developer.dueros.baidu.com/didp/doc/dueros-bot-platform/dbp-nlu/defaultIntent_markdown */ this.addIntentHandler('ai.dueros.common.default_intent', () => { this.waitAnswer(); return { outputSpeech: '您可以對我說第幾個來告訴我您的答案。您也可以說重新開始重新玩,或者說退出來退出游戲。' }; }); } /** * 獲取新一輪問題列表和相應的信息,并將信息存入session中 * * @return 新一輪答題話術 */ startNewGame() { let questionsList = question_list; let gameQuestions = this.populateGameQuestions(questionsList); let correctAnswerIndex = Math.floor(Math.random() * (ANSWER_COUNT)); console.log(correctAnswerIndex); let roundAnswers = this.populateRoundAnswers(gameQuestions, 0,correctAnswerIndex,questionsList); let currentQuestionIndex = 0; let spokenQuestion = Object.keys(questionsList[gameQuestions[currentQuestionIndex]])[0]; let repromptText = '第1題:\n' + spokenQuestion + '\n'; for (let i = 0; i < ANSWER_COUNT; i += 1) { repromptText += `${i + 1}. ${roundAnswers[i]}. `; } let currentQuestion = questionsList[gameQuestions[currentQuestionIndex]]; this.setSessionAttribute('currentQuestionIndex',currentQuestionIndex); this.setSessionAttribute('correctAnswerIndex',correctAnswerIndex + 1); this.setSessionAttribute('gameQuestions',gameQuestions); this.setSessionAttribute('questionsList',questionsList); this.setSessionAttribute('score',0); this.setSessionAttribute('correctAnswerText',currentQuestion[Object.keys(currentQuestion)[0]][0]); return repromptText; } /** * 從問題列表中隨機抽取問題。問題個數由變量GAME_LENGTH定義 * @param {list} translatedQuestions 所有問題列表 * @return 問題id列表 */ populateGameQuestions(translatedQuestions) { let gameQuestions = []; let indexList = []; let index = translatedQuestions.length; if (GAME_LENGTH > index) { throw new Error('Invalid Game Length.'); } for (let i = 0; i < translatedQuestions.length; i += 1) { indexList.push(i); } for (let j = 0; j < GAME_LENGTH; j += 1) { let rand = Math.floor(Math.random() * index); index -= 1; let temp = indexList[index]; indexList[index] = indexList[rand]; indexList[rand] = temp; gameQuestions.push(indexList[index]); } return gameQuestions; } /** * 從問題列表中隨機抽取問題。問題個數由變量GAME_LENGTH定義 * @param {list} gameQuestionIndexes 一輪問答中問題id列表 * @param {int} currentQuestionIndex 當前問題Index * @param {int} correctAnswerTargetLocation 當前問題答案Index * @param {list} translatedQuestions 所有問題列表 * @return 當前問題答案選項列表 */ populateRoundAnswers(gameQuestionIndexes,currentQuestionIndex,correctAnswerTargetLocation,translatedQuestions) { const answers = []; const translatedQuestion = translatedQuestions[gameQuestionIndexes[currentQuestionIndex]]; const answersCopy = translatedQuestion[Object.keys(translatedQuestion)[0]].slice(); let index = answersCopy.length; if (index < ANSWER_COUNT) { throw new Error('Not enough answers for question.'); } // 打亂當前問題答案列表順序 for (let j = 1; j < answersCopy.length; j += 1) { const rand = Math.floor(Math.random() * (index - 1)) + 1; index -= 1; const swapTemp1 = answersCopy[index]; answersCopy[index] = answersCopy[rand]; answersCopy[rand] = swapTemp1; } // 將正確答案放置到correctAnswerTargetLocation的位置 for (let i = 0; i < ANSWER_COUNT; i += 1) { answers[i] = answersCopy[i]; } const swapTemp2 = answers[0]; answers[0] = answers[correctAnswerTargetLocation]; answers[correctAnswerTargetLocation] = swapTemp2; return answers; } } exports.handler = function(event, context, callback) { try { let b = new InquiryBot(event); // 0: debug 1: online b.botMonitor.setEnvironmentInfo(privateKey, 0); b.run().then(function(result) { callback(null, result); }).catch(callback); } catch (e) { callback(e); } }
至此,問答技能就開發完成了。開發者可以在技能開放平臺的模擬測試頁面對技能進行測試。
關于如何使用nodejs BOT SDK開發問答類技能模板就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。