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

如何在EDN文件中编写Clara Rules并访问修改会话事实?

在Clojure中用外部EDN编写Clara Rules的完整结构及会话事实操作

一、外部EDN编写Clara Rules的完整结构

Clara Rules支持将规则定义在外部EDN文件中,每个规则是一个包含核心字段的Map,完整结构说明如下:

  • :name:规则唯一标识(必填)
  • :lhs:规则左部(条件),由一组模式组成(必填)
    每个模式包含:
    • :type:匹配的事实类全限定名(必填)
    • :binding:可选,将匹配到的事实绑定到变量(如:binding :?user),供RHS引用
    • :constraints:约束条件列表,支持Clojure表达式,可引用绑定变量
  • :rhs:规则右部(动作),是Clojure表达式列表(必填),可使用clara.rules/insert!、clara.rules/retract!等API
  • :params:可选,规则参数集合,用于接收外部传入的值
  • :salience:可选,规则优先级,数值越高执行顺序越靠前

示例完整EDN规则:

{
  :name "update-user-criteria"
  :params #{:?default-id}
  :lhs [
    {:type rules.rules.User, :binding :?user, :constraints [(= (:user-id ?user) "userfact1")]}
    {:type rules.rules.UserCriteria, :binding :?criteria}
  ]
  :rhs [
    (let [new-id (:user-id ?user)
          updated-ids (conj (:ids ?criteria) new-id)]
      (clara.rules/retract! ?criteria)
      (clara.rules/insert! (rules.rules.UserCriteria. updated-ids)))
  ]
}

二、在EDN规则中绑定并访问会话现有事实

你之前无法绑定事实的核心原因是未在LHS模式中指定:binding字段,正确的绑定方法:

  1. 在LHS的目标事实模式中添加:binding :?变量名,将匹配到的事实绑定到变量
  2. 在RHS中直接通过该变量引用事实,读取其属性

修正后的rules.edn示例:

{
  :name "criteria-1", 
  :lhs [
    {:type rules.rules.User, :constraints []} ; 补充你的实际约束条件
    {:type rules.rules.UserCriteria, :binding :?criteria}
  ]
  :rhs [
    (let [id (:user-id ?user)
          updated-criteria (conj (:ids ?criteria) id)]
      (clara.rules/retract! ?criteria)
      (clara.rules/insert! (rules.rules.UserCriteria. updated-criteria)))
  ]
}

注意:EDN中的类名必须是运行时可加载的全限定名,比如你的User对应rules.rules.User,避免拼写错误(如你之前写的rules.rules.Users是错误的)。

三、修改会话中现有事实的正确方式

Clara Rules中的事实是不可变的,无法直接修改,标准流程是:

  1. 在LHS中匹配并绑定要修改的旧事实
  2. 在RHS中用clara.rules/retract!移除旧事实
  3. 基于旧事实的属性创建新实例,用clara.rules/insert!插入会话

四、从会话中获取事实的最优方法

你当前使用的(first (first (:fact->explanation session-data)))方式不够直观,推荐两种更简洁的方法:

方法1:使用Clara查询

定义查询(可写在EDN或代码中),通过clara.rules.api/query获取指定事实:

; 定义查询(可放入EDN规则文件)
(def get-user-criteria
  '{:name "get-user-criteria"
    :params []
    :lhs [{:type rules.rules.UserCriteria, :binding :?c}]
    :rhs [(clara.rules/return ?c)]})

; 执行查询获取事实
(let [session (-> (mk-session (conj (fetch-rules-from-file) get-user-criteria))
                  (insert (->User "userfact1" "Alice")
                          (->UserCriteria [100]))
                  (fire-rules))
      criteria (first (clara.rules.api/query session :get-user-criteria))]
  criteria)

方法2:使用clara.rules.api/get-facts函数

直接获取会话中指定类型的所有事实:

(let [session (-> (mk-session (fetch-rules-from-file))
                  (insert (->User "userfact1" "Alice")
                          (->UserCriteria [100]))
                  (fire-rules))
      criteria-list (clara.rules.api/get-facts session rules.rules.UserCriteria)]
  (first criteria-list)) ; 获取第一个UserCriteria实例

补充:代码修正点

  1. 简化规则读取函数:如果rules.edn是单个规则Map,用vector包装;如果是规则列表,直接读取即可:
; 单规则文件
(defn fetch-rules-from-file []
  (vector (edn/read-string (slurp "rules.edn"))))

; 多规则列表文件
(defn fetch-rules-from-file []
  (edn/read-string (slurp "rules.edn")))
  1. 确保rules.edn中的:type字段与代码中定义的defrecord全限定名完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 12:19:57