コード例 #1
0
    def multiple_save_info(cls, question: str, session_id: str,
                           context_id: str, std_question_id: int,
                           collection: str, partition: str, qa: QA,
                           qa_manager: QAManager, **kwargs):
        """
        多轮问答保存信息至session的info中

        @param {str} question - 客户反馈的信息文本(提问回答)
        @param {str} session_id - 客户的session id
        @param {str} context_id - 上下文临时id
        @param {int} std_question_id - 上下文中对应的提问问题id
        @param {str} collection - 提问答案参数指定的问题分类
        @param {str} partition - 提问答案参数指定的场景标签
        @param {QA} qa - 服务器的问答处理模块实例对象
        @param {QAManager} qa_manager - 服务器的问答数据管理实例对象
        @param {kwargs} - 扩展传入参数
            ask {list} - 问题列表,注意最后的问题必须有tips或to参数
                [
                    {'info_key': '保存的key值', 'next_tips': '下一个问题'},
                    ...,
                    {'info_key': '保存的key值', 'tips': '处理完成提示', 'to': 跳转到指定问题id},
                ]
        @param {str, object} - 按照不同的处理要求返回内容
            'answer', [str, ...]  - 直接返回回复内容,第二个参数为回复内容
            'to', int - 跳转到指定问题处理,第二个参数为std_question_id
            'again', [str, ...] - 再获取一次答案,第二个参数为提示内容,如果第2个参数为None代表使用原来的参数再提问一次
            'break', [collection, partition] - 跳出问题(让问题继续走匹配流程),可以返回[collection, partition]变更分类和场景
            默认为'again'
        """
        _step = qa.get_cache_value(session_id, 'multiple_save_info',
                                   {}).get(context_id, 0)
        _ask = kwargs.get('ask')[_step]

        # 保存值
        _info_key = _ask.get('info_key')
        _info = dict()
        _info[_info_key] = question
        qa.update_session_info(session_id, _info)

        # 处理下一个问题
        _to = _ask.get('to', None)
        _tips = _ask.get('tips', None)
        _next_tips = _ask.get('next_tips', None)
        if _to is not None or _tips is not None:
            # 最后一个问题
            qa.del_cache(session_id, 'multiple_save_info')
            if _to is None:
                return 'answer', [
                    _tips,
                ]
            else:
                return 'to', _to
        else:
            # 还有下一个问题
            qa.add_cache(session_id, 'multiple_save_info',
                         {context_id: _step + 1})
            return 'again', [
                _next_tips,
            ]
