This is an automated email from the ASF dual-hosted git repository.
aradzinski pushed a commit to branch NLPCRAFT-387
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git
The following commit(s) were added to refs/heads/NLPCRAFT-387 by this push:
new e69144f Code review & WIP on NLPCRAFT-387
e69144f is described below
commit e69144f290fe085d5bacab5e0cce58f06ff26cc8
Author: Aaron Radzinzski <[email protected]>
AuthorDate: Mon Aug 2 16:59:02 2021 -0700
Code review & WIP on NLPCRAFT-387
---
.../apache/nlpcraft/examples/alarm/AlarmModel.java | 10 ++--
.../alarm/src/main/resources/alarm_samples.txt | 12 +++-
.../alarm/src/main/resources/intents.idl | 2 +-
.../nlpcraft/examples/alarm/NCAlarmModelSpec.scala | 15 ++++-
.../common/nlp/numeric/NCFuzzyNumericsConfig.scala | 62 ---------------------
.../common/nlp/numeric/NCNumericFuzzy.scala | 65 ++++++++++++++++++++++
.../common/nlp/numeric/NCNumericManager.scala | 2 +-
7 files changed, 95 insertions(+), 73 deletions(-)
diff --git
a/nlpcraft-examples/alarm/src/main/java/org/apache/nlpcraft/examples/alarm/AlarmModel.java
b/nlpcraft-examples/alarm/src/main/java/org/apache/nlpcraft/examples/alarm/AlarmModel.java
index bff4f10..0e15a02 100644
---
a/nlpcraft-examples/alarm/src/main/java/org/apache/nlpcraft/examples/alarm/AlarmModel.java
+++
b/nlpcraft-examples/alarm/src/main/java/org/apache/nlpcraft/examples/alarm/AlarmModel.java
@@ -94,10 +94,10 @@ public class AlarmModel extends NCModelFileAdapter {
}
/**
- * TODO: It is implemented as specail method just for tests reasons.
+ * Calculates time duration for given tokens.
*
- * @param numToks
- * @return
+ * @param numToks Tokens to calculate time duration for.
+ * @return Time duration in ms.
*/
public static long calculateTime(List<NCToken> numToks) {
LocalDateTime now = LocalDateTime.now();
@@ -106,7 +106,7 @@ public class AlarmModel extends NCModelFileAdapter {
for (NCToken num : numToks) {
String unit = num.meta("nlpcraft:num:unit");
- // Skip possible fractionals to simplify.
+ // Skip possible fractional to simplify.
long v = ((Double)num.meta("nlpcraft:num:from")).longValue();
if (v <= 0)
@@ -122,7 +122,7 @@ public class AlarmModel extends NCModelFileAdapter {
case "year": { dt = dt.plusYears(v); break; }
default:
- // It shouldn't be an assert, because 'datetime' unit can
be extended.
+ // It shouldn't be an assertion, because 'datetime' unit
can be extended outside.
throw new NCRejection("Unsupported time unit: " + unit);
}
}
diff --git a/nlpcraft-examples/alarm/src/main/resources/alarm_samples.txt
b/nlpcraft-examples/alarm/src/main/resources/alarm_samples.txt
index 188d1d6..d0f84a8 100644
--- a/nlpcraft-examples/alarm/src/main/resources/alarm_samples.txt
+++ b/nlpcraft-examples/alarm/src/main/resources/alarm_samples.txt
@@ -22,4 +22,14 @@
Ping me in 3 minutes tomorrow
Buzz me in an hour and 15mins
Set my alarm for 30s
-Please, wake me up in twenty five minutes!
\ No newline at end of file
+Please, wake me up in twenty-five minutes!
+Buzz me in few minutes
+Buzz me in a couple of minutes
+Buzz me in an hour
+Buzz me in a couple of hours
+Buzz me in an hour and 15mins
+Buzz me in one hour and 15mins
+Buzz me in 1 hour and 15mins
+Buzz me in 1h and 15mins
+Buzz me in a day, 1h and 15mins
+Buzz me in one day, 1h and 15mins
diff --git a/nlpcraft-examples/alarm/src/main/resources/intents.idl
b/nlpcraft-examples/alarm/src/main/resources/intents.idl
index bae42ae..3c1810b 100644
--- a/nlpcraft-examples/alarm/src/main/resources/intents.idl
+++ b/nlpcraft-examples/alarm/src/main/resources/intents.idl
@@ -24,7 +24,7 @@ fragment=when
@iseq = meta_tok('nlpcraft:num:isequalcondition') // Excludes
conditional statements.
tok_id() == 'nlpcraft:num' && @type == 'datetime' && @iseq == true
- }[0,7]
+ }[1,7]
// Intents (using fragments).
intent=alarm
diff --git
a/nlpcraft-examples/alarm/src/test/java/org/apache/nlpcraft/examples/alarm/NCAlarmModelSpec.scala
b/nlpcraft-examples/alarm/src/test/java/org/apache/nlpcraft/examples/alarm/NCAlarmModelSpec.scala
index dd74617..4782757 100644
---
a/nlpcraft-examples/alarm/src/test/java/org/apache/nlpcraft/examples/alarm/NCAlarmModelSpec.scala
+++
b/nlpcraft-examples/alarm/src/test/java/org/apache/nlpcraft/examples/alarm/NCAlarmModelSpec.scala
@@ -26,17 +26,23 @@ import java.time.LocalDateTime
import java.time.temporal.ChronoUnit.MILLIS
import scala.jdk.CollectionConverters.SeqHasAsJava
+/**
+ * Model for alarm spec.
+ */
class AlarmModelWrapper extends AlarmModel {
@NCIntentRef("alarm")
def onMatch(@NCIntentTerm("nums") numToks: List[NCToken]): NCResult =
NCResult.text(String.valueOf(calculateTime(numToks.asJava)))
}
+/**
+ * Unit tests that checks that alarm model produces correct time calculations.
+ */
@NCTestEnvironment(model = classOf[AlarmModelWrapper], startClient = true)
class NCAlarmModelSpec extends NCTestContext {
- // Checks with 10 seconds precision. Enough to be sure that calculation
result is correct.
+ // Checks with 1 second precision. Enough to be sure that calculation
result is correct.
private def check(req: String, expectedTime: Long): Unit =
- checkResult(req, _.toLong, (calcTime: Long) => Math.abs(expectedTime -
calcTime) <= 10000)
+ checkResult(req, _.toLong, (calcTime: Long) => Math.abs(expectedTime -
calcTime) <= 1000)
@Test
def test(): Unit = {
@@ -45,7 +51,10 @@ class NCAlarmModelSpec extends NCTestContext {
def mkPeriod(hours: Int, mins: Int): Long =
now.until(now.plusHours(hours).plusMinutes(mins), MILLIS)
// Fuzzy.
- check("Buzz me in few minutes.", mkPeriod(0, 5))
+ check("Buzz me in few minutes.", mkPeriod(0, 2))
+ check("Buzz me in a minute or two.", mkPeriod(0, 2))
+ check("Buzz me in one or two minutes.", mkPeriod(0, 2))
+ check("Buzz me in a couple of minutes.", mkPeriod(0, 2))
check("Buzz me in an hour.", mkPeriod(1, 0))
// Complex periods.
diff --git
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/nlp/numeric/NCFuzzyNumericsConfig.scala
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/nlp/numeric/NCFuzzyNumericsConfig.scala
deleted file mode 100644
index 745b9d1..0000000
---
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/nlp/numeric/NCFuzzyNumericsConfig.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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
- *
- * https://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.
- */
-
-package org.apache.nlpcraft.common.nlp.numeric
-
-import org.apache.nlpcraft.common.makro.NCMacroParser
-
-case class NCFuzzyNumericPeriod(unit: NCNumericUnit, value: Int)
-
-/**
- * Fuzzy numeric configuration.
- */
-object NCFuzzyNumericsConfig {
- val NUMS: Map[String, NCFuzzyNumericPeriod] = {
- val parser = new NCMacroParser
-
- def make(txt: String, unit: NCNumericUnit, value: Int): Seq[(String,
NCFuzzyNumericPeriod)] =
- parser.expand(txt).map(_ -> NCFuzzyNumericPeriod(unit, value))
-
- import org.apache.nlpcraft.common.nlp.numeric.{NCNumericUnit => U}
-
- // Datetime 1.
- val singleDt =
- Map(
- "in {a|an} second" -> U("second", "datetime"),
- "in {a|an} hour" -> U("hour", "datetime"),
- "in {a|an} minute" -> U("minute", "datetime"),
- "in {a|an} day" -> U("day", "datetime"),
- "in {a|an} week" -> U("week", "datetime"),
- "in {a|an} month" -> U("month", "datetime"),
- "in {a|an} year" -> U("year", "datetime")
- ).flatMap { case (txt, u) => make(txt, u, 1) }
-
- // Datetime 2.
- val fewDt =
- Map(
- "in {a|an|_} few seconds" -> U("second", "datetime"),
- "in {a|an|_} few minutes" -> U("minute", "datetime"),
- "in {a|an|_} few hours" -> U("hour", "datetime"),
- "in {a|an|_} few days" -> U("day", "datetime"),
- "in {a|an|_} few weeks" -> U("week", "datetime"),
- "in {a|an|_} few months" -> U("month", "datetime"),
- "in {a|an|_} few years" -> U("year", "datetime")
- ).flatMap { case (txt, u) => make(txt, u, 5) }
-
- singleDt ++ fewDt
- }
-}
diff --git
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/nlp/numeric/NCNumericFuzzy.scala
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/nlp/numeric/NCNumericFuzzy.scala
new file mode 100644
index 0000000..eb15a0d
--- /dev/null
+++
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/nlp/numeric/NCNumericFuzzy.scala
@@ -0,0 +1,65 @@
+/*
+ * 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
+ *
+ * https://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.
+ */
+
+package org.apache.nlpcraft.common.nlp.numeric
+
+import org.apache.nlpcraft.common.makro.NCMacroParser
+
+case class NCNumericFuzzyPeriod(unit: NCNumericUnit, value: Int)
+
+/**
+ * Fuzzy numeric configuration.
+ */
+object NCNumericFuzzy {
+ val NUMS: Map[String, NCNumericFuzzyPeriod] = {
+ val parser = new NCMacroParser
+
+ def make(txt: String, unit: NCNumericUnit, value: Int): Seq[(String,
NCNumericFuzzyPeriod)] =
+ parser.expand(txt).map(_ -> NCNumericFuzzyPeriod(unit, value))
+
+ import org.apache.nlpcraft.common.nlp.numeric.{NCNumericUnit => U}
+
+ val singleDt =
+ Map(
+ "in {a|an} second {or two|_}" -> U("second", "datetime"),
+ "in {a|an} hour {or two|_}" -> U("hour", "datetime"),
+ "in {a|an} minute {or two|_}" -> U("minute", "datetime"),
+ "in {a|an} day {or two|_}" -> U("day", "datetime"),
+ "in {a|an} week {or two|_}" -> U("week", "datetime"),
+ "in {a|an} month {or two|_}" -> U("month", "datetime"),
+ "in {a|an} year {or two|_}" -> U("year", "datetime")
+ ).flatMap { case (txt, u) => make(txt, u, 1) }
+
+ val bitDt =
+ Map(
+ "in {a|an} bit" -> U("second", "datetime")
+ ).flatMap { case (txt, u) => make(txt, u, 60) }
+
+ val fewDt =
+ Map(
+ "in {a|an|_} {few|couple|one or two|two or three} seconds" ->
U("second", "datetime"),
+ "in {a|an|_} {few|couple|one or two|two or three} minutes" ->
U("minute", "datetime"),
+ "in {a|an|_} {few|couple|one or two|two or three} hours" ->
U("hour", "datetime"),
+ "in {a|an|_} {few|couple|one or two|two or three} days" ->
U("day", "datetime"),
+ "in {a|an|_} {few|couple|one or two|two or three} weeks" ->
U("week", "datetime"),
+ "in {a|an|_} {few|couple|one or two|two or three} months" ->
U("month", "datetime"),
+ "in {a|an|_} {few|couple|one or two|two or three} years" ->
U("year", "datetime")
+ ).flatMap { case (txt, u) => make(txt, u, 2) }
+
+ singleDt ++ fewDt ++ bitDt
+ }
+}
diff --git
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/nlp/numeric/NCNumericManager.scala
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/nlp/numeric/NCNumericManager.scala
index 1b97003..a502117 100644
---
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/nlp/numeric/NCNumericManager.scala
+++
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/nlp/numeric/NCNumericManager.scala
@@ -118,7 +118,7 @@ object NCNumericManager extends NCService {
val senToks: Seq[NCNlpSentenceToken] = ns.tokens.toSeq
val senWords: Seq[String] = senToks.map(_.normText)
- NCFuzzyNumericsConfig.NUMS.map { case (txt, period) => txt.split(" ")
-> period }.flatMap {
+ NCNumericFuzzy.NUMS.map { case (txt, period) => txt.split(" ") ->
period }.flatMap {
case (dtWords, dtPeriod) =>
senWords.indexOfSlice(dtWords) match {
case -1 => None