文件導航

Agent

laya.Agent 載入一個 checkpoint,回答關於某個狀態的型別化問題。laya.load 是 Agent(...) 的快捷方式,laya.RLAgent 是 Agent 的別名。ONNXAgent 在 CPU 上執行匯出的 ONNX 模型; 從 laya.onnx_agent 匯入它。

名稱、型別、預設值與程式碼保持英文;其餘為譯文(尚未翻譯的條目暫顯示英文原文)。

Agent

Agent(
    model_id_or_path: str = "convaiinnovations/laya",
    device: Optional[str] = None,
    token: Optional[str] = None,
    subfolder: Optional[str] = None,
    fast: bool = False,
    compile: bool = False,
    revision: Optional[str] = None,
    expected_sha256: Optional[Dict[str, str]] = None,
    lang_temperatures: Optional[Dict[str, Dict[str, Any]]] = None,
    hooks=None,
    on_predict_start=None,
    on_predict_end=None,
    hooks_raise: bool = True,
    hooks_concurrent: bool = True,
    hooks_timeout: Optional[float] = None,
    calibration: Optional[str] = None,
    backend: Optional[str] = None,
    compile_warmup: bool = True,
    compile_cache: bool = False,
    compile_mode: str = "default",
)

基類: HookRegistry

System 1 決策模型執行時:快速、非自迴歸、經過校準的決策。

dtype 是自動轉換的目標型別,不是每次呼叫的精度。在 MPS 上,只有行數達到 mps_amp_min_rows 時呼叫才會自動轉換,所以 dtype 可以是 float16,而某次呼叫實際以 float32 執行。dtype_for(rows) 返回行數為 rows 的呼叫所用的精度。

載入一個 Laya checkpoint。

backend 選擇 "eager"、"auto"、"compile" 或 "tilelang";見 laya.backends。它的優先順序高於 fast 與 compile;省略它就保留那些舊標誌。要用 ONNX,請改用 load(backend="onnx")。

revision 可選地把 Hub 下載固定到某個明確的 commit SHA/分支/tag;不給時,用 huggingface_hub 的常規預設值和已有的離線快取。expected_sha256({相對 checkpoint 目錄的路徑: 十六進位制摘要})在任何權重被解析或執行之前校驗產物完整性;它是可選的,對本地目錄同樣生效。產物缺失會拋 FileNotFoundError,摘要不匹配會拋 ValueError;兩者都會拒絕這次載入。

fast=True 把編碼器/決策頭的前向換成 TileLang 快速路徑(僅 CUDA,需要 pip install laya[fast]);見 Agent.accelerate。

compile=True 讓模型跑在 torch.compile 下,並開啟 ModernBERT 編碼器的 reference_compile。torch.compile 會按輸入形狀特化,而 Laya 幾乎每個請求都會遇到新形狀,所以那些圖通常是入不敷出;流量重複時才用它。fast=True 優先,因為 TileLang 路徑替換掉的正是將要被編譯的那個前向。

編譯過的 agent 會在返回前執行 warmup();compile_warmup=False 會把這份工作推遲到請求時或手動呼叫 warmup() 時。eager 與 fast agent 不受影響。compile_cache=True 會啟用一個持久的 Laya Inductor 目錄(程序級),並尊重已有的 TORCHINDUCTOR_CACHE_DIR;見編譯工程說明。compile_mode="reduce-overhead" 會啟用 CUDA graph:它可能佔用更多 GPU 記憶體,並會為每一個新形狀單獨記錄;CUDA 輸出在下一次重放之前會被複製,編譯後的 CUDA graph 前向是序列化的。預設模式仍是 "default"。

subfolder 從捆綁了多個 checkpoint 的倉庫裡挑一個,例如 Agent("convaiinnovations/laya", subfolder="multilingual")。只會下載那個子目錄,所以捆綁不會讓每個使用者都付出整個家族的代價。

calibration 是可選的 JSON 路徑,含 temperature 與 temperature_by_options。它在 checkpoint 配置之後應用,因此擬合出來的對映可以覆蓋隨包釋出的標量,而不必重寫 model.safetensors。

hooks / on_predict_start / on_predict_end 觀察或塑造每一次預測;見 laya.hooks。hooks_raise=False 時鉤子失敗只警告並繼續,hooks_concurrent=False 會把不適合並行執行的鉤子序列化,hooks_timeout 以秒為單位限制每次鉤子呼叫(None 表示不限制)。

參數

model_id_or_pathstr= "convaiinnovations/laya"
deviceOptional[str]= None
tokenOptional[str]= None
subfolderOptional[str]= None
fastbool= False
compilebool= False
revisionOptional[str]= None
expected_sha256Optional[Dict[str, str]]= None
lang_temperaturesOptional[Dict[str, Dict[str, Any]]]= None
hooks= None
on_predict_start= None
on_predict_end= None
hooks_raisebool= True
hooks_concurrentbool= True
hooks_timeoutOptional[float]= None
calibrationOptional[str]= None
backendOptional[str]= None
compile_warmupbool= True
compile_cachebool= False
compile_modestr= "default"