コード例 #2
0
ファイル: api_tools.py プロジェクト: snakeclub/chat_robot
    def weather(cls, question: str, session_id: str, context_id: str,
                std_question_id: int, collection: str, partition: str, qa: QA,
                qa_manager: QAManager, **kwargs):
        """
        查询天气

        @param {str} question - 客户反馈的信息文本(提问回答)
        @param {str} session_id - 客户的session id
        @param {str} context_id - 上下文临时id
        @param {int} std_question_id - 上下文中对应的提问问题id
        @param {str} collection - 提问答案参数指定的问题分类
        @param {str} partition - 提问答案参数指定的场景标签
        @param {QA} qa - 服务器的问答处理模块实例对象
        @param {QAManager} qa_manager - 服务器的问答数据管理实例对象
        @param {kwargs} - 扩展传入参数
            time {list} - nlp分词的时间词语列表
            addr {list} - nlp分词的地址词语列表

        @returns {str, object} - 按照不同的处理要求返回内容
            'answer', [str, ...]  - 直接返回回复内容,第二个参数为回复内容
            'to', int - 跳转到指定问题处理,第二个参数为std_question_id
            'again', [str, ...] - 再获取一次答案,第二个参数为提示内容,如果第2个参数为None代表使用原来的参数再提问一次
            'break', [collection, partition] - 跳出问题(让问题继续走匹配流程),可以返回[collection, partition]变更分类和场景
            默认为'again'
        """
        _match_city_code = ''
        _match_day = 0  # 0代表当前,1代表明天,2代表后天
        # 检查是不是第二次的选项
        _cache_info = qa.get_cache_value(session_id,
                                         'weather',
                                         default=None,
                                         context_id=context_id)
        if _cache_info is not None:
            if question.isdigit():
                if question not in _cache_info['addr_dict'].keys():
                    # 回答不在选项范围
                    return 'again', [
                        '亲, 您输入的序号不对, 请输入正确的序号选择城市',
                    ]
                else:
                    _match_day = _cache_info['day']
                    _match_city_code = _cache_info['addr_dict'][question]
            else:
                # 不是选项,是文字
                return 'answer', [
                    WEATHER_ERROR,
                ]
        else:
            # 尝试获取日期
            for _word in kwargs.get('time', []):
                if _word in ['明天']:
                    _match_day = 1
                elif _word in ['后天']:
                    _match_day = 2

            # 尝试获取地址
            with redis.Redis(connection_pool=qa.redis_pool) as _redis:
                _match_addr = cls._search_city(kwargs.get('addr', []), _redis)
                if len(_match_addr) == 0:
                    # 没有匹配到地址,尝试获取客户info中的地址
                    _addr = qa.get_info_by_key(session_id, 'addr', default='')

                    if _addr == '' and WEATHER_TRY_USE_IP_ADDR:
                        # 尝试通过IP地址获取地址
                        _addr = cls._get_addr_by_ip(
                            qa.get_info_by_key(session_id, 'ip', default=''),
                            qa)

                    if _addr != '':
                        _addrs_with_class = qa.nlp.cut_sentence(_addr)
                        _addrs = [item[0] for item in _addrs_with_class]
                        _match_addr = cls._search_city(_addrs, _redis)

                _len = len(_match_addr)
                if _len == 1:
                    _match_city_code = _match_addr[0][1][0]
                elif _len > 1:
                    # 匹配到多个,进行提问让客户选择
                    _tips = ['找到了多个地址,您想查询哪个地址的天气?请输入序号进行选择: ']
                    _index = 1
                    _cache_info = dict()
                    _cache_info['day'] = _match_day
                    _cache_info['addr_dict'] = dict()
                    for item in _match_addr:
                        # 加入到上下文
                        _cache_info['addr_dict'][str(_index)] = item[1][0]

                        # 获取详细地址
                        _tips.append(
                            '%d.%s' %
                            (_index, cls._get_city_full_name(item[0], _redis)))
                        _index += 1

                    # 添加到cache中
                    qa.add_cache(session_id,
                                 'weather',
                                 _cache_info,
                                 context_id=context_id)

                    # 重新提问
                    return 'again', _tips

        if _match_city_code == '':
            # 没有找到地址,直接返回退出
            return 'answer', [
                WEATHER_ERROR,
            ]

        # 查询天气, 先查本地缓存
        _today = datetime.datetime.now().strftime('%Y-%m-%d')
        with redis.Redis(connection_pool=qa.redis_pool) as _redis:
            _json = _redis.get('api_tool_ask:weather:cache:%s:%s' %
                               (_match_city_code, _today))
            if _json is None:
                # 要进行查询
                _api_back = NetTool.restful_api_call(
                    'http://t.weather.sojson.com/api/weather/city/%s' %
                    _match_city_code,
                    back_type='text',
                    logger=qa.logger)
                if _api_back['is_success']:
                    _json = _api_back['back_object']
                    _wdata = json.loads(_json)
                    if _wdata['status'] == 200:
                        # 存入缓存,一天到期
                        _redis.set('api_tool_ask:weather:cache:%s:%s' %
                                   (_match_city_code, _today),
                                   _json,
                                   ex=86400)
                    else:
                        return 'answer', [
                            WEATHER_ERROR,
                        ]
                else:
                    # 获取失败
                    return 'answer', [
                        WEATHER_ERROR,
                    ]
            else:
                _wdata = json.loads(_json)

        # 返回结果
        _end_str = ''  # 结束语
        if _match_day == 0:
            _end_str = '湿度%s, PM2.5: %s, 空气质量%s, %s, ' % (
                _wdata['data']['shidu'], _wdata['data']['pm25'],
                _wdata['data']['quality'], _wdata['data']['ganmao'])

        _answer = '亲, %s%s的天气%s, 吹%s%s, %s, %s, %s%s' % (
            _wdata['cityInfo']['city'],
            _wdata['data']['forecast'][_match_day]['ymd'],
            _wdata['data']['forecast'][_match_day]['type'],
            _wdata['data']['forecast'][_match_day]['fl'],
            _wdata['data']['forecast'][_match_day]['fx'],
            _wdata['data']['forecast'][_match_day]['high'],
            _wdata['data']['forecast'][_match_day]['low'], _end_str,
            _wdata['data']['forecast'][_match_day]['notice'])

        return 'answer', [
            _answer,
        ]