https://github.com/sourdoughcat/decision-engine
https://github.com/sourdoughcat/decision-engine
Last synced: 6 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/sourdoughcat/decision-engine
- Owner: SourdoughCat
- Created: 2023-09-09T12:19:15.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2023-09-10T10:22:21.000Z (almost 2 years ago)
- Last Synced: 2024-12-09T00:09:44.522Z (6 months ago)
- Language: Rust
- Size: 40 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Decision Engine
> :warning: this is alpha software and there are known bugs due to decision engine trying to dynamically evaluate things
A configuration driven decision engine written in Rust with Python bindings.
Python usage:
```py
import pandas as pd
from decision_engine.engine import DecisionEnginedecision_engine = DecisionEngine.model_validate(
{
"config": {
"key": "action",
"default_action": "high",
"rules": [
["score < 80", "low"],
["score <= 99", "medium"],
["score > 99", "high"],
],
},
}
)dataframe = pd.DataFrame({"score": [0.0, 85, 100]})
print(decision_engine.transform(dataframe))
# action
# 0 low
# 1 medium
# 2 high
```This also works with multiple conditions, whereby it takes the first one which is "true".
```py
import pandas as pd
from decision_engine.engine import DecisionEnginedecision_engine = DecisionEngine.model_validate(
{
"config": {
"key": "action",
"default_action": "high",
"rules": [
["override", "'override'"],
["not override and score < 100", "low"],
["score >= 100", "high"],
],
},
}
)dataframe = pd.DataFrame({"score": [0.0, 85, 100], "override": [True, False, False]})
print(decision_engine.transform(dataframe))
# action
# 0 'override'
# 1 low
# 2 high
```The outputs can also target a variable, and does not need to be a constant:
```py
import pandas as pd
from decision_engine.engine import DecisionEnginedecision_engine = DecisionEngine.model_validate(
{
"config": {
"key": "action",
"default_action": "high",
"rules": [
["override", "model_a"],
["not override and score < 100", "model_b"],
["score >= 100", "model_a"],
],
},
}
)dataframe = pd.DataFrame(
{
"score": [0.0, 85, 100],
"override": [True, False, False],
"model_a": [1.0, 2.0, 3.0],
"model_b": [4.0, 5.0, 6.0],
}
)
print(decision_engine.transform(dataframe))
# action
# 0 1.0
# 1 5.0
# 2 3.0
```## Developer Notes
From a development perspective the Rust and Python bindings are kept in two separate crates:
* `decision_engine`
* `decision_engine_py`This allows the Rust crate to remain "pure" and the Python bindings to be developed separately.
The decision engine is configuration driven which can easily be exported in `toml` or `json` format and parsed in Rust or Python.
For example, in Rust, we may define a decision engine as follows:
```toml
key = "action"[rule_config]
default_action = "'high'"
rules = [
["score <= 80", "low"],
["score <=100", "medium"],
["score > 100", "high"],
]
```Which would have the corresponding `json` setup as
```json
{
"config": {
"key": "action",
"default_action": "high",
"rules": [
[
"score < 80",
"low"
],
[
"score <= 99",
"medium"
],
[
"score > 99",
"high"
]
]
}
}
```### Tests and Formatting
We use `just` for running tests and auto formatters. This can be installed via `brew install just`
```sh
$ just test
$ just format
$ just lint
```