Class: Hg::ApiAiClient

Inherits:
Object
  • Object
show all
Defined in:
lib/hg/api_ai_client.rb

Defined Under Namespace

Classes: QueryError

Constant Summary collapse

UNKNOWN_SYSTEM_ACTION =

Name of action for unrecognized messages.

'input.unknown'

Instance Method Summary collapse

Constructor Details

#initialize(session_id) ⇒ ApiAiClient

Returns a new instance of ApiAiClient.



15
16
17
18
19
20
21
22
# File 'lib/hg/api_ai_client.rb', line 15

def initialize(session_id)
  # TODO: access token should be set by Hg config option
  @client = ApiAiRuby::Client.new(
    client_access_token: ENV['API_AI_CLIENT_ACCESS_TOKEN'],
    api_version: '20170210',
    api_session_id: session_id
  )
end

Instance Method Details

#query(message, context_name: nil) ⇒ Hash

Parse a natural language message with API.ai.

Parameters:

  • message (String)

    The natural language query to be parsed.

  • context_name (String) (defaults to: nil)

    The context name to set on the Dialogflow session.

Returns:

  • (Hash)

    The information parsed from the message.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/hg/api_ai_client.rb', line 32

def query(message, context_name: nil)
  # TODO: which logger?
  retry_counter = 0

  begin
    retry_counter += 1

    # Build a contexts object if one is passed.
    contexts = context_name ? [context_name] : nil

    api_ai_response = @client.text_request(message, contexts: contexts)
  rescue ApiAiRuby::ClientError, ApiAiRuby::RequestError => e
    Sidekiq::Logging.logger.error 'Error with API.ai query request'
    Sidekiq::Logging.logger.error e
    Sidekiq::Logging.logger.error e.backtrace.join("\n")

    # Retry the call 3 times.
    retry if retry_counter < 3

    raise QueryError.new
  else
    # If the API.ai call fails...
    if api_ai_response[:status][:code] != 200
      # ...log an error.
      Sidekiq::Logging.logger.error "Error with API.ai request: #{api_ai_response.inspect}"

      # Return the default action.
      return {
        action: Hg::InternalActions::DEFAULT,
        intent: Hg::InternalActions::DEFAULT
      }
    end

    intent_name = api_ai_response[:result][:metadata][:intentName]

    # Determine the action name
    action_from_response = api_ai_response[:result][:action]

    # Use intent name as action name if no action name is defined for this intent.
    action_name =
      if action_from_response.blank?
        intent_name
      # Set to default action if message is not recognized.
      elsif action_from_response == UNKNOWN_SYSTEM_ACTION.freeze
        Hg::InternalActions::DEFAULT
      else
        action_from_response
      end

    response = api_ai_response[:result][:fulfillment][:speech]

    return {
      intent: intent_name,
      action: action_name,
      parameters: parsed_params(api_ai_response[:result][:parameters]),
      response: response
    }
  end
end