Quickstart: QnA Maker client library

Get started with the QnA Maker client library. Follow these steps to install the package and try out the example code for basic tasks.

Use the QnA Maker client library for .NET to:

  • Create a knowledgebase
  • Update a knowledgebase
  • Publish a knowledgebase
  • Get prediction runtime endpoint key
  • Wait for long-running task
  • Download a knowledgebase
  • Get answer
  • Delete a knowledgebase

Reference documentation | Library source code | Package (NuGet) | C# Samples

Note

New resources created after July 1, 2019, will use custom subdomain names. For more information and a complete list of regional endpoints, see Custom subdomain names for Cognitive Services.

Prerequisites

  • Azure subscription - Create one for free
  • The Visual Studio IDE or current version of .NET Core.
  • Once you have your Azure subscription, create a QnA Maker resource in the Azure portal to get your authoring key and resource name. After it deploys, select Go to resource.
    • You will need the key and resource name from the resource you create to connect your application to the QnA Maker API. You'll paste your key and resource name into the code below later in the quickstart.
    • You can use the free pricing tier (F0) to try the service, and upgrade later to a paid tier for production.

Setting up

Using Visual Studio, create a .NET Core application and install the client library by right-clicking on the solution in the Solution Explorer and selecting Manage NuGet Packages. In the package manager that opens select Browse, check Include prerelease, and search for Microsoft.Azure.CognitiveServices.Knowledge.QnAMaker. Select version 2.0.0-preview.1, and then Install.

Tip

Want to view the whole quickstart code file at once? You can find it on GitHub, which contains the code examples in this quickstart.

From the project directory, open the program.cs file and add the following using directives:

using Microsoft.Azure.CognitiveServices.Knowledge.QnAMaker;
using Microsoft.Azure.CognitiveServices.Knowledge.QnAMaker.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

In the application's Main method, add variables and code, shown in the following section, to use the common tasks in this quickstart.

Important

Go to the Azure portal and find the key and endpoint for the QnA Maker resource you created in the prerequisites. They will be located on the resource's key and endpoint page, under resource management. You need the entire key to create your knowledgebase. You need only the resource name from the endpoint. The format is https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com. Remember to remove the key from your code when you're done, and never post it publicly. For production, consider using a secure way of storing and accessing your credentials. For example, Azure key vault provides secure key storage.

var authoringKey = "REPLACE-WITH-YOUR-QNA-MAKER-KEY";
var resourceName = "REPLACE-WITH-YOUR-RESOURCE-NAME";

var authoringURL = $"https://{resourceName}.cognitiveservices.azure.com";
var queryingURL = $"https://{resourceName}.azurewebsites.net";

Object models

QnA Maker uses two different object models:

  • QnAMakerClient is the object to create, manage, publish, and download the knowledgebase.
  • QnAMakerRuntime is the object to query the knowledge base with the GenerateAnswer API and send new suggested questions using the Train API (as part of active learning).

Using this example knowledge base

The knowledge base in this quickstart starts with 2 conversational QnA pairs, this is done on purpose to simplify the example and to have highly predictable Ids to use in the Update method, associating follow-up prompts with questions to new pairs. This was planned and implemented in a specific order for this quickstart.

If you plan to develop your knowledge base over time with follow-up prompts that are dependent on existing QnA pairs, you may choose:

  • For larger knowledgebases, manage the knowledge base in a text editor or TSV tool that supports automation, then completely replace the knowledge base at once with an update.
  • For smaller knowledgebases, manage the follow-up prompts entirely in the QnA Maker portal.

Details about the QnA pairs used in this quickstart:

  • Types of QnA pair - there are 2 types of QnA pairs in this knowledge base, after the update: chitchat and domain-specific information. This is typical if your knowledgebase is tied to a conversation application such as a chatbot.
  • While the knowledgebase answers could be filtered by metadata or use followup prompts, this quickstart doesn't show that. Look for those language-agnostic generateAnswer examples here.
  • Answer text is markdown and can contain a wide variety of markdown such as images (publicly available internet-based images), links (to publicly available URLs), and bullet points, this quickstart doesn't use that variety.

QnAMakerClient object model

The authoring QnA Maker client is a QnAMakerClient object that authenticates to Azure using Microsoft.Rest.ServiceClientCredentials, which contains your key.

Once the client is created, use the Knowledge base property to create, manage, and publish your knowledge base.

Manage your knowledge base by sending a JSON object. For immediate operations, a method usually returns a JSON object indicating status. For long-running operations, the response is the operation ID. Call the client.Operations.GetDetailsAsync method with the operation ID to determine the status of the request.

QnAMakerRuntimeClient object model

The prediction QnA Maker client is a QnAMakerRuntimeClient object that authenticates to Azure using Microsoft.Rest.ServiceClientCredentials, which contains your prediction runtime key, returned from the authoring client call, client.EndpointKeys.GetKeys after the knowledgebase is published.

Use the GenerateAnswer method to get an answer from the query runtime.

Code examples

These code snippets show you how to do the following with the QnA Maker client library for .NET:

Authenticate the client for authoring the knowledge base

Instantiate a client object with your key, and use it with your resource to construct the endpoint to create an QnAMakerClient with your endpoint and key. Create a ServiceClientCredentials object.

var client = new QnAMakerClient(new ApiKeyServiceClientCredentials(authoringKey))
{ Endpoint = authoringURL };

Create a knowledge base

A knowledge base stores question and answer pairs for the CreateKbDTO object from three sources:

  • For editorial content, use the QnADTO object.
    • To use metadata and follow-up prompts, use the editorial context, because this data is added at the individual QnA pair level.
  • For files, use the FileDTO object. The FileDTO includes the filename as well as the public URL to reach the file.
  • For URLs, use a list of strings to represent publicly available URLs.

The creation step also includes properties for the knowledgebase:

  • defaultAnswerUsedForExtraction - what is returned when no answer is found
  • enableHierarchicalExtraction - automatically create prompt relationships between extracted QnA pairs
  • language - when creating the first knowledgebase of a resource, set the language to use in the Azure Search index.

Call the CreateAsync method then pass the returned operation ID to the MonitorOperation method to poll for status.

The final line of the following code returns the knowledge base ID from the response from MonitorOperation.

private static async Task<string> CreateSampleKb(IQnAMakerClient client)
{
    var qna1 = new QnADTO
    {
        Answer = "Yes, You can use our [REST APIs](https://docs.microsoft.com/rest/api/cognitiveservices/qnamaker/knowledgebase) to manage your knowledge base.",
        Questions = new List<string> { "How do I manage my knowledgebase?" },
        Metadata = new List<MetadataDTO> {
            new MetadataDTO { Name = "Category", Value = "api" },
            new MetadataDTO { Name = "Language", Value = "REST" }
        },

    };

    var qna2 = new QnADTO
    {
        Answer = "Yes, You can use our [.NET SDK](https://www.nuget.org/packages/Microsoft.Azure.CognitiveServices.Knowledge.QnAMaker) with the [.NET Reference Docs](https://docs.microsoft.com/dotnet/api/microsoft.azure.cognitiveservices.knowledge.qnamaker?view=azure-dotnet) to manage your knowledge base.",
        Questions = new List<string> { "Can I program with C#?" },
        Metadata = new List<MetadataDTO> {
            new MetadataDTO { Name = "Category", Value = "api" },
            new MetadataDTO { Name = "Language", Value = ".NET" }
        }
    };

    var file1 = new FileDTO
    {
        FileName = "myfile.tsv",
        FileUri = "https://mydomain/myfile.tsv"

    };

    var createKbDto = new CreateKbDTO
    {
        Name = "QnA Maker .NET SDK Quickstart",
        QnaList = new List<QnADTO> { qna1, qna2 },
        //Files = new List<FileDTO> { file1 }

    };

    var createOp = await client.Knowledgebase.CreateAsync(createKbDto);
    createOp = await MonitorOperation(client, createOp);

    return createOp.ResourceLocation.Replace("/knowledgebases/", string.Empty);
}

Make sure the include the MonitorOperation function, referenced in the above code, in order to successfully create a knowledge base.

Update a knowledge base

You can update a knowledge base by passing in the knowledge base ID and an UpdatekbOperationDTO containing add, update, and delete DTO objects to the UpdateAsync method. Use the MonitorOperation method to determine if the update succeeded.

private static async Task UpdateKB(IQnAMakerClient client, string kbId)
{

    var urls = new List<string> {
        "https://docs.microsoft.com/azure/cognitive-services/QnAMaker/troubleshooting"
    };

    var updateOp = await client.Knowledgebase.UpdateAsync(kbId, new UpdateKbOperationDTO
    {
        // Create JSON of changes
        Add = new UpdateKbOperationDTOAdd
        {
            QnaList = new List<QnADTO> {
                new QnADTO {
                    Questions = new List<string> {
                        "bye",
                        "end",
                        "stop",
                        "quit",
                        "done"
                    },
                    Answer = "goodbye",
                    Metadata = new List<MetadataDTO> {
                        new MetadataDTO { Name = "Category", Value="Chitchat" },
                        new MetadataDTO { Name = "Chitchat", Value = "end" },
                    }
                },
                new QnADTO {
                    Questions = new List<string> {
                        "hello",
                        "hi",
                        "start"
                    },
                    Answer = "Hello, please select from the list of questions or enter a new question to continue.",
                    Metadata = new List<MetadataDTO> {
                        new MetadataDTO { Name = "Category", Value="Chitchat" },
                        new MetadataDTO { Name = "Chitchat", Value = "begin" }
                    },
                    Context = new QnADTOContext
                    {
                        IsContextOnly = false,
                        Prompts = new List<PromptDTO>
                        {
                            new PromptDTO
                            {
                                DisplayOrder =1,
                                DisplayText= "Use REST",
                                QnaId=1

                            },
                            new PromptDTO
                            {
                                DisplayOrder =2,
                                DisplayText= "Use .NET NuGet package",
                                QnaId=2

                            },
                        }
                    }
                },
            },
            Urls = urls
        },
        Update = null,
        Delete = null
    }); ;

    // Loop while operation is success
    updateOp = await MonitorOperation(client, updateOp);
}

Make sure the include the MonitorOperation function, referenced in the above code, in order to successfully update a knowledge base.

Download a knowledge base

Use the DownloadAsync method to download the database as a list of QnADocumentsDTO. This is not equivalent to the QnA Maker portal's export from the Settings page because the result of this method is not a file.

private static async Task DownloadKb(IQnAMakerClient client, string kbId)
{
    var kbData = await client.Knowledgebase.DownloadAsync(kbId, EnvironmentType.Prod);
    Console.WriteLine("KB Downloaded. It has {0} QnAs.", kbData.QnaDocuments.Count);

    // Do something meaningful with data
}

