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 f4bcd1d  WIP.
f4bcd1d is described below

commit f4bcd1d3527051f38d276c13acbcb67176127206
Author: Aaron Radzinski <[email protected]>
AuthorDate: Thu Aug 20 21:33:14 2020 -0700

    WIP.
---
 _layouts/documentation.html |   7 ++
 examples/weather_bot.html   | 273 ++++++++++++++++++++++++++++----------------
 intent-matching.html        |   2 +-
 tools/model_inspector.html  |  45 ++++++++
 4 files changed, 229 insertions(+), 98 deletions(-)

diff --git a/_layouts/documentation.html b/_layouts/documentation.html
index 074e27d..51b3a61 100644
--- a/_layouts/documentation.html
+++ b/_layouts/documentation.html
@@ -127,6 +127,13 @@ layout: interior
                 <a href="/tools/sql_model_gen.html">SQL Model Generator</a>
                 {% endif %}
             </li>
+            <li>
+                {% if page.id == "model_inspector" %}
+                <a class="active" href="/tools/model_inspector.html">Model 
Inspector</a>
+                {% else %}
+                <a href="/tools/model_inspector.html">Model Inspector</a>
+                {% endif %}
+            </li>
             <li class="side-nav-title">Examples</li>
             <li>
                 {% if page.id == "alarm_clock" %}
diff --git a/examples/weather_bot.html b/examples/weather_bot.html
index 5d07fa0..2094f15 100644
--- a/examples/weather_bot.html
+++ b/examples/weather_bot.html
@@ -108,85 +108,58 @@ id: weather_bot
             <code>NCModelFileAdapter</code> in our Java-based model 
implementation. Create new <code>weather_model.json</code>
             file and add the following model declaration into it:
         </p>
-        <pre class="brush: js, highlight: [10, 42, 50, 59]">
+        <pre class="brush: js, highlight: [10, 18, 28]">
 {
-    "id": "nlpcraft.weather.ex",
-    "name": "Weather Example Model",
-    "version": "1.0",
-    "description": "Weather example model.",
-    "examples": [
-        "What's the local weather forecast?",
-        "What's the weather in Moscow?"
-    ],
-    "macros": [
-        {
-            "name": "&lt;OF&gt;",
-            "macro": "{of|for|per}"
-        },
-        {
-            "name": "&lt;CHANCE&gt;",
-            "macro": 
"{chance|possibility|probability|odds|likelihood|potential|risk|opportunity}"
-        },
-        {
-            "name": "&lt;PHENOMENON&gt;",
-            "macro": "{high sea|severe weather|hail|heat wave|cold 
wave|derecho|supercell|avalanche|cyclone|wildfire|landslide|firestorm|dust 
storm|thunder snow|winter 
storm|cloudburst|shower|condensation|precipitation|drizzle|rainstorm|rain 
storm|rainfall|rain|storm|sun|sunshine|cloud|hot|cold|dry|wet|wind||hurricane|typhoon|sand-storm|sand
 storm|tornado|humid|fog|snow|smog|black 
ice|haze|thundershower|thundersnow|sleet|drought|wildfire|blizzard|avalanche|mist|thunderstorm}"
-        },
-        {
-            "name": "&lt;CUR&gt;",
-            "macro": "{current|present|moment|now}"
-        },
-        {
-            "name": "&lt;WEATHER&gt;",
-            "macro": "{weather 
{condition|temp|temperature|data|*}|condition|temp|temperature}"
-        },
-        {
-            "name": "&lt;FORECAST&gt;",
-            "macro": "{forecast|prognosis|prediction}"
-        },
-        {
-            "name": "&lt;HISTORY&gt;",
-            "macro": "{history|past}"
-        }
-    ],
-    "elements": [
-        {
-            "id": "wt:hist",
-            "description": "Past weather conditions.",
-            "synonyms": [
-                "{&lt;WEATHER&gt;|*} &lt;HISTORY&gt;",
-                "&lt;HISTORY&gt; {&lt;OF&gt;|*} 
{&lt;WEATHER&gt;|&lt;PHENOMENON&gt;}"
-            ]
-        },
-        {
-            "id": "wt:curr",
-            "description": "Current weather conditions.",
-            "synonyms": [
-                "{&lt;CUR&gt;|*} {&lt;WEATHER&gt;|&lt;PHENOMENON&gt;}",
-                "&lt;CHANCE&gt; &lt;OF&gt; &lt;PHENOMENON&gt;",
-                "&lt;PHENOMENON&gt; {&lt;CHANCE&gt;|*}"
-            ]
-        },
-        {
-            "id": "wt:fcast",
-            "description": "Future weather forecast.",
-            "synonyms": [
-                "{&lt;PHENOMENON&gt;|&lt;WEATHER&gt;|*} &lt;FORECAST&gt;",
-                "&lt;FORECAST&gt; {&lt;OF&gt;|*} 
{&lt;WEATHER&gt;|&lt;PHENOMENON&gt;}"
-            ]
-        }
-    ]
+  "id": "nlpcraft.weather.ex",
+  "name": "Weather Example Model",
+  "version": "1.0",
+  "description": "Weather example model.",
+  "macros": [
+  ],
+  "elements": [
+    {
+      "id": "wt:phen",
+      "description": "Weather phenomenon.",
+      "synonyms": [
+        "{high sea|severe weather|hail|heat wave|cold 
wave|derecho|supercell|avalanche|cyclone|wildfire|landslide|firestorm|dust 
storm|thunder snow|winter 
storm|cloudburst|shower|condensation|precipitation|drizzle|rainstorm|rain 
storm|rainfall|rain|storm|sun|sunshine|cloud|hot|cold|dry|wet|wind||hurricane|typhoon|sand-storm|sand
 storm|tornado|humid|fog|snow|smog|black 
ice|haze|thundershower|thundersnow|sleet|drought|wildfire|blizzard|avalanche|mist|thunderstorm}",
+        "{weather 
{condition|temp|temperature|data|*}|condition|temp|temperature}"
+      ]
+    },
+    {
+      "id": "wt:hist",
+      "description": "History (past) indicator.",
+      "groups": [
+        "indicator"
+      ],
+      "synonyms": [
+        "{history|past|previous}"
+      ]
+    },
+    {
+      "id": "wt:fcast",
+      "description": "Forecast (future) indicator.",
+      "groups": [
+        "indicator"
+      ],
+      "synonyms": [
+        "{future|forecast|prognosis|prediction}"
+      ]
+    }
+  ]
 }
         </pre>
         <p>There are number of important points here:</p>
         <ul>
             <li>
