接受知識庫中主動式學習建議的問題

注意

QnA Maker 服務即將於 2025 年 3 月 31 日淘汰。 現在,Azure AI 語言提供較新版本的問題和答案功能。 如需瞭解語言服務內的問題解答功能,請參閱問題解答。 從 2022 年 10 月 1 日開始,您將無法建立新的 QnA Maker 資源。 如需將現有的 QnA Maker 知識庫移轉至問題解答的相關資訊,請參閱移轉指南

主動式學習會在您核准建議之後改變知識庫或搜尋服務,然後儲存並訓練。 如果您核准建議,則系統會將其新增為替代問題。

開啟主動式學習

為了查看建議的問題,您必須針對 QnA Maker 資源開啟主動式學習

檢視建議的問題

  1. 為了查看建議的問題,請在 [編輯知識庫] 頁面上選取 [檢視選項],然後選取 [顯示主動式學習建議]。 如果沒有針對任何問答配對的建議,則會停用此選項。

    在入口網站的 [編輯] 區段中,選取 [顯示建議] 以查看作用中學習的新問題替代方式。

  2. 選取 [依建議篩選],將包含問答配對的知識庫篩選成僅顯示建議。

    使用 [依建議篩選] 切換,僅檢視作用中學習的建議問題替代方式。

  3. 每個 QnA 配對都會建議新的問題替代方式,附有核取記號 (用以接受問題) 和 x (用以拒絕建議)。 選取核取記號可新增問題。

    藉由選取綠色核取記號或紅色刪除標記,選取或拒絕作用中學習的建議問題替代方式。

    您可以在內容工具列中選取 [全部新增] 或 [全部拒絕] 來新增或刪除「所有建議」。

  4. 選取 [儲存並訓練],以儲存對知識庫所做的變更。

  5. 選取 [發佈],以允許可從 GenerateAnswer API 取得變更。

    當您將 5 個以上的查詢叢集化時,每隔 30 分鐘 QnA Maker 便會建議替代問題,讓您接受或拒絕它們。

主動式學習建議會儲存在匯出的知識庫中

當您的應用程式已啟用主動式學習,且您匯出應用程式時,tsv 檔案中的 SuggestedQuestions 資料行會保留主動式學習資料。

SuggestedQuestions 資料行是隱含 autosuggested 和明確 usersuggested 意見反應資訊的 JSON 物件。 針對單一使用者提交的 help 問題,此 JSON 物件的範例為:

[
    {
        "clusterHead": "help",
        "totalAutoSuggestedCount": 1,
        "totalUserSuggestedCount": 0,
        "alternateQuestionList": [
            {
                "question": "help",
                "autoSuggestedCount": 1,
                "userSuggestedCount": 0
            }
        ]
    }
]

當您重新匯入此應用程式時,主動式學習會繼續為您的知識庫收集資訊和提供建議。

從 Bot 使用 GenerateAnswer 和訓練 API 的架構流程

Bot 或其他用戶端應用程式應該使用下列架構流程來使用主動式學習:

  1. Bot 會使用 GenerateAnswer API 從知識庫取得答案,也會使用 top 屬性取得一些答案。

  2. Bot 會判定明確的意見反應:

    • 使用您自己的自訂商務邏輯,篩選出低分數。
    • 在 Bot 或用戶端應用程式中,顯示使用者的可能答案清單,並取得使用者選取的答案。
  3. Bot 會使用訓練 API將選取的答案送回 QnA Maker

在 GenerateAnswer 要求中使用 top 屬性來取得數個相符的答案

將問題提交給 QnA Maker 以取得答案時,JSON 主體的 top 屬性會設定要傳回的答案數目。

{
    "question": "wi-fi",
    "isTest": false,
    "top": 3
}

使用 score 屬性以及商務邏輯,取得要向使用者顯示的答案清單

當用戶端應用程式 (例如聊天機器人) 收到回應時,系統會傳回前 3 個問題。 使用 score 屬性來分析分數之間的鄰近性。 這個鄰近性範圍是由您自己的商務邏輯決定。