Publish a knowledge base

Publish the knowledge base using the PublishAsync method. This takes the current saved and trained model, referenced by the knowledge base ID, and publishes that at your endpoint. This is a necessary step in order to query your knowledgebase.

private static async Task PublishKb(IQnAMakerClient client, string kbId)
{
    await client.Knowledgebase.PublishAsync(kbId);
}

Get query runtime key

Once a knowledgebase is published, you need the query runtime key to query the runtime. This isn't the same key used to create the original client object.

Use the EndpointKeys method to get the EndpointKeysDTO class.

Use either of the key properties returned in the object to query the knowledgebase.

private static async Task<String> GetQueryEndpointKey(IQnAMakerClient client)
{
    var endpointKeysObject = await client.EndpointKeys.GetKeysAsync();

    return endpointKeysObject.PrimaryEndpointKey;
}

A runtime key is necessary to query your knowledgebase.

Authenticate the runtime for generating an answer

Create a QnAMakerRuntimeClient to query the knowledge base to generate an answer or train from active learning.

var runtimeClient = new QnAMakerRuntimeClient(new EndpointKeyServiceClientCredentials(primaryQueryEndpointKey))
{ RuntimeEndpoint = queryingURL };

Use the QnAMakerRuntimeClient to:

  • get an answer from the knowledgebase
  • to send new suggested questions to the knowledge base for active learning.

Generate an answer from the knowledge base

Generate an answer from a published knowledgebase using the RuntimeClient.GenerateAnswerAsync method. This method accepts the knowledge base ID and the QueryDTO. Access additional properties of the QueryDTO, such a Top and Context to use in your chat bot.

private static async Task GenerateAnswer(IQnAMakerRuntimeClient runtimeClient, string kbId)
{
    var response = await runtimeClient.Runtime.GenerateAnswerAsync(kbId, new QueryDTO { Question = "How do I manage my knowledgebase?" });
    Console.WriteLine("Endpoint Response: {0}.", response.Answers[0].Answer);

    // Do something meaningful with answer
}

Use the QnA Maker client library for Node.js to:

  • Create a knowledgebase
  • Update a knowledgebase
  • Publish a knowledgebase
  • Get prediction runtime endpoint key
  • Wait for long-running task
  • Download a knowledgebase
  • Get answer
  • Delete knowledge base

Reference documentation | Library source code | Package (npm) | Node.js Samples

Note

New resources created after July 1, 2019, will use custom subdomain names. For more information and a complete list of regional endpoints, see Custom subdomain names for Cognitive Services.

Prerequisites

  • Azure subscription - Create one for free
  • The current version of Node.js.
  • Once you have your Azure subscription, create a QnA Maker resource in the Azure portal to get your authoring key and resource. After it deploys, select Go to resource.
    • You will need the key and resource name from the resource you create to connect your application to the QnA Maker API. You'll paste your key and resource name into the code below later in the quickstart.
    • You can use the free pricing tier (F0) to try the service, and upgrade later to a paid tier for production.

Setting up

Create a new Node.js application

In a console window (such as cmd, PowerShell, or Bash), create a new directory for your app, and navigate to it.

mkdir qnamaker_quickstart && cd qnamaker_quickstart

Run the npm init -y command to create a node application with a package.json file.

npm init -y

Install the client library

Install the following NPM packages:

npm install @azure/cognitiveservices-qnamaker
npm install @azure/cognitiveservices-qnamaker-runtime
npm install @azure/ms-rest-js

Your app's package.json file is updated with the dependencies.

Create a file named index.js and import the following libraries:

const msRest = require("@azure/ms-rest-js");
const qnamaker = require("@azure/cognitiveservices-qnamaker");
const qnamaker_runtime = require("@azure/cognitiveservices-qnamaker-runtime");

Create a variable for your resource's Azure key and resource name. Both the authoring and prediction URLs use the resource name as the subdomain.

Important

Go to the Azure portal and find the key and endpoint for the QnA Maker resource you created in the prerequisites. They will be located on the resource's key and endpoint page, under resource management. You need the entire key to create your knowledgebase. You need only the resource name from the endpoint. The format is https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com. Remember to remove the key from your code when you're done, and never post it publicly. For production, consider using a secure way of storing and accessing your credentials. For example, Azure key vault provides secure key storage.

var key_var = 'QNA_MAKER_SUBSCRIPTION_KEY';
if (!process.env[key_var]) {
    throw new Error('please set/export the following environment variable: ' + key_var);
}
var subscription_key = process.env[key_var];

var endpoint_var = 'QNA_MAKER_ENDPOINT';
if (!process.env[endpoint_var]) {
    throw new Error('please set/export the following environment variable: ' + endpoint_var);
}
var endpoint = process.env[endpoint_var];

var runtime_endpoint_var = 'QNA_MAKER_RUNTIME_ENDPOINT';
if (!process.env[runtime_endpoint_var]) {
    throw new Error('please set/export the following environment variable: ' + runtime_endpoint_var);
}
var runtime_endpoint = process.env[runtime_endpoint_var];

Object models

QnA Maker uses two different object models:

  • QnAMakerClient is the object to create, manage, publish, and download the knowledgebase.
  • QnAMakerRuntime is the object to query the knowledge base with the GenerateAnswer API and send new suggested questions using the Train API (as part of active learning).

QnAMakerClient object model

The authoring QnA Maker client is a QnAMakerClient object that authenticates to Azure using your credentials, which contains your key.

Once the client is created, use the knowledgebase to create, manage, and publish your knowledge base.

Manage your knowledge base by sending a JSON object. For immediate operations, a method usually returns a JSON object indicating status. For long-running operations, the response is the operation ID. Call the client.operations.getDetails method with the operation ID to determine the status of the request.

QnAMakerRuntimeClient object model

The prediction QnA Maker client is a QnAMakerRuntimeClient object that authenticates to Azure using Microsoft.Rest.ServiceClientCredentials, which contains your prediction runtime key, returned from the authoring client call, client.EndpointKeys.getKeys after the knowledgebase is published.

Code examples

These code snippets show you how to do the following with the QnA Maker client library for .NET:

Authenticate the client for authoring the knowledge base

Instantiate a client with your endpoint and key. Create an ServiceClientCredentials object with your key, and use it with your endpoint to create an QnAMakerClient object.

const creds = new msRest.ApiKeyCredentials({ inHeader: { 'Ocp-Apim-Subscription-Key': subscription_key } });
const qnaMakerClient = new qnamaker.QnAMakerClient(creds, endpoint);
const knowledgeBaseClient = new qnamaker.Knowledgebase(qnaMakerClient);

Create a knowledge base

A knowledge base stores question and answer pairs for the CreateKbDTO object from three sources:

  • For editorial content, use the QnADTO object.
    • To use metadata and follow-up prompts, use the editorial context, because this data is added at the individual QnA pair level.
  • For files, use the FileDTO object. The FileDTO includes the filename as well as the public URL to reach the file.
  • For URLs, use a list of strings to represent publicly available URLs.

The creation step also includes properties for the knowledgebase:

  • defaultAnswerUsedForExtraction - what is returned when no answer is found
  • enableHierarchicalExtraction - automatically create prompt relationships between extracted QnA pairs
  • language - when creating the first knowledgebase of a resource, set the language to use in the Azure Search index.

Call the create method with the knowledge base information. The knowledge base information is basically a JSON object.

When the create method returns, pass the returned operation ID to the wait_for_operation method to poll for status. The wait_for_operation method returns when the operation completes. Parse the resourceLocation header value of the returned operation to get the new knowledge base ID.

const createKnowledgeBase = async (qnaClient, kbclient) => {

    console.log(`Creating knowledge base...`)

    const qna1 = {
        answer: "Yes, You can use our [REST APIs](https://docs.microsoft.com/rest/api/cognitiveservices/qnamaker/knowledgebase) to manage your knowledge base.",
        questions: ["How do I manage my knowledgebase?"],
        metadata: [
            { name: "Category", value: "api" },
            { name: "Language", value: "REST" }
        ]
    };

    const qna2 = {
        answer: "Yes, You can use our JS SDK on NPM for [authoring](https://www.npmjs.com/package/@azure/cognitiveservices-qnamaker), [query runtime](https://www.npmjs.com/package/@azure/cognitiveservices-qnamaker-runtime), and [the reference docs](https://docs.microsoft.com/en-us/javascript/api/@azure/cognitiveservices-qnamaker/?view=azure-node-latest) to manage your knowledge base.",
        questions: ["How do I manage my knowledgebase?"],
        metadata: [
            { name: "Category", value: "api" },
            { name: "Language", value: "JavaScript" }
        ]
    };

    const create_kb_payload = {
        name: 'QnA Maker JavaScript SDK Quickstart',
        qnaList: [
            qna1,
            qna2
        ],
        urls: [],
        files: [
            /*{
                fileName: "myfile.md",
                fileUri: "https://mydomain/myfile.md"
            }*/
        ],
        defaultAnswerUsedForExtraction: "No answer found.",
        enableHierarchicalExtraction: true,
        language: "English"
    };

    const results = await kbclient.create(create_kb_payload)

    if ( ! results._response.status.toString().startsWith("2")) {
        console.log(`Create request failed - HTTP status ${results._response.status}`)
        return
    }

    const operationResult = await wait_for_operation(qnaClient, results.operationId)

    if (!operationResult || !operationResult.operationState || !(operationResult.operationState = "Succeeded") || !operationResult.resourceLocation) {
        console.log(`Create operation state failed - HTTP status ${operationResult._response.status}`)
        return
    }

    // parse resourceLocation for KB ID
    const kbID = operationResult.resourceLocation.replace("/knowledgebases/", "");

    return kbID;
}

Make sure the include the wait_for_operation function, referenced in the above code, in order to successfully create a knowledge base.

Update a knowledge base

You can update a knowledge base by passing in the knowledge base ID and an UpdateKbOperationDTO containing add, update, and delete DTO objects to the update method. The DTOs are also basically JSON objects. Use the wait_for_operation method to determine if the update succeeded.

