Presenting Arta — A Python Rules Engine
Make Rule Handling Simple
Arta is a new open source rules engine from #OSSbyMAIF.
What is it?
Arta is a python library (i.e., a python package) for developers and data scientists designed to simplify rules handling in python code.
By configuring sets of rules in one or more YAML files rather than if
/ else
in the source code, rules will gain clarity, and maintaining them will be child’s play.
With transparent and readable rules, collaboration will be improved. No need to read some code to check the rules anymore.
Origins
The idea of a simple rules engine came at MAIF during a code refactoring of our Melusine implementation.
Melusine is a document processing library which can be powered by machine learning models. When working on its code refactoring, the development team had to deal with many hard coded business rules. It could be things like:
“If my email is important and is not forwarded and without a thank you email, etc., set its priority to high.”
And so on…
Maintaining rules in the code is error-prone, it can be hard to check them and sometimes even tricky to find them. When using a rules engine, all rules are defined in the same place and follow a standard definition (i.e., same schema). No more business rules in the code and easy reading also leads to less regression bugs.
At this point, the team was looking for the absolute python rules engine package but couldn’t find the perfect fit: Arta was born.
Open Source
Why share Arta publicly? The idea came out quite naturally, maybe because open source philosophy shares some of MAIF values (i.e., common sharing, transparency). And it seemed to be a fair return from a team who was using some public packages (e.g., LangChain, Pydantic, FastAPI, pandas, etc.).
Sharing Arta follows the wish that it will help others within their own python projects.
A Simple Example
How to use it? One of Arta’s major goals is “simplicity”, as much as customization will allow. There are 3 implementation steps:
1. First, the hardest part, understand all the business rules of the concerned python application. Then, define them in a YAML file following Arta rule’s schema. Doing so will require building the different “condition expressions” (i.e., Boolean expressions) and identifying the triggered “actions”.
2. Second, implement the action functions in a python module. These functions can do anything: returning a filled dictionary, calling an API, writing in a database, etc.
3. Lastly, in your application code, instantiate the RulesEngine
class and call its instance method apply_rules()
by passing it the input data.
Here is a very (and intentionally) simple example. Use Arta to set a priority level on emails based on their properties and the following rules:
- High: email is important and not forwarded and not a thank you email.
- Medium: email is about contract or customer.
- Low: everything else.
Step 1
After installing Arta in your python virtual environment (e.g., pip install -U arta
), create the following YAML file (e.g., rules.yaml
):
---
rules:
default_rule_set:
priority:
HIGH:
simple_condition: input.important==True and input.forwarded==False and input.content_type!="thank_you"
action: set_priority
action_parameters:
code: 1
label: high
MEDIUM:
simple_condition: input.content_type=="contract" or input.content_type=="customer"
action: set_priority
action_parameters:
code: 2
label: medium
LOW:
simple_condition: null
action: set_priority
action_parameters:
code: 3
label: low
actions_source_modules:
- action
Step 2
Create a new python module with the action function implementation (e.g., action.py
):
from typing import Any
def set_priority(code: bool, label: str, **kwargs: Any) -> dict[str, Any]:
"""Return a dictionary containing the priority information."""
return {"code": code, "label": label}
Step 3
Create a main.py
module and apply the rules on the data set using Arta’s rules engine:
from typing import Any
from arta import RulesEngine
eng = RulesEngine(config_path=".")
data: dict[str, Any] = {
"id": 1,
"from": "someone@test.fr",
"to": "someone-else@test.eu",
"important": True,
"forwarded": True,
"content_type": "contract",
"subject": "New subscription",
"content": "Lorem ipsum...",
}
result: dict[str, Any] = eng.apply_rules(input_data=data)
print(result)
You are done! You have set and used your first Arta’s rules. Now print the result. You should get for this email:
{'priority': {'code': 2, 'label': 'medium'}}
N.B: If complex conditions are needed (i.e., doing math, calling a function to check things, etc.), you should use the standard conditions rather than simple conditions. Using standard conditions is the most powerful way of using Arta.
Next
The package core maintainers are currently from MAIF and will keep an eye on Arta as it is already used by productive apps.
Some GitHub issues have been opened for tracking new feature ideas but feel free to create new ones (even more for bugs) and of course, Arta is open to contributions (cf. repo’s contributing guidelines).
During the end of the year, we planned to publish new articles about Arta. As an example, we were thinking about writing on how we combined Arta and Melusine but also on how to create convenient custom conditions in order to simplify condition handling.
For more information: