Search code examples
botframeworkazure-qna-maker

How do I update an answer from the bot prior to it being sent to the user?


I'm working on a bot that uses the QnA Maker service using the Node.js version of the framework.

I'd like to enhance the answers provided by the bot by including dynamic content. I want to be able to replace [shortcode-thing] when present in an answer with dynamically generated content. I have code in place that achieves the identification and replacement of the shortcode. Where I'm lost is adding it into the flow of the conversation.

I'm using the QnAMakerDialog class as the core of the interaction between the bot and the QnA Maker service. So that in time I can provide a multiturn experience.

Is this possible using Middleware? If so, how do I identify the answer and update the content of the answer so that the updated answer is sent to the user?

Alternatively, is there a way to extend the QnAMakerDialog to intercept the action of sending the answer?


Solution

  • I've found a way of achieving my desired result.

    First, I've implemented a class to act as my middleware. For example:

    class filterAnswer {
        /*
         * Called each time the bot receives a new request.
         */
        async onTurn( context, next ) {
      
          /*
           * Called each time a set of activities is sent.
           */
          context.onSendActivities( async function( _context, activities, next ) {
      
            // Loop through all of the activities in the stack.
            activities.forEach( activity => {
      
              // Only examine messages, ignore other types.
              if ( activity.type === "message" ) {
      
                // Ignore a message if it doesn't have any text.
                if ( activity.text !== undefined ) {
                  
                  let fixedText = activity.text;  
                  
                  // Do stuff to the text.
    
                  // Assigm the text back to the activity.
                  activity.text = fixedText;
      
                }
              }
            } );
      
            // Continuing processing activities by other middleware.
            await next();
      
          } );
      
          // Continue processing the request.
          await next();
        }
      
      }
    }
    

    Then I can add the my custom middleware to the list of middleware like this:

    const adapter = new BotFrameworkAdapter( {
      // bot configuration values
    } ); 
    
    // Add custom middleware
    adapter.use( new filterAnswer() );
    

    This is based on looking at examples like the Transcript Logger and the Spell Check Middleware. As well as the Middleware interface and SendActivitiesHandler documentation.

    As mentioned by others in the comments I could implement this in my QnAMakerDialog. I'm following the QnA Maker Sample which I think abstracts me away a bit to far from the underlying QnA Maker interaction. Especially I want to leverage all of the cool things the SDK classes do like provide a multiturn experience.