Search code examples
pythonsqlitechatbotrasa-nlu

How to find similarity between entity in input to that of database


I am trying to create a chatbot with rasa nlu that will help with hotel search. I created a small sqlite database containing the names and other description of a few restaurants. This is the structure of my database

Name            Cuisine    Price   ambience location    rating
Flower Drum     chinese    high    2        south       5
Little Italy    italian    high    2        south       2
Quattro         mexican    low     2        center      3
Domino's Pizza  fast food  mid     0        east        3

I trained the interpreter on some custom intents like this.

## intent:hotel_search
- I'm looking for a [Mexican](cuisine) restaurant in the [North](location) of town
- Which is the [best](rating) restaurant in the city
- Which restaurant has the most [rating](rating) in the city
- I am looking for a [burger](dish) joint in the [south](location) of the city
- I am trying to find an [expensive](price) [Indian](cuisine) restaurant in the [east](location) of the city

This is the code for training the interpreter

def train(data, config_file, model_dir):
    training_data = load_data(data)
    trainer = Trainer(config.load(config_file))
    trainer.train(training_data)
    model_directory = trainer.persist(model_dir, fixed_model_name = 'chat')

This is the code for finding hotels from the sqlite database

def find_hotels(params):
    # Create the base query
    query = 'SELECT * FROM hotels'
    # Add filter clauses for each of the parameters
    if len(params) > 0:
        filters = ["{}=?".format(k) for k in params]
        query += " WHERE " + " and ".join(filters)
    # Create the tuple of values
    t = tuple(params.values())

    # Open connection to DB
    conn = sqlite3.connect('hotels.sqlite')
    # Create a cursor
    c = conn.cursor()
    # Execute the query
    c.execute(query, t)
    # Return the results
    return c.fetchall()

This is the code for responding to the input message

# Define respond()
def respond(message):
    # responses
    responses = ["I'm sorry :( I couldn't find anything like that",
                 '{} is a great hotel!',
                 '{} or {} would work!',
                 '{} is one option, but I know others too :)']

    # Extract the entities
    entities = interpreter.parse(message)["entities"]
    # Initialize an empty params dictionary
    params = {}
    # Fill the dictionary with entities
    for ent in entities:
        params[ent["entity"]] = str(ent["value"])

    print("\n\nparams: {}\n\n".format(params))
    # Find hotels that match the dictionary
    results = find_hotels(params)
    print("\n\nresults: {}\n\n".format(results))
    # Get the names of the hotels and index of the response
    names = [r[0] for r in results]
    n = min(len(results),3)
    # Select the nth element of the responses array
    return responses[n].format(*names)

But when I test the interpreter with this example

I am looking for an expensive Chinese restaurant in the south of the city

This is the result I get

params: {'price': 'expensive', 'cuisine': 'chinese', 'location': 'south'}

results: []

I'm sorry :( I couldn't find anything like that

If I were to remove the expensive word from the input question I get a proper result such as this

I am looking for a Chinese restaurant in the south of the city

params: {'cuisine': 'chinese', 'location': 'south'}

results: [('Flower Drum', 'chinese', 'high', 2, 'south', 5)]

Flower Drum is a great hotel!

The bot is able to recognize all the entities but, it is not able to select the right data from the database as there is no data entry by the name expensive in the price colomn in the database. How do I train the bot to recognize the word expensive as high


Solution

  • You can add synonyms in your nlu.md. Add this to your file and 'expensive' gets mapped to high:

    ## synonym:high
    - expensive