Документация

Вспомогательные функции

Определение языка

laya.detect_language — это laya.lang.analyse.

Имена, типы, значения по умолчанию и код остаются на английском; остальное переведено (ещё не переведённые записи показываются в английском оригинале).

analyse

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

Полный результат определения для состояния.

Возвращает script, script_profile, language (по мере возможности, может быть None), is_english, non_latin_fraction и mixed_segment (строка или поле, которое сделало преимущественно английское состояние неанглийским, иначе None).

Читаются именно строковые значения. Когда у состояния их несколько, достаточно одного неанглийского значения: объединение всех значений в одно окно позволяло длинной английской заметке заполнить 4000 символов или перевесовать короткое немецкое сообщение, и это сообщение затем отправлялось на английский чекпойнт (#384). Сканирование сегментов всё равно останавливается на 4000 символов, что и делает огромное поле дешёвым; значение, до которого оно не дошло, читается отдельно после этого.

Параметры

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

detect_script

detect_script(text: str) -> str

Доминирующая письменность text: 'latin', 'han', 'devanagari', ... или 'unknown', если букв нет.

Параметры

textstr

is_english

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

True, когда можно ожидать, что английский чекпойнт прочитает это состояние.

Параметры

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

Электронная почта

clean_email_body

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

Удаляет цитируемую историю письма, подписи и дисклеймеры, чтобы держать вход сфокусированным.

max_chars — это длина, до которой обрезается результат, 3000 символов, если не увеличено -- см. email_state, который принимает тот же бюджет и передаёт его дальше.

Параметры

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

Строит чистый словарь состояния для классификации почты.

max_chars — это бюджет, до которого clean_email_body обрезает тело, и его стоит увеличить для длинного сообщения: при значении по умолчанию тело обрывается после 3000 символов, так что запрос, который приходит в последних абзацах, никогда не доходит до модели -- в том числе через predict_long, который сканирует состояние в окнах именно для того, чтобы читать дальше одного окна. Игнорируется при clean=False, который пропускает тело целиком.

Любое другое именованное слово становится полем состояния, так что модель его читает; опечатка здесь — это мутация входа, а не ошибка.

Параметры

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

Пресеты вопросов

triage_questions

triage_questions() -> Dict

Предустановленные вопросы для триажа тикетов поддержки клиентов.

email_questions

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

Предустановленные вопросы для триажа входящей почты и фильтрации угроз.

Параметры

categoriesOptional[Dict[str, str]]= None

guard_questions

guard_questions() -> Dict

Предустановленные вопросы для ограничителей входа LLM в реальном времени.

moderation_questions

moderation_questions() -> Dict

Предустановленные вопросы для безопасности контента и модерации.

router_questions

router_questions() -> Dict

Предустановленные вопросы для интеллектуальной маршрутизации моделей.

Отбор кандидатов

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,
    return_scores: bool = False,
) -> Any

Возвращает top-k меток choice для state.

embed_fn сопоставляет список строк массиву формы (len(texts), dim). Она вызывается один раз: сначала текст запроса, затем по одной строке на каждую опцию в порядке criteria. Строки опций совпадают с render_options для вопроса choice.

Когда k не меньше числа меток, каждая метка возвращается в своём исходном порядке, а embed_fn не вызывается.

Ничьи сохраняют более раннюю метку. Ранжирование — это знаковый косинус, а не порог схожести: метка, набравшая 0 -- полное отсутствие сигнала или нефинитный вектор, обработанный как таковой, -- всё же обгоняет более раннюю метку, набравшую отрицательное значение, а k отбрасывает отрицательные метки первыми.

При return_scores=True возвращается пара (labels, scores), где scores содержит знаковый косинус каждой сохранённой метки в порядке ранжирования -- те же значения, которые predict_shortlist сообщает в своих метаданных shortlist. scores равен None, когда ничего не было отброшено, в точности как в этих метаданных.

Параметры

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

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]

Формирует шортлист для каждого вопроса choice, затем один раз вызывает predict или system_one.

Вопросы, не являющиеся choice, передаются без изменений. Choice, у которого число меток <= k, передаётся без изменений и не вызывает embed_fn. Словарь questions вызывающего не изменяется.