const updateKnowledgeBase = async (qnaClient, kbclient, kb_id) => {

    console.log(`Updating knowledge base...`)

    const urls = [
        "https://docs.microsoft.com/azure/cognitive-services/QnAMaker/troubleshooting"
    ]

    const qna3 = {
        answer: "goodbye",
        questions: [
            "bye",
            "end",
            "stop",
            "quit",
            "done"
        ],
        metadata: [
            { name: "Category", value: "Chitchat" },
            { name: "Chitchat", value: "end" }
        ]
    };

    const qna4 = {
        answer: "Hello, please select from the list of questions or enter a new question to continue.",
        questions: [
            "hello",
            "hi",
            "start"
        ],
        metadata: [
            { name: "Category", value: "Chitchat" },
            { name: "Chitchat", value: "begin" }
        ],
        context: {
            isContextOnly: false,
            prompts: [
                {
                    displayOrder: 1,
                    displayText: "Use REST",
                    qna: null,
                    qnaId: 1
                },
                {
                    displayOrder: 2,
                    displayText: "Use JS NPM package",
                    qna: null,
                    qnaId: 2
                },
            ]
        }
    };

    console.log(JSON.stringify(qna4))

    // Add new Q&A lists, URLs, and files to the KB.
    const kb_add_payload = {
        qnaList: [
            qna3,
            qna4
        ],
        urls: urls,
        files: []
    };

    // Bundle the add, update, and delete requests.
    const update_kb_payload = {
        add: kb_add_payload,
        update: null,
        delete: null,
        defaultAnswerUsedForExtraction: "No answer found. Please rephrase your question."
    };

    console.log(JSON.stringify(update_kb_payload))

    const results = await kbclient.update(kb_id, update_kb_payload)

    if ( ! results._response.status.toString().startsWith("2")) {
        console.log(`Update request failed - HTTP status ${results._response.status}`)
        return false
    }

    const operationResult = await wait_for_operation(qnaClient, results.operationId)

    if (operationResult.operationState != "Succeeded") {
        console.log(`Update operation state failed - HTTP status ${operationResult._response.status}`)
        return false
    }

    console.log(`Update operation state ${operationResult._response.status} - HTTP status ${operationResult._response.status}`)
    return true
}

Make sure the include the wait_for_operation function, referenced in the above code, in order to successfully update a knowledge base.

Download a knowledge base

Use the download method to download the database as a list of QnADocumentsDTO. This is not equivalent to the QnA Maker portal's export from the Settings page because the result of this method is not a TSV file.

const downloadKnowledgeBase = async (KBclient, kb_id) => {

    console.log(`Downloading knowledge base...`)

    var kbData = await KBclient.download(kb_id, "Prod");
    console.log(`Knowledge base downloaded. It has ${kbData.qnaDocuments.length} QnAs.`);

    // Do something meaningful with data
}

Publish a knowledge base

Publish the knowledge base using the publish method. This takes the current saved and trained model, referenced by the knowledge base ID, and publishes that at an endpoint. Check the HTTP response code to validate that the publish succeeded.

const publishKnowledgeBase = async (kbclient, kb_id) => {

    console.log(`Publishing knowledge base...`)

    const results = await kbclient.publish(kb_id)

    if ( ! results._response.status.toString().startsWith("2")) {
        console.log(`Publish request failed - HTTP status ${results._response.status}`)
        return false
    }

    console.log(`Publish request succeeded - HTTP status ${results._response.status}`)

    return true
}

Get query runtime key

Once a knowledgebase is published, you need the query runtime key to query the runtime. This isn't the same key used to create the original client object.

Use the EndpointKeys.getKeys method to get the EndpointKeysDTO class.

Use either of the key properties returned in the object to query the knowledgebase.

const getEndpointKeys = async (qnaClient) => {

    console.log(`Getting runtime endpoint keys...`)

    const runtimeKeysClient = await qnaClient.endpointKeys;
    const results = await runtimeKeysClient.getKeys()

    if ( ! results._response.status.toString().startsWith("2")) {
        console.log(`GetEndpointKeys request failed - HTTP status ${results._response.status}`)
        return null
    }

    console.log(`GetEndpointKeys request succeeded - HTTP status ${results._response.status} - primary key ${results.primaryEndpointKey}`)

    return results.primaryEndpointKey
}

Authenticate the runtime for generating an answer

Create a QnAMakerRuntimeClient to query the knowledge base to generate an answer or train from active learning.

const queryRutimeCredentials = new msRest.ApiKeyCredentials({ inHeader: { 'Authorization': 'EndpointKey ' + primaryQueryRuntimeKey } });
const runtimeClient = new qnamaker_runtime.QnAMakerRuntimeClient(queryRutimeCredentials, runtime_endpoint);

Use the QnAMakerRuntimeClient to get an answer from the knowledge or to send new suggested questions to the knowledge base for active learning.

Generate an answer from the knowledge base

Generate an answer from a published knowledge base using the RuntimeClient.runtime.generateAnswer method. This method accepts the knowledge base ID and the QueryDTO. Access additional properties of the QueryDTO, such a Top and Context to use in your chat bot.

const generateAnswer = async (runtimeClient, runtimeKey, kb_id) => {

    console.log(`Querying knowledge base...`)

    const requestQuery = await runtimeClient.runtime.generateAnswer(
        kb_id,
        {
            question: "How do I manage my knowledgebase?",
            top: 1,
            strictFilters: [
                { name: "Category", value: "api" }
            ]
        }
    );
    console.log(JSON.stringify(requestQuery));

}

This is a simple example querying the knowledge base. To understand advanced querying scenarios, review other query examples.

Delete a knowledge base

Delete the knowledge base using the delete method with a parameter of the knowledge base ID.

const deleteKnowledgeBase = async (KBclient, kb_id) => {

    console.log(`Deleting knowledge base...`)

    const results = await KBclient.deleteMethod(kb_id)

    if ( ! results._response.status.toString().startsWith("2")) {
        console.log(`Delete operation state failed - HTTP status ${results._response.status}`)
        return false
    }

    console.log(`Delete operation state succeeded - HTTP status ${results._response.status}`)
    return true
}

Get status of an operation

Some methods, such as create and update, can take enough time that instead of waiting for the process to finish, an operation is returned. Use the operation ID from the operation to poll (with retry logic) to determine the status of the original method.

The delayTimer call in the following code block is used to simulate the retry logic. Replace this with your own retry logic.

const wait_for_operation = async (qnaClient, operation_id) => {

    let state = "NotStarted"
    let operationResult = undefined

    while ("Running" === state || "NotStarted" === state) {

        operationResult = await qnaClient.operations.getDetails(operation_id)
        state = operationResult.operationState;

        console.log(`Operation state - ${state}`)

        await delayTimer(1000);
    }

    return operationResult;
}
const delayTimer = async (timeInMs) => {
    return await new Promise((resolve) => {
        setTimeout(resolve, timeInMs);
    });
}

Run the application

Run the application with node index.js command from your application directory.

node index.js

The source code for this sample can be found on GitHub.

Use the QnA Maker client library for python to:

  • Create a knowledgebase
  • Update a knowledgebase
  • Publish a knowledgebase
  • Get prediction runtime endpoint key
  • Wait for long-running task
  • Download a knowledgebase
  • Get answer
  • Delete knowledge base

Reference documentation | Library source code | Package (PyPi) | Python samples

Note

New resources created after July 1, 2019, will use custom subdomain names. For more information and a complete list of regional endpoints, see Custom subdomain names for Cognitive Services.

Prerequisites

  • Azure subscription - Create one for free
  • Python 3.x
  • Once you have your Azure subscription, create a QnA Maker resource in the Azure portal to get your authoring key and endpoint. After it deploys, select Go to resource.
    • You will need the key and endpoint from the resource you create to connect your application to the QnA Maker API. You'll paste your key and endpoint into the code below later in the quickstart.
    • You can use the free pricing tier (F0) to try the service, and upgrade later to a paid tier for production.

Setting up

Install the client library

After installing Python, you can install the client library with:

pip install azure-cognitiveservices-knowledge-qnamaker

Create a new python application

Create a new Python file named quickstart-file.py and import the following libraries.

import os
import time

from azure.cognitiveservices.knowledge.qnamaker.authoring import QnAMakerClient
from azure.cognitiveservices.knowledge.qnamaker.runtime import QnAMakerRuntimeClient
from azure.cognitiveservices.knowledge.qnamaker.authoring.models import QnADTO, MetadataDTO, CreateKbDTO, OperationStateType, UpdateKbOperationDTO, UpdateKbOperationDTOAdd, EndpointKeysDTO, QnADTOContext, PromptDTO
from azure.cognitiveservices.knowledge.qnamaker.runtime.models import QueryDTO
from msrest.authentication import CognitiveServicesCredentials

Create variables for your resource's Azure endpoint and key.

Important

Go to the Azure portal and find the key and endpoint for the QnA Maker resource you created in the prerequisites. They will be located on the resource's key and endpoint page, under resource management. You need the entire key to create your knowledgebase. You need only the resource name from the endpoint. The format is https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com. Remember to remove the key from your code when you're done, and never post it publicly. For production, consider using a secure way of storing and accessing your credentials. For example, Azure key vault provides secure key storage.

key_var_name = 'QNA_MAKER_SUBSCRIPTION_KEY'
if not key_var_name in os.environ:
    raise Exception('Please set/export the environment variable: {}'.format(key_var_name))
subscription_key = os.environ[key_var_name]

endpoint_var_name = 'QNA_MAKER_ENDPOINT'
if not endpoint_var_name in os.environ:
    raise Exception('Please set/export the environment variable: {}'.format(endpoint_var_name))
endpoint = os.environ[endpoint_var_name]

runtime_endpoint_var_name = 'QNA_MAKER_RUNTIME_ENDPOINT'
if not runtime_endpoint_var_name in os.environ:
    raise Exception('Please set/export the environment variable: {}'.format(runtime_endpoint_var_name))
runtime_endpoint = os.environ[runtime_endpoint_var_name]

Object models

QnA Maker Maker uses two different object models:

  • QnAMakerClient is the object to create, manage, publish, and download the knowledgebase.
  • QnAMakerRuntime is the object to query the knowledge base with the GenerateAnswer API and send new suggested questions using the Train API (as part of active learning).

Using this example knowledge base

The knowledge base in this quickstart starts with 2 conversational QnA pairs, this is done on purpose to simplify the example and to have highly predictable Ids to use in the Update method, associating follow-up prompts with questions to new pairs. This was planned and implemented in a specific order for this quickstart.

If you plan to develop your knowledge base over time with follow-up prompts that are dependent on existing QnA pairs, you may choose:

  • For larger knowledgebases, manage the knowledge base in a text editor or TSV tool that supports automation, then completely replace the knowledge base at once with an update.
  • For smaller knowledgebases, manage the follow-up prompts entirely in the QnA Maker portal.

