You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Experta规则引擎中提取含具体Lambda条件的规则

解决Experta规则引擎中Lambda条件的可读化提取问题

问题

使用Experta库构建规则引擎时,提取规则后发现Lambda函数仅显示内存地址(如Iris(petal_width=P(<function IrisExpert.<lambda> at 0x7fe3fd4788c8>,))),无法直观看到具体的判断条件,需要提取出包含Lambda核心逻辑的规则格式(如Iris(petal_width=P(x > 5)))。

解决方案

Experta的P(Predicate)类默认的__repr__方法不会解析Lambda的源码内容,因此需要自定义一个支持可读输出的P子类,利用inspect模块获取Lambda函数的源码文本,并重写__repr__方法来展示核心判断逻辑。

修改后的完整代码

from experta import *
import pydot
import inspect

# 自定义支持可读输出的Predicate子类
class ReadableP(P):
    def __repr__(self):
        if callable(self.predicate):
            try:
                # 获取lambda函数的源码文本
                source = inspect.getsource(self.predicate).strip()
                # 提取lambda的核心判断表达式
                if source.startswith('lambda'):
                    expr = source.split(':', 1)[1].strip()
                    return f"P({expr})"
                return f"P({source})"
            except (TypeError, OSError):
                # 无法获取源码时使用默认输出
                return super().__repr__()
        return super().__repr__()

class Iris(Fact):
    """IRIS"""
    sepal_length = Field(float)
    sepal_width = Field(float)
    petal_length = Field(float)
    petal_width = Field(float)

class Species(Fact):
    """Species characteristics"""
    pass


class IrisExpert(KnowledgeEngine):

    def __init__(self):
        super().__init__()
        self.status = None

    # 使用自定义的ReadableP替代原P
    @Rule(Iris(sepal_length=ReadableP(lambda x: x > 5), sepal_width=ReadableP(lambda x: x < 3)))
    def rule1(self):
        self.status = 'Iris Setosa'
        return self.declare(Species(flower='Iris Setosa'))

    @Rule(AND(
        Iris(sepal_length=ReadableP(lambda x: x > 5.5)),
        Iris(sepal_width=ReadableP(lambda x: x > 2.5))
    ))
    def rule2(self):
        self.status = 'Iris Versicolor'
        return self.declare(Species(flower='Iris Versicolor'))

    @Rule(AND(
        Iris(petal_length=ReadableP(lambda x: x > 4.8)),
        Iris(petal_width=ReadableP(lambda x: x > 1.8))
    ))
    def rule3(self):
        self.status = 'Iris Virginica'
        return self.declare(Species(flower='Iris Virginica'))

def execute_fuc(key):
    if key == 'rule1':
        print('executing rule-1')
        engine.rule1()
    elif key == 'rule2':
        print('executing rule-2')
        engine.rule2()
    else:
        print('executing rule-3')
        engine.rule3()


# 创建规则引擎实例
engine = IrisExpert()
engine.reset()
# 创建Pydot图
graph = pydot.Dot(graph_type='digraph', comment='IRIS Expert Rules')
# 为每个规则添加节点
for rule_instance in engine.get_rules():
    quality = rule_instance()
    # 现在repr会显示可读的Lambda条件
    qual_node = pydot.Node(repr(quality))
    graph.add_node(qual_node)
    for rule in rule_instance:
        print('rule_format: ', repr(rule))

说明

  1. ReadableP类:继承自Experta的P类,重写__repr__方法,通过inspect.getsource获取Lambda函数的源码,提取出:后的核心判断表达式,输出为P(表达式)的格式。
  2. 异常处理:当Lambda函数无法获取源码(如在交互式环境中定义)时,会 fallback 到原P类的默认输出,避免报错。
  3. 规则替换:只需将原规则中的P替换为ReadableP,即可实现规则提取时的可读化输出。

内容的提问来源于stack exchange,提问作者merkle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 23:42:09