blob: 4f9393666d0c7ffc1347fdafb9beae85fc386f18 [file] [log] [blame]
/*
* 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.probe.mgrs.model
import io.opencensus.trace.Span
import org.apache.nlpcraft.common._
import org.apache.nlpcraft.common.ascii.NCAsciiTable
import org.apache.nlpcraft.model._
import org.apache.nlpcraft.probe.mgrs.NCProbeModel
import org.apache.nlpcraft.probe.mgrs.deploy._
import scala.util.control.Exception._
/**
* Model manager.
*/
object NCModelManager extends NCService {
// Deployed models keyed by their IDs.
@volatile private var data: Map[String, NCProbeModel] = _
// Access mutex.
private final val mux = new Object()
/**
*
* @param parent Optional parent span.
* @throws NCE
* @return
*/
@throws[NCE]
override def start(parent: Span = null): NCService = startScopedSpan("start", parent) { span =>
ackStarting()
mux.synchronized {
data = NCDeployManager.getModels.map(pm => {
pm.model.onInit()
pm.model.getId -> pm
}).toMap
logger.info(s"Models deployed: ${data.size}")
if (data.isEmpty) {
logger.error(s"To start the probe provide $BO${R}at least one model:$RST")
logger.error(" +-- Check probe configuration ('probe.conf' file) or -DNLPCRAFT_TEST_MODELS system property if using embedded probe.")
throw new NCE(s"Probe requires at least one model deployed to start.")
}
data.values.foreach(pm => {
val mdl = pm.model
val contCnt = pm.continuousSynonyms.flatMap(_._2.map(_._2.count)).sum
val sparseCnt = pm.sparseSynonyms.map(_._2.size).sum
val allIdlSyns = pm.idlSynonyms.values.flatMap(_.toSeq)
val sparseIdlCnt = allIdlSyns.count(_.sparse)
val contIdlCnt = allIdlSyns.size - sparseIdlCnt
def withWarn(i: Int): String = if (i == 0) s"0 ${r("(!)")}" else i.toString
val tbl = NCAsciiTable()
tbl += Seq(
s"${B}Name:$RST ${bo(c(mdl.getName))}",
s"${B}ID:$RST ${bo(mdl.getId)}",
s"${B}Version:$RST ${mdl.getVersion}",
s"${B}Origin:$RST ${mdl.getOrigin}",
s"${B}Elements:$RST ${withWarn(pm.elements.keySet.size)}"
)
tbl += Seq(
s"${B}Synonyms:$RST",
s"$B Simple continuous:$RST $contCnt",
s"$B Simple sparse:$RST $sparseCnt",
s"$B IDL continuous:$RST $contIdlCnt",
s"$B IDL sparse:$RST $sparseIdlCnt",
)
tbl += Seq(s"${B}Intents:$RST ${withWarn(pm.intents.size)}") ++
(
for (cb <- pm.callbacks) yield
s" ${g(bo(cb._1))} @ ${m(cb._2.origin)} -> ${c(cb._2.className)}${bo("#")}${c(cb._2.methodName)}(...)"
).toSeq
tbl.info(logger, Some("Model:"))
})
}
addTags(
span,
"deployedModels" -> data.values.map(_.model.getId).mkString(",")
)
ackStarted()
}
/**
* Stops this component.
*/
override def stop(parent: Span = null): Unit = startScopedSpan("stop", parent) { _ =>
ackStopping()
mux.synchronized {
if (data != null)
data.values.foreach(m => discardModel(m.model))
}
ackStopped()
}
/**
*
* @param mdl
*/
private def discardModel(mdl: NCModel): Unit = {
require(Thread.holdsLock(mux))
ignoring(classOf[Throwable]) {
// Ack.
logger.info(s"Model discarded: ${mdl.getId}")
mdl.onDiscard()
}
}
/**
*
* @return
*/
def getAllModels(parent: Span = null): List[NCProbeModel] =
startScopedSpan("getAllModels", parent) { _ =>
mux.synchronized { data.values.toList }
}
/**
*
* @param mdlId Model ID.
*/
def getModelOpt(mdlId: String, parent: Span = null): Option[NCProbeModel] =
startScopedSpan("getModelOpt", parent, "mdlId" -> mdlId) { _ =>
mux.synchronized { data.get(mdlId) }
}
/**
*
* @param mdlId Model ID.
*/
def getModel(mdlId: String, parent: Span = null): NCProbeModel =
getModelOpt(mdlId, parent).getOrElse(throw new NCE(s"Model not found: $mdlId"))
}