From a9f9b96e396152638d6b3bfd76c5b676ff4ca3fc Mon Sep 17 00:00:00 2001
From: Fei Chen <43032123+feich-ms@users.noreply.github.com>
Date: Sat, 31 Oct 2020 04:06:46 +0800
Subject: [PATCH] Fix a regression on multiturn extraction functionality of qna
url or file import api (#1042) (#1043)
* fix regression on file and url import api
* add unit tests for multiturn extraction"
---
packages/lu/src/parser/qnabuild/builder.ts | 32 +++-
.../lu/test/parser/qnabuild/qnabuild.test.js | 161 ++++++++++++++++++
2 files changed, 184 insertions(+), 9 deletions(-)
diff --git a/packages/lu/src/parser/qnabuild/builder.ts b/packages/lu/src/parser/qnabuild/builder.ts
index 0ebefa17f..d16102d97 100644
--- a/packages/lu/src/parser/qnabuild/builder.ts
+++ b/packages/lu/src/parser/qnabuild/builder.ts
@@ -301,7 +301,9 @@ export class Builder {
url: string,
subscriptionkey: string,
endpoint: string,
- kbName: string) {
+ kbName: string,
+ enableHierarchicalExtraction: boolean = false,
+ defaultAnswerUsedForExtraction: string = 'More Answers') {
const qnaBuildCore = new QnaBuildCore(subscriptionkey, endpoint)
const kbs = (await qnaBuildCore.getKBList()).knowledgebases
@@ -320,7 +322,7 @@ export class Builder {
}
// create a new kb
- kbId = await this.createUrlKB(qnaBuildCore, url, kbName)
+ kbId = await this.createUrlKB(qnaBuildCore, url, kbName, enableHierarchicalExtraction, defaultAnswerUsedForExtraction)
const kbJson = await qnaBuildCore.exportKB(kbId, 'Test')
const kb = new KB(kbJson)
@@ -335,7 +337,9 @@ export class Builder {
fileUri: string,
subscriptionkey: string,
endpoint: string,
- kbName: string) {
+ kbName: string,
+ enableHierarchicalExtraction: boolean = false,
+ defaultAnswerUsedForExtraction: string = 'More Answers') {
const qnaBuildCore = new QnaBuildCore(subscriptionkey, endpoint)
const kbs = (await qnaBuildCore.getKBList()).knowledgebases
@@ -354,7 +358,7 @@ export class Builder {
}
// create a new kb
- kbId = await this.createFileKB(qnaBuildCore, fileName, fileUri, kbName)
+ kbId = await this.createFileKB(qnaBuildCore, fileName, fileUri, kbName, enableHierarchicalExtraction, defaultAnswerUsedForExtraction)
const kbJson = await qnaBuildCore.exportKB(kbId, 'Test')
const kb = new KB(kbJson)
@@ -465,12 +469,17 @@ export class Builder {
return kbId
}
- async createUrlKB(qnaBuildCore: QnaBuildCore, url: string, kbName: string) {
- const kbJson = {
+ async createUrlKB(qnaBuildCore: QnaBuildCore, url: string, kbName: string, enableHierarchicalExtraction: boolean, defaultAnswerUsedForExtraction: string) {
+ let kbJson: any = {
name: kbName,
qnaList: [],
urls: [url],
- files: []
+ files: [],
+ }
+
+ if (enableHierarchicalExtraction) {
+ kbJson.enableHierarchicalExtraction = true
+ kbJson.defaultAnswerUsedForExtraction = defaultAnswerUsedForExtraction
}
let response = await qnaBuildCore.importKB(kbJson)
@@ -481,8 +490,8 @@ export class Builder {
return kbId
}
- async createFileKB(qnaBuildCore: QnaBuildCore, fileName: string, fileUri: string, kbName: string) {
- let kbJson = {
+ async createFileKB(qnaBuildCore: QnaBuildCore, fileName: string, fileUri: string, kbName: string, enableHierarchicalExtraction: boolean, defaultAnswerUsedForExtraction: string) {
+ let kbJson: any = {
name: kbName,
qnaList: [],
urls: [],
@@ -492,6 +501,11 @@ export class Builder {
}]
}
+ if (enableHierarchicalExtraction) {
+ kbJson.enableHierarchicalExtraction = true
+ kbJson.defaultAnswerUsedForExtraction = defaultAnswerUsedForExtraction
+ }
+
let response = await qnaBuildCore.importKB(kbJson)
let operationId = response.operationId
const opResult = await this.getKBOperationStatus(qnaBuildCore, operationId, 1000)
diff --git a/packages/lu/test/parser/qnabuild/qnabuild.test.js b/packages/lu/test/parser/qnabuild/qnabuild.test.js
index 084923830..bac157fdd 100644
--- a/packages/lu/test/parser/qnabuild/qnabuild.test.js
+++ b/packages/lu/test/parser/qnabuild/qnabuild.test.js
@@ -134,6 +134,87 @@ describe('builder: importUrlOrFileReference function return lu content from file
})
})
+describe('builder: importUrlOrFileReference function return lu content from file sucessfully with multiturn extraction enabled', () => {
+ before(function () {
+ nock('https://westus.api.cognitive.microsoft.com')
+ .get(uri => uri.includes('qnamaker'))
+ .reply(200, {
+ knowledgebases:
+ [{
+ name: 'test.en-us.qna',
+ id: 'f8c64e2a-1111-3a09-8f78-39d7adc76ec5',
+ hostName: 'https://myqnamakerbot.azurewebsites.net'
+ }]
+ })
+
+ nock('https://westus.api.cognitive.microsoft.com')
+ .post(uri => uri.includes('createasync'))
+ .reply(202, {
+ operationId: 'f8c64e2a-aaaa-3a09-8f78-39d7adc76ec5'
+ })
+
+ nock('https://westus.api.cognitive.microsoft.com')
+ .get(uri => uri.includes('operations'))
+ .reply(200, {
+ operationState: 'Succeeded',
+ resourceLocation: 'a/b/f8c64e2a-2222-3a09-8f78-39d7adc76ec5'
+ })
+
+ nock('https://westus.api.cognitive.microsoft.com')
+ .get(uri => uri.includes('knowledgebases'))
+ .reply(200, {
+ qnaDocuments: [{
+ id: 1,
+ source: 'SurfaceManual.pdf',
+ questions: ['User Guide'],
+ answer: 'More Answers',
+ metadata: [],
+ prompts: [{
+ displayOrder: 0,
+ displayText: 'With Windows 10',
+ qnaId: 2
+ }]
+ },
+ {
+ id: 2,
+ source: 'SurfaceManual.pdf',
+ questions: ['With Windows 10'],
+ answer: '**With Windows 10**',
+ metadata: [],
+ prompts: []
+ }]
+ })
+ })
+
+ nock('https://westus.api.cognitive.microsoft.com')
+ .delete(uri => uri.includes('knowledgebases'))
+ .reply(200)
+
+ it('should return lu content from file successfully', async () => {
+ const builder = new Builder()
+ const luContent = await builder.importFileReference(
+ 'SurfaceManual.pdf',
+ 'https://download.microsoft.com/download/2/9/B/29B20383-302C-4517-A006-B0186F04BE28/surface-pro-4-user-guide-EN.pdf',
+ uuidv1(),
+ 'https://westus.api.cognitive.microsoft.com/qnamaker/v4.0',
+ 'mytest.en-us.qna',
+ true)
+
+ assert.equal(luContent,
+ `> # QnA pairs${NEWLINE}${NEWLINE}` +
+ `> !# @qna.pair.source = SurfaceManual.pdf${NEWLINE}${NEWLINE}` +
+ `${NEWLINE}${NEWLINE}` +
+ `# ? User Guide${NEWLINE}${NEWLINE}` +
+ `\`\`\`markdown${NEWLINE}` +
+ `More Answers${NEWLINE}\`\`\`${NEWLINE}${NEWLINE}` +
+ `> !# @qna.pair.source = SurfaceManual.pdf${NEWLINE}${NEWLINE}` +
+ `${NEWLINE}${NEWLINE}` +
+ `# ? With Windows 10${NEWLINE}${NEWLINE}` +
+ `\`\`\`markdown${NEWLINE}` +
+ `**With Windows 10**${NEWLINE}\`\`\`${NEWLINE}${NEWLINE}`)
+ })
+})
+
describe('builder: importUrlOrFileReference function return lu content from url sucessfully', () => {
before(function () {
nock('https://westus.api.cognitive.microsoft.com')
@@ -193,6 +274,86 @@ describe('builder: importUrlOrFileReference function return lu content from url
})
})
+describe('builder: importUrlOrFileReference function return lu content from url sucessfully with multiturn extraction enabled', () => {
+ before(function () {
+ nock('https://westus.api.cognitive.microsoft.com')
+ .get(uri => uri.includes('qnamaker'))
+ .reply(200, {
+ knowledgebases:
+ [{
+ name: 'test.en-us.qna',
+ id: 'f8c64e2a-1111-3a09-8f78-39d7adc76ec5',
+ hostName: 'https://myqnamakerbot.azurewebsites.net'
+ }]
+ })
+
+ nock('https://westus.api.cognitive.microsoft.com')
+ .post(uri => uri.includes('createasync'))
+ .reply(202, {
+ operationId: 'f8c64e2a-aaaa-3a09-8f78-39d7adc76ec5'
+ })
+
+ nock('https://westus.api.cognitive.microsoft.com')
+ .get(uri => uri.includes('operations'))
+ .reply(200, {
+ operationState: 'Succeeded',
+ resourceLocation: 'a/b/f8c64e2a-2222-3a09-8f78-39d7adc76ec5'
+ })
+
+ nock('https://westus.api.cognitive.microsoft.com')
+ .get(uri => uri.includes('knowledgebases'))
+ .reply(200, {
+ qnaDocuments: [{
+ id: 1,
+ source: 'SurfaceManual.pdf',
+ questions: ['User Guide'],
+ answer: 'More Answers',
+ metadata: [],
+ prompts: [{
+ displayOrder: 0,
+ displayText: 'With Windows 10',
+ qnaId: 2
+ }]
+ },
+ {
+ id: 2,
+ source: 'SurfaceManual.pdf',
+ questions: ['With Windows 10'],
+ answer: '**With Windows 10**',
+ metadata: [],
+ prompts: []
+ }]
+ })
+
+ nock('https://westus.api.cognitive.microsoft.com')
+ .delete(uri => uri.includes('knowledgebases'))
+ .reply(200)
+ })
+
+ it('should return lu content from url successfully', async () => {
+ const builder = new Builder()
+ const luContent = await builder.importUrlReference(
+ 'https://docs.microsoft.com/en-in/azure/cognitive-services/qnamaker/faqs',
+ uuidv1(),
+ 'https://westus.api.cognitive.microsoft.com/qnamaker/v4.0',
+ 'mytest.en-us.qna',
+ true)
+
+ assert.equal(luContent,
+ `> # QnA pairs${NEWLINE}${NEWLINE}` +
+ `> !# @qna.pair.source = SurfaceManual.pdf${NEWLINE}${NEWLINE}` +
+ `${NEWLINE}${NEWLINE}` +
+ `# ? User Guide${NEWLINE}${NEWLINE}` +
+ `\`\`\`markdown${NEWLINE}` +
+ `More Answers${NEWLINE}\`\`\`${NEWLINE}${NEWLINE}` +
+ `> !# @qna.pair.source = SurfaceManual.pdf${NEWLINE}${NEWLINE}` +
+ `${NEWLINE}${NEWLINE}` +
+ `# ? With Windows 10${NEWLINE}${NEWLINE}` +
+ `\`\`\`markdown${NEWLINE}` +
+ `**With Windows 10**${NEWLINE}\`\`\`${NEWLINE}${NEWLINE}`)
+ })
+})
+
describe('builder: importUrlOrFileReference function return lu content from url sucessfully when updating kb', () => {
before(function () {
nock('https://westus.api.cognitive.microsoft.com')