Example #1
0
def get_date_range_aggregate(request, responder):
    """
    When a user asks for a statistic, such as average, sum, count or percentage,
    in addition to a date range filter such as date of hire, termination or birth (required),
    and categorical filters (if any), this function captures all the relevant entities,
    calculates the desired statistic function and returns it.

    'function' entities represent the statistic functions - sum, average, percentage, count
    """

    # Checks for existing function entity from previous turn
    func_entity = request.frame.get('function')

    # If the user provides a new function entity, it replaces the one in context from previous turns
    func_entities = extract_entities_from_type(request, 'function')

    if func_entities:
        func_entity = func_entities[0]

    if func_entity:
        # Resolve the recognized function entity to its canonical form, one that can be used in
        # the output dialog as well as in the '_agg_function', which is used to calculate the values
        # of these desired function entities
        function, responder = _resolve_function_entity(responder, func_entity)

        # If there are any categorical entities (eg. race, gender, position etc.) in the query that
        # need filtering on, '_resolve_categorical_entities' fetches these entities, resolves them
        # to their canonical form and filters the knowledge base on all the conditions requested by
        # the user query
        qa, size = _resolve_categorical_entities(request, responder)

        # Resolve the duration that is explicitly or implicitly mentioned in the query
        # and then filtering the KB to retain all employees satisfying that duration criteria
        out = _resolve_time(request, responder, qa, size)

        if out:
            qa, size, field = out
        qa_out = qa.execute(size=size)

        # Calculate and return desired mathemical value
        responder.slots['value'] = _agg_function(qa_out, func=function)

        if function == 'pct':
            responder.reply("Of the total employees, the {function} "
                            "that meet your criteria is {value}")
        else:
            responder.reply("The {function} of employees is {value}")

    else:
        responder.reply('What time-filtered statistic would you like to know?')
        responder.listen()
Example #2
0
def get_date_range_employees(request, responder):
    """
	When a user asks for a list of employees that satisfy certain criteria in addition
	to satisfying a specified date range criterion (date of hire/termination/birth), 
	this dialogue state filters the knowledge base on those criteria and returns the 
	shortlisted list of names.
	"""

    # If there are any categorical entities (eg. race, gender, department etc.) in the query that
    # need filtering on, '_resolve_categorical_entities' fetches these entities, resolves them to
    # their canonical form and filters the database on all the conditions requested by the user query
    qa, size = _resolve_categorical_entities(request, responder)

    # Resolve the duration that is explicitly or implicitly mentioned in the query
    # and then filtering the KB to retain all employees satisfying that duration criteria
    out = _resolve_time(request, responder, qa, size)

    if out:
        qa, size, field = out

        # Finding extreme entities such as 'highest', 'lowest', 'youngest' etc. (if any)
        extreme_entity = [
            e for e in request.entities if e['type'] == 'extreme'
        ]

        # Filter on the extreme entities if they exist
        if extreme_entity:
            extreme_entity = extreme_entity[0]
            qa, size = _resolve_extremes(request, responder, qa,
                                         extreme_entity, field)

        qa_out = qa.execute(size=size)

        if qa_out:
            responder.slots['emp_list'] = _get_names(qa_out)

            # Give the natural language response according to the size of the list to be displayed
            if len(qa_out) == 1:
                responder.reply(
                    "Here is the employee you are looking for: {emp_list}")
            else:
                responder.reply(
                    "Here are some employees that match your criteria: {emp_list}"
                )

    else:
        responder.listen()
def get_salary_employees(request, responder):
    """
	When a user asks for a list of employees that satisfy certain criteria in addition
	to satisfying a specified monetary criterion, this dialogue state filters the
	knowledge base on those criteria and returns the shortlisted list of names.
	"""

    money_entities = [e for e in request.entities if e['type'] == 'money']

    categorical_entities = [
        e for e in request.entities
        if e['type'] in ('state', 'sex', 'maritaldesc', 'citizendesc',
                         'racedesc', 'performance_score', 'employment_status',
                         'employee_source', 'position', 'department')
    ]

    # Resolve the recognized function entity to its canonical form, one that can be used in
    # the output dialog as well as in the '_agg_function', which is used to calculate the values
    # of these desired function entities
    qa, size = _resolve_categorical_entities(request, responder)

    # Filter the knowledge base on ant time related entities that occur in the query
    qa = _resolve_time_in_salary(request, responder, qa)

    if money_entities:
        qa, size = _apply_money_filter(qa, request, responder)

    qa_out = qa.execute(size=size)
    responder.slots['emp_list'] = _get_names(qa_out)

    if qa_out:
        if size == 1:
            responder.reply(
                "Here is the employee you are looking for with their hourly pay: {emp_list}"
            )
        else:
            responder.reply(
                "Here are some employees with their hourly pay: {emp_list}")
    else:
        responder.reply("No such employees found")