backend

backend: str

當前生效的推理後端,包含舊的 compile 與 fast 標誌。

backend_object

backend_object

已安裝的 Backend 物件;舊執行時為 None。

set_backend

set_backend(name: str = "auto", strict: bool = False, options) -> str

切換後端;後端不可用時只給出警告並使用 eager,除非 strict=True。

選項會傳給後端建構函式,例如 compile 的 warmup=False,或 tilelang 的 use_graphs=False。切換會等待在途推理結束。

參數

namestr= "auto"
strictbool= False
options

accelerate

accelerate(use_graphs: bool = True, strict: bool = False)

把模型的前向換成 TileLang 快速路徑(融合的 GEMM/GEGLU/LayerNorm/RoPE 核心、滑窗 flash attention、16 位常駐權重、按形狀桶構建的 CUDA graph)。

快速路徑按呼叫當時 agent 的自動轉換 dtype 執行(bf16 或 fp16),所以它與被它替換掉的原始前向在舍入誤差內一致(見 benchmarks/parity_fast.py)。改過 agent.dtype 之後,先呼叫 deaccelerate() 再呼叫 accelerate() 來重建它。啟用成功返回 True。strict=False 時任何失敗(沒有 CUDA、缺 tilelang)都會保留原始路徑。

參數

use_graphsbool= True
strictbool= False

warmup

warmup(shapes=None) -> float

立刻用每種形狀的合成輸入跑一遍前向,返回花掉的秒數。

compile=True 會在載入時呼叫它,除非設了 compile_warmup=False。額外的形狀仍可手動預熱。fast=True 會在首次使用時按形狀桶構建它的核心與 CUDA graph;在開始服務之前呼叫它,就能把這份代價從最初的幾個請求裡挪走。用原始前向時,這只是幾次普通的前向傳播。shapes 是 (rows, tokens, markers) 的列表;tokens 會被限制在 agent 的 max_len 以內。不會向任何呼叫方返回或記錄任何東西,鉤子也不會執行。

參數

shapes= None

deaccelerate

deaccelerate()

恢復原始前向。

dtype_for

dtype_for(rows: int) -> torch.dtype

行數為 rows 個問題行的一次前向所用的精度。

dtype 是自動轉換的目標型別,在載入時設定一次。一次前向是否做自動轉換是按呼叫決定的:在 MPS 上只有行數達到 mps_amp_min_rows 才會。行數為 rows 的前向會做自動轉換時返回 dtype,否則返回 torch.float32。一次 predict 呼叫每個問題佔一行。

參數

rowsint

predict_batch

predict_batch(
    states: List[Union[str, dict, list]],
    questions: Dict[str, Dict[str, Any]],
    batch_size: Optional[int] = None,
    lang: Optional[str] = None,
    hooks=None,
    on_predict_start=None,
    on_predict_end=None,
    hooks_raise: Optional[bool] = None,
    hooks_timeout: Optional[float] = None,
    max_len: Optional[int] = None,
    head_max_len: Optional[int] = None,
    sort_by_length: bool = False,
    min_confidence: Optional[float] = None,
) -> List[Dict[str, Any]]

對多個狀態評估同一組問題,把它們打包進共享的前向傳播。

這是吞吐路徑。system_one/predict 每次前向只處理一個狀態;在 GPU 上那會讓批次維度大部分空著。predict_batch 把多個狀態的問題行歸併進同一個張量,於是一次本來要 N 次序列前向的呼叫只需一次(或 ceil(len(states) / batch_size) 次),在 GPU 上每次決策快好幾倍。

參數

statesList[Union[str, dict, list]]

狀態列表(每一項是文本字串、JSON 字典或對話輪次列表)。同一組 questions 會對照每一個狀態評估。

questionsDict[str, Dict[str, Any]]

問題定義,與 system_one 接受的完全一致。

batch_sizeOptional[int]= None

每次前向傳播中狀態數的可選上限。None 表示一次全發;批次處理很多或很長的狀態時,設上它可以給峰值記憶體封頂。

langOptional[str]= None
hooksHookArg= None

每次呼叫的鉤子,追加在 Agent 上已安裝的鉤子之後。見 laya.hooks。

on_predict_startPredictHookArg= None

每次呼叫的起始鉤子。它可以改寫狀態/問題,或呼叫 ctx.skip(...) 短路推理。

on_predict_endPredictHookArg= None

每次呼叫的結束鉤子。它可以改寫結果。

hooks_raiseOptional[bool]= None

覆蓋本次呼叫中 Agent 的 hooks_raise。

hooks_timeoutOptional[float]= None

覆蓋本次呼叫中 Agent 的 hooks_timeout。

max_lenOptional[int]= None

覆蓋本次呼叫中 agent 配置的 max_len。起始鉤子也可以設定 ctx.max_len 來塑造 token 預算。

head_max_lenOptional[int]= None

覆蓋本次呼叫中 agent 配置的 head_max_len。起始鉤子也可以設定 ctx.head_max_len。

sort_by_lengthbool= False

