Python library for aligning structured objects (dict, list, primitives) and scoring similarity in [0, 1], with optional human-readable reasoning.
This is a cleaned-up, standalone version of the Object Aligner originally developed as part of the PromptOpt prompt optimization framework. The original implementation can be found in the first commit of PromptOpt (Dec 20, 2024).
uv add object-alignerOr:
pip install object-alignerfrom object_aligner import ObjectAligner
schema = {"type": "string", "score": "jaro"}
aligner = ObjectAligner(schema)
result = aligner.metric("hello", "hallo")
print(result) # {"score": ...}
result_with_reasoning = aligner.metric("hello", "hallo", generate_reasoning=True)
print(result_with_reasoning["score"])
print(result_with_reasoning["reasoning"])Built-in string metrics include exact, jaro, jaro_winkler, levenshtein, damerau_levenshtein, osa, indel, and lcsseq.
Schemas stay declarative: put the metric name in score, and pass the implementation through custom_metrics when you construct the aligner.
from object_aligner import ObjectAligner
def semantic_toy(gold: str, pred: str) -> float:
return 0.95 if gold.lower()[0] == pred.lower()[0] else 0.2
schema = {"type": "string", "score": "semantic_toy", "threshold": 0.5}
aligner = ObjectAligner(
schema,
custom_metrics={"string": {"semantic_toy": semantic_toy}},
)
print(aligner.metric("cat", "car"))
print(aligner.metric("cat", "dog"))Numeric schemas support the same mechanism:
def closish(gold: float, pred: float) -> float:
return 0.8 if abs(gold - pred) <= 2 else 0.1
aligner = ObjectAligner(
{"type": "number", "score": "closish"},
custom_metrics={"number": {"closish": closish}},
)For integer schemas, custom metrics first look in the integer registry and then fall back to the number registry.
ObjectAligner takes the schema plus optional keyword arguments such as custom_metrics and generate_reasoning:
aligner = ObjectAligner(schema)
aligner = ObjectAligner(schema, custom_metrics={"string": {...}})The older ObjectAligner("name", schema) form and get_name() are no longer supported.
Install dependencies:
uv syncRun the test suite:
uv run pytestThe repository includes a comprehensive pytest suite under tests/ covering primitives, lists, dicts, nesting, API behavior, regressions from the docs, and edge cases.
See docs/index.md for the full guide.