Esempio n. 1
0
        def _pair_with_human(cursor, my_id, my_index, partner_id, scenario, chat_id):
            controller, my_session, partner_session = _init_controller(my_index, HumanSystem.name(), scenario, chat_id)
            self.controller_map[my_id] = controller
            self.controller_map[partner_id] = controller

            self.sessions[my_id] = my_session
            self.sessions[partner_id] = partner_session

            # ensures that partner is actually in waiting state
            self._get_user_info(cursor, partner_id, assumed_status=Status.Waiting)

            # Update partner
            self._update_user(cursor, partner_id,
                              status=Status.Chat,
                              partner_id=my_id,
                              partner_type=HumanSystem.name(),
                              scenario_id=scenario.uuid,
                              agent_index=1 - my_index,
                              message="",
                              chat_id=chat_id)

            # Update me
            self._update_user(cursor, my_id,
                              status=Status.Chat,
                              partner_id=partner_id,
                              partner_type=HumanSystem.name(),
                              scenario_id=scenario_id,
                              agent_index=my_index,
                              message="",
                              chat_id=chat_id)

            return True
Esempio n. 2
0
def add_systems(args, config_dict, schema, debug=False):
    """
    Params:
    config_dict: A dictionary that maps the bot name to a dictionary containing configs for the bot. The
        dictionary should contain the bot type (key 'type') and. for bots that use an underlying model for generation,
        the path to the directory containing the parameters, vocab, etc. for the model.
    Returns:
    agents: A dict mapping from the bot name to the System object for that bot.
    pairing_probabilities: A dict mapping from the bot name to the probability that a user is paired with that
        bot. Also includes the pairing probability for humans (backend.Partner.Human)
    """

    total_probs = 0.0
    # systems = {HumanSystem.name(): HumanSystem()}
    ### changed parts from original craigslistbargain code
    # get_system: in craigslistbargain/systems/__init__.py
    systems = {HumanSystem.name(): HumanSystem(), RulebasedSystem.name(): get_system("rulebased", args)}
    ###
    pairing_probabilities = {}
    timed = False if debug else True
    for (sys_name, info) in config_dict.iteritems():
        if "active" not in info.keys():
            warnings.warn("active status not specified for bot %s - assuming that bot is inactive." % sys_name)
        if info["active"]:
            name = info["type"]
            try:
                model = get_system(name, args, schema=schema, timed=timed, model_path=info.get('checkpoint'))
            except ValueError:
                warnings.warn(
                    'Unrecognized model type in {} for configuration '
                    '{}. Ignoring configuration.'.format(info, sys_name))
                continue
            systems[sys_name] = model
            if 'prob' in info.keys():
                prob = float(info['prob'])
                pairing_probabilities[sys_name] = prob
                total_probs += prob
    print '{} systems loaded'.format(len(systems))
    for name in systems:
        print name

    # TODO: clean up pairing probabilities (obsolete)
    if total_probs > 1.0:
        raise ValueError("Probabilities for active bots can't exceed 1.0.")
    if len(pairing_probabilities.keys()) != 0 and len(pairing_probabilities.keys()) != len(systems.keys()):
        remaining_prob = (1.0-total_probs)/(len(systems.keys()) - len(pairing_probabilities.keys()))
    else:
        remaining_prob = 1.0 / len(systems.keys())
    inactive_bots = set()
    for system_name in systems.keys():
        if system_name not in pairing_probabilities.keys():
            if remaining_prob == 0.0:
                inactive_bots.add(system_name)
            else:
                pairing_probabilities[system_name] = remaining_prob

    for sys_name in inactive_bots:
        systems.pop(sys_name, None)

    return systems, pairing_probabilities
Esempio n. 3
0
        def _init_controller(my_index, partner_type, scenario, chat_id):
            my_session = self.systems[HumanSystem.name()].new_session(my_index, scenario.get_kb(my_index))
            partner_session = self.systems[partner_type].new_session(1 - my_index, scenario.get_kb(1 - my_index))

            controller = Controller(scenario, [my_session, partner_session], chat_id=chat_id)

            return controller, my_session, partner_session
Esempio n. 4
0
def add_systems(args, config_dict, schema):
    """
    Args:
        config_dict: A dictionary that maps the bot name to a dictionary containing configs for the bot. The
        dictionary should contain the bot type (key 'type') and. for bots that use an underlying model for generation,
        the path to the directory containing the parameters, vocab, etc. for the model.

    Returns:
        systems: A dict mapping from the bot name to the System object for that bot.

    """

    total_probs = 0.0
    systems = {HumanSystem.name(): HumanSystem()}
    timed = False if params['debug'] else True
    for (sys_name, info) in config_dict.iteritems():
        if "active" not in info.keys():
            warnings.warn(
                "active status not specified for bot %s - assuming that bot is inactive."
                % sys_name)
        if info["active"]:
            name = info["type"]
            try:
                model = get_system(name,
                                   args,
                                   schema=schema,
                                   timed=timed,
                                   model_path=args.checkpoint)
            except ValueError:
                warnings.warn(
                    'Unrecognized model type in {} for configuration '
                    '{}. Ignoring configuration.'.format(info, sys_name))
                continue
            systems[sys_name] = model

    return systems
