第 11 章 PMML 模型执行


您可以使用 Business Central (Menu Projects Projects Import Asset)将 PMML 文件导入到 Red Hat Process Automation Manager 项目中,或将 PMML 文件打包为没有 Business Central 的项目知识 JAR (KJAR)文件的一部分。在 Red Hat Process Automation Manager 项目中实现了 PMML 文件后,您可以通过在 Java 应用程序中直接嵌入 PMML 调用或向配置的 KIE 服务器发送 ApplyPmmlModelCommand 命令来执行基于 PMML 的决策服务。

有关使用项目打包和部署方法包括 PMML 资产的更多信息,请参阅 打包和部署 Red Hat Process Automation Manager 项目

注意

您还可以在 Business Central 中包含 PMML 模型作为 Decision Model 和 Notation (DMN)服务的一部分。当您在 DMN 文件中包含 PMML 模型时,您可以调用 PMML 模型作为 DMN 决策节点或业务知识模型节点的方框函数表达式。有关在 DMN 服务中包含 PMML 模型的更多信息,请参阅使用 DMN 模型设计决策服务

11.1. 直接嵌入 Java 应用程序中的 PMML 调用

当知识资产直接嵌入到调用程序中或物理拉取时,KIE 容器是本地的,或使用 KJAR 的 Maven 依赖项进行物理拉取。通常,如果代码版本和 PMML 定义版本之间有紧密关系,您通常直接将知识资产嵌入到项目中。在有意更新并重新部署应用程序后,对决定所做的任何更改都会生效。这种方法的一个优点是,正确的操作不依赖于任何外部依赖项到运行时,这可能是锁定环境的限制。

使用 Maven 依赖项可以进一步的灵活性,因为决策的特定版本可以动态更改(例如,使用系统属性),它可以定期扫描更新和自动更新。这引入了对服务的部署时间的外部依赖项,但在本地执行决策,从而减少在运行时对外部服务的依赖。

先决�件

�程

  1. 在客户端应用程序中,将以下依赖项添加到 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>
    Copy to Clipboard Toggle word wrap

    & lt;version > 是项目中当前使用的 Red Hat Process Automation Manager 的 Maven 工件版本(如 7.44.0.Final-redhat-00006)。

    注意

    考虑将 Red Hat Business Automation Manager (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.9.1.redhat-00003</version>
      <scope>import</scope>
      <type>pom</type>
    </dependency>
    Copy to Clipboard Toggle word wrap

    有关 Red Hat Business Automation BOM 的更多信息,请参阅 RHPAM 产品和 maven 库版本之间的映射是什么?

  2. classpathReleaseId 创建 KIE 容器:

    KieServices kieServices = KieServices.Factory.get();
    
    ReleaseId releaseId = kieServices.newReleaseId( "org.acme", "my-kjar", "1.0.0" );
    KieContainer kieContainer = kieServices.newKieContainer( releaseId );
    Copy to Clipboard Toggle word wrap

    其它选项:

    KieServices kieServices = KieServices.Factory.get();
    
    KieContainer kieContainer = kieServices.getKieClasspathContainer();
    Copy to Clipboard Toggle word wrap
  3. 创建 PMMLRequestData 类实例,它将 PMML 模型应用到一组数据:

    public class PMMLRequestData {
        private String correlationId; 
    1
    
        private String modelName; 
    2
    
        private String source; 
    3
    
        private List<ParameterInfo<?>> requestParams; 
    4
    
        ...
    }
    Copy to Clipboard Toggle word wrap
    1
    标识与特定请求或结果关联的数据
    2
    应该应用到请求数据的模型名称
    3
    由内部生成的 PMMLRequestData 对象用来识别所生成的请求的片段
    4
    发送输入数据点的默认机制
  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
    
        ...
    }
    Copy to Clipboard Toggle word wrap
    1
    当模型类型是 MiningModel 时使用。segmentationId 用于区分多个分段。
    2
    segmentationId 一起使用,以识别生成结果的片段。
    3
    用于维护片段的顺序。
    4
    用于确定模型是否已成功应用,其中 OK 表示成功。
    5
    包含结果变量的名称及其关联的值。

    除了正常的 getter 方法外,pmML4Result 类还支持以下方法直接检索结果变量的值:

    public <T> Optional<T> getResultValue(String objName, String objField, Class<T> clazz, Object...params)
    
    public Object getResultValue(String objName, String objField, Object...params)
    Copy to Clipboard Toggle word wrap
  5. 创建 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
    
        ...
    }
    Copy to Clipboard Toggle word wrap
    1
    处理许多不同类型的参数类
    2
    期望作为模型输入的变量名称
    3
    变量的实际类型的类
    4
    变量的实际值
  6. 根据您创建的所需的 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;
    }
    Copy to Clipboard Toggle word wrap

    规则由 RuleUnitExecutor 类执行。RuleUnitExecutor 类创建 KIE 会话,并将所需的 DataSource 对象添加到这些会话中,然后根据作为参数传递给 run () 方法的 RuleUnit 执行规则。calculatePossiblePackageNamesgetStartingRuleUnit 方法决定传递给 run () 方法的 RuleUnit 类的完全限定名称。

为便于您的 PMML 模型执行,您还可以使用 Red Hat Process Automation Manager 支持的 PMML4ExecutionHelper 类。有关 PMML 帮助程序类的详情,请参考 第 11.1.1 节 “pmML 执行帮助程序类”

11.1.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;
}
Copy to Clipboard Toggle word wrap

使用 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
   }
}
Copy to Clipboard Toggle word wrap

当您使用 PMML4ExecutionHelper 时,您不需要指定可能的软件包名称或 RuleUnit 类,如您在典型的 PMML 模型执行中一样。

要构建 PMML4ExecutionHelper 类,您可以使用 PMML4ExecutionHelperFactory 类来确定如何检索 PMML4ExecutionHelper 的实例。

以下是用于构建 PMML4ExecutionHelper 类的可用的 PMML4ExecutionHelperFactory 类方法:

pmML4ExecutionHelperFactory 方法 KIE 基础中的 PMML 资产

当 PMML 资产已编译并从现有 KIE 基础中使用时,使用这些方法:

public static PMML4ExecutionHelper getExecutionHelper(String modelName, KieBase kbase)

public static PMML4ExecutionHelper getExecutionHelper(String modelName, KieBase kbase, boolean includeMiningDataSources)
Copy to Clipboard Toggle word wrap
PMML4ExecutionHelperFactory 方法在项目 classpath 上 PMML 资产

当 PMML 资产位于项目 classpath 时使用这些方法。classPath 参数是 PMML 文件的项目类路径位置:

public static PMML4ExecutionHelper getExecutionHelper(String modelName,  String classPath, KieBaseConfiguration kieBaseConf)

public static PMML4ExecutionHelper getExecutionHelper(String modelName,String classPath, KieBaseConfiguration kieBaseConf, boolean includeMiningDataSources)
Copy to Clipboard Toggle word wrap
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)
Copy to Clipboard Toggle word wrap
PMML4ExecutionHelperFactory 方法在资源中 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)
Copy to Clipboard Toggle word wrap
注意

classpath、bytes 数组和资源 PMML4ExecutionHelperFactory 方法为生成的规则和 Java 类创建一个 KIE 容器。容器用作 RuleUnitExecutor 使用的 KIE 基础的来源。容器不是持久性的。已在 KIE 基础中的 PMML 资产的 PMML4ExecutionHelperFactory 方法不会以这种方式创建 KIE 容器。

返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat