业务规则引擎
ZEN Engine是一个跨平台的开源业务规则引擎(BRE)。它使用Rust编写,并为NodeJS、Python和Go提供原生绑定。ZEN Engine允许从JSON文件加载和执行JSON决策模型(JDM)。

开源React编辑器可在我们的JDM编辑器仓库中获得。
使用
ZEN Engine被构建为可嵌入您的Rust、NodeJS、Python或Go应用程序的BRE。它从JSON内容解析JDM。获取JSON内容的方式由您决定,例如从文件系统、数据库或服务调用。
支持的平台
Zen Engine原生可用的平台列表:
- NodeJS - GitHub | 文档 | npmjs
- Python - GitHub | 文档 | pypi
- Go - GitHub | 文档
- Rust (核心) - GitHub | 文档 | crates.io
完整的**业务规则管理系统(BRMS)**解决方案:
Rust
[dependencies]
zen-engine = "0"
use serde_json::json;
use zen_engine::DecisionEngine;
use zen_engine::model::DecisionContent;
async fn evaluate() {
let decision_content: DecisionContent = serde_json::from_str(include_str!("jdm_graph.json")).unwrap();
let engine = DecisionEngine::default();
let decision = engine.create_decision(decision_content.into());
let result = decision.evaluate(&json!({ "input": 12 })).await;
}
更高级的用例请访问Rust文档。
JSON决策模型(JDM)
GoRules JDM(JSON决策模型)是一个设计用于简化决策模型表示和实现的建模框架。
理解GoRules JDM
GoRules JDM的核心围绕着将决策模型表示为存储在JSON格式中的互连图的概念。这些图捕捉了GoRules Zen-Engine中各种决策点、条件和结果之间的复杂关系。
图由节点和边组成,边充当信息从一个节点移动到另一个节点的路径,通常从左到右。
输入节点作为所有与上下文相关数据的入口,而输出节点产生决策过程的结果。数据的流动从输入节点到输出节点,穿过所有互连的中间节点。当数据流经这个网络时,它在每个节点都会进行评估,连接决定了数据在图中的传递方向。
要查看JDM图的实际效果,您可以使用带有内置模拟器的免费在线编辑器。
除了图的输入节点(请求)和输出节点(响应)外,还有5种主要节点类型:
- 决策表节点
- 开关节点
- 函数节点
- 表达式节点
- 决策节点
决策表节点
概述
表格提供了决策过程的结构化表示,允许开发人员和业务用户以清晰简洁的方式表达复杂的规则。

结构
决策表的核心是其模式,定义了输入和输出的结构。输入包含使用ZEN表达式语言的业务友好表达式,可以适应各种条件,如相等性、数值比较、布尔值、日期时间函数、数组函数等。模式的输出决定了决策表生成的结果形式。 输入和输出通过用户友好的界面表达,通常类似于电子表格。这便于轻松修改和添加规则,使业务用户能够参与决策逻辑而无需深入复杂的代码。
评估过程
决策表按照指定的命中策略,从上到下逐行评估。 单行通过输入列从左到右评估。每个输入列代表"AND"运算符。如果单元格为空,则该列被评估为真,与值无关。
如果一行中的单个单元格失败(由于错误或其他原因),则跳过该行。
命中策略
命中策略决定了基于匹配规则的结果计算方式。
评估的结果是:
- 一个对象,如果决策表的命中策略是
first
并且有规则匹配。结构由输出字段定义。带点(.)的限定字段名会导致嵌套对象。 null
/undefined
,如果在first
命中策略中没有规则匹配- 对象数组,如果决策表的命中策略是
collect
(每个匹配规则一个数组项),或者如果没有规则匹配则为空数组
输入
在评估规则或行时,输入列体现了AND
运算符。值通常由(限定)名称组成,如customer.country
或customer.age
。
输入有两种评估类型,一元
和表达式
。
一元评估
一元评估通常用于当我们想要单独比较来自传入上下文的单个字段时,例如customer.country
和cart.total
。当列在其模式中定义了field
时激活。
示例
对于输入:
{
"customer": {
"country": "US"
},
"cart": {
"total": 1500
}
}

