question

Brandon Fosdick avatar image
Brandon Fosdick asked

Convert JSGF grammars to example utterances using Ruby

I've just started playing with Alexa and making examples for anything non-trivial is already becoming cumbersome. So, using the JSGF gem I wrote awhile back, I've whipped up a bit of code that converts grammars into examples. Hopefully it'll be useful for someone else too. Be careful though; large grammars tend to produce even larger example sets. To use this, install the 'jsgf' gem, and then dump the following into a ruby file (I put it in a Rakefile). It's still a bit rough, and the JSGF gem itself still needs a lot of work, but it's a start. Feel free point out bugs, etc. [code]require 'jsgf' module JSGF class Grammar # Convert a {Grammar} into a set of sample utterances for Alexa # @option slots [Array] The rule names that should be used as slot names # @return [Array ] An array of the example strings def to_examples(slots:[]) raise StandardError, "The grammar must have at least one root rule" unless roots raise StandardError, "The grammar must contain at least one public rule" if roots.empty? roots.flat_map {|name, rule| expand_atom(rule, ["#{name}Intent"], slots:slots) } end # Expand an {Atom} into an array of strings # @return [Array] def expand_atom(atom, prefix=[], slots:[], slot_name:nil) case atom when JSGF::Alternation atom.map {|a| expand_atom(a, prefix, slots:slots, slot_name:slot_name) } when JSGF::Atom if prefix.first.is_a?(Array) prefix.map {|pref| expand_atom(atom, pref, slots:slots, slot_name:slot_name) } else atom_name = atom.to_s atom_name = "{#{atom_name}|#{slot_name}}" if slot_name && !atom_name.empty? atom_name = nil if atom_name.empty? [[*prefix, atom_name].compact.join(' ')] end when JSGF::Rule, Array atom.reduce(prefix) {|memo, a| expand_atom(a, memo, slots:slots, slot_name:slot_name)} when Hash reference_name = atom[:name] slot_name = slots.include?(reference_name) ? reference_name : nil expand_atom(rules[atom[:name]], prefix, slots:slots, slot_name:slot_name) else raise "Unknown atom #{atom}" end end end end # Example usage. Replace this with your actual grammar. grammar = JSGF.grammar 'ColorExpert' do rule MyColorIs: 'my favorite color is :Color' rule Color: %w{green red blue orange gold silver yellow black white} end File.write('utterances.txt', grammar.to_examples(slots:['Color'])) [/code]
alexa skills kitcommunity projects
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Brandon Fosdick avatar image
Brandon Fosdick answered
Ok, clearly posting code here doesn't work, or I did something wrong. Can someone help a newbie out? Preview seems to be broken too.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Brandon Fosdick avatar image
Brandon Fosdick answered
I created a gist for the example: https://gist.github.com/bfoz/72e561a83e534f5aa078 I don't know why I didn't think of that originally. It's Sunday I guess.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

justin avatar image
justin answered
Awesome Brandon, thanks for sharing! I've edited your original post, and have enabled the [code*][/code*] tags (minus the *). I may have to remove these if issues start showing up. Otherwise, the [pre*] tag works for this as well, but doesn't have the pretty colors. Sorry it doesn't highlight the best for you Ruby folk!
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Brandon Fosdick avatar image
Brandon Fosdick answered
Thanks! Bad highlighting is better than no highlighting. It doesn't look that bad anyway.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.