Example #4
0
def get_salary_employees(request, responder):
    """
    When a user asks for a list of employees that satisfy certain criteria in addition
    to satisfying a specified monetary criterion, this dialogue state filters the
    knowledge base on those criteria and returns the shortlisted list of names.
    """

    money_entities = extract_entities_from_type(request, 'money')

    # Resolve the recognized function entity to its canonical form, one that can be used in
    # the output dialog as well as in the '_agg_function', which is used to calculate the values
    # of these desired function entities
    qa, size = _resolve_categorical_entities(request, responder)

    # Filter the knowledge base on ant time related entities that occur in the query
    qa = _resolve_time_in_salary(request, responder, qa)

    if money_entities:
        out = _apply_money_filter(qa, request, responder)
        if not out:
            return

        qa, size = out

    qa_out = qa.execute(size=size)
    responder.slots['emp_list'] = _get_names_with_money(qa_out)

    if qa_out:
        if size == 1:
            reply = "Here is the employee you are looking for with their hourly pay: {emp_list}"
            responder.reply(reply)
        else:
            responder.reply(
                "Here are some employees with their hourly pay: {emp_list}")
    else:
        responder.reply("No such employees found")
def get_salary_aggregate(request, responder):
    """
	When a user asks for a statistic, such as average, sum, count or percentage,
	in addition to an income related filter (required) and categorical filters (if any),
	this function captures all the relevant entities, calculates the desired
	statistic function and returns it.

	'function' entities represent the statistic functions - sum, average, percentage, count
	"""

    # Checks for existing function entity from previous turn
    func_entity = request.frame.get('function')

    # If the user provides a new function entity, it replaces the one in context from previous turns
    func_entities = [e for e in request.entities if e['type'] == 'function']
    money_entities = [e for e in request.entities if e['type'] == 'money']
    recur_ent = [
        e['value'][0]['cname'] for e in request.entities
        if e['type'] == 'time_recur'
    ]
    extreme_entity = [e for e in request.entities if e['type'] == 'extreme']

    # If there are any categorical entities (eg. race, gender, department etc.) in the query that
    # need filtering on, '_resolve_categorical_entities' fetches these entities, resolves them to
    # their canonical form and filters the database on all the conditions requested by the user query
    qa, size = _resolve_categorical_entities(request, responder)

    # Filter the knowledge base on ant time related entities that occur in the query
    qa = _resolve_time_in_salary(request, responder, qa)

    # default reply
    salary_response = "Hmm, looks like you want a salary statistic. You can ask me about averages, sums, counts and percentages. For eg. what is the average salary for women?"

    if func_entities:
        func_entity = func_entities[0]

    if func_entity:
        # Resolve the recognized function entity to its canonical form, one that can be used in
        # the output dialog as well as in the '_agg_function', which is used to calculate the values
        # of these desired function entities
        function, responder = _resolve_function_entity(responder, func_entity)

        if money_entities:
            out = _apply_money_filter(qa, request, responder)
            if out:
                qa, size = out
            else:
                return

            qa_out = qa.execute(size=size)

            # If there is a multiplicative factor or recurring duration over which the amount is to
            # be returned, convert default (hourly) to that duration. For eg. 'what the average monthly salary'
            if recur_ent and function in ('avg', 'sum'):
                responder = _calculate_agg_salary(responder, qa_out, function,
                                                  recur_ent[0])
                if np.isnan(responder.slots['value']):
                    responder.reply(salary_response)
                    responder.listen()
                    return
                responder.reply(
                    "the {function} {interval} salary, based on your criteria, is ${value}"
                )

            # Else calculate aggregate value on default duration (i.e. hourly)
            else:
                responder = _calculate_agg_salary(responder, qa_out, function)

                # default return if NaN
                if np.isnan(responder.slots['value']):
                    responder.reply(salary_response)
                    responder.listen()
                    return

                # Responses specific to type functions
                if function in ('avg', 'sum'):
                    responder.reply(
                        'Based on your criteria, the {function} salary is ${value}'
                    )
                else:
                    responder.reply("The {function} of employees is {value}")

        # Capture any implicit mentions of money and resolve count or percentage queries (eg. how many people get more than 30)
        elif function not in ('avg', 'sum'):

            out = _apply_money_filter(qa, request, responder)
            if out:
                qa, size = out
            else:
                return

            qa_out = qa.execute(size=size)
            responder = _calculate_agg_salary(responder, qa_out, function)

            # default return if NaN
            if np.isnan(responder.slots['value']):
                responder.reply(salary_response)
                responder.listen()
                return
            responder.reply("The {function} of employees is {value}")

        else:
            responder.reply(
                "I see you are looking for the {function}, can you be more specific?"
            )
            responder.frame['function'] = func_entity
            responder.params.allowed_intents = (
                'general.get_aggregate', 'salary.get_salary_aggregate',
                'date.get_date_range_aggregate')
            responder.listen()

    else:
        responder.reply(salary_response)
        responder.listen()