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 2021/07/07 09:34:37 UTC

[incubator-nlpcraft] 01/01: WIP.

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

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

commit 29be252427bcb70b2b7d5ca6d3b3112dcc87fcaf
Author: Sergey Kamov <sk...@gmail.com>
AuthorDate: Wed Jul 7 12:34:25 2021 +0300

    WIP.
---
 .../org/apache/nlpcraft/common/util/NCUtils.scala  | 62 +++++++++++++++-------
 .../apache/nlpcraft/model/NCIntentSampleRef.java   | 41 ++++++++++++++
 .../probe/mgrs/deploy/NCDeployManager.scala        | 50 +++++++++++------
 3 files changed, 120 insertions(+), 33 deletions(-)

diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/util/NCUtils.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/util/NCUtils.scala
index ef20c34..becbb36 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/util/NCUtils.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/util/NCUtils.scala
@@ -2233,29 +2233,55 @@ object NCUtils extends LazyLogging {
         }
     }
 
+    def isFile(path: String): Boolean = {
+        val f = new File(path)
+
+        f.exists() && f.isFile
+    }
+
     /**
       *
-      * @param s
+      * @return
       */
-    def isSuitableConfig(s: String): Boolean = {
-        def isFile: Boolean = {
-            val f = new File(s)
-
-            f.exists() && f.isFile
-        }
+    def isResource(res: String): Boolean = getClass.getClassLoader.getResource(res) != null
 
-        def isResource: Boolean = getClass.getClassLoader.getResource(s) != null
+    /**
+      *
+      * @param url
+      * @return
+      */
+    def isUrl(url: String): Boolean =
+        try {
+            new URL(url)
 
-        def isUrl: Boolean =
-            try {
-                new URL(s)
+            true
+        }
+        catch {
+            case _: MalformedURLException => false
+        }
 
-                true
-            }
-            catch {
-                case _: MalformedURLException => false
-            }
+    /**
+      *
+      * @param s
+      */
+    def isSuitableConfig(s: String): Boolean = isFile(s) || isResource(s) || isUrl(s)
 
-        isFile || isResource || isUrl
-    }
+    /**
+      *
+      * @param src
+      * @throws
+      * @return
+      */
+    @throws[NCE]
+    def readAnySource(src: String): List[String] =
+        if (isFile(src))
+            readFile(new File(src))
+        else if (isResource(src))
+            readResource(src)
+        else if (isUrl(src))
+            Using.resource(new URL(src).openStream()) { is => readStream(is) }
+        else {
+            // TODO:
+            throw new NCE(s"Source is not found: $src")
+        }
 }
