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]=NonetokenOptional[str]=NonesubfolderOptional[str]=Nonefastbool=Falsecompilebool=FalserevisionOptional[str]=Noneexpected_sha256Optional[Dict[str, str]]=Nonelang_temperaturesOptional[Dict[str, Dict[str, Any]]]=Nonehooks=Noneon_predict_start=Noneon_predict_end=Nonehooks_raisebool=Truehooks_concurrentbool=Truehooks_timeoutOptional[float]=NonecalibrationOptional[str]=NonebackendOptional[str]=Nonecompile_warmupbool=Truecompile_cachebool=Falsecompile_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=Falseoptions
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=Truestrictbool=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]=NonehooksHookArg=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]=Nonehooks=Noneon_predict_start=Noneon_predict_end=Nonehooks_raiseOptional[bool]=Nonehooks_timeoutOptional[float]=Nonemax_lenOptional[int]=Nonehead_max_lenOptional[int]=Nonemin_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=NonequestionsOptional[Dict[str, Any]]=Nonereturn_detailsbool=Falsemin_confidenceOptional[float]=Nonepredict_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=NonequestionsOptional[Dict[str, Any]]=Nonereturn_detailsbool=Falsemin_confidenceOptional[float]=Nonepredict_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 保持載入時的樣子。
參數
recordscompute_ecebool=Falseseedint=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。
參數
recordsmin_bucket_nint=MIN_BINNING_BUCKET_NMIN_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]=NonetokenOptional[str]=NonesubfolderOptional[str]=Nonefastbool=Falsecompilebool=FalserevisionOptional[str]=Noneexpected_sha256Optional[Dict[str, str]]=Nonelang_temperaturesOptional[Dict[str, Dict[str, Any]]]=Nonehooks=Noneon_predict_start=Noneon_predict_end=Nonehooks_raisebool=Truehooks_concurrentbool=Truehooks_timeoutOptional[float]=NonecalibrationOptional[str]=NonebackendOptional[str]=Noneonnx_pathOptional[str]=Nonecompile_warmupbool=Truecompile_cachebool=Falsecompile_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_pathstrHuggingFace 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=NonequestionsOptional[Dict[str, Dict[str, Any]]]=Nonereturn_detailsbool=Falsemin_confidenceOptional[float]=Nonepredict_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=NonequestionsOptional[Dict[str, Dict[str, Any]]]=Nonereturn_detailsbool=Falsemin_confidenceOptional[float]=Nonepredict_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