You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nlpcraft.apache.org by ar...@apache.org on 2020/08/21 21:54:31 UTC
[incubator-nlpcraft-website] branch master updated: Reworked
weather example docs.
This is an automated email from the ASF dual-hosted git repository.
aradzinski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft-website.git
The following commit(s) were added to refs/heads/master by this push:
new 4bc5ebe Reworked weather example docs.
4bc5ebe is described below
commit 4bc5ebeb2716dbced3cc38551f918922a9881cdc
Author: Aaron Radzinski <ar...@datalingvo.com>
AuthorDate: Fri Aug 21 14:54:21 2020 -0700
Reworked weather example docs.
---
examples/weather_bot.html | 205 +++++++++++++++-------------------------------
1 file changed, 64 insertions(+), 141 deletions(-)
diff --git a/examples/weather_bot.html b/examples/weather_bot.html
index 2094f15..ce5ab42 100644
--- a/examples/weather_bot.html
+++ b/examples/weather_bot.html
@@ -154,28 +154,47 @@ id: weather_bot
<code>Line 10</code> defines an element <code>wt:phen</code> for various weather phenomenon.
</li>
<li>
- <code>Line 18</code> defines an element <code>wt:hist</code> which presence will indicate the
+ <code>Line 18</code> defines an element <code>wt:hist</code> whose presence will indicate the
request for the past (history) weather information.
</li>
<li>
- <code>Line 28</code> defines an element <code>wt:fcast</code> which presence will indicate the
+ <code>Line 28</code> defines an element <code>wt:fcast</code> whose presence will indicate the
request for the future (forecast) weather information.
</li>
</ul>
<p>
- Now that our model is ready let's create a Java class that would load this model and define intents
- that use the model elements we have just defined.
+ Now that our model is ready let's create a Java class that would load this model and define the intent
+ that uses the model elements we have just defined.
</p>
</section>
<section id="code">
<h3 class="section-title">Model Class</h3>
<p>
- Our Java implementation uses one auxiliary class <a target="github" href="https://github.com/apache/incubator-nlpcraft/blob/master/src/main/scala/org/apache/nlpcraft/examples/weather/WeatherResultWrapper.java">WeatherResultWrapper.java</a>
- that is used for JSON result formatting. Note that the main <a target="github" href="https://github.com/apache/incubator-nlpcraft/blob/master/src/main/scala/org/apache/nlpcraft/examples/weather/WeatherModel.java">WeatherModel</a> class
- have number of utility methods that we'll skip here (you can see the entire class by following the link above) and
- we'll concentrate on the intents only:
+ Below is a full source code for our implementation. Note that this code uses several
+ <a href="#tools">external tools</a> for IP-based geo-location and the weather information
+ provider (Dark Sky). Note also that despite its apparent simplicity the model logic implementation is non-trivial.
+ Significant portion of the code deals with a complex <b>temporal and geographical ambiguity</b>, i.e. the sentences like the these:
</p>
- <pre class="brush: java, highlight: []">
+ <dl>
+ <dt>
+ <code>'show my local weather'</code> vs <code>'show local Boston weather'</code>
+ </dt>
+ <dd>
+ In the first sentence the word <code>local</code> indicates that the user is asking about her local weather
+ (i.e. the weather for the location based on the IP address of the user's REST agent). However, in the
+ second sentence the same word <code>local</code> is effectively ignored as user clearly indicated the city
+ for the weather request (Boston).
+ </dd>
+ <dt>
+ <code>'show weather forecast'</code> vs <code>'show weather forecast for today'</code> vs <code>'show last week weather forecast'</code>
+ </dt>
+ <dd>
+ In these three sentences the word <code>forecast</code> defines future, current and past timeframe for the
+ weather request. It acts as a future indicator in the first sentence and is effectively ignored in the second
+ and third sentences.
+ </dd>
+ </dl>
+ <pre class="brush: java, highlight: [24, 71, 79, 97, 99, 100, 101, 146]">
package org.apache.nlpcraft.examples.weather;
import com.google.gson.Gson;
@@ -330,42 +349,26 @@ public class WeatherModel extends NCModelFileAdapter {
}
}
</pre>
- <p>
- There three methods define three intents. Each intent is defined "in place", i.e. as an annotation on the
- method that acts as a callback for that intent:
- </p>
<ul>
<li>
- Line 1 defines intent and the callback for the weather forecast (weather in the future):
- <ul>
- <li>Intent is ordered (default), supports conversation (default) and has ID <code>fcast</code></li>
- <li>Intent has one mandatory term and two optional terms:
- <ul>
- <li>
- Mandatory term is defined as a token with ID <code>wt:fcast</code> as defined
- in the model.
- </li>
- <li>
- Two optional terms (their IDs are <code>city</code> and <code>date</code>) define
- optional city and date for the weather report. If not provided, their will be taken
- from either conversation context or assume the default value (current IP geo location
- and current time, if available).
- </li>
- </ul>
- </li>
- </ul>
+ <code>Line 146</code> loads the model configuration from the external <code>weather_model.json</code>
+ file.
+ </li>
+ <li>
+ Method <code>preGeo(...)</code> on the <code>line 24</code> handles the geo location processing including
+ IP-based geo-location and resolution of the geographical ambiguity.
</li>
<li>
- Lines 3-5 define formal parameters for the <code>fcast</code> intent callback method. Note that we use term IDs
- (<code>city</code> and <code>date</code>) in <code>@NCIntentTerm</code> annotations to automatically
- assign tokens from the detected terms to their corresponding method formal parameters.
+ <code>Line 97</code> defines a callback for the intent defined on the <code>line 71</code>. Note that
+ callback implementation also deals with the temporal ambiguity.
</li>
<li>
- Lines 10-14 and lines 19-23 define two other intents and their callbacks methods in the same manner.
+ <code>Lines 99, 100, and 101</code> define formal callback method parameters that correspond
+ to the intent's terms (see <code>line 71</code>).
</li>
<li>
- Implementation of all intent callback method is pretty straightforward and deals mostly with figuring
- out the default location and time if either one isn't provided.
+ <code>Line 79</code> defines input sentence samples that are used for both documentation as well as
+ auto-validation purposed (see <a href="#testing">testing</a> second for details).
</li>
</ul>
</section>
@@ -460,136 +463,56 @@ public class WeatherModel extends NCModelFileAdapter {
<section id="testing">
<h3 class="section-title">Testing</h3>
<p>
- NLPCraft comes with easy to use <a href="/tools/test_framework.html">test framework</a> for
- data models that can be used with
- any unit testing framework like JUnit or ScalaTest. It is essentially a simplified
- version of Java REST client that is custom designed for data model testing.
+ Let's develop a unit test for our model. Remember the <a target="javadoc" href="/apis/latest/org/apache/nlpcraft/model/NCIntentSample.html">@NCIntentSample</a>
+ annotation we have used in our code next to intent definition? Auto-testing utility is relying on it.
</p>
<p>
- We would like to test with following user requests:
+ <p>
+ Part of the <a href="/tools/test_framework.html">test framework</a>, the auto-validator class <a
+ target="javadoc"
+ href="/apis/latest/org/apache/nlpcraft/model/tools/test/NCTestAutoModelValidator.html">NCTestAutoModelValidator</a> takes one or more model IDs
+ (or class names) and performs validation. Validation consists of starting an embedded probe with a given model,
+ scanning for <a target="javadoc" href="/apis/latest/org/apache/nlpcraft/model/NCIntentSample.html">@NCIntentSample</a> annotations
+ and their corresponding callback methods, submitting each sample input
+ sentences from <a target="javadoc" href="/apis/latest/org/apache/nlpcraft/model/NCIntentSample.html">@NCIntentSample</a>
+ annotation and checking that resulting intent matches the intent the sample was attached to.
</p>
- <ul>
- <li><code>"What's the local weather forecast?"</code></li>
- <li><code>"What's the weather in Moscow?"</code></li>
- <li><code>"Chance of snow?"</code> (using conversation context)</li>
- <li><code>"Moscow?"</code> (using conversation context).</li>
- </ul>
<p>
- Let's create new Java class <code>WeatherTest.java</code> with the following code:
+ Note that auto-testing does not require any additional code to be written - the class gathers all required information from the model
+ itself.
</p>
- <pre class="brush: java, highlight: [47, 43, 55, 59]">
-package org.apache.nlpcraft.examples.weather;
-
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
-import org.apache.nlpcraft.common.NCException;
-import org.apache.nlpcraft.model.tools.test.NCTestClient;
-import org.apache.nlpcraft.model.tools.test.NCTestClientBuilder;
-import org.apache.nlpcraft.model.tools.test.NCTestResult;
-import org.apache.nlpcraft.probe.embedded.NCEmbeddedProbe;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import java.io.IOException;
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-class WeatherTest {
- private static final Gson GSON = new Gson();
- private static final Type TYPE_MAP_RESP = new TypeToken<HashMap<String, Object>>() {}.getType();
- private NCTestClient cli;
-
- private void checkIntent(String txt, String intentId, boolean shouldBeSame) throws NCException, IOException {
- NCTestResult res = cli.ask(txt);
-
- assertTrue(res.isOk(), () -> res.getResultError().get());
-
- assert res.getResult().isPresent();
-
- Map<String, Object> map = GSON.fromJson(res.getResult().get(), TYPE_MAP_RESP);
-
- if (shouldBeSame)
- assertEquals(intentId, map.get("intentId"));
- else
- assertNotEquals(intentId, map.get("intentId"));
- }
-
- @BeforeEach
- void setUp() throws NCException, IOException {
- NCEmbeddedProbe.start(WeatherModel.class);
-
- cli = new NCTestClientBuilder().newBuilder().build();
-
- cli.open("nlpcraft.weather.ex"); // See weather_model.json
- }
-
- @AfterEach
- void tearDown() throws NCException, IOException {
- if (cli != null)
- cli.close();
-
- NCEmbeddedProbe.stop();
- }
-
- @Test
- void test() throws NCException, IOException {
- // Empty parameter.
- assertTrue(cli.ask("").isFailed());
-
- // Only latin charset is supported.
- assertTrue(cli.ask("El tiempo en España").isFailed());
-
- // Should be passed.
- checkIntent("What's the local weather forecast?", "fcast", true);
- checkIntent("What's the weather in Moscow?", "curr", true);
- // Can be answered with conversation.
- checkIntent("Chance of snow?", "curr", true);
- checkIntent("Moscow", "curr", true);
-
- cli.clearConversation();
-
- // Cannot be answered without conversation.
- assertTrue(cli.ask("Moscow").isFailed());
- }
-}
- </pre>
<p>
- This test is pretty straight forward:
+ Let's configure IDEA Runtime Configuration (remember - there's no need to write any additional code here):
</p>
<ul>
<li>
- On line 47 we open the test client with the model ID (see <code>weather_model.yaml</code>
- file for where we declared it).
+ <b>Main class:</b> <code>org.apache.nlpcraft.model.tools.test.NCTestAutoModelValidator</code>
</li>
<li>
- Test on line 59 is where we issue our test sentences and we should see
- the confirmation messages in our test console output.
+ <b>VM options: </b> <code>-DNLPCRAFT_TEST_MODELS=org.apache.nlpcraft.examples.weather.WeatherModel</code>
</li>
</ul>
<div class="bq info">
<p><b>Embedded Probe</b></p>
<p>
- This test uses <a href="/tools/embedded_probe.html">embedded probe</a> which automatically
- starts and stops the data probe from within the tests itself. See lines 43 and 55 for details.
+ This test (as well as manual test client from <a href="/tools/test_framework.html">test framework</a>) use
+ <a href="/tools/embedded_probe.html">embedded probe</a> which automatically
+ starts and stops the data probe from within the tests itself. However, when not testing you will need
+ to start data probe separately.
</p>
<p>
- <b>NOTE:</b> when using this test you don't need to start data probe standalone in a previous step.
+ <b>NOTE:</b> when using this test you don't need to start data probe standalone.
</p>
</div>
<p>
- Right click on this class in the project view and run it. You should be getting standard output in
- JUnit panel as well as the output in the data probe console.
+ Start this Runtime Configuration and you should be getting standard log in the output console.
</p>
</section>
<section>
<h2 class="section-title">Done! 👌</h2>
<p>
- You've created pretty full featured weather bot data model, deployed it into the data probe, started the
- REST server and tested this model using JUnit 5 and the built-in test framework.
+ You've created alarm clock data model, deployed it into the data probe, started the
+ REST server and tested this model using the built-in test framework.
</p>
</section>
</div>