This is an automated email from the ASF dual-hosted git repository.
sergeykamov pushed a commit to branch NLPCRAFT-491
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git
The following commit(s) were added to refs/heads/NLPCRAFT-491 by this push:
new 4d2154f0 WIP.
4d2154f0 is described below
commit 4d2154f0b0ad28fbc94244c76c3e5d6b6025bc07
Author: Sergey Kamov <[email protected]>
AuthorDate: Thu Apr 7 12:26:28 2022 +0300
WIP.
---
.../nlpcraft/examples/order/OrderModel.scala | 12 +++----
...taExtenderMapper.scala => EntityExtender.scala} | 37 +++++++++++--------
.../order/components/RequestValidator.scala | 42 ++++++++++++++++++++++
.../order/components/StanfordPipeline.scala | 15 +++++---
4 files changed, 81 insertions(+), 25 deletions(-)
diff --git
a/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/OrderModel.scala
b/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/OrderModel.scala
index 9f4ba3bf..58c84685 100644
---
a/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/OrderModel.scala
+++
b/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/OrderModel.scala
@@ -41,6 +41,7 @@ import scala.jdk.OptionConverters.*
*/
object OrderModel extends LazyLogging:
private val DFLT_QTY = 1
+ private val UNEXPECTED = new NCRejection("Unexpected request in given
context.")
private def toStr[T](name: String, seq: Iterable[T]): String = if
seq.nonEmpty then s"$name: ${seq.mkString(", ")}." else ""
private def extractPizzaSize(e: NCEntity): String =
e.get[String]("ord:pizza:size:value")
private def extractQty(e: NCEntity, qty: String): Option[Int] =
Option.when(e.contains(qty))(e.get[String](qty).toDouble.toInt)
@@ -156,7 +157,7 @@ class OrderModel extends NCModelAdapter (new
NCModelConfig("nlpcraft.order.ex",
doExecute(im, o)
case DIALOG_SHOULD_CANCEL => doStop(im, o)
case DIALOG_IS_READY => askConfirmOrAskSpecify(o)
- case DIALOG_SPECIFY | NO_DIALOG => throw new
NCRejection("Unexpected request.")
+ case DIALOG_SPECIFY | NO_DIALOG => throw UNEXPECTED
)
/**
@@ -170,7 +171,7 @@ class OrderModel extends NCModelAdapter (new
NCModelConfig("nlpcraft.order.ex",
(o: Order) => o.getState match
case DIALOG_CONFIRM | DIALOG_IS_READY => doContinue(o)
case DIALOG_SHOULD_CANCEL => askConfirmOrAskSpecify(o)
- case DIALOG_SPECIFY | NO_DIALOG => throw new
NCRejection("Unexpected request.")
+ case DIALOG_SPECIFY | NO_DIALOG => throw UNEXPECTED
)
/**
*
@@ -195,7 +196,7 @@ class OrderModel extends NCModelAdapter (new
NCModelConfig("nlpcraft.order.ex",
def onOrder(im: NCIntentMatch, @NCIntentTerm("ps") ps: List[NCEntity],
@NCIntentTerm("ds") ds: List[NCEntity]): NCResult = withLog(
im,
(o: Order) =>
- if ps.isEmpty && ds.isEmpty then throw new NCRejection("Please
order some pizza or drinks");
+ require(ps.nonEmpty || ds.nonEmpty);
o.add(ps.map(extractPizza), ds.map(extractDrink)); // It doesn't
depend on order validity and dialog state.
askIsReadyOrAskSpecify(o)
)
@@ -213,9 +214,8 @@ class OrderModel extends NCModelAdapter (new
NCModelConfig("nlpcraft.order.ex",
if o.setPizzaNoSize(extractPizzaSize(size)) then
o.setState(NO_DIALOG);
askIsReadyOrAskSpecify(o)
- else
- throw new NCRejection("Unexpected request.")
- case DIALOG_CONFIRM | NO_DIALOG | DIALOG_IS_READY |
DIALOG_SHOULD_CANCEL => throw new NCRejection("Unexpected request.")
+ else throw UNEXPECTED
+ case DIALOG_CONFIRM | NO_DIALOG | DIALOG_IS_READY |
DIALOG_SHOULD_CANCEL => throw UNEXPECTED
)
/**
*
diff --git
a/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/DataExtenderMapper.scala
b/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/EntityExtender.scala
similarity index 57%
rename from
nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/DataExtenderMapper.scala
rename to
nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/EntityExtender.scala
index 44278aea..dbd772c3 100644
---
a/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/DataExtenderMapper.scala
+++
b/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/EntityExtender.scala
@@ -26,31 +26,40 @@ import scala.jdk.CollectionConverters.*
/**
*
+ * @param id
+ * @param copyProperty
*/
-case class DataExtenderMapper(key: String, prop: String, extKey: String,
extProp: String) extends NCEntityMapper:
- private def extract(e: NCEntity): mutable.Seq[NCToken] =
e.getTokens.asScala
+case class EntityData(id: String, copyProperty: String)
+
+/**
+ *
+ */
+case class EntityExtender(mainDataSeq: Seq[EntityData], extraData: EntityData)
extends NCEntityMapper:
+ private def getToks(e: NCEntity): mutable.Seq[NCToken] =
e.getTokens.asScala
override def map(req: NCRequest, cfg: NCModelConfig, entities:
util.List[NCEntity]): util.List[NCEntity] =
+ val mainDataMap = mainDataSeq.map(p => p.id -> p).toMap
+
var es = entities.asScala
- val data = es.filter(_.getId == key)
- val extData = es.filter(_.getId == extKey)
+ val main = es.filter(e => mainDataMap.contains(e.getId))
+ val extra = es.filter(_.getId == extraData.id)
- if data.nonEmpty && data.size == extData.size then
+ if main.nonEmpty && main.size == extra.size then
var ok = true
val mapped =
- for ((e1, e2) <- data.zip(extData) if ok) yield
+ for ((e1, e2) <- main.zip(extra) if ok) yield
if e1.getId == e2.getId then
ok = false
null
else
- val (data, extData) = if e1.getId == key then (e1, e2)
else (e2, e1)
+ val (mEnt, eEnt) = if mainDataMap.contains(e1.getId)
then (e1, e2) else (e2, e1)
new NCPropertyMapAdapter with NCEntity:
- data.keysSet().forEach(k => put(k, data.get(k)))
- put[String](prop,
extData.get[String](extProp).toLowerCase)
- override val getTokens: JList[NCToken] =
(extract(data) ++ extract(extData)).sortBy(_.getIndex).asJava
+ mEnt.keysSet().forEach(k => put(k, mEnt.get(k)))
+ put[String](mainDataMap(mEnt.getId).copyProperty,
eEnt.get[String](extraData.copyProperty).toLowerCase)
+ override val getTokens: JList[NCToken] =
(getToks(mEnt) ++ getToks(eEnt)).sortBy(_.getIndex).asJava
override val getRequestId: String =
req.getRequestId
- override val getId: String = data.getId
+ override val getId: String = mEnt.getId
- es = es --= data
- es = es --= extData
- (es ++ mapped).sortBy(extract(_).head.getIndex).asJava
+ es = es --= main
+ es = es --= extra
+ (es ++ mapped).sortBy(getToks(_).head.getIndex).asJava
else entities
\ No newline at end of file
diff --git
a/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/RequestValidator.scala
b/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/RequestValidator.scala
new file mode 100644
index 00000000..ea1534b7
--- /dev/null
+++
b/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/RequestValidator.scala
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+package org.apache.nlpcraft.examples.order.components
+
+import org.apache.nlpcraft.*
+
+import java.util
+import scala.jdk.CollectionConverters.*
+
+/**
+ *
+ */
+class RequestValidator extends NCEntityValidator:
+ override def validate(req: NCRequest, cfg: NCModelConfig, ents:
util.List[NCEntity]): Unit =
+ val es = ents.asScala
+
+ def count(id: String): Int = es.count(_.getId == id)
+
+ val cntPizza = count("ord:pizza")
+ val cntDrink = count("ord:drink")
+ val cntNums = count("stanford:number")
+ val cntSize = count("ord:pizza:size")
+
+ if cntNums != 1 && cntNums > cntPizza + cntDrink then
+ throw new NCRejection("Too many unrecognized numerics in the
request.")
+ if cntSize != 1 && cntSize > cntPizza then
+ throw new NCRejection("Too many unrecognized pizza sizes in the
request.")
\ No newline at end of file
diff --git
a/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/StanfordPipeline.scala
b/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/StanfordPipeline.scala
index 440cd61c..34bebf67 100644
---
a/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/StanfordPipeline.scala
+++
b/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/StanfordPipeline.scala
@@ -42,14 +42,19 @@ object StanfordPipeline:
private val ps = new PorterStemmer
override def stem(txt: String): String = ps.synchronized {
ps.stem(txt) }
+ import EntityExtender as Ex
+ import EntityData as D
+
new NCPipelineBuilder().
withTokenParser(tokParser).
withTokenEnricher(new NCEnStopWordsTokenEnricher()).
withEntityParser(new NCStanfordNLPEntityParser(stanford,
"number")).
withEntityParser(new NCSemanticEntityParser(stemmer, tokParser,
"order_model.yaml")).
- withEntityMappers(Seq(
- DataExtenderMapper(key = "ord:pizza", prop = "ord:pizza:size",
extKey = "ord:pizza:size", extProp = "ord:pizza:size:value"),
- DataExtenderMapper(key = "ord:pizza", prop = "ord:pizza:qty",
extKey = "stanford:number", extProp = "stanford:number:nne"),
- DataExtenderMapper(key = "ord:drink", prop = "ord:drink:qty",
extKey = "stanford:number", extProp = "stanford:number:nne")
- ).asJava).
+ withEntityMappers(
+ Seq(
+ Ex(Seq(D("ord:pizza", "ord:pizza:size")),
D("ord:pizza:size", "ord:pizza:size:value")),
+ Ex(Seq(D("ord:pizza", "ord:pizza:qty"), D("ord:drink",
"ord:drink:qty")), D("stanford:number", "stanford:number:nne")),
+ ).asJava
+ ).
+ withEntityValidator(new RequestValidator()).
build()
\ No newline at end of file