{
    "answers": [
        {
            "questions": [
                "Wi-Fi Direct Status Indicator"
            ],
            "answer": "**Wi-Fi Direct Status Indicator**\n\nStatus bar icons indicate your current Wi-Fi Direct connection status:  \n\nWhen your device is connected to another device using Wi-Fi Direct, '$  \n\n+ *+ ' Wi-Fi Direct is displayed in the Status bar.",
            "score": 74.21,
            "id": 607,
            "source": "Bugbash KB.pdf",
            "metadata": []
        },
        {
            "questions": [
                "Wi-Fi - Connections"
            ],
            "answer": "**Wi-Fi**\n\nWi-Fi is a term used for certain types of Wireless Local Area Networks (WLAN). Wi-Fi communication requires access to a wireless Access Point (AP).",
            "score": 74.15,
            "id": 599,
            "source": "Bugbash KB.pdf",
            "metadata": []
        },
        {
            "questions": [
                "Turn Wi-Fi On or Off"
            ],
            "answer": "**Turn Wi-Fi On or Off**\n\nTurning Wi-Fi on makes your device able to discover and connect to compatible in-range wireless APs.  \n\n1.  From a Home screen, tap ::: Apps > e Settings .\n2.  Tap Connections > Wi-Fi , and then tap On/Off to turn Wi-Fi on or off.",
            "score": 69.99,
            "id": 600,
            "source": "Bugbash KB.pdf",
            "metadata": []
        }
    ]
}

用戶端應用程式在問題具有類似分數時的後續動作

您的用戶端應用程式會顯示所有問題,並且讓使用者可以選取最能代表其意圖的「單一問題」。

一旦使用者選取了其中一個現有問題,用戶端應用程式就會使用 QnA Maker 訓練 API,將使用者的選擇當作意見反應傳送。 此意見反應會完成主動式學習意見反應迴圈。

將 API 定型

主動式學習意見反應會隨著訓練 API POST 要求傳送至 QnA Maker。 API 簽章為:

POST https://<QnA-Maker-resource-name>.azurewebsites.net/qnamaker/knowledgebases/<knowledge-base-ID>/train
Authorization: EndpointKey <endpoint-key>
Content-Type: application/json
{"feedbackRecords": [{"userId": "1","userQuestion": "<question-text>","qnaId": 1}]}
HTTP 要求屬性 名稱 類型 目的
URL 路由參數 知識庫識別碼 字串 測試您知識庫的 GUID。
自訂子網域 QnAMaker 資源名稱 字串 資源名稱會用作 QnA Maker 的自訂子網域。 在您發佈知識庫之後,可以在 [設定] 頁面上使用此項。 其會列示為 host
標頭 Content-Type 字串 傳送至 API 的本文媒體類型。 預設值為:application/json
標頭 授權 字串 您的端點金鑰 (EndpointKey xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)。
張貼本文 JSON 物件 JSON 訓練意見反應

JSON 主體有數個設定:

JSON 主體屬性 類型 目的
feedbackRecords array 意見反應清單。
userId 字串 接受所建議問題的人員的使用者識別碼。 使用者識別碼格式是由您決定。 例如,電子郵件地址可以是您架構中的有效使用者識別碼。 選擇性。
userQuestion 字串 使用者查詢的確切文字。 必要。
qnaID number 問題的識別碼,可在 GenerateAnswer 回應中找到。

範例 JSON 主體看起來像這樣:

{
    "feedbackRecords": [
        {
            "userId": "1",
            "userQuestion": "<question-text>",
            "qnaId": 1
        }
    ]
}

成功回應會傳回狀態 204 且沒有 JSON 回應主體。

將許多意見反應記錄批次成單一呼叫

在用戶端應用程式 (例如 Bot) 中,您可以儲存資料,然後在 feedbackRecords 陣列的單一 JSON 主體中傳送許多記錄。

範例 JSON 主體看起來像這樣:

