13.2. 直接嵌入 Java 应用程序中的 PMML 传统调用
当知识资产直接嵌入到调用程序中,或者被实际拉取为 KJAR 的 Maven 依赖关系时,KIE 容器是本地的。如果代码版本和 PMML 定义版本之间有紧密关系,则您直接将知识资产嵌入到项目中。在有意更新并重新部署应用程序后,对决策的任何更改都会生效。这种方法的一个优点是,正确的操作不依赖于任何外部依赖项来运行,这可能受锁定的环境限制。
使用 Maven 依赖项可进行进一步的灵活性,因为决策的特定版本可以动态更改(例如,使用系统属性),它可以定期扫描更新并自动更新。这会对服务的部署时间进行外部依赖,但在本地执行决策,从而减少在运行期间对外部服务的依赖。
先决条件
- 已创建包含要执行的 PMML 模型的 KJAR。有关项目打包的更多信息,请参阅 打包和部署 Red Hat Process Automation Manager 项目。
流程
在客户端应用程序中,将以下依赖项添加到 Java 项目的相关类路径中:
<!-- Required for the PMML compiler --> <dependency> <groupId>org.drools</groupId> <artifactId>kie-pmml</artifactId> <version>${rhpam.version}</version> </dependency> <!-- Required for the KIE public API --> <dependency> <groupId>org.kie</groupId> <artifactId>kie-api</artifactId> <version>${rhpam.version}</version> </dependencies> <!-- Required if not using classpath KIE container --> <dependency> <groupId>org.kie</groupId> <artifactId>kie-ci</artifactId> <version>${rhpam.version}</version> </dependency>
&
lt;version
> 是项目中当前使用的 Red Hat Process Automation Manager 的 Maven 工件版本(例如 7.67.0.Final-redhat-00024)。注意考虑将 Red Hat Business Automation 材料清单(BOM)依赖项添加到项目
pom.xml
文件,而不是为每个依赖项指定 Red Hat Process Automation Manager <version
>。Red Hat Business Automation BOM 适用于 Red Hat Decision Manager 和 Red Hat Process Automation Manager。添加 BOM 文件时,项目中包含来自提供的 Maven 存储库的正确依赖项版本。BOM 依赖项示例:
<dependency> <groupId>com.redhat.ba</groupId> <artifactId>ba-platform-bom</artifactId> <version>7.13.5.redhat-00002</version> <scope>import</scope> <type>pom</type> </dependency>
有关 Red Hat Business Automation BOM 的更多信息,请参阅 RHPAM 产品与 maven 库版本之间的映射是什么?
重要要使用传统实施,请确保将
kie-pmml-ement
ation 系统属性设置为legacy
。从
类路径
或ReleaseId
创建 KIE 容器:KieServices kieServices = KieServices.Factory.get(); ReleaseId releaseId = kieServices.newReleaseId( "org.acme", "my-kjar", "1.0.0" ); KieContainer kieContainer = kieServices.newKieContainer( releaseId );
备选选项:
KieServices kieServices = KieServices.Factory.get(); KieContainer kieContainer = kieServices.getKieClasspathContainer();
创建
PMMLRequestData
类的实例,它将您的 PMML 模型应用于一组数据:public class PMMLRequestData { private String correlationId; 1 private String modelName; 2 private String source; 3 private List<ParameterInfo<?>> requestParams; 4 ... }
创建
PMML4Result
类的实例,其中包含将 PMML 的规则应用到输入数据的输出信息:public class PMML4Result { private String correlationId; private String segmentationId; 1 private String segmentId; 2 private int segmentIndex; 3 private String resultCode; 4 private Map<String, Object> resultVariables; 5 ... }
除了普通的 getter 方法外,M
PMML4Result
类还支持以下方法直接检索结果变量的值:public <T> Optional<T> getResultValue(String objName, String objField, Class<T> clazz, Object...params) public Object getResultValue(String objName, String objField, Object...params)
创建
ParameterInfo
类的实例,作为作为PMMLRequestData
类一部分的基本数据类型对象的打包程序:public class ParameterInfo<T> { 1 private String correlationId; private String name; 2 private String capitalizedName; private Class<T> type; 3 private T value; 4 ... }
根据您创建的所需的 PMML 类实例执行 PMML 模型:
public void executeModel(KieBase kbase, Map<String,Object> variables, String modelName, String correlationId, String modelPkgName) { RuleUnitExecutor executor = RuleUnitExecutor.create().bind(kbase); PMMLRequestData request = new PMMLRequestData(correlationId, modelName); PMML4Result resultHolder = new PMML4Result(correlationId); variables.entrySet().forEach( es -> { request.addRequestParam(es.getKey(), es.getValue()); }); DataSource<PMMLRequestData> requestData = executor.newDataSource("request"); DataSource<PMML4Result> resultData = executor.newDataSource("results"); DataSource<PMMLData> internalData = executor.newDataSource("pmmlData"); requestData.insert(request); resultData.insert(resultHolder); List<String> possiblePackageNames = calculatePossiblePackageNames(modelName, modelPkgName); Class<? extends RuleUnit> ruleUnitClass = getStartingRuleUnit("RuleUnitIndicator", (InternalKnowledgeBase)kbase, possiblePackageNames); if (ruleUnitClass != null) { executor.run(ruleUnitClass); if ( "OK".equals(resultHolder.getResultCode()) ) { // extract result variables here } } } protected Class<? extends RuleUnit> getStartingRuleUnit(String startingRule, InternalKnowledgeBase ikb, List<String> possiblePackages) { RuleUnitRegistry unitRegistry = ikb.getRuleUnitRegistry(); Map<String,InternalKnowledgePackage> pkgs = ikb.getPackagesMap(); RuleImpl ruleImpl = null; for (String pkgName: possiblePackages) { if (pkgs.containsKey(pkgName)) { InternalKnowledgePackage pkg = pkgs.get(pkgName); ruleImpl = pkg.getRule(startingRule); if (ruleImpl != null) { RuleUnitDescr descr = unitRegistry.getRuleUnitFor(ruleImpl).orElse(null); if (descr != null) { return descr.getRuleUnitClass(); } } } } return null; } protected List<String> calculatePossiblePackageNames(String modelId, String...knownPackageNames) { List<String> packageNames = new ArrayList<>(); String javaModelId = modelId.replaceAll("\\s",""); if (knownPackageNames != null && knownPackageNames.length > 0) { for (String knownPkgName: knownPackageNames) { packageNames.add(knownPkgName + "." + javaModelId); } } String basePkgName = PMML4UnitImpl.DEFAULT_ROOT_PACKAGE+"."+javaModelId; packageNames.add(basePkgName); return packageNames; }
规则由
RuleUnitExecutor
类执行。RuleUnitExecutor
类将创建 KIE 会话并将所需的DataSource
对象添加到这些会话,然后基于RuleUnit
来执行规则,后者作为参数传递到run()
方法。calculatePossiblePackageNames
和getStartingRuleUnit
方法决定了传递给run()
方法的RuleUnit
类的完全限定名称。
为方便您的 PMML 模型执行,您还可以使用 Red Hat Process Automation Manager 支持的 PMML4ExecutionHelper
类。有关 PMML 帮助程序类的更多信息,请参阅 第 13.2.1 节 “PMML 执行帮助程序类”。
13.2.1. PMML 执行帮助程序类
Red Hat Process Automation Manager 提供了一个 PMML4ExecutionHelper
类,它可帮助创建 PMML 模型执行所需的 PMMLRequestData
类,并帮助使用 RuleUnitExecutor
类执行规则。
以下是在没有时间和 PMML4ExecutionHelper
类的情况下执行的 PMML 模型示例,作为比较:
在不使用 PMML4ExecutionHelper
的情况下执行 PMML 模型示例
public void executeModel(KieBase kbase, Map<String,Object> variables, String modelName, String correlationId, String modelPkgName) { RuleUnitExecutor executor = RuleUnitExecutor.create().bind(kbase); PMMLRequestData request = new PMMLRequestData(correlationId, modelName); PMML4Result resultHolder = new PMML4Result(correlationId); variables.entrySet().forEach( es -> { request.addRequestParam(es.getKey(), es.getValue()); }); DataSource<PMMLRequestData> requestData = executor.newDataSource("request"); DataSource<PMML4Result> resultData = executor.newDataSource("results"); DataSource<PMMLData> internalData = executor.newDataSource("pmmlData"); requestData.insert(request); resultData.insert(resultHolder); List<String> possiblePackageNames = calculatePossiblePackageNames(modelName, modelPkgName); Class<? extends RuleUnit> ruleUnitClass = getStartingRuleUnit("RuleUnitIndicator", (InternalKnowledgeBase)kbase, possiblePackageNames); if (ruleUnitClass != null) { executor.run(ruleUnitClass); if ( "OK".equals(resultHolder.getResultCode()) ) { // extract result variables here } } } protected Class<? extends RuleUnit> getStartingRuleUnit(String startingRule, InternalKnowledgeBase ikb, List<String> possiblePackages) { RuleUnitRegistry unitRegistry = ikb.getRuleUnitRegistry(); Map<String,InternalKnowledgePackage> pkgs = ikb.getPackagesMap(); RuleImpl ruleImpl = null; for (String pkgName: possiblePackages) { if (pkgs.containsKey(pkgName)) { InternalKnowledgePackage pkg = pkgs.get(pkgName); ruleImpl = pkg.getRule(startingRule); if (ruleImpl != null) { RuleUnitDescr descr = unitRegistry.getRuleUnitFor(ruleImpl).orElse(null); if (descr != null) { return descr.getRuleUnitClass(); } } } } return null; } protected List<String> calculatePossiblePackageNames(String modelId, String...knownPackageNames) { List<String> packageNames = new ArrayList<>(); String javaModelId = modelId.replaceAll("\\s",""); if (knownPackageNames != null && knownPackageNames.length > 0) { for (String knownPkgName: knownPackageNames) { packageNames.add(knownPkgName + "." + javaModelId); } } String basePkgName = PMML4UnitImpl.DEFAULT_ROOT_PACKAGE+"."+javaModelId; packageNames.add(basePkgName); return packageNames; }
使用 PMML4ExecutionHelper
进行 PMML 模型执行示例
public void executeModel(KieBase kbase, Map<String,Object> variables, String modelName, String modelPkgName, String correlationId) { PMML4ExecutionHelper helper = PMML4ExecutionHelperFactory.getExecutionHelper(modelName, kbase); helper.addPossiblePackageName(modelPkgName); PMMLRequestData request = new PMMLRequestData(correlationId, modelName); variables.entrySet().forEach(entry -> { request.addRequestParam(entry.getKey(), entry.getValue); }); PMML4Result resultHolder = helper.submitRequest(request); if ("OK".equals(resultHolder.getResultCode)) { // extract result variables here } }
当您使用 PMML4ExecutionHelper
时,您不需要像典型的 PMML 模型执行一样指定可能的软件包名称或 RuleUnit
类。
要构建 PMML4ExecutionHelper
类,请使用 PMML4ExecutionHelper
class 确定如何检索 PMML4ExecutionHelper
的实例。
以下是构建 PMML4ExecutionHelper
类类方法的 PMML4ExecutionHelper
类方法:
- pmML4ExecutionHelperFactory 方法,用于 KIE 基础中的 PMML 资产
当 PMML 资产已编译并从现有 KIE 基础中使用这些方法:
public static PMML4ExecutionHelper getExecutionHelper(String modelName, KieBase kbase) public static PMML4ExecutionHelper getExecutionHelper(String modelName, KieBase kbase, boolean includeMiningDataSources)
- pmML4ExecutionHelperFactory 方法用于项目类路径上的 PMML 资产
当 PMML 资产位于项目类路径上时,请使用以下方法。
classPath
参数是 PMML 文件的项目类路径位置:public static PMML4ExecutionHelper getExecutionHelper(String modelName, String classPath, KieBaseConfiguration kieBaseConf) public static PMML4ExecutionHelper getExecutionHelper(String modelName,String classPath, KieBaseConfiguration kieBaseConf, boolean includeMiningDataSources)
- PMML4ExecutionHelperFactory 方法用于字节阵列中的 PMML 资产
当 PMML 资产采用字节阵列的形式时,请使用以下方法:
public static PMML4ExecutionHelper getExecutionHelper(String modelName, byte[] content, KieBaseConfiguration kieBaseConf) public static PMML4ExecutionHelper getExecutionHelper(String modelName, byte[] content, KieBaseConfiguration kieBaseConf, boolean includeMiningDataSources)
- 资源中的 PMML4ExecutionHelper factory 方法,用于资源中的 PMML 资产
当 PMML 资产采用
org.kie.api.io.Resource
对象的形式时,请使用以下方法:public static PMML4ExecutionHelper getExecutionHelper(String modelName, Resource resource, KieBaseConfiguration kieBaseConf) public static PMML4ExecutionHelper getExecutionHelper(String modelName, Resource resource, KieBaseConfiguration kieBaseConf, boolean includeMiningDataSources)
classpath、byte 数组和资源 PMML4ExecutionHelperFactory
方法为生成的规则和 Java 类创建 KIE 容器。容器用作 RuleUnitExecutor
使用的 KIE 基础的源。容器没有保留。在 KIE 基本中已有 PMML4ExecutionHelperFactory
方法的 PMML4ExecutionHelperFactory 方法不会以这种方式创建 KIE 容器。