Example #1
0
    def async_respond_to_queued_utts(session_key, user_utt, talker_names):
        user_utt = U(user_utt)

        failsafe_user_utt = {
            'raw_utt': user_utt,
            'spelled_utt': user_utt,
            'spelled_tags': [],
            'corefed_utt': user_utt,
            'corefed_tags': []
        }

        failsafe_bot_response = {
            'talker_name': "failsafe",
            'utt': u'Sorry, could you say that again, please :)',
            'score': -1.0,
            'confidence': -1.0,
            'talker_weight': 1.0
        }

        pipe = db.pipeline()
        pipe.set(last_bot_utt_key(session_key), AsyncBot.none_pickle, nx=True)
        pipe.set(new_user_utt_key(session_key), AsyncBot.none_pickle, nx=True)
        pipe.rename(new_user_utt_key(session_key),
                    last_user_utt_key(session_key))
        pipe.set(new_user_utt_key(session_key),
                 pickle.dumps(failsafe_user_utt, -1))
        pipe.delete(new_bot_utts_key(session_key))
        pipe.zadd(new_bot_utts_key(session_key),
                  pickle.dumps(failsafe_bot_response, -1),
                  -failsafe_bot_response['score'])
        pipe.delete(new_bot_followups_key(session_key))
        pipe.execute()

        responders = [
            async_talkers[tn] for tn in talker_names if
            not getattr(async_talkers[tn].klass._respond_to, '_no_op', False)
        ]
        follow_uppers = [
            async_talkers[tn] for tn in talker_names
            if not getattr(async_talkers[tn].klass.follow_up, '_no_op', False)
        ]

        sa = dict(immutable=True)
        if config.celery_timeouts:
            sa['soft_time_limit'] = config.talker_respond_timeout
            sa['time_limit'] = config.talker_respond_timeout + 2
        job = (
            AsyncBot.preprocessor.preprocess.signature(
                (user_utt, session_key), **sa) | celery.group(
                    t.respond_to.signature((session_key, ), **sa)
                    for t in responders) |
            # add noop because of https://github.com/celery/celery/issues/3585
            AsyncBot.noop.si(session_key))
        if follow_uppers:
            job = (job | celery.group(
                t.follow_up.signature((session_key, ), **sa)
                for t in follow_uppers))
        job = job | AsyncBot.combine_responses_and_follow_ups.signature(
            (session_key, ), **sa)
        return job.delay(time_limit=3)
Example #2
0
        def preprocess(user_raw_utt, session_key):
            try:
                pipe = db.pipeline(transaction=False)
                pipe.get(last_bot_utt_key(session_key))
                state, pret = self.get_state(session_key, pipe)
                last_bot_utt = pickle.loads(pret[0])

                state, user_utt_dict = self.object.preprocess(
                    state, user_raw_utt, last_bot_utt)

                pipe = db.pipeline(transaction=False)
                pipe.set(new_user_utt_key(session_key),
                         pickle.dumps(user_utt_dict, -1))
                self.save_state(session_key, state, pipe)
            except:
                handle_async_error(session_key=session_key)
Example #3
0
 def set_article(article, session_key):
     try:
         state = self.get_state(session_key)
         state, article_dict = self.object.set_article(state, article)
         pipe = db.pipeline(transaction=False)
         pipe.set(article_key(session_key),
                  pickle.dumps(article_dict, -1))
         self.save_state(session_key, state, pipe)
     except:
         handle_async_error(session_key=session_key)
Example #4
0
 def set_article(session_key):
     try:
         if getattr(self.object.set_article, '_no_op', False):
             return
         pipe = db.pipeline(transaction=False)
         pipe.get(article_key(session_key))
         state, pret = self.get_state(session_key, pipe)
         article = pickle.loads(pret[0])
         state = self.object.set_article(state, article)
         self.save_state(session_key, state)
     except:
         handle_async_error(session_key=session_key)