把編碼後長度相近的狀態按「八個批次」為一組歸到一起,以減少 padding。需要顯式給出大於 1、且小於狀態數的 batch_size;否則沒有任何效果。結果保持輸入順序。這樣會快取最多八個批次的已分詞狀態,而不是一個。改變批次形狀可能輕微改變浮點預測結果。

min_confidenceOptional[float]= None

回傳值

每個狀態一個結果字典的列表,形狀與 system_one 的輸出完全相同,並按下標與 states 對齊。

predict_long

predict_long(
    state: Union[str, dict, list],
    questions: Dict[str, Dict[str, Any]],
    window: Optional[int] = None,
    stride: Optional[int] = None,
    aggregate: str = "auto",
    batch_size: Optional[int] = None,
    lang: Optional[str] = None,
    hooks=None,
    on_predict_start=None,
    on_predict_end=None,
    hooks_raise: Optional[bool] = None,
    hooks_timeout: Optional[float] = None,
) -> Dict[str, Any]

對超出上下文視窗的狀態評估問題:用互相重疊的視窗掃描它,並按問題聚合。

system_one/predict 會把超出 max_len 的狀態截斷到一個視窗(第一個;對話列表則取最後一個),其餘部分被靜默丟棄。predict_long 只把狀態分詞一次,切成互相重疊的 token 視窗,在共享的前向傳播裡給每個視窗打分(經由 predict_batch),再把各視窗的答案合併起來:

  • noul -> P(true) 取各視窗的最大值(只要有一個視窗支援,該陳述就成立)
  • choice-> 取單個最自信視窗的答案,這樣區域性訊號不會被長文件裡佔絕大多數的中性視窗投票壓過去 (取平均會把它淹沒 —— 中性多數說了算)
  • score -> 同樣取最自信視窗的檔位

返回的機率/置信度是作出決定的那個視窗的,不是針對整篇文件校準過的數字:沒有任何訊號時,noul 在多視窗上取最大值也會隨視窗數往上漂;而當文件裡沒有任何決定性的內容時,choice 可能落在一個自信地中性的視窗上。因此每個答案都帶著 answer["window"] —— 作出決定的視窗的 index、在分詞後狀態中的 token_start/token_end,以及視窗總數 count —— 這樣呼叫方可以檢視答案來自哪一段,而不是盲信那個原始數字。那段就是模型讀到的範圍,而不只是被要求的範圍:視窗會被限制在問題留出的空間之內,所以交給 predict_batch 的內容不會再次被截短。

已經裝得進一個視窗的狀態會直接交給 system_one(輸出完全相同)。

鉤子包住的是「為該狀態作答的那次推理」——對一個需要多個視窗的文件來說,就是那次統一的、覆蓋所有視窗的 predict_batch:on_predict_start 只觸發一次,而 ctx.states 裡按掃描順序放著解碼後的視窗文本 —— 不是呼叫方傳入的 state,後者已被分詞用以產生這些視窗。根據這條鏈最後留下什麼,有三種結果:

  • ctx.skip([result]) 直接為文件作答:載荷回來時沒有視窗歸屬資訊,usage["windows"] 為 0,因為什麼都沒打分
  • 保持本方法構建出來的掃描:每個視窗都被打分,每個答案都帶 answer["window"],usage["windows"] 就是視窗數
  • 被改寫過的掃描(ctx.states 以任何方式被替換):答案按實際打過分的那些狀態聚合,但沒有任何答案帶 answer["window"] —— 上面那些偏移描述的是本方法的視窗,不是模型讀到的文本

參數

stateUnion[str, dict, list]
questionsDict[str, Dict[str, Any]]
windowOptional[int]= None

每個視窗容納的狀態 token 數。預設取 checkpoint 的狀態預算(max_len - head_max_len - 8),而且無論哪種取值,都會被限制在問題為狀態在 max_len 內留出的空間裡 —— 取其中最小的空間,因為每一份視窗列表都要為所有問題打分。更寬的視窗在送往模型的途中會再次被截斷,所以這裡會把它夾緊,並在呼叫方主動要求時給出 RuntimeWarning。讓空間變小的正是選項:在英文 checkpoint 上,2 個選項的問題給狀態留下 483 個 token,100 個選項的只留下 100 個。視窗更小能更好地隔離區域性訊號(一段很短的決定性文本在它所在窗口裡佔比更大,那個視窗就能清楚地把它分類出來),代價是視窗數更多;預設的大視窗偏向上下文與吞吐。noul 對此不敏感;而當決定性的一段只佔一份長文件很小的一部分、其餘都是中性內容時,choice/score 會受益於更小的視窗。

strideOptional[int]= None

視窗之間的 token 步長。預設是有效視窗的一半(50% 重疊),這樣靠近邊界的片段仍然能完整落進某個視窗。超過有效視窗的步長會被拒絕,而不是被夾緊:那樣每兩個視窗之間的 token 將沒有任何視窗會讀到,而這正是這個方法存在的意義所在 —— 防止這種失敗。

aggregatestr= "auto"

"auto"(即上面那套按型別的規則)是目前唯一的模式。

batch_sizeOptional[int]= None

