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 c50ad6bf WIP.
c50ad6bf is described below
commit c50ad6bfc522ed8bc94d8dcc749335488fe36228
Author: Sergey Kamov <[email protected]>
AuthorDate: Wed Apr 6 15:11:16 2022 +0300
WIP.
---
.../org/apache/nlpcraft/examples/order/Order.scala | 91 ++++--
.../nlpcraft/examples/order/OrderModel.scala | 358 ++++++++++++---------
.../order/components/StanfordPipeline.scala | 49 +++
.../order/src/main/resources/order_model.yaml | 3 +-
.../examples/order/cli/OrderModelClientCli.scala | 6 +-
5 files changed, 323 insertions(+), 184 deletions(-)
diff --git
a/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/Order.scala
b/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/Order.scala
index 5b14b106..395cc20a 100644
---
a/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/Order.scala
+++
b/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/Order.scala
@@ -19,43 +19,86 @@ package org.apache.nlpcraft.examples.order
import scala.collection.mutable
-case class Pizza(name: String, var size: Option[String], qty: Option[Int])
-case class Drink(name: String, qty: Option[Int])
-
+case class Pizza(name: String, var size: Option[String], var qty: Option[Int]):
+ require(name != null && name.nonEmpty)
+case class Drink(name: String, var qty: Option[Int]):
+ require(name != null && name.nonEmpty)
enum State:
- case ORDER_EMPTY, ORDER_INVALID, ORDER_VALID, ASK_CONTINUE, ASK_CONFIRM,
ASK_CANCEL
+ case NO_DIALOG, DIALOG_IS_READY, DIALOG_SHOULD_CANCEL, DIALOG_SPECIFY,
DIALOG_CONFIRM
import org.apache.nlpcraft.examples.order.State.*
class Order:
- private var state = ORDER_EMPTY
+ private var state = NO_DIALOG
private val pizzas = mutable.LinkedHashMap.empty[String, Pizza]
private val drinks = mutable.LinkedHashMap.empty[String, Drink]
- private def findPizzaNoSize: Option[Pizza] =
pizzas.values.find(_.size.isEmpty)
+ /**
+ *
+ * @return
+ */
+ def isEmpty: Boolean = pizzas.isEmpty && drinks.isEmpty
- def addPizza(p: Pizza): Unit =
- pizzas += p.name -> p
- state = if findPizzaNoSize.nonEmpty then ORDER_INVALID else ORDER_VALID
- def addDrink(d: Drink): Unit =
- if state == ORDER_EMPTY then state = ORDER_VALID
- drinks += d.name -> d
+ /**
+ *
+ * @return
+ */
+ def isValid: Boolean = !isEmpty && findPizzaNoSize.isEmpty
- def getState: State = state
- def setState(state: State) = this.state = state
+ /**
+ *
+ * @param ps
+ * @param ds
+ */
+ def add(ps: Seq[Pizza], ds: Seq[Drink]): Unit =
+ for (p <- ps)
+ pizzas.get(p.name) match
+ case Some(ex) =>
+ if p.size.nonEmpty then ex.size = p.size
+ if p.qty.nonEmpty then ex.qty = p.qty
+ case None => pizzas += p.name -> p
+
+ for (d <- ds)
+ drinks.get(d.name) match
+ case Some(ex) => if d.qty.nonEmpty then ex.qty = d.qty
+ case None => drinks += d.name -> d
+ /**
+ *
+ * @return
+ */
def getPizzas: Map[String, Pizza] = pizzas.toMap
+
+ /**
+ *
+ * @return
+ */
def getDrinks: Map[String, Drink] = drinks.toMap
- def getPizzaNoSize: Pizza =
- require(state == ORDER_INVALID)
- findPizzaNoSize.get
- def setPizzaNoSize(size: String): Unit =
- require(state == ORDER_INVALID)
- require(size != null)
- findPizzaNoSize.get.size = Option(size)
- def clear(): Unit =
- pizzas.clear()
- drinks.clear()
+ /**
+ *
+ * @return
+ */
+ def findPizzaNoSize: Option[Pizza] = pizzas.values.find(_.size.isEmpty)
+ /**
+ *
+ * @param size
+ */
+ def setPizzaNoSize(size: String): Boolean =
+ findPizzaNoSize match
+ case Some(p) =>
+ p.size = Option(size)
+ true
+ case None => false
+ /**
+ *
+ * @return
+ */
+ def getState: State = state
+ /**
+ *
+ * @param state
+ */
+ def setState(state: State): Unit = this.state = state
\ No newline at end of file
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 47ab58e6..9f4ba3bf 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
@@ -20,198 +20,240 @@ package org.apache.nlpcraft.examples.order
import com.typesafe.scalalogging.LazyLogging
import edu.stanford.nlp.pipeline.StanfordCoreNLP
import opennlp.tools.stemmer.PorterStemmer
-import org.antlr.v4.runtime.misc.Predicate
import org.apache.nlpcraft.*
+import org.apache.nlpcraft.NCResultType.*
+import org.apache.nlpcraft.examples.order.State.*
+import org.apache.nlpcraft.examples.order.components.*
import org.apache.nlpcraft.internal.util.NCResourceReader
import org.apache.nlpcraft.nlp.*
import org.apache.nlpcraft.nlp.entity.parser.*
-
-import scala.collection.mutable
-import org.apache.nlpcraft.NCResultType.*
-import org.apache.nlpcraft.examples.order.components.*
import org.apache.nlpcraft.nlp.entity.parser.semantic.*
import org.apache.nlpcraft.nlp.entity.parser.stanford.*
import org.apache.nlpcraft.nlp.token.parser.stanford.*
-import org.apache.nlpcraft.examples.order.State.*
-import scala.jdk.CollectionConverters.*
import java.util.Properties
-import scala.jdk.OptionConverters._
-
-object StanfordEn:
- val PIPELINE: NCPipeline =
- val stanford =
- val props = new Properties()
- props.setProperty("annotators", "tokenize, ssplit, pos, lemma,
ner")
- new StanfordCoreNLP(props)
- val tokParser = new NCStanfordNLPTokenParser(stanford)
- val stemmer = new NCSemanticStemmer():
- private val ps = new PorterStemmer
- override def stem(txt: String): String = ps.synchronized {
ps.stem(txt) }
-
- new NCPipelineBuilder().
- withTokenParser(tokParser).
- withEntityParser(new NCStanfordNLPEntityParser(stanford,
"number")).
- withEntityParser(new NCSemanticEntityParser(stemmer, tokParser,
"order_model.yaml")).
- withEntityMappers(Seq(new PizzaSizeExtender, new PizzaQtyExtender,
new DrinkQtyExtender).asJava).
- withEntityValidator(new OrderValidator).
- build()
+import scala.collection.mutable
+import scala.jdk.CollectionConverters.*
+import scala.jdk.OptionConverters.*
+/**
+ *
+ */
object OrderModel extends LazyLogging:
- private def norm(s: String) = s.trim.replaceAll("(?m)^[ \t]*\r?\n", "")
- private def withComma[T](iter: Iterable[T]): String = iter.mkString(", ")
- private def seq2Str[T](name: String, seq: Iterable[T]): String = if
seq.nonEmpty then s"$name: ${withComma(seq)}." else ""
-
+ private val DFLT_QTY = 1
+ 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).toInt)
+ private def extractQty(e: NCEntity, qty: String): Option[Int] =
Option.when(e.contains(qty))(e.get[String](qty).toDouble.toInt)
private def extractPizza(e: NCEntity): Pizza =
Pizza(e.get[String]("ord:pizza:value"),
e.getOpt[String]("ord:pizza:size").toScala, extractQty(e, "ord:pizza:qty"))
- private def extractDrink(e: NCEntity): Drink =
Drink(e.get[String]("ord:drink:value"), extractQty(e, "ord:drink:qty"))
+ private def extractDrink(e: NCEntity): Drink =
+ Drink(e.get[String]("ord:drink:value"), extractQty(e, "ord:drink:qty"))
- private def getContent(o: Order): String =
- s"""
- |${seq2Str("Pizza", o.getPizzas.values.map(p => s"${p.name}
${p.size.getOrElse("undefined")} ${p.qty.getOrElse(1)}"))}
- |${seq2Str("Drinks", o.getDrinks.values.map(p => s"${p.name}
${p.qty.getOrElse(1)}"))}
- """.stripMargin
+ private def getDescription(o: Order): String =
+ if !o.isEmpty then
+ val s1 = toStr("Pizza", o.getPizzas.values.map(p => s"${p.name}
size: ${p.size.getOrElse("undefined")} count: ${p.qty.getOrElse(DFLT_QTY)}"))
+ val s2 = toStr("Drinks", o.getDrinks.values.map(p => s"${p.name}
count: ${p.qty.getOrElse(DFLT_QTY)}"))
+ if s2.isEmpty then s1
+ else if s1.isEmpty then s2 else s"$s1 $s2"
+ else "Nothing ordered."
- private def toString(o: Order): String =
- norm(
- s"""
- |Order
- |${getContent(o)}
- """.stripMargin
- )
import org.apache.nlpcraft.examples.order.OrderModel.*
+
/**
*
*/
-class OrderModel extends NCModelAdapter (
- new NCModelConfig("nlpcraft.order.ex", "Order Example Model", "1.0"),
StanfordEn.PIPELINE
-) with LazyLogging:
- private val ords = mutable.HashMap.empty[String, Order]
-
- private def getOrder(im: NCIntentMatch): Order =
ords.getOrElseUpdate(im.getContext.getRequest.getUserId, new Order)
- private def getLastIntentId(im: NCIntentMatch): Option[String] =
- im.getContext.getConversation.getDialogFlow.asScala.lastOption match
- case Some(e) => Some(e.getIntentMatch.getIntentId)
- case None => None
-
- private def mkOrderFinishDialog(o: Order): NCResult =
-// if o.isValid then
-// o.wait4Approve(true)
-// new NCResult("Is order ready?", ASK_DIALOG)
-// else NCResult(s"What is size size (large, medium or small) for:
${o.getPizzaNoSize.name}", ASK_DIALOG)
- null
-
- private def mkOrderContinueDialog(o: Order): NCResult =
-// require(o.inProgress)
-// NCResult("OK. Please continue", ASK_DIALOG)
- null
-
- private def mkOrderConfirmDialog(o: Order): NCResult =
+class OrderModel extends NCModelAdapter (new
NCModelConfig("nlpcraft.order.ex", "Order Example Model", "1.0"),
StanfordPipeline.PIPELINE) with LazyLogging:
+ private val userOrders = mutable.HashMap.empty[String, Order]
+
+ private def withLog(im: NCIntentMatch, body: Order => NCResult): NCResult =
+ val o = userOrders.getOrElseUpdate(im.getContext.getRequest.getUserId,
new Order)
+ def getState: String = o.getState.toString.toLowerCase
+ val state = getState
+
+ try body.apply(o)
+ finally println(s"'${im.getIntentId}' called ($state -> $getState)")
+
+ private def askIsReady(o: Order): NCResult =
+ val res = NCResult(s"Is order ready?", ASK_DIALOG)
+ o.setState(DIALOG_IS_READY)
+ res
+
+ private def askSpecify(o: Order) =
+ require(!o.isValid)
+ val res = o.findPizzaNoSize match
+ case Some(p) => NCResult(s"Choose size (large, medium or small)
for: '${p.name}'", ASK_DIALOG)
+ case None =>
+ require(o.isEmpty)
+ NCResult(s"Please order something. Ask `menu` to look what you
can order.", ASK_DIALOG)
+ o.setState(DIALOG_SPECIFY)
+ res
+
+ private def askShouldStop(o: Order) =
+ val res = NCResult(s"Should current order be canceled?", ASK_DIALOG)
+ o.setState(DIALOG_SHOULD_CANCEL)
+ res
+
+ private def doShowMenu() =
NCResult(
- norm(
- s"""
- |Let me specify your order.
- |${getContent(o)}
- |Is it correct?
- """.stripMargin
- ),
- ASK_DIALOG
+ "There are accessible for order: margherita, carbonara and
marinara. Sizes: large, medium or small. " +
+ "Also there are tea, green tea, coffee and cola.",
+ ASK_RESULT
)
- private def mkClearResult(im: NCIntentMatch, o: Order): NCResult =
- o.clear()
+ private def doShowStatus(o: Order, newState: State) =
+ val res = NCResult(s"Current order state: ${getDescription(o)}",
ASK_RESULT)
+ o.setState(newState)
+ res
+
+ private def askConfirm(o: Order): NCResult =
+ require(o.isValid)
+ val res = NCResult(s"Let's specify your order. ${getDescription(o)} Is
it correct?", ASK_DIALOG)
+ o.setState(DIALOG_CONFIRM)
+ res
+
+ private def clear(im: NCIntentMatch, o: Order): Unit =
+ userOrders.remove(im.getContext.getRequest.getUserId)
val conv = im.getContext.getConversation
conv.clearStm(_ => true)
conv.clearDialog(_ => true)
- NCResult("Order canceled. We are ready for new orders.", ASK_RESULT)
-
- private def mkExecuteResult(o: Order): NCResult =
- println(s"EXECUTED:")
- println(OrderModel.toString(o))
- o.clear()
- NCResult("Congratulations. Your order executed. You can start make new
orders.", ASK_RESULT)
+ private def doExecute(im: NCIntentMatch, o: Order): NCResult =
+ require(o.isValid)
+ val res = NCResult(s"Executed: ${getDescription(o)}", ASK_RESULT)
+ clear(im, o)
+ res
+
+ private def doStop(im: NCIntentMatch, o: Order): NCResult =
+ val res =
+ if !o.isEmpty then NCResult(s"Everything cancelled. Ask `menu` to
look what you can order.", ASK_RESULT)
+ else NCResult(s"Nothing to cancel. Ask `menu` to look what you can
order.", ASK_RESULT)
+ clear(im, o)
+ res
+
+ private def doContinue(o: Order): NCResult =
+ val res = NCResult(s"OK, please continue.", ASK_RESULT)
+ o.setState(NO_DIALOG)
+ res
+
+ private def askConfirmOrAskSpecify(o: Order): NCResult = if o.isValid then
askConfirm(o) else askSpecify(o)
+ private def askIsReadyOrAskSpecify(o: Order): NCResult = if o.isValid then
askIsReady(o) else askSpecify(o)
+ private def doExecuteOrAskSpecify(im: NCIntentMatch, o: Order): NCResult =
if o.isValid then doExecute(im, o) else askSpecify(o)
+ private def askStopOrDoStop(im: NCIntentMatch, o: Order): NCResult = if
o.isValid then askShouldStop(o) else doStop(im, o)
+
+ /**
+ *
+ * @param im
+ * @return
+ */
@NCIntent("intent=yes term(yes)={# == 'ord:yes'}")
- def onYes(im: NCIntentMatch, @NCIntentTerm("yes") yes: NCEntity): NCResult
=
- val o = getOrder(im)
- val lastIntentId = getLastIntentId(im).orNull
-
-// if o.isWait4Approve then
-// o.wait4Approve(false)
-// mkOrderConfirmDialog(o)
-// else if lastIntentId == "stop" then mkOrderContinueDialog(o)
-// else mkOrderFinishDialog(o)
- null
-
+ def onYes(im: NCIntentMatch): NCResult = withLog(
+ im,
+ (o: Order) => o.getState match
+ case DIALOG_CONFIRM =>
+ require(o.isValid);
+ 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.")
+ )
+
+ /**
+ *
+ * @param im
+ * @return
+ */
@NCIntent("intent=no term(no)={# == 'ord:no'}")
- def onNo(im: NCIntentMatch, @NCIntentTerm("no") no: NCEntity): NCResult =
- val o = getOrder(im)
- val lastIntentId = getLastIntentId(im).orNull
-
-// if o.isWait4Approve then
-// o.wait4Approve(false)
-// mkClearResult(im, o)
-// else if lastIntentId == "stop" then mkOrderContinueDialog(o)
-// else mkOrderFinishDialog(o)
- null
-
+ def onNo(im: NCIntentMatch): NCResult = withLog(
+ im,
+ (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.")
+ )
+ /**
+ *
+ * @param im
+ * @return
+ */
@NCIntent("intent=stop term(stop)={# == 'ord:stop'}")
- def onStop(im: NCIntentMatch, @NCIntentTerm("stop") stop: NCEntity):
NCResult =
- val o = getOrder(im)
-
- o.getState match
- case ORDER_VALID | ORDER_INVALID =>
- o.setState(ASK_CANCEL)
- NCResult("Are you sure that you want to cancel current
order?", ASK_DIALOG)
- case _ => NCResult("Nothing to cancel.", ASK_RESULT)
-
+ def onStop(im: NCIntentMatch): NCResult = withLog(
+ im,
+ // It doesn't depend on order validity and dialog state.
+ (o: Order) => askStopOrDoStop(im, o)
+ )
+
+ /**
+ *
+ * @param im
+ * @param ps
+ * @param ds
+ * @return
+ */
@NCIntent("intent=order term(ps)={# == 'ord:pizza'}* term(ds)={# ==
'ord:drink'}*")
- def onOrder(im: NCIntentMatch, @NCIntentTerm("ps") ps: List[NCEntity],
@NCIntentTerm("ds") ds: List[NCEntity]): NCResult =
- if ps.isEmpty && ds.isEmpty then throw new NCRejection("Please order
some pizza or drinks")
-
- val o = getOrder(im)
-
- for (p <- ps) o.addPizza(extractPizza(p))
- for (d <- ds) o.addDrink(extractDrink(d))
-
- mkOrderFinishDialog(o)
-
+ 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");
+ o.add(ps.map(extractPizza), ds.map(extractDrink)); // It doesn't
depend on order validity and dialog state.
+ askIsReadyOrAskSpecify(o)
+ )
+ /**
+ *
+ * @param im
+ * @param size
+ * @return
+ */
@NCIntent("intent=orderPizzaSize term(size)={# == 'ord:pizza:size'}")
- def onOrderPizzaSize(im: NCIntentMatch, @NCIntentTerm("size") size:
NCEntity): NCResult =
- val o = getOrder(im)
-
- o.getState match
- case ORDER_INVALID => o.setPizzaNoSize(extractPizzaSize(size))
- case _ => NCRejection("") // TODO
-
- mkOrderFinishDialog(o)
-
+ def onOrderPizzaSize(im: NCIntentMatch, @NCIntentTerm("size") size:
NCEntity): NCResult = withLog(
+ im,
+ (o: Order) => o.getState match
+ case DIALOG_SPECIFY =>
+ 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.")
+ )
+ /**
+ *
+ * @param im
+ * @return
+ */
@NCIntent("intent=status term(status)={# == 'ord:status'}")
- def onStatus(im: NCIntentMatch, @NCIntentTerm("status") s: NCEntity):
NCResult =
- val o = getOrder(im)
-
- o.getState match
- case ORDER_VALID | ORDER_INVALID =>
NCResult(OrderModel.toString(o), ASK_RESULT)
- case _ => NCResult("Nothing ordered.", ASK_RESULT)
-
+ def onStatus(im: NCIntentMatch): NCResult = withLog(
+ im,
+ (o: Order) => o.getState match
+ case DIALOG_CONFIRM =>
+ require(o.isValid);
+ askConfirm(o) // Ignore `status`, confirm again.
+ //case DIALOG_SPECIFY => askSpecify(o) // Ignore `status`, specify
again.
+ case DIALOG_SHOULD_CANCEL => doShowStatus(o, NO_DIALOG) // Changes
state.
+ case NO_DIALOG | DIALOG_IS_READY | DIALOG_SPECIFY =>
doShowStatus(o, o.getState) // Keeps same state.
+ )
+ /**
+ *
+ * @param im
+ * @return
+ */
@NCIntent("intent=finish term(finish)={# == 'ord:finish'}")
- def onFinish(im: NCIntentMatch, @NCIntentTerm("finish") f: NCEntity):
NCResult =
- val o = getOrder(im)
-
- o.getState match
- case ORDER_VALID | ASK_CONTINUE =>
- o.setState(ASK_CONFIRM)
- mkOrderConfirmDialog(o)
- case _ => NCResult("Nothing to finish.", ASK_RESULT)
-
+ def onFinish(im: NCIntentMatch): NCResult = withLog(
+ im,
+ (o: Order) => o.getState match
+ case DIALOG_CONFIRM => doExecuteOrAskSpecify(im, o) // Like YES
if valid.
+ case DIALOG_SPECIFY => askSpecify(o) // Ignore `finish`, specify
again.
+ case NO_DIALOG | DIALOG_IS_READY | DIALOG_SHOULD_CANCEL =>
askConfirmOrAskSpecify(o)
+ )
+ /**
+ *
+ * @param im
+ * @return
+ */
@NCIntent("intent=menu term(menu)={# == 'ord:menu'}")
- def onMenu(im: NCIntentMatch, @NCIntentTerm("menu") m: NCEntity): NCResult
=
- NCResult(
- "There are margherita, marbonara and marinara. Sizes: large,
medium or small. " +
- "Also there are tea, grean tea, coffee and cola.",
- ASK_RESULT
- )
\ No newline at end of file
+ def onMenu(im: NCIntentMatch): NCResult = withLog(
+ im,
+ // It doesn't depend and doesn't influence on order validity and
dialog state.
+ _ => doShowMenu()
+ )
\ 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
new file mode 100644
index 00000000..723db572
--- /dev/null
+++
b/nlpcraft-examples/order/src/main/java/org/apache/nlpcraft/examples/order/components/StanfordPipeline.scala
@@ -0,0 +1,49 @@
+/*
+ * 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 edu.stanford.nlp.pipeline.StanfordCoreNLP
+import opennlp.tools.stemmer.PorterStemmer
+import org.apache.nlpcraft.*
+import org.apache.nlpcraft.nlp.entity.parser.semantic.*
+import org.apache.nlpcraft.nlp.entity.parser.stanford.NCStanfordNLPEntityParser
+import org.apache.nlpcraft.nlp.token.parser.stanford.NCStanfordNLPTokenParser
+import scala.jdk.CollectionConverters.*
+import java.util.Properties
+
+/**
+ *
+ */
+object StanfordPipeline:
+ val PIPELINE: NCPipeline =
+ val stanford =
+ val props = new Properties()
+ props.setProperty("annotators", "tokenize, ssplit, pos, lemma,
ner")
+ new StanfordCoreNLP(props)
+ val tokParser = new NCStanfordNLPTokenParser(stanford)
+ val stemmer = new NCSemanticStemmer():
+ private val ps = new PorterStemmer
+ override def stem(txt: String): String = ps.synchronized {
ps.stem(txt) }
+
+ new NCPipelineBuilder().
+ withTokenParser(tokParser).
+ withEntityParser(new NCStanfordNLPEntityParser(stanford,
"number")).
+ withEntityParser(new NCSemanticEntityParser(stemmer, tokParser,
"order_model.yaml")).
+ withEntityMappers(Seq(new PizzaSizeExtender, new PizzaQtyExtender,
new DrinkQtyExtender).asJava).
+ withEntityValidator(new OrderValidator).
+ build()
\ No newline at end of file
diff --git a/nlpcraft-examples/order/src/main/resources/order_model.yaml
b/nlpcraft-examples/order/src/main/resources/order_model.yaml
index 40b07c30..450d3a0d 100644
--- a/nlpcraft-examples/order/src/main/resources/order_model.yaml
+++ b/nlpcraft-examples/order/src/main/resources/order_model.yaml
@@ -20,7 +20,7 @@ elements:
description: "Kinds of pizza."
values:
"margherita": [ ]
- "marbonara": [ ]
+ "carbonara": [ ]
"marinara": [ ]
- id: "ord:pizza:size"
@@ -63,6 +63,7 @@ elements:
- id: "ord:finish"
description: "Order finish."
synonyms:
+ - "order"
- "{order|I|_} {is|are|have|has|_} {ready|done|finish}"
- id: "ord:menu"
diff --git
a/nlpcraft-examples/order/src/test/java/org/apache/nlpcraft/examples/order/cli/OrderModelClientCli.scala
b/nlpcraft-examples/order/src/test/java/org/apache/nlpcraft/examples/order/cli/OrderModelClientCli.scala
index 01cd4a1e..35c8ae0b 100644
---
a/nlpcraft-examples/order/src/test/java/org/apache/nlpcraft/examples/order/cli/OrderModelClientCli.scala
+++
b/nlpcraft-examples/order/src/test/java/org/apache/nlpcraft/examples/order/cli/OrderModelClientCli.scala
@@ -65,7 +65,11 @@ object OrderModelClientCli extends LazyLogging :
print(s">>> ")
try
- println(ask(scala.io.StdIn.readLine()))
+ var in = scala.io.StdIn.readLine()
+
+ if in != null then
+ in = in.trim
+ if in.nonEmpty then println(ask(in))
println
catch
case e: NCRejection => println(s"Request rejected:
${e.getMessage}")