Esempio n. 5
0
def add_systems(args, config_dict, schema, debug=False):
    """
    Params:
    config_dict: A dictionary that maps the bot name to a dictionary containing configs for the bot. The
        dictionary should contain the bot type (key 'type') and. for bots that use an underlying model for generation,
        the path to the directory containing the parameters, vocab, etc. for the model.
    Returns:
    agents: A dict mapping from the bot name to the System object for that bot.
    pairing_probabilities: A dict mapping from the bot name to the probability that a user is paired with that
        bot. Also includes the pairing probability for humans (backend.Partner.Human)
    """

    total_probs = 0.0
    systems = {HumanSystem.name(): HumanSystem()}
    pairing_probabilities = {}
    timed = False if debug else True
    print 'timed:', timed
    for (sys_name, info) in config_dict.iteritems():
        if "active" not in info.keys():
            warnings.warn(
                "active status not specified for bot %s - assuming that bot is inactive."
                % sys_name)
        if info["active"]:
            name = info["type"]
            try:
                # TODO: model related arguments should be in config_dict (read from params.json), instead of in command line args, currently we are assuming there is only one model that needs `checkpoint`
                model = get_system(name,
                                   args,
                                   schema=schema,
                                   timed=timed,
                                   model_path=args.checkpoint)
            except ValueError:
                warnings.warn(
                    'Unrecognized model type in {} for configuration '
                    '{}. Ignoring configuration.'.format(info, sys_name))
                continue
            systems[sys_name] = model
            if 'prob' in info.keys():
                prob = float(info['prob'])
                pairing_probabilities[sys_name] = prob
                total_probs += prob

    # TODO: clean up pairing probabilities (obsolete)
    if total_probs > 1.0:
        raise ValueError("Probabilities for active bots can't exceed 1.0.")
    if len(pairing_probabilities.keys()) != 0 and len(
            pairing_probabilities.keys()) != len(systems.keys()):
        remaining_prob = (1.0 - total_probs) / (
            len(systems.keys()) - len(pairing_probabilities.keys()))
    else:
        remaining_prob = 1.0 / len(systems.keys())
    inactive_bots = set()
    for system_name in systems.keys():
        if system_name not in pairing_probabilities.keys():
            if remaining_prob == 0.0:
                inactive_bots.add(system_name)
            else:
                pairing_probabilities[system_name] = remaining_prob

    for sys_name in inactive_bots:
        systems.pop(sys_name, None)

    return systems, pairing_probabilities
Esempio n. 6
0
 def is_user_partner_bot(self, cursor, userid):
     u = self._get_user_info_unchecked(cursor, userid)
     return len(u.partner_type) > 0 and u.partner_type != HumanSystem.name()