每次前向傳播的視窗數上限,用來給超長狀態的記憶體用量封頂。

langOptional[str]= None

按語言選擇溫度,與 system_one 一致。

hooksHookArg= None

每次呼叫的鉤子,追加在 Agent 上已安裝的鉤子之後。見 laya.hooks。

on_predict_startPredictHookArg= None

每次呼叫的起始鉤子,與 system_one 一致。

on_predict_endPredictHookArg= None

每次呼叫的結束鉤子,與 system_one 一致。

hooks_raiseOptional[bool]= None

覆蓋本次呼叫中 Agent 的 hooks_raise。

hooks_timeoutOptional[float]= None

覆蓋本次呼叫中 Agent 的 hooks_timeout。

異常

ValueError:aggregate 不是 "auto";問題的選項填滿了整個序列,沒有給狀態留出空間;或者 stride 越過了有效視窗,導致兩個視窗之間的 token 不會被任何東西讀到。

返回單個結果字典,形狀與 system_one 相同,並加上 usage["windows"]。這個鍵始終存在,計的是模型為得出答案而打分的視窗數:裝得進一個視窗的狀態是 1;用 N 個重疊視窗掃描的文件是 N(起始鉤子改寫後就是它改寫成的那個 N);起始鉤子直接為文件作答、或者在任何視窗被讀取之前就沒有留下要打分的狀態時是 0 —— 兩條路徑都是如此,所以快取下來的答案永遠不會被讀成「模型讀過的視窗」。

跨多個視窗時,截斷相關的鍵與其它 usage 欄位一樣合併:truncated、state_tokens 與 state_tokens_dropped 求和(因此 truncated 是被截斷的視窗數,而 token 計數里包含重疊部分),truncated_questions 則是最後一個視窗的列表。兩者可以不一致:只有靠前的某個視窗被截斷時,truncated 大於 0 而 truncated_questions 是空的。當某個視窗大於該問題決策頭留出的空間時,它就被截斷。這裡要判斷的是 usage["truncated"] > 0,而不是 is True。

system_one

system_one(
    state: Union[str, dict, list],
    questions: Dict[str, Dict[str, Any]],
    lang: Optional[str] = None,
    hooks=None,
    on_predict_start=None,
    on_predict_end=None,
    hooks_raise: Optional[bool] = None,
    hooks_timeout: Optional[float] = None,
    max_len: Optional[int] = None,
    head_max_len: Optional[int] = None,
    min_confidence: Optional[float] = None,
) -> Dict[str, Any]

在一次並行的前向傳播裡,對狀態評估一組型別化問題。

參數

stateUnion[str, dict, list]

文本字串、JSON 字典或對話輪次列表。

questionsDict[str, Dict[str, Any]]

把 question_id 對映到問題定義的字典。

  • choice: {"type": "choice", "instructions": "...", "criteria": {"optA": "...", ...}}
  • score: {"type": "score", "instructions": "...", "criteria": ["lvl0", "lvl1", ...]}
  • noul: {"type": "noul", "instructions": "...", "criteria": {"false": "...", "true": "..."}, "labels": {"false": "B", "true": "A"}}

Noul 的 criteria 與 labels 都是可選的。labels 只控制展示給模型的文字;它們的鍵仍然保持 false/true 的語義,返回的 noul 值永遠表示 P(true)。為相容起見,labels 預設為 false/true。

langOptional[str]= None
hooks= None
on_predict_start= None
on_predict_end= None
hooks_raiseOptional[bool]= None
hooks_timeoutOptional[float]= None
max_lenOptional[int]= None
head_max_lenOptional[int]= None
min_confidenceOptional[float]= None

回傳值

含答案、機率、校準後的置信度與 token 用量的字典。問題為空時返回空答案與零 token 用量,不做分詞也不做模型前向。

當決策頭預算讓兩個選項落在同一段 token 上時,usage 會為碰巧如此的每個問題帶一個 options 條目 —— total、distinct 與 tokens_per_option —— 因為在 58 段可區分的跨度裡只挑得出 42 個時,這個天花板是預算造成的,不是模型造成的。選項全部存活的問題不會出現,所以什麼都沒被壓掉的請求與原來完全一樣。

usage 還會報告狀態是否裝得下:truncated、state_tokens、state_tokens_dropped,以及 truncated_questions(決策頭留下的空間太少的那幾個問題)。關心答案是否看到了整個狀態的呼叫方,應該讀 usage["truncated"],而不是拿自己發出去的內容長度去估算。

要一次性給很多狀態打分,見 predict_batch,它讓這些狀態共用前向傳播。

decide

decide(
    state: Union[str, dict, list],
    schema: Any = None,
    questions: Optional[Dict[str, Any]] = None,
    return_details: bool = False,
    min_confidence: Optional[float] = None,
    predict_kwargs,
) -> Any

把 state 對照一個 schema(JSON schema 或 pydantic 模型)作答,返回型別化的值。

見 laya.structured。schema 與 questions 只能給一個;額外的關鍵字參數會透傳給 predict / system_one。

參數

