MoonBit production rule engine (Rete network): cross-fact working memory, incremental propagation, deterministic conflict resolution, auditable execution
规则集(条件 → 动作)
│ 编译
▼
Rete 网络
alpha 节点:单条件测试(共享子条件只算一次)
beta 节点:跨事实变量绑定 join(订单 + 客户 + 设备)
terminal 节点:规则完整匹配 → 待触发集合
│
▼
工作内存(Working Memory):insert / update / retract
│ 增量传播:事实变化只重算受影响分支
▼
冲突消解:salience(优先级)+ specificity(条件数)+ recency(新近度)
▼
动作执行 → 修改事实 → 连锁激活(match-select-act 循环,fire limit 上限)// OR:VIP 退款 或 大额订单,任一成立即触发
ReteRule::new("or_demo", "VIP退款或大额订单",
"(customer.level==VIP && ticket.type==refund) || order.amount>100000",
"action=manual_review", 10, "OR 组语义")
// NOT:下单且客户不在黑名单才自动放行(黑名单事实存在即拦截)
ReteRule::new("not_demo", "下单且非黑名单",
"order.status==placed && !customer.blacklist==true",
"action=auto_approve", 8, "否定语义")// 1. 定义规则:跨事实条件 + 变量绑定 + 动作
let rules : Array[ReteRule] = [
ReteRule::new("risk_manual", "大额新客风控",
"order.amount>100000 && customer.is_new==true && order.customer_id==customer.id",
"action=manual_review & order.status=hold",
10, "大额+新客强制人工"),
]
// 2. 编译网络 + 构造工作内存 + 插入事实(增量传播)
let engine = ReteEngine::new(rules)
let wm = WorkingMemory::new()
let cus = Fact::make("customer")
cus.set("is_new", "true"); cus.set("id", "c-1")
let ord = Fact::make("order")
ord.set("amount", "150000"); ord.set("customer_id", "c-1")
engine.insert(wm, cus); engine.insert(wm, ord)
// 3. 冲突消解 + 动作执行 + 连锁激活
let result = engine.fire_all(wm)
// result.fired → 触发规则序列(salience/specificity/recency/rule id 确定性排序)
// result.trace → 每条规则的触发轨迹(可审计)
// result.facts → 动作执行后的工作内存快照这段代码在独立第三方项目中实测通过(moon add mw1696803-hub/moonup → 编译 → 运行),输出 fired rules: 1 / order.status=hold。
| 维度 | moonrule(已有) | MoonUp Rete(本仓库) |
|---|---|---|
| 回答的问题 | 这份 JSON 合不合法 | 事实流变化时哪些规则触发、顺序、动作 |
| 状态 | 无状态,单条数据求值 | 有状态工作内存,多事实 |
| 匹配 | 单条表达式 → true/false | 跨事实变量绑定 join |
| 增量 | 每次全量求值 | 增量传播,只重算受影响分支 |
| 执行 | 只判断,不改数据 | 动作修改事实 → 连锁激活 |
| 能力 | rust-rule-engine (Rust, Grule 系) | Drools (JVM, ReteOO) | MoonUp Rete(本仓库) |
|---|---|---|---|
| 有状态工作内存 | ✅ | ✅ | ✅ |
| 跨事实变量绑定 join | ✅ | ✅ | ✅ |
| 增量传播(事实增删改) | ✅ RETE-UL 索引 | ✅ | ✅(全表过滤清理,未做 O(1) 索引) |
| AND / OR / NOT 条件 | ✅ GRL 表达式 | ✅ | ✅(OR 顶层组、NOT 全集扫描;括号嵌套路线图) |
| 冲突消解 | salience + 优先级 | salience + 复杂度 + 最近性 | salience → specificity → recency → rule id |
| 动作执行 + 连锁激活 | ✅ | ✅ | ✅(match-select-act,fire limit 100) |
| 事实撤回 | ✅ TMS 级联失效、多 justification | ✅ TMS | ✅ 三层内存清理、未执行激活失效;不做 TMS 多理由归因 |
| 后向链式推理 | ✅ | ✅ | ❌ 明确不做(只做前向数据驱动) |
| 并行 / 分布式执行 | ✅ 多线程、Redis 流式后端 | ✅ Kie Server | ❌ 单线程确定性执行(嵌入式定位) |
| DSL 表达力 | GRL,方法调用、自定义函数 | 完整 Drools 规则语言 | 受限 DSL:原子比较 + 组合 + 赋值/标签;不做表达式求值与方法调用 |
| 嵌入形态 | Rust crate,原生 | JVM 容器 | MoonBit 原生 + WASM,浏览器/native 双端可跑 |
| 规模定位 | 100–10,000+ 条规则,生产级 | 企业级 | 几十到几百条规则,嵌入式 MVP |
// 1. 实时风控:跨三类事实关联(beta join)
ReteRule::new("risk_hold", "跨事实风控",
"order.amount>100000 && customer.is_new==true && device.risk==high",
"action=manual_review & order.status=hold", 10, "跨事实强制人工")
// 2. 工单路由:多规则共享"客户等级==VIP"子条件(alpha 节点复用,一次测试)
ReteRule::new("vip_senior", "VIP工单进资深坐席",
"customer.vip==true && ticket.priority==high", "ticket.route=senior_agent", 10, "")
ReteRule::new("vip_sla", "VIP工单加急",
"customer.vip==true && ticket.priority==high", "ticket.sla=15min", 8, "共享 VIP 条件")
// 3. 库存联动:下单 → 扣库存 → 低于阈值补货 → 连锁激活
ReteRule::new("stock_apply", "下单扣库存",
"order.status==placed && product.stock>=order.qty",
"product.stock-=order.qty & order.status=fulfilled", 10, "")
ReteRule::new("stock_reorder", "低库存补货",
"product.stock<10", "product.stock+=100 & action=reorder_triggered", 8, "")
// 4. 复合条件:OR 组(VIP 退款或大额订单)与 NOT 否定(非黑名单才放行)
ReteRule::new("or_rule", "VIP退款或大额订单",
"(customer.level==VIP && ticket.type==refund) || order.amount>100000",
"action=manual_review", 10, "")
ReteRule::new("not_rule", "下单且非黑名单",
"order.status==placed && !customer.blacklist==true", "action=auto_approve", 8, "")
// 5. 规则配置化:规则集来自 JSON(parse_rules_json),引擎代码零修改
let rules = parse_rules_json(json_str) // Result[Array[ReteRule], String]
let engine = ReteEngine::new(rules!)let engine = ReteEngine::new([/* 上述规则 */])
let wm = WorkingMemory::new()
let dev = Fact::make("device"); dev.set("risk", "high")
let cus = Fact::make("customer"); cus.set("is_new", "true"); cus.set("id", "c-1001")
let ord = Fact::make("order"); ord.set("amount", "150000"); ord.set("customer_id", "c-1001")
engine.insert(wm, dev); engine.insert(wm, cus); engine.insert(wm, ord)
let result = engine.fire_all(wm) // result.fired / result.trace / result.facts| 能力 | 状态 | 说明 |
|---|---|---|
| Rete 网络编译(alpha/beta/terminal) | ✅ | 规则 DSL → 共享网络 |
| 共享子条件(alpha 节点复用) | ✅ | 多条规则共享条件只测一次 |
| 跨事实变量绑定 join | ✅ | 一条规则匹配多条事实 |
| 工作内存 insert/update/retract | ✅ | 事实生命周期管理 |
| 增量传播 | ✅ | 事实变化只重算受影响分支 |
| 冲突消解(salience/specificity/recency) | ✅ | 确定性排序 |
| 动作执行 + 连锁激活 | ✅ | match-select-act,fire limit |
| 触发轨迹记录 | ✅ | 命中规则、顺序、字段变更,可审计 |
| WASM 导出 | ✅ | 浏览器本地运行 |
| 线性匹配模式 | ✅ | 规则量小时简单路径 |
| \|\| OR 组(顶层,组可括号包裹) | ✅ | 任一组成立即匹配;每组独立编译网络、共享 terminal |
| ! 否定条件 | ✅ | 工作内存中不存在满足条件的事实才满足(扫描全集) |
| 括号嵌套(OR 内嵌于 AND,如 a && (b \|\| c)) | 🔜 路线图 | 需表达式树解析 |
| JSON/配置文件加载规则 | ✅ | parse_rules_json:规则集从 JSON 注入(id/condition/action 校验、带定位错误),引擎与业务解耦 |
| 大规模规则集性能基准 | ✅ | 见「性能基准」节(1000 规则 × 2000 事实实测) |
| 模块 | 能力 |
|---|---|
| rete | Rete 网络编译、工作内存、增量传播、冲突消解、动作执行、OR/NOT 复合条件 DSL、JSON 规则加载(本仓库核心) |
| engine | 线性匹配模式(规则量小时简单路径,保留) |
| evidence / guardrail / case | 可选决策组件(建立在引擎之上、与引擎解耦,按需引入) |
moon run main # 端到端 Demo(跨事实风控 + 工单路由 + 库存联动 + OR/NOT + AI Agent + JSON 加载)
moon test # 单元测试
moon build --release --target wasm-gc # WASM 构建{
"rules": [
{
"id": "risk_hold",
"condition": "order.amount>100000 && customer.is_new==true",
"action": "action=manual_review & order.status=hold",
"priority": 10
}
]
}let rules = parse_rules_json(json_str) // Result[Array[ReteRule], String],带定位错误
let engine = ReteEngine::new(rules!)moon add mw1696803-hub/moonupimport {
"mw1696803-hub/moonup/lib/rete",
}let rules : Array[@rete.ReteRule] = [
@rete.ReteRule::new(
"risk_hold", "跨事实风控",
"order.amount>100000 && customer.is_new==true && order.customer_id==customer.id",
"action=manual_review & order.status=hold",
10, "大额新客人工复核",
),
]
let eng = @rete.ReteEngine::new(rules)
let wm = @rete.WorkingMemory::new()
let cus = @rete.Fact::make("customer")
cus.set("is_new", "true"); cus.set("id", "c-1")
let ord = @rete.Fact::make("order")
ord.set("amount", "150000"); ord.set("customer_id", "c-1")
eng.insert(wm, cus); eng.insert(wm, ord)
let r = eng.fire_all(wm)
// 输出: fired rules: 1 / order.status=hold验证记录:2026-10-21 在独立项目 moonup-consume-test 中执行 moon add mw1696803-hub/moonup 成功下载 @0.1.0,按上述代码编译运行,输出 fired rules: 1 与 order.status=hold,跨事实规则正确触发。包本身就是"轮子":任何 MoonBit 项目一条命令接入。
// LLM 已从用户原话抽出结构化字段(生产中这是 JSON → Fact 解析)
let wm = WorkingMemory::new()
wm.insert(Fact::make("customer").set("vip", "true"))
wm.insert(Fact::make("ticket").set("priority", "high").set("type", "refund"))
let engine = ReteEngine::new([
Rule::new("vip_refund", "VIP退款", "customer.vip==true && ticket.type==refund",
"ticket.route=senior_agent", 10, ""),
])
let result = engine.fire_all(wm)
// result.fired → ["vip_refund"]
// result.trace → ["rule=vip_refund facts=[1,2] action=ticket.route=senior_agent"]
// 同一字段组合恒得同一结果,且可解释为什么触发——LLM 可能幻觉,规则执行不会。| 规则数 | 事实数 | 网络编译 (ms) | insert + fire (ms) | 触发数 |
|---|---|---|---|---|
| 50 | 100 | 1 | 16 | 50 |
| 200 | 500 | 1 | 104 | 200 |
| 500 | 1000 | 2 | 758 | 500 |
| 1000 | 2000 | 8 | 4915 | 1000 |
| 验收标准 | 状态 | 证据位置 |
|---|---|---|
| 01 MoonBit 为主要实现语言 | ✅ | 核心逻辑、规则执行与测试全部 MoonBit 实现 |
| 02 仓库公开,连续可追踪提交 | ✅ | 本仓库持续提交,CI 见 GitHub Actions |
| 03 README、可运行示例、必要测试 | ✅ | 本 README;moon run main;moon test |
| 04 本期实质新增 | ✅ | Rete 网络、工作内存、增量传播、冲突消解均为本期新增 |
| 05 开源合规:许可证与参考来源 | ✅ | MIT;Rete 算法与 Drools 设计思想参考见「原创 / 参考」 |
| 06 AI 可解释 | ✅ | 见「AI 使用说明」 |
| 07 发布到 mooncakes.io | ✅ | 已发布 mw1696803-hub/moonup@0.1.1(包页),moon add mw1696803-hub/moonup 可直接依赖 |
Install
Download zipMoonBit production rule engine (Rete network): cross-fact working memory, incremental propagation, deterministic conflict resolution, auditable execution