Docs

Helpers

Helpers

Language detection

laya.detect_language is laya.lang.analyse.

Names, types, defaults and code stay in English; the rest is translated (entries not translated yet are shown in the original English).

analyse

analyse(state: Union[str, bytes, Mapping, list, None]) -> Dict[str, object]

Full detection result for a state.

Returns script, script_profile, language (best effort, may be None), is_english, non_latin_fraction and mixed_segment (the line or field that made a mostly English state non-English, else None).

String values are what get read. When a state has several of them, one non-English value is enough: joining every value into one window let a long English note fill the 4000 characters, or outvote a short German message, and that message was then sent to the English checkpoint (#384). The segment scan still stops at 4000 characters, which is what keeps a huge field cheap; a value it did not reach is read on its own afterwards.

Parameters

stateUnion[str, bytes, Mapping, list, None]

detect_script

detect_script(text: str) -> str

Dominant script of text: 'latin', 'han', 'devanagari', ... or 'unknown' if there are no letters.

Parameters

textstr

is_english

is_english(state: Union[str, bytes, Mapping, list, None]) -> bool

True when the English checkpoint can be expected to read this state.

Parameters

stateUnion[str, bytes, Mapping, list, None]

Email

clean_email_body

clean_email_body(body: str, max_chars: int = 3000) -> str

Remove quoted email history, signatures and disclaimers to keep input focused.

max_chars is the length the result is cut to, 3000 characters unless raised -- see email_state, which takes the same budget and passes it through.

Parameters

bodystr
max_charsint= 3000

email_state

email_state(
    subject: str,
    body: str,
    sender: Optional[str] = None,
    clean: bool = True,
    max_chars: int = 3000,
    extra,
) -> Dict

Construct a clean state dictionary for email classification.

max_chars is the budget clean_email_body cuts the body to, and it is worth raising for a long message: at the default the body stops after 3000 characters, so a request that arrives in the last paragraphs never reaches the model -- including through predict_long, which scans a state in windows precisely so it can read past one window's worth. Ignored when clean=False, which passes the body through whole.

Any other keyword becomes a field of the state, so it is read by the model; a typo here is an input mutation, not an error.

Parameters

subjectstr
bodystr
senderOptional[str]= None
cleanbool= True
max_charsint= 3000
extra

Question presets

triage_questions

triage_questions() -> Dict

Preset questions for customer support ticket triage.

email_questions

email_questions(categories: Optional[Dict[str, str]] = None) -> Dict

Preset questions for inbound email triage and threat filtering.

Parameters

categoriesOptional[Dict[str, str]]= None

guard_questions

guard_questions() -> Dict

Preset questions for real-time LLM input guardrails.

moderation_questions

moderation_questions() -> Dict

Preset questions for content safety and moderation.

router_questions

router_questions() -> Dict

Preset questions for intelligent model routing.

Shortlisting

shortlist_choice

shortlist_choice(
    state: Any,
    criteria: Any,
    embed_fn: Callable[[Sequence[str]], Any],
    k: int = DEFAULT_SHORTLIST_K,
    DEFAULT_SHORTLIST_K,
    instructions: Optional[str] = None,
) -> List[Any]

Return the top-k choice labels for state.

embed_fn maps a list of strings to an array of shape (len(texts), dim). It is called once, with the query text first and then one string per option in criteria order. Option strings match render_options for a choice question.

When k is at least the number of labels, every label is returned in its original order and embed_fn is not called.

Ties keep the earlier label. A zero vector scores 0 and does not outrank a label that came before it.

Parameters

stateAny
criteriaAny
embed_fnCallable[[Sequence[str]], Any]
kint= DEFAULT_SHORTLIST_K
DEFAULT_SHORTLIST_K
instructionsOptional[str]= None

predict_shortlist

predict_shortlist(
    agent: Any,
    state: Any,
    questions: Dict[str, Dict[str, Any]],
    embed_fn: Callable[[Sequence[str]], Any],
    k: int = DEFAULT_SHORTLIST_K,
    DEFAULT_SHORTLIST_K,
    predict_kwargs: Any,
) -> Dict[str, Any]

Shortlist each choice question, then call predict or system_one once.

Non-choice questions are forwarded unchanged. A choice whose label count is <= k is forwarded unchanged and does not call embed_fn. The caller's questions dict is not mutated.

The returned dict is the model result plus a shortlist entry. Probabilities on a shortlisted choice are over the kept labels only. shortlist[qid] holds labels (rank order), scores (cosine, or None when nothing was dropped), k, n, and passthrough.

Extra keyword arguments are forwarded to predict / system_one (for example model= on a Router).

Parameters

agentAny
stateAny
questionsDict[str, Dict[str, Any]]
embed_fnCallable[[Sequence[str]], Any]
kint= DEFAULT_SHORTLIST_K
DEFAULT_SHORTLIST_K
predict_kwargsAny

embed_fn_from_agent

embed_fn_from_agent(
    agent: Any,
    max_length: int = 512,
    batch_size: int = 32,
) -> Callable[[Sequence[str]], np.ndarray]

Mean-pool the checkpoint encoder already loaded on agent.

The callable embeds a list of strings with agent.tok and agent.model.encoder. It does not run the decision head and does not download weights. A dedicated bi-encoder passed as embed_fn will usually shortlist better; this helper is for callers who only have the Laya checkpoint in memory.

Padding positions are excluded from the mean. The encoder's train/eval flag is left as the caller set it (a loaded Agent is already in eval). Each call uses the current agent.device, including after CPU fallback.

Parameters

agentAny
max_lengthint= 512
batch_sizeint= 32

cached_embed_fn

cached_embed_fn(
    embed_fn: Callable[[Sequence[str]], Any],
    maxsize: int = 4096,
) -> Callable[[Sequence[str]], np.ndarray]

Cache embed_fn output per input string, under an LRU bound.

predict_shortlist embeds the query plus every option text on each call. When the same option set is shortlisted on every request -- a fixed intent or label list, as in the README's BANKING77 example -- the option rows do not change between calls, yet they are re-embedded every time. Wrapping the embedder once::

embed_fn = cached_embed_fn(embed_fn_from_agent(agent))

leaves the first call unchanged and reduces each repeat call to embedding the new query alone.

Lookups are exact string matches. Texts missing from the cache are deduplicated and embedded in a single embed_fn call, so a cold cache costs the same number of batched calls as the unwrapped function. Rows are stored as float32; the cache holds at most maxsize strings and then evicts the least recently used entry, bounding memory at about maxsize * dim * 4 bytes. Nothing is cached when embed_fn raises or returns a bad shape.

The wrapper is safe to share between threads: the lock covers only cache reads and writes, never the embedding call. The returned callable carries cache_info() -- a dict with size, maxsize, hits and misses -- and cache_clear(). Clear the cache if the model or weights behind embed_fn change.

Parameters

embed_fnCallable[[Sequence[str]], Any]
maxsizeint= 4096

Abstention

check_min_confidence

check_min_confidence(v: Any) -> float

Validate opt-in abstention threshold min_confidence (#361).

Must be a real number in [0.0, 1.0]. Booleans are rejected (even though isinstance(True, int)).

Parameters

vAny

flag_low_confidence

flag_low_confidence(results: List[Dict[str, Any]], min_confidence: float) -> None

Opt-in abstention marker (#361): flag answers whose confidence falls below min_confidence.

Reads answer_confidence (max(p), the quantity the calibration figures describe and the one that does not drift with the number of options), falling back to confidence if answer_confidence is absent. The raw answer and confidence stay intact; low_confidence: True is added.

Parameters

resultsList[Dict[str, Any]]
min_confidencefloat

Calibration and training

answer_confidence

answer_confidence(p: np.ndarray, k: int) -> float

Probability mass on the answer being reported: max(p).

This is the quantity temperature scaling fits, and the quantity every calibration figure in this repository is computed on -- both benchmark harnesses take conf = max(probs) before calling ece_score. The README's gating section relies on the property that goes with it: of the answers returned at confidence c, about c of them are right. That property is conditional, and the condition is not met by default -- it holds only after the temperatures have been fitted and validated on held-out data for this checkpoint and this option count. The shipped checkpoints are over-confident: choice:11+ is a ~10x sharpener that returns a point mass at 1.0, so a threshold applied to them selects below model accuracy (issue #394).

confidence_from_probs below reports a different quantity on a different scale and carries no such guarantee, so the two must not be compared against the same threshold.

Parameters

pnp.ndarray
kint

confidence_from_probs

confidence_from_probs(p: np.ndarray, k: int) -> float

Normalized Shannon entropy confidence: 1 - H(p) / log(k).

How concentrated the whole distribution is. Useful, but not calibrated: it is not what temperature scaling fits and not what the reported ECE measures. See answer_confidence.

Parameters

pnp.ndarray
kint

ece_score

ece_score(conf: np.ndarray, correct: np.ndarray, bins: int = 15) -> float

Expected Calibration Error across confidence bins.

Parameters

confnp.ndarray
correctnp.ndarray
binsint= 15

fit_temperatures

fit_temperatures = fit_temperature_map

fit_one_temperature

fit_one_temperature(pairs: Sequence, min_n: Optional[int] = None) -> float

Fit one scalar T by NLL + LBFGS on log T.

The result is clamp_temperature of the optimised scale, so it lies in [TEMP_MIN, TEMP_MAX] (or is the neutral 1.0 when the value is not a number). Returns 1.0 when fewer than min_n pairs are given. min_n defaults to MIN_BUCKET_N (the per-bucket floor). Type-level fits pass MIN_TYPE_N, which is lower, so a dataset that fills no bucket still gets a scalar instead of staying at 1.0.

Parameters

pairsSequence
min_nOptional[int]= None

fit_temperature_map

fit_temperature_map(
    records: Iterable,
    compute_ece: bool = False,
    seed: int = 0,
) -> Dict[str, Any]

Fit type-level scalars and per-bucket temperatures.

MIN_BUCKET_N is the per-bucket floor: smaller buckets are omitted from temperature_by_options and the type-level scalar covers them. MIN_TYPE_N is the separate, lower floor for that scalar only.

compute_ece=False (the default, and the path Agent.fit_temperatures stores) fits on every record and returns no report key. seed is ignored on this path.

compute_ece=True holds out ECE_HOLDOUT_FRAC of each bucket, stratified by temp_bucket, using seed so the same records always split the same way. Temperatures are fit on the remainder only and ECE is scored only on the held-out records. report["n"] is the number of records passed in; report["n_eval"] is the held-out count the ECE rests on. A bucket that would drop below MIN_BUCKET_N after the holdout is fit on all of its records, left out of the eval set, and named in report["buckets_excluded_from_eval"] instead of being dropped. n_by_bucket always counts the full input, including when the fit itself used a subset.

Parameters

recordsIterable
compute_ecebool= False
seedint= 0

render_options

render_options(q: Dict) -> List[str]

Render option texts in label-index order. Noul semantic order is always [false, true].

Parameters

qDict

proper_reward

proper_reward(
    q: torch.Tensor,
    target: torch.Tensor,
    qtype: torch.Tensor,
    mask: torch.Tensor,
    w_sph: float = 0.5,
    w_rps: float = 1.0,
    log_floor: float = -9.21,
) -> torch.Tensor

Strictly proper scoring rule reward: log score + spherical score + ranked probability score.

q: [..., N, K] reported distributions target: [N, K] (one-hot or soft target distributions)

Parameters

qtorch.Tensor
targettorch.Tensor
qtypetorch.Tensor
masktorch.Tensor
w_sphfloat= 0.5
w_rpsfloat= 1.0
log_floorfloat= -9.21

td_lambda_targets

td_lambda_targets(p_true: torch.Tensor, batch: Dict, lam: float = 1.0) -> torch.Tensor

TD(lambda) targets for multi-turn conversation trajectories.

Parameters

p_truetorch.Tensor
batchDict
lamfloat= 1.0

QTYPES

QTYPES = {"choice": 0, "score": 1, "noul": 2}

QTYPE_NAMES

QTYPE_NAMES = {v: k for k, v in QTYPES.items()}