stateUnion[str, dict, list]
schemaAny= None
questionsOptional[Dict[str, Any]]= None
return_detailsbool= False
min_confidenceOptional[float]= None
predict_kwargs

decide_batch

decide_batch(
    states: List[Union[str, dict, list]],
    schema: Any = None,
    questions: Optional[Dict[str, Any]] = None,
    return_details: bool = False,
    min_confidence: Optional[float] = None,
    predict_kwargs,
) -> List[Any]

一次性把多個狀態對照同一個 schema(JSON schema 或 pydantic 模型)作答。

這是 :meth:decide 的吞吐版本:schema 只規劃一次,它的問題通過 :meth:predict_batch 跑遍每一個狀態(共享的前向傳播,結果保持輸入順序),然後像 decide 那樣把每個狀態的答案投影出來。額外的關鍵字參數(batch_size=、lang=、hooks= 等)會透傳給 predict_batch。見 laya.structured。

參數

statesList[Union[str, dict, list]]
schemaAny= None
questionsOptional[Dict[str, Any]]= None
return_detailsbool= False
min_confidenceOptional[float]= None
predict_kwargs

fit_temperatures

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

用 CPU 上的記錄擬合逐桶溫度,並存到這個 agent 上。

records 是 (qtype, logits, target, k)。手上有帶標籤的前向記錄時,用 laya.calibrate.records_from_labeled 構造它們;這個方法不下載權重,也不寫 model.safetensors。seed 只在 compute_ece 為真時影響留出的 ECE 切分。checkpoint 的 cfg 保持載入時的樣子。

參數

records
compute_ecebool= False
seedint= 0

fit_binning

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

在這個 agent 已擬合的溫度之上擬合一張直方圖分箱對映,並存下來。

records 與 fit_temperatures 消費的是同一批 (qtype, logits, target[, k]) 元組。這張對映的鍵與 temperature_by_options 完全一致,疊加在當前溫度之上,由 save_calibration 寫成 binning_map。

參數

records
min_bucket_nint= MIN_BINNING_BUCKET_N
MIN_BINNING_BUCKET_N

save_calibration

save_calibration(path: str) -> None

寫出溫度,以及它們是為哪個 checkpoint 擬合的。不寫權重。

參數

pathstr

load_calibration

load_calibration(path: str) -> None

把 save_calibration 寫出的 JSON 對映讀進這個 agent。

沒有 version 的檔案會被當作版本 1,仍然能載入。版本更新、但記錄的 checkpoint 與這個 agent 對不上的檔案會給出警告,也仍然載入。不是數字、或落在 [TEMP_MIN, TEMP_MAX] 之外的值,會像載入 checkpoint 時那樣用 clamp_temperature 夾住。

參數

pathstr

load

load(
    model_id_or_path: str = "convaiinnovations/laya",
    device: Optional[str] = None,
    token: Optional[str] = None,
    subfolder: Optional[str] = None,
    fast: bool = False,
    compile: bool = False,
    revision: Optional[str] = None,
    expected_sha256: Optional[Dict[str, str]] = None,
    lang_temperatures: Optional[Dict[str, Dict[str, Any]]] = None,
    hooks=None,
    on_predict_start=None,
    on_predict_end=None,
    hooks_raise: bool = True,
    hooks_concurrent: bool = True,
    hooks_timeout: Optional[float] = None,
    calibration: Optional[str] = None,
    backend: Optional[str] = None,
    onnx_path: Optional[str] = None,
    compile_warmup: bool = True,
    compile_cache: bool = False,
    compile_mode: str = "default",
) -> Agent

載入一個 Laya agent。

subfolder 從捆綁了多個 checkpoint 的倉庫裡挑一個:

laya.load("convaiinnovations/laya")                           # English (repo root)
laya.load("convaiinnovations/laya", subfolder="multilingual")
laya.load("convaiinnovations/laya", fast=True)                # TileLang GPU fast path
laya.load("convaiinnovations/laya", compile=True)              # torch.compile the model

model_id_or_path 也接受 checkpoint 名稱或別名 —— 與 Router 解析的是同一批,所以兩個入口讀的是同一張表:

laya.load("typed-decisions")
laya.load("ml")                                               # multilingual

其它任何東西(Hub 倉庫 id、本地目錄)都會原樣傳給 Agent。

backend 選擇 "auto"、"eager"、"compile"、"tilelang" 或 "onnx"。ONNX 會返回現有的 ONNXAgent,帶 onnx_path(預設 "laya.onnx")。其它後端用 Agent;顯式的 backend 優先順序高於那些舊標誌。

revision/expected_sha256 會固定並校驗下載下來的產物;見 Agent。hooks / on_predict_start / on_predict_end 觀察或塑造每一次預測;見 laya.hooks。calibration 就是 Agent 接受的那個可選 JSON 路徑。

參數

