Skip to main content

Lightweight explainable scoring and ranking engine for Python backends.

Project description

DecisionKit

CI PyPI version Python versions License: MIT

DecisionKit is a lightweight explainable scoring and ranking engine for Python backends.

Describe criteria, weights, constraints, penalties, and bonuses — in code or config — then get ranked alternatives with scores, human-readable explanations, and audit-ready output.

No machine learning. No database. No web UI. Core has zero runtime dependencies.

Project status

Beta (v0.3.0) — useful for real backend workflows; API aims to stay stable across minor releases. See CHANGELOG.md.

Installation

pip install decisionkit

Optional YAML support:

pip install "decisionkit[yaml]"

From source:

pip install -e ".[dev]"

Quick start

from decisionkit import DecisionModel, Criterion

model = DecisionModel(
    criteria=[
        Criterion("relevance", weight=0.5, direction="max"),
        Criterion("rating", weight=0.3, direction="max"),
        Criterion("workload", weight=0.2, direction="min"),
    ],
    method="weighted_sum",
    explain=True,
)

result = model.rank([
    {"id": "reviewer_1", "relevance": 0.92, "rating": 4.8, "workload": 7},
    {"id": "reviewer_2", "relevance": 0.81, "rating": 4.5, "workload": 2},
])

print(result.best.id)
print(result.explain())

Config-driven usage

from decisionkit import DecisionModel

config = {
    "method": "weighted_sum",
    "explain": True,
    "criteria": [
        {"name": "relevance", "weight": 0.5, "direction": "max"},
        {"name": "rating", "weight": 0.3, "direction": "max"},
        {"name": "workload", "weight": 0.2, "direction": "min"},
    ],
    "constraints": [
        {
            "name": "available_only",
            "field": "available",
            "operator": "eq",
            "value": True,
            "reason": "Reviewer must be available",
        }
    ],
    "penalties": [
        {
            "name": "high_workload_penalty",
            "field": "workload",
            "operator": "gt",
            "value": 5,
            "amount": 0.1,
        }
    ],
    "bonuses": [
        {
            "name": "exact_topic_bonus",
            "field": "topic_match",
            "operator": "gte",
            "value": 0.9,
            "amount": 0.05,
        }
    ],
}

model = DecisionModel.from_dict(config)
result = model.rank(
    [
        {
            "id": "reviewer_1",
            "relevance": 0.92,
            "rating": 4.8,
            "workload": 7,
            "available": True,
            "topic_match": 0.95,
        },
        {
            "id": "reviewer_2",
            "relevance": 0.81,
            "rating": 4.5,
            "workload": 2,
            "available": True,
            "topic_match": 0.8,
        },
    ],
    context={"max_workload": 5},
)

print(result.best.id)
print(result.to_audit_dict(include_hash=True)["audit_hash"])

JSON and optional YAML helpers:

model = DecisionModel.from_json(model.to_json())
# pip install "decisionkit[yaml]"
# model = DecisionModel.from_yaml(model.to_yaml())

Rules: constraints, penalties, bonuses

Operators: eq, ne, gt, gte, lt, lte, in, not_in, contains, between.

Context-aware rule:

{
    "name": "within_capacity",
    "field": "workload",
    "operator": "lte",
    "context": "max_workload",
}

Compound rule (all = AND, any = OR):

{
    "name": "eligible",
    "all": [
        {"field": "available", "operator": "eq", "value": True},
        {"field": "workload", "operator": "lte", "context": "max_workload"},
    ],
}

Audit export and hash

audit = result.to_audit_dict(
    decision_id="req-123",
    metadata={"tenant": "acme"},
    timestamp="2026-07-10T10:00:00Z",
    include_hash=True,
)
digest = result.audit_hash()  # sha256 of canonical decision payload

The digest covers method, model, context, inputs, exclusions, ranking, and best alternative. It excludes decision_id, metadata, and timestamp by default. Details: docs/audit.md.

FastAPI integration

from fastapi import FastAPI, HTTPException
from decisionkit import DecisionModel, ValidationError

app = FastAPI()

@app.post("/rank")
def rank(payload: dict):
    try:
        model = DecisionModel.from_dict(payload["model"])
        result = model.rank(
            payload["alternatives"],
            context=payload.get("context", {}),
        )
        return result.to_audit_dict(
            decision_id=payload.get("decision_id"),
            include_hash=True,
        )
    except ValidationError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc

See examples/fastapi_example.py.

Django service-layer integration

Keep DecisionKit in a service module; store config in settings/admin/DB:

from decisionkit import DecisionModel

def rank_reviewers(candidates: list[dict], model_config: dict) -> dict:
    model = DecisionModel.from_dict(model_config)
    result = model.rank(candidates, context={"max_workload": 5})
    return result.to_audit_dict(decision_id="editorial-assign", include_hash=True)

See examples/django_service_example.py.

How DecisionKit compares

Approach Fit
Ad-hoc if / spreadsheet scoring Fast to start, hard to explain, test, or reuse
Generic rule engines Great for branching logic; weaker at weighted ranking + score breakdowns
Academic MCDA toolkits Broad method coverage; often awkward for backend APIs and audits
DecisionKit Backend-friendly weighted ranking with rules, explanations, and audit hashes

DecisionKit is not trying to replace every MCDA method. It focuses on explainable scoring you can ship in Django/FastAPI services.

Supported methods

Method Key Notes
Weighted sum weighted_sum Min-max normalization; min criteria inverted
TOPSIS topsis Vector normalization + closeness to ideal

Examples

python examples/reviewer_selection.py
python examples/vendor_ranking.py
python examples/task_prioritization.py
python examples/risk_scoring.py
python examples/django_service_example.py

More: docs/examples.md

Documentation

Development

pip install -e ".[dev]"
python -m ruff check src tests examples
python -m mypy src
python -m pytest --cov=decisionkit --cov-report=term-missing

CI runs on Python 3.11 and 3.12 (see .github/workflows/ci.yml).

Release steps: RELEASE.md

Roadmap

v0.4.0

  • AHP method (optional, still backend-friendly)
  • Nested boolean rule trees (beyond flat all/any)
  • Signed / hashed decision record helpers for long-term storage

Later

  • ELECTRE / PROMETHEE (only if API stays simple)
  • decisionkit-django integration package
  • Optional CLI for batch ranking

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

decisionkit-0.3.0.tar.gz (30.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

decisionkit-0.3.0-py3-none-any.whl (25.9 kB view details)

Uploaded Python 3

File details

Details for the file decisionkit-0.3.0.tar.gz.

File metadata

  • Download URL: decisionkit-0.3.0.tar.gz
  • Upload date:
  • Size: 30.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for decisionkit-0.3.0.tar.gz
Algorithm Hash digest
SHA256 a8ac13e938d4d2d575f883f5e15f8638b6b1f4638dd3ea9c2db440bfb8e66fb6
MD5 6a119cebd8183c710ff7c7f86c18f1c3
BLAKE2b-256 988dcc1298bc8b754a948610f07e49df35d693a0c7f77dbf812cc58023b64803

See more details on using hashes here.

File details

Details for the file decisionkit-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: decisionkit-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 25.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for decisionkit-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d106f6147ff086e95f2908643f6d09b8b999678a48c48eb84e8d8fdd52d25265
MD5 48bb52987698752c3cec5b796aeedecf
BLAKE2b-256 9c679c0c73aa04e6df29cce87154b0d84bef5ecfeb29ae6efd1133565550eb87

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page