V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
noobsheldon
V2EX  ›  问与答

有人玩过 wit.ai 吗?请教个问题,详情如下。

  •  
  •   noobsheldon · 2017-03-06 14:35:18 +08:00 · 1133 次点击
    这是一个创建于 2627 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Wit 的 Python 的 SDK 中,如果一个 story 定义多个自定义函数:

    actions = {
        'func1': func1,
        'func2': func2,
        'func3': func3,
        'send': send
    }
    

    如果是这样的话。调用一次 run_actions 时是直接把 func1 , func2 , func3 , send 一起执行了么? 以下是 Python 的 SDK 源码。

    from __future__ import unicode_literals
    import json
    import logging
    import os
    import requests
    import sys
    import uuid
    from prompt_toolkit import prompt
    from prompt_toolkit.history import InMemoryHistory
    
    WIT_API_HOST = os.getenv('WIT_URL', 'https://api.wit.ai')
    WIT_API_VERSION = os.getenv('WIT_API_VERSION', '20160516')
    DEFAULT_MAX_STEPS = 5
    INTERACTIVE_PROMPT = '> '
    LEARN_MORE = 'Learn more at https://wit.ai/docs/quickstart'
    
    class WitError(Exception):
        pass
    
    def req(logger, access_token, meth, path, params, **kwargs):
        full_url = WIT_API_HOST + path
        logger.debug('%s %s %s', meth, full_url, params)
        headers = {
            'authorization': 'Bearer ' + access_token,
            'accept': 'application/vnd.wit.' + WIT_API_VERSION + '+json'
        }
        headers.update(kwargs.pop('headers', {}))
        rsp = requests.request(
            meth,
            full_url,
            headers=headers,
            params=params,
            **kwargs
        )
        if rsp.status_code > 200:
            raise WitError('Wit responded with status: ' + str(rsp.status_code) +
                           ' (' + rsp.reason + ')')
        json = rsp.json()
        if 'error' in json:
            raise WitError('Wit responded with an error: ' + json['error'])
    
        logger.debug('%s %s %s', meth, full_url, json)
        return json
    
    def validate_actions(logger, actions):
        if not isinstance(actions, dict):
            logger.warn('The second parameter should be a dictionary.')
        for action in ['send']:
            if action not in actions:
                logger.warn('The \'' + action + '\' action is missing. ' +
                                LEARN_MORE)
        for action in actions.keys():
            if not hasattr(actions[action], '__call__'):
                logger.warn('The \'' + action +
                                '\' action should be a function.')
        return actions
    
    class Wit(object):
        access_token = None
        actions = {}
        _sessions = {}
    
        def __init__(self, access_token, actions=None, logger=None):
            self.access_token = access_token
            self.logger = logger or logging.getLogger(__name__)
            if actions:
                self.actions = validate_actions(self.logger, actions)
    
        def message(self, msg, context=None, verbose=None):
            params = {}
            if verbose:
                params['verbose'] = True
            if msg:
                params['q'] = msg
            if context:
                params['context'] = json.dumps(context)
            resp = req(self.logger, self.access_token, 'GET', '/message', params)
            return resp
    
        def speech(self, audio_file, verbose=None, headers=None):
            """ Sends an audio file to the /speech API.
            Uses the streaming feature of requests (see `req`), so opening the file
            in binary mode is strongly reccomended (see
            http://docs.python-requests.org/en/master/user/advanced/#streaming-uploads).
            Add Content-Type header as specified here: https://wit.ai/docs/http/20160526#post--speech-link
    
            :param audio_file: an open handler to an audio file
            :param verbose:
            :param headers: an optional dictionary with request headers
            :return:
            """
            params = {}
            headers = headers or {}
            if verbose:
                params['verbose'] = True
            resp = req(self.logger, self.access_token, 'POST', '/speech', params,
                       data=audio_file, headers=headers)
            return resp
    
        def converse(self, session_id, message, context=None, reset=None,
                     verbose=None):
            if context is None:
                context = {}
            params = {'session_id': session_id}
            if verbose:
                params['verbose'] = True
            if message:
                params['q'] = message
            if reset:
                params['reset'] = True
            resp = req(self.logger, self.access_token, 'POST', '/converse', params,
                       data=json.dumps(context))
            return resp
    
        def __run_actions(self, session_id, current_request, message, context, i,
                          verbose):
            if i <= 0:
                raise WitError('Max steps reached, stopping.')
            json = self.converse(session_id, message, context, verbose=verbose)
            if 'type' not in json:
                raise WitError('Couldn\'t find type in Wit response')
            if current_request != self._sessions[session_id]:
                return context
    
            self.logger.debug('Context: %s', context)
            self.logger.debug('Response type: %s', json['type'])
    
            # backwards-cpmpatibility with API version 20160516
            if json['type'] == 'merge':
                json['type'] = 'action'
                json['action'] = 'merge'
    
            if json['type'] == 'error':
                raise WitError('Oops, I don\'t know what to do.')
    
            if json['type'] == 'stop':
                return context
    
            request = {
                'session_id': session_id,
                'context': dict(context),
                'text': message,
                'entities': json.get('entities'),
            }
            if json['type'] == 'msg':
                self.throw_if_action_missing('send')
                response = {
                    'text': json.get('msg').encode('utf8'),
                    'quickreplies': json.get('quickreplies'),
                }
                self.actions['send'](request, response)
            elif json['type'] == 'action':
                action = json['action']
                self.throw_if_action_missing(action)
                context = self.actions[action](request)
                if context is None:
                    self.logger.warn('missing context - did you forget to return it?')
                    context = {}
            else:
                raise WitError('unknown type: ' + json['type'])
            if current_request != self._sessions[session_id]:
                return context
            return self.__run_actions(session_id, current_request, None, context,
                                      i - 1, verbose)
    
        def run_actions(self, session_id, message, context=None,
                        max_steps=DEFAULT_MAX_STEPS, verbose=None):
            if not self.actions:
                self.throw_must_have_actions()
            if context is None:
                context = {}
    
            # Figuring out whether we need to reset the last turn.
            # Each new call increments an index for the session.
            # We only care about the last call to run_actions.
            # All the previous ones are discarded (preemptive exit).
            current_request = self._sessions[session_id] + 1 if session_id in self._sessions else 1
            self._sessions[session_id] = current_request
    
            context = self.__run_actions(session_id, current_request, message,
                                         context, max_steps, verbose)
    
            # Cleaning up once the last call to run_actions finishes.
            if current_request == self._sessions[session_id]:
                del self._sessions[session_id]
    
            return context
    
        def interactive(self, context=None, max_steps=DEFAULT_MAX_STEPS):
            """Runs interactive command line chat between user and bot. Runs
            indefinately until EOF is entered to the prompt.
    
            context -- optional initial context. Set to {} if omitted
            max_steps -- max number of steps for run_actions.
            """
            if not self.actions:
                self.throw_must_have_actions()
            if max_steps <= 0:
                raise WitError('max iterations reached')
            if context is None:
                context = {}
    
            # input/raw_input are not interchangible between python 2 and 3
            try:
                input_function = raw_input
            except NameError:
                input_function = input
    
            session_id = uuid.uuid1()
            history = InMemoryHistory()
            while True:
                try:
                    message = prompt(INTERACTIVE_PROMPT, history=history, mouse_support=True).rstrip()
                except (KeyboardInterrupt, EOFError):
                    return
                context = self.run_actions(session_id, message, context, max_steps)
    
        def throw_if_action_missing(self, action_name):
            if action_name not in self.actions:
                raise WitError('unknown action: ' + action_name)
    
        def throw_must_have_actions(self):
            raise WitError('You must provide the `actions` parameter to be able to use runActions. ' + LEARN_MORE)
    
    
    
    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3802 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 04:41 · PVG 12:41 · LAX 21:41 · JFK 00:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.