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/13 22:44:01 UTC
[incubator-nlpcraft] branch NLPCRAFT-41 updated: Refactored weather
example.
This is an automated email from the ASF dual-hosted git repository.
aradzinski pushed a commit to branch NLPCRAFT-41
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git
The following commit(s) were added to refs/heads/NLPCRAFT-41 by this push:
new 292f1af Refactored weather example.
292f1af is described below
commit 292f1afafb998c117baae9a73e52359c8a910539
Author: Aaron Radzinski <ar...@datalingvo.com>
AuthorDate: Thu Aug 13 15:43:45 2020 -0700
Refactored weather example.
---
.../examples/misc/darksky/DarkSkyService.java | 2 +-
.../nlpcraft/examples/weather/WeatherModel.java | 190 ++++++---------------
.../nlpcraft/examples/weather/weather_model.json | 113 ++++--------
3 files changed, 93 insertions(+), 212 deletions(-)
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/misc/darksky/DarkSkyService.java b/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/misc/darksky/DarkSkyService.java
index c58bdb9..10995a2 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/misc/darksky/DarkSkyService.java
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/misc/darksky/DarkSkyService.java
@@ -175,7 +175,7 @@ public class DarkSkyService {
log.debug("DarkSky time machine API call [lat={}, lon={}, from={}, to={}]", lat, lon, from, to);
if (Duration.between(from, to).get(SECONDS) > maxDaysSecs)
- throw new DarkSkyException(String.format("Too long request period [from=%s, to=%s]", from, to));
+ throw new DarkSkyException(String.format("Request period is too long [from=%s, to=%s]", from, to));
long durMs = to.toEpochMilli() - from.toEpochMilli();
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/weather/WeatherModel.java b/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/weather/WeatherModel.java
index 7bc6d3e..4534e6b 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/weather/WeatherModel.java
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/weather/WeatherModel.java
@@ -44,30 +44,21 @@ 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 srv = new DarkSkyService("097e1aad75b22b88f494cf49211975aa", 31);
+ private final DarkSkyService darkSky = new DarkSkyService("097e1aad75b22b88f494cf49211975aa", 31);
// Geo manager.
private final GeoManager geoMrg = new GeoManager();
-
+
+ // Default shift in days for history and forecast.
+ private static final int DAYS_SHIFT = 5;
+
+ // GSON instance.
private static final Gson GSON = new Gson();
-
+
// Keywords for 'local' weather.
private static final Set<String> LOCAL_WORDS = new HashSet<>(Arrays.asList("my", "local", "hometown"));
/**
- * Date range holder.
- */
- private static class DateRange {
- private final Instant from;
- private final Instant to;
-
- DateRange(Instant from, Instant to) {
- this.from = from;
- this.to = to;
- }
- }
-
- /**
* Coordinates holder.
*/
private static class Coordinate {
@@ -81,46 +72,23 @@ public class WeatherModel extends NCModelFileAdapter {
}
/**
- * Makes JSON result.
- *
- * @param res Weather holder.
- * @return Query result.
- */
- private NCResult makeResult(Object res) {
- return NCResult.json(GSON.toJson(res));
- }
-
- /**
- * Extracts date range from given solver context.
- *
- * @param tok date token.
- * @return Pair of dates.
- */
- private DateRange extractDate(NCToken tok) {
- return new DateRange(
- Instant.ofEpochMilli(tok.meta("nlpcraft:date:from")),
- Instant.ofEpochMilli(tok.meta("nlpcraft:date:to"))
- );
- }
-
- /**
* Extracts geo location (city) from given solver context that is suitable for Dark Sky API weather service.
*
* @param ctx Intent solver context.
- * @param dateTokOpt Optional date token.
+ * @param geoTokOpt Optional geo token.
* @return Geo location.
*/
- private Coordinate prepGeo(NCIntentMatch ctx, Optional<NCToken> dateTokOpt) throws NCRejection {
- if (dateTokOpt.isPresent()) {
- NCToken tok = dateTokOpt.get();
+ private Coordinate prepGeo(NCIntentMatch ctx, Optional<NCToken> geoTokOpt) throws NCRejection {
+ if (geoTokOpt.isPresent()) {
+ NCToken geoTok = geoTokOpt.get();
- Map<String, Object> cityMeta = tok.meta("nlpcraft:city:citymeta");
+ Map<String, Object> 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 = tok.meta("nlpcraft:city:city");
+ String city = geoTok.meta("nlpcraft:city:city");
throw new NCRejection(String.format("Latitude and longitude not found for: %s", city));
}
@@ -172,108 +140,62 @@ public class WeatherModel extends NCModelFileAdapter {
/**
*
* @param ctx
- * @param shift
* @return
*/
- private NCResult onPeriodMatch(
- NCIntentMatch ctx,
- Optional<NCToken> cityTokOpt,
- Optional<NCToken> dateTokOpt,
- int shift
- ) {
- assert shift != 0;
-
- checkMatch(ctx);
-
- try {
- Coordinate cr = prepGeo(ctx, cityTokOpt);
-
- Instant now = Instant.now();
-
- DateRange range = dateTokOpt.map(this::extractDate).orElseGet(
- () -> shift > 0 ?
- new DateRange(now, now.plus(shift, DAYS)) :
- new DateRange(now.plus(shift, DAYS), now)
- );
-
- return makeResult(srv.getTimeMachine(cr.latitude, cr.longitude, range.from, range.to));
- }
- catch (DarkSkyException e) {
- throw new NCRejection(e.getLocalizedMessage());
- }
- catch (NCRejection e) {
- throw e;
- }
- catch (Exception e) {
- throw new NCRejection("Weather provider error.", e);
- }
- }
-
- /**
- * Callback on forecast intent match.
- *
- * @param ctx Intent solver context.
- * @return Query result.
- */
- @NCIntent("intent=fcast conv=true term={id == 'wt:fcast'} term(city)={id == 'nlpcraft:city'}? term(date)={id == 'nlpcraft:date'}?")
- @NCIntentSample({
- "What's the weather forecast in Moscow?",
- "Will it be hot next Sunday?",
- "How about a rain next week in London"
- })
- public NCResult onForecastMatch(
- NCIntentMatch ctx,
- @NCIntentTerm("city") Optional<NCToken> cityTokOpt,
- @NCIntentTerm("date") Optional<NCToken> dateTokOpt
- ) {
- return onPeriodMatch(ctx, cityTokOpt, dateTokOpt, 5);
- }
-
- /**
- * Callback on history intent match.
- *
- * @param ctx Intent solver context.
- * @return Query result.
- */
- @NCIntent("intent=hist conv=true term={id == 'wt:hist'} term(city)={id == 'nlpcraft:city'}? term(date)={id == 'nlpcraft:date'}?")
- @NCIntentSample({
- "What the weather history in Moscow last week?"
- })
- public NCResult onHistoryMatch(
- NCIntentMatch ctx,
- @NCIntentTerm("city") Optional<NCToken> cityTokOpt,
- @NCIntentTerm("date") Optional<NCToken> dateTokOpt
- ) {
- return onPeriodMatch(ctx, cityTokOpt, dateTokOpt, -5);
- }
-
- /**
- * Callback on current date intent match.
- *
- * @param ctx Intent solver context.
- * @return Query result.
- */
- @NCIntent("intent=curr conv=true term={id == 'wt:curr'} term(city)={id == 'nlpcraft:city'}? term(date)={id == 'nlpcraft:date'}?")
+ @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 current weather in Moscow"
+ "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?"
})
- public NCResult onCurrentMatch(
+ public NCResult onMatch(
NCIntentMatch ctx,
+ @NCIntentTerm("ind") List<NCToken> indToksOpt,
@NCIntentTerm("city") Optional<NCToken> cityTokOpt,
@NCIntentTerm("date") Optional<NCToken> dateTokOpt
) {
checkMatch(ctx);
try {
- Coordinate cr = prepGeo(ctx, cityTokOpt);
+ Instant now = Instant.now();
+
+ Instant from = now;
+ Instant to = now;
- if (dateTokOpt.isPresent()) {
- DateRange range = extractDate(dateTokOpt.get());
+ if (indToksOpt.stream().anyMatch(tok -> tok.getId().equals("wt:hist")))
+ from = from.minus(DAYS_SHIFT, DAYS);
+ else if (indToksOpt.stream().anyMatch(tok -> tok.getId().equals("wt:fcast")))
+ to = from.plus(DAYS_SHIFT, DAYS);
- return makeResult(srv.getTimeMachine(cr.latitude, cr.longitude, range.from, range.to));
+ 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));
+ Coordinate latLon = prepGeo(ctx, cityTokOpt); // Handles optional city too.
+
+ return NCResult.json(GSON.toJson(from == to ? darkSky.getCurrent(latLon.latitude, latLon.longitude) :
+ darkSky.getTimeMachine(latLon.latitude, latLon.longitude, from, to)));
}
catch (DarkSkyException e) {
throw new NCRejection(e.getLocalizedMessage());
@@ -287,7 +209,7 @@ public class WeatherModel extends NCModelFileAdapter {
}
/**
- * Initializes the model.
+ * Loads the model.
*/
public WeatherModel() {
// Load model from external JSON file on classpath.
@@ -296,6 +218,6 @@ public class WeatherModel extends NCModelFileAdapter {
@Override
public void onDiscard() {
- srv.stop();
+ darkSky.stop();
}
}
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/weather/weather_model.json b/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/weather/weather_model.json
index 14d43ab..b5d6577 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/weather/weather_model.json
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/examples/weather/weather_model.json
@@ -16,81 +16,40 @@
*/
{
- "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?",
- "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?"
- ],
- "macros": [
- {
- "name": "<OF>",
- "macro": "{of|for|per}"
- },
- {
- "name": "<CHANCE>",
- "macro": "{chance|possibility|probability|odds|likelihood|potential|risk|opportunity}"
- },
- {
- "name": "<PHENOMENON>",
- "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": "<CUR>",
- "macro": "{current|present|moment|now}"
- },
- {
- "name": "<WEATHER>",
- "macro": "{weather {condition|temp|temperature|data|*}|condition|temp|temperature}"
- },
- {
- "name": "<FORECAST>",
- "macro": "{forecast|prognosis|prediction}"
- },
- {
- "name": "<HISTORY>",
- "macro": "{history|past}"
- }
- ],
- "elements": [
- {
- "id": "wt:hist",
- "description": "Past weather conditions.",
- "synonyms": [
- "{<WEATHER>|*} <HISTORY>",
- "<HISTORY> {<OF>|*} {<WEATHER>|<PHENOMENON>}"
- ]
- },
- {
- "id": "wt:curr",
- "description": "Current weather conditions.",
- "synonyms": [
- "{<CUR>|*} {<WEATHER>|<PHENOMENON>}",
- "<CHANCE> <OF> <PHENOMENON>",
- "<PHENOMENON> {<CHANCE>|*}"
- ]
- },
- {
- "id": "wt:fcast",
- "description": "Future weather forecast.",
- "synonyms": [
- "{<PHENOMENON>|<WEATHER>|*} <FORECAST>",
- "<FORECAST> {<OF>|*} {<WEATHER>|<PHENOMENON>}"
- ]
- }
- ]
+ "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}"
+ ]
+ }
+ ]
}
\ No newline at end of file