Sapcai 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +26 -0
- data/.rspec +2 -0
- data/.rubocop.yml +14 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +67 -0
- data/LICENSE +21 -0
- data/README.md +76 -0
- data/bin/sapcaicli +39 -0
- data/lib/sapcai.rb +27 -0
- data/lib/sapcai/apis/build/build.rb +76 -0
- data/lib/sapcai/apis/build/dialog_conversation.rb +13 -0
- data/lib/sapcai/apis/build/dialog_message.rb +17 -0
- data/lib/sapcai/apis/build/dialog_response.rb +17 -0
- data/lib/sapcai/apis/connect/connect.rb +16 -0
- data/lib/sapcai/apis/connect/message.rb +44 -0
- data/lib/sapcai/apis/connect/models/message.rb +20 -0
- data/lib/sapcai/apis/connect/utils.rb +9 -0
- data/lib/sapcai/apis/errors.rb +6 -0
- data/lib/sapcai/apis/request/analyse.rb +27 -0
- data/lib/sapcai/apis/request/converse.rb +50 -0
- data/lib/sapcai/apis/request/models/action.rb +19 -0
- data/lib/sapcai/apis/request/models/conversation.rb +128 -0
- data/lib/sapcai/apis/request/models/entity.rb +16 -0
- data/lib/sapcai/apis/request/models/intent.rb +13 -0
- data/lib/sapcai/apis/request/models/response.rb +119 -0
- data/lib/sapcai/apis/request/request.rb +18 -0
- data/lib/sapcai/apis/request/utils.rb +30 -0
- data/lib/sapcai/utils.rb +18 -0
- data/misc/.gitkeep +0 -0
- data/misc/logo-inline.png +0 -0
- data/misc/recast-ai-tokens.png +0 -0
- data/recastai.gemspec +30 -0
- metadata +161 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9e47964ce4e02cec9d7da03829d841a75453b96aa4d6af59f30835a7a019c3cc
|
4
|
+
data.tar.gz: 78541aae03f89f1f90269261b68b8c6646da70aad56046e18726b5ad6db67355
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c8c6cd91f3ecb5247bdd8569db561cbd5a009b43cf2e3dd227b4252ced1ebfc74eea987915532789fb7e9b38cfe5ee51cbe5ac97e9e6f0dd1977bb897a197c0d
|
7
|
+
data.tar.gz: 1220701dc3be3056758d54f3da07dac8785ec839c7a652e8e2b99cbd1525d940edad41bc14df2d3a9c805eb0791b8d5c61e82c3102dc931432583a8082433085
|
data/.gitignore
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Default
|
2
|
+
cache
|
3
|
+
log/*.log
|
4
|
+
VM/*.log
|
5
|
+
tmp/**/*
|
6
|
+
public/system/**
|
7
|
+
public/uploads/
|
8
|
+
db/schema.rb
|
9
|
+
dump.rdb
|
10
|
+
coverage/
|
11
|
+
|
12
|
+
# Configuration
|
13
|
+
config/application.yml
|
14
|
+
config/database.yml
|
15
|
+
config/secrets.yml
|
16
|
+
|
17
|
+
# OS-Generated
|
18
|
+
.DS_Store
|
19
|
+
|
20
|
+
# IDE-Generated
|
21
|
+
.idea/
|
22
|
+
.bashrc
|
23
|
+
|
24
|
+
# Misc
|
25
|
+
*~
|
26
|
+
.ruby-version
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Metrics/LineLength:
|
2
|
+
Max: 9999
|
3
|
+
Metrics/MethodLength:
|
4
|
+
Max: 9999
|
5
|
+
Style/Documentation:
|
6
|
+
Enabled: false
|
7
|
+
Style/SpaceBeforeBlockBraces:
|
8
|
+
EnforcedStyle: no_space
|
9
|
+
Style/RedundantSelf:
|
10
|
+
Enabled: false
|
11
|
+
Style/WordArray:
|
12
|
+
Enabled: false
|
13
|
+
Style/RaiseArgs:
|
14
|
+
EnforcedStyle: compact
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
Sapcai (4.0.0)
|
5
|
+
httmultiparty (~> 0.3)
|
6
|
+
httparty (~> 0.13)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
addressable (2.4.0)
|
12
|
+
awesome_print (1.6.1)
|
13
|
+
crack (0.4.3)
|
14
|
+
safe_yaml (~> 1.0.0)
|
15
|
+
diff-lcs (1.2.5)
|
16
|
+
docile (1.3.1)
|
17
|
+
hashdiff (0.3.0)
|
18
|
+
httmultiparty (0.3.16)
|
19
|
+
httparty (>= 0.7.3)
|
20
|
+
mimemagic
|
21
|
+
multipart-post
|
22
|
+
httparty (0.16.3)
|
23
|
+
mime-types (~> 3.0)
|
24
|
+
multi_xml (>= 0.5.2)
|
25
|
+
json (2.1.0)
|
26
|
+
mime-types (3.2.2)
|
27
|
+
mime-types-data (~> 3.2015)
|
28
|
+
mime-types-data (3.2018.0812)
|
29
|
+
mimemagic (0.3.2)
|
30
|
+
multi_xml (0.6.0)
|
31
|
+
multipart-post (2.0.0)
|
32
|
+
rspec (3.4.0)
|
33
|
+
rspec-core (~> 3.4.0)
|
34
|
+
rspec-expectations (~> 3.4.0)
|
35
|
+
rspec-mocks (~> 3.4.0)
|
36
|
+
rspec-core (3.4.4)
|
37
|
+
rspec-support (~> 3.4.0)
|
38
|
+
rspec-expectations (3.4.0)
|
39
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
40
|
+
rspec-support (~> 3.4.0)
|
41
|
+
rspec-mocks (3.4.1)
|
42
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
43
|
+
rspec-support (~> 3.4.0)
|
44
|
+
rspec-support (3.4.1)
|
45
|
+
safe_yaml (1.0.4)
|
46
|
+
simplecov (0.16.1)
|
47
|
+
docile (~> 1.1)
|
48
|
+
json (>= 1.8, < 3)
|
49
|
+
simplecov-html (~> 0.10.0)
|
50
|
+
simplecov-html (0.10.2)
|
51
|
+
webmock (1.24.2)
|
52
|
+
addressable (>= 2.3.6)
|
53
|
+
crack (>= 0.3.2)
|
54
|
+
hashdiff
|
55
|
+
|
56
|
+
PLATFORMS
|
57
|
+
ruby
|
58
|
+
|
59
|
+
DEPENDENCIES
|
60
|
+
Sapcai!
|
61
|
+
awesome_print (~> 1.6)
|
62
|
+
rspec (~> 3.4)
|
63
|
+
simplecov (~> 0.15)
|
64
|
+
webmock (~> 1.24)
|
65
|
+
|
66
|
+
BUNDLED WITH
|
67
|
+
1.17.1
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 SAP Conversational AI
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
[logo]: https://cdn.cai.tools.sap/brand/sapcai/sap-cai-black.svg "SAP Conversational AI"
|
4
|
+
|
5
|
+
![alt text][logo]
|
6
|
+
|
7
|
+
# SAP Conversational AI - SDK Ruby
|
8
|
+
|
9
|
+
SAP Conversational AI official SDK in Ruby
|
10
|
+
|
11
|
+
## Synospis
|
12
|
+
|
13
|
+
This module is a wrapper around the [SAP Conversational AI](https://cai.tools.sap) API, and allows you to:
|
14
|
+
* [Analyse your text](https://github.com/SAPConversationalAI/SDK-Ruby/wiki/01---Analyse-text)
|
15
|
+
* [Manage a conversation](https://github.com/SAPConversationalAI/SDK-Ruby/wiki/02---Manage-conversation)
|
16
|
+
* [Receive and send messages](https://github.com/SAPConversationalAI/SDK-Ruby/wiki/03---Receive-and-send-messages)
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
This gem supports ruby 2.3+.
|
21
|
+
|
22
|
+
```bash
|
23
|
+
gem install Sapcai
|
24
|
+
```
|
25
|
+
|
26
|
+
You can now use the SDK in your code. All you need is your bot's token. In case you have enabled our versioning feature in the settings of your bot, you can refer to our [versioning documentation](https://cai.tools.sap/docs/concepts/versioning) to learn how to select the appropriate token for you versions and environments.
|
27
|
+
|
28
|
+
Using the entire SDK:
|
29
|
+
```ruby
|
30
|
+
require 'sapcai'
|
31
|
+
|
32
|
+
client = Sapcai::Client.new('YOUR_TOKEN')
|
33
|
+
|
34
|
+
client.request.analyse_text('Hi')
|
35
|
+
client.connect.broadcast_message('Hello')
|
36
|
+
```
|
37
|
+
|
38
|
+
Extracting one single API:
|
39
|
+
```ruby
|
40
|
+
require 'sapcai'
|
41
|
+
|
42
|
+
request = Sapcai::Request.new('YOUR_TOKEN')
|
43
|
+
request.analyse_text('Hi')
|
44
|
+
|
45
|
+
connect = Sapcai::Connect.new('YOUR_TOKEN')
|
46
|
+
connect.broadcast_message('Hi')
|
47
|
+
```
|
48
|
+
|
49
|
+
## More
|
50
|
+
|
51
|
+
You can view the whole API reference at [cai.tools.sap/docs/](https://cai.tools.sap/docs/api-reference).
|
52
|
+
|
53
|
+
You can follow us on Twitter at [@sapcai](https://twitter.com/sapcai) for updates and releases.
|
54
|
+
|
55
|
+
|
56
|
+
## License
|
57
|
+
|
58
|
+
Copyright (c) [2019] [SAP Conversational AI](https://cai.tools.sap)
|
59
|
+
|
60
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
61
|
+
of this software and associated documentation files (the "Software"), to deal
|
62
|
+
in the Software without restriction, including without limitation the rights
|
63
|
+
to tsuse, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
64
|
+
copies of the Software, and to permit persons to whom the Software is
|
65
|
+
furnished to do so, subject to the following conditions:
|
66
|
+
|
67
|
+
The above copyright notice and this permission notice shall be included in all
|
68
|
+
copies or substantial portions of the Software.
|
69
|
+
|
70
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
71
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
72
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
73
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
74
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
75
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
76
|
+
SOFTWARE.
|
data/bin/sapcaicli
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
require_relative '../lib/sapcai'
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.banner = "Usage: sapcaicli -[-t]oken TOKEN <--text TEXT | --file FILE>"
|
10
|
+
|
11
|
+
opts.on('-t', '--token=TOKEN', String, "the request token to use for the call") do |t|
|
12
|
+
options[:token] = t
|
13
|
+
end
|
14
|
+
|
15
|
+
opts.on('--text=TEXT', String, 'the text to process') do |t|
|
16
|
+
options[:text] = t
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on('--file=FILE', String, 'the file to process') do |f|
|
20
|
+
options[:file] = f
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on("-h", "--help", "Prints this help") do
|
24
|
+
puts opts
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
end.parse!
|
28
|
+
|
29
|
+
client = Sapcai::Client.new(options[:token])
|
30
|
+
|
31
|
+
if options[:text]
|
32
|
+
response = client.request.analyse_text(options[:text])
|
33
|
+
elsif options[:file]
|
34
|
+
response = client.request.analyse_file(options[:file])
|
35
|
+
else
|
36
|
+
raise OptionParser::MissingArgument.new('You need to give either --text or --file')
|
37
|
+
end
|
38
|
+
|
39
|
+
puts response.intent
|
data/lib/sapcai.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require 'json'
|
6
|
+
require 'httparty'
|
7
|
+
require 'httmultiparty'
|
8
|
+
|
9
|
+
require 'sapcai/utils'
|
10
|
+
require 'sapcai/apis/connect/connect'
|
11
|
+
require 'sapcai/apis/request/request'
|
12
|
+
require 'sapcai/apis/build/build'
|
13
|
+
|
14
|
+
module Sapcai
|
15
|
+
class Client
|
16
|
+
attr_reader :token, :language
|
17
|
+
|
18
|
+
def initialize(token = nil, language = nil)
|
19
|
+
[Sapcai::Request, Sapcai::Connect, Sapcai::Build].each do |api|
|
20
|
+
i = api.name.rindex('::')
|
21
|
+
name = i.nil? ? api.name : api.name[(i + 2)..-1]
|
22
|
+
|
23
|
+
self.class.send(:define_method, name.downcase.to_sym, ->{ api.new(token, language) })
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'httparty'
|
4
|
+
|
5
|
+
require_relative 'dialog_response'
|
6
|
+
require_relative 'dialog_message'
|
7
|
+
require_relative 'dialog_conversation'
|
8
|
+
|
9
|
+
module Sapcai
|
10
|
+
class Build
|
11
|
+
attr_reader :token, :language
|
12
|
+
|
13
|
+
def initialize(token = nil, language = nil)
|
14
|
+
@token = token
|
15
|
+
@language = language
|
16
|
+
end
|
17
|
+
|
18
|
+
def headers
|
19
|
+
{ 'Authorization' => "Token #{@token}", 'Content-Type' => 'application/json' }
|
20
|
+
end
|
21
|
+
|
22
|
+
def dialog(msg, conversation_id, language = nil, options = {})
|
23
|
+
raise Sapcai::SapcaiError.new('Token is missing') unless @token
|
24
|
+
|
25
|
+
log_level = options[:log_level] || "info"
|
26
|
+
proxy = options[:proxy] || {}
|
27
|
+
|
28
|
+
language = @language if language.nil?
|
29
|
+
body = { message: msg, conversation_id: conversation_id, language: language, log_level: log_level}
|
30
|
+
body[:memory] = options[:memory] unless options[:memory].nil?
|
31
|
+
|
32
|
+
options = { body: body.to_json, headers: self.headers }
|
33
|
+
if proxy != {}
|
34
|
+
options[:http_proxyaddr] = proxy[:host]
|
35
|
+
options[:http_proxyport] = proxy[:port]
|
36
|
+
end
|
37
|
+
response = HTTParty.post("#{Sapcai::Utils::BUILD_ENDPOINT}/dialog", options)
|
38
|
+
raise Sapcai::SapcaiError.new(JSON.parse(response.body)['message']) if response.code != 200
|
39
|
+
|
40
|
+
res = JSON.parse(response.body)['results']
|
41
|
+
Sapcai::DialogResponse.new(res['messages'], res['conversation'], res['nlp'], res['logs'])
|
42
|
+
end
|
43
|
+
|
44
|
+
def update_conversation(user, bot, version, conversation_id, opts)
|
45
|
+
raise Sapcai::SapcaiError.new('Token is missing') unless @token
|
46
|
+
|
47
|
+
body = opts
|
48
|
+
|
49
|
+
url = "#{Sapcai::Utils::BUILD_ENDPOINT}/users/#{user}/bots/#{bot}/versions/#{version}/builder/conversation_states/#{conversation_id}"
|
50
|
+
response = HTTParty.put(url, body: body.to_json, headers: self.headers)
|
51
|
+
raise Sapcai::SapcaiError.new(JSON.parse(response.body)['message']) if response.code != 200
|
52
|
+
|
53
|
+
Sapcai::DialogConversation.new(JSON.parse(response.body)['results'])
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_conversation(user, bot, version, conversation_id)
|
57
|
+
raise Sapcai::SapcaiError.new('Token is missing') unless @token
|
58
|
+
|
59
|
+
url = "#{Sapcai::Utils::BUILD_ENDPOINT}/users/#{user}/bots/#{bot}/versions/#{version}/builder/conversation_states/#{conversation_id}"
|
60
|
+
response = HTTParty.get(url, headers: self.headers)
|
61
|
+
raise Sapcai::SapcaiError.new(JSON.parse(response.body)['message']) if response.code != 200
|
62
|
+
|
63
|
+
Sapcai::DialogConversation.new(JSON.parse(response.body)['results'])
|
64
|
+
end
|
65
|
+
|
66
|
+
def delete_conversation(user, bot, version, conversation_id)
|
67
|
+
raise Sapcai::SapcaiError.new('Token is missing') unless @token
|
68
|
+
|
69
|
+
url = "#{Sapcai::Utils::BUILD_ENDPOINT}/users/#{user}/bots/#{bot}/versions/#{version}/builder/conversation_states/#{conversation_id}"
|
70
|
+
response = HTTParty.delete(url, headers: self.headers)
|
71
|
+
raise Sapcai::SapcaiError.new(JSON.parse(response.body)['message']) if response.code != 204
|
72
|
+
|
73
|
+
true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Sapcai
|
2
|
+
class DialogConversation
|
3
|
+
attr_reader :id, :language, :memory, :skill, :skill_occurences
|
4
|
+
|
5
|
+
def initialize(conv)
|
6
|
+
@id = conv['conversation_id'] || conv['id']
|
7
|
+
@language = conv['language']
|
8
|
+
@memory = conv['memory']
|
9
|
+
@skill = conv['skill'] || conv['last_skill']
|
10
|
+
@skill_occurences = conv['skill_occurences'] || skill['last_skill_occurences']
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Sapcai
|
2
|
+
class DialogMessage
|
3
|
+
attr_reader :type, :content
|
4
|
+
|
5
|
+
def initialize(msg)
|
6
|
+
raise Sapcai::SapcaiError('Invalid message format') unless message_is_valid(msg)
|
7
|
+
@type = msg['type']
|
8
|
+
@content = msg['content']
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def message_is_valid(msg)
|
14
|
+
msg.is_a?(Hash) && msg.key?('type') && msg.key?('content')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'dialog_message'
|
2
|
+
require_relative 'dialog_conversation'
|
3
|
+
require_relative '../request/models/response'
|
4
|
+
module Sapcai
|
5
|
+
class DialogResponse
|
6
|
+
attr_reader :messages, :conversation, :nlp, :logs
|
7
|
+
|
8
|
+
def initialize(messages, conversation, nlp, logs)
|
9
|
+
raise Sapcai::SapcaiError("Invalid messages format: #{messages}") unless messages.is_a?(Array)
|
10
|
+
|
11
|
+
@messages = messages.map{ |m| Sapcai::DialogMessage.new(m) }
|
12
|
+
@conversation = DialogConversation.new(conversation)
|
13
|
+
@nlp = Response.new('results' => nlp)
|
14
|
+
@logs = logs
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative 'models/message'
|
4
|
+
require_relative 'utils'
|
5
|
+
|
6
|
+
module Sapcai
|
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 SapcaiError.new('Token is missing') if token.nil?
|
19
|
+
|
20
|
+
response = HTTParty.post(
|
21
|
+
"#{Utils::CONVERSATION_ENDPOINT}#{conversation_id}/messages",
|
22
|
+
body: { messages: payload.to_json },
|
23
|
+
headers: { 'Authorization' => "Token #{token}" }
|
24
|
+
)
|
25
|
+
raise SapcaiError.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 SapcaiError.new('Token is missing') if token.nil?
|
33
|
+
|
34
|
+
response = HTTParty.post(
|
35
|
+
Utils::MESSAGE_ENDPOINT,
|
36
|
+
body: { messages: payload.to_json },
|
37
|
+
headers: { 'Authorization' => "Token #{token}" }
|
38
|
+
)
|
39
|
+
raise SapcaiError.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 Sapcai
|
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,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative 'models/response'
|
4
|
+
require_relative 'utils'
|
5
|
+
require_relative '../errors'
|
6
|
+
|
7
|
+
module Sapcai
|
8
|
+
module Analyse
|
9
|
+
def analyse_text(text, token: nil, language: nil)
|
10
|
+
token ||= @token
|
11
|
+
raise SapcaiError.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 SapcaiError.new(JSON.parse(response.body)['message']) if response.code != 200
|
23
|
+
|
24
|
+
Response.new(JSON.parse(response.body))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
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 Sapcai
|
8
|
+
module Converse
|
9
|
+
def converse_text(text, token: nil, language: nil, conversation_token: nil, memory: nil)
|
10
|
+
token ||= @token
|
11
|
+
raise SapcaiError.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 SapcaiError.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 SapcaiError.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 SapcaiError.new(JSON.parse(response.body)['message']) if response.code != 200
|
46
|
+
|
47
|
+
Conversation.new(response.body, token)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Sapcai
|
4
|
+
class Action
|
5
|
+
attr_reader :slug
|
6
|
+
attr_reader :done
|
7
|
+
attr_reader :reply
|
8
|
+
|
9
|
+
def initialize(action)
|
10
|
+
@slug = action['slug']
|
11
|
+
@done = action['done']
|
12
|
+
@reply = action['reply']
|
13
|
+
end
|
14
|
+
|
15
|
+
def done?
|
16
|
+
@done
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative 'action'
|
4
|
+
require_relative 'entity'
|
5
|
+
require_relative 'intent'
|
6
|
+
require_relative '../utils'
|
7
|
+
|
8
|
+
module Sapcai
|
9
|
+
class Conversation
|
10
|
+
attr_reader :raw, :uuid, :source, :replies, :action, :next_actions, :memory, :entities, :sentiment, :intents,
|
11
|
+
:conversation_token, :language, :processing_language, :version, :timestamp, :status
|
12
|
+
|
13
|
+
def initialize(response, token)
|
14
|
+
@token = token
|
15
|
+
|
16
|
+
@raw = response
|
17
|
+
|
18
|
+
response = JSON.parse(response)
|
19
|
+
response = response['results']
|
20
|
+
|
21
|
+
@uuid = response['uuid']
|
22
|
+
@source = response['source']
|
23
|
+
@replies = response['replies']
|
24
|
+
@action = response['action'] ? Action.new(response['action']) : nil
|
25
|
+
@next_actions = response['next_actions'].map{ |i| Action.new(i) }
|
26
|
+
@sentiment = response['sentiment']
|
27
|
+
@memory = response['memory'].reject{ |_, e| e.nil? }.map{ |n, e| Entity.new(n, e) }
|
28
|
+
@entities = response['entities'].flat_map{ |n, e| e.map{ |ee| Entity.new(n, ee) } }
|
29
|
+
@intents = response['intents'].map{ |i| Intent.new(i) }
|
30
|
+
@conversation_token = response['conversation_token']
|
31
|
+
@language = response['language']
|
32
|
+
@processing_language = response['processing_language']
|
33
|
+
@version = response['version']
|
34
|
+
@timestamp = response['timestamp']
|
35
|
+
@status = response['status']
|
36
|
+
end
|
37
|
+
|
38
|
+
def reply
|
39
|
+
@replies.any? ? @replies.first : nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def next_action
|
43
|
+
@next_actions.any? ? @next_actions.first : nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def joined_replies(sep = ' ')
|
47
|
+
@replies.join(sep)
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_memory(key = nil)
|
51
|
+
return @memory if key.nil?
|
52
|
+
|
53
|
+
@memory.each do |entity|
|
54
|
+
return entity if entity.name.casecmp(key.to_s).zero?
|
55
|
+
end
|
56
|
+
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def intent
|
61
|
+
@intents.any? ? @intents.first : nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def vpositive?
|
65
|
+
@sentiment == Utils::SENTIMENT_VPOSITIVE
|
66
|
+
end
|
67
|
+
|
68
|
+
def positive?
|
69
|
+
@sentiment == Utils::SENTIMENT_POSITIVE
|
70
|
+
end
|
71
|
+
|
72
|
+
def neutral?
|
73
|
+
@sentiment == Utils::SENTIMENT_NEUTRAL
|
74
|
+
end
|
75
|
+
|
76
|
+
def negative?
|
77
|
+
@sentiment == Utils::SENTIMENT_NEGATIVE
|
78
|
+
end
|
79
|
+
|
80
|
+
def vnegative?
|
81
|
+
@sentiment == Utils::SENTIMENT_VNEGATIVE
|
82
|
+
end
|
83
|
+
|
84
|
+
def set_memory(memory)
|
85
|
+
body = { conversation_token: @conversation_token, memory: memory }
|
86
|
+
response = HTTParty.put(
|
87
|
+
Utils::CONVERSE_ENDPOINT,
|
88
|
+
body: body,
|
89
|
+
headers: { 'Authorization' => "Token #{@token}" }
|
90
|
+
)
|
91
|
+
raise SapcaiError.new(JSON.parse(response.body)['message']) if response.code != 200
|
92
|
+
|
93
|
+
response = JSON.parse(response.body)
|
94
|
+
response = response['results']
|
95
|
+
response['memory'].reject{ |_, e| e.nil? }.map{ |n, e| Entity.new(n, e) }
|
96
|
+
end
|
97
|
+
|
98
|
+
def reset_memory(name = nil)
|
99
|
+
body = { conversation_token: @conversation_token }
|
100
|
+
body[:memory] = { name => nil } unless name.nil?
|
101
|
+
|
102
|
+
response = HTTParty.put(
|
103
|
+
Utils::CONVERSE_ENDPOINT,
|
104
|
+
body: body,
|
105
|
+
headers: { 'Authorization' => "Token #{@token}" }
|
106
|
+
)
|
107
|
+
raise SapcaiError.new(JSON.parse(response.body)['message']) if response.code != 200
|
108
|
+
|
109
|
+
response = JSON.parse(response.body)
|
110
|
+
response = response['results']
|
111
|
+
response['memory'].reject{ |_, e| e.nil? }.map{ |n, e| Entity.new(n, e) }
|
112
|
+
end
|
113
|
+
|
114
|
+
def reset_conversation
|
115
|
+
body = { conversation_token: @conversation_token }
|
116
|
+
response = HTTParty.delete(
|
117
|
+
Utils::CONVERSE_ENDPOINT,
|
118
|
+
body: body,
|
119
|
+
headers: { 'Authorization' => "Token #{@token}" }
|
120
|
+
)
|
121
|
+
raise SapcaiError.new(JSON.parse(response.body)['message']) if response.code != 200
|
122
|
+
|
123
|
+
response = JSON.parse(response.body)
|
124
|
+
response = response['results']
|
125
|
+
response['memory'].reject{ |_, e| e.nil? }.map{ |n, e| Entity.new(n, e) }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Sapcai
|
4
|
+
class Entity
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize(name, data)
|
8
|
+
@name = name
|
9
|
+
|
10
|
+
data.each_pair do |k, v|
|
11
|
+
self.instance_variable_set("@#{k}", v)
|
12
|
+
self.define_singleton_method(k.to_sym){ v }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative 'intent'
|
4
|
+
require_relative 'entity'
|
5
|
+
require_relative '../utils'
|
6
|
+
|
7
|
+
module Sapcai
|
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 :processing_language
|
19
|
+
attr_reader :version
|
20
|
+
attr_reader :timestamp
|
21
|
+
attr_reader :status
|
22
|
+
|
23
|
+
def initialize(response)
|
24
|
+
@raw = JSON.dump(response)
|
25
|
+
response = response['results']
|
26
|
+
|
27
|
+
@uuid = response['uuid']
|
28
|
+
@source = response['source']
|
29
|
+
@intents = response['intents'].map{ |i| Intent.new(i) }
|
30
|
+
@act = response['act']
|
31
|
+
@type = response['type']
|
32
|
+
@sentiment = response['sentiment']
|
33
|
+
@entities = response['entities'].flat_map{ |n, e| e.map{ |ee| Entity.new(n, ee) } }
|
34
|
+
@language = response['language']
|
35
|
+
@processing_language = response['processing_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 Sapcai
|
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 Sapcai
|
4
|
+
class Utils
|
5
|
+
# Endpoints
|
6
|
+
REQUEST_ENDPOINT = 'https://api.cai.tools.sap/v2/request/'.freeze
|
7
|
+
CONVERSE_ENDPOINT = 'https://api.cai.tools.sap/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
|
data/lib/sapcai/utils.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Sapcai
|
4
|
+
class Utils
|
5
|
+
# Versioning
|
6
|
+
MAJOR = '4'.freeze
|
7
|
+
MINOR = '0'.freeze
|
8
|
+
PATCH = '0'.freeze
|
9
|
+
VERSION = "#{MAJOR}.#{MINOR}.#{PATCH}".freeze
|
10
|
+
|
11
|
+
# Endpoints
|
12
|
+
TRAIN_ENDPOINT = 'https://api.cai.tools.sap/v2/'.freeze
|
13
|
+
CONNECT_ENDPOINT = 'https://api.cai.tools.sap/connect/v1/'.freeze
|
14
|
+
HOST_ENDPOINT = 'https://api.cai.tools.sap/host/v1/'.freeze
|
15
|
+
MONITOR_ENDPOINT = 'https://api.cai.tools.sap/monitor/v1/'.freeze
|
16
|
+
BUILD_ENDPOINT = 'https://api.cai.tools.sap/build/v1'.freeze
|
17
|
+
end
|
18
|
+
end
|
data/misc/.gitkeep
ADDED
File without changes
|
Binary file
|
Binary file
|
data/recastai.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
dir = File.dirname(__FILE__)
|
4
|
+
$LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
|
5
|
+
|
6
|
+
require 'date'
|
7
|
+
require 'lib/sapcai/utils'
|
8
|
+
|
9
|
+
Gem::Specification.new do |spec|
|
10
|
+
spec.name = 'Sapcai'
|
11
|
+
spec.version = Sapcai::Utils::VERSION
|
12
|
+
spec.date = Date.today
|
13
|
+
spec.summary = 'SAP Conversational AI official SDK for Ruby'
|
14
|
+
spec.description = 'SAP Conversational AI official SDK for Ruby. Allows you to make requests to your bots.'
|
15
|
+
spec.homepage = 'https://github.com/SAPConversationalAI/SDK-ruby'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
spec.authors = ['SAP CAI team']
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject{ |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
spec.executables = ['sapcaicli']
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
spec.required_ruby_version = '>= 2.2'
|
22
|
+
|
23
|
+
spec.add_dependency 'httparty', '~> 0.13'
|
24
|
+
spec.add_dependency 'httmultiparty', '~> 0.3'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'rspec', '~> 3.4'
|
27
|
+
spec.add_development_dependency 'webmock', '~> 1.24'
|
28
|
+
spec.add_development_dependency 'awesome_print', '~> 1.6'
|
29
|
+
spec.add_development_dependency 'simplecov', '~> 0.15'
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: Sapcai
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 4.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- SAP CAI team
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-01-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.13'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.13'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: httmultiparty
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.4'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: webmock
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.24'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.24'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: awesome_print
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.6'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.6'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.15'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.15'
|
97
|
+
description: SAP Conversational AI official SDK for Ruby. Allows you to make requests
|
98
|
+
to your bots.
|
99
|
+
email:
|
100
|
+
executables:
|
101
|
+
- sapcaicli
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- ".gitignore"
|
106
|
+
- ".rspec"
|
107
|
+
- ".rubocop.yml"
|
108
|
+
- Gemfile
|
109
|
+
- Gemfile.lock
|
110
|
+
- LICENSE
|
111
|
+
- README.md
|
112
|
+
- bin/sapcaicli
|
113
|
+
- lib/sapcai.rb
|
114
|
+
- lib/sapcai/apis/build/build.rb
|
115
|
+
- lib/sapcai/apis/build/dialog_conversation.rb
|
116
|
+
- lib/sapcai/apis/build/dialog_message.rb
|
117
|
+
- lib/sapcai/apis/build/dialog_response.rb
|
118
|
+
- lib/sapcai/apis/connect/connect.rb
|
119
|
+
- lib/sapcai/apis/connect/message.rb
|
120
|
+
- lib/sapcai/apis/connect/models/message.rb
|
121
|
+
- lib/sapcai/apis/connect/utils.rb
|
122
|
+
- lib/sapcai/apis/errors.rb
|
123
|
+
- lib/sapcai/apis/request/analyse.rb
|
124
|
+
- lib/sapcai/apis/request/converse.rb
|
125
|
+
- lib/sapcai/apis/request/models/action.rb
|
126
|
+
- lib/sapcai/apis/request/models/conversation.rb
|
127
|
+
- lib/sapcai/apis/request/models/entity.rb
|
128
|
+
- lib/sapcai/apis/request/models/intent.rb
|
129
|
+
- lib/sapcai/apis/request/models/response.rb
|
130
|
+
- lib/sapcai/apis/request/request.rb
|
131
|
+
- lib/sapcai/apis/request/utils.rb
|
132
|
+
- lib/sapcai/utils.rb
|
133
|
+
- misc/.gitkeep
|
134
|
+
- misc/logo-inline.png
|
135
|
+
- misc/recast-ai-tokens.png
|
136
|
+
- recastai.gemspec
|
137
|
+
homepage: https://github.com/SAPConversationalAI/SDK-ruby
|
138
|
+
licenses:
|
139
|
+
- MIT
|
140
|
+
metadata: {}
|
141
|
+
post_install_message:
|
142
|
+
rdoc_options: []
|
143
|
+
require_paths:
|
144
|
+
- lib
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '2.2'
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
requirements: []
|
156
|
+
rubyforge_project:
|
157
|
+
rubygems_version: 2.7.6
|
158
|
+
signing_key:
|
159
|
+
specification_version: 4
|
160
|
+
summary: SAP Conversational AI official SDK for Ruby
|
161
|
+
test_files: []
|