Details about the QnA pairs used in this quickstart:

  • Types of QnA pair - there are 2 types of QnA pairs in this knowledge base, after the update: chitchat and domain-specific information. This is typical if your knowledgebase is tied to a conversation application such as a chatbot.
  • While the knowledgebase answers could be filtered by metadata or use followup prompts, this quickstart doesn't show that. Look for those language-agnostic generateAnswer examples here.
  • Answer text is markdown and can contain a wide variety of markdown such as images (publicly available internet-based images), links (to publicly available URLs), and bullet points, this quickstart doesn't use that variety.

QnAMakerClient object model

The authoring QnA Maker client is a QnAMakerClient object that authenticates to Azure using Microsoft.Rest.ServiceClientCredentials, which contains your key.

Once the client is created, use the Knowledge base property to create, manage, and publish your knowledge base.

Manage your knowledge base by sending a JSON object. For immediate operations, a method usually returns a JSON object indicating status. For long-running operations, the response is the operation ID. Call the operations.get_details method with the operation ID to determine the status of the request.

QnAMakerRuntimeClient object model

The prediction QnA Maker client is a QnAMakerRuntimeClient object that authenticates to Azure using Microsoft.Rest.ServiceClientCredentials, which contains your prediction runtime key, returned from the authoring client call, client.EndpointKeysOperations.get_keys after the knowledgebase is published.

Use the generate_answer method to get an answer from the query runtime.

Authenticate the client for authoring the knowledge base

Instantiate a client with your endpoint and key. Create an CognitiveServicesCredentials object with your key, and use it with your endpoint to create an QnAMakerClient object.

client = QnAMakerClient(endpoint=endpoint, credentials=CognitiveServicesCredentials(subscription_key))

Create a knowledge base

Use the client object to get a knowledge base operations object.

A knowledge base stores question and answer pairs for the CreateKbDTO object from three sources:

  • For editorial content, use the QnADTO object.
    • To use metadata and follow-up prompts, use the editorial context, because this data is added at the individual QnA pair level.
  • For files, use the FileDTO object. The FileDTO includes the filename as well as the public URL to reach the file.
  • For URLs, use a list of strings to represent publicly available URLs.

Call the create method then pass the returned operation ID to the Operations.getDetails method to poll for status.

The final line of the following code returns the knowledge base ID from the response from MonitorOperation.

def create_kb(client):
    print ("Creating knowledge base...")

    qna1 = QnADTO(
        answer="Yes, You can use our [REST APIs](https://docs.microsoft.com/rest/api/cognitiveservices/qnamaker/knowledgebase) to manage your knowledge base.",
        questions=["How do I manage my knowledgebase?"],
        metadata=[
            MetadataDTO(name="Category", value="api"),
            MetadataDTO(name="Language", value="REST"),
        ]
    )

    qna2 = QnADTO(
        answer="Yes, You can use our [Python SDK](https://pypi.org/project/azure-cognitiveservices-knowledge-qnamaker/) with the [Python Reference Docs](https://docs.microsoft.com/python/api/azure-cognitiveservices-knowledge-qnamaker/azure.cognitiveservices.knowledge.qnamaker?view=azure-python) to manage your knowledge base.",
        questions=["Can I program with Python?"],
        metadata=[
            MetadataDTO(name="Category", value="api"),
            MetadataDTO(name="Language", value="Python"),
        ]
    )

    urls = []
    files=[]

    create_kb_dto = CreateKbDTO(
        name="QnA Maker Python SDK Quickstart",
        qna_list=[
            qna1,
            qna2
        ],
        urls=urls,
        files=[],
        enable_hierarchical_extraction=True,
        default_answer_used_for_extraction="No answer found.",
        language="English"
    )
    create_op = client.knowledgebase.create(create_kb_payload=create_kb_dto)

    create_op_monitor = _monitor_operation(client=client, operation=create_op)

    # Get knowledge base ID from resourceLocation HTTP header
    knowledge_base_ID = create_op_monitor.resource_location.replace("/knowledgebases/", "")
    print("Created KB with ID: {}".format(knowledge_base_ID))

    return knowledge_base_ID

Make sure the include the _monitor_operation function, referenced in the above code, in order to successfully create a knowledge base.

Update a knowledge base

You can update a knowledge base by passing in the knowledge base ID and an UpdateKbOperationDTO containing add, update, and delete DTO objects to the update method. Use the Operation.getDetail method to determine if the update succeeded.

def update_kb(client, kb_id):
    print ("Updating knowledge base...")

    qna3 = QnADTO(
        answer="goodbye",
        questions=[
            "bye",
            "end",
            "stop",
            "quit",
            "done"
            ],
        metadata=[
            MetadataDTO(name="Category", value="Chitchat"),
            MetadataDTO(name="Chitchat", value="end"),
        ]
    )

    qna4 = QnADTO(
        answer="Hello, please select from the list of questions or enter a new question to continue.",
        questions=[
            "hello",
            "hi",
            "start"
        ],
        metadata=[
            MetadataDTO(name="Category", value="Chitchat"),
            MetadataDTO(name="Chitchat", value="begin"),
        ],
        context = QnADTOContext(

            is_context_only = False,
            prompts = [

                PromptDTO(
                    display_order =1,
                    display_text= "Use REST",
                    qna_id=1

                ),
                PromptDTO(
                    display_order =2,
                    display_text= "Use .NET NuGet package",
                    qna_id=2
                ),
            ]
        )

    )

    urls = [
        "https://docs.microsoft.com/azure/cognitive-services/QnAMaker/troubleshooting"
    ]



    update_kb_operation_dto = UpdateKbOperationDTO(
        add=UpdateKbOperationDTOAdd(
            qna_list=[
                qna3,
                qna4
            ],
            urls = urls,
            files=[]
        ),
        delete=None,
        update=None
    )
    update_op = client.knowledgebase.update(kb_id=kb_id, update_kb=update_kb_operation_dto)
    _monitor_operation(client=client, operation=update_op)
    print("Updated knowledge base.")

Make sure the include the _monitor_operation function, referenced in the above code, in order to successfully update a knowledge base.

Download a knowledge base

Use the download method to download the database as a list of QnADocumentsDTO. This is not equivalent to the QnA Maker portal's export from the Settings page because the result of this method is not a TSV file.

def download_kb(client, kb_id):
    print("Downloading knowledge base...")
    kb_data = client.knowledgebase.download(kb_id=kb_id, environment="Prod")
    print("Downloaded knowledge base. It has {} QnAs.".format(len(kb_data.qna_documents)))

Publish a knowledge base

Publish the knowledge base using the publish method. This takes the current saved and trained model, referenced by the knowledge base ID, and publishes that at an endpoint.

def publish_kb(client, kb_id):
    print("Publishing knowledge base...")
    client.knowledgebase.publish(kb_id=kb_id)
    print("Published knowledge base.")

Get query runtime key

Once a knowledgebase is published, you need the query runtime key to query the runtime. This isn't the same key used to create the original client object.

Use the EndpointKeysOperations.get_keys method to get the EndpointKeysDTO class.

Use either of the key properties returned in the object to query the knowledgebase.

def getEndpointKeys_kb(client):
    print("Getting runtime endpoint keys...")
    keys = client.endpoint_keys.get_keys()
    print("Primary runtime endpoint key: {}.".format(keys.primary_endpoint_key))

    return keys.primary_endpoint_key

Authenticate the runtime for generating an answer

Create a QnAMakerRuntimeClient to query the knowledge base to generate an answer or train from active learning.

runtimeClient = QnAMakerRuntimeClient(runtime_endpoint=runtime_endpoint, credentials=CognitiveServicesCredentials(queryRuntimeKey))

Use the QnAMakerRuntimeClient to get an answer from the knowledge or to send new suggested questions to the knowledge base for active learning.

Generate an answer from the knowledge base

Generate an answer from a published knowledge base using the RuntimeClient.runtime.generateAnswer method. This method accepts the knowledge base ID and the QueryDTO. Access additional properties of the QueryDTO, such a Top and Context to use in your chat bot.

def generate_answer(client, kb_id, runtimeKey):
    print ("Querying knowledge base...")

    authHeaderValue = "EndpointKey " + runtimeKey

    listSearchResults = client.runtime.generate_answer(kb_id, QueryDTO(question = "How do I manage my knowledgebase?"), dict(Authorization=authHeaderValue))

    for i in listSearchResults.answers:
        print(f"Answer ID: {i.id}.")
        print(f"Answer: {i.answer}.")
        print(f"Answer score: {i.score}.")

This is a simple example querying the knowledge base. To understand advanced querying scenarios, review other query examples.

Delete a knowledge base

Delete the knowledge base using the delete method with a parameter of the knowledge base ID.

def delete_kb(client, kb_id):
    print("Deleting knowledge base...")
    client.knowledgebase.delete(kb_id=kb_id)
    print("Deleted knowledge base.")

Get status of an operation

Some methods, such as create and update, can take enough time that instead of waiting for the process to finish, an operation is returned. Use the operation ID from the operation to poll (with retry logic) to determine the status of the original method.

The setTimeout call in the following code block is used to simulate asynchronous code. Replace this with retry logic.

def _monitor_operation(client, operation):

    for i in range(20):
        if operation.operation_state in [OperationStateType.not_started, OperationStateType.running]:
            print("Waiting for operation: {} to complete.".format(operation.operation_id))
            time.sleep(5)
            operation = client.operations.get_details(operation_id=operation.operation_id)
        else:
            break
    if operation.operation_state != OperationStateType.succeeded:
        raise Exception("Operation {} failed to complete.".format(operation.operation_id))

    return operation

Run the application

Run the application with the python command on your quickstart file.

python quickstart-file.py

The source code for this sample can be found on GitHub.

Use the QnA Maker client library for Java to:

  • Create a knowledgebase
  • Update a knowledgebase
  • Publish a knowledgebase
  • Get prediction runtime endpoint key
  • Wait for long-running task
  • Download a knowledgebase
  • Get answer
  • Delete knowledge base

Library source code (authoring) | Package | Samples

Note

New resources created after July 1, 2019, will use custom subdomain names. For more information and a complete list of regional endpoints, see Custom subdomain names for Cognitive Services.

Prerequisites

  • Azure subscription - Create one for free
  • JDK
  • Once you have your Azure subscription, create a QnA Maker resource in the Azure portal to get your authoring key and endpoint. After it deploys, select Go to resource.
    • You will need the key and endpoint from the resource you create to connect your application to the QnA Maker API. You'll paste your key and endpoint into the code below later in the quickstart.
    • You can use the free pricing tier (F0) to try the service, and upgrade later to a paid tier for production.

Setting up

Install the client libraries

After installing Java, you can install the client libraries using Maven from MVN Repository.

Create a new Java application

Create a new file named quickstart.java and import the following libraries.

