wit_ai 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b8aff10821a6cd3d9f6e3c3c41c25c9473b8c0e29c499c85b527d9de713bd98c
4
+ data.tar.gz: 5cb36e2fd49330c661f44da94fa6530bf608602721fc651ce403ccacceb64277
5
+ SHA512:
6
+ metadata.gz: 3379043b960510e9e446ad20f22ac74eab790f36a10e51886aaadf57bc4ca9c9b8771154417e2cfc07d6c971afe33277fa816717a6f3a0707b363efe67fe4e1f
7
+ data.tar.gz: 4c7951e8a4f07e880ef781100bfa2703c45d2402891cf04a67506362fed89dbaef0d470e78ad7eb3f1c2dadd6f56e725eb3339cd5a7f1dcc8228db8ae2b6167e
@@ -0,0 +1,9 @@
1
+ **Do you want to request a *feature*, report a *bug*, or ask a *question* about wit-ruby?**
2
+
3
+ **What is the current behavior?**
4
+
5
+ **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem.**
6
+
7
+ **What is the expected behavior?**
8
+
9
+ **If applicable, what is the App ID where you are experiencing this issue? If you do not provide this, we cannot help.**
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ *.swo
3
+ *.swp
4
+ .idea/
5
+ Gemfile.lock
data/CHANGES.md ADDED
@@ -0,0 +1,105 @@
1
+ ## v7.0.0
2
+ - Updated API version to latest: `20200513`. Browse the latest HTTP API documentation [here](https://wit.ai/docs/http/20200513#get__message_link).
3
+ - Added intents and traits CRUD methods.
4
+ - More consistent, transparent naming of entities methods.
5
+
6
+ ## v6.0.0
7
+ The most important change is the removal of `.converse()` and `.run_actions()`. Follow the migration tutorial [here](https://github.com/wit-ai/wit-stories-migration-tutorial), or [read more here](https://wit.ai/blog/2017/07/27/sunsetting-stories).
8
+
9
+ ### Breaking changes
10
+
11
+ - `converse` and `run_actions` are removed
12
+ - updated and added new examples that leverage the /message API
13
+
14
+ ## v5.0.0
15
+
16
+ - `converse` and `run_actions` are deprecated
17
+ - `interactive` now calls `message`
18
+
19
+ ### Breaking changes
20
+ - Renamed WitException to Wit::Error
21
+ - Changed Wit::Error to inherit from StandardError instead of Exception
22
+ - Moved constants inside Wit namespace
23
+ - Moved #req and #validate_actions to private methods within Wit namespace
24
+
25
+ ## v4.1.0
26
+
27
+ - `converse` now takes `reset` as optional parameter.
28
+
29
+ ### Breaking changes
30
+
31
+ - `run_actions` now resets the last turn on new messages and errors.
32
+
33
+ ## v4.0.0
34
+
35
+ After a lot of internal dogfooding and bot building, we decided to change the API in a backwards-incompatible way. The changes are described below and aim to simplify user code and accommodate upcoming features.
36
+
37
+ See `./examples` to see how to use the new API.
38
+
39
+ ### Breaking changes
40
+
41
+ - `say` renamed to `send` to reflect that it deals with more than just text
42
+ - Removed built-in actions `merge` and `error`
43
+ - Actions signature simplified with `request` and `response` arguments
44
+ - INFO level replaces LOG level
45
+
46
+ ## v3.4
47
+
48
+ - allows for overriding API version, by setting `WIT_API_VERSION`
49
+ - `interactive()` mode
50
+ - warns instead of throwing when validating actions
51
+
52
+ ### breaking
53
+
54
+ - bumped default API version from `20160330` to `20160516`
55
+
56
+ ## v3.3.1
57
+
58
+ - fixed recursive call when running actions
59
+ - throws an exception if context passed is not a Hash
60
+
61
+ ## v3.3
62
+
63
+ Unifying action parameters
64
+
65
+ ### breaking
66
+
67
+ - the `say` action now takes 3 parameters: `session_id`, `context`, `msg`
68
+ - the `error` action now takes 3 parameters: `session_id`, `context`, `error`
69
+
70
+ ## v3.2
71
+
72
+ Updating action parameters
73
+
74
+ ### breaking
75
+
76
+ - the `merge` action now takes 4 parameters: `session_id`, `context`, `entities`, `msg`
77
+ - the `error` action now takes `context` as second parameter
78
+ - custom actions now take 2 parameters: `session_id`, `context`
79
+
80
+ ## v3.1
81
+
82
+ - allows for custom logging
83
+ - better error message
84
+
85
+ ## v3.0
86
+
87
+ Bot Engine integration
88
+
89
+ ### breaking
90
+
91
+ - the `message` API is wrapped around a `Wit` class, and doesn't take the token as first parameter
92
+
93
+ ## v2.0
94
+
95
+ Rewrite in pure Ruby
96
+
97
+ ### breaking
98
+
99
+ - audio recording and streaming have been removed because:
100
+ - many people only needed access to the HTTP API, and audio recording did not make sense for server-side use cases
101
+ - dependent on platform, choice best left to developers
102
+ - forced us to maintain native bindings as opposed to a pure Pythonic library
103
+ - we renamed the functions to match the HTTP API more closely
104
+ - `.text_query(string, access_token)` becomes `.message(access_token, string)`
105
+ - all functions now return a Ruby dict instead of a JSON string
@@ -0,0 +1,76 @@
1
+ # Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to make participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, sex characteristics, gender identity and expression,
9
+ level of experience, education, socio-economic status, nationality, personal
10
+ appearance, race, religion, or sexual identity and orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies within all project spaces, and it also applies when
49
+ an individual is representing the project or its community in public spaces.
50
+ Examples of representing a project or community include using an official
51
+ project e-mail address, posting via an official social media account, or acting
52
+ as an appointed representative at an online or offline event. Representation of
53
+ a project may be further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at <opensource-conduct@fb.com>. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72
+
73
+ [homepage]: https://www.contributor-covenant.org
74
+
75
+ For answers to common questions about this code of conduct, see
76
+ https://www.contributor-covenant.org/faq
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,34 @@
1
+ # Contributing to wit-ruby
2
+
3
+ We want to make contributing to this project as easy and transparent as
4
+ possible.
5
+
6
+ ## Pull Requests
7
+ We actively welcome your pull requests.
8
+
9
+ 1. Fork the repo and create your branch from `master`.
10
+ 2. If you've added code that should be tested, add tests.
11
+ 3. If you've changed APIs, update the documentation.
12
+ 4. Ensure the test suite passes.
13
+ 5. If you haven't already, complete the Contributor License Agreement ("CLA").
14
+
15
+ ## Contributor License Agreement ("CLA")
16
+
17
+ In order to accept your pull request, we need you to submit a CLA. You only need
18
+ to do this once to work on any of Facebook's open source projects.
19
+
20
+ Complete your CLA here: <https://code.facebook.com/cla>
21
+
22
+ ## Issues
23
+
24
+ We use GitHub issues to track public bugs. Please ensure your description is
25
+ clear and has sufficient instructions to be able to reproduce the issue.
26
+
27
+ Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
28
+ disclosure of security bugs. In those cases, please go through the process
29
+ outlined on that page and do not file a public issue.
30
+
31
+ ## License
32
+
33
+ By contributing to wit-ruby, you agree that your contributions will be licensed
34
+ under the LICENSE file in the root directory of this source tree.
data/Gemfile ADDED
@@ -0,0 +1 @@
1
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Copyright (c) 2014, Wit.ai, Inc. All rights reserved.
3
+ *
4
+ * You are hereby granted a non-exclusive, worldwide, royalty-free license to
5
+ * use, copy, modify, and distribute this software in source code or binary
6
+ * form for use in connection with the web services and APIs provided by
7
+ * Wit.ai.
8
+ *
9
+ * As with any software that integrates with the Wit.ai platform, your use
10
+ * of this software is subject to the Wit.ai Terms of Service
11
+ * [https://wit.ai/terms]. This copyright notice shall be included in all
12
+ * copies or substantial portions of the software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
+ * DEALINGS IN THE SOFTWARE.
21
+ *
22
+ */
data/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # wit-ruby
2
+
3
+ `wit-ruby` is the Ruby SDK for [Wit.ai](http://wit.ai).
4
+
5
+ ## Install
6
+
7
+ From RubyGems:
8
+ ```bash
9
+ gem install wit
10
+ ```
11
+
12
+ From source:
13
+ ```bash
14
+ git clone https://github.com/wit-ai/wit-ruby
15
+ gem build wit.gemspec
16
+ gem install wit-*.gem
17
+ ```
18
+
19
+ ## Quickstart
20
+
21
+ Run in your terminal:
22
+
23
+ ```bash
24
+ ruby examples/basic.rb <your_token>
25
+ ```
26
+
27
+ See the `examples` folder for more examples.
28
+
29
+ ## API
30
+
31
+ ### Overview
32
+
33
+ `wit-ruby` provides a Wit class with the following methods:
34
+ * `message` - the Wit [message API](https://wit.ai/docs/http/20200513#get-intent-via-text-link)
35
+ * `interactive` - starts an interactive conversation with your bot
36
+
37
+ ### Wit class
38
+
39
+ The Wit constructor takes a `Hash` with the following symbol keys:
40
+ * `:access_token` - the access token of your Wit instance
41
+
42
+ A minimal example looks like this:
43
+ ```ruby
44
+ require 'wit'
45
+
46
+ client = Wit.new(access_token: access_token)
47
+ client.message('set an alarm tomorrow at 7am')
48
+ ```
49
+
50
+ ### Create new App Using the Access Token
51
+
52
+ Creates new app using the server token.
53
+ See [POST /apps](https://wit.ai/docs/http/20200513#post__apps_link).
54
+
55
+ ```ruby
56
+ new_app_payload = {name: "new-app-1", lang: "en", private: true}
57
+ # set_new_app_token will make the client use the new app's token.
58
+ # that flag is set to false by default.
59
+ client.create_new_app(new_app_payload, set_new_app_token = true)
60
+ ```
61
+
62
+ ### Train the app programatically using '/utterances'
63
+
64
+ Trains and annotates an utterance or more.
65
+ See [POST /utterances](https://wit.ai/docs/http/20200513#post__utterances_link).
66
+
67
+ ```ruby
68
+ # you have to create the intent and entity before using any of them.
69
+ utterance_payload = {
70
+ text: "I want to fly to china",
71
+ intent: "flight_request",
72
+ entities: [
73
+ {
74
+ "entity": "wit$location:to",
75
+ "start": 17,
76
+ "end": 22,
77
+ "body": "china",
78
+ "entities": []
79
+ }
80
+ ],
81
+ traits: []
82
+ }
83
+
84
+ # utterance payload can be a list of utterances or a single one
85
+ client.post_utterances(utterance_payload)
86
+ ```
87
+
88
+ ### .message()
89
+
90
+ The Wit [message API](https://wit.ai/docs/http/20200513#get-intent-via-text-link).
91
+
92
+ Takes the following parameters:
93
+ * `msg` - the text you want Wit.ai to extract the information from
94
+
95
+ Example:
96
+ ```ruby
97
+ rsp = client.message('what is the weather in London?')
98
+ puts("Yay, got Wit.ai response: #{rsp}")
99
+ ```
100
+
101
+ ### .interactive()
102
+
103
+ Starts an interactive conversation with your bot.
104
+
105
+ Example:
106
+ ```ruby
107
+ client.interactive
108
+ ```
109
+
110
+ ### CRUD operations for intents
111
+ `payload` in the parameters is a hash containing API arguments.
112
+
113
+ #### .get_intents()
114
+ Returns a list of available intents for the app.
115
+ See [GET /intents](https://wit.ai/docs/http/20200513#get__intents_link).
116
+
117
+ #### .get_intent(intent)
118
+ Returns all available information about an intent.
119
+ See [GET /intents/:intent](https://wit.ai/docs/http/20200513#get__intents__intent_link).
120
+
121
+ #### .post_intents(payload)
122
+ Creates a new intent.
123
+ See [POST /intents](https://wit.ai/docs/http/20200513#post__intents_link).
124
+
125
+ #### .delete_intents(intent)
126
+ Permanently deletes the intent.
127
+ See [DELETE /intents/:intent](https://wit.ai/docs/http/20200513#delete__intents__intent_link).
128
+
129
+ ### CRUD operations for entities
130
+ `payload` in the parameters is a hash containing API arguments.
131
+
132
+ #### .get_entities()
133
+ Returns a list of available entities for the app.
134
+ See [GET /entities](https://wit.ai/docs/http/20200513#get--entities-link)
135
+
136
+ #### .post_entities(payload)
137
+ Creates a new entity with the given attributes.
138
+ See [POST /entities](https://wit.ai/docs/http/20200513#post--entities-link)
139
+
140
+ #### .get_entity(entity)
141
+ Returns all the information available for an entity.
142
+ See [GET /entities/:entity](https://wit.ai/docs/http/20200513#get--entities-:entity-link)
143
+
144
+ #### .put_entities(entity, payload)
145
+ Updates an entity with the given attributes.
146
+ See [PUT /entities/:entity](https://wit.ai/docs/http/20200513#put--entities-:entity-link)
147
+
148
+ #### .delete_entities(entity)
149
+ Permanently removes the entity.
150
+ See [DELETE /entities/:entity](https://wit.ai/docs/http/20200513#delete--entities-:entity-link)
151
+
152
+ #### .post_entities_keywords(entity, payload)
153
+ Adds a possible value into the list of keywords for the keywords entity.
154
+ See [POST /entities/:entity/keywords](https://wit.ai/docs/http/20160526#post--entities-:entity-id-values-link)
155
+
156
+ #### .delete_entities_keywords(entity, keyword)
157
+ Deletes a keyword from the entity.
158
+ See [DELETE /entities/:entity/keywords/:keyword](https://wit.ai/docs/http/20200513#delete--entities-:entity-keywords-link)
159
+
160
+ #### .post_entities_keywords_synonyms(entity, keyword, payload)
161
+ Creates a new synonym for the keyword of the entity.
162
+ See [POST /entities/:entity/keywords/:keyword/synonyms](https://wit.ai/docs/http/20200513#post--entities-:entity-keywords-:keyword-synonyms-link)
163
+
164
+ #### delete_entities_keywords_synonyms(entity, keyword, synonym)
165
+ Deletes a synonym of the keyword of the entity.
166
+ See [DELETE /entities/:entity/keywords/:keyword/synonyms/:synonym](https://wit.ai/docs/http/20200513#delete--entities-:entity-keywords-:keyword-synonyms-link)
167
+
168
+ ### CRUD operations for traits
169
+ `payload` in the parameters is a hash containing API arguments.
170
+
171
+ #### .get_traits()
172
+ Returns a list of available traits for the app.
173
+ See [GET /traits](https://wit.ai/docs/http/20200513#get__traits_link).
174
+
175
+ #### .get_trait(trait)
176
+ Returns all available information about a trait.
177
+ See [GET /traits/:trait](https://wit.ai/docs/http/20200513#get__traits__trait_link).
178
+
179
+ #### .post_traits(payload)
180
+ Creates a new trait.
181
+ See [POST /traits](https://wit.ai/docs/http/20200513#post__traits_link).
182
+
183
+ #### .post_traits_values(trait, payload)
184
+ Adds a new value to an existing trait.
185
+ See [POST /traits/:trait/values](https://wit.ai/docs/http/20200513#post__traits__trait_values_link).
186
+
187
+ #### .delete_traits_values(trait, value)
188
+ Permanently deletes a value of an existing trait.
189
+ See [POST /traits/:trait/values](https://wit.ai/docs/http/20200513#delete__traits__trait_values_link).
190
+
191
+ #### .delete_traits(trait)
192
+ Permanently deletes the trait.
193
+ See [DELETE /traits/:trait](https://wit.ai/docs/http/20200513#delete__traits__trait_link).
194
+
195
+
196
+ See the [docs](https://wit.ai/docs) for more information.
197
+
198
+ ### Logging
199
+
200
+ Default logging is to `STDOUT` with `INFO` level.
201
+
202
+ You can setup your logging level as follows:
203
+ ```ruby
204
+ Wit.logger.level = Logger::WARN
205
+ ```
206
+ See the [Logger class](http://ruby-doc.org/stdlib-2.1.0/libdoc/logger/rdoc/Logger.html) docs for more information.
207
+
208
+ ## Thanks
209
+
210
+ Thanks to [Justin Workman](http://github.com/xtagon) for releasing a first version in October 2013. We really appreciate!
211
+
212
+
213
+ ## License
214
+
215
+ The license for wit-ruby can be found in LICENSE file in the root directory of this source tree.
216
+
217
+
218
+ ## Terms of Use
219
+
220
+ Our terms of use can be found at https://opensource.facebook.com/legal/terms.
221
+
222
+
223
+ ## Privacy Policy
224
+
225
+ Our privacy policy can be found at https://opensource.facebook.com/legal/privacy.
data/examples/basic.rb ADDED
@@ -0,0 +1,14 @@
1
+ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
2
+
3
+ require 'wit'
4
+
5
+ if ARGV.length == 0
6
+ puts("usage: #{$0} <wit-access-token>")
7
+ exit 1
8
+ end
9
+
10
+ access_token = ARGV[0]
11
+ ARGV.shift
12
+
13
+ client = Wit.new(access_token: access_token)
14
+ client.interactive
@@ -0,0 +1,56 @@
1
+ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
2
+
3
+ require 'wit'
4
+
5
+ if ARGV.length == 0
6
+ puts("usage: #{$0} <wit-access-token>")
7
+ exit 1
8
+ end
9
+
10
+ access_token = ARGV[0]
11
+ ARGV.shift
12
+
13
+ # Celebrities example
14
+ # See https://wit.ai/aleka/wit-example-celebrities/
15
+
16
+ def first_entity_resolved_value(entities, entity)
17
+ return nil unless entities.has_key? entity
18
+ val = entities[entity][0]['resolved']['values'][0]
19
+ return nil if val.nil?
20
+ return val
21
+ end
22
+
23
+ def first_trait_value(traits, trait)
24
+ return nil unless traits.has_key? trait
25
+ val = traits[trait][0]['value']
26
+ return nil if val.nil?
27
+ return val
28
+ end
29
+
30
+ def handle_message(response)
31
+ greetings = first_trait_value(response['traits'], 'wit$greetings')
32
+ celebrity = first_entity_resolved_value(response['entities'], 'wit$notable_person:notable_person')
33
+
34
+ case
35
+ when celebrity
36
+ return wikidata_description(celebrity)
37
+ when greetings
38
+ return "Hi! You can say something like 'Tell me about Beyonce'"
39
+ else
40
+ return "Um. I don't recognize that name. " \
41
+ "Which celebrity do you want to learn about?"
42
+ end
43
+ end
44
+
45
+ def wikidata_description(celebrity)
46
+ return "I recognize #{celebrity['name']}" unless celebrity.dig('external', 'wikidata')
47
+ wikidata_id = celebrity.fetch('external').fetch('wikidata')
48
+ api = URI("https://www.wikidata.org/w/api.php?action=wbgetentities&format=json&ids=#{wikidata_id}&props=descriptions&languages=en")
49
+ rsp = Net::HTTP.get_response(api)
50
+ wikidata = JSON.parse(rsp.body)
51
+ description = wikidata['entities'][wikidata_id]['descriptions']['en']['value']
52
+ return "ooo yes I know #{celebrity['name']} -- #{description}"
53
+ end
54
+
55
+ client = Wit.new(access_token: access_token)
56
+ client.interactive(method(:handle_message))
data/examples/joke.rb ADDED
@@ -0,0 +1,58 @@
1
+ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
2
+
3
+ require 'wit'
4
+
5
+ if ARGV.length == 0
6
+ puts("usage: #{$0} <wit-access-token>")
7
+ exit 1
8
+ end
9
+
10
+ access_token = ARGV[0]
11
+ ARGV.shift
12
+
13
+ # Joke example
14
+ # See https://wit.ai/aleka/wit-example-joke-bot/
15
+
16
+ def first_value(obj, key)
17
+ return nil unless obj.has_key? key
18
+ val = obj[key][0]['value']
19
+ return nil if val.nil?
20
+ return val
21
+ end
22
+
23
+ $all_jokes = {
24
+ 'chuck' => [
25
+ 'Chuck Norris counted to infinity - twice.',
26
+ 'Death once had a near-Chuck Norris experience.',
27
+ ],
28
+ 'tech' => [
29
+ 'Did you hear about the two antennas that got married? The ceremony was long and boring, but the reception was great!',
30
+ 'Why do geeks mistake Halloween and Christmas? Because Oct 31 === Dec 25.',
31
+ ],
32
+ 'default' => [
33
+ 'Why was the Math book sad? Because it had so many problems.',
34
+ ],
35
+ }
36
+
37
+ def handle_message(response)
38
+ entities = response['entities']
39
+ traits = response['traits']
40
+ get_joke = first_value(traits, 'getJoke')
41
+ greetings = first_value(traits, 'wit$greetings')
42
+ category = first_value(entities, 'category:category')
43
+ sentiment = first_value(traits, 'wit$sentiment')
44
+
45
+ case
46
+ when get_joke
47
+ return $all_jokes[category || 'default'].sample
48
+ when sentiment
49
+ return sentiment == 'positive' ? 'Glad you liked it.' : 'Hmm.'
50
+ when greetings
51
+ return 'Hey this is joke bot :)'
52
+ else
53
+ return 'I can tell jokes! Say "tell me a joke about tech"!'
54
+ end
55
+ end
56
+
57
+ client = Wit.new(access_token: access_token)
58
+ client.interactive(method(:handle_message))
Binary file
data/lib/wit.rb ADDED
@@ -0,0 +1,229 @@
1
+ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
2
+
3
+ require 'json'
4
+ require 'logger'
5
+ require 'net/http'
6
+ require 'securerandom'
7
+
8
+ class Wit
9
+ class Error < StandardError; end
10
+
11
+ WIT_API_HOST = ENV['WIT_URL'] || 'https://api.wit.ai'
12
+ WIT_API_VERSION = ENV['WIT_API_VERSION'] || '20200513'
13
+ LEARN_MORE = 'Learn more at https://wit.ai/docs/quickstart'
14
+
15
+ def initialize(opts = {})
16
+ @access_token = opts[:access_token]
17
+
18
+ if opts[:logger]
19
+ @logger = opts[:logger]
20
+ end
21
+ end
22
+
23
+ def logger
24
+ @logger ||= begin
25
+ x = Logger.new(STDOUT)
26
+ x.level = Logger::INFO
27
+ x
28
+ end
29
+ end
30
+
31
+ def message(msg, n=nil, verbose=nil)
32
+ params = {}
33
+ params[:q] = msg unless msg.nil?
34
+ params[:n] = n unless n.nil?
35
+ params[:verbose] = verbose unless verbose.nil?
36
+ res = req(logger, @access_token, Net::HTTP::Get, '/message', params)
37
+ return res
38
+ end
39
+
40
+ def interactive(handle_message=nil, context={})
41
+ while true
42
+ print '> '
43
+ msg = STDIN.gets.strip
44
+ if msg == ''
45
+ next
46
+ end
47
+
48
+ begin
49
+ if handle_message.nil?
50
+ puts(message(msg))
51
+ else
52
+ puts(handle_message.call(message(msg)))
53
+ end
54
+ rescue Error => exp
55
+ logger.error("error: #{exp.message}")
56
+ end
57
+ end
58
+ rescue Interrupt => _exp
59
+ puts
60
+ end
61
+
62
+ def create_new_app(payload, set_new_app_token = false)
63
+ response = req(logger, @access_token, Net::HTTP::Post, "/apps", {}, payload)
64
+ @access_token = response['access_token'] if set_new_app_token
65
+ return response
66
+ end
67
+
68
+ def post_utterances(payload)
69
+ payload = [payload] if payload.is_a? Hash
70
+
71
+ payload.each do |utterance|
72
+ unless utterance[:entities].empty?
73
+ utterance[:entities] = validate_entities utterance[:entities]
74
+ end
75
+ validate_payload utterance
76
+ end
77
+ req(logger, @access_token, Net::HTTP::Post, "/utterances", {}, payload)
78
+ end
79
+
80
+ def get_intents
81
+ req(logger, @access_token, Net::HTTP::Get, "/intents")
82
+ end
83
+
84
+ def get_intent(intent)
85
+ req(logger, @access_token, Net::HTTP::Get, "/intents/#{URI.encode(intent)}")
86
+ end
87
+
88
+ def post_intents(payload)
89
+ req(logger, @access_token, Net::HTTP::Post, "/intents", {}, payload)
90
+ end
91
+
92
+ def delete_intents(intent)
93
+ req(logger, @access_token, Net::HTTP::Delete, "/intents/#{URI.encode(intent)}")
94
+ end
95
+
96
+ def get_entities
97
+ req(logger, @access_token, Net::HTTP::Get, "/entities")
98
+ end
99
+
100
+ def post_entities(payload)
101
+ payload = payload.map {|k, v| [(k.to_sym rescue k), v]}.to_h.reject{ |k| ![:name, :roles, :lookups, :keywords].include?(k) }
102
+ validate_payload payload
103
+ req(logger, @access_token, Net::HTTP::Post, "/entities", {}, payload)
104
+ end
105
+
106
+ def get_entity(entity)
107
+ req(logger, @access_token, Net::HTTP::Get, "/entities/#{URI.encode(entity)}")
108
+ end
109
+
110
+ def put_entities(entity, payload)
111
+ payload = payload.map {|k, v| [(k.to_sym rescue k), v]}.to_h.reject{ |k| ![:name, :roles, :lookups, :keywords].include?(k) }
112
+ validate_payload payload
113
+ req(logger, @access_token, Net::HTTP::Put, "/entities/#{URI.encode(entity)}", {}, payload)
114
+ end
115
+
116
+ def delete_entities(entity)
117
+ req(logger, @access_token, Net::HTTP::Delete, "/entities/#{URI.encode(entity)}")
118
+ end
119
+
120
+ def post_entities_keywords(entity, payload)
121
+ payload = payload.map {|k, v| [(k.to_sym rescue k), v]}.to_h.reject{ |k| ![:keyword, :synonyms].include?(k) }
122
+ validate_payload payload
123
+ req(logger, @access_token, Net::HTTP::Post, "/entities/#{URI.encode(entity)}/keywords", {}, payload)
124
+ end
125
+
126
+ def delete_entities_keywords(entity, keyword)
127
+ req(logger, @access_token, Net::HTTP::Delete, "/entities/#{URI.encode(entity)}/keywords/#{URI.encode(keyword)}")
128
+ end
129
+
130
+ def post_entities_keywords_synonyms(entity, keyword, payload)
131
+ payload = payload.map {|k, v| [(k.to_sym rescue k), v]}.to_h.reject{ |k| ![:synonym].include?(k) }
132
+ validate_payload payload
133
+ req(logger,@access_token, Net::HTTP::Post, "/entities/#{URI.encode(entity)}/keywords/#{URI.encode(keyword)}/synonyms", {}, payload)
134
+ end
135
+
136
+ def delete_entities_keywords_synonyms(entity, keyword, synonym)
137
+ req(logger,@access_token, Net::HTTP::Delete, "/entities/#{URI.encode(entity)}/keywords/#{URI.encode(keyword)}/synonyms/#{URI.encode(synonym)}")
138
+ end
139
+
140
+ def get_traits
141
+ req(logger, @access_token, Net::HTTP::Get, "/traits")
142
+ end
143
+
144
+ def get_trait(trait)
145
+ req(logger, @access_token, Net::HTTP::Get, "/traits/#{URI.encode(trait)}")
146
+ end
147
+
148
+ def post_traits(payload)
149
+ req(logger, @access_token, Net::HTTP::Post, "/traits", {}, payload)
150
+ end
151
+
152
+ def post_traits_values(trait, payload)
153
+ req(logger, @access_token, Net::HTTP::Post, "/traits/#{URI.encode(trait)}/values", {}, payload)
154
+ end
155
+
156
+ def delete_traits_values(trait, value)
157
+ req(logger, @access_token, Net::HTTP::Delete, "/traits/#{URI.encode(trait)}/values/#{URI.encode(value)}")
158
+ end
159
+
160
+ def delete_traits(trait)
161
+ req(logger, @access_token, Net::HTTP::Delete, "/traits/#{URI.encode(trait)}")
162
+ end
163
+
164
+ private
165
+
166
+ def validate_payload(payload)
167
+ key_types = {
168
+ id: String,
169
+ name: String,
170
+ roles: Array,
171
+ lookups: Array,
172
+ keywords: Array,
173
+ keyword: String,
174
+ synonyms: Array,
175
+ text: String,
176
+ intent: String,
177
+ entities: Array,
178
+ traits: Array
179
+ }
180
+ payload.each do |k, v|
181
+ raise Error.new("#{k.to_s} in request body must be #{key_types[k].to_s} type") unless key_types[k] == v.class
182
+ end
183
+ end
184
+
185
+ def validate_entities(entities)
186
+ entity_keys = {
187
+ entity: String,
188
+ start: Integer,
189
+ end: Integer,
190
+ body: String,
191
+ entities: Array
192
+ }
193
+ entities.each do |entity|
194
+ entity = entity.map {|k, v| [(k.to_sym rescue k), v]}.to_h.reject{ |k| !entity_keys.keys.include?(k) }
195
+ entity.each do |k, v|
196
+ if k == :entities && !v.empty?
197
+ validate_entities(v)
198
+ end
199
+ raise Error.new("#{k.to_s} in entities body must be #{entity_keys[k].to_s} type") unless entity_keys[k] == v.class
200
+ end
201
+ end
202
+
203
+ return entities
204
+ end
205
+
206
+ def req(logger, access_token, meth_class, path, params={}, payload={})
207
+ uri = URI(WIT_API_HOST + path)
208
+ uri.query = URI.encode_www_form(params)
209
+
210
+ logger.debug("#{meth_class} #{uri}")
211
+
212
+ request = meth_class.new(uri)
213
+ request['authorization'] = 'Bearer ' + access_token
214
+ request['accept'] = 'application/vnd.wit.' + WIT_API_VERSION + '+json'
215
+ request.add_field 'Content-Type', 'application/json'
216
+ request.body = payload.to_json
217
+
218
+ Net::HTTP.start(uri.host, uri.port, {:use_ssl => uri.scheme == 'https'}) do |http|
219
+ rsp = http.request(request)
220
+ json = JSON.parse(rsp.body)
221
+ if rsp.code.to_i != 200
222
+ error_msg = (json.is_a?(Hash) and json.has_key?('error')) ? json['error'] : json
223
+ raise Error.new("Wit responded with an error: #{error_msg}")
224
+ end
225
+ logger.debug("#{meth_class} #{uri} #{json}")
226
+ json
227
+ end
228
+ end
229
+ end
data/wit.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'wit_ai'
5
+ s.version = '7.0.0'
6
+ s.summary = 'Ruby SDK for Wit.ai'
7
+ s.description = 'Ruby SDK for Wit.ai'
8
+ s.authors = ['The Wit Team']
9
+ s.email = 'help@wit.ai'
10
+ s.homepage = 'https://wit.ai'
11
+ s.license = 'GPL-2.0'
12
+ s.platform = Gem::Platform::RUBY
13
+ s.required_ruby_version = '>= 1.9.3'
14
+ s.require_paths = ['lib']
15
+ s.files = `git ls-files`.split("\n")
16
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wit_ai
3
+ version: !ruby/object:Gem::Version
4
+ version: 7.0.0
5
+ platform: ruby
6
+ authors:
7
+ - The Wit Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-07-15 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby SDK for Wit.ai
14
+ email: help@wit.ai
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - ".github/ISSUE_TEMPLATE.md"
20
+ - ".gitignore"
21
+ - CHANGES.md
22
+ - CODE_OF_CONDUCT.md
23
+ - CONTRIBUTING.md
24
+ - Gemfile
25
+ - LICENSE
26
+ - README.md
27
+ - examples/basic.rb
28
+ - examples/celebrities.rb
29
+ - examples/joke.rb
30
+ - examples/wit-example-celebrities.zip
31
+ - examples/wit-example-joke-bot.zip
32
+ - lib/wit.rb
33
+ - wit.gemspec
34
+ homepage: https://wit.ai
35
+ licenses:
36
+ - GPL-2.0
37
+ metadata: {}
38
+ post_install_message:
39
+ rdoc_options: []
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.9.3
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubygems_version: 3.2.3
54
+ signing_key:
55
+ specification_version: 4
56
+ summary: Ruby SDK for Wit.ai
57
+ test_files: []