Возвращаемый словарь — это результат модели плюс запись shortlist. Вероятности на сокращённом choice — только по сохранённым меткам. shortlist[qid] содержит labels, scores, k, n и passthrough. labels — это порядок ранжирования, который создал шортлист, или сам порядок criteria, когда passthrough задан и ранжирование не выполнялось; scores — знаковый косинус каждой сохранённой метки в этом порядке -- включая отрицательные, никогда не обрезается до 0 -- или None, когда ничего не было отброшено.

Дополнительные именованные аргументы передаются в predict / system_one (например, model= у Router).

Параметры

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) энкодер чекпойнта, уже загруженный на agent.

Вызываемый объект встраивает список строк с помощью agent.tok и agent.model.encoder. Он не запускает голову принятия решений и не загружает веса. Выделенный би-энкодер, переданный как embed_fn, обычно даёт лучший шортлист; этот помощник — для вызывающих, у которых в памяти есть только чекпойнт Laya.

Позиции padding исключаются из среднего. Флаг train/eval энкодера остаётся таким, каким его задал вызывающий (загруженный Agent уже в eval). Каждый вызов использует текущий agent.device, в том числе после перехода на CPU.

Параметры

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]

Кэширует вывод embed_fn по каждой входной строке в пределах границы LRU.

predict_shortlist встраивает запрос плюс текст каждой опции при каждом вызове. Когда один и тот же набор опций попадает в шортлист при каждом запросе -- фиксированный список интентов или меток, как в примере BANKING77 из README -- строки опций не меняются между вызовами, но встраиваются заново каждый раз. Обёртка эмбеддера один раз::

embed_fn = cached_embed_fn(embed_fn_from_agent(agent))

оставляет первый вызов неизменным и сводит каждый повторный вызов к встраиванию только нового запроса.

Поиск — точное совпадение строк. Тексты, отсутствующие в кэше, дедуплицируются и встраиваются за один вызов embed_fn, так что холодный кэш стоит того же числа пакетных вызовов, что и необёрнутая функция. Строки хранятся как float32; кэш содержит не более maxsize строк, а затем вытесняет запись, использованную реже всего, ограничивая память примерно maxsize * dim * 4 байтами. Ничего не кэшируется, когда embed_fn возбуждает исключение или возвращает неверную форму.

Обёртку безопасно разделять между потоками: блокировка покрывает только чтение и запись кэша, но никогда — вызов встраивания. Возвращаемый вызываемый объект несёт cache_info() -- словарь с size, maxsize, hits и misses -- и cache_clear(). Очистите кэш, если модель или веса за embed_fn меняются.

Параметры

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

Воздержание от ответа

check_min_confidence

check_min_confidence(v: Any)

