RecastAI 2.1.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8d58d68e62629b591fffce5b9b25760cbf33df04
4
- data.tar.gz: feeffc07cefdc2ac4330ac7c55a97c34f3739f95
3
+ metadata.gz: 8e0d9d38204152540d567fca3d5d666bc1074bff
4
+ data.tar.gz: 6c75863441add341d3832dc812ed281088d68da7
5
5
  SHA512:
6
- metadata.gz: 0432fb7213212e053006db659ed72125dd4cfa0805c3bd6987e12a0b2941038a81e9ec664387afac90200622184fbaccda3a6ea727deef00438b66163456c6c3
7
- data.tar.gz: b8e8ecacb4793e2ea3ea898a7a1ae3c27f8045878b6503fce23545d3d6f7e930e67b600376c424af1e73c529a93406292e4af755d5430be6a229ef06a86f374f
6
+ metadata.gz: fd45c6c44cfd34dd279b9a45399284c6085a61404b98e08b308b24220085510f5d60be5d5bf9de0969e3318c10719e29dd3876af0f9d73535c5ed8feab34ff83
7
+ data.tar.gz: 4c8f99a187d5db0885f10b1166602ce0e52a7d1142c00eb3c3fc8697e4b885d931fa5d171e2a5e6dc560aba8c3543b78eb07cfa5b5cd9917bec1fb0ea10b1c1f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- RecastAI (2.0.0)
4
+ RecastAI (3.0.0)
5
5
  httmultiparty (~> 0.3)
6
6
  httparty (~> 0.13)
7
7
 
@@ -19,12 +19,11 @@ GEM
19
19
  httparty (>= 0.7.3)
20
20
  mimemagic
21
21
  multipart-post
22
- httparty (0.13.7)
23
- json (~> 1.8)
22
+ httparty (0.14.0)
24
23
  multi_xml (>= 0.5.2)
25
24
  json (1.8.3)
26
- mimemagic (0.3.1)
27
- multi_xml (0.5.5)
25
+ mimemagic (0.3.2)
26
+ multi_xml (0.6.0)
28
27
  multipart-post (2.0.0)
29
28
  rspec (3.4.0)
30
29
  rspec-core (~> 3.4.0)
@@ -61,4 +60,4 @@ DEPENDENCIES
61
60
  webmock (~> 1.24)
62
61
 
63
62
  BUNDLED WITH
64
- 1.12.5
63
+ 1.14.5
data/README.md CHANGED
@@ -9,35 +9,35 @@ Recast.AI official SDK in Ruby
9
9
  ## Synospis
10
10
 