/* Download the following files.
 * - https://repo1.maven.org/maven2/com/microsoft/azure/cognitiveservices/azure-cognitiveservices-qnamaker/1.0.0-beta.1/azure-cognitiveservices-qnamaker-1.0.0-beta.1.jar
 * - https://repo1.maven.org/maven2/com/microsoft/azure/cognitiveservices/azure-cognitiveservices-qnamaker/1.0.0-beta.1/azure-cognitiveservices-qnamaker-1.0.0-beta.1.pom
 * Move the downloaded .jar file to a folder named "lib" directly under the current folder.
 * Rename the downloaded file to pom.xml.
 * At the command line, run
 * mvn dependency:copy-dependencies
 * This will download the .jar files depended on by azure-cognitiveservices-qnamaker-1.0.0-beta.1.jar to the folder "target/dependency" under the current folder. Move these .jar files to the "lib" folder as well.
 */
import com.microsoft.azure.cognitiveservices.knowledge.qnamaker.*;
import com.microsoft.azure.cognitiveservices.knowledge.qnamaker.models.*;

import java.io.*;
import java.lang.Object.*;
import java.time.format.DateTimeFormatter;  
import java.time.LocalDateTime; 
import java.util.*;
import java.net.*;

Create variables for your resource's Azure endpoint and key.

Important

Go to the Azure portal and find the key and endpoint for the QnA Maker resource you created in the prerequisites. They will be located on the resource's key and endpoint page, under resource management. You need the entire key to create your knowledgebase. You need only the resource name from the endpoint. The format is https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com. Remember to remove the key from your code when you're done, and never post it publicly. For production, consider using a secure way of storing and accessing your credentials. For example, Azure key vault provides secure key storage.

/* Configure the local environment:
* Set the following environment variables on your local machine using the
* appropriate method for your preferred shell (Bash, PowerShell, Command
* Prompt, etc.).
*
* QNA_MAKER_SUBSCRIPTION_KEY
* QNA_MAKER_ENDPOINT
* QNA_MAKER_RUNTIME_ENDPOINT
*
* If the environment variable is created after the application is launched in a console or with Visual
* Studio, the shell (or Visual Studio) needs to be closed and reloaded to take the environment variable into account.
*/
private static String authoring_key = System.getenv("QNA_MAKER_SUBSCRIPTION_KEY");
private static String authoring_endpoint = System.getenv("QNA_MAKER_ENDPOINT");
private static String runtime_endpoint = System.getenv("QNA_MAKER_RUNTIME_ENDPOINT");

Object models

QnA Maker uses two different object models:

  • QnAMakerClient is the object to create, manage, publish, and download the knowledgebase.
  • QnAMakerRuntime is the object to query the knowledge base with the GenerateAnswer API and send new suggested questions using the Train API (as part of active learning).

Using this example knowledge base

The knowledge base in this quickstart starts with 2 conversational QnA pairs, this is done on purpose to simplify the example and to have highly predictable Ids to use in the Update method, associating follow-up prompts with questions to new pairs. This was planned and implemented in a specific order for this quickstart.

If you plan to develop your knowledge base over time with follow-up prompts that are dependent on existing QnA pairs, you may choose:

  • For larger knowledgebases, manage the knowledge base in a text editor or TSV tool that supports automation, then completely replace the knowledge base at once with an update.
  • For smaller knowledgebases, manage the follow-up prompts entirely in the QnA Maker portal.

Details about the QnA pairs used in this quickstart:

  • Types of QnA pair - there are 2 types of QnA pairs in this knowledge base, after the update: chitchat and domain-specific information. This is typical if your knowledgebase is tied to a conversation application such as a chatbot.
  • While the knowledgebase answers could be filtered by metadata or use followup prompts, this quickstart doesn't show that. Look for those language-agnostic generateAnswer examples here.
  • Answer text is markdown and can contain a wide variety of markdown such as images (publicly available internet-based images), links (to publicly available URLs), and bullet points, this quickstart doesn't use that variety.

QnAMakerClient object model

The authoring QnA Maker client is a QnAMakerClient object that authenticates to Azure using MsRest::ServiceClientCredentials, which contains your key.

Once the client is created, use the methods of the client's Knowledgebases property to create, manage, and publish your knowledge base.

For immediate operations, a method usually returns the result, if any. For long-running operations, the response is an Operation object. Call the getDetails method with the operation.operationId value to determine the status of the request.

QnAMakerRuntimeClient object model

The runtime QnA Maker client is a QnAMakerRuntimeClient object.

After you publish your knowledge base using the authoring client, use the runtime client's generateAnswer method to get an answer from the knowledge base.

You create a runtime client by calling QnAMakerRuntimeManager.authenticate and passing a runtime endpoint key. To obtain the runtime endpoint key, use the authoring client to call getKeys.

Authenticate the client for authoring the knowledge base

Instantiate a client with your authoring endpoint and subscription key.

/* Note QnAMakerManager.authenticate() does not set the baseUrl paramater value
 * as the value for QnAMakerClient.endpoint, so we still need to call withEndpoint().
 */
QnAMakerClient authoring_client = QnAMakerManager.authenticate(authoring_key).withEndpoint(authoring_endpoint);
Knowledgebases kb_client = authoring_client.knowledgebases();
Operations ops_client = authoring_client.operations();
EndpointKeys keys_client = authoring_client.endpointKeys();

Create a knowledge base

A knowledge base stores question and answer pairs for the CreateKbDTO object from three sources:

  • For editorial content, use the QnADTO object.
    • To use metadata and follow-up prompts, use the editorial context, because this data is added at the individual QnA pair level.
  • For files, use the FileDTO object. The FileDTO includes the filename as well as the public URL to reach the file.
  • For URLs, use a list of strings to represent publicly available URLs.

Call the create method then pass the operationId property of the returned operation to the getDetails method to poll for status.

The final line of the following code returns the knowledge base ID.

public String create_kb () throws Exception {
    System.out.println("Creating KB...");

    String name = "QnA Maker FAQ from quickstart";

    var metadata = new MetadataDTO()
        .withName ("Category")
        .withValue ("api");

    List<MetadataDTO> metadata_list = Arrays.asList(new MetadataDTO[]{ metadata });

    var qna = new QnADTO()
        .withAnswer ("You can use our REST APIs to manage your knowledge base.")
        .withQuestions ( Arrays.asList(new String[]{ "How do I manage my knowledgebase?" }))
        .withMetadata (metadata_list);

    List<QnADTO> qna_list = Arrays.asList(new QnADTO[]{ qna });

    var urls = Arrays.asList(new String[]{ "https://docs.microsoft.com/en-in/azure/cognitive-services/qnamaker/faqs" });

    var payload = new CreateKbDTO().withName(name).withQnaList(qna_list).withUrls(urls);

    var result = kb_client.create(payload);
    var kb_id = wait_for_operation(result);

    System.out.println("Created KB with ID: " + kb_id + ".\n");
    return kb_id;
}

Update a knowledge base

You can update a knowledge base by calling update and passing in the knowledge base ID and an UpdateKbOperationDTO object. That object in turn can contain:

Pass the operationId property of the returned operation to the getDetails method to poll for status.

public void update_kb (String kb_id) throws Exception {
    System.out.println("Updating KB...");

    var update = new UpdateKbOperationDTOUpdate().withName ("New KB name");

    var payload = new UpdateKbOperationDTO().withUpdate((UpdateKbOperationDTOUpdate)update);

    var result = kb_client.update(kb_id, payload);
    wait_for_operation(result);

    System.out.println("Updated KB.");
}

Download a knowledge base

Use the download method to download the database as a list of QnADocumentsDTO. This is not equivalent to the QnA Maker portal's export from the Settings page because the result of this method is not a TSV file.

public void download_kb(String kb_id) {
    System.out.println("Downloading KB...");

    var kb_data = kb_client.download(kb_id, EnvironmentType.PROD);
    System.out.println("KB Downloaded. It has " + kb_data.qnaDocuments().size() + " question/answer sets.");

    System.out.println("Downloaded KB.\n");
}

Publish a knowledge base

Publish the knowledge base using the publish method. This takes the current saved and trained model, referenced by the knowledge base ID, and publishes that at an endpoint.

public void publish_kb(String kb_id) {
    System.out.println("Publishing KB...");
    kb_client.publish(kb_id);
    System.out.println("KB published.\n");
}

Generate an answer from the knowledge base

Once a knowledge base is published, you need the runtime endpoint key to query the knowledge base. This is not the same as the subscription key used to create the authoring client.

Use the getKeys method to get an EndpointKeysDTO object.

Create a runtime client by calling QnAMakerRuntimeManager.authenticate and passing a runtime endpoint key from the EndpointKeysDTO object.

Generate an answer from a published knowledge base using the generateAnswer method. This method accepts the knowledge base ID and a QueryDTO object.

public void query_kb(String kb_id) {
    System.out.println("Sending query to KB...");
    
    var runtime_key = keys_client.getKeys().primaryEndpointKey();
    QnAMakerRuntimeClient runtime_client = QnAMakerRuntimeManager.authenticate(runtime_key).withRuntimeEndpoint(runtime_endpoint);
    var query = (new QueryDTO()).withQuestion("How do I manage my knowledgebase?");
    var result = runtime_client.runtimes().generateAnswer(kb_id, query);
    System.out.println("Answers:");
    for (var answer : result.answers()) {
        System.out.println(answer.answer().toString());
    };
    System.out.println();
}

This is a simple example of querying a knowledge base. To understand advanced querying scenarios, review other query examples.

Delete a knowledge base

Delete the knowledge base using the delete method with a parameter of the knowledge base ID.

public void delete_kb(String kb_id) {
    System.out.println("Deleting KB...");
    kb_client.delete(kb_id);
    System.out.println("KB deleted.\n");
}

Get status of an operation

Some methods, such as create and update, can take enough time that instead of waiting for the process to finish, an operation is returned. Use the operation ID from the operation to poll (with retry logic) to determine the status of the original method.

public String wait_for_operation(Operation op) throws Exception {
    System.out.println ("Waiting for operation to finish...");
    Boolean waiting = true;
    String result = "";
    while (true == waiting) {
        var op_ = ops_client.getDetails(op.operationId());
        var state = op_.operationState();
        if (OperationStateType.FAILED == state) {
            throw new Exception("Operation failed.");
        }
        if (OperationStateType.SUCCEEDED == state) {
            waiting = false;
            // Remove "/knowledgebases/" from the resource location.
            result = op_.resourceLocation().replace("/knowledgebases/", "");
        }
        if (true == waiting) {
            System.out.println("Waiting 10 seconds for operation to complete...");
            Thread.sleep(10000);
        }
    }
    return result;
}

Run the application

