ITADN

[FEATURE] Rule-driven actions with provenance for the reasoning engine

#1095Opencxzg007 创建于 10 天前
C
cxzg007commented
## Problem Statement The reasoning engine models a `Rule` with a `handler: Optional[Callable]` field (`semantica/reasoning/reasoner.py:34`), but this field is **never invoked anywhere in the codebase** — a repo-wide search finds only its declaration. When a rule matches, `Reasoner.forward_chain()` and `ReteEngine.execute_matches()` only treat the rule's `conclusion` as a new derived fact string; they cannot trigger any *action* (writing back to the KG, retracting a fact, emitting an event, or calling an external tool). In other words, Semantica today is a *pure inference* engine, not a *production rule system*. There is no way to say "WHEN this pattern matches, THEN do X" where X is a side effect rather than just a new fact. This is a capability gap versus mature rule systems (Drools, CLIPS, pyknow) and limits Semantica's use in automated knowledge-graph maintenance / agentic workflows. Separately, `semantica/reasoning/reasoning_provenance.py` imports `from .reasoning_engine import ReasoningEngine`, but no `ReasoningEngine` class / `reasoning_engine.py` module exists — the lazy import hides a latent bug. ## Proposed Solution Introduce a **structured Action layer** driven by rule matches, plus optional **provenance tracking** for every action-induced change. **L1 — Action type system.** Define an `Action` abstraction executed when a rule fires, instead of a single opaque callback: - `AssertAction` — assert a new fact (optionally write back to `KnowledgeGraph` / `GraphStore`) - `RetractAction` — retract a fact (truth maintenance) - `CallAction` — call an external function/tool (wraps the existing `handler`) - `EmitEventAction` — emit an event for pipeline / agent subscribers Wire execution into `Reasoner.forward_chain()` and `ReteEngine.execute_matches()`: when a rule with actions fires, run its actions with the match bindings. **L2 — Provenance-aware actions.** When enabled, every fact asserted/retracted by an action records *which rule, which bindings, when, and at what confidence* via the existing `semantica.provenance` machinery, and integrates with the existing `ExplanationGenerator`. This yields **explainable, automated knowledge evolution** — answer "why did the graph change?" for rule-driven edits. (Also fixes the dangling `ReasoningEngine` import in `reasoning_provenance.py`.) ## Alternatives Considered - **Only wire the existing `handler` callback (L0).** Minimal, but leaves a bare callback with no structured semantics, no KG write-back, and no provenance — low differentiation. - **External post-processing of inference results.** Users manually inspect `InferenceResult`s and mutate the KG themselves. Works today but is ad hoc, untracked, and not reusable. ## Use Cases 1. **Automated KG maintenance**: WHEN `Person(?x) AND worksAt(?x, ?c)` THEN assert `Employee(?x)` and write it back to the graph store, with provenance. 2. **Constraint enforcement / repair**: on a SHACL / consistency violation, fire a rule whose action emits an event or asserts a correction (ties into the recent SHACL work). 3. **Agentic tool-calling**: WHEN a domain pattern matches THEN a `CallAction` invokes an external tool, letting the reasoner drive downstream workflows. ## Impact Assessment - **Who would benefit?** Users building automated / agentic KG pipelines, anyone needing explainable rule-driven graph edits. - **Priority**: (deferring to maintainers) - **Breaking Changes**: No — `actions` is additive; `handler` stays supported (wrapped as a `CallAction`). Rules without actions behave exactly as today. - **Dependencies**: Reuses existing `semantica.provenance` and `ExplanationGenerator`; optional KG write-back via existing `KnowledgeGraph` / `GraphStore`. ## Implementation Ideas ```python from semantica.reasoning import Reasoner, Rule, AssertAction reasoner = Reasoner(provenance=True) reasoner.add_rule(Rule( rule_id="r1", name="infer-employee", conditions=["Person(?x)", "worksAt(?x, ?c)"], conclusion="Employee(?x)", actions=[AssertAction("Employee(?x)", write_back=True)], )) reasoner.add_fact("Person(John)") reasoner.add_fact("worksAt(John, Acme)") reasoner.forward_chain() # fires r1 -> asserts Employee(John), records provenance ``` ## Additional Context - Related to the reasoning module (`Reasoner`, `ReteEngine`). - Latent bug: `reasoning_provenance.py` references a non-existent `ReasoningEngine` / `reasoning_engine.py`. - Similar features: Drools / CLIPS / pyknow production-rule engines. ## Contribution - [x] I'm willing to help implement this feature - [x] I can help with documentation - [x] I can help with testing
1 条评论