Rules
Let the knowledge graph derive facts for you.
A rule tells the knowledge graph how to derive new facts from existing ones. Instead of computing a total, a status or a score in your app, you describe it once as a rule and the graph keeps the result up to date as the data changes.
What a rule looks like
Rules are written in Datalog. A rule has a head (what to derive) and a body (when to derive it):
:cpc[?ad, ?cpc] :-
:Ad[?ad],
:spend[?ad, ?spend],
:clicks[?ad, ?clicks],
FILTER(?clicks > 0),
BIND(?spend / ?clicks AS ?cpc) .
This derives a cost per click for every ad that has spend and at least one click. The : prefix is your
datastore’s own vocabulary: manta-codegen writes it and the other prefixes to namespaces.ts, so you can look up
the full names there.
Derived facts are inferred: you read them like any other property, but they are never stored as data you have to maintain. When the inputs change, the derived facts change with them.
Adding rules
Changing rules is a two-step process, so nothing goes live by accident:
- Stage the change: add, change or remove a rule.
- Commit the staged rules. If RDFox can’t load the rule set, the commit is rolled back and returns
success: false. Run Validate first to catch syntax and stratification errors.
You can do this in two ways:
- Ask the agent. In the Manta chat, describe the rule you want. The agent writes it, stages it and shows you the change before committing.
- From your app.
@manta-eu/clienthas hooks for the same steps, includinguseStageRuleOperationMutation,useCommitStagedRulesMutationanduseClearStagedRulesMutation.
From a backend
The same steps are GraphQL mutations, so a backend can manage rules without the chat. See calling Manta from a backend for the endpoint and authentication.
1. Stage a change. operation is ADD, CHANGE or REMOVE, and ruleIri names the rule to change or remove:
mutation StageRule($input: StageRuleOperationInput!) {
stageRuleOperation(input: $input) {
success
ruleIri
operation
error
}
}
{
"input": {
"humanIntent": "Derive the cost per click of every ad",
"operation": "ADD",
"newRule": ":cpc[?ad, ?cpc] :- :Ad[?ad], :spend[?ad, ?spend], :clicks[?ad, ?clicks], FILTER(?clicks > 0), BIND(?spend / ?clicks AS ?cpc) ."
}
}
2. Validate the staged rules:
mutation {
validateStagedRules {
isValid
isStratifiable
syntaxErrors
nonStratifiableComponents
error
}
}
3. Commit them. Run it with dryRun: true first to see what would change:
mutation {
commitStagedRules(dryRun: false) {
success
rulesAdded
rulesUpdated
rulesDeleted
error
}
}
clearStagedRules discards staged changes. Pass ruleIris to discard a subset. validateStagedRules and
commitStagedRules take the same optional ruleIris. dryRun on commit defaults to false. The rules query
lists the rules in the datastore.
A rule that feeds back into itself through an aggregate or a negation cannot be evaluated. Validate reports it before commit.
Reuse facts other rules already derive instead of recomputing them, and be careful with rules that create new entities from their own output, since they can grow without end.