model_id_or_pathstr= "convaiinnovations/laya"
deviceOptional[str]= None
tokenOptional[str]= None
subfolderOptional[str]= None
fastbool= False
compilebool= False
revisionOptional[str]= None
expected_sha256Optional[Dict[str, str]]= None
lang_temperaturesOptional[Dict[str, Dict[str, Any]]]= None
hooks= None
on_predict_start= None
on_predict_end= None
hooks_raisebool= True
hooks_concurrentbool= True
hooks_timeoutOptional[float]= None
calibrationOptional[str]= None
backendOptional[str]= None
onnx_pathOptional[str]= None
compile_warmupbool= True
compile_cachebool= False
compile_modestr= "default"

ONNXAgent

ONNXAgent(
    model_id_or_path: str,
    onnx_path: str = "laya.onnx",
    token: Optional[str] = None,
    subfolder: Optional[str] = None,
    revision: Optional[str] = None,
    expected_sha256: Optional[Dict[str, str]] = None,
    hooks=None,
    on_predict_start=None,
    on_predict_end=None,
    hooks_raise: bool = True,
    hooks_concurrent: bool = True,
    hooks_timeout: Optional[float] = None,
    lang_temperatures: Optional[Dict[str, Dict[str, Any]]] = None,
    calibration: Optional[str] = None,
)

基類: HookRegistry

通過 ONNX 執行的 System 1 決策模型:針對 CPU 最佳化的快速決策。

載入一個由 ONNX Runtime 支撐的 Laya agent。

參數

model_id_or_pathstr

HuggingFace Hub ID,或原始 PyTorch checkpoint 的本地路徑(用來載入分詞器與配置)。

onnx_pathstr= "laya.onnx"

匯出的 .onnx 檔案的路徑。

tokenOptional[str]= None

私有或受限 checkpoint 用的可選 HuggingFace token;不給時退回 $HF_TOKEN,與 Agent 完全一致。只會去取分詞器與配置 —— 計算圖本身就是本地的 onnx_path。

subfolderOptional[str]= None

從捆綁倉庫下載時的可選子目錄。

revisionOptional[str]= None

可選的 Hub 版本(commit SHA/分支/tag)。不給時,用 huggingface_hub 的常規預設值和已有的離線快取。

expected_sha256Optional[Dict[str, str]]= None

可選的 {相對 checkpoint 目錄的路徑: 十六進位制摘要},在任何 checkpoint 檔案被解析之前校驗;它是可選的,對本地目錄同樣生效。產物缺失會拋 FileNotFoundError,摘要不匹配會拋 ValueError;兩者都會拒絕這次載入。

hooksHookArg= None

可選的預測鉤子;見 laya.hooks。

on_predict_startPredictHookArg= None

可選的起始鉤子,在推理之前執行。

on_predict_endPredictHookArg= None

可選的結束鉤子,在推理之後執行。

hooks_raisebool= True

為 False 時,鉤子失敗只警告,推理繼續。

hooks_concurrentbool= True

為 False 時,鉤子用鎖序列化。

hooks_timeoutOptional[float]= None

以秒為單位限制每次鉤子呼叫;None 表示不限制。

lang_temperaturesOptional[Dict[str, Dict[str, Any]]]= None

可選的按語言溫度覆蓋,按語言程式碼索引,每項是 {"temperature": [3 floats], "temperature_by_options": {}}。當 system_one/predict 收到 lang= 時應用,與 PyTorch 的 Agent 對齊;否則跨後端切換會丟掉校準。

calibrationOptional[str]= None

load_calibration

load_calibration(path: str) -> None

把 save_calibration 寫出的 JSON 對映讀進這個 agent。

參數

pathstr

system_one

system_one(
    state: Union[str, dict, list],
    questions: Dict[str, Dict[str, Any]],
    lang: Optional[str] = None,
    hooks=None,
    on_predict_start=None,
    on_predict_end=None,
    hooks_raise: Optional[bool] = None,
    hooks_timeout: Optional[float] = None,
    max_len: Optional[int] = None,
    head_max_len: Optional[int] = None,
    min_confidence: Optional[float] = None,
) -> Dict[str, Any]

在一次 ONNX Runtime 會話執行裡,對狀態評估一組型別化問題。

lang 選擇按語言的溫度覆蓋(見 lang_temperatures),與 PyTorch Agent.system_one 的簽名一致,因此兩個後端可以互換使用。

它是基於 predict_batch 定義的,與 PyTorch 的 Agent.system_one 完全一樣,這樣單狀態路徑與批次路徑就不會各自漂移。

參數

stateUnion[str, dict, list]

文本字串、JSON 字典或對話輪次列表。

questionsDict[str, Dict[str, Any]]

問題定義,形狀與 Agent.system_one 接受的一致。

langOptional[str]= None

按語言的溫度覆蓋(見 lang_temperatures)。

hooksHookArg= None

每次呼叫的鉤子,追加在 agent 上已安裝的鉤子之後。

on_predict_startPredictHookArg= None

每次呼叫的起始鉤子。它可以改寫狀態/問題,或呼叫 ctx.skip(...) 短路推理。

on_predict_endPredictHookArg= None

每次呼叫的結束鉤子。它可以改寫結果。

hooks_raiseOptional[bool]= None

覆蓋本次呼叫中 agent 的 hooks_raise。