Проверяет opt-in порог отказа от ответа min_confidence (#361, #394).

Либо вещественное число в [0.0, 1.0] (один порог для каждого ответа; логические значения отклоняются, хотя isinstance(True, int)), либо сопоставление по бакетам (см. :func:check_min_confidence_map), так что порог может различаться по числу опций. Возвращает значение в его проверенной форме -- float для скалярного случая, dict[str, float] для случая сопоставления -- которое принимают обе функции gating ниже.

Параметры

vAny

check_min_confidence_map

check_min_confidence_map(m: Dict[Any, Any]) -> Dict[str, float]

Проверяет карту порогов отказа от ответа по бакетам (#394).

Ключи — это строки бакетов по числу опций в написании common.temp_bucket -- "choice:2", "choice:3-5", "score:6-10", "noul:2" и так далее -- плюс необязательный "default", используемый для любого бакета, который карта не называет. Значения — вещественные числа в [0.0, 1.0]. Один порог уверенности не переносится между числами опций (#394); это позволяет вызывающему фильтровать каждый бакет на уровне, который фактически заслуживает его калибровка. Подберите её с помощью :func:laya.calibrate.fit_abstention_thresholds.

Параметры

mDict[Any, Any]

resolve_min_confidence

resolve_min_confidence(
    answer: Dict[str, Any],
    thresholds: Dict[str, float],
    default: float = 0.0,
) -> float

Порог, по которому фильтруется бакет числа опций этого ответа, в рамках карты по бакетам.

Сначала откатывается к записи "default" карты, затем к default (0.0 -- ничего не фильтровать), для бакета, который карта не называет, так что ненастроенный бакет никогда не отказывается от ответа неожиданно.

Параметры

answerDict[str, Any]
thresholdsDict[str, float]
defaultfloat= 0.0

flag_low_confidence

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

Opt-in маркер отказа от ответа (#361): помечает ответы, уверенность которых падает ниже min_confidence.

Читает answer_confidence (max(p), величина, которую описывают калибровочные числа и которая не дрейфует с числом опций), с откатом на confidence, если answer_confidence отсутствует. Сырой ответ и уверенность остаются нетронутыми; low_confidence: True добавляется, когда ответ падает ниже порога, и удаляется, если ранее помеченный ответ теперь его превышает (например, когда словарь результата переиспользуется или переоценивается с другим порогом).

min_confidence — либо float (один порог для каждого ответа), либо сопоставление по бакетам (#394), и тогда каждый ответ фильтруется по порогу своего бакета числа опций через :func:resolve_min_confidence.

Параметры

resultsList[Dict[str, Any]]
min_confidencefloat

apply_confidence_gate

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

Сообщает состояние gating по уверенности для ответов, к которым gating действительно применялся.

Gating — это политика, а политика, применение которой нельзя наблюдать, не является таковой. Когда min_confidence задан, это записывает abstention -- одно из :data:GATE_STATES -- в каждый ответ, плюс abstention_threshold, чтобы вызывающий мог ответить на три вопроса, на которые иначе не может:

  • какая доля решений отказалась от ответа, вместо того чтобы выводить это из того, была ли случайно выставлена low_confidence;
  • на скольких ответах gating не смог определить решение, что логическое значение вообще не может выразить;
  • какой порог дал эти результаты -- flag_low_confidence потребляет порог и отбрасывает его, так что без этого пакетный прогон с порогами по классам нельзя переразбить.

GATE_UNEVALUATED -- это случай, который логическое значение не может выразить: gating сработал, а ответ не несёт пригодной уверенности, так что gating не смог решить. Сообщить об этом как о прохождении -- та же ложь, что и сообщить об этом как о флаге.

Когда min_confidence не задан, это не записывает ничего. Ни abstention, ни abstention_threshold, ни флага. В этом весь контракт: вызов без gating возвращает ровно ту же полезную нагрузку, что и раньше, и наличие поля -- не четвёртое значение, прочитанное из него -- говорит вызывающему, что gating сработал. Вызывайте его безусловно, один раз за вызов, вместо проверки if min_confidence is not None:: именно эта проверка оставляет путь, сообщающий вообще ничего, -- состояние, которое эта функция и призвана отличать.

Сам флаг остаётся за :func:flag_low_confidence -- это делегирует, а не переписывает правило заново, так что логическое значение и сообщаемое состояние не могут разойтись.

min_confidence, равный ровно 0.0, был задан, поэтому состояния сообщаются, а :func:flag_low_confidence трактует 0.0 как пустую операцию, ведь ничто не может упасть ниже него. Каждый ответ, несущий пригодную уверенность, поэтому читается как passed, и именно эхо порога отличает это от настоящего прохождения при настоящем пороге.

Параметры

resultsList[Dict[str, Any]]
min_confidenceOptional[float]= None

GATE_STATES

GATE_STATES = (GATE_PASSED, GATE_ABSTAINED, GATE_UNEVALUATED)

Калибровка и обучение

answer_confidence

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

Масса вероятности на сообщаемом ответе: max(p).

Это величина, которую подгоняет температурное масштабирование, и величина, по которой вычисляется каждое калибровочное число в этом репозитории -- оба стенда бенчмарков берут conf = max(probs) перед вызовом ece_score. Раздел README про gating опирается на сопутствующее свойство: из ответов, возвращённых с уверенностью c, примерно c верны. Это свойство условно, и условие по умолчанию не выполняется -- оно сохраняется только после того, как температуры подобраны и проверены на отложенных данных для этого чекпойнта и этого числа опций. Поставляемые чекпойнты сверхуверены: choice:11+ — заостритель ~10x, возвращающий точечную массу в 1.0, так что порог, применённый к ним, отбирает ниже точности модели (issue #394).

confidence_from_probs ниже сообщает другую величину в другом масштабе и не несёт такой гарантии, поэтому их нельзя сравнивать с одним и тем же порогом.

Параметры

pnp.ndarray
kint

confidence_from_probs

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

Уверенность по нормированной энтропии Шеннона: 1 - H(p) / log(k).

Насколько сконцентрировано всё распределение. Полезно, но не калибровано: это не то, что подгоняет температурное масштабирование, и не то, что измеряет сообщаемый ECE. См. answer_confidence.

Параметры

pnp.ndarray
kint

ece_score

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

Ожидаемая ошибка калибровки (ECE) по бинам уверенности.

Параметры

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

Подбирает один скаляр T методом NLL + LBFGS по log T.

Результат — это clamp_temperature оптимизированного масштаба, так что он лежит в [TEMP_MIN, TEMP_MAX] (или равен нейтральному 1.0, когда значение не является числом). Возвращает 1.0, когда задано меньше min_n пар. min_n по умолчанию равен MIN_BUCKET_N (нижний порог на бакет). Подгонки на уровне типа передают MIN_TYPE_N, который ниже, так что набор данных, не заполняющий ни один бакет, всё равно получает скаляр, а не остаётся на 1.0.

Параметры

pairsSequence
min_nOptional[int]= None

fit_temperature_map

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

Подбирает скаляры на уровне типа и температуры по бакетам.

MIN_BUCKET_N — это нижний порог на бакет: меньшие бакеты исключаются из temperature_by_options, и их покрывает скаляр на уровне типа. MIN_TYPE_N — это отдельный, более низкий порог только для этого скаляра.

compute_ece=False (значение по умолчанию и путь, который сохраняет Agent.fit_temperatures) подгоняется по всем записям и не возвращает ключ report. seed на этом пути игнорируется.

compute_ece=True откладывает ECE_HOLDOUT_FRAC каждого бакета, стратифицированно по temp_bucket, используя seed, чтобы одни и те же записи всегда делились одинаково. Температуры подбираются только по остатку, а ECE оценивается только по отложенным записям. report["n"] — число поданных записей; report["n_eval"] — отложенное число, на которое опирается ECE. Бакет, который после отложения упал бы ниже MIN_BUCKET_N, подгоняется по всем своим записям, исключается из набора оценки и указывается в report["buckets_excluded_from_eval"] вместо отбрасывания. n_by_bucket всегда считает весь вход, в том числе когда сама подгонка использовала подмножество.

Параметры

recordsIterable
compute_ecebool= False
seedint= 0

fit_abstention_thresholds

fit_abstention_thresholds(
    records: Iterable,
    temperature: Sequence[float],
    temperature_by_options: Dict[str, float],
    binning_map: Optional[Dict[str, Dict[str, Any]]] = None,
    target_error: float = 0.10,
    min_bucket_n: int = MIN_ABSTAIN_BUCKET_N,
    MIN_ABSTAIN_BUCKET_N,
    conservative: bool = True,
) -> Dict[str, float]

Подбирает порог отказа от ответа по temp_bucket, чтобы gating удерживал целевой уровень ошибки в каждом бакете.

Один min_confidence не переносится между числами опций (#394): калиброванная уверенность ответа с 2 опциями и с 12 опциями живёт в разных масштабах, так что один порог отсекает слишком много или слишком мало в зависимости от вопроса. Вместо этого здесь подбирается один порог на бакет, с ключами в точности как у temperature_by_options (common.temp_bucket, например "choice:3-5"), и результат — это карта min_confidence, которую :func:laya.confidence.check_min_confidence / :func:laya.confidence.apply_confidence_gate принимают напрямую.

records — это те же кортежи (qtype, logits, target[, k]), что потребляет fit_temperature_map (records_from_labeled строит их). Уверенность — это калиброванный max(p) -- логиты сначала масштабируются подобранными temperature / temperature_by_options, так что пороги и числа, которые сообщает runtime, находятся в одном масштабе. target_error — это допускаемая ошибка среди принятых ответов; min_bucket_n опускает бакеты, слишком малые для подгонки, а conservative добавляет запас в одну выборку. Пороги — это эмпирические срезы по калибровочному набору, а не формальная гарантия покрытия -- проверяйте на отложенных данных (fit_temperature_map(..., compute_ece=True) даёт отложенное разбиение) для gating в продакшене.

Передавайте binning_map, когда у агента, который будет обслуживать эти пороги, он установлен -- через Agent.fit_binning или через калибровочную полезную нагрузку, которая несёт binning_map -- потому что runtime перекалибровывает answer_confidence через эту карту, прежде чем что-либо её прочитает, так что срез, подобранный без неё, — это срез в масштабе, которого gating никогда не видит. Тогда пороги оказываются в бинаризованном масштабе, и порядок, в котором подбирались эти двое, перестаёт иметь значение. Измерено на 1,200 синтетических записях с 12 опциями при target_error=0.10: срез, подобранный без карты, удерживает 9.8% ошибки при 50% покрытия на небинаризованных уверенностях, а при сравнении того же числа с бинаризованными пропускает 94.5% ответов при 25.6% ошибки.

Параметры

recordsIterable
temperatureSequence[float]
temperature_by_optionsDict[str, float]
binning_mapOptional[Dict[str, Dict[str, Any]]]= None
target_errorfloat= 0.10
min_bucket_nint= MIN_ABSTAIN_BUCKET_N
MIN_ABSTAIN_BUCKET_N
conservativebool= True

fit_binning_map

fit_binning_map(
    records: Iterable,
    temperature: Sequence[float],
    temperature_by_options: Dict[str, float],
    bins: int = 15,
    min_bucket_n: int = MIN_BINNING_BUCKET_N,
    MIN_BINNING_BUCKET_N,
) -> Dict[str, Dict[str, Any]]

Подбирает карту перекалибровки гистограммной бинаризации по temp_bucket для answer_confidence.

Температурное масштабирование применяет один скаляр на бакет; оно не может исправить бакет, у которого кривая надёжности не является простым заострением/сглаживанием (патологический choice:11+, который несёт поставляемый английский чекпойнт, — один из таких). Гистограммная бинаризация — это непараметрическая альтернатива: разделите калиброванные уверенности бакета на bins бинов равной ширины в [0, 1] и отобразите каждую уверенность, попадающую в бин, в эмпирическую точность этого бина. Она не требует предположения о монотонности и лишних зависимостей (только NumPy; изотоническая регрессия потребовала бы scikit-learn).

records — это те же кортежи (qtype, logits, target[, k]), что потребляет fit_temperature_map; уверенность — это калиброванный max(p) (логиты сначала масштабируются подобранными temperature / temperature_by_options), так что карта бинаризации компонуется поверх карты температур, а не заменяет её. Возвращает {bucket: {"bins": N, "values": [recalibrated confidence per bin]}}; бакеты ниже min_bucket_n опускаются. Примените её с помощью :func:apply_binning_map. Пустой бин (диапазон уверенности, который калибровочный набор никогда не выдавал) отображается в свою собственную середину, то есть оставляет эту область без изменений, так что невиданное значение никогда не перекалибровывается в выдуманный 0.

Параметры

recordsIterable
temperatureSequence[float]
temperature_by_optionsDict[str, float]
binsint= 15
min_bucket_nint= MIN_BINNING_BUCKET_N
MIN_BINNING_BUCKET_N

apply_binning_map

apply_binning_map(
    confidence: float,
    bucket: str,
    binning_map: Dict[str, Dict[str, Any]],
) -> float

Перекалибровывает один answer_confidence для его bucket по числу опций (common.temp_bucket).

Возвращает уверенность без изменений, когда в карте нет записи для бакета, так что бакет, для которого карта не подбиралась, проходит насквозь, а не приводится к неверному значению.

Параметры

confidencefloat
bucketstr
binning_mapDict[str, Dict[str, Any]]

fit_binning

fit_binning(
    records,
    min_bucket_n: int = MIN_BINNING_BUCKET_N,
    MIN_BINNING_BUCKET_N,
) -> Dict[str, Any]

Подбирает карту гистограммной бинаризации поверх подобранных температур этого агента и сохраняет её.

records — это те же кортежи (qtype, logits, target[, k]), что потребляет fit_temperatures. Ключи карты в точности как у temperature_by_options, она компонуется поверх текущих температур и записывается save_calibration как binning_map.

Параметры

records
min_bucket_nint= MIN_BINNING_BUCKET_N
MIN_BINNING_BUCKET_N

render_options

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

Отрисовывает тексты опций в порядке индексов меток. Семантический порядок Noul всегда [false, true].

Параметры

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

Вознаграждение по строго собственному (proper) правилу оценки: log score + spherical score + ranked probability score.

q: [..., N, K] сообщаемые распределения target: [N, K] (one-hot или мягкие целевые распределения)

Параметры

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) для траекторий многоходовых разговоров.

Параметры

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()}