Here is the main method for the application.

    public static void main(String[] args) {
        try {
            Quickstart quickstart = new Quickstart();
            String kb_id = quickstart.create_kb();
//			quickstart.list_kbs();
            quickstart.update_kb(kb_id);
            quickstart.publish_kb(kb_id);
            quickstart.download_kb(kb_id);
            quickstart.query_kb(kb_id);
            quickstart.delete_kb(kb_id);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }

Run the application as follows. This presumes your class name is Quickstart and your dependencies are in a subfolder named lib below the current folder.

javac Quickstart.java -cp .;lib\*
java -cp .;lib\* Quickstart

The source code for this sample can be found on GitHub.

Use the QnA Maker client library for Go to:

  • Create a knowledgebase
  • Update a knowledgebase
  • Publish a knowledgebase
  • Get prediction runtime endpoint key
  • Wait for long-running task
  • Download a knowledgebase
  • Get answer
  • Delete knowledge base

Reference (authoring) | Reference (runtime) | Library source code (authoring) | Library source code (runtime) | Samples

Note

New resources created after July 1, 2019, will use custom subdomain names. For more information and a complete list of regional endpoints, see Custom subdomain names for Cognitive Services.

Prerequisites

  • Azure subscription - Create one for free
  • Go
  • Once you have your Azure subscription, create a QnA Maker resource in the Azure portal to get your authoring key and endpoint. After it deploys, select Go to resource.
    • You will need the key and endpoint from the resource you create to connect your application to the QnA Maker API. You'll paste your key and endpoint into the code below later in the quickstart.
    • You can use the free pricing tier (F0) to try the service, and upgrade later to a paid tier for production.

Setting up

Create a new Go application

Create a new file named kb_sample.go and import the following libraries.

import (
    "context"
    "fmt"
    "github.com/Azure/azure-sdk-for-go/services/cognitiveservices/v4.0/qnamaker"
    "github.com/Azure/azure-sdk-for-go/services/cognitiveservices/v4.0/qnamakerruntime"
    "github.com/Azure/go-autorest/autorest"
    "log"
    "os"
    "strings"
    "time"
)

Create variables for your resource's Azure endpoint and key.

Important

Go to the Azure portal and find the key and endpoint for the QnA Maker resource you created in the prerequisites. They will be located on the resource's key and endpoint page, under resource management. You need the entire key to create your knowledgebase. You need only the resource name from the endpoint. The format is https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com. Remember to remove the key from your code when you're done, and never post it publicly. For production, consider using a secure way of storing and accessing your credentials. For example, Azure key vault provides secure key storage.

var subscription_key string = os.Getenv("QNA_MAKER_SUBSCRIPTION_KEY")
var endpoint string = os.Getenv("QNA_MAKER_ENDPOINT")
var runtime_endpoint string = os.Getenv("QNA_MAKER_RUNTIME_ENDPOINT")

Object models

QnA Maker uses two different object models:

  • QnAMakerClient is the object to create, manage, publish, and download the knowledgebase.
  • QnAMakerRuntime is the object to query the knowledge base with the GenerateAnswer API and send new suggested questions using the Train API (as part of active learning).

Using this example knowledge base

The knowledge base in this quickstart starts with 2 conversational QnA pairs, this is done on purpose to simplify the example and to have highly predictable Ids to use in the Update method, associating follow-up prompts with questions to new pairs. This was planned and implemented in a specific order for this quickstart.

If you plan to develop your knowledge base over time with follow-up prompts that are dependent on existing QnA pairs, you may choose:

  • For larger knowledgebases, manage the knowledge base in a text editor or TSV tool that supports automation, then completely replace the knowledge base at once with an update.
  • For smaller knowledgebases, manage the follow-up prompts entirely in the QnA Maker portal.

Details about the QnA pairs used in this quickstart:

  • Types of QnA pair - there are 2 types of QnA pairs in this knowledge base, after the update: chitchat and domain-specific information. This is typical if your knowledgebase is tied to a conversation application such as a chatbot.
  • While the knowledgebase answers could be filtered by metadata or use followup prompts, this quickstart doesn't show that. Look for those language-agnostic generateAnswer examples here.
  • Answer text is markdown and can contain a wide variety of markdown such as images (publicly available internet-based images), links (to publicly available URLs), and bullet points, this quickstart doesn't use that variety.

QnAMakerClient object model

Use the KnowledgebaseClient to create, update, publish, download, and delete your knowledge base. These operations are covered in the following sections.

Use the OperationsClient to check on the status of long-running operations such as creating and updating knowledge bases.

QnAMakerRuntimeClient object model

After you publish your knowledge base, use the RuntimeClient to query your knowledge base. This operation is covered in Query the knowledge base.

Create a knowledge base

A knowledge base stores question and answer pairs for the CreateKbDTO object from three sources:

  • For editorial content, use the QnADTO object.
    • To use metadata and follow-up prompts, use the editorial context, because this data is added at the individual QnA pair level.
  • For files, use the FileDTO object. The FileDTO includes the filename as well as the public URL to reach the file.
  • For URLs, use a list of strings to represent publicly available URLs.

Call the create method then pass the operationId property of the returned operation to the getDetails method to poll for status.

The final line of the following code returns the knowledge base ID.

// Create a knowledge base.
func create_kb () string {
    // Get the context, which is required by the SDK methods.
    ctx := context.Background()

    client := qnamaker.NewKnowledgebaseClient(endpoint)
    // Set the subscription key on the client.
    client.Authorizer = autorest.NewCognitiveServicesAuthorizer(subscription_key)

    name := "QnA Maker FAQ"

    /*
    The fields of QnADTO are pointers, and we cannot get the addresses of literal values,
    so we declare helper variables.
    */
    id := int32(0)
    answer := "You can use our REST APIs to manage your Knowledge Base. See here for details: https://westus.dev.cognitive.microsoft.com/docs/services/58994a073d9e04097c7ba6fe/operations/58994a073d9e041ad42d9baa"
    source := "Custom Editorial"
    questions := []string{ "How do I programmatically update my Knowledge Base?" }

    // The fields of MetadataDTO are also pointers.
    metadata_name_1 := "category"
    metadata_value_1 := "api"
    metadata := []qnamaker.MetadataDTO{ qnamaker.MetadataDTO{ Name: &metadata_name_1, Value: &metadata_value_1 } }
    qna_list := []qnamaker.QnADTO{ qnamaker.QnADTO{
        ID: &id,
        Answer: &answer,
        Source: &source,
        Questions: &questions,
        Metadata: &metadata,
    } }

    urls := []string{}
    files := []qnamaker.FileDTO{}

    // The fields of CreateKbDTO are all pointers, so we get the addresses of our variables.
    createKbPayload := qnamaker.CreateKbDTO{ Name: &name, QnaList: &qna_list, Urls: &urls, Files: &files }

    // Create the KB.
    kb_result, kb_err := client.Create (ctx, createKbPayload)
    if kb_err != nil {
        log.Fatal(kb_err)
    }

    // Wait for the KB create operation to finish.
    fmt.Println ("Waiting for KB create operation to finish...")
    // Operation.OperationID is a pointer, so we need to dereference it.
    return wait_for_operation (*kb_result.OperationID)
}

Update a knowledge base

You can update a knowledge base by calling update and passing in the knowledge base ID and an UpdateKbOperationDTO object. That object in turn can contain:

Pass the operationId property of the returned operation to the getDetails method to poll for status.

// Update a knowledge base.
func update_kb (kb_id string) {
    // Get the context, which is required by the SDK methods.
    ctx := context.Background()

    client := qnamaker.NewKnowledgebaseClient(endpoint)
    // Set the subscription key on the client.
    client.Authorizer = autorest.NewCognitiveServicesAuthorizer(subscription_key)

    // Add new Q&A lists, URLs, and files to the KB.
    /*
    The fields of QnADTO are pointers, and we cannot get the addresses of literal values,
    so we declare helper variables.
    */
    id := int32(1)
    answer := "You can change the default message if you use the QnAMakerDialog. See this for details: https://docs.botframework.com/en-us/azure-bot-service/templates/qnamaker/#navtitle"
    source := "Custom Editorial"
    questions := []string{ "How can I change the default message from QnA Maker?" }

    // The fields of MetadataDTO are also pointers.
    metadata_name_1 := "category"
    metadata_value_1 := "api"
    metadata := []qnamaker.MetadataDTO{ qnamaker.MetadataDTO{ Name: &metadata_name_1, Value: &metadata_value_1 } }
    qna_list := []qnamaker.QnADTO{ qnamaker.QnADTO{
        ID: &id,
        Answer: &answer,
        Source: &source,
        Questions: &questions,
        Metadata: &metadata,
    } }

    urls := []string{}
    files := []qnamaker.FileDTO{}

    /*
    The fields of UpdateKbOperationDTOAdd, updateKBUpdatePayload, updateKBDeletePayload,
    and UpdateKbOperationDTO are all pointers, so we get the addresses of our variables.
    */
    updateKBAddPayload := qnamaker.UpdateKbOperationDTOAdd{ QnaList: &qna_list, Urls: &urls, Files: &files }

    // Update the KB name.
    name := "New KB name"
    updateKBUpdatePayload := qnamaker.UpdateKbOperationDTOUpdate { Name: &name }

    // Delete the QnaList with ID 0.
    ids := []int32{ 0 }
    updateKBDeletePayload := qnamaker.UpdateKbOperationDTODelete { Ids: &ids }

    // Bundle the add, update, and delete requests.
    updateKbPayload := qnamaker.UpdateKbOperationDTO{ Add: &updateKBAddPayload, Update: &updateKBUpdatePayload, Delete: &updateKBDeletePayload }

    // Update the KB.
    kb_result, kb_err := client.Update (ctx, kb_id, updateKbPayload)
    if kb_err != nil {
        log.Fatal(kb_err)
    }

    // Wait for the KB update operation to finish.
    fmt.Println ("Waiting for KB update operation to finish...")
    // Operation.OperationID is a pointer, so we need to dereference it.
    wait_for_operation (*kb_result.OperationID)
}

Download a knowledge base

Use the download method to download the database as a list of QnADocumentsDTO. This is not equivalent to the QnA Maker portal's export from the Settings page because the result of this method is not a TSV file.

// Download a knowledge base.
func download_kb (kb_id string) {
    // Get the context, which is required by the SDK methods.
    ctx := context.Background()

    client := qnamaker.NewKnowledgebaseClient(endpoint)
    // Set the subscription key on the client.
    client.Authorizer = autorest.NewCognitiveServicesAuthorizer(subscription_key)

    result, kb_err := client.Download (ctx, kb_id, "Prod")
    if kb_err != nil {
        log.Fatal(kb_err)
    }
    fmt.Println ("KB " + kb_id + " downloaded. It contains " + string (len(*result.QnaDocuments)) + " question/answer sets.")
}

Publish a knowledge base

Publish the knowledge base using the publish method. This takes the current saved and trained model, referenced by the knowledge base ID, and publishes that at an endpoint.

// Publish a knowledge base.
func publish_kb (kb_id string) {
    // Get the context, which is required by the SDK methods.
    ctx := context.Background()

    client := qnamaker.NewKnowledgebaseClient(endpoint)
    // Set the subscription key on the client.
    client.Authorizer = autorest.NewCognitiveServicesAuthorizer(subscription_key)

    _, kb_err := client.Publish (ctx, kb_id)
    if kb_err != nil {
        log.Fatal(kb_err)
    }
    fmt.Println ("KB " + kb_id + " published.")
}

Query the knowledge base

Once a knowledgebase is published, you need the runtime endpoint key to query the knowledge. This is not the same as the subscription key used to create the authoring client.

Create an EndpointKeysClient and use the getKeys method to get an EndpointKeysDTO object.

// Get runtime endpoint key.
func get_runtime_endpoint_key () string {
    // Get the context, which is required by the SDK methods.
    ctx := context.Background()

    client := qnamaker.NewEndpointKeysClient(endpoint)
    // Set the subscription key on the client.
    client.Authorizer = autorest.NewCognitiveServicesAuthorizer(subscription_key)

    result, err := client.GetKeys (ctx)
    if err != nil {
        log.Fatal(err)
    }

    return *result.PrimaryEndpointKey
}

Create a RuntimeClient and call the GenerateAnswer method to query the knowledge base.

// Send a query to a knowledge base.
func query_kb (kb_id string) {
    // Get the context, which is required by the SDK methods.
    ctx := context.Background()

    client := qnamakerruntime.NewRuntimeClient(runtime_endpoint)

    runtime_key := get_runtime_endpoint_key()
    // Set the runtime key on the client.
    headers := make(map[string]interface{})
    headers["Authorization"] = "EndpointKey " + runtime_key
    client.Authorizer = autorest.NewAPIKeyAuthorizerWithHeaders(headers)

    /*
    The fields of QueryDTO are pointers, and we cannot get the addresses of literal values,
    so we declare helper variables.
    */
    question := "Is the QnA Maker service free?"
    var answers int32
    answers = 3

    query := qnamakerruntime.QueryDTO {
        Question: &question,
        Top: &answers,
    }

    result, kb_err := client.GenerateAnswer (ctx, kb_id, query)
    if kb_err != nil {
        log.Fatal(kb_err)
    }
    fmt.Println ("Top answers:\n")
    for _, answer := range *result.Answers {
        fmt.Printf ("Answer: %s", *answer.Answer)
        fmt.Printf ("Score: %f\n", *answer.Score)
    }
}

This is a simple example of querying a knowledge base. To understand advanced querying scenarios, review other query examples.

Delete a knowledge base

Delete the knowledge base using the delete method with a parameter of the knowledge base ID.

// Delete a knowledge base.
func delete_kb (kb_id string) {
    // Get the context, which is required by the SDK methods.
    ctx := context.Background()

    client := qnamaker.NewKnowledgebaseClient(endpoint)
    // Set the subscription key on the client.
    client.Authorizer = autorest.NewCognitiveServicesAuthorizer(subscription_key)

    _, kb_err := client.Delete (ctx, kb_id)
    if kb_err != nil {
        log.Fatal(kb_err)
    }
    fmt.Println ("KB " + kb_id + " delete.")
}

Get status of an operation

Some methods, such as create and update, can take enough time that instead of waiting for the process to finish, an operation is returned. Use the operation ID from the operation to poll (with retry logic) to determine the status of the original method.

func wait_for_operation (operation_id string) string {
    // Get the context, which is required by the SDK methods.
    ctx := context.Background()

    ops_client := qnamaker.NewOperationsClient(endpoint)
    // Set the subscription key on the client.
    ops_client.Authorizer = autorest.NewCognitiveServicesAuthorizer(subscription_key)

    result := ""
    done := false
    for done == false {
        op_result, op_err := ops_client.GetDetails (ctx, operation_id)
        if op_err != nil {
            log.Fatal(op_err)
        }
        // If the operation isn't finished, wait and query again.
        if op_result.OperationState == "Running" || op_result.OperationState == "NotStarted" {
            fmt.Println ("Operation is not finished. Waiting 10 seconds...")
            time.Sleep (time.Duration(10) * time.Second)
        } else {
            done = true
            fmt.Print ("Operation result: " + op_result.OperationState)
            fmt.Println ()
            if op_result.OperationState == "Failed" {
                handle_error (op_result)
                log.Fatal()
            } else {
                result = strings.ReplaceAll(*op_result.ResourceLocation, "/knowledgebases/", "")
            }
        }
    }
    return result
}

Handle errors

The following code demonstrates how to handle errors that might be returned by the SDK's functions.

// Helper function to handle errors.
func print_inner_error (error qnamaker.InnerErrorModel) {
    if error.Code != nil {
        fmt.Println (*error.Code)
    }
    if error.InnerError != nil {
        print_inner_error (*error.InnerError)
    }
}

// Helper function to handle errors.
func print_error_details (errors []qnamaker.Error) {
    for _, err := range errors {
        if err.Message != nil {
            fmt.Println (*err.Message)
        }
        if err.Details != nil {
            print_error_details (*err.Details)
        }
        if err.InnerError != nil {
            print_inner_error (*err.InnerError)
        }
    }
}

// Helper function to handle errors.
func handle_error (result qnamaker.Operation) {
    if result.ErrorResponse != nil {
        response := *result.ErrorResponse
        if response.Error != nil {
            err := *response.Error
            if err.Message != nil {
                fmt.Println (*err.Message)
            }
            if err.Details != nil {
                print_error_details (*err.Details)
            }
            if err.InnerError != nil {
                print_inner_error (*err.InnerError)
            }
        }
    }
}

Run the application

Here is the main method for the application.

func main() {
    fmt.Println ("Creating KB...")
    kb_id := create_kb()
    fmt.Println ()

    list_kbs()
    fmt.Println ()

    fmt.Println ("Updating KB...")
    update_kb (kb_id)
    fmt.Println ()

    fmt.Println ("Publishing KB...")
    publish_kb (kb_id)
    fmt.Println ()

    fmt.Println ("Downloading KB...")
    download_kb (kb_id)
    fmt.Println ()

    fmt.Println ("Querying KB...")
    query_kb (kb_id)
    fmt.Println()

    fmt.Println ("Deleting KB...")
    delete_kb (kb_id)
    fmt.Println ()
}

Run the application with the go command on your quickstart file.

go run kb_sample.go

The source code for this sample can be found on GitHub

Use the QnA Maker client library for Ruby to:

  • Create a knowledgebase
  • Update a knowledgebase
  • Publish a knowledgebase
  • Get prediction runtime endpoint key
  • Wait for long-running task
  • Download a knowledgebase
  • Get answer
  • Delete knowledge base

Library source code (authoring) | Library source code (runtime) | Package (authoring) | Package (runtime) | Ruby samples

Note

New resources created after July 1, 2019, will use custom subdomain names. For more information and a complete list of regional endpoints, see Custom subdomain names for Cognitive Services.

Prerequisites

  • Azure subscription - Create one for free
  • Ruby 2.x
  • Once you have your Azure subscription, create a QnA Maker resource in the Azure portal to get your authoring key and endpoint. After it deploys, select Go to resource.
    • You will need the key and endpoint from the resource you create to connect your application to the QnA Maker API. You'll paste your key and endpoint into the code below later in the quickstart.
    • You can use the free pricing tier (F0) to try the service, and upgrade later to a paid tier for production.

Setting up

Install the client libraries

After installing Ruby, you can install the client libraries with:

gem install azure_cognitiveservices_qnamaker
gem install azure_cognitiveservices_qnamakerruntime

Create a new Ruby application

Create a new file named quickstart.rb and import the following libraries.

require 'azure_cognitiveservices_qnamaker'
require 'azure_cognitiveservices_qnamakerruntime'
include Azure::CognitiveServices::Qnamaker::V4_0::Models
include Azure::CognitiveServices::QnamakerRuntime::V4_0::Models

Create variables for your resource's Azure endpoint and key.

Important

Go to the Azure portal and find the key and endpoint for the QnA Maker resource you created in the prerequisites. They will be located on the resource's key and endpoint page, under resource management. You need the entire key to create your knowledgebase. You need only the resource name from the endpoint. The format is https://YOUR-RESOURCE-NAME.cognitiveservices.azure.com. Remember to remove the key from your code when you're done, and never post it publicly. For production, consider using a secure way of storing and accessing your credentials. For example, Azure key vault provides secure key storage.

key_var_name = 'QNA_MAKER_SUBSCRIPTION_KEY'
if nil == ENV[key_var_name]
    raise Exception("Please set/export the environment variable: #{key_var_name}\n")
end
subscription_key = ENV[key_var_name]

endpoint_var_name = 'QNA_MAKER_ENDPOINT'
if nil == ENV[endpoint_var_name]
    raise Exception("Please set/export the environment variable: #{endpoint_var_name}\n")
end
endpoint = ENV[endpoint_var_name]

runtime_endpoint_var_name = 'QNA_MAKER_RUNTIME_ENDPOINT'
if nil == ENV[runtime_endpoint_var_name]
    raise Exception("Please set/export the environment variable: #{runtime_endpoint_var_name}\n")
end
runtime_endpoint = ENV[runtime_endpoint_var_name]

Object models

QnA Maker uses two different object models:

  • QnAMakerClient is the object to create, manage, publish, and download the knowledgebase.
  • QnAMakerRuntime is the object to query the knowledge base with the GenerateAnswer API and send new suggested questions using the Train API (as part of active learning).

Using this example knowledge base

The knowledge base in this quickstart starts with 2 conversational QnA pairs, this is done on purpose to simplify the example and to have highly predictable Ids to use in the Update method, associating follow-up prompts with questions to new pairs. This was planned and implemented in a specific order for this quickstart.

If you plan to develop your knowledge base over time with follow-up prompts that are dependent on existing QnA pairs, you may choose:

  • For larger knowledgebases, manage the knowledge base in a text editor or TSV tool that supports automation, then completely replace the knowledge base at once with an update.
  • For smaller knowledgebases, manage the follow-up prompts entirely in the QnA Maker portal.

Details about the QnA pairs used in this quickstart:

  • Types of QnA pair - there are 2 types of QnA pairs in this knowledge base, after the update: chitchat and domain-specific information. This is typical if your knowledgebase is tied to a conversation application such as a chatbot.
  • While the knowledgebase answers could be filtered by metadata or use followup prompts, this quickstart doesn't show that. Look for those language-agnostic generateAnswer examples here.
  • Answer text is markdown and can contain a wide variety of markdown such as images (publicly available internet-based images), links (to publicly available URLs), and bullet points, this quickstart doesn't use that variety.

QnAMakerClient object model

The authoring QnA Maker client is a QnAMakerClient object that authenticates to Azure using MsRest::ServiceClientCredentials, which contains your key.

Once the client is created, use the methods of the client's knowledgebase property to create, manage, and publish your knowledge base.

For immediate operations, a method usually returns the result, if any. For long-running operations, the response is an operation object. Call the operations.get_details method with the operation.operation_id value to determine the status of the request.

QnAMakerRuntimeClient object model

The runtime QnA Maker client is a QnAMakerRuntimeClient object.

After you publish your knowledge base using the authoring client, use the runtime client's runtime.generate_answer method to get an answer from the knowledge base.

When you call generate_answer, pass a hash for the custom_headers optional parameter. This hash should include a key Authorization and a value EndpointKey YOUR_ENDPOINT_KEY. For the value of YOUR_ENDPOINT_KEY, use the authoring client to call endpoint_keys.get_keys.

Authenticate the client for authoring the knowledge base

Instantiate a client with your authoring endpoint and subscription key.

credentials = MsRestAzure::CognitiveServicesCredentials.new(subscription_key)
client = Azure::CognitiveServices::Qnamaker::V4_0::QnamakerClient.new(credentials)
client.endpoint = endpoint

Create a knowledge base

A knowledge base stores question and answer pairs for the CreateKbDTO object from three sources:

  • For editorial content, use the QnADTO object.
    • To use metadata and follow-up prompts, use the editorial context, because this data is added at the individual QnA pair level.
  • For files, use the FileDTO object. The FileDTO includes the filename as well as the public URL to reach the file.
  • For URLs, use a list of strings to represent publicly available URLs.

Call the create method then pass the operation_id property of the returned operation to the operations.get_details method to poll for status.

The final line of the following code returns the knowledge base ID.

def create_kb(client)
    print("Creating knowledge base...\n")

    metadata_1 = MetadataDTO.new()
    metadata_1.name = "Category"
    metadata_1.value = "api"
    metadata_2 = MetadataDTO.new()
    metadata_2.name = "Language"
    metadata_2.value = "REST"
    qna1 = QnADTO.new()
    qna1.answer = "Yes, You can use our [REST APIs](https://docs.microsoft.com/rest/api/cognitiveservices/qnamaker/knowledgebase) to manage your knowledge base."
    qna1.questions = ["How do I manage my knowledgebase?"]
    qna1.metadata = [metadata_1, metadata_2]

    metadata_2 = MetadataDTO.new()
    metadata_2.name = "Language"
    metadata_2.value = "Ruby"
    qna2 = QnADTO.new()
    qna2.answer = "Yes, You can use our [Ruby SDK](https://rubygems.org/gems/azure_cognitiveservices_qnamaker) to manage your knowledge base."
    qna2.questions = ["Can I program with Ruby?"]
    qna2.metadata = [metadata_1, metadata_2]

    create_kb_dto = CreateKbDTO.new()
    create_kb_dto.name = "QnA Maker Ruby SDK Quickstart"
    create_kb_dto.qna_list = [qna1, qna2]

    operation = client.knowledgebase.create(create_kb_payload=create_kb_dto)
    result = _monitor_operation(client, operation)
    knowledge_base_ID = result.resource_location.sub! "/knowledgebases/", ""

    print("Created KB with ID: #{knowledge_base_ID}\n")

    return knowledge_base_ID
end

Update a knowledge base

You can update a knowledge base by calling knowledgebase.update and passing in the knowledge base ID and an UpdateKbOperationDTO object. That object in turn can contain:

Pass the operation_id property of the returned operation to the operations.get_details method to poll for status.

def update_kb(client, kb_id)
    print("Updating knowledge base...\n")

    metadata_1 = MetadataDTO.new()
    metadata_1.name = "Category"
    metadata_1.value = "Chitchat"
    metadata_2 = MetadataDTO.new()
    metadata_2.name = "Chitchat"
    metadata_2.value = "end"
    qna3 = QnADTO.new()
    qna3.answer = "goodbye"
    qna3.questions = ["bye", "end", "stop", "quit", "done"]
    qna3.metadata=[metadata_1, metadata_2]

    metadata_2 = MetadataDTO.new()
    metadata_2.name = "Chitchat"
    metadata_2.value = "begin"
    prompt_1 = PromptDTO.new()
    prompt_1.display_order = 1
    prompt_1.display_text = "Use REST"
    prompt_1.qna_id = 1
    prompt_2 = PromptDTO.new()
    prompt_2.display_order = 2
    prompt_2.display_text = "Use .NET NuGet package"
    prompt_2.qna_id = 2
    context = QnADTOContext.new()
    context.is_context_only = false
    context.prompts = [prompt_1, prompt_2]
    qna4 = QnADTO.new()
    qna4.answer = "Hello, please select from the list of questions or enter a new question to continue."
    qna4.questions = ["hello", "hi", "start"]
    qna4.metadata=[metadata_1, metadata_2]
    qna4.context = context

    add = UpdateKbOperationDTOAdd.new()
    add.qna_list = [qna3, qna4]
    add.urls = ["https://docs.microsoft.com/azure/cognitive-services/QnAMaker/troubleshooting"]
    update_kb_operation_dto = UpdateKbOperationDTO.new()
    update_kb_operation_dto.add = add

    operation = client.knowledgebase.update(kb_id, update_kb_operation_dto)
    _monitor_operation(client, operation)
    print("Updated knowledge base.\n")
end

Download a knowledge base

Use the knowledgebase.download method to download the database as a list of QnADocumentsDTO. This is not equivalent to the QnA Maker portal's export from the Settings page because the result of this method is not a TSV file.

def download_kb(client, kb_id)
    print("Downloading knowledge base...\n")
    kb_data = client.knowledgebase.download(kb_id, "Prod")
    print("Downloaded knowledge base. It has #{kb_data.qna_documents.length()} QnAs.\n")
end

Publish a knowledge base

Publish the knowledge base using the knowledgebase.publish method. This takes the current saved and trained model, referenced by the knowledge base ID, and publishes that at an endpoint.

def publish_kb(client, kb_id)
    print("Publishing knowledge base...\n")
    client.knowledgebase.publish(kb_id)
    print("Published knowledge base.\n")
end

Get query runtime key

Once a knowledgebase is published, you need the runtime endpoint key to query the knowledge. This is not the same as the subscription key used to create the authoring client.

Use the endpoint_keys.get_keys method to get an EndpointKeysDTO object.

Use either of the key properties returned in the object to query the knowledgebase.

def getEndpointKeys_kb(client)
    print("Getting runtime endpoint keys...\n")
    keys = client.endpoint_keys.get_keys()
    print("Primary runtime endpoint key: #{keys.primary_endpoint_key}.\n")

    return keys.primary_endpoint_key
end

Authenticate the runtime for generating an answer

Create a QnAMakerRuntimeClient to query the knowledge base to generate an answer or train from active learning.

credentials = MsRestAzure::CognitiveServicesCredentials.new(subscription_key)
runtime_client = Azure::CognitiveServices::QnamakerRuntime::V4_0::QnamakerRuntimeClient.new(credentials)
runtime_client.runtime_endpoint = runtime_endpoint

Use the QnAMakerRuntimeClient to get an answer from the knowledge or to send new suggested questions to the knowledge base for active learning.

Generate an answer from the knowledge base

Generate an answer from a published knowledge base using the RuntimeClient.runtime.generateAnswer method. This method accepts the knowledge base ID and the QueryDTO. Access additional properties of the QueryDTO, such a Top and Context to use in your chat bot.

def generate_answer(client, kb_id, endpoint_key)
    print("Querying knowledge base...\n")

    query = QueryDTO.new()
    query.question = "How do I manage my knowledgebase?"
    headers = Hash.new
    headers["Authorization"] = "EndpointKey #{endpoint_key}"
    listSearchResults = client.runtime.generate_answer(kb_id, query, custom_headers:headers)

    for i in listSearchResults.answers
        print("Answer ID: #{i.id}.\n")
        print("Answer: #{i.answer}.\n")
        print("Answer score: #{i.score}.\n")
    end
end

This is a simple example of querying a knowledge base. To understand advanced querying scenarios, review other query examples.

Delete a knowledge base

Delete the knowledge base using the knowledgebase.delete method with a parameter of the knowledge base ID.

def delete_kb(client, kb_id)
    print("Deleting knowledge base...\n")
    client.knowledgebase.delete(kb_id)
    print("Deleted knowledge base.\n")
end

Get status of an operation

Some methods, such as create and update, can take enough time that instead of waiting for the process to finish, an operation is returned. Use the operation ID from the operation to poll (with retry logic) to determine the status of the original method.

def _monitor_operation(client, operation)

    for i in 1..20
        if ["NotStarted", "Running"].include?(operation.operation_state)
            print("Waiting for operation: #{operation.operation_id} to complete.\n")
            sleep(10)
            operation = client.operations.get_details(operation.operation_id)
        else
            break
        end
    end
    if operation.operation_state != "Succeeded"
        raise Exception("Operation #{operation.operation_id} failed to complete.")
    end

    return operation
end

Run the application

Here is the main method for the application.


credentials = MsRestAzure::CognitiveServicesCredentials.new(subscription_key)
client = Azure::CognitiveServices::Qnamaker::V4_0::QnamakerClient.new(credentials)
client.endpoint = endpoint

kb_id = create_kb(client)
update_kb(client, kb_id)
publish_kb(client, kb_id)
download_kb(client, kb_id)

runtime_endpoint_key = getEndpointKeys_kb(client)

credentials = MsRestAzure::CognitiveServicesCredentials.new(subscription_key)
runtime_client = Azure::CognitiveServices::QnamakerRuntime::V4_0::QnamakerRuntimeClient.new(credentials)
runtime_client.runtime_endpoint = runtime_endpoint

generate_answer(runtime_client, kb_id, runtime_endpoint_key)

delete_kb(client, kb_id)

Run the application with the ruby command on your quickstart file.

ruby quickstart.rb

The source code for this sample can be found on GitHub.

Clean up resources

If you want to clean up and remove a Cognitive Services subscription, you can delete the resource or resource group. Deleting the resource group also deletes any other resources associated with it.

Next steps