expando 0.1.0 → 0.2.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 +4 -4
- data/.gitignore +10 -0
- data/.travis.yml +24 -0
- data/CHANGELOG.md +25 -0
- data/Gemfile +2 -2
- data/LICENSE +21 -0
- data/README.md +197 -1
- data/bin/expando +66 -23
- data/expando.gemspec +4 -4
- data/lib/expando.rb +1 -0
- data/lib/expando/entity_updater.rb +1 -1
- data/lib/expando/expander.rb +3 -2
- data/lib/expando/intent_updater.rb +11 -7
- data/lib/expando/project_template.rb +63 -0
- data/lib/expando/updater.rb +4 -4
- data/lib/expando/version.rb +1 -1
- metadata +17 -17
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/circle.yml +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3bd58f23e215da7402729a76f97e4fc0d911703d
|
|
4
|
+
data.tar.gz: 0e9efe0ff94fe9f396dc52f8e23dc220aafcd08e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8a8af208c737854b2f41668ef9f5ed05619d7a45d7f5244e65b0f5d1bc83712bddf8403d8cb03959058abafcc181aa844e6e49000bae2105ccf56492e34b34f1
|
|
7
|
+
data.tar.gz: 70f2e16be50180d35c3c9d1a86eb6c70fce6b31afb6bf58deb578e6ce2868eb3b6da4a9e320c80955a597a9e4e56c6ba35715f94fcb258de9500138e87606af0
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
script: bundle exec rspec spec
|
|
2
|
+
cache: bundler
|
|
3
|
+
language: ruby
|
|
4
|
+
|
|
5
|
+
rvm:
|
|
6
|
+
- 2.3.1
|
|
7
|
+
- 2.2.5
|
|
8
|
+
- jruby-9.1.2.0
|
|
9
|
+
|
|
10
|
+
notifications:
|
|
11
|
+
flowdock:
|
|
12
|
+
secure: "\
|
|
13
|
+
tTIHwkZu67u3G4wkSYmN0suFk34RKLRX6njmP1JgtYzofTM8y07DyYj0viBbeBAFOV6\
|
|
14
|
+
TZrhmRhzShd5HwCNaHjYBY/CbLxaJyUgd96J5uw7Z2whOX4egETALuDl1sekjOBXeJp\
|
|
15
|
+
UQ7UtxhhcMLeAZUGafXOJJ0qP27bjpeij0sgOfYf/3Wad+EJA2ADdgwm3iVZ7lB2DFo\
|
|
16
|
+
/s2OD/XBf2EDDj8YVU8vZde/FpCZMLV1WGYvzTPhH1Umuni+OlCHsYCLajZ5kuKBswC\
|
|
17
|
+
9T5Rkx2Ad0gEoMsnZPLgqunsFgi+kkpWRHN+9O4zmG1LfllrRE+cNIPk3kK6J2MyC+Q\
|
|
18
|
+
FEHpLKfyW8mEsVov3+yDJm/N9+tgQhp+X22UIo4AK4uVBwghpNytYU8O2UgACpk4tPH\
|
|
19
|
+
K5X/q6nLJRuCzf9bxBzdQO9+oMgr/Scz+9hdRfEer8T59W0YyMuErJc9OxqnWw61JvR\
|
|
20
|
+
+9eMztpeNdh4XldkAIymG7QjXBJk3l0CkUbhDaJMhiTjDuyuCrFrMp0sDfo//5K4IR/\
|
|
21
|
+
lF01iYsSFYaPknkYiPXRpcbIRHBQILMRX/ALUUbfNSd3VUwP5V/oYCUEnWlkalxvzWg\
|
|
22
|
+
7IpwWlZbxqp5N2UR4egeR+1Pn4SW8Sry/BusNox5idrXGc2jS19VVspoLy260Z7ILg9\
|
|
23
|
+
+oEcVztS3wu3c=\
|
|
24
|
+
"
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
## [v0.2.0](https://github.com/expando-lang/expando/tree/v0.2.0)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/expando-lang/expando/compare/v0.1.0...v0.2.0)
|
|
6
|
+
|
|
7
|
+
**Added**
|
|
8
|
+
|
|
9
|
+
- Enable using config file in current directory. See [1ab20a5](https://github.com/expando-lang/expando/commit/04004f4b3639d31492ebc9f3aa55a1fd67ad1a00)
|
|
10
|
+
|
|
11
|
+
**Closed issues:**
|
|
12
|
+
|
|
13
|
+
- Add new project initialization [\#1](https://github.com/expando-lang/expando/issues/1)
|
|
14
|
+
|
|
15
|
+
**Merged pull requests:**
|
|
16
|
+
|
|
17
|
+
- Add project initialization [\#2](https://github.com/expando-lang/expando/pull/2) ([techpeace](https://github.com/techpeace))
|
|
18
|
+
|
|
19
|
+
## [v0.1.0](https://github.com/expando-lang/expando/tree/v0.1.0) (2016-05-27)
|
|
20
|
+
|
|
21
|
+
- Initial release
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
data/Gemfile
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
gem 'api-ai-ruby', github: 'voxable-labs/api-ai-ruby'
|
|
4
4
|
# Uncomment the below when developing on api-ai-ruby locally
|
|
5
|
-
gem 'api-ai-ruby', :path => '../../api-ai-ruby'
|
|
5
|
+
# gem 'api-ai-ruby', :path => '../../api-ai-ruby'
|
|
6
6
|
|
|
7
7
|
# Specify your gem's dependencies in expando.gemspec
|
|
8
8
|
gemspec
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016 Voxable LLC
|
|
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
CHANGED
|
@@ -1,2 +1,198 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img title="Expando logo" src='https://cloud.githubusercontent.com/assets/2220/19525778/b1b3130e-95e7-11e6-9efd-09f195f720ff.png' width=300 />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a title="Gem Version" href="https://rubygems.org/gems/expando">
|
|
7
|
+
<img src="https://img.shields.io/gem/v/expando.svg" />
|
|
8
|
+
</a>
|
|
9
|
+
<a title="Linux Build Status" href="https://travis-ci.org/expando-lang/expando">
|
|
10
|
+
<img src="https://img.shields.io/travis/expando-lang/expando/master.svg?label=Linux%20build" />
|
|
11
|
+
</a>
|
|
12
|
+
<a title="Code Climate" href="https://codeclimate.com/github/expando-lang/expando">
|
|
13
|
+
<img src="https://img.shields.io/codeclimate/github/expando-lang/expando.svg" />
|
|
14
|
+
</a>
|
|
15
|
+
<a title="Dependency Status" href="https://gemnasium.com/expando-lang/expando">
|
|
16
|
+
<img src="https://img.shields.io/gemnasium/expando-lang/expando.svg" />
|
|
17
|
+
</a>
|
|
18
|
+
<a title="Security" href="https://hakiri.io/github/expando-lang/expando/master">
|
|
19
|
+
<img src="https://hakiri.io/github/expando-lang/expando/master.svg" />
|
|
20
|
+
</a>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
Expando is a translation language for easily defining user utterance examples when building conversational interfaces for Natural Language Understanding services like [API.AI](https://api.ai), [LUIS](https://www.luis.ai/), or the [Alexa Skills Kit](https://developer.amazon.com/alexa). This is roughly analagous to the concept of building grammars for speech recognition systems.
|
|
24
|
+
|
|
25
|
+
## What's all this, then?
|
|
26
|
+
|
|
27
|
+
The following line of Expando:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
(is it possible to|can I|how do I) return (something|an item)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
...would be expanded by producing the Cartesian product of the phrases in parentheses that are separated by pipes:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
is it possible to return something
|
|
37
|
+
is it possible to return an item
|
|
38
|
+
can I return something
|
|
39
|
+
can I return an item
|
|
40
|
+
how do I return something
|
|
41
|
+
how do I return an item
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This encoding makes it much easier to manage multiple user utterance examples when building conversational interfaces.
|
|
45
|
+
|
|
46
|
+
Using Expando, you can:
|
|
47
|
+
|
|
48
|
+
* House your intents and entities in version control, simplifying collaboration.
|
|
49
|
+
* Use the CLI to automatically update your intents and entities (only supports API.AI, at the moment).
|
|
50
|
+
* Make use of the expansion syntax to dramatically simplify the encoding of utterance examples.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
This reference implementation of the Expando language is built with Ruby, and packaged as a [gem](https://rubygems.org/). You can install it with:
|
|
55
|
+
|
|
56
|
+
```console
|
|
57
|
+
$ gem install expando
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Getting started
|
|
61
|
+
|
|
62
|
+
The Expando CLI features an `init` command for initializing new Expando projects:
|
|
63
|
+
|
|
64
|
+
```console
|
|
65
|
+
$ mkdir support-bot
|
|
66
|
+
$ cd support-bot
|
|
67
|
+
$ expando init
|
|
68
|
+
✓ intents directory created
|
|
69
|
+
✓ entities directory created
|
|
70
|
+
✓ .expando.rc.yaml file created
|
|
71
|
+
✓ circle.yaml file created
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This will create `intents` and `entities` directories, for housing the utterance examples themselves, as well as some configuration files.
|
|
75
|
+
|
|
76
|
+
### Configure API.AI integration
|
|
77
|
+
|
|
78
|
+
If you'll be using Expando to update the intents and entities of an existing API.AI agent, you'll need to copy the client access token and developer access token for the agent to `.expando.rc.yaml`:
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
# API.AI credentials - add the credentials for your agent below
|
|
82
|
+
:client_access_token: REPLACE_WITH_TOKEN
|
|
83
|
+
:developer_access_token: REPLACE_WITH_TOKEN
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Set up continuous integration
|
|
87
|
+
|
|
88
|
+
The `circle.yaml` file can be used to configure [CircleCI](https://circleci.com/) to enable automatically updating an API.AI agent when commits are pushed to your Expando project's repo.
|
|
89
|
+
|
|
90
|
+
### Create intent and entity files
|
|
91
|
+
|
|
92
|
+
Let's assume we have an agent on API.AI named `support-bot`. If we want to use the Expando syntax for one of this agent's intents named `openHours`, we'd create a file in the `intents` directory named `openHours.txt`.
|
|
93
|
+
|
|
94
|
+
It's also possible to create expandable entity examples in the same manner. A file named `entities/products.txt` would match to a `products` entity on API.AI.
|
|
95
|
+
|
|
96
|
+
## Syntax
|
|
97
|
+
|
|
98
|
+
Currently, Expando supports phrase combinations, and optional phrases.
|
|
99
|
+
|
|
100
|
+
### Phrase combination
|
|
101
|
+
|
|
102
|
+
Using the above example, we could include the following line of Expando in the file `intents/openHours.txt`:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
(when|what times) are you open
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
This would be expanded by creating a version of this utterance with each of the phrases enclosed by paretheses and separated by pipes:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
when are you open
|
|
112
|
+
what times are you open
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
If multiple sets of phrases are included on the same line, a Cartesian product of each of the phrases will be created. The following line of Expando:
|
|
116
|
+
|
|
117
|
+
```text
|
|
118
|
+
(when|what times) are (you|y'all|you guys) open
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
...would result in this full list of utterances:
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
when are you open
|
|
125
|
+
when are y'all open
|
|
126
|
+
when are you guys open
|
|
127
|
+
what times are you open
|
|
128
|
+
what times are y'all open
|
|
129
|
+
what times are you guys open
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Optional phrases
|
|
133
|
+
|
|
134
|
+
By making the final phrase in a set blank, you can make it optional. The following Expando:
|
|
135
|
+
|
|
136
|
+
```text
|
|
137
|
+
what are your (open|) hours
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
...would result in:
|
|
141
|
+
|
|
142
|
+
```text
|
|
143
|
+
what are your open hours
|
|
144
|
+
what are your hours
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
It's also possible to make an entire set of phrases optional:
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
what are your (open|business|) hours
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
...results in:
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
what are your open hours
|
|
157
|
+
what are your business hours
|
|
158
|
+
what are your hours
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Essentially, you're making the last phrase in the set an empty string.
|
|
162
|
+
|
|
163
|
+
## Updating API.AI
|
|
164
|
+
|
|
165
|
+
In order to update intents or entities on API.AI, use the following commands:
|
|
166
|
+
|
|
167
|
+
```console
|
|
168
|
+
$ expando update intents
|
|
169
|
+
$ expando update entities
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
It's also possible to target specific entities or intents for updating:
|
|
173
|
+
|
|
174
|
+
```console
|
|
175
|
+
$ expando update intents openHours
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
You can also access full help for the Expando CLI:
|
|
179
|
+
|
|
180
|
+
```console
|
|
181
|
+
$ expando --help
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
..and also help for specific Expando CLI commands:
|
|
185
|
+
|
|
186
|
+
```console
|
|
187
|
+
$ expando update --help
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Documentation
|
|
191
|
+
|
|
192
|
+
Documentation for the source code of the `expando` gem itself can be viewed [here](http://www.rubydoc.info/github/expando-lang/expando/master).
|
|
193
|
+
|
|
194
|
+
## Credits
|
|
195
|
+
|
|
196
|
+
<p align="center"><a href="https://voxable.io"><img title="Voxable logo" src="https://cloud.githubusercontent.com/assets/2220/14663745/8b5688dc-0689-11e6-95b9-7765fa59128e.png" /></a></p>
|
|
197
|
+
|
|
198
|
+
Initial work on Expando was graciously funded by the good folks at [vThreat](https://vthreat.com). Expando is brought to you by [Voxable](http://voxable.io), a conversational interface agency in Austin, Texas.
|
data/bin/expando
CHANGED
|
@@ -9,9 +9,19 @@ include GLI::App
|
|
|
9
9
|
|
|
10
10
|
version Expando::VERSION
|
|
11
11
|
|
|
12
|
-
program_desc 'A tool for managing files written in the Expando
|
|
12
|
+
program_desc 'A tool for managing files written in the Expando language.'
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
# Prefer using config file frow current working directory. Otherwise, use config
|
|
15
|
+
# file in home directory.
|
|
16
|
+
config_filename = '.expando.rc.yaml'
|
|
17
|
+
current_directory_config_filename = File.join(Dir.pwd, config_filename)
|
|
18
|
+
home_directory_config_filename = File.join(ENV['HOME'], config_filename)
|
|
19
|
+
|
|
20
|
+
if File.exist?(current_directory_config_filename)
|
|
21
|
+
config_file current_directory_config_filename
|
|
22
|
+
else
|
|
23
|
+
config_file home_directory_config_filename
|
|
24
|
+
end
|
|
15
25
|
|
|
16
26
|
flag :client_access_token, desc: 'Api.ai Client Access Token'
|
|
17
27
|
flag :developer_access_token, desc: 'Api.ai Developer Access Token'
|
|
@@ -20,56 +30,78 @@ flag :entities_path, desc: 'The path to the directory containing entity
|
|
|
20
30
|
|
|
21
31
|
# Make credentials globally accessible
|
|
22
32
|
pre do | global_options, command, options, args |
|
|
33
|
+
|
|
23
34
|
# TODO: Why are these being repeated in global_options?
|
|
24
|
-
global_options[:credentials] = {
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
global_options[ :credentials ] = {
|
|
36
|
+
client_access_token: global_options[ :client_access_token ],
|
|
37
|
+
developer_access_token: global_options[ :developer_access_token ]
|
|
27
38
|
}
|
|
28
39
|
end
|
|
29
40
|
|
|
30
|
-
desc 'Update entities and/or intents'
|
|
41
|
+
desc 'Update an Api.ai agent\'s entities and/or intents'
|
|
31
42
|
long_desc <<-DESC
|
|
32
43
|
Update Expando's entities and intents on Api.ai based on the contents of the
|
|
33
44
|
files in the entities and intents directories, respectively.
|
|
34
45
|
DESC
|
|
35
46
|
command [ :update, :u ] do | c |
|
|
36
|
-
|
|
47
|
+
|
|
48
|
+
c.desc "Update an Api.ai agent's entities"
|
|
37
49
|
c.long_desc <<-DESC
|
|
38
50
|
Updates the specified entities. The entity names can be specified after this
|
|
39
|
-
argument in a
|
|
51
|
+
argument in a space delimited list, and should match the file name of the
|
|
40
52
|
specific entity in the entities directory. If no entity name is specified,
|
|
41
53
|
all entities are updated.
|
|
42
54
|
DESC
|
|
43
|
-
c.arg 'entity
|
|
55
|
+
c.arg 'entity entity[ entity]*'
|
|
44
56
|
c.command :entities do | entities |
|
|
57
|
+
entities.flag :entities_path, desc: 'The path to the directory containing entity files'
|
|
58
|
+
|
|
45
59
|
entities.action do | global_options, options, args |
|
|
46
|
-
#
|
|
47
|
-
|
|
60
|
+
# Determine path to entity files
|
|
61
|
+
entities_path_from_options = options[ :entities_path ] || global_options[ :entities_path ]
|
|
62
|
+
entities_path = entities_path_from_options ? File.expand_path( entities_path_from_options ) : nil
|
|
63
|
+
|
|
64
|
+
if args.empty?
|
|
65
|
+
entity_names = Dir.entries( entities_path )[ 2..-1 ].collect { | f | f.gsub( '.txt', '' ) }
|
|
66
|
+
else
|
|
67
|
+
entity_names = args
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
entity_names.each do | entity |
|
|
48
71
|
updater = Expando::EntityUpdater.new( entity,
|
|
49
|
-
client_keys: global_options[:credentials],
|
|
50
|
-
|
|
51
|
-
entities_path: global_options[:entities_path])
|
|
72
|
+
client_keys: global_options[ :credentials ],
|
|
73
|
+
entities_path: entities_path )
|
|
52
74
|
updater.update!
|
|
53
75
|
end
|
|
54
76
|
end
|
|
55
77
|
end
|
|
56
78
|
|
|
57
|
-
c.desc "Update Api.ai intents"
|
|
79
|
+
c.desc "Update an Api.ai agent's intents"
|
|
58
80
|
c.long_desc <<-DESC
|
|
59
81
|
Updates the specified intents. The intent names can be specified after this
|
|
60
|
-
argument in a
|
|
82
|
+
argument in a space delimited list, and should match the file name of the
|
|
61
83
|
specific intent in the intents directory. If no intent name is specified,
|
|
62
84
|
all intents are updated.
|
|
63
85
|
DESC
|
|
64
|
-
c.arg 'intent
|
|
86
|
+
c.arg 'intent intent[ intent]*'
|
|
65
87
|
c.command :intents do | intents |
|
|
88
|
+
intents.flag :intents_path, desc: 'The path to the directory containing intent files'
|
|
89
|
+
|
|
66
90
|
intents.action do | global_options, options, args |
|
|
67
|
-
#
|
|
68
|
-
|
|
91
|
+
# Determine path to intent files
|
|
92
|
+
intents_path_from_options = options[ :intents_path ] || global_options[ :intents_path ]
|
|
93
|
+
intents_path = intents_path_from_options ? File.expand_path( intents_path_from_options ) : nil
|
|
94
|
+
|
|
95
|
+
if args.empty?
|
|
96
|
+
intent_names = Dir.entries( intents_path )[ 2..-1 ].collect { | f | f.gsub( '.txt', '' ) }
|
|
97
|
+
else
|
|
98
|
+
intent_names = args
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
intent_names.each do | intent |
|
|
69
102
|
updater = Expando::IntentUpdater.new( intent,
|
|
70
|
-
client_keys: global_options[:credentials],
|
|
71
|
-
intents_path:
|
|
72
|
-
entities_path: global_options[:entities_path])
|
|
103
|
+
client_keys: global_options[ :credentials ],
|
|
104
|
+
intents_path: intents_path)
|
|
73
105
|
updater.update!
|
|
74
106
|
end
|
|
75
107
|
end
|
|
@@ -79,4 +111,15 @@ command [ :update, :u ] do | c |
|
|
|
79
111
|
#c.default_command :entities
|
|
80
112
|
end
|
|
81
113
|
|
|
82
|
-
|
|
114
|
+
desc 'Initialize a new Expando project'
|
|
115
|
+
long_desc <<-DESC
|
|
116
|
+
Create the necessary files and directories for a new Expando project in the
|
|
117
|
+
current working directory.
|
|
118
|
+
DESC
|
|
119
|
+
command [ :init, :i ] do | c |
|
|
120
|
+
c.action do
|
|
121
|
+
Expando::ProjectTemplate.init!
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
exit run(ARGV)
|
data/expando.gemspec
CHANGED
|
@@ -24,8 +24,8 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
spec.add_development_dependency 'rspec_junit_formatter', '~> 0.2.2'
|
|
25
25
|
spec.add_development_dependency 'climate_control', '~> 0.0.3'
|
|
26
26
|
|
|
27
|
-
spec.add_runtime_dependency 'api-ai-ruby'
|
|
28
|
-
spec.add_runtime_dependency 'gli', '~> 2.
|
|
29
|
-
spec.add_runtime_dependency 'colorize', '~> 0.
|
|
30
|
-
spec.add_runtime_dependency 'awesome_print', '~> 1.
|
|
27
|
+
spec.add_runtime_dependency 'api-ai-ruby'
|
|
28
|
+
spec.add_runtime_dependency 'gli', '~> 2.14.0'
|
|
29
|
+
spec.add_runtime_dependency 'colorize', '~> 0.8.1'
|
|
30
|
+
spec.add_runtime_dependency 'awesome_print', '~> 1.7.0'
|
|
31
31
|
end
|
data/lib/expando.rb
CHANGED
|
@@ -53,7 +53,7 @@ module Expando
|
|
|
53
53
|
|
|
54
54
|
# @return [Array<String>] The expanded list of entities.
|
|
55
55
|
def expanded_entities
|
|
56
|
-
entity_file_path = File.join( @entities_path, @name.to_s + '.txt')
|
|
56
|
+
entity_file_path = File.join( File.expand_path( @entities_path ), @name.to_s + '.txt')
|
|
57
57
|
Expander.expand! file_lines( entity_file_path )
|
|
58
58
|
end
|
|
59
59
|
end
|
data/lib/expando/expander.rb
CHANGED
|
@@ -46,10 +46,11 @@ module Expando
|
|
|
46
46
|
expanded_line = line
|
|
47
47
|
|
|
48
48
|
replacement_values.each do |value|
|
|
49
|
-
expanded_line = expanded_line.sub(
|
|
49
|
+
expanded_line = expanded_line.sub( TOKEN_REGEX, value )
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
# TODO: Replace multiple spaces with a single space
|
|
53
|
+
expanded_lines << expanded_line.strip
|
|
53
54
|
end
|
|
54
55
|
end
|
|
55
56
|
|
|
@@ -44,15 +44,19 @@ module Expando
|
|
|
44
44
|
json[ :userSays ] = expanded_utterances
|
|
45
45
|
|
|
46
46
|
# TODO: Make this a separate, tested method
|
|
47
|
-
|
|
48
|
-
responses = responses.collect { |response| response.chomp }
|
|
47
|
+
responses_path = File.join( File.expand_path( @intents_path ), '..', 'responses', @name.to_s + '.txt' )
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
if File.exist?(responses_path)
|
|
50
|
+
responses = File.readlines responses_path
|
|
51
|
+
responses = responses.collect { |response| response.chomp }
|
|
52
|
+
|
|
53
|
+
responsesJson = json[ :responses ]
|
|
54
|
+
responsesJson[ 0 ][ :speech ] = responses
|
|
55
|
+
json[:responses] = responsesJson
|
|
56
|
+
end
|
|
53
57
|
|
|
54
58
|
# Clean up portions of the JSON response that we don't need in the request
|
|
55
|
-
%w{templates state priority webhookUsed}.each { |key| json.delete( key.to_sym ) }
|
|
59
|
+
%w{auto templates state priority webhookUsed lastUpdate fallbackIntent cortanaCommand}.each { |key| json.delete( key.to_sym ) }
|
|
56
60
|
|
|
57
61
|
json
|
|
58
62
|
end
|
|
@@ -76,7 +80,7 @@ module Expando
|
|
|
76
80
|
|
|
77
81
|
# @return [Array<String>] The expanded list of intent utterances.
|
|
78
82
|
def expanded_utterances
|
|
79
|
-
intent_utterance_file_path = File.join( @intents_path, @name.to_s + '.txt')
|
|
83
|
+
intent_utterance_file_path = File.join( File.expand_path( @intents_path ), @name.to_s + '.txt')
|
|
80
84
|
# TODO: Test
|
|
81
85
|
utterances = Expander.expand! file_lines( intent_utterance_file_path )
|
|
82
86
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Expando
|
|
2
|
+
class ProjectTemplate
|
|
3
|
+
class << self
|
|
4
|
+
# Initialize a new Expando project in the current working directory.
|
|
5
|
+
def init!
|
|
6
|
+
mkdir 'intents'
|
|
7
|
+
mkdir 'entities'
|
|
8
|
+
|
|
9
|
+
config_file_contents = <<-CONFIG_FILE
|
|
10
|
+
# API.AI credentials - add the credentials for your agent below
|
|
11
|
+
:client_access_token: REPLACE_WITH_TOKEN
|
|
12
|
+
:developer_access_token: REPLACE_WITH_TOKEN
|
|
13
|
+
CONFIG_FILE
|
|
14
|
+
|
|
15
|
+
mkfile '.expando.rc.yaml', config_file_contents
|
|
16
|
+
|
|
17
|
+
circleci_config_file_contents = <<-CIRCLECI_CONFIG_FILE
|
|
18
|
+
deployment:
|
|
19
|
+
staging:
|
|
20
|
+
branch: /.*/
|
|
21
|
+
commands:
|
|
22
|
+
- bundle exec ./bin/expando update intents
|
|
23
|
+
- bundle exec ./bin/expando update entities
|
|
24
|
+
CIRCLECI_CONFIG_FILE
|
|
25
|
+
|
|
26
|
+
mkfile 'circle.yaml', circleci_config_file_contents
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
# Attempt to create the specified directory. Output progress to user.
|
|
32
|
+
#
|
|
33
|
+
# @param directory [String] The directory to create.
|
|
34
|
+
def mkdir(directory)
|
|
35
|
+
full_path = File.join(Dir.pwd, directory)
|
|
36
|
+
|
|
37
|
+
if Dir.exist?(full_path)
|
|
38
|
+
puts '•'.colorize(:blue) + " #{directory} directory exists (skipping)"
|
|
39
|
+
else
|
|
40
|
+
Dir.mkdir(full_path)
|
|
41
|
+
puts '✓'.colorize(:green) + " #{directory} directory created"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Attempt to create the specified file. Output progress to user.
|
|
46
|
+
#
|
|
47
|
+
# @param name [String] The name of the file.
|
|
48
|
+
# @param contents [String] The contents of the file.
|
|
49
|
+
def mkfile(name, contents)
|
|
50
|
+
full_path = File.join(Dir.pwd, name)
|
|
51
|
+
|
|
52
|
+
if File.exist?(name)
|
|
53
|
+
puts '•'.colorize(:blue) + " #{name} file exists (skipping)"
|
|
54
|
+
else
|
|
55
|
+
File.open(full_path, 'w') do |file|
|
|
56
|
+
file << contents
|
|
57
|
+
end
|
|
58
|
+
puts '✓'.colorize(:green) + " #{name} file created"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
data/lib/expando/updater.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
module Expando
|
|
2
2
|
class Updater
|
|
3
3
|
# The default location of intent source files
|
|
4
|
-
DEFAULT_INTENTS_PATH = File.join( Dir.
|
|
4
|
+
DEFAULT_INTENTS_PATH = File.join( Dir.pwd, 'intents')
|
|
5
5
|
|
|
6
6
|
# The default location of entity source files
|
|
7
|
-
DEFAULT_ENTITIES_PATH = File.join( Dir.
|
|
7
|
+
DEFAULT_ENTITIES_PATH = File.join( Dir.pwd, 'entities' )
|
|
8
8
|
|
|
9
9
|
# Initialize a new `Updater`.
|
|
10
10
|
#
|
|
@@ -44,7 +44,7 @@ module Expando
|
|
|
44
44
|
|
|
45
45
|
{
|
|
46
46
|
client_access_token: client_access_token,
|
|
47
|
-
developer_access_token: developer_access_token
|
|
47
|
+
developer_access_token: developer_access_token
|
|
48
48
|
}
|
|
49
49
|
end
|
|
50
50
|
|
|
@@ -111,4 +111,4 @@ module Expando
|
|
|
111
111
|
File.read( file_path ).lines.collect{ |line| line.chomp }
|
|
112
112
|
end
|
|
113
113
|
end
|
|
114
|
-
end
|
|
114
|
+
end
|
data/lib/expando/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: expando
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matt Buck
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2016-
|
|
11
|
+
date: 2016-10-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -84,58 +84,58 @@ dependencies:
|
|
|
84
84
|
name: api-ai-ruby
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
86
86
|
requirements:
|
|
87
|
-
- - "
|
|
87
|
+
- - ">="
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version:
|
|
89
|
+
version: '0'
|
|
90
90
|
type: :runtime
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
|
-
- - "
|
|
94
|
+
- - ">="
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version:
|
|
96
|
+
version: '0'
|
|
97
97
|
- !ruby/object:Gem::Dependency
|
|
98
98
|
name: gli
|
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
|
100
100
|
requirements:
|
|
101
101
|
- - "~>"
|
|
102
102
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: 2.
|
|
103
|
+
version: 2.14.0
|
|
104
104
|
type: :runtime
|
|
105
105
|
prerelease: false
|
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
107
|
requirements:
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: 2.
|
|
110
|
+
version: 2.14.0
|
|
111
111
|
- !ruby/object:Gem::Dependency
|
|
112
112
|
name: colorize
|
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
|
114
114
|
requirements:
|
|
115
115
|
- - "~>"
|
|
116
116
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: 0.
|
|
117
|
+
version: 0.8.1
|
|
118
118
|
type: :runtime
|
|
119
119
|
prerelease: false
|
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
121
|
requirements:
|
|
122
122
|
- - "~>"
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
|
-
version: 0.
|
|
124
|
+
version: 0.8.1
|
|
125
125
|
- !ruby/object:Gem::Dependency
|
|
126
126
|
name: awesome_print
|
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
|
128
128
|
requirements:
|
|
129
129
|
- - "~>"
|
|
130
130
|
- !ruby/object:Gem::Version
|
|
131
|
-
version: 1.
|
|
131
|
+
version: 1.7.0
|
|
132
132
|
type: :runtime
|
|
133
133
|
prerelease: false
|
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
|
135
135
|
requirements:
|
|
136
136
|
- - "~>"
|
|
137
137
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: 1.
|
|
138
|
+
version: 1.7.0
|
|
139
139
|
description: A translation language for defining user utterance examples in conversational
|
|
140
140
|
interfaces.
|
|
141
141
|
email:
|
|
@@ -149,20 +149,21 @@ extra_rdoc_files: []
|
|
|
149
149
|
files:
|
|
150
150
|
- ".gitignore"
|
|
151
151
|
- ".rspec"
|
|
152
|
-
- ".
|
|
153
|
-
-
|
|
152
|
+
- ".travis.yml"
|
|
153
|
+
- CHANGELOG.md
|
|
154
154
|
- Gemfile
|
|
155
|
+
- LICENSE
|
|
155
156
|
- README.md
|
|
156
157
|
- Rakefile
|
|
157
158
|
- bin/console
|
|
158
159
|
- bin/expando
|
|
159
160
|
- bin/setup
|
|
160
|
-
- circle.yml
|
|
161
161
|
- expando.gemspec
|
|
162
162
|
- lib/expando.rb
|
|
163
163
|
- lib/expando/entity_updater.rb
|
|
164
164
|
- lib/expando/expander.rb
|
|
165
165
|
- lib/expando/intent_updater.rb
|
|
166
|
+
- lib/expando/project_template.rb
|
|
166
167
|
- lib/expando/updater.rb
|
|
167
168
|
- lib/expando/version.rb
|
|
168
169
|
homepage: http://voxable.io
|
|
@@ -184,9 +185,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
184
185
|
version: '0'
|
|
185
186
|
requirements: []
|
|
186
187
|
rubyforge_project:
|
|
187
|
-
rubygems_version: 2.
|
|
188
|
+
rubygems_version: 2.5.1
|
|
188
189
|
signing_key:
|
|
189
190
|
specification_version: 4
|
|
190
191
|
summary: The Expando reference implementation.
|
|
191
192
|
test_files: []
|
|
192
|
-
has_rdoc:
|
data/.ruby-gemset
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
expando
|
data/.ruby-version
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ruby-2.2.0
|
data/circle.yml
DELETED