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}")

Reply via email to