RecastAI 2.1.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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