11
11
  This module is a wrapper around the [Recast.AI](https://recast.ai) API, and allows you to:
12
- * [build a bot](https://github.com/RecastAI/SDK-Ruby/wiki/Build-your-bot)
13
- * [analyze your text](https://github.com/RecastAI/SDK-Ruby/wiki/Analyse-text)
12
+ * [Analyse your text](https://github.com/RecastAI/SDK-Ruby/wiki/01---Analyse-text)
13
+ * [Manage a conversation](https://github.com/RecastAI/SDK-Ruby/wiki/02---Manage-conversation)
14
+ * [Receive and send messages](https://github.com/RecastAI/SDK-Ruby/wiki/03---Receive-and-send-messages)
14
15
 
15
16
  ## Installation
16
17
 
18
+ This gem supports ruby 2.3+.
19
+
17
20
  ```bash
18
- gem install 'RecastAI'
21
+ gem install RecastAI
19
22
  ```
20
23
 
21
- ## Documentation
22
-
23
- You can find the full documentation [here](https://github.com/RecastAI/SDK-Ruby/wiki).
24
+ You can now use the sdk in your code.
24
25
 
25
- ## Specs
26
+ Using the entire SDK:
27
+ ```ruby
28
+ require 'recastai'
26
29
 
27
- ### Classes
30
+ client = RecastAI.new('YOUR_TOKEN')
31
+ ```
28
32
 
29
- This module contains 7 classes, as follows:
33
+ Extracting one single API:
34
+ ```ruby
35
+ require 'recastai'
30
36
 
31
- * [Client](https://github.com/RecastAI/SDK-Ruby/wiki/Class-Client) is the client allowing you to make requests.
32
- * [Response](https://github.com/RecastAI/SDK-Ruby/wiki/Class-Response) wraps the response from a call to [Recast.AI](https://recast.ai) API with the text_request or file_request Client methods.
33
- * [Conversation](https://github.com/RecastAI/SDK-Ruby/wiki/Class-Conversation) wraps the response from a call to [Recast.AI](https://recast.ai) API with the text_converse Client method.
34
- * [Action](https://github.com/RecastAI/SDK-Ruby/wiki/Class-Action) represents an action to do when using the text_converse method.
35
- * [Intent](https://github.com/RecastAI/SDK-Ruby/wiki/Class-Intent) represents an intent matched when using either the text_request, file_request or text_converse methods.
36
- * [Entity](https://github.com/RecastAI/SDK-Ruby/wiki/Class-Entity) represents an entity extracted from an input.
37
- * [RecastError](https://github.com/RecastAI/SDK-Ruby/wiki/Class-RecastError) is the error returned by the module.
37
+ request = RecastAI::Request.new('YOUR_TOKEN')
38
+ connect = RecastAI::Connect.new('YOUR_TOKEN')
39
+ ```
38
40
 
39
- Don't hesitate to dive into the code, it's commented ;)
40
- `
41
41
  ## More
42
42
 
43
43
  You can view the whole API reference at [man.recast.ai](https://man.recast.ai).
@@ -52,7 +52,7 @@ You can follow us on Twitter at [@recastai](https://twitter.com/recastai) for up
52
52
 
53
53
  ## License
54
54
 
55
- Copyright (c) [2016] [Recast.AI](https://recast.ai)
55
+ Copyright (c) [2017] [Recast.AI](https://recast.ai)
56
56
 
57
57
  Permission is hereby granted, free of charge, to any person obtaining a copy
58
58
  of this software and associated documentation files (the "Software"), to deal
data/lib/recastai.rb CHANGED
@@ -2,15 +2,25 @@
2
2
 
3
3
  $LOAD_PATH.unshift(File.dirname(__FILE__))
4
4
 
5
+ require 'json'
5
6
  require 'httparty'
6
7
  require 'httmultiparty'
7
- require 'json'
8
8
 
9
9
  require 'recastai/utils'
10
- require 'recastai/errors'
11
- require 'recastai/client'
12
- require 'recastai/response'
13
- require 'recastai/conversation'
14
- require 'recastai/action'
15
- require 'recastai/intent'
16
- require 'recastai/entity'
10
+ require 'recastai/apis/connect/connect'
11
+ require 'recastai/apis/request/request'
12
+
13
+ module RecastAI
14
+ class Client
15
+ attr_reader :token, :language
16
+
17
+ def initialize(token = nil, language = nil)
18
+ [RecastAI::Request, RecastAI::Connect].each do |api|
19
+ i = api.name.rindex('::')
20
+ name = i.nil? ? api.name : api.name[(i + 2)..-1]
21
+
22
+ self.class.send(:define_method, name.downcase.to_sym, ->{ api.new(token, language) })
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative 'message'
4
+
5
+ module RecastAI
6
+ class Connect
7
+ include Message
8
+
9
+ attr_reader :token, :language
10
+
11
+ def initialize(token = nil, language = nil)
12
+ @token = token
13
+ @language = language
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative 'models/message'
4
+ require_relative 'utils'
5
+
6
+ module RecastAI
7
+ module Message
8
+ def handle_message(request, &block)
9
+ request.body.rewind if request.body.respond_to?(:rewind)
10
+ body = request.body.is_a?(String) ? request.body : request.body.read
11
+ message = Msg.new(body)
12
+
13
+ yield(message)
14
+ end
15
+
16
+ def send_message(payload, conversation_id, token: nil)
17
+ token ||= @token
18
+ raise RecastError.new('Token is missing') if token.nil?
19
+
20
+ response = HTTParty.post(
21
+ "#{Utils::CONVERSATION_ENDPOINT}#{conversation_id}/messages",
22
+ body: { messages: payload },
23
+ headers: { 'Authorization' => "Token #{token}" }
24
+ )
25
+ raise RecastError.new(JSON.parse(response.body)['message']) if response.code != 201
26
+
27
+ response
28
+ end
29
+
30
+ def broadcast_message(payload, token: nil)
31
+ token ||= @token
32
+ raise RecastError.new('Token is missing') if token.nil?
33
+
34
+ response = HTTParty.post(
35
+ Utils::MESSAGE_ENDPOINT,
36
+ body: { messages: payload },
37
+ headers: { 'Authorization' => "Token #{token}" }
38
+ )
39
+ raise RecastError.new(JSON.parse(response.body)['message']) if response.code != 201
40
+
41
+ response
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ module RecastAI
4
+ class Msg
5
+ attr_reader :content, :type, :conversation_id
6
+
7
+ def initialize(request)
8
+ request = JSON.parse(request)
9
+ request.each do |k, v|
10
+ k = k.gsub(/(.)([A-Z])/,'\1_\2').downcase
11
+ self.instance_variable_set("@#{k}", v)
12
+ self.define_singleton_method(k.to_sym){ v }
13
+ end
14
+
15
+ @conversation_id = request['message']['conversation']
16
+ @content = request['message']['attachment']['content']
17
+ @type = request['message']['attachment']['type']
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ module RecastAI
4
+ class Utils
5
+ # Endpoints
6
+ MESSAGE_ENDPOINT = 'https://api.recast.ai/connect/v1/messages/'.freeze
7
+ CONVERSATION_ENDPOINT = 'https://api.recast.ai/connect/v1/conversations/'.freeze
8
+ end
9
+ end
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module RecastAI
4
- class RecastError < Exception
4
+ class RecastError < RuntimeError
5
5
  end
6
6
  end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative 'models/response'
4
+ require_relative 'utils'
5
+ require_relative '../errors'
6
+
7
+ module RecastAI
8
+ module Analyse
9
+ def analyse_text(text, token: nil, language: nil)
10
+ token ||= @token
11
+ raise RecastError.new('Token is missing') if token.nil?
12
+
13
+ language ||= @language
14
+
15
+ body = { text: text }
16
+ body[:language] = language unless language.nil?
17
+ response = HTTParty.post(
18
+ Utils::REQUEST_ENDPOINT,
19
+ body: body,
20
+ headers: { 'Authorization' => "Token #{token}" }
21
+ )
22
+ raise RecastError.new(JSON.parse(response.body)['message']) if response.code != 200
23
+
24
+ Response.new(response.body)
25
+ end
26
+
27
+ def analyse_file(file, token: nil, language: nil)
28
+ token ||= @token
29
+ raise RecastError.new('Token is missing') if token.nil?
30
+
31
+ language ||= @language
32
+
33
+ body = { voice: File.new(file) }
34
+ body[:language] = language unless language.nil?
35
+ response = HTTMultiParty.post(
36
+ Utils::REQUEST_ENDPOINT,
37
+ body: body,
38
+ headers: { 'Authorization' => "Token #{token}" }
39
+ )
40
+ raise RecastError.new(JSON.parse(response.body)['message']) if response.code != 200
41
+
42
+ Response.new(response.body)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative 'models/conversation'
4
+ require_relative 'utils'
5
+ require_relative '../errors'
6
+
7
+ module RecastAI
8
+ module Converse
9
+ def converse_text(text, token: nil, language: nil, conversation_token: nil, memory: nil)
10
+ token ||= @token
11
+ raise RecastError.new('Token is missing') if token.nil?
12
+
13
+ language ||= @language
14
+
15
+ body = { text: text }
16
+ body[:language] = language unless language.nil?
17
+ body[:conversation_token] = conversation_token unless conversation_token.nil?
18
+ body[:memory] = memory unless memory.nil?
19
+
20
+ response = HTTParty.post(
21
+ Utils::CONVERSE_ENDPOINT,
22
+ body: body,
23
+ headers: { 'Authorization' => "Token #{token}" }
24
+ )
25
+ raise RecastError.new(JSON.parse(response.body)['message']) if response.code != 200
26
+
27
+ Conversation.new(response.body, token)
28
+ end
29
+
30
+ def converse_file(file, token: nil, language: nil, conversation_token: nil, memory: nil)
31
+ token ||= @token
32
+ raise RecastError.new('Token is missing') if token.nil?
33
+
34
+ language ||= @language
35
+
36
+ body = { voice: File.new(file) }
37
+ body[:language] = language unless language.nil?
38
+ body[:conversation_token] = conversation_token unless conversation_token.nil?
39
+ body[:memory] = memory unless memory.nil?
40
+ response = HTTMultiParty.post(
41
+ Utils::CONVERSE_ENDPOINT,
42
+ body: body,
43
+ headers: { 'Authorization' => "Token #{token}" }
44
+ )
45
+ raise RecastError.new(JSON.parse(response.body)['message']) if response.code != 200
46
+
47
+ Conversation.new(response.body, token)
48
+ end
49
+ end
50
+ end
@@ -1,7 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- ##
4
- # This class builds an action used by RecastAI:::Conversation
5
3
  module RecastAI
6
4
  class Action
7
5
  attr_reader :slug
@@ -0,0 +1,105 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative 'action'
4
+ require_relative 'entity'
5
+ require_relative 'intent'
6
+
7
+ module RecastAI
8
+ class Conversation
9
+ attr_reader :raw, :uuid, :source, :replies, :action, :next_actions, :memory, :entities, :intents,
10
+ :conversation_token, :language, :version, :timestamp, :status
11
+
12
+ def initialize(response, token)
13
+ @token = token
14
+
15
+ @raw = response
16
+
17
+ response = JSON.parse(response)
18
+ response = response['results']
19
+
20
+ @uuid = response['uuid']
21
+ @source = response['source']
22
+ @replies = response['replies']
23
+ @action = response['action'] ? Action.new(response['action']) : nil
24
+ @next_actions = response['next_actions'].map{ |i| Action.new(i) }
25
+ @memory = response['memory'].reject { |_, e| e.nil? }.map{ |n, e| Entity.new(n, e) }
26
+ @entities = response['entities'].flat_map{ |_, e| e.map{ |ee| Entity.new(n, ee) } }
27
+ @intents = response['intents'].map{ |i| Intent.new(i) }
28
+ @conversation_token = response['conversation_token']
29
+ @language = response['language']
30
+ @version = response['version']
31
+ @timestamp = response['timestamp']
32
+ @status = response['status']
33
+ end
34
+
35
+ def reply
36
+ @replies.any? ? @replies.first : nil
37
+ end
38
+
39
+ def next_action
40
+ @next_actions.any? ? @next_actions.first : nil
41
+ end
42
+
43
+ def joined_replies(sep = ' ')
44
+ @replies.join(sep)
45
+ end
46
+
47
+ def get_memory(key = nil)
48
+ return @memory if key.nil?
49
+
50
+ @memory.each do |entity|
51
+ return entity if entity.name.casecmp(key.to_s).zero?
52
+ end
53
+
54
+ nil
55
+ end
56
+
57
+ def intent
58
+ @intents.any? ? @intents.first : nil
59
+ end
60
+
61
+ def set_memory(memory)
62
+ body = { conversation_token: @conversation_token, memory: memory }
63
+ response = HTTParty.put(
64
+ Utils::CONVERSE_ENDPOINT,
65
+ body: body,
66
+ headers: { 'Authorization' => "Token #{@token}" }
67
+ )
68
+ raise RecastError.new(JSON.parse(response.body)['message']) if response.code != 200
69
+
70
+ response = JSON.parse(response.body)
71
+ response = response['results']
72
+ response['memory'].reject { |_, e| e.nil? }.map { |n, e| Entity.new(n, e) }
73
+ end
74
+
75
+ def reset_memory(name = nil)
76
+ body = { conversation_token: @conversation_token }
77
+ body[:memory] = { name => nil } unless name.nil?
78
+
79
+ response = HTTParty.put(
80
+ Utils::CONVERSE_ENDPOINT,
81
+ body: body,
82
+ headers: { 'Authorization' => "Token #{@token}" }
83
+ )
84
+ raise RecastError.new(JSON.parse(response.body)['message']) if response.code != 200
85
+
86
+ response = JSON.parse(response.body)
87
+ response = response['results']
88
+ response['memory'].reject { |_, e| e.nil? }.map { |n, e| Entity.new(n, e) }
89
+ end
90
+
91
+ def reset_conversation
92
+ body = { conversation_token: @conversation_token }
93
+ response = HTTParty.delete(
94
+ Utils::CONVERSE_ENDPOINT,
95
+ body: body,
96
+ headers: { 'Authorization' => "Token #{@token}" }
97
+ )
98
+ raise RecastError.new(JSON.parse(response.body)['message']) if response.code != 200
99
+
100
+ response = JSON.parse(response.body)
101
+ response = response['results']
102
+ response['memory'].reject { |_, e| e.nil? }.map { |n, e| Entity.new(n, e) }
103
+ end
104
+ end
105
+ end
@@ -1,7 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- ##
4
- # This class build an Entity used in RecastAI::Response and RecastAI::Conversation
5
3
  module RecastAI
6
4
  class Entity
7
5
  attr_reader :name
@@ -9,8 +7,6 @@ module RecastAI
9
7
  def initialize(name, data)
10
8
  @name = name
11
9
 
12
- # For each pair key, value, set a instance variable
13
- # and an attr_reader named k and returning v
14
10
  data.each_pair do |k, v|
15
11
  self.instance_variable_set("@#{k}", v)
16
12
  self.define_singleton_method(k.to_sym){ v }
@@ -1,7 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- ##
4
- # This class builds an intent from RecastAI::Request and RecastAI::Conversation
5
3
  module RecastAI
6
4
  class Intent
7
5
  attr_reader :slug
@@ -0,0 +1,119 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative 'intent'
4
+ require_relative 'entity'
5
+ require_relative '../utils'
6
+
7
+ module RecastAI
8
+ class Response
9
+ attr_reader :raw
10
+ attr_reader :uuid
11
+ attr_reader :source
12
+ attr_reader :intents
13
+ attr_reader :act
14
+ attr_reader :type
15
+ attr_reader :sentiment
16
+ attr_reader :entities
17
+ attr_reader :language
18
+ attr_reader :version
19
+ attr_reader :timestamp
20
+ attr_reader :status
21
+
22
+ def initialize(response)
23
+ @raw = response
24
+
25
+ response = JSON.parse(response)
26
+ response = response['results']
27
+
28
+ @uuid = response['uuid']
29
+ @source = response['source']
30
+ @intents = response['intents'].map{ |i| Intent.new(i) }
31
+ @act = response['act']
32
+ @type = response['type']
33
+ @sentiment = response['sentiment']
34
+ @entities = response['entities'].flat_map{ |n, e| e.map{ |ee| Entity.new(n, ee) } }
35
+ @language = response['language']
36
+ @version = response['version']
37
+ @timestamp = response['timestamp']
38
+ @status = response['status']
39
+ end
40
+
41
+ def intent
42
+ @intents.any? ? @intents.first : nil
43
+ end
44
+
45
+ def get(name)
46
+ @entities.each do |entity|
47
+ return entity if entity.name.casecmp(name.to_s).zero?
48
+ end
49
+
50
+ nil
51
+ end
52
+
53
+ def all(name)
54
+ @entities.select do |entity|
55
+ entity.name.casecmp(name.to_s).zero?
56
+ end
57
+ end
58
+
59
+ def assert?
60
+ @act == Utils::ACT_ASSERT
61
+ end
62
+
63
+ def command?
64
+ @act == Utils::ACT_COMMAND
65
+ end
66
+
67
+ def wh_query?
68
+ @act == Utils::ACT_WH_QUERY
69
+ end
70
+
71
+ def yn_query?
72
+ @act == Utils::ACT_YN_QUERY
73
+ end
74
+
75
+ def abbreviation?
76
+ !@type.index(Utils::TYPE_ABBREVIATION).nil?
77
+ end
78
+
79
+ def entity?
80
+ !@type.index(Utils::TYPE_ENTITY).nil?
81
+ end
82
+
83
+ def description?
84
+ !@type.index(Utils::TYPE_DESCRIPTION).nil?
85
+ end
86
+
87
+ def human?
88
+ !@type.index(Utils::TYPE_HUMAN).nil?
89
+ end
90
+
91
+ def location?
92
+ !@type.index(Utils::TYPE_LOCATION).nil?
93
+ end
94
+
95
+ def number?
96
+ !@type.index(Utils::TYPE_NUMBER).nil?
97
+ end
98
+
99
+ def vpositive?
100
+ @sentiment == Utils::SENTIMENT_VPOSITIVE
101
+ end
102
+
103
+ def positive?
104
+ @sentiment == Utils::SENTIMENT_POSITIVE
105
+ end
106
+
107
+ def neutral?
108
+ @sentiment == Utils::SENTIMENT_NEUTRAL
109
+ end
110
+
111
+ def negative?
112
+ @sentiment == Utils::SENTIMENT_NEGATIVE
113
+ end
114
+
115
+ def vnegative?
116
+ @sentiment == Utils::SENTIMENT_VNEGATIVE
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative 'analyse'
4
+ require_relative 'converse'
5
+
6
+ module RecastAI
7
+ class Request
8
+ include Converse
9
+ include Analyse
10
+
11
+ attr_reader :token, :language
12
+
13
+ def initialize(token = nil, language = nil)
14
+ @token = token
15
+ @language = language
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ module RecastAI
4
+ class Utils
5
+ # Endpoints
6
+ REQUEST_ENDPOINT = 'https://api.recast.ai/v2/request/'.freeze
7
+ CONVERSE_ENDPOINT = 'https://api.recast.ai/v2/converse/'.freeze
8
+
9
+ # Act constants
10
+ ACT_ASSERT = 'assert'.freeze
11
+ ACT_COMMAND = 'command'.freeze
12
+ ACT_WH_QUERY = 'wh-query'.freeze
13
+ ACT_YN_QUERY = 'yn-query'.freeze
14
+
15
+ # Type constants
16
+ TYPE_ABBREVIATION = 'abbr:'.freeze
17
+ TYPE_ENTITY = 'enty:'.freeze
18
+ TYPE_DESCRIPTION = 'desc:'.freeze
19
+ TYPE_HUMAN = 'hum:'.freeze
20
+ TYPE_LOCATION = 'loc:'.freeze
21
+ TYPE_NUMBER = 'num:'.freeze
22
+
23
+ # Sentiment constants
24
+ SENTIMENT_VPOSITIVE = 'vpositive'.freeze
25
+ SENTIMENT_POSITIVE = 'positive'.freeze
26
+ SENTIMENT_NEUTRAL = 'neutral'.freeze
27
+ SENTIMENT_NEGATIVE = 'negative'.freeze
28
+ SENTIMENT_VNEGATIVE = 'vnegative'.freeze
29
+ end
30
+ end
@@ -3,34 +3,15 @@
3
3
  module RecastAI
4
4
  class Utils
5
5
  # Versioning
6
- MAJOR = '2'.freeze
7
- MINOR = '1'.freeze
8
- MICRO = '1'.freeze
6
+ MAJOR = '3'.freeze
7
+ MINOR = '0'.freeze
8
+ MICRO = '0'.freeze
9
9
  VERSION = "#{MAJOR}.#{MINOR}.#{MICRO}".freeze
10
10
 
11
11
  # Endpoints
12
- REQUEST_ENDPOINT = 'https://api.recast.ai/v2/request'.freeze
13
- CONVERSE_ENDPOINT = 'https://api.recast.ai/v2/converse'.freeze
14
-
15
- # Act constants
16
- ACT_ASSERT = 'assert'.freeze
17
- ACT_COMMAND = 'command'.freeze
18
- ACT_WH_QUERY = 'wh-query'.freeze
19
- ACT_YN_QUERY = 'yn-query'.freeze
20
-
21
- # Type constants
22
- TYPE_ABBREVIATION = 'abbr:'.freeze
23
- TYPE_ENTITY = 'enty:'.freeze
24
- TYPE_DESCRIPTION = 'desc:'.freeze
25
- TYPE_HUMAN = 'hum:'.freeze
26
- TYPE_LOCATION = 'loc:'.freeze
27
- TYPE_NUMBER = 'num:'.freeze
28
-
29
- # Sentiment constants
30
- SENTIMENT_VPOSITIVE = 'vpositive'.freeze
31
- SENTIMENT_POSITIVE = 'positive'.freeze
32
- SENTIMENT_NEUTRAL = 'neutral'.freeze
33
- SENTIMENT_NEGATIVE = 'negative'.freeze
34
- SENTIMENT_VNEGATIVE = 'vnegative'.freeze
12
+ TRAIN_ENDPOINT = 'https://api.recast.ai/v2/'.freeze
13
+ CONNECT_ENDPOINT = 'https://api.recast.ai/connect/v1/'.freeze
14
+ HOST_ENDPOINT = 'https://api.recast.ai/host/v1/'.freeze
15
+ MONITOR_ENDPOINT = 'https://api.recast.ai/monitor/v1/'.freeze
35
16
  end
36
17
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: RecastAI
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Renvoisé
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-14 00:00:00.000000000 Z
11
+ date: 2017-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -113,13 +113,20 @@ files:
113
113
  - bin/file
114
114
  - bin/text
115
115
  - lib/recastai.rb
116
- - lib/recastai/action.rb
117
- - lib/recastai/client.rb
118
- - lib/recastai/conversation.rb
119
- - lib/recastai/entity.rb
120
- - lib/recastai/errors.rb
121
- - lib/recastai/intent.rb
122
- - lib/recastai/response.rb
116
+ - lib/recastai/apis/connect/connect.rb
117
+ - lib/recastai/apis/connect/message.rb
118
+ - lib/recastai/apis/connect/models/message.rb
119
+ - lib/recastai/apis/connect/utils.rb
120
+ - lib/recastai/apis/errors.rb
121
+ - lib/recastai/apis/request/analyse.rb
122
+ - lib/recastai/apis/request/converse.rb
123
+ - lib/recastai/apis/request/models/action.rb
124
+ - lib/recastai/apis/request/models/conversation.rb
125
+ - lib/recastai/apis/request/models/entity.rb
126
+ - lib/recastai/apis/request/models/intent.rb
127
+ - lib/recastai/apis/request/models/response.rb
128
+ - lib/recastai/apis/request/request.rb
129
+ - lib/recastai/apis/request/utils.rb
123
130
  - lib/recastai/utils.rb
124
131
  - misc/.gitkeep
125
132
  - misc/logo-inline.png
@@ -145,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
152
  version: '0'
146
153
  requirements: []
147
154
  rubyforge_project:
148
- rubygems_version: 2.5.1
155
+ rubygems_version: 2.5.2
149
156
  signing_key:
150
157
  specification_version: 4
151
158
  summary: Recast.AI official SDK for Ruby
@@ -1,104 +0,0 @@
1
- # encoding: utf-8
2
-
3
- ##
4
- # This class is the main entrypoint to Recast.AI
5
- # When using *_converse, a RecastAI::Conversation object is returned
6
- # When using *_request, a RecastAI::Response object is returned
7
- module RecastAI
8
- class Client
9
- attr_accessor :token
10
- attr_accessor :language
11
-
12
- def initialize(token = nil, language = nil)
13
- @token = token
14
- @language = language
15
- end
16
-
17
- ##
18
- # Perform a text converse to Recast.AI
19
- #
20
- # * *Args* :
21
- # - +text+ - String, the text to process
22
- # - +options+ - Hash, request's options
23
- # * *Returns* :
24
- # - An instance of Conversation
25
- # * *Throws* :
26
- # - RecastError
27
- def text_converse(text, options = {})
28
- token = options[:token] || @token
29
- raise(RecastError.new('Token is missing')) if token.nil?
30
-
31
- language = options[:language] || @language
32
-
33
- body = { text: text }
34
- body[:language] = language unless language.nil?
35
- body[:conversation_token] = options[:conversation_token] unless options[:conversation_token].nil?
36
- body[:memory] = options[:memory] unless options[:memory].nil?
37
-
38
- response = HTTParty.post(
39
- Utils::CONVERSE_ENDPOINT,
40
- body: body,
41
- headers: { Authorization: "Token #{token}" }
42
- )
43
- raise(RecastError.new(response.message)) if response.code != 200
44
-
45
- Conversation.new(response.body)
46
- end
47
-
48
- ##
49
- # Perform a text request to Recast.AI
50
- #
51
- # * *Args* :
52
- # - +text+ - String, the text to process
53
- # - +options+ - Hash, request's options
54
- # * *Returns* :
55
- # - An instance of Response
56
- # * *Throws* :
57
- # - RecastError
58
- def text_request(text, options = {})
59
- token = options[:token] || @token
60
- raise(RecastError.new('Token is missing')) if token.nil?
61
-
62
- language = options[:language] || @language
63
-
64
- body = { text: text }
65
- body[:language] = language unless language.nil?
66
- response = HTTParty.post(
67
- Utils::REQUEST_ENDPOINT,
68
- body: body,
69
- headers: { Authorization: "Token #{token}" }
70
- )
71
- raise(RecastError.new(response.message)) if response.code != 200
72
-
73
- Response.new(response.body)
74
- end
75
-
76
- ##
77
- # Perform a voice file request to Recast.AI
78
- #
79
- # * *Args* :
80
- # - +file+ - String or File, the voice file to process
81
- # - +options+ - Hash, request's options
82
- # * *Returns* :
83
- # - An instance of Response
84
- # * *Throws* :
85
- # - RecastError
86
- def file_request(file, options = {})
87
- token = options[:token] || @token
88
- raise(RecastError.new('Token is missing')) if token.nil?
89
-
90
- language = options[:language] || @language
91
-
92
- body = { voice: File.new(file) }
93
- body[:language] = language unless language.nil?
94
- response = HTTMultiParty.post(
95
- Utils::REQUEST_ENDPOINT,
96
- body: body,
97
- headers: { Authorization: "Token #{token}" }
98
- )
99
- raise(RecastError.new(response.message)) if response.code != 200
100
-
101
- Response.new(response.body)
102
- end
103
- end
104
- end
@@ -1,182 +0,0 @@
1
- # encoding: utf-8
2
-
3
- ##
4
- # This class builds a conversation from *_converse
5
- module RecastAI
6
- class Conversation
7
- attr_reader :raw
8
- attr_reader :uuid
9
- attr_reader :source
10
- attr_reader :replies
11
- attr_reader :action
12
- attr_reader :next_actions
13
- attr_reader :memory
14
- attr_reader :entities
15
- attr_reader :intents
16
- attr_reader :conversation_token
17
- attr_reader :language
18
- attr_reader :version
19
- attr_reader :timestamp
20
- attr_reader :status
21
-
22
- def initialize(response)
23
- @raw = response
24
-
25
- response = JSON.parse(response)
26
- response = response['results']
27
-
28
- @uuid = response['uuid']
29
- @source = response['source']
30
- @replies = response['replies']
31
- @action = response['action'] ? Action.new(response['action']) : nil
32
- @next_actions = response['next_actions'].map{ |i| Action.new(i) }
33
- @memory = response['memory'].select{ |n, e| !e.nil? }.map{ |n, e| Entity.new(n, e) }
34
- @entities = response['entities'].flat_map{ |n, e| e.map{ |ee| Entity.new(n, ee) } }
35
- @intents = response['intents'].map{ |i| Intent.new(i) }
36
- @conversation_token = response['conversation_token']
37
- @language = response['language']
38
- @version = response['version']
39
- @timestamp = response['timestamp']
40
- @status = response['status']
41
- end
42
-
43
- ##
44
- # Returns the first reply provided there is one
45
- #
46
- # * *Args* :
47
- # * *Returns* :
48
- # - A String or nil
49
- def reply
50
- @replies.any? ? @replies.first : nil
51
- end
52
-
53
- ##
54
- # Returns the first next action provided there is one
55
- #
56
- # * *Args* :
57
- # * *Returns* :
58
- # - An instance of Action or nil
59
- def next_action
60
- @next_actions.any? ? @next_actions.first : nil
61
- end
62
-
63
- ##
64
- # Returns the replies joined with sep
65
- #
66
- # * *Args* :
67
- # - +sep+ - String, the separator (default: ' ')
68
- # * *Returns* :
69
- # - A String or nil
70
- def joined_replies(sep=' ')
71
- @replies.join(sep)
72
- end
73
-
74
- ##
75
- # Returns the first entity in the memory name matches the parameter
76
- # If no name is provided, returns the full memory
77
- #
78
- # * *Args* :
79
- # - +key+ - String, the memory's field name
80
- # * *Returns* :
81
- # - An instance of Entity or a Memory
82
- def get_memory(key=nil)
83
- return @memory if key.nil?
84
-
85
- @memory.each do |entity|
86
- return entity if entity.name.casecmp(key.to_s) == 0
87
- end
88
-
89
- nil
90
- end
91
-
92
- ##
93
- # Returns the first intent provided there is one
94
- #
95
- # * *Args* :
96
- # * *Returns* :
97
- # - A String or nil
98
- def intent
99
- @intents.any? ? @intents.first : nil
100
- end
101
-
102
- class << self
103
- ##
104
- # Merges the conversation memory with the one given
105
- #
106
- # * *Args* :
107
- # - +token+ - String, your request_token
108
- # - +conversation_token+ String, the token of the conversation whose memory will be updated
109
- # - +memory+ Hash, the memory you want to update with
110
- # * *Returns* :
111
- # - An updated Memory
112
- # * *Throws* :
113
- # - RecastError
114
- def set_memory(token, conversation_token, memory)
115
- body = { conversation_token: conversation_token, memory: memory }
116
- response = HTTParty.put(
117
- Utils::CONVERSE_ENDPOINT,
118
- body: body,
119
- headers: { Authorization: "Token #{token}" }
120
- )
121
- raise(RecastError.new(response.message)) if response.code != 200
122
-
123
- response = JSON.parse(response.body)
124
- response = response['results']
125
- response['memory'].select{ |n, e| !e.nil? }.map{ |n, e| Entity.new(n, e) }
126
- end
127
-
128
- ##
129
- # Reset the conversation memory fully or partially with the one given
130
- #
131
- # * *Args* :
132
- # - +token+ - String, your request_token
133
- # - +conversation_token+ String, the token of the conversation whose memory will be updated
134
- # - +memory+ Hash, the memory you want to update with
135
- # * *Returns* :
136
- # - A fully or partially reset Memory
137
- # * *Throws* :
138
- # - RecastError
139
- def reset_memory(token, conversation_token, name=nil)
140
- body = { conversation_token: conversation_token }
141
- unless name.nil?
142
- body[:memory] = { name => nil }
143
- end
144
- response = HTTParty.put(
145
- Utils::CONVERSE_ENDPOINT,
146
- body: body,
147
- headers: { Authorization: "Token #{token}" }
148
- )
149
- raise(RecastError.new(response.message)) if response.code != 200
150
-
151
- response = JSON.parse(response.body)
152
- response = response['results']
153
- response['memory'].select{ |n, e| !e.nil? }.map{ |n, e| Entity.new(n, e) }
154
- end
155
-
156
- ##
157
- # Resets the conversation state by setting every memory field to nil,
158
- # all actions to not done, and the last action to nil
159
- #
160
- # * *Args* :
161
- # - +token+ - String, your request_token
162
- # - +conversation_token+ - String, the token of the conversation to reset
163
- # * *Returns* :
164
- # - A fully reset Memory
165
- # * *Throws* :
166
- # - RecastError
167
- def reset_conversation(token, conversation_token)
168
- body = { conversation_token: conversation_token }
169
- response = HTTParty.delete(
170
- Utils::CONVERSE_ENDPOINT,
171
- body: body,
172
- headers: { Authorization: "Token #{token}" }
173
- )
174
- raise(RecastError.new(response.message)) if response.code != 200
175
-
176
- response = JSON.parse(response.body)
177
- response = response['results']
178
- response['memory'].select{ |n, e| !e.nil? }.map{ |n, e| Entity.new(n, e) }
179
- end
180
- end
181
- end
182
- end
@@ -1,227 +0,0 @@
1
- # encoding: utf-8
2
-
3
- ##
4
- # This class builds a response from *_request
5
- module RecastAI
6
- class Response
7
- attr_reader :raw
8
- attr_reader :uuid
9
- attr_reader :source
10
- attr_reader :intents
11
- attr_reader :act
12
- attr_reader :type
13
- attr_reader :sentiment
14
- attr_reader :entities
15
- attr_reader :language
16
- attr_reader :version
17
- attr_reader :timestamp
18
- attr_reader :status
19
-
20
- def initialize(response)
21
- @raw = response
22
-
23
- response = JSON.parse(response)
24
- response = response['results']
25
-
26
- @uuid = response['uuid']
27
- @source = response['source']
28
- @intents = response['intents'].map{ |i| Intent.new(i) }
29
- @act = response['act']
30
- @type = response['type']
31
- @sentiment = response['sentiment']
32
- @entities = response['entities'].flat_map{ |n, e| e.map{ |ee| Entity.new(n, ee) } }
33
- @language = response['language']
34
- @version = response['version']
35
- @timestamp = response['timestamp']
36
- @status = response['status']
37
- end
38
-
39
- ##
40
- # Returns the first intent provided there is one
41
- #
42
- # * *Args* :
43
- # * *Returns* :
44
- # - A String or nil
45
- def intent
46
- @intents.any? ? @intents.first : nil
47
- end
48
-
49
- ##
50
- # Returns the first entity whose name matches the parameter
51
- #
52
- # * *Args* :
53
- # - +name+ - String, the entity's name
54
- # * *Returns* :
55
- # - An instance of Entity or nil
56
- def get(name)
57
- @entities.each do |entity|
58
- return entity if entity.name.casecmp(name.to_s) == 0
59
- end
60
-
61
- nil
62
- end
63
-
64
- ##
65
- # Returns all entities whose names matches the parameter
66
- #
67
- # * *Args* :
68
- # - +name+ - String, the entities' names
69
- # * *Returns* :
70
- # - An array of instances of Entity or an empty array
71
- def all(name)
72
- @entities.select do |entity|
73
- entity.name.casecmp(name.to_s) == 0
74
- end
75
- end
76
-
77
- ##
78
- # Return whether or not the act is an assertion
79
- #
80
- # + *Args* :
81
- # + *Returns* :
82
- # - True or False
83
- def assert?
84
- @act == Utils::ACT_ASSERT
85
- end
86
-
87
- ##
88
- # Return whether or not the act is a command
89
- #
90
- # + *Args* :
91
- # + *Returns* :
92
- # - True or False
93
- def command?
94
- @act == Utils::ACT_COMMAND
95
- end
96
-
97
- ##
98
- # Return whether or not the act is a wh-query
99
- #
100
- # + *Args* :
101
- # + *Returns* :
102
- # - True or False
103
- def wh_query?
104
- @act == Utils::ACT_WH_QUERY
105
- end
106
-
107
- ##
108
- # Return whether or not the act is a yn-query
109
- #
110
- # + *Args* :
111
- # + *Returns* :
112
- # - True or False
113
- def yn_query?
114
- @act == Utils::ACT_YN_QUERY
115
- end
116
-
117
- ##
118
- # Return whether or not the type is an abbreviation
119
- #
120
- # + *Args* :
121
- # + *Returns* :
122
- # - True or False
123
- def abbreviation?
124
- !@type.index(Utils::TYPE_ABBREVIATION).nil?
125
- end
126
-
127
- ##
128
- # Return whether or not the type is an entity
129
- #
130
- # + *Args* :
131
- # + *Returns* :
132
- # - True or False
133
- def entity?
134
- !@type.index(Utils::TYPE_ENTITY).nil?
135
- end
136
-
137
- ##
138
- # Return whether or not the type is a description
139
- #
140
- # + *Args* :
141
- # + *Returns* :
142
- # - True or False
143
- def description?
144
- !@type.index(Utils::TYPE_DESCRIPTION).nil?
145
- end
146
-
147
- ##
148
- # Return whether or not the type is a human
149
- #
150
- # + *Args* :
151
- # + *Returns* :
152
- # - True or False
153
- def human?
154
- !@type.index(Utils::TYPE_HUMAN).nil?
155
- end
156
-
157
- ##
158
- # Return whether or not the type is a location
159
- #
160
- # + *Args* :
161
- # + *Returns* :
162
- # - True or False
163
- def location?
164
- !@type.index(Utils::TYPE_LOCATION).nil?
165
- end
166
-
167
- ##
168
- # Return whether or not the type is a number
169
- #
170
- # + *Args* :
171
- # + *Returns* :
172
- # - True or False
173
- def number?
174
- !@type.index(Utils::TYPE_NUMBER).nil?
175
- end
176
-
177
- ##
178
- # Return whether or not the sentiment is very positive
179
- #
180
- # + *Args* :
181
- # + *Returns* :
182
- # - True or False
183
- def vpositive?
184
- @sentiment == Utils::SENTIMENT_VPOSITIVE
185
- end
186
-
187
- ##
188
- # Return whether or not the sentiment is positive
189
- #
190
- # + *Args* :
191
- # + *Returns* :
192
- # - True or False
193
- def positive?
194
- @sentiment == Utils::SENTIMENT_POSITIVE
195
- end
196
-
197
- ##
198
- # Return whether or not the sentiment is neutral
199
- #
200
- # + *Args* :
201
- # + *Returns* :
202
- # - True or False
203
- def neutral?
204
- @sentiment == Utils::SENTIMENT_NEUTRAL
205
- end
206
-
207
- ##
208
- # Return whether or not the sentiment is negative
209
- #
210
- # + *Args* :
211
- # + *Returns* :
212
- # - True or False
213
- def negative?
214
- @sentiment == Utils::SENTIMENT_NEGATIVE
215
- end
216
-
217
- ##
218
- # Return whether or not the sentiment is very negative
219
- #
220
- # + *Args* :
221
- # + *Returns* :
222
- # - True or False
223
- def vnegative?
224
- @sentiment == Utils::SENTIMENT_VNEGATIVE
225
- end
226
- end
227
- end