| <!DOCTYPE html> |
| <!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> |
| <!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]--> |
| <!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]--> |
| <!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]--><head> |
| <meta charset='utf-8'/><meta http-equiv='X-UA-Compatible' content='IE=edge'/><meta name='viewport' content='width=device-width, initial-scale=1'/><meta name='keywords' content='groovy, natural language processing, nlp, nlpcraft'/><meta name='description' content='This blog looks at using Apache NLPCraft from Groovy.'/><title>The Apache Groovy programming language - Blogs - Converting natural language into actions with NLPCraft and Groovy</title><link href='../img/favicon.ico' type='image/x-ico' rel='icon'/><link rel='stylesheet' type='text/css' href='../css/bootstrap.css'/><link rel='stylesheet' type='text/css' href='../css/font-awesome.min.css'/><link rel='stylesheet' type='text/css' href='../css/style.css'/><link rel='stylesheet' type='text/css' href='https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css'/> |
| </head><body> |
| <div id='fork-me'> |
| <a href='https://github.com/apache/groovy'> |
| <img style='position: fixed; top: 20px; right: -58px; border: 0; z-index: 100; transform: rotate(45deg);' src='/img/horizontal-github-ribbon.png'/> |
| </a> |
| </div><div id='st-container' class='st-container st-effect-9'> |
| <nav class='st-menu st-effect-9' id='menu-12'> |
| <h2 class='icon icon-lab'>Socialize</h2><ul> |
| <li> |
| <a href='https://groovy-lang.org/mailing-lists.html' class='icon'><span class='fa fa-envelope'></span> Discuss on the mailing-list</a> |
| </li><li> |
| <a href='https://twitter.com/ApacheGroovy' class='icon'><span class='fa fa-twitter'></span> Groovy on Twitter</a> |
| </li><li> |
| <a href='https://groovy-lang.org/events.html' class='icon'><span class='fa fa-calendar'></span> Events and conferences</a> |
| </li><li> |
| <a href='https://github.com/apache/groovy' class='icon'><span class='fa fa-github'></span> Source code on GitHub</a> |
| </li><li> |
| <a href='https://groovy-lang.org/reporting-issues.html' class='icon'><span class='fa fa-bug'></span> Report issues in Jira</a> |
| </li><li> |
| <a href='http://stackoverflow.com/questions/tagged/groovy' class='icon'><span class='fa fa-stack-overflow'></span> Stack Overflow questions</a> |
| </li><li> |
| <a href='http://groovycommunity.com/' class='icon'><span class='fa fa-slack'></span> Slack Community</a> |
| </li> |
| </ul> |
| </nav><div class='st-pusher'> |
| <div class='st-content'> |
| <div class='st-content-inner'> |
| <!--[if lt IE 7]> |
| <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> |
| <![endif]--><div><div class='navbar navbar-default navbar-static-top' role='navigation'> |
| <div class='container'> |
| <div class='navbar-header'> |
| <button type='button' class='navbar-toggle' data-toggle='collapse' data-target='.navbar-collapse'> |
| <span class='sr-only'></span><span class='icon-bar'></span><span class='icon-bar'></span><span class='icon-bar'></span> |
| </button><a class='navbar-brand' href='../index.html'> |
| <i class='fa fa-star'></i> Apache Groovy |
| </a> |
| </div><div class='navbar-collapse collapse'> |
| <ul class='nav navbar-nav navbar-right'> |
| <li class=''><a href='https://groovy-lang.org/learn.html'>Learn</a></li><li class=''><a href='https://groovy-lang.org/documentation.html'>Documentation</a></li><li class=''><a href='/download.html'>Download</a></li><li class=''><a href='https://groovy-lang.org/support.html'>Support</a></li><li class=''><a href='/'>Contribute</a></li><li class=''><a href='https://groovy-lang.org/ecosystem.html'>Ecosystem</a></li><li class=''><a href='/blog'>Blog posts</a></li><li class=''><a href='https://groovy.apache.org/events.html'></a></li><li> |
| <a data-effect='st-effect-9' class='st-trigger' href='#'>Socialize</a> |
| </li><li class=''> |
| <a href='../search.html'> |
| <i class='fa fa-search'></i> |
| </a> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div><div id='content' class='page-1'><div class='row'><div class='row-fluid'><div class='col-lg-3'><ul class='nav-sidebar'><li><a href='./'>Blog index</a></li><li class='active'><a href='#doc'>Converting natural language into actions with NLPCraft and Groovy</a></li><li><a href='#_controlling_house_light_switches' class='anchor-link'>Controlling house light switches</a></li><li><a href='#_asking_for_the_time' class='anchor-link'>Asking for the time</a></li><li><a href='#_further_information' class='anchor-link'>Further information</a></li></ul><br/><ul class='nav-sidebar'><li style='padding: 0.35em 0.625em; background-color: #eee'><span>Related posts</span></li><li><a href='./natural-language-processing-with-groovy'>Natural Language Processing with Groovy, OpenNLP, CoreNLP, Nlp4j, Datumbox, Smile, Spark NLP, DJL and TensorFlow</a></li></ul></div><div class='col-lg-8 col-lg-pull-0'><a name='doc'></a><h1>Converting natural language into actions with NLPCraft and Groovy</h1><p><span>Author: <i>Paul King</i></span><br/><span>Published: 2023-03-10 07:22PM (Last updated: 2023-03-13 01:32PM)</span></p><hr/><div id="preamble"> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>This blog looks at using |
| <a href="https://nlpcraft.apache.org/index.html">Apache NLPCraft</a> |
| with Groovy.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Apache NLPCraft (incubating) is a library for converting |
| natural language into actions. |
| It is designed around an advanced Intent Definition Language (IDL) for |
| defining natural language <em>intents</em> and a fully deterministic intent |
| matching algorithm.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The |
| <a href="https://github.com/paulk-asert/groovy-data-science">groovy-data-science</a> |
| GitHub repo has an example using the previous 0.9.0 version of Apache NLPCraft. |
| The earlier version supported Java, Scala2, Kotlin and Groovy. |
| The |
| <a href="https://github.com/paulk-asert/groovy-data-science/blob/master/subprojects/LanguageProcessingNLPCraft/src/main/groovy/Lights.groovy">example</a> in the |
| <a href="https://github.com/paulk-asert/groovy-data-science/blob/master/subprojects/LanguageProcessingNLPCraft/">LanguageProcessingNLPCraft</a> project showed how |
| to interact with models in all 4 of those languages.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The project recently announced the release of version |
| <a href="https://nlpcraft.apache.org/relnotes/release-notes-1.0.0.html">1.0.0</a> |
| which represents a deep refactoring over 18 months. |
| The new version offers many enhancements and supports Scala3 for its models. |
| If you are going to be using NLPCraft extensively, then Scala3 |
| is probably your best choice as programming language. Having said that, |
| since we are on the JVM, certain integration steps aren’t too hard. |
| We’ll show using Groovy as the client language.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_controlling_house_light_switches">Controlling house light switches</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p><span class="image right"><img src="https://original.accentuate.io/556263801041/1636542278424/Lighting-Automation-Mob.jpg" alt="House lighting (source: accentuate.io)" width="180"></span> |
| First, a bit of background about the example. |
| We are trying to determine the intent behind English language |
| commands to turn lights on and off in a house. |
| We are going to use the project’s pre-defined model which is part of their examples. |
| It is defined using a combination of |
| <a href="https://nlpcraft.apache.org/examples/light_switch.html#model">YAML</a> |
| and |
| <a href="https://nlpcraft.apache.org/examples/light_switch.html#code">Scala3 code</a>. |
| The key thing to note is that the model is made up of a number of keywords |
| comprising <em>actions</em> and <em>locations</em>. |
| If these are matched, the lightswitch (<code>ls</code>) intent is triggered. |
| Actions and locations will become more obvious soon in our example.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Our example uses an English language model but NLPCraft can support |
| any natural language. |
| They provide the lightswitch model also in |
| <a href="https://nlpcraft.apache.org/examples/light_switch_fr.html">French</a> and other languages.</p> |
| </div> |
| <div class="paragraph"> |
| <p>We also need to add NLPCraft dependencies: <code>org.apache.nlpcraft:nlpcraft:1.0.0</code> |
| and <code>org.apache.nlpcraft:nlpcraft-example-lightswitch:1.0.0</code> (for the pre-compiled model). You can use <code>@Grab</code> statements in your script or add the dependencies to your build file.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <div class="title">Note</div> |
| </td> |
| <td class="content"> |
| Depending on the Groovy version and modules you are using, if you see exceptions |
| complaining about Jackson databind versions, simply exclude the Jackson versions |
| Groovy is referencing. They are more recent than what Scala is expecting. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>Finally, here is the Groovy code:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="prettyprint highlight"><code data-lang="groovy">import org.apache.nlpcraft.NCModelClient |
| import org.apache.nlpcraft.examples.lightswitch.LightSwitchModel |
| import static scala.collection.immutable.HashMap$.MODULE$ as ScalaMap |
| |
| var data = ScalaMap.empty() // no optional data |
| var user = 'someUserId' |
| var expectedIntent = 'ls' // from model |
| |
| var phrases = [ |
| 'Turn on the lights in the master bedroom', |
| 'Please, no lights!', |
| 'Turn up the illumination in garage and 1st floor' |
| ] |
| |
| new NCModelClient(new LightSwitchModel()).withCloseable { client -> |
| phrases.each { phrase -> |
| var result = client.ask(phrase, user, data) |
| println result.body |
| assert result.intentId.get() == expectedIntent |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Here, we are just going to print the result returned by the callback |
| in the model class. Typically, we’d instead have HomeKit, Arduino or |
| some other kind of integration at this point. We’ll also check that |
| the <code>ls</code> intent was triggered.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When we run this script, our assertions pass, and the output is:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>Lights are [on] in [master bedroom]. |
| Lights are [off] in [entire house]. |
| Lights are [on] in [1st floor, garage].</pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_asking_for_the_time">Asking for the time</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p><span class="image right"><img src="https://www.personalrobots.biz/wp-content/uploads/2021/10/takara-robot-watch-calculator.jpg" alt="Robot watch (source: personalrobots.biz)" width="150"></span> |
| Let’s now look at the NLPCraft <code>time</code> <a href="https://nlpcraft.apache.org/examples/time.html">example</a>. |
| It’s a very simple world time bot implementation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The model is again defined as a combination of |
| <a href="https://nlpcraft.apache.org/examples/time.html#model">YAML</a> |
| and |
| <a href="https://nlpcraft.apache.org/examples/time.html#code">Scala3 code</a>. |
| A pre-compiled version is available as |
| <code>org.apache.nlpcraft:nlpcraft-example-time:1.0.0</code> from Maven central. |
| We used a locally built version with <code>DefaultScalaModule</code> enabled |
| for YAML processing. |
| We also need the <code>groovy-yaml</code> module on the Groovy side if not already there.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The model defines two intents:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>intent2</code> should be triggered |
| if a match is found for a city location.</p> |
| </li> |
| <li> |
| <p><code>intent1</code> will be triggered |
| if it looks like you are asking for the time without a city; this |
| corresponds to finding the local time.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Here is the Groovy client code:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="prettyprint highlight"><code data-lang="groovy">import groovy.yaml.YamlSlurper |
| import org.apache.nlpcraft.NCModelClient |
| import org.apache.nlpcraft.examples.time.TimeModel |
| import static scala.collection.immutable.HashMap$.MODULE$ as ScalaMap |
| |
| var data = ScalaMap.empty() // no optional data |
| var user = 'someUserId' |
| var phrases = [ |
| "What time is it now in New York City?" : 'intent2', |
| "What's the current time in Singapore?" : 'intent2', |
| "Show me time of the day in London." : 'intent2', |
| "Can you please give me Tokyo's current date and time." : 'intent2', |
| "What's the local time?" : 'intent1' |
| ] |
| |
| new NCModelClient(new TimeModel()).withCloseable { client -> |
| phrases.each { phrase, expected -> |
| var result = client.ask(phrase, user, data) |
| assert result.intentId.get() == expected |
| var body = new YamlSlurper().parseText(result.body) |
| body.with{ println "$city, $country: $localTime" } |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Again, all our assertions pass, and here is the output:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>New york city, United states: 12 Mar. 2023, 10:09:41 pm |
| Singapore, Singapore: 13 Mar. 2023, 10:09:41 am |
| London, United kingdom: 13 Mar. 2023, 2:09:41 am |
| Tokyo, Japan: 13 Mar. 2023, 11:09:41 am |
| Brisbane, Australia: 13 Mar. 2023, 12:09:42 pm</pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_further_information">Further information</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p><a href="https://nlpcraft.apache.org/index.html">Apache NLPCraft website</a></p> |
| </div> |
| <div class="sidebarblock"> |
| <div class="content"> |
| <div class="title">Update history</div> |
| <div class="paragraph"> |
| <p><strong>13/Mar/2023</strong>: Added the time example.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div></div></div></div></div><footer id='footer'> |
| <div class='row'> |
| <div class='colset-3-footer'> |
| <div class='col-1'> |
| <h1>Groovy</h1><ul> |
| <li><a href='https://groovy-lang.org/learn.html'>Learn</a></li><li><a href='https://groovy-lang.org/documentation.html'>Documentation</a></li><li><a href='/download.html'>Download</a></li><li><a href='https://groovy-lang.org/support.html'>Support</a></li><li><a href='/'>Contribute</a></li><li><a href='https://groovy-lang.org/ecosystem.html'>Ecosystem</a></li><li><a href='/blog'>Blog posts</a></li><li><a href='https://groovy.apache.org/events.html'></a></li> |
| </ul> |
| </div><div class='col-2'> |
| <h1>About</h1><ul> |
| <li><a href='https://github.com/apache/groovy'>Source code</a></li><li><a href='https://groovy-lang.org/security.html'>Security</a></li><li><a href='https://groovy-lang.org/learn.html#books'>Books</a></li><li><a href='https://groovy-lang.org/thanks.html'>Thanks</a></li><li><a href='http://www.apache.org/foundation/sponsorship.html'>Sponsorship</a></li><li><a href='https://groovy-lang.org/faq.html'>FAQ</a></li><li><a href='https://groovy-lang.org/search.html'>Search</a></li> |
| </ul> |
| </div><div class='col-3'> |
| <h1>Socialize</h1><ul> |
| <li><a href='https://groovy-lang.org/mailing-lists.html'>Discuss on the mailing-list</a></li><li><a href='https://twitter.com/ApacheGroovy'>Groovy on Twitter</a></li><li><a href='https://groovy-lang.org/events.html'>Events and conferences</a></li><li><a href='https://github.com/apache/groovy'>Source code on GitHub</a></li><li><a href='https://groovy-lang.org/reporting-issues.html'>Report issues in Jira</a></li><li><a href='http://stackoverflow.com/questions/tagged/groovy'>Stack Overflow questions</a></li><li><a href='http://groovycommunity.com/'>Slack Community</a></li> |
| </ul> |
| </div><div class='col-right'> |
| <p> |
| The Groovy programming language is supported by the <a href='http://www.apache.org'>Apache Software Foundation</a> and the Groovy community. |
| </p><div text-align='right'> |
| <img src='../img/asf_logo.png' title='The Apache Software Foundation' alt='The Apache Software Foundation' style='width:60%'/> |
| </div><p>Apache® and the Apache feather logo are either registered trademarks or trademarks of The Apache Software Foundation.</p> |
| </div> |
| </div><div class='clearfix'>© 2003-2023 the Apache Groovy project — Groovy is Open Source: <a href='http://www.apache.org/licenses/LICENSE-2.0.html' alt='Apache 2 License'>license</a>, <a href='https://privacy.apache.org/policies/privacy-policy-public.html'>privacy policy</a>.</div> |
| </div> |
| </footer></div> |
| </div> |
| </div> |
| </div> |
| </div><script src='../js/vendor/jquery-1.10.2.min.js' defer></script><script src='../js/vendor/classie.js' defer></script><script src='../js/vendor/bootstrap.js' defer></script><script src='../js/vendor/sidebarEffects.js' defer></script><script src='../js/vendor/modernizr-2.6.2.min.js' defer></script><script src='../js/plugins.js' defer></script><script src='https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js'></script><script>document.addEventListener('DOMContentLoaded',prettyPrint)</script><script> |
| (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ |
| (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), |
| m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) |
| })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); |
| |
| ga('create', 'UA-257558-10', 'auto'); |
| ga('send', 'pageview'); |
| </script> |
| </body></html> |