You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nlpcraft.apache.org by se...@apache.org on 2022/03/29 18:47:50 UTC

[incubator-nlpcraft] branch NLPCRAFT-490 updated: WIP.

This is an automated email from the ASF dual-hosted git repository.

sergeykamov pushed a commit to branch NLPCRAFT-490
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git


The following commit(s) were added to refs/heads/NLPCRAFT-490 by this push:
     new f4071b9  WIP.
f4071b9 is described below

commit f4071b9f71d64012949d6dda7854719c1143f279
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Tue Mar 29 21:47:35 2022 +0300

    WIP.
---
 .../scala/org/apache/nlpcraft/NCModelClient.java   |  5 +-
 .../nlpcraft/internal/impl/NCModelClientImpl.scala | 14 +--
 .../intent/matcher/NCIntentSolverManager.scala     | 99 ++++++++++++++--------
 .../nlpcraft/internal/impl/NCModelClientSpec.scala |  2 +-
 .../internal/impl/NCModelClientSpec2.scala         |  4 +-
 5 files changed, 78 insertions(+), 46 deletions(-)

diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/NCModelClient.java b/nlpcraft/src/main/scala/org/apache/nlpcraft/NCModelClient.java
index b3c82a0..c90d436 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/NCModelClient.java
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/NCModelClient.java
@@ -109,9 +109,10 @@ public class NCModelClient implements AutoCloseable {
      * @param txt
      * @param data
      * @param usrId
+     * @param saveHistory
      * @return
      */
-    public NCWinnerIntent getWinnerIntent(String txt, Map<String, Object> data, String usrId) {
-        return impl.getWinnerIntent(txt, data, usrId);
+    public NCWinnerIntent getWinnerIntent(String txt, Map<String, Object> data, String usrId, boolean saveHistory) {
+        return impl.getWinnerIntent(txt, data, usrId, saveHistory);
     }
 }
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelClientImpl.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelClientImpl.scala
index 7c605b5..8637096 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelClientImpl.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelClientImpl.scala
@@ -26,6 +26,7 @@ import org.apache.nlpcraft.internal.dialogflow.NCDialogFlowManager
 import org.apache.nlpcraft.internal.impl.*
 import org.apache.nlpcraft.internal.intent.matcher.*
 import org.apache.nlpcraft.internal.util.*
+import org.apache.nlpcraft.internal.intent.matcher.NCIntentSolveType.*
 
 import java.util
 import java.util.concurrent.*
@@ -48,7 +49,7 @@ class NCModelClientImpl(mdl: NCModel) extends LazyLogging:
     private val convMgr = NCConversationManager(mdl.getConfig)
     private val dlgMgr = NCDialogFlowManager(mdl.getConfig)
     private val plMgr = NCModelPipelineManager(mdl.getConfig, mdl.getPipeline)
-    private val intentsMgr = NCIntentSolverManager(dlgMgr, intents.map(p => p.intent -> p.function).toMap)
+    private val intentsMgr = NCIntentSolverManager(dlgMgr, convMgr, intents.map(p => p.intent -> p.function).toMap)
 
     init()
 
@@ -75,7 +76,7 @@ class NCModelClientImpl(mdl: NCModel) extends LazyLogging:
         dlgMgr.start()
         plMgr.start()
 
-    private def ask0(txt: String, data: JMap[String, AnyRef], usrId: String, testRun: Boolean): Either[NCResult, NCWinnerIntent] =
+    private def ask0(txt: String, data: JMap[String, AnyRef], usrId: String, typ: NCIntentSolveType): Either[NCResult, NCWinnerIntent] =
         val plData = plMgr.prepare(txt, data, usrId)
 
         val userId = plData.request.getUserId
@@ -99,7 +100,7 @@ class NCModelClientImpl(mdl: NCModel) extends LazyLogging:
                 override val getVariants: util.Collection[NCVariant] = plData.variants.asJava
                 override val getTokens: JList[NCToken] = plData.tokens
 
-        intentsMgr.solve(mdl, ctx, testRun)
+        intentsMgr.solve(mdl, ctx, typ)
 
      /*
       * @param txt
@@ -107,7 +108,8 @@ class NCModelClientImpl(mdl: NCModel) extends LazyLogging:
       * @param usrId
       * @return
       */
-    def ask(txt: String, data: JMap[String, AnyRef], usrId: String): NCResult = ask0(txt, data, usrId, false).swap.toOption.get
+    def ask(txt: String, data: JMap[String, AnyRef], usrId: String): NCResult =
+        ask0(txt, data, usrId, REGULAR).swap.toOption.get
 
     /**
       *
@@ -190,5 +192,5 @@ class NCModelClientImpl(mdl: NCModel) extends LazyLogging:
         dlgMgr.close()
         convMgr.close()
 
-    def getWinnerIntent(txt: String, data: JMap[String, AnyRef], usrId: String): NCWinnerIntent =
-        ask0(txt, data, usrId, true).toOption.get
\ No newline at end of file
+    def getWinnerIntent(txt: String, data: JMap[String, AnyRef], usrId: String, saveHistory: Boolean): NCWinnerIntent =
+        ask0(txt, data, usrId, if saveHistory then TEST_HISTORY else TEST_NO_HISTORY).toOption.get
\ No newline at end of file
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 b46f38f..74a751a 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
@@ -20,6 +20,7 @@ package org.apache.nlpcraft.internal.intent.matcher
 import com.typesafe.scalalogging.LazyLogging
 import org.apache.nlpcraft.*
 import org.apache.nlpcraft.internal.ascii.NCAsciiTable
+import org.apache.nlpcraft.internal.conversation.NCConversationManager
 import org.apache.nlpcraft.internal.dialogflow.NCDialogFlowManager
 import org.apache.nlpcraft.internal.intent.*
 
@@ -31,6 +32,9 @@ import scala.collection.mutable.ArrayBuffer
 import scala.jdk.CollectionConverters.*
 import scala.language.postfixOps
 
+enum NCIntentSolveType:
+    case REGULAR, TEST_HISTORY, TEST_NO_HISTORY
+
 object NCIntentSolverManager:
     /**
       * Sentence variant & its weight.
@@ -229,7 +233,11 @@ import org.apache.nlpcraft.internal.intent.matcher.NCIntentSolverManager.*
 /**
  * Intent solver that finds the best matching intent given user sentence.
  */
-class NCIntentSolverManager(dialog: NCDialogFlowManager, intents: Map[NCIDLIntent, NCIntentMatch => NCResult]) extends LazyLogging:
+class NCIntentSolverManager(
+    dialog: NCDialogFlowManager,
+    conv: NCConversationManager,
+    intents: Map[NCIDLIntent, NCIntentMatch => NCResult]
+) extends LazyLogging:
     /**
      * Main entry point for intent engine.
      *
@@ -625,10 +633,10 @@ class NCIntentSolverManager(dialog: NCDialogFlowManager, intents: Map[NCIDLInten
       *
       * @param mdl
       * @param ctx
-      * @param testRun
+      * @param typ
       * @return
       */
-    private def solveIteration(mdl: NCModel, ctx: NCContext, testRun: Boolean): Option[IterationResult] =
+    private def solveIteration(mdl: NCModel, ctx: NCContext, typ: NCIntentSolveType): Option[IterationResult] =
         require(intents.nonEmpty)
 
         val req = ctx.getRequest
@@ -667,16 +675,33 @@ class NCIntentSolverManager(dialog: NCDialogFlowManager, intents: Map[NCIDLInten
             try
                 if mdl.onMatchedIntent(im) then
                     // This can throw NCIntentSkip exception.
-                    if testRun then
-                        Loop.finish(Option(IterationResult(Right(NCWinnerIntentImpl(im.getIntentId, im.getIntentEntities)), im)))
-                    else
-                        val cbRes = intentRes.fn(im)
-                        // Store won intent match in the input.
-                        if cbRes.getIntentId == null then
-                            cbRes.setIntentId(intentRes.intentId)
-                        logger.info(s"Intent '${intentRes.intentId}' for variant #${intentRes.variantIdx + 1} selected as the <|best match|>")
-                        dialog.addMatchedIntent(im, cbRes, ctx)
-                        Loop.finish(Option(IterationResult(Left(cbRes), im)))
+                    import NCIntentSolveType.*
+
+                    def saveHistory(r: NCResult): Unit =
+                        dialog.addMatchedIntent(im, r, ctx)
+                        conv.getConversation(req.getUserId).addEntities(
+                            req.getRequestId, im.getIntentEntities.asScala.flatMap(_.asScala).toSeq.distinct
+                        )
+
+                    typ match
+                        case REGULAR =>
+                            val cbRes = intentRes.fn(im)
+                            // Store won intent match in the input.
+                            if cbRes.getIntentId == null then
+                                cbRes.setIntentId(intentRes.intentId)
+                            logger.info(s"Intent '${intentRes.intentId}' for variant #${intentRes.variantIdx + 1} selected as the <|best match|>")
+
+                            saveHistory(cbRes)
+
+                            Loop.finish(Option(IterationResult(Left(cbRes), im)))
+
+                        case TEST_HISTORY =>
+                            // Added dummy result. TODO: is it ok?
+                            saveHistory(new NCResult())
+
+                            Loop.finish(Option(IterationResult(Right(NCWinnerIntentImpl(im.getIntentId, im.getIntentEntities)), im)))
+                        case TEST_NO_HISTORY =>
+                            Loop.finish(Option(IterationResult(Right(NCWinnerIntentImpl(im.getIntentId, im.getIntentEntities)), im)))
                 else
                     logger.info(s"Model '${ctx.getModelConfig.getId}' triggered rematching of intents by intent '${intentRes.intentId}' on variant #${intentRes.variantIdx + 1}.")
                     Loop.finish()
@@ -693,14 +718,16 @@ class NCIntentSolverManager(dialog: NCDialogFlowManager, intents: Map[NCIDLInten
       *
       * @param mdl
       * @param ctx
-      * @param testRun
+      * @param typ
       * @return
       */
-    def solve(mdl: NCModel, ctx: NCContext, testRun: Boolean): ResultData =
+    def solve(mdl: NCModel, ctx: NCContext, typ: NCIntentSolveType): ResultData =
+        import NCIntentSolveType.*
+
         val ctxRes = mdl.onContext(ctx)
 
         if ctxRes != null then
-            if testRun then E("`onContext` method overriden, intents cannot be found.") // TODO: test
+            if typ != REGULAR then E("`onContext` method overriden, intents cannot be found.") // TODO: test
             if intents.nonEmpty then logger.warn("`onContext` method overrides existed intents. They are ignored.") // TODO: text.
 
             Left(ctxRes)
@@ -713,29 +740,31 @@ class NCIntentSolverManager(dialog: NCDialogFlowManager, intents: Map[NCIDLInten
 
             try
                 while (loopRes == null)
-                    solveIteration(mdl, ctx, testRun) match
+                    solveIteration(mdl, ctx, typ) match
                         case Some(iterRes) => loopRes = iterRes
                         case None => // No-op.
 
-                if testRun then
-                    loopRes.result
-                else
-                    mdl.onResult(loopRes.intentMatch, loopRes.result.swap.toOption.get) match
-                        case null => loopRes.result
-                        case res => Left(res)
+                typ match
+                    case REGULAR =>
+                        mdl.onResult(loopRes.intentMatch, loopRes.result.swap.toOption.get) match
+                            case null => loopRes.result
+                            case res => Left(res)
+                    case _ => loopRes.result
             catch
                 case e: NCRejection =>
-                    if testRun then throw e
+                    typ match
+                        case REGULAR =>
+                            mdl.onRejection(if loopRes != null then loopRes.intentMatch else null, e) match
+                                case null => throw e
+                                case res => Left(res)
+                        case _ => throw e
 
-                    mdl.onRejection(if loopRes != null then loopRes.intentMatch else null, e) match
-                        case null => throw e
-                        case res => Left(res)
                 case e: Throwable =>
-                    if testRun then throw e
-
-                    mdl.onError(ctx, e) match
-                        case null => throw e
-                        case res =>
-                            logger.warn("Error during execution.", e)
-
-                            Left(res)
+                    typ match
+                        case REGULAR =>
+                            mdl.onError(ctx, e) match
+                                case null => throw e
+                                case res =>
+                                    logger.warn("Error during execution.", e)
+                                    Left(res)
+                        case _ => throw e
\ No newline at end of file
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec.scala
index f50fb14..d1c3daa 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec.scala
@@ -41,7 +41,7 @@ class NCModelClientSpec:
 
             client.validateSamples()
 
-            val winner = client.getWinnerIntent("Lights on at second floor kitchen", null, "userId")
+            val winner = client.getWinnerIntent("Lights on at second floor kitchen", null, "userId", true)
             println(s"Winner intent: ${winner.getIntentId}")
             println("Entities: \n" + winner.getArguments.asScala.map(p => p.asScala.map(s).mkString(", ")).mkString("\n"))
         }
diff --git a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec2.scala b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec2.scala
index 99e5d3b..b7c2f62 100644
--- a/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec2.scala
+++ b/nlpcraft/src/test/scala/org/apache/nlpcraft/internal/impl/NCModelClientSpec2.scala
@@ -44,7 +44,7 @@ class NCModelClientSpec2:
 
         Using.resource(new NCModelClient(mdl)) { client =>
             case class Result(txt: String):
-                private val wi = client.getWinnerIntent(txt, null, "userId")
+                private val wi = client.getWinnerIntent(txt, null, "userId", true)
                 private val allArgs: JList[JList[NCEntity]] = wi.getArguments
 
                 val intentId: String = wi.getIntentId
@@ -84,7 +84,7 @@ class NCModelClientSpec2:
 
             // 3. No winners.
             try
-                client.getWinnerIntent("x", null, "userId")
+                client.getWinnerIntent("x", null, "userId", false)
 
                 require(false)
             catch