Example #5
0
        def follow_up(session_key):
            try:
                if getattr(self.object.follow_up, '_no_op', False):
                    return
                pipe = db.pipeline(transaction=False)
                pipe.zrange(new_bot_utts_key(session_key), 0, -1)
                state, pret = self.get_state(session_key, pipe)
                new_bot_utts = [pickle.loads(bu) for bu in pret[0]]

                state, new_bot_utt, confidence = self.object.follow_up(
                    state, new_bot_utts)

                pipe = db.pipeline(transaction=False)
                if confidence is not None and confidence > 0:
                    fu_data = pickle.dumps(
                        (self.klass.__name__, new_bot_utt, confidence), -1)
                    pipe.zadd(new_bot_followups_key(session_key), fu_data,
                              -confidence)
                self.save_state(session_key, state, pipe)
            except:
                handle_async_error(session_key=session_key)
Example #6
0
        def respond_to(session_key):
            try:
                if getattr(self.object._respond_to, '_no_op', False):
                    return
                pipe = db.pipeline(transaction=False)
                pipe.get(last_user_utt_key(session_key))
                pipe.get(last_bot_utt_key(session_key))
                pipe.get(new_user_utt_key(session_key))
                state, pipe_ret = self.get_state(session_key, pipe)
                (last_user_utt_dict, last_bot_utt,
                 user_utt_dict) = (pickle.loads(r) for r in pipe_ret)
                state, bot_utt, confidence = self.object.respond_to(
                    state, last_user_utt_dict, last_bot_utt, user_utt_dict)

                if confidence is None or bot_utt is None:
                    self.save_state(session_key, state)
                    return

                name = self.klass.__name__
                weight = AsyncBot.talker_weight[name]
                score = confidence * weight
                utts = [{
                    'talker_name': name,
                    'utt': chatbot.postprocess_utt(bot_utt),
                    'score': score,
                    'confidence': confidence,
                    'talker_weight': weight
                }]
                if self.klass.apply_profanity:
                    chatbot.filter_nsfw_utterances(utts, user_utt_dict)

                pipe = db.pipeline(transaction=False)
                pipe.zadd(new_bot_utts_key(session_key),
                          pickle.dumps(utts[0], -1), -utts[0]['score'])
                self.save_state(session_key, state, pipe)
            except:
                handle_async_error(session_key=session_key)
Example #7
0
 def get_state(self, session_key, pipe=None):
     _pipe = pipe or db.pipeline()
     state_key = session_key + self.state_suffix
     _pipe.get(state_key)
     pret = _pipe.execute()
     state_pickle = pret.pop(-1)
     if state_pickle is None:
         print('Computning new state for: %s' % (self.base_name, ))
         state = self.object.new_state()
     else:
         state = pickle.loads(state_pickle)
     if pipe is not None:
         return state, pret
     else:
         return state
Example #8
0
    def combine_responses_and_follow_ups(session_key):
        pipe = db.pipeline()
        pipe.zrange(new_bot_utts_key(session_key), 0, -1)
        pipe.delete(new_bot_utts_key(session_key))
        pipe.zrange(new_bot_followups_key(session_key), 0, -1)
        pipe.delete(new_bot_followups_key(session_key))
        utts, _, follow_ups, _ = pipe.execute()

        utts = [pickle.loads(u) for u in utts]
        follow_ups = [pickle.loads(fu) for fu in follow_ups]

        new_bot_utt = utts[0]['utt']

        utt_table = []
        sel_fu = None
        if follow_ups:
            sel_fu = chatbot.select_follow_up(follow_ups)
        if sel_fu:
            name, fu, confidence = sel_fu
            new_bot_utt = chatbot.postprocess_utt(fu)
            utt_table.append({
                'talker_name': name + ' sel_fup',
                'utt': fu,
                'score': confidence,
                'confidence': confidence,
                'talker_weight': 1.0
            })

        for name, fu, confidence in follow_ups:
            score = confidence
            if confidence and 1 < confidence:
                score = 1.0 + (score - 1.0) * config.talker_weight[name]
            utt_table.append({
                'talker_name': name + ' fup',
                'utt': fu,
                'score': score,
                'confidence': confidence,
                'talker_weight': 1.0
            })

        utt_table.extend(utts)
        db.set(last_bot_utt_key(session_key), pickle.dumps(new_bot_utt, -1))
        return new_bot_utt, utt_table