ZEN Engine 是一个跨平台、开源业务规则引擎 (BRE)。它是用 Rust 编写的,并提供NodeJS、Python和Go的本机绑定。 ZEN Engine 允许从 JSON 文件加载和执行 JSON 决策模型 (JDM)。
我们的JDM Editor存储库上提供了开源 React 编辑器。
安装
go get github.com/gorules/zen-go
用法
ZEN Engine 构建为可嵌入的 BRE,适用于您的Rust、NodeJS、Python或Go应用程序。它从 JSON 内容解析 JDM。您可以自行决定是否从文件系统、数据库或服务调用中获取 JSON 内容。
加载并执行规则
package main
import (
"fmt"
"os"
"path"
)
func readTestFile(key string) ([]byte, error) {
filePath := path.Join("test-data", key)
return os.ReadFile(filePath)
}
func main() {
engine := zen.NewEngine(zen.EngineConfig{Loader: readTestFile})
defer engine.Dispose() // Call to avoid leaks
output, err := engine.Evaluate("rule.json", map[string]any{})
if err != nil {
fmt.Println(err)
}
fmt.Println(output)
}
有关规则格式和高级用法的更多详细信息,请查看文档。
JSON 决策模型 (JDM)
GoRules JDM(JSON 决策模型)是一个建模框架,旨在简化决策模型的表示和实现。
了解 GoRules JDM
GoRules JDM 的核心围绕决策模型的概念,即以 JSON 格式存储的互连图。这些图表捕获了 GoRules Zen 引擎中各种决策点、条件和结果之间的复杂关系。
图是通过将节点与边连接起来而形成的,这些边就像将信息从一个节点移动到另一个节点(通常是从左到右)的路径。
输入节点充当与上下文相关的所有数据的入口,而输出节点则产生决策过程的结果。数据的传输遵循从输入节点到输出节点的路径,遍历其间所有互连的节点。当数据流经该网络时,它会在每个节点处进行评估,并且连接决定数据沿着图传递的位置。
要查看 JDM Graph 的实际效果,您可以使用带有内置模拟器的免费在线编辑器。
除了图输入节点(请求)和输出节点(响应)之外,还有 5 种主要节点类型:
- 决策表节点
- 切换节点
- 功能节点
- 表达节点
- 决策节点
决策表节点
概述
表格提供了决策过程的结构化表示,允许开发人员和业务用户以清晰简洁的方式表达复杂的规则。
结构
决策表的核心是它的模式,用输入和输出定义结构。输入包括使用 ZEN 表达式语言的业务友好表达式,适应一系列条件,例如相等、数字比较、布尔值、日期时间函数、数组函数等。该模式的输出规定了决策表生成的结果的形式。输入和输出通过用户友好的界面表示,通常类似于电子表格。这有助于轻松修改和添加规则,使业务用户能够为决策逻辑做出贡献,而无需深入研究复杂的代码。
评估流程
决策表从上到下逐行评估,遵循指定的命中策略。单行通过输入列从左到右进行评估。每个输入列代表AND运算符。如果单元格为空,则该列将被真实评估,与值无关。
如果行中的单个单元格失败(由于错误或其他原因),则跳过该行。
命中策略
命中策略根据匹配规则确定结果计算。
评估结果为:
- 如果决策表的命中策略first与规则匹配,则为对象。该结构由输出字段定义。内部带有点 (.) 的限定字段名称会导致嵌套对象。
- null/undefinedfirst如果命中策略中没有匹配的规则
- 如果决策表的命中策略是(collect每个匹配规则一个数组项),则为对象数组;如果没有规则匹配,则为空数组
输入
在规则或行的评估中,输入列体现了AND运算符。这些值通常由(限定)名称组成,例如customer.country或customer.age。
输入的评估有两种类型,Unary和Expression。
一元评估
当我们想要分别比较传入上下文中的单个字段时,通常使用一元求值,例如customer.country和cart.total。当列field在其模式中定义时,它被激活。
例子
对于输入:
{
"customer": {
"country": "US"
},
"cart": {
"total": 1500
}
}
这个评估转化为
IF customer.country == 'US' AND cart.total > 1000 THEN {"fees": {"percent": 2}}
ELSE IF customer.country == 'US' THEN {"fees": {"flat": 30}}
ELSE IF customer.country == 'CA' OR customer.country == 'MX' THEN {"fees": {"flat": 50}}
ELSE {"fees": {"flat": 150}}
表达评估
当我们想在单个单元格内创建更复杂的求值逻辑时,可以使用表达式求值。它允许我们比较同一单元格内传入上下文的多个字段。
可以通过提供空的内部列配置来使用它Selector (field)。
输出
输出列充当评估期间满足条件时决策表将生成的数据的蓝图。
当决策表中的一行满足其指定条件时,输出列确定将返回的信息的性质和结构。每个输出列代表一个不同的字段,这些字段的集合形成与已验证行关联的输出或结果。这种机制允许决策表精确定义和控制数据输出。
切换节点(新)
GoRules JDM 中的 Switch 节点向决策模型引入了动态分支机制,使图能够根据条件发散。
条件是用 Zen 表达式语言编写的。
通过合并 Switch 节点,决策模型变得更加灵活和上下文感知。在需要基于不同输入的不同决策逻辑的场景中,此功能特别有价值。 Switch 节点有效地管理图中的分支,增强 GoRules JDM 中决策模型的整体复杂性和现实性,使其成为构建智能和自适应系统的关键组件。
Switch节点保留传入的数据而不做任何修改;它将整个上下文转发到输出分支。
命中策略
切换节点有两个 HitPolicy 选项,first和collect。
在首次命中策略的上下文中,图分支到初始匹配条件,类似于在表中观察到的行为。相反,在收集命中策略下,该图扩展到条件成立的所有分支,从而允许分支到多个路径。
注意:如果同一条件有多个边,则不保证执行顺序。
函数节点
函数节点是 JavaScript 片段,允许使用 JavaScript 快速轻松地解析、重新映射或以其他方式修改数据。节点的输入作为函数的参数提供。函数在捆绑到 ZEN 引擎中的 QuickJS 引擎之上执行。
函数超时设置为 50ms。
const handler = (input, {dayjs, Big}) => {
return {
...input,
someField: 'hello'
};
};
有两个内置库:
- dayjs - 用于日期操作
- big.js - 用于任意精度的十进制算术。
表达节点
表达式节点用作使用 Zen 表达式语言将输入对象转换为替代对象的工具。指定输出属性时,每个属性都需要单独的行。这些行由两个字段定义:
-
Key - 输出属性的限定名称
-
价值------通过禅宗表达语言表达的价值
注意:表达式节点中的任何错误都会导致图表停止。
决策节点
"决策"节点旨在扩展决策模型的功能。其功能是在执行过程中调用和重用其他决策模型。
通过合并"决策"节点,开发人员可以模块化决策逻辑,从而提高复杂系统的可重用性和可维护性。