This is an automated email from the ASF dual-hosted git repository.
sergeykamov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git
The following commit(s) were added to refs/heads/master by this push:
new 79255bb Bugfixes and tests.
79255bb is described below
commit 79255bbbe2f61ad36ff03713a52c00724da51b6e
Author: Sergey Kamov <[email protected]>
AuthorDate: Tue Feb 22 16:28:44 2022 +0300
Bugfixes and tests.
---
.../intent/matcher/NCIntentSolverManager.scala | 24 ++--
.../internal/impl/NCModelCallbacksSpec.scala | 157 +++++++++++++++++++++
2 files changed, 169 insertions(+), 12 deletions(-)
diff --git
a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentSolverManager.scala
b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentSolverManager.scala
index d093e9b..11475bd 100644
---
a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentSolverManager.scala
+++
b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentSolverManager.scala
@@ -697,26 +697,26 @@ class NCIntentSolverManager(dialog: NCDialogFlowManager,
intents: Map[NCIDLInten
* @return
*/
def solve(mdl: NCModel, ctx: NCContext): NCResult =
- val resCtx: NCResult = mdl.onContext(ctx)
+ var res: NCResult = mdl.onContext(ctx)
- if resCtx != null then
- resCtx
+ if res != null then
+ res
else
- var res: IterationResult = null
+ var loopRes: IterationResult = null
try
- while (res == null)
+ while (loopRes == null)
solveIteration(mdl, ctx) match
- case Some(iterRes) => res = iterRes
+ case Some(iterRes) => loopRes = iterRes
case None => // No-op.
- mdl.onResult(res.intentMatch, res.result)
+ res = mdl.onResult(loopRes.intentMatch, loopRes.result)
- res.result
+ if res != null then res else loopRes.result
catch
case e: NCRejection =>
- mdl.onRejection(if res != null then res.intentMatch else
null, e)
- throw e
+ val res = mdl.onRejection(if loopRes != null then
loopRes.intentMatch else null, e)
+ if res != null then res else throw e
case e: Throwable =>
- mdl.onError(ctx, e)
- throw e
\ No newline at end of file
+ val res = mdl.onError(ctx, e)
+ if res != null then res else throw e
\ No newline at end of file
diff --git
a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelCallbacksSpec.scala
b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelCallbacksSpec.scala
new file mode 100644
index 0000000..b601e5d
--- /dev/null
+++
b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelCallbacksSpec.scala
@@ -0,0 +1,157 @@
+/*
+ * 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.internal.impl
+
+import org.apache.nlpcraft.*
+import org.apache.nlpcraft.NCResultType.*
+import org.apache.nlpcraft.nlp.entity.parser.semantic.*
+import
org.apache.nlpcraft.nlp.entity.parser.semantic.impl.en.NCEnSemanticPorterStemmer
+import org.apache.nlpcraft.nlp.util.NCTestModelAdapter
+import org.apache.nlpcraft.nlp.util.opennlp.*
+import org.junit.jupiter.api.*
+
+import scala.jdk.CollectionConverters.*
+import scala.util.Using
+
+/**
+ *
+ */
+class NCModelCallbacksSpec:
+ enum State:
+ case
+ Default,
+ MatchFalse, VariantFalse,
+ ContextNotNull, ResultNotNull, RejectionNotNull, ErrorNotNull,
+ IntentError, IntentReject
+
+ import State.*
+
+ private val states = collection.mutable.HashSet.empty[State]
+
+ private val RESULT_INTENT = mkResult("result-intent")
+ private val RESULT_CONTEXT = mkResult("result-context")
+ private val RESULT_RESULT = mkResult("result-result")
+ private val RESULT_REJECTION = mkResult("result-rejection")
+ private val RESULT_ERROR = mkResult("result-error")
+
+ private val MDL: NCModel =
+ new NCTestModelAdapter():
+ @NCIntent("intent=x term(x)={# == 'x'}")
+ def intent(im: NCIntentMatch, @NCIntentTerm("x") x: NCEntity):
NCResult =
+ if has(IntentError) then throw new RuntimeException("Error")
+ else if has(IntentReject) then throw new
NCRejection("Rejection")
+ else RESULT_INTENT
+
+ override def onMatchedIntent(ctx: NCIntentMatch): Boolean = if
has(MatchFalse) then false else true
+ override def onVariant(vrn: NCVariant): Boolean = if
has(VariantFalse) then false else true
+ override def onContext(ctx: NCContext): NCResult = if
has(ContextNotNull) then RESULT_CONTEXT else null
+ override def onResult(ctx: NCIntentMatch, res: NCResult): NCResult
= if has(ResultNotNull) then RESULT_RESULT else null
+ override def onRejection(ctx: NCIntentMatch, e: NCRejection):
NCResult = if has(RejectionNotNull) then RESULT_REJECTION else null
+ override def onError(ctx: NCContext, e: Throwable): NCResult = if
has(ErrorNotNull) then RESULT_ERROR else null
+
+ MDL.getPipeline.getEntityParsers.add(
+ new NCSemanticEntityParser(
+ new NCEnSemanticPorterStemmer,
+ EN_PIPELINE.getTokenParser,
+ Seq(NCSemanticTestElement("x")).asJava
+ )
+ )
+
+ /**
+ *
+ * @param s
+ * @return
+ */
+ private def has(s: State): Boolean = states.synchronized {
states.contains(s) }
+
+ /**
+ *
+ * @param txt
+ * @return
+ */
+ private def mkResult(txt: String): NCResult =
+ val res = new NCResult()
+ res.setType(NCResultType.ASK_RESULT)
+ res.setBody(txt)
+ res
+
+ /**
+ *
+ * @param states
+ * @return
+ */
+ private def set(states: State*) =
+ this.states.synchronized {
+ this.states.clear()
+ this.states ++= states
+ }
+
+ /**
+ *
+ * @param client
+ * @param exp
+ * @param states
+ */
+ private def testOk(client: NCModelClient, exp: NCResult, states: State*):
Unit =
+ set(states*)
+
+ val res = client.ask("x", null, "userId")
+
+ require(res.getBody == exp.getBody)
+
+ /**
+ *
+ * @param client
+ * @param states
+ */
+ private def testFail(client: NCModelClient, states: State*): Unit =
+ set(states*)
+
+ try
+ client.ask("x", null, "userId")
+
+ require(false)
+ catch
+ case e: Throwable => println(s"Expected error: ${e.getMessage}")
+
+ /**
+ *
+ */
+ @Test
+ def test(): Unit = Using.resource(new NCModelClient(MDL)) { client =>
+ testOk(client, RESULT_INTENT)
+ testOk(client, RESULT_RESULT, ResultNotNull)
+ testOk(client, RESULT_CONTEXT, ContextNotNull)
+
+ testFail(client, IntentReject)
+ testFail(client, IntentError)
+ testFail(client, VariantFalse)
+
+ testOk(client, RESULT_REJECTION, IntentReject, RejectionNotNull)
+ testOk(client, RESULT_ERROR, IntentError, ErrorNotNull)
+
+ val threadReset =
+ new Thread("reset-thread"):
+ override def run(): Unit =
+ Thread.sleep(500)
+ states.clear()
+
+ threadReset.start()
+
+ testOk(client, RESULT_INTENT, MatchFalse)
+ }