hooks_timeoutOptional[float]= None

覆蓋本次呼叫中 agent 的 hooks_timeout。

max_lenOptional[int]= None

覆蓋本次呼叫中配置的 max_len。

head_max_lenOptional[int]= None

覆蓋本次呼叫中配置的 head_max_len。

min_confidenceOptional[float]= None

可選的棄權閾值,作用在 answer_confidence 上(#361);低於它的答案會帶上 low_confidence: True 返回。

回傳值

含答案、機率、校準後的置信度與 token 用量的字典。

要一次性給很多狀態打分,見 predict_batch,它讓這些狀態共用會話執行。

predict_batch

predict_batch(
    states: List[Union[str, dict, list]],
    questions: Dict[str, Dict[str, Any]],
    batch_size: Optional[int] = None,
    lang: Optional[str] = None,
    hooks=None,
    on_predict_start=None,
    on_predict_end=None,
    hooks_raise: Optional[bool] = None,
    hooks_timeout: Optional[float] = None,
    max_len: Optional[int] = None,
    head_max_len: Optional[int] = None,
    sort_by_length: bool = False,
    min_confidence: Optional[float] = None,
) -> List[Dict[str, Any]]

對多個狀態評估同一組問題,共用 ONNX Runtime 的會話執行。

這是吞吐路徑,與 laya.agent.Agent.predict_batch 對應:system_one 每次會話執行只歸併一個狀態的問題行,所以 N 個狀態要 N 次執行。predict_batch 把多個狀態的行歸併進一次執行 —— 或 ceil(len(states) / batch_size) 次 —— 這正是 ONNX Runtime 自身的並行在 CPU 上發揮價值的地方。

參數

statesList[Union[str, dict, list]]

狀態列表(每一項是文本字串、JSON 字典或對話輪次列表)。同一組 questions 會對照每一個狀態評估。

questionsDict[str, Dict[str, Any]]

問題定義,與 system_one 接受的完全一致。

batch_sizeOptional[int]= None

每次會話執行中狀態數的可選上限。None 表示一次全發;批次處理很多或很長的狀態時,設上它可以給峰值記憶體封頂。

langOptional[str]= None

應用到每一個狀態的按語言溫度覆蓋;見 lang_temperatures。

hooksHookArg= None

每次呼叫的鉤子,追加在 agent 上已安裝的鉤子之後。

on_predict_startPredictHookArg= None

每次呼叫的起始鉤子。它可以改寫狀態/問題,或呼叫 ctx.skip(...) 短路推理。

on_predict_endPredictHookArg= None

每次呼叫的結束鉤子。它可以改寫結果。

hooks_raiseOptional[bool]= None

覆蓋本次呼叫中 agent 的 hooks_raise。

hooks_timeoutOptional[float]= None

覆蓋本次呼叫中 agent 的 hooks_timeout。

max_lenOptional[int]= None

覆蓋本次呼叫中配置的 max_len。

head_max_lenOptional[int]= None

覆蓋本次呼叫中配置的 head_max_len。

sort_by_lengthbool= False

把編碼後長度相近的狀態按「八個批次」為一組歸到一起以減少 padding,與 Agent.predict_batch 完全一樣。需要顯式給出大於 1、且小於狀態數的 batch_size;否則沒有任何效果。結果保持輸入順序。改變批次形狀可能讓決策閾值附近的浮點預測結果輕微變化。

min_confidenceOptional[float]= None

可選的棄權閾值,作用在 answer_confidence 上(#361);低於它的答案會帶上 low_confidence: True 返回。

回傳值

每個狀態一個結果字典的列表,形狀與 system_one 的輸出完全相同,並按下標與 states 對齊。

predict_long

predict_long(
    state: Union[str, dict, list],
    questions: Dict[str, Dict[str, Any]],
    window: Optional[int] = None,
    stride: Optional[int] = None,
    aggregate: str = "auto",
    batch_size: Optional[int] = None,
    lang: Optional[str] = None,
    hooks=None,
    on_predict_start=None,
    on_predict_end=None,
    hooks_raise: Optional[bool] = None,
    hooks_timeout: Optional[float] = None,
) -> Dict[str, Any]

對超出上下文視窗的狀態評估問題:用互相重疊的視窗掃描它,並按問題聚合。

這是 laya.agent.Agent.predict_long 的 ONNX 版本,聚合規則相同:system_one 會把超出 max_len 的狀態截斷到一個視窗,其餘部分被靜默丟棄。predict_long 只把狀態分詞一次,切成互相重疊的 token 視窗,通過 predict_batch 給每個視窗打分 —— 於是這些視窗共用 ONNX Runtime 的會話執行,而不是各付一次 —— 再把各視窗的答案合併起來:

  • noul -> P(true) 取各視窗的最大值(只要有一個視窗支援,該陳述就成立)
  • choice-> 取單個最自信視窗的答案,這樣區域性訊號不會被長文件裡佔絕大多數的中性視窗投票壓過去
  • score -> 同樣取最自信視窗的檔位

返回的機率/置信度是作出決定的那個視窗的,不是針對整篇文件校準過的數字,理由與 PyTorch 那邊的說明相同。每個答案都帶著 answer["window"] —— 作出決定的視窗的 index、在分詞後狀態中的 token_start/token_end,以及視窗總數 count。

已經裝得進一個視窗的狀態會直接交給 system_one(輸出完全相同)。

參數

stateUnion[str, dict, list]

文本字串、JSON 字典或對話輪次列表。

questionsDict[str, Dict[str, Any]]

問題定義,與 system_one 接受的完全一致。

windowOptional[int]= None

每個視窗容納的狀態 token 數。預設取按問題計的狀態預算(max_len - head_max_len - 8)。與 Agent.predict_long 一樣,視窗更小能更好地隔離區域性訊號,代價是視窗數更多。

strideOptional[int]= None

視窗之間的 token 步長。預設是 window // 2(50% 重疊)。

aggregatestr= "auto"

"auto"(即上面那套按型別的規則)是目前唯一的模式。

batch_sizeOptional[int]= None

每次會話執行的視窗數上限,用來給超長狀態的記憶體用量封頂。

langOptional[str]= None

按語言選擇溫度,與 system_one 一致。

hooksHookArg= None

每次呼叫的鉤子,追加在 agent 上已安裝的鉤子之後。它們遵循 Agent.predict_long 的約定:包住為狀態作答的那次推理;直接作答的起始鉤子(ctx.skip(...))會得到 usage["windows"] == 0 且沒有視窗歸屬資訊;被改寫過的掃描在聚合時不帶 answer["window"]。

on_predict_startPredictHookArg= None

每次呼叫的起始鉤子,與 system_one 一致。

on_predict_endPredictHookArg= None

每次呼叫的結束鉤子,與 system_one 一致。

hooks_raiseOptional[bool]= None

覆蓋本次呼叫中 agent 的 hooks_raise。

hooks_timeoutOptional[float]= None

覆蓋本次呼叫中 agent 的 hooks_timeout。

返回單個結果字典,形狀與 system_one 相同,並加上 usage["windows"]。跨多個視窗時,截斷相關的鍵與 Agent.predict_long 中的合併方式相同:truncated 是視窗數,truncated_questions 是最後一個視窗的列表,所以 truncated 大於 0 而列表為空是可能的。

decide

decide(
    state: Union[str, dict, list],
    schema: Any = None,
    questions: Optional[Dict[str, Dict[str, Any]]] = None,
    return_details: bool = False,
    min_confidence: Optional[float] = None,
    predict_kwargs,
) -> Any

把 state 對照一個 schema(JSON schema 或 pydantic 模型)作答,返回型別化的值。

見 laya.structured。schema 與 questions 只能給一個;額外的關鍵字參數會透傳給 predict / system_one。

參數

stateUnion[str, dict, list]
schemaAny= None
questionsOptional[Dict[str, Dict[str, Any]]]= None
return_detailsbool= False
min_confidenceOptional[float]= None
predict_kwargs

decide_batch

decide_batch(
    states: List[Union[str, dict, list]],
    schema: Any = None,
    questions: Optional[Dict[str, Dict[str, Any]]] = None,
    return_details: bool = False,
    min_confidence: Optional[float] = None,
    predict_kwargs,
) -> List[Any]

通過 predict_batch 把多個狀態對照同一個 schema 作答;見 laya.structured。

參數

statesList[Union[str, dict, list]]
schemaAny= None
questionsOptional[Dict[str, Dict[str, Any]]]= None
return_detailsbool= False
min_confidenceOptional[float]= None
predict_kwargs

量化匯出

scripts/export_onnx.py --quantize 會在 fp32 匯出的旁邊寫出一份 INT8 僅權重量化的副本 (laya.onnx 也會生成 laya.int8.onnx)。動態量化把 MatMul 權重轉成 int8,啟用的 scale 在執行時按每個輸入現算,所以不需要校準資料集;ONNXAgent 只要把 onnx_path 指向它就能載入 結果。在 CPU 上它比 eager 模型快約 2 倍,比 fp32 ONNX 圖快約 1.8 倍,體積則依 checkpoint 不同小 1.4-2.8 倍。

INT8 犧牲的是實打實的精度,所以它是體積/延遲上的取捨,不是免費的 —— 在校準過的機率或置信度 要緊的場合不要用它。scale 預設是逐張量的;--per-channel 可以改用逐通道權重,但在動態 路徑上這會讓決策模型崩掉(與 eager 模型的一致率在英文 checkpoint 上跌到約 32%、在多語言 checkpoint 上跌到約 40%,而逐張量分別約為 67% / 83%;見 issue #790)。即便逐張量,在較大的 checkpoint 上也有明顯漂移;精度安全的 int8 需要 QAT 或 SmoothQuant 式的離群值處理。int8 圖只能 跑在 CPU 上:ONNX Runtime 在 CUDAExecutionProvider 上沒有 INT8 MatMul 核心,GPU provider 會 逐節點靜默回退。

python scripts/export_onnx.py --model convaiinnovations/laya --output laya.onnx --quantize