This is an automated email from the ASF dual-hosted git repository.
sergeykamov pushed a commit to branch NLPCRAFT-477
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git
The following commit(s) were added to refs/heads/NLPCRAFT-477 by this push:
new 91aeced WIP.
91aeced is described below
commit 91aeced201f88f0c20365f7755e26053f1c56aa0
Author: Sergey Kamov <[email protected]>
AuthorDate: Thu Feb 17 22:03:41 2022 +0300
WIP.
---
.../scala/org/apache/nlpcraft/NCIntentMatch.java | 8 ++
.../internal/intent/matcher/NCIntentMatcher.scala | 27 ------
.../internal/intent/matcher/NCIntentSolver.scala | 108 +++++++++++----------
.../dialogflow/NCDialogFlowManagerSpec.scala | 11 ++-
.../impl/scan/NCModelIntentsInvalidArgsSpec.scala | 9 +-
5 files changed, 74 insertions(+), 89 deletions(-)
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/NCIntentMatch.java
b/nlpcraft/src/main/scala/org/apache/nlpcraft/NCIntentMatch.java
index 372c24d..0c1259c 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/NCIntentMatch.java
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/NCIntentMatch.java
@@ -78,4 +78,12 @@ public interface NCIntentMatch {
* @see #getIntentEntities()
*/
NCVariant getVariant();
+
+
+ /**
+ * Gets context of the user input query.
+ *
+ * @return Original query context.
+ */
+ NCContext getContext();
}
diff --git
a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentMatcher.scala
b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentMatcher.scala
deleted file mode 100644
index 5fde322..0000000
---
a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentMatcher.scala
+++ /dev/null
@@ -1,27 +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.internal.intent.matcher
-
-/**
- *
- */
-object NCIntentMatcher:
- /**
- *
- */
- def bestMatch(): Unit = ???
\ No newline at end of file
diff --git
a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentSolver.scala
b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentSolver.scala
index a4b067c..5e7fcca 100644
---
a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentSolver.scala
+++
b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/intent/matcher/NCIntentSolver.scala
@@ -32,12 +32,6 @@ import scala.jdk.CollectionConverters.*
import scala.language.postfixOps
/**
-// TODO: order.
- // TODO: NCIntentSolverInput contains model.
- // TODO: logic with RedoSolver.
- // TODO: NCIntentMatcher API.
- // TODO: why 2 classes NCIntentSolver and NCIntentSolverEngine.
-
* Intent solver that finds the best matching intent given user sentence.
*/
case class NCIntentSolver(dialog: NCDialogFlowManager, intents:
Map[NCIDLIntent, NCIntentMatch => NCResult]) extends LazyLogging:
@@ -570,72 +564,80 @@ case class NCIntentSolver(dialog: NCDialogFlowManager,
intents: Map[NCIDLIntent,
/**
*
- * @param in Intent solver input.
+ * @param slvIn Intent solver input.
* @param span Parent span.
* @return
* @throws NCRejection
*/
- private def solveIteration(in: NCIntentSolverInput): Option[NCResult] =
+ private def solveIteration(slvIn: NCIntentSolverInput): Option[NCResult] =
// Should it be an assertion?
if intents.isEmpty then throw new NCRejection("Intent solver has no
registered intents.")
- val ctx = in.context
+ val ctx = slvIn.context
val req = ctx.getRequest
- val results =
+ val intentResults =
try solveIntents(ctx, intents)
catch case e: Exception => throw new NCRejection("Processing
failed due to unexpected error.", e)
- if results.isEmpty then throw new NCRejection("No matching intent
found.")
-
- var i = -1
-
- for (res <- results if res != null)
+ if intentResults.isEmpty then throw new NCRejection("No matching
intent found.")
+
+ object Loop:
+ private var data: Option[Option[NCResult]] = None
+ private var stopped: Boolean = false
+
+ def hasNext: Boolean = !stopped
+
+ def finish(data: Option[NCResult]): Unit =
+ Loop.data = Option(data)
+ Loop.stopped = true
+
+ def result: Option[NCResult] = data.getOrElse(throw new
NCRejection("No matching intent found - all intents were skipped."))
+
+ for (intentRes <- intentResults.filter(_ != null) if Loop.hasNext)
+ val intentMatch: NCIntentMatch =
+ new NCIntentMatch:
+ override val getContext: NCContext = ctx
+ override val getIntentId: String = intentRes.intentId
+ override val getIntentEntities: JList[JList[NCEntity]] =
intentRes.groups.map(_.entities).map(_.asJava).asJava
+ override def getTermEntities(idx: Int): JList[NCEntity] =
intentRes.groups(idx).entities.asJava
+ override def getTermEntities(termId: String):
JList[NCEntity] =
+ intentRes.groups.find(_.termId === termId) match
+ case Some(g) => g.entities.asJava
+ case None => Collections.emptyList()
+ override val getVariant: NCVariant =
+ new NCVariant:
+ override def getEntities: JList[NCEntity] =
intentRes.variant.entities.asJava
try
- i += 1
-
- val intentMatch: NCIntentMatch =
- new NCIntentMatch:
- override val getIntentId: String = res.intentId
- override val getIntentEntities: JList[JList[NCEntity]]
= res.groups.map(_.entities).map(_.asJava).asJava
- override def getTermEntities(idx: Int):
JList[NCEntity] = res.groups(idx).entities.asJava
- override def getTermEntities(termId: String):
JList[NCEntity] =
- res.groups.find(_.termId === termId) match
- case Some(g) => g.entities.asJava
- case None => Collections.emptyList()
- override val getVariant: NCVariant =
- new NCVariant:
- override def getEntities: JList[NCEntity] =
res.variant.entities.asJava
-
- if !in.model.onMatchedIntent(intentMatch) then
- logger.info(
- s"Model '${ctx.getModelConfig.getId}' triggered
rematching of intents by intent '${res.intentId}' on variant #${res.variantIdx
+ 1}."
- )
+ if slvIn.model.onMatchedIntent(intentMatch) then
+ // This can throw NCIntentSkip exception.
+ val cbRes = intentRes.fn(intentMatch)
- return None
+ // Store won intent match in the input.
+ slvIn.intentMatch = intentMatch
- // This can throw NCIntentSkip exception.
- val cbRes = res.fn(intentMatch)
+ if cbRes.getIntentId == null then
+ cbRes.setIntentId(intentRes.intentId)
- // Store won intent match in the input.
- in.intentMatch = intentMatch
+ logger.info(s"Intent '${intentRes.intentId}' for variant
#${intentRes.variantIdx + 1} selected as the <|best match|>")
- if cbRes.getIntentId == null then
- cbRes.setIntentId(res.intentId)
+ dialog.addMatchedIntent(intentMatch, cbRes, ctx)
- logger.info(s"Intent '${res.intentId}' for variant
#${res.variantIdx + 1} selected as the <|best match|>")
-
- dialog.addMatchedIntent(intentMatch, cbRes, ctx)
+ Loop.finish(Option(cbRes))
+ else
+ logger.info(
+ s"Model '${ctx.getModelConfig.getId}' triggered
rematching of intents by intent '${intentRes.intentId}' on variant
#${intentRes.variantIdx + 1}."
+ )
- return Option(cbRes)
- catch
- case e: NCIntentSkip =>
- // No-op - just skipping this result.
- e.getMessage match
- case s if s != null => logger.info(s"Selected intent
'${res.intentId}' skipped: $s")
- case _ => logger.info(s"Selected intent
'${res.intentId}' skipped.")
+ Loop.finish(None)
+ catch
+ case e: NCIntentSkip =>
+ // No-op - just skipping this result.
+ e.getMessage match
+ case s if s != null => logger.info(s"Selected
intent '${intentRes.intentId}' skipped: $s")
+ case _ => logger.info(s"Selected intent
'${intentRes.intentId}' skipped.")
- throw new NCRejection("No matching intent found - all intents were
skipped.")
+ Loop.result
/**
*
@@ -649,7 +651,7 @@ case class NCIntentSolver(dialog: NCDialogFlowManager,
intents: Map[NCIDLIntent,
while (res != null)
solveIteration(in) match
- case Some(solverRes) => res = solverRes
+ case Some(iterRes) => res = iterRes
case None => // No-op.
res
\ No newline at end of file
diff --git
a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/dialogflow/NCDialogFlowManagerSpec.scala
b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/dialogflow/NCDialogFlowManagerSpec.scala
index 55b4816..ef93002 100644
---
a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/dialogflow/NCDialogFlowManagerSpec.scala
+++
b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/dialogflow/NCDialogFlowManagerSpec.scala
@@ -28,12 +28,13 @@ import java.util
*
*/
class NCDialogFlowManagerSpec:
- case class IntentMatchMock(intentId: String) extends NCIntentMatch:
- override def getIntentId: String = intentId
- override def getIntentEntities: util.List[util.List[NCEntity]] = null
+ case class IntentMatchMock(intentId: String, ctx: NCContext) extends
NCIntentMatch:
+ override val getContext: NCContext = ctx
+ override val getIntentId: String = intentId
+ override val getIntentEntities: util.List[util.List[NCEntity]] = null
override def getTermEntities(idx: Int): util.List[NCEntity] = null
override def getTermEntities(termId: String): util.List[NCEntity] =
null
- override def getVariant: NCVariant = null
+ override val getVariant: NCVariant = null
case class ContextMock(userId: String, reqTs: Long = NCUtils.now())
extends NCContext:
override def isOwnerOf(ent: NCEntity): Boolean = false
@@ -68,7 +69,7 @@ class NCDialogFlowManagerSpec:
* @param id
* @param ctx
*/
- private def addMatchedIntent(id: String, ctx: NCContext): Unit =
mgr.addMatchedIntent(IntentMatchMock(id), null, ctx)
+ private def addMatchedIntent(id: String, ctx: NCContext): Unit =
mgr.addMatchedIntent(IntentMatchMock(id, ctx), null, ctx)
/**
*
diff --git
a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/scan/NCModelIntentsInvalidArgsSpec.scala
b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/scan/NCModelIntentsInvalidArgsSpec.scala
index 2ed745e..ebd5ed5 100644
---
a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/scan/NCModelIntentsInvalidArgsSpec.scala
+++
b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/scan/NCModelIntentsInvalidArgsSpec.scala
@@ -68,12 +68,13 @@ class NCModelIntentsInvalidArgsSpec:
def col[T](t: T): util.List[T] = java.util.Collections.singletonList(t)
new NCIntentMatch:
- override def getIntentId: String = "intentId"
- override def getIntentEntities: util.List[util.List[NCEntity]] =
col(col(e))
+ override val getContext: NCContext = null
+ override val getIntentId: String = "intentId"
+ override val getIntentEntities: util.List[util.List[NCEntity]] =
col(col(e))
override def getTermEntities(idx: Int): util.List[NCEntity] =
col(e)
override def getTermEntities(termId: String): util.List[NCEntity]
= col(e)
- override def getVariant: NCVariant = new NCVariant:
- override def getEntities: util.List[NCEntity] = col(e)
+ override val getVariant: NCVariant = new NCVariant:
+ override val getEntities: util.List[NCEntity] = col(e)
private def mkResult0(obj: Any): NCResult =
println(s"Result body: $obj, class=${obj.getClass}")