TVL Constraint Expressions (SDK Semantics)¶
Traigent compiles TVL constraints expressions into a safe subset of Python.
This applies to both:
- Legacy constraints (
constraints: [{id, type, rule/when/then, ...}]) - TVL 0.9 structural constraints (
constraints: { structural: [{expr|when/then}, ...], ... })
Namespaces¶
params: the candidate configuration (the current trial’s parameter values)metrics: evaluation metrics (may be empty/Nonefor purely structural checks)
Examples:
params.model == "gpt-4o"metrics.token_cost_usd <= 0.05
Operators and literals¶
- Equality: use
==(single=is not supported and will raise a validation error) - Comparisons:
<,<=,>,>=,!= - Membership:
in,not in - Booleans:
and,or,not - CEL-style aliases are accepted and translated before parsing:
&&→and||→or!x→not x(but!=remains!=)true/false/null→True/False/None
Functions¶
The evaluator exposes a small set of safe helpers:
len,min,max,sum,abs,any,allmath.<fn>via Python’smathmodule (for examplemath.log,math.sqrt)
Accessing keys (including dotted names)¶
params.<name> is attribute access over a dictionary. This works when <name> is a valid identifier key.
If your tuned-variable name contains dots or other non-identifier characters (for example retriever.k), use
subscript access:
params["retriever.k"] >= 3metrics["p95_latency_ms"] <= 1200
Nested access only works when the configuration is actually nested:
params.retriever.kworks only ifparams["retriever"]is a dict with keyk.
Guarding against missing values¶
Missing params.<name> / metrics.<name> values resolve to None. Guard explicitly when needed:
params.temperature is None or params.temperature <= 0.8
when/then constraints¶
Conditional constraints use implication semantics:
- Spec form:
when: A,then: B - Equivalent expression:
not (A) or (B)