-                <code>Line 10</code> defines several macros that are used 
later on throughout the model's elements
-                to shorten the synonym declarations. Note how macros coupled 
with option groups
-                shorten overall synonym declarations 1000:1 vs. manually 
listing all possible word permutations.
+                <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
+                request for the past (history) weather information.
             </li>
             <li>
-                <code>Lines 42, 50, 59</code> define three model elements: the 
past, present and future (forecast) weather
-                condition.
+                <code>Line 28</code> defines an element <code>wt:fcast</code> 
which presence will indicate the
+                request for the future (forecast) weather information.
             </li>
         </ul>
         <p>
@@ -202,43 +175,138 @@ id: weather_bot
             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:
         </p>
-        <pre class="brush: java, highlight: [1, 2, 3, 4, 5, 10, 11, 12, 13, 
14, 19, 20, 21, 22, 23]">
-    @NCIntent("intent=fcast term={id == 'wt:fcast'} term(city)={id == 
'nlpcraft:city'}? term(date)={id == 'nlpcraft:date'}?")
-    public NCResult onForecastMatch(
-        NCIntentMatch ctx,
-        @NCIntentTerm("city") Optional&lt;NCToken&gt; cityTokOpt,
-        @NCIntentTerm("date") Optional&lt;NCToken&gt; dateTokOpt
-    ) {
-        return onPeriodMatch(ctx, cityTokOpt, dateTokOpt, 5);
-    }
-                
-    @NCIntent("intent=hist term={id == 'wt:hist'} term(city)={id == 
'nlpcraft:city'}? term(date)={id == 'nlpcraft:date'}?")
-    public NCResult onHistoryMatch(
-        NCIntentMatch ctx,
-        @NCIntentTerm("city") Optional&lt;NCToken&gt; cityTokOpt,
-        @NCIntentTerm("date") Optional&lt;NCToken&gt; dateTokOpt
-    ) {
-        return onPeriodMatch(ctx, cityTokOpt, dateTokOpt, -5);
+        <pre class="brush: java, highlight: []">
+package org.apache.nlpcraft.examples.weather;
+
+import com.google.gson.Gson;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.nlpcraft.examples.misc.darksky.DarkSkyException;
+import org.apache.nlpcraft.examples.misc.darksky.DarkSkyService;
+import org.apache.nlpcraft.examples.misc.geo.keycdn.GeoManager;
+import org.apache.nlpcraft.examples.misc.geo.keycdn.beans.GeoDataBean;
+import org.apache.nlpcraft.model.*;
+import java.time.Instant;
+import java.util.*;
+import static java.time.temporal.ChronoUnit.DAYS;
+
+public class WeatherModel extends NCModelFileAdapter {
+    // Please register your own account at 
https://darksky.net/dev/docs/libraries and
+    // replace this demo token with your own.
+    private final DarkSkyService darkSky = new 
DarkSkyService("097e1aad75b22b88f494cf49211975aa", 31);
+
+    private final GeoManager geoMrg = new GeoManager();
+    private static final int DAYS_SHIFT = 5;
+    private static final Gson GSON = new Gson();
+    private static final Set&lt;String&gt; LOCAL_WORDS = new 
HashSet&lt;&gt;(Arrays.asList("my", "local", "hometown"));
+
+    private Pair&lt;Double, Double&gt; prepGeo(NCIntentMatch ctx, 
Optional&lt;NCToken&gt; geoTokOpt) throws NCRejection {
+        if (geoTokOpt.isPresent()) {
+            NCToken geoTok = geoTokOpt.get();
+
+            Map&lt;String, Object&gt; cityMeta = 
geoTok.meta("nlpcraft:city:citymeta");
+
+            Double lat = (Double)cityMeta.get("latitude");
+            Double lon = (Double)cityMeta.get("longitude");
+
+            if (lat == null || lon == null) {
+                String city = geoTok.meta("nlpcraft:city:city");
+
+                throw new NCRejection(String.format("Latitude and longitude 
not found for: %s", city));
+            }
+
+            return Pair.of(lat, lon);
+        }
+
+        Optional&lt;GeoDataBean&gt; geoOpt = 
geoMrg.get(ctx.getContext().getRequest());
+
+        if (!geoOpt.isPresent())
+            throw new NCRejection("City cannot be determined.");
+
+        // Manually process request for local weather. We need to separate 
between 'local Moscow weather'
+        // and 'local weather' which are different. Basically, if there is 
word 'local/my/hometown' in the user
+        // input and there is no city in the current sentence - this is a 
request for the weather at user's
+        // current location, i.e. we should implicitly assume user's location 
and clear conversion context.
+        // In all other cases - we take location from either current sentence 
or conversation STM.
+
+        // NOTE: we don't do this separation on intent level as it is easier 
to do it here instead of
+        // creating more intents with almost identical callbacks.
+
+        @SuppressWarnings("SuspiciousMethodCalls")
+        boolean hasLocalWord =
+            ctx.getVariant().stream().anyMatch(t -&gt; 
LOCAL_WORDS.contains(t.meta("nlpcraft:nlp:origtext")));
+
+        if (hasLocalWord)
+            // Because we implicitly assume user's current city at this point 
we need to clear
+            // 'nlpcraft:city' tokens from conversation since they would no 
longer be valid.
+            ctx.getContext().getConversation().clearStm(t -&gt; 
t.getId().equals("nlpcraft:city"));
+
+        // Try current user location.
+        GeoDataBean geo = geoOpt.get();
+
+        return Pair.of(geo.getLatitude(), geo.getLongitude());
     }
-                        
-    @NCIntent("intent=curr term={id == 'wt:curr'} term(city)={id == 
'nlpcraft:city'}? term(date)={id == 'nlpcraft:date'}?")
-    public NCResult onCurrentMatch(
+                    
+    @NCIntent(
+        "intent=req " +
+        "conv=true " + // Support conversation context (i.e. short term 
memory).
+        "term={id == 'wt:phen'}+ " + // One or more weather phenomenon (at 
least is mandatory).
+        "term(ind)={groups @@ 'indicator'}* " + // Optional indicator words 
(zero or more).
+        "term(city)={id == 'nlpcraft:city'}? " + // Optional city.
+        "term(date)={id == 'nlpcraft:date'}?" // Optional date (overrides 
indicator words).
+    )
+    @NCIntentSample({
+        "What's the local weather forecast?",
+        "What's the weather in Moscow?",
+        "What is the weather like outside?",
+        "How's the weather?",
+        "What's the weather forecast for the rest of the week?",
+        "What's the weather forecast this week?",
+        "What's the weather out there?",
+        "Is it cold outside?",
+        "Is it hot outside?",
+        "Will it rain today?",
+        "When it will rain in Delhi?",
+        "Is there any possibility of rain in Delhi?",
+        "Is it raining now?",
+        "Is there any chance of rain today?",
+        "Was it raining in Beirut last week?",
+        "How about yesterday?"
+    })
+    public NCResult onMatch(
         NCIntentMatch ctx,
+        @NCIntentTerm("ind") List&lt;NCToken&gt; indToksOpt,
         @NCIntentTerm("city") Optional&lt;NCToken&gt; cityTokOpt,
         @NCIntentTerm("date") Optional&lt;NCToken&gt; dateTokOpt
     ) {
-        checkMatch(ctx);
+        // Reject if intent match is not exact (at least one "dangling" token 
remain).
+        if (ctx.isAmbiguous())
+            throw new NCRejection("Please clarify your request.");
 
         try {
-            Coordinate cr = prepGeo(ctx, cityTokOpt);
+            Instant now = Instant.now();
 
-            if (dateTokOpt.isPresent()) {
-                DateRange range = extractDate(dateTokOpt.get());
+            Instant from = now;
+            Instant to = now;
 
-                return makeResult(srv.getTimeMachine(cr.latitude, 
cr.longitude, range.from, range.to), ctx.getIntentId());
+            if (indToksOpt.stream().anyMatch(tok -&gt; 
tok.getId().equals("wt:hist")))
+                from = from.minus(DAYS_SHIFT, DAYS);
+            else if (indToksOpt.stream().anyMatch(tok -&gt; 
tok.getId().equals("wt:fcast")))
+                to = from.plus(DAYS_SHIFT, DAYS);
+
+            if (dateTokOpt.isPresent()) { // Date token overrides any 
indicators.
+                NCToken dateTok = dateTokOpt.get();
+
+                from = 
Instant.ofEpochMilli(dateTok.meta("nlpcraft:date:from"));
+                to = Instant.ofEpochMilli(dateTok.meta("nlpcraft:date:to"));
             }
 
-            return makeResult(srv.getCurrent(cr.latitude, cr.longitude), 
ctx.getIntentId());
+            Pair&lt;Double, Double&gt; latLon = prepGeo(ctx, cityTokOpt); // 
Handles optional city too.
+
+            double lat = latLon.getLeft();
+            double lon = latLon.getRight();
+
+            return NCResult.json(GSON.toJson(from == to ? 
darkSky.getCurrent(lat, lon) :
+                darkSky.getTimeMachine(lat, lon, from, to)));
         }
         catch (DarkSkyException e) {
             throw new NCRejection(e.getLocalizedMessage());
@@ -250,6 +318,17 @@ id: weather_bot
             throw new NCRejection("Weather provider error.", e);
         }
     }
+                                
+    public WeatherModel() {
+        // Load model from external JSON file on classpath.
+        super("org/apache/nlpcraft/examples/weather/weather_model.json");
+    }
+
+    @Override
+    public void onDiscard() {
+        darkSky.stop();
+    }
+}
         </pre>
         <p>
             There three methods define three intents. Each intent is defined 
"in place", i.e. as an annotation on the
diff --git a/intent-matching.html b/intent-matching.html
index fd6b25e..c433ac0 100644
--- a/intent-matching.html
+++ b/intent-matching.html
@@ -78,7 +78,7 @@ id: intent_matching
                         Optional annotation that provides one or more sample 
of the input that associated intent should match on.
                         Although this annotation is optional it's highly 
recommended to provide at least 5 samples per intent.
                         These samples serve not only documentation purpose but 
also used in built-in model <a 
href="/tools/test_framework.html">auto-validation</a>
-                        and model lint tool.
+                        and <a href="/tools/model_inspector.html">model 
inspector</a> tool.
                     </td>
                 </tr>
             </tbody>
diff --git a/tools/model_inspector.html b/tools/model_inspector.html
new file mode 100644
index 0000000..18321cf
--- /dev/null
+++ b/tools/model_inspector.html
@@ -0,0 +1,45 @@
+---
+active_crumb: Model Inspector
+layout: documentation
+id: model_inspector
+---
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<div class="col-md-8 second-column">
+    <section id="overview">
+        <h2 class="section-title">Overview</h2>
+    </section>
+    <section id="usage">
+        <h2 class="section-title">Usage</h2>
+    </section>
+</div>
+<div class="col-md-2 third-column">
+    <ul class="side-nav">
+        <li class="side-nav-title">On This Page</li>
+        <li><a href="#overview">Overview</a></li>
+        <li><a href="#usage">Usage</a></li>
+        {% include quick-links.html %}
+    </ul>
+</div>
+
+
+
+
+
+

Reply via email to