{
    "feedbackRecords": [
        {
            "userId": "1",
            "userQuestion": "How do I ...",
            "qnaId": 1
        },
        {
            "userId": "2",
            "userQuestion": "Where is ...",
            "qnaId": 40
        },
        {
            "userId": "3",
            "userQuestion": "When do I ...",
            "qnaId": 33
        }
    ]
}

Bot Framework 範例程式碼

如果使用者的查詢應該用於主動式學習,則您的 Bot Framework 程式碼必須呼叫訓練 API。 有兩段要撰寫的程式碼:

  • 判斷是否應該使用查詢來進行主動式學習
  • 將查詢送回 QnA Maker 訓練 API,以進行主動式學習

Azure Bot 範例中,這兩個活動都是以程式設計的。

訓練 API 的範例 C# 程式碼,搭配 Bot Framework 4.x

下列程式碼說明如何使用訓練 API,將資訊送回 QnA Maker。

public class FeedbackRecords
{
    // <summary>
    /// List of feedback records
    /// </summary>
    [JsonProperty("feedbackRecords")]
    public FeedbackRecord[] Records { get; set; }
}

/// <summary>
/// Active learning feedback record
/// </summary>
public class FeedbackRecord
{
    /// <summary>
    /// User id
    /// </summary>
    public string UserId { get; set; }

    /// <summary>
    /// User question
    /// </summary>
    public string UserQuestion { get; set; }

    /// <summary>
    /// QnA Id
    /// </summary>
    public int QnaId { get; set; }
}

/// <summary>
/// Method to call REST-based QnAMaker Train API for Active Learning
/// </summary>
/// <param name="endpoint">Endpoint URI of the runtime</param>
/// <param name="FeedbackRecords">Feedback records train API</param>
/// <param name="kbId">Knowledgebase Id</param>
/// <param name="key">Endpoint key</param>
/// <param name="cancellationToken"> Cancellation token</param>
public async static void CallTrain(string endpoint, FeedbackRecords feedbackRecords, string kbId, string key, CancellationToken cancellationToken)
{
    var uri = endpoint + "/knowledgebases/" + kbId + "/train/";

    using (var client = new HttpClient())
    {
        using (var request = new HttpRequestMessage())
        {
            request.Method = HttpMethod.Post;
            request.RequestUri = new Uri(uri);
            request.Content = new StringContent(JsonConvert.SerializeObject(feedbackRecords), Encoding.UTF8, "application/json");
            request.Headers.Add("Authorization", "EndpointKey " + key);

            var response = await client.SendAsync(request, cancellationToken);
            await response.Content.ReadAsStringAsync();
        }
    }
}

訓練 API 的範例 Node.js 程式碼,搭配 Bot Framework 4.x

下列程式碼說明如何使用訓練 API,將資訊送回 QnA Maker。

async callTrain(stepContext){

    var trainResponses = stepContext.values[this.qnaData];
    var currentQuery = stepContext.values[this.currentQuery];

    if(trainResponses.length > 1){
        var reply = stepContext.context.activity.text;
        var qnaResults = trainResponses.filter(r => r.questions[0] == reply);

        if(qnaResults.length > 0){

            stepContext.values[this.qnaData] = qnaResults;

            var feedbackRecords = {
                FeedbackRecords:[
                    {
                        UserId:stepContext.context.activity.id,
                        UserQuestion: currentQuery,
                        QnaId: qnaResults[0].id
                    }
                ]
            };

            // Call Active Learning Train API
            this.activeLearningHelper.callTrain(this.qnaMaker.endpoint.host, feedbackRecords, this.qnaMaker.endpoint.knowledgeBaseId, this.qnaMaker.endpoint.endpointKey);

            return await stepContext.next(qnaResults);
        }
        else{

            return await stepContext.endDialog();
        }
    }

    return await stepContext.next(stepContext.result);
}

最佳作法

如需使用主動式學習時的最佳做法,請參閱最佳做法

下一步