此评估转化为
如果 customer.country == 'US' 且 cart.total > 1000 则 {"fees": {"percent": 2}}
否则如果 customer.country == 'US' 则 {"fees": {"flat": 30}}
否则如果 customer.country == 'CA' 或 customer.country == 'MX' 则 {"fees": {"flat": 50}}
否则 {"fees": {"flat": 150}}
列表显示了输入字段中一元测试的基本示例:
输入项 | 输入表达式 |
---|---|
"A" | 字段等于"A" |
"A", "B" | 字段为"A"或"B" |
36 | 数值等于36 |
< 36 | 小于36的值 |
> 36 | 大于36的值 |
[20..39] | 20到39之间的值(包括20和39) |
20,39 | 值为20或39 |
<20, >39 | 小于20或大于39的值 |
true | 布尔值true |
false | 布尔值false |
任何值,甚至null/undefined | |
null | 值为null或undefined |
注:完整列表请访问ZEN表达式语言。
表达式评估
当我们想在单个单元格内创建更复杂的评估逻辑时,使用表达式评估。它允许我们在同一个单元格内比较来自输入上下文的多个字段。
可以通过在列配置中提供空的选择器(字段)
来使用。
示例
对于输入:
{
"transaction": {
"country": "US",
"createdAt": "2023-11-20T19:00:25Z",
"amount": 10000
}
}

如果 time(transaction.createdAt) > time("17:00:00") 且 transaction.amount > 1000 则 {"status": "reject"}
否则 {"status": "approve"}
注:完整列表请访问ZEN表达式语言。
输出
输出列作为决策表在评估过程中满足条件时将生成的数据蓝图。
当决策表中的一行满足其指定条件时,输出列决定了将返回的信息的性质和结构。每个输出列代表一个不同的字段,这些字段的集合形成与验证行相关的输出或结果。这种机制允许决策表精确定义和控制数据输出。
示例

结果将是:
{
"flatProperty": "A",
"output": {
"nested": {
"property": "B"
},
"property": 36
}
}
开关节点(新)
GoRules JDM中的开关节点引入了决策模型的动态分支机制,使图能够根据条件发生分歧。
条件使用Zen表达式语言编写。
通过引入开关节点,决策模型变得更加灵活和上下文感知。这种能力在需要基于不同输入的多样化决策逻辑的场景中特别有价值。开关节点有效管理图内的分支,增强了GoRules JDM中决策模型的整体复杂性和现实性,使其成为构建智能和自适应系统的关键组件。
开关节点保留传入数据而不进行修改;它将整个上下文转发到输出分支。

命中策略
开关节点有两种命中策略选项,first
和collect
。
在首次命中策略的情况下,图表分支到第一个匹配条件,类似于表中观察到的行为。相反,在收集命中策略下,图表扩展到所有条件成立的分支,允许分支到多个路径。
注:如果同一条件有多个边,执行顺序不保证。
可用版本:
- Python 0.16.0
- NodeJS 0.13.0
- Rust 0.16.0
- Go 0.1.0
函数节点
函数节点是JavaScript片段,允许使用JavaScript快速轻松地解析、重新映射或以其他方式修改数据。节点的输入作为函数的参数提供。函数在捆绑到ZEN引擎中的QuickJS引擎之上执行。
函数超时设置为50毫秒。
const handler = (input, {dayjs, Big}) => {
return {
...input,
someField: 'hello'
};
};
有两个内置库:
表达式节点
表达式节点作为使用Zen表达式语言将输入对象转换为替代对象的工具。在指定输出属性时,每个属性需要单独的行。这些行由两个字段定义:
- 键 - 输出属性的限定名称
- 值 - 通过Zen表达式语言表达的值
注:表达式节点内的任何错误都会使图停止。

决策节点
"决策"节点旨在扩展决策模型的能力。其功能是在执行期间调用和重用其他决策模型。
通过结合"决策"节点,开发人员可以模块化决策逻辑,促进复杂系统中的可重用性和可维护性。
支持矩阵
架构 | Rust | NodeJS | Python | Go |
---|---|---|---|---|
linux-x64-gnu | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
linux-arm64-gnu | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
darwin-x64 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
darwin-arm64 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
win32-x64-msvc | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
我们目前不支持linux-musl。
贡献
JDM标准正在不断发展,由于有许多公司正在使用GoRules Zen-Engine和GoRules BRMS,我们需要对其开发和路线图保持严格控制。 因此,我们目前无法接受任何代码贡献,除了帮助编写文档和增加测试。