Skip to content
Talk to our solutions team

Values

Every directional read, cell read and pattern read on a document returns a Value. It is either a hit or a miss, it knows why it missed, and it carries the provenance of the hit. Documents reach rules through kis rules only today; see bbox.

This is the document read Value. Facts read with in.Value and out.Value return the engine’s own value type, listed under in.Value.

out.Set("loanAmount", bbox.Doc().Right("Loan Amount").Currency());
// read coercion

Whether a value was extracted.

rule LoanAmountPresent "the amount must be readable" salience 20 {
when
bbox.Doc().Right("Loan Amount").Missing()
then
findings.Critical("LoanAmountPresent", "extraction",
strings.Sprintf("Loan amount not found: %s",
bbox.Doc().Right("Loan Amount").Reason()));
}

Explains a miss: which stage failed, rather than an empty string that could mean any of four things, label not found, label found but nothing beside it, value found but the coercion rejected it, or scope excluded it.

This is the first thing to put in a finding when an extraction fails, and the first thing to log when a rule silently produces nothing.

Renders the provenance of a hit: what text matched as the label, on which page, at what distance.

Reason explains a failure; Why explains a success. When a rule extracted the wrong value, matched the label in the footer rather than the body, Why is what tells you.

rule TraceAmountRead "record where the amount came from" salience 5 {
when
bbox.Doc().Right("Loan Amount").Found()
then
log.Debug("loan amount provenance",
"why", bbox.Doc().Right("Loan Amount").Why());
}

The extracted text, or "".

The value as a number, or 0.

Commas and a leading $ are stripped before parsing, so a bare "$1,234" reads as 1234 rather than as zero. Anything else around the number still gives 0: coerce first with Number() or Currency() when the value embeds a number in other text.

Each returns another Value, so they compose with Found(), Or() and Str().

Strips the $ sign and thousands separators, leaving a bare number. Accounting negatives keep their sign: (1,234.56) and 1,234.56- both become -1234.56. The earliest amount in the text wins.

One call in place of a hand-escaped regular expression.

rule CaptureLoanAmount "the amount, as a bare number" {
when
bbox.Doc().Right("Loan Amount").Found()
then
out.Set("loanAmount", bbox.Doc().Right("Loan Amount").Currency());
}

Extracts the first number in the value.

Extracts a percentage as a bare number.

A %-suffixed number is preferred wherever it sits in the value; only when the value contains no % does the first bare number win. That ordering matters on a line like "Rate 6.125% (APR 6.310%)".

Normalises to YYYY-MM-DD, reading 2006-01-02, 01/02/2006, 1/2/2006, 01-02-2006, 1-2-2006, January 2, 2006, Jan 2, 2006, 2 January 2006 and 01/02/06 (month first).

A value that does not parse is a miss, not a zero date. There is no "0001-01-01" sentinel to compare against: ask Found().

Normalises an affirmative or negative to "Yes" or "No": yes, y, true, x and checked are "Yes"; no, n, false and unchecked are "No"; anything else is a miss.

Single-letter forms count: a form’s answer column is routinely a lone Y or N. A trailing . or : that OCR glued to the answer is ignored.

Title-cases the value.

Trims the value. Present for symmetry, reads already trim, so a chain can be written uniformly.

Keeps only the first substring matching the pattern.

ParameterTypeMeaning
patternstringA regular expression

The last resort, kept so the coercion set above can stay closed. Reaching for it repeatedly is a signal that a coercion is missing, worth reporting rather than working around.

A coercion that leaves nothing, a Number() on text with no digits, is a miss whose reason says so.

Substitutes a fallback when the read missed.

ParameterTypeMeaning
fallbackstringThe value to use instead

The result is found, but it carries no confidence, because it was supplied rather than extracted. That distinction survives into the output, so a downstream consumer can still tell a default from a reading.

rule PropertyTypeWithDefault "unstated property type is single family" {
when
in.Has("application")
then
out.Set("propertyType",
bbox.Doc().Right("Property Type").Or("Single Family"));
}

Use it where the absence has a defined meaning. Where absence is a problem, raise a finding instead, a default quietly papers over a document you could not read.

The computed extraction confidence, from 0 to 1.

A real score, not a constant: label edit distance, value OCR confidence, alignment and proximity all contribute. It is worth gating on.

rule LowConfidenceAmount "the amount was read, but not clearly" {
when
bbox.Doc().Right("Loan Amount").Found() &&
bbox.Doc().Right("Loan Amount").Confidence() < 0.8
then
findings.Warn("LowConfidenceAmount", "extraction",
strings.Sprintf("Loan amount read at %s confidence",
to.Fixed(bbox.Doc().Right("Loan Amount").Confidence(), 2)));
}

The page the value was found on, or 0.

Where on the page the value was found, for tooling that has to show which occurrence a read bound. A value with no provenance has a zero box.

The metadata out.Set carries beside the value: confidence, and where known method, anchor, matched_text, page and distance. The engine never inspects them; they are readable afterwards with out.AttrNum and out.AttrStr.

Lets the engine carry the extracted text without a conversion at the call site.

A miss becomes null, which is what makes out.Set skip it, so writing a missing value does not put an empty string in your output where a consumer would read it as data. You rarely call this directly; it is why out.Set(path, someRead) behaves correctly.

A read that missed and a read that found an empty string are different, and the API keeps them different at every step: Missing() distinguishes them, Reason() explains which stage failed, Or() marks a supplied value as unscored, and EngineValue() keeps a miss out of the output entirely.

The one thing that collapses the distinction is Str(), a miss and an empty hit both give "". Guard with Found() before Str() whenever the difference matters.