Esempio n. 7
0
    def attempt_join_chat(self, userid):
        def _init_controller(my_index, partner_type, scenario, chat_id):
            my_session = self.systems[HumanSystem.name()].new_session(my_index, scenario.get_kb(my_index))
            partner_session = self.systems[partner_type].new_session(1 - my_index, scenario.get_kb(1 - my_index))

            controller = Controller(scenario, [my_session, partner_session], chat_id=chat_id)

            return controller, my_session, partner_session

        def _pair_with_human(cursor, my_id, my_index, partner_id, scenario, chat_id):
            controller, my_session, partner_session = _init_controller(my_index, HumanSystem.name(), scenario, chat_id)
            self.controller_map[my_id] = controller
            self.controller_map[partner_id] = controller

            self.sessions[my_id] = my_session
            self.sessions[partner_id] = partner_session

            # ensures that partner is actually in waiting state
            self._get_user_info(cursor, partner_id, assumed_status=Status.Waiting)

            # Update partner
            self._update_user(cursor, partner_id,
                              status=Status.Chat,
                              partner_id=my_id,
                              partner_type=HumanSystem.name(),
                              scenario_id=scenario.uuid,
                              agent_index=1 - my_index,
                              message="",
                              chat_id=chat_id)

            # Update me
            self._update_user(cursor, my_id,
                              status=Status.Chat,
                              partner_id=partner_id,
                              partner_type=HumanSystem.name(),
                              scenario_id=scenario_id,
                              agent_index=my_index,
                              message="",
                              chat_id=chat_id)

            return True

        def _pair_with_bot(cursor, userid, my_index, bot_type, scenario, chat_id):
            controller, my_session, bot_session = _init_controller(my_index, bot_type, scenario, chat_id)

            config = bot_session.config
            if config is not None:
                cursor.execute('INSERT INTO bot VALUES (?,?,?)',
                           (chat_id, bot_type, json.dumps(list(config))))

            self.controller_map[userid] = controller

            self.sessions[userid] = my_session

            self._update_user(cursor, userid,
                              status=Status.Chat,
                              partner_id=0,
                              partner_type=bot_type,
                              scenario_id=scenario_id,
                              agent_index=my_index,
                              message="",
                              chat_id=chat_id)

            return True

        def _get_other_waiting_users(cursor, userid):
            cursor.execute("SELECT name FROM active_user WHERE name!=? AND status=? AND connected_status=1",
                           (userid, Status.Waiting))
            userids = [r[0] for r in cursor.fetchall()]
            return userids

        def _choose_scenario_and_partner_type(cursor):
            # for each scenario, get number of complete dialogues per agent type
            all_partners = self.systems.keys() if not self.active_system else [self.active_system]

            if self.active_scenario is not None:
                return self.scenario_db.scenarios_list[self.active_scenario], np.random.choice(all_partners)

            cursor.execute('''SELECT * FROM scenario''')
            db_scenarios = cursor.fetchall()
            scenario_dialogues = defaultdict(lambda: defaultdict(int))

            for (scenario_id, partner_type, complete, active) in db_scenarios:
                complete = set(json.loads(complete))
                active = set(json.loads(active))
                # map from scenario ID -> partner type -> # of completed dialogues with that partner
                if scenario_id not in scenario_dialogues:
                    scenario_dialogues[scenario_id] = {}

                scenario_dialogues[scenario_id][partner_type] = len(complete) + len(active)

            # find "active" scenarios (scenarios for which at least one agent type has no completed or active dialogues)
            active_scenarios = defaultdict(list)
            for sid in scenario_dialogues.keys():
                for partner_type in all_partners:
                    if scenario_dialogues[sid][partner_type] < self.num_chats_per_scenario[partner_type]:
                        active_scenarios[sid].append(partner_type)

            # if all scenarios have at least one dialogue per agent type (i.e. no active scenarios),
            # just select a random scenario and agent type
            if len(active_scenarios.keys()) == 0:
                sid = np.random.choice(scenario_dialogues.keys())
                p = np.random.choice(all_partners)
                return self.scenario_db.get(sid), p

            # otherwise, select a random active scenario and an agent type that it's missing
            sid = np.random.choice(active_scenarios.keys())
            p = np.random.choice(active_scenarios[sid])
            return self.scenario_db.get(sid), p

        def _update_used_scenarios(scenario_id, partner_type, chat_id):
            cursor.execute(
                '''SELECT active FROM scenario WHERE scenario_id=? AND partner_type=?''',
                (scenario_id, partner_type))
            active_set = set(json.loads(cursor.fetchone()[0]))
            active_set.add(chat_id)
            cursor.execute('''UPDATE scenario SET active=? WHERE scenario_id=? AND partner_type=?''',
                           (json.dumps(list(active_set)), scenario_id, partner_type))

        try:
            with self.conn:
                cursor = self.conn.cursor()
                others = _get_other_waiting_users(cursor, userid)

                scenario, partner_type = _choose_scenario_and_partner_type(cursor)
                scenario_id = scenario.uuid
                #my_index = np.random.choice([0, 1])
                # TODO: hack for buyer/seller
                my_index = 0 if self.scenario_int_id[scenario_id] % 2 == 0 else 1
                chat_id = self._generate_chat_id()
                if partner_type == HumanSystem.name():
                    if len(others) == 0:
                        return None
                    partner_id = np.random.choice(others)

                    try:
                        _pair_with_human(cursor, userid, my_index, partner_id, scenario, chat_id)
                    except UnexpectedStatusException:
                        self.logger.warn("Attempt to pair user {:s} with {:s} failed. User {:s} not in waiting "
                                         "status".format(userid, partner_id, partner_id))
                        return False
                    except ConnectionTimeoutException:
                        self.logger.warn("Attempt to pair user {:s} with {:s} failed. User {:s} had connection "
                                         "timeout".format(userid, partner_id, partner_id))
                        return False
                    _update_used_scenarios(scenario_id, HumanSystem.name(), chat_id)
                    if my_index == 0:
                        self.add_chat_to_db(chat_id, scenario_id, userid, partner_id, HumanSystem.name(),
                                            HumanSystem.name())
                    else:
                        self.add_chat_to_db(chat_id, scenario_id, partner_id, userid, HumanSystem.name(),
                                            HumanSystem.name())
                    self.logger.debug("Paired users {:s} and {:s} in chat with ID {:s} and scenario {:s}".format(
                        userid, partner_id, chat_id, scenario_id
                    ))
                    return True
                else:
                    _update_used_scenarios(scenario_id, partner_type, chat_id)
                    if my_index == 0:
                        self.add_chat_to_db(chat_id, scenario_id, userid, 0, HumanSystem.name(), partner_type)
                    else:
                        self.add_chat_to_db(chat_id, scenario_id, 0, userid, partner_type, HumanSystem.name())

                    self.logger.debug("Paired user {:s} with bot of type {:s} in chat with ID {:s} and scenario "
                                      "{:s}".format(userid, partner_type, chat_id, scenario_id))
                    return _pair_with_bot(cursor, userid, my_index, partner_type, scenario, chat_id)

        except sqlite3.IntegrityError:
            print("WARNING: Rolled back transaction")