Step 9: Optimize Question Answering Performance

The MindMeld question answerer is a powerful component which streamlines the development of applications that need to answer questions in addition to understanding user requests. The question answerer relies on a knowledge base which encompasses all of the important world knowledge for a given application use case. For example, the question answerer might rely on a knowledge base which knows details about every product in a product catalog. Alternately, the question answerer might have a knowledge base containing detailed information about every song or album in a music library.

To leverage the MindMeld question answerer in your application, you must first create your knowledge base, as described in Step 5. With the knowledge base created, your dialogue state handlers can invoke the question answerer, as illustrated in Step 4, to find answers, validate questions, and suggest alternatives. For example, a simple dialogue handler which finds nearby Kwik-E-Mart store locations might resemble the snippet below. Notice that the application imports the QuestionAnswerer component.

from mindmeld import Application

app = Application(__name__)

@app.handle(intent='find_nearest_store')
def send_nearest_store(request, responder):
    try:
        user_location = request.context['location']
    except KeyError:
        responder.reply("I'm not sure. You haven't told me where you are!")
        responder.suggest([{'type': 'location', 'text': 'Share your location'}])
        return

    stores = app.question_answerer.get(index='stores', _sort='location', _sort_type='distance',
                                       _sort_location=user_location)
    target_store = stores[0]
    responder.slots['store_name'] = target_store['store_name']

    responder.frame['target_store'] = target_store
    responder.reply('Your nearest Kwik-E-Mart is located at {store_name}.')

Assuming you have already created an index, such as stores, and uploaded the knowledge base data, the get() method provides a flexible mechanism for retrieving relevant results.

cd $MM_APP_ROOT
python
from mindmeld.components import QuestionAnswerer
qa = QuestionAnswerer('.')
stores = qa.get(index='stores')
stores[0]
{
  "store_name": "23 Elm Street",
  "open_time": "7am",
  "close_time": "9pm",
  "address": "100 Central Plaza, Suite 800, Elm Street, Capital City, CA 10001",
  "phone_number": "(+1) 415-555-1100"
}

Similarly, to retrieve store locations on Market Street, you could use something like:

stores = qa.get('market', index='stores')
stores[0]
{
  "store_name": "Pine and Market",
  "open_time": "6am",
  "close_time": "10pm",
  "address": "750 Market Street, Capital City, CA 94001",
  "phone_number": "(+1) 650-555-4500"
}

By default, the get() method uses a baseline ranking algorithm which displays the most relevant documents based on text similarity.

Proximity-Based Ranking

Location-based ranking is fairly common in mobile applications. We have already seen an intent designed to provide the nearest retail locations for a given user in our Kwik-E-Mart example. Going further, to support proximity-based ranking, is straightforward to accomplish using the MindMeld question answerer.

First, let's assume that you have created a knowledge base for the stores index, which contains every retail location. Each store object also has a location field which contains latitude and longitude coordinates for each store.

{
  "store_name": "23 Elm Street",
  "open_time": "7am",
  "close_time": "9pm",
  "address": "100 Central Plaza, Suite 800, Elm Street, Capital City, CA 10001",
  "phone_number": "(+1) 415-555-1100",
  "location": {"latitude": 37.790683, "longitude": -122.403889}
},
{
  "store_name": "Pine and Market",
  "open_time": "6am",
  "close_time": "10pm",
  "address": "750 Market Street, Capital City, CA 94001",
  "phone_number": "(+1) 650-555-4500",
  "location": {"latitude": 37.790426, "longitude": -122.405752}
}
...

We can now retrieve the nearest stores using the sort argument of the get() method as follows:

my_loc = {"latitude": 37.790415, "longitude": -122.405218}
stores = qa.get(index='stores', location=my_loc, sort='location')
stores[0]
{
  "store_name": "Pine and Market",
  "open_time": "6am",
  "close_time": "10pm",
  "address": "750 Market Street, Capital City, CA 94001",
  "phone_number": "(+1) 650-555-4500",
  "location": {"latitude": 37.790426, "longitude": -122.405752}
}

See the User Guide for more about how to use the Question Answerer to find answers to questions, validate user requests, disambiguate entities, and offer alternative suggestions.