\ No newline at end of file
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/NCIntentSampleRef.java b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/NCIntentSampleRef.java
new file mode 100644
index 0000000..19d236b
--- /dev/null
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/NCIntentSampleRef.java
@@ -0,0 +1,41 @@
+/*
+ * 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.model;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+// TODO:
+@Retention(value=RUNTIME)
+@Target(value=METHOD)
+@Repeatable(NCIntentSampleRef.NCIntentSampleList.class)
+public @interface NCIntentSampleRef {
+    String value();
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(value=METHOD)
+    @Documented
+    @interface NCIntentSampleList {
+        NCIntentSampleRef[] value();
+    }
+}
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala
index 9e5ec78..b081798 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala
@@ -57,6 +57,7 @@ object NCDeployManager extends NCService {
     private final val CLS_QRY_RES = classOf[NCResult]
     private final val CLS_SLV_CTX = classOf[NCIntentMatch]
     private final val CLS_SAMPLE = classOf[NCIntentSample]
+    private final val CLS_SAMPLE_REF = classOf[NCIntentSampleRef]
 
     // Java and scala lists.
     private final val CLS_SCALA_SEQ = classOf[Seq[_]]
@@ -1611,32 +1612,50 @@ object NCDeployManager extends NCService {
             val mtdStr = method2Str(m)
 
             val smpAnns = m.getAnnotationsByType(CLS_SAMPLE)
+            val smpAnnsRef = m.getAnnotationsByType(CLS_SAMPLE_REF)
             val intAnns = m.getAnnotationsByType(CLS_INTENT)
             val refAnns = m.getAnnotationsByType(CLS_INTENT_REF)
 
-            if (smpAnns.nonEmpty) {
-                if (intAnns.isEmpty && refAnns.isEmpty)
-                    throw new NCE(s"@NCIntentSample annotation without corresponding @NCIntent or @NCIntentRef annotations: $mtdStr")
+            if (smpAnns.nonEmpty || smpAnnsRef.nonEmpty) {
+                if (intAnns.isEmpty && refAnns.isEmpty) {
+                    // TODO:
+                    throw new NCE(s"@NCIntentSample or @NCIntentSampleRef annotations without corresponding @NCIntent or @NCIntentRef annotations: $mtdStr")
+                }
                 else {
-                    val seqSeq = smpAnns.toSeq.map(_.value().toSeq)
+                    def read[T](arr: Array[T], claxx: Class[_], getValue: T => Seq[String]): Seq[Seq[String]] = {
+                        val seq = arr.toSeq.map(getValue)
+
+                        if (seq.exists(_.isEmpty))
+                            logger.warn(s"@${claxx.getName} annotation is empty: $mtdStr")
 
-                    if (seqSeq.exists(_.isEmpty))
-                        logger.warn(s"@NCIntentSample annotation is empty: $mtdStr")
+                        seq
+                    }
+
+                    val seqSeq =
+                        read[NCIntentSample](
+                            smpAnns, classOf[NCIntentSample], _.value().toSeq
+                        ) ++
+                        read[NCIntentSampleRef](
+                            smpAnnsRef, classOf[NCIntentSampleRef], a => U.readAnySource(a.value())
+                        )
+
+                    // TODO: text
                     if (U.containsDups(seqSeq.flatten.toList))
-                        logger.warn(s"@NCIntentSample annotation has duplicates: $mtdStr")
+                        logger.warn(s"@NCIntentSample and @NCIntentSampleRef annotations have duplicates: $mtdStr")
 
                     val distinct = seqSeq.map(_.distinct).distinct
 
-                    for (ann <- intAnns) {
-                        for (intent <- NCIdlCompiler.compileIntents(ann.value(), mdl, mtdStr))
-                            samples += (intent.id -> distinct)
-                    }
+                    for (ann <- intAnns; intent <- NCIdlCompiler.compileIntents(ann.value(), mdl, mtdStr))
+                        samples += (intent.id -> distinct)
+
                     for (ann <- refAnns)
                         samples += (ann.value() -> distinct)
                 }
             }
-            else if (intAnns.nonEmpty || refAnns.nonEmpty)
-                logger.warn(s"@NCIntentSample annotation is missing for: $mtdStr")
+            else if (intAnns.nonEmpty || refAnns.nonEmpty) {
+                // TODO: text
+                logger.warn(s"@NCIntentSample or @NCIntentSampleRef annotations are missing for: $mtdStr")
+            }
         }
 
         if (samples.nonEmpty) {
@@ -1656,7 +1675,7 @@ object NCDeployManager extends NCService {
             val processed = mutable.HashSet.empty[Case]
 
             samples.
-                flatMap { case (_, smp) =>smp.flatten.map(_.toLowerCase) }.
+                flatMap { case (_, smp) => smp.flatten.map(_.toLowerCase) }.
                 map(s => s -> SEPARATORS.foldLeft(s)((s, ch) => s.replaceAll(s"\\$ch", s" $ch "))).
                 foreach {
                     case (s, sNorm) =>
@@ -1666,7 +1685,8 @@ object NCDeployManager extends NCService {
                             if (!allSyns.exists(_.intersect(seq).nonEmpty)) {
                                 // Not a warning since the parent class can contain direct synonyms (NLPCRAFT-348).
                                 // See NLPCRAFT-349 for the additional issue.
-                                logger.debug(s"@NCIntentSample sample doesn't contain any direct synonyms (check if its parent class contains any) [" +
+                                // TODO: text
+                                logger.debug(s"@NCIntentSample or @NCIntentSampleRef sample doesn't contain any direct synonyms (check if its parent class contains any) [" +
                                     s"mdlId=$mdlId, " +
                                     s"origin=${mdl.getOrigin}, " +
                                     s"""sample="$s"""" +