Search code examples
pythonandroid-intentchatbottraining-datafunction-call

How to execute a function on a response intent to a specific question?


I am training a chatbot on my data. I have a function that goes through my data and returns either 4 random items where their category is = "Beverages" or "Entrees" depending on what parameter I pass to it. I want this function to execute each time the user asks "what are the main dishes" or "what beverages do you have".

The problem I'm facing is that each time the user asks "what are the main dishes" it only executes the function 1 time and uses the same output each time the user asks that question instead of retrieving another random 4 items. Same problem for "what beverages do you have".

Here are my intents:

 bevarages_category_intent = {
        "tag": "bevarages category",
        "patterns": [
            "what drinks are available",
            "what drinks do you have",
            "i'm thirsty"
        ],
        "responses": [
            "Here are some suggestions: " + ', '.join(get_products_by_category("Beverages"))
        ]
    }

    entrees_category_intent = {
        "tag": "entrees category",
        "patterns": [
            "what are the main dishes",
            "what are some main dishes you recommend",
            "what kind of entrees do you have",
            "i'm hungry"
        ],
        "responses": [
            "Here are some suggestions: " + ', '.join(get_products_by_category("Entrees"))
        ]
    }

and here is my function:

def get_products_by_category(category):
    products = []
    
    # Define the CSV file path
    csv_file = "products.csv"
    
    # Read the CSV file
    with open(csv_file, 'r', newline='') as file:
        reader = csv.reader(file)
        header = next(reader)  # Skip the header row
        
        # Find the index of the "Category" column
        category_index = header.index("Category")
        
        # Iterate over the rows and check for the desired category
        for row in reader:
            if row[category_index] == category:
                products.append(row[0])
        
         # Randomly select 4 rows
        random_products = random.sample(products, 4)
    
    return random_products

I tried to use the {type=function_call ...} and I also tried the lambda:.... But none of them worked.


Solution

  • First, to avoid reading the file each time you want suggestions, store the data in a dictionnary where the key is a category and the value a list of items

    def get_products_by_category():
        products = defaultdict(list)
        csv_file = "products.csv"
        with open(csv_file, 'r', newline='') as file:
            reader = csv.reader(file)
            header = next(reader)
            category_index = header.index("Category")
            for row in reader:
                products[row[category_index]].append(row[0])
        return products
    

    Then use a helper method to build a string from a sample of values

    def get_sample(items):
        return ', '.join(random.sample(items, 4))
    

    Then what you need is lambdas, that will allow you code to execute when you need it, and so re-execute each time you need it, leading to different values

    products_by_category = get_products_by_category()
    
    categories = [
        {
            "tag": "bevarages category",
            "patterns": ["what drinks are available", "what drinks do you have", "i'm thirsty"],
            "responses": [lambda: "Here are some suggestions: " + get_sample(products_by_category["Beverages"])]
        },
        {
            "tag": "entrees category",
            "patterns": ["what are the main dishes", "what are some main dishes you recommend",
                         "what kind of entrees do you have", "i'm hungry"],
            "responses": [lambda: "Here are some suggestions: " + get_sample(products_by_category["Entrees"])]
        }
    ]
    
    choice = ""
    while choice != "exit":
        choice = input("What do you want ?")
        stop = False
        for category in categories:
            for pattern in category["patterns"]:
                if pattern == choice:
                    response = random.choice(category['responses'])
                    print(response()) # call response() since it's a lambda
                    break