跳至主要內容

文字分詞器模組

文字分詞器模組負責把字串轉換成模型可用的 token ID 序列。
這層只做分詞、編碼與反向解碼,不負責模型推理。典型流程是先把文字編碼成 MLMultiArrayonnxruntime.tensor,再把編碼結果傳給對應的 CoreML 或 ONNX Runtime 推理器。

目前這套模組的目標是“端側推理夠用”:

  • WordPiece 兼容度最高,適合 BERTCN-CLIP 一類模型
  • BPESentencePiece 採用輕量兼容策略,適合多數端側編碼場景
  • 不把複雜分詞器訓練、採樣或完整上游生態行為搬到運行時里

該模組在 20260319 以後版本方可使用

建立分詞器

coreml.new_text_tokenizer(opts)

文字分詞器物件, 錯誤資訊 = coreml.new_text_tokenizer({
type = 分詞器類型,
vocab_path = 詞表路徑,
merges_path = merges 檔案路徑,
model_path = SentencePiece 模型路徑,
pattern = 正則表達式,
context_length = 上下文長度,
do_lower_case = 是否轉小寫,
vocab_limit = 詞表上限,
clean_text = 是否先清洗文字,
add_bos = 是否添加起始 token,
add_eos = 是否添加結束 token,
bos_token = 起始 token 文字,
eos_token = 結束 token 文字,
pad_token = 填充 token 文字,
unk_token = 未知 token 文字,
})

type 取值

  • wordpiece / bert / cn_clip
  • bpe / gpt2_bpe / clip_bpe
  • sentencepiece / spm
  • regex / pattern
  • byte / bytes
  • whitespace / space
  • character / char

預設 wordpiece

如果 coreml.new_text_tokenizer(...) 的第一個參數不是 table,會直接按 wordpiece 快捷構造處理,也就是等價於 coreml.new_wordpiece_tokenizer(vocab_path) 這類用法。

常用參數

  • vocab_path
    文字型,詞表檔案路徑。

  • merges_path
    文字型,BPE 系分詞器使用的 merges 檔案路徑。

  • model_path
    文字型,SentencePiece 兼容模式可使用的 .model 檔案路徑。

  • pattern
    文字型,Regex 分詞器使用的正則表達式。

  • context_length
    整數型,可選參數,輸出 token 序列長度。

  • do_lower_case
    布林型,可選參數,是否先轉小寫。

  • vocab_limit
    整數型,可選參數,僅 WordPiece 常用,用於限制詞表上限。

  • clean_text
    布林型,可選參數,是否在分詞前先做基礎文字清洗。

  • add_bos / add_eos
    布林型,可選參數,是否在編碼結果前後附加起始 / 結束 token。

  • bos_token / eos_token / pad_token / unk_token
    文字型,可選參數,對應特殊 token 在詞表中的文字。

不是所有分詞器類型都支援上面所有字段。目前實現的必填項與預設值如下:

  • wordpiece 支援直接傳 vocab_path 字串,或傳 table;要求 vocab_path 存在;預設 context_length = 52do_lower_case = truevocab_limit = 21128,並要求詞表裡存在 [PAD][UNK][CLS][SEP]
  • bpe 只接受 table;要求 vocab_pathmerges_path;預設 context_length = 77do_lower_case = falseclean_text = falseadd_bos = falseadd_eos = false
  • sentencepiece 只接受 table;要求 vocab_pathmodel_path 至少一個;預設 context_length = 77do_lower_case = falseclean_text = truebos_token = "<s>"eos_token = "</s>"pad_token = "<pad>"unk_token = "<unk>"
  • regex 只接受 table;要求 vocab_pathpattern;預設 context_length = 77do_lower_case = falseclean_text = true
  • whitespace / character / byte 只接受 table;要求 vocab_path;預設 context_length = 77do_lower_case = falseclean_text = true

選擇建議:

  • 已知模型使用 vocab.txt + WordPiece,就選 wordpiece
  • 已知模型使用 vocab.json + merges.txt,就選 bpe
  • 已知模型使用 .vocab.model,就選 sentencepiece
  • 只有簡單規則切詞需求時,再考慮 regexwhitespacecharacterbyte

回傳值

  • 文字分詞器物件
    物件型,建立失敗返回 nil

  • 錯誤資訊
    文字型,成功時為 nil,失敗時返回錯誤資訊。

說明

  • 分詞器物件適合建立一次後復用,不建議每次編碼都重新構造
  • 建立階段主要決定三件事:分詞演算法、詞表來源、固定輸出長度
  • 如果模型效果明顯不對,優先檢查分詞器類型、詞表檔案、special token 設定和 context_length 是否與訓練時一致
  • WordPiece 是目前最完整、最穩的一類
  • BPESentencePiece 以端側編碼兼容為目標,不承諾復刻所有上游實現的全部細節

快捷構造器

以下快捷函式本質上都是對 coreml.new_text_tokenizer(...) 的轉發,適合在你已經確定分詞器類型時直接使用。

coreml.new_wordpiece_tokenizer(opts)

  • 等價於 coreml.new_text_tokenizer({ type = "wordpiece", ... })
  • 適合 BERTCN-CLIPWordPiece 風格文字模型
  • 也支援直接傳詞表路徑字串:coreml.new_wordpiece_tokenizer(vocab_path)

coreml.new_bpe_tokenizer(opts)

  • 等價於 coreml.new_text_tokenizer({ type = "bpe", ... })
  • 同時覆蓋 gpt2_bpeclip_bpe 一類 vocab.json + merges.txt 模型

coreml.new_sentencepiece_tokenizer(opts)

  • 等價於 coreml.new_text_tokenizer({ type = "sentencepiece", ... })
  • 使用面向端側推理的輕量兼容實現
  • 支援 .vocab.model

coreml.new_regex_tokenizer(opts)

  • 等價於 coreml.new_text_tokenizer({ type = "regex", ... })
  • 適合基於規則切詞和簡單詞表映射的場景

coreml.new_byte_tokenizer(opts)

  • 等價於 coreml.new_text_tokenizer({ type = "byte", ... })
  • 會先把文字轉成 UTF-8 位元組流,再按位元組查詞表

coreml.new_whitespace_tokenizer(opts)

  • 等價於 coreml.new_text_tokenizer({ type = "whitespace", ... })
  • 適合空格切詞、詞表直查的輕量文字模型

coreml.new_character_tokenizer(opts)

  • 等價於 coreml.new_text_tokenizer({ type = "character", ... })
  • 適合字元級文字模型

類型判斷

coreml.is_text_tokenizer(value)

是否文字分詞器 = coreml.is_text_tokenizer(需要判斷的值)

用於判斷一個值是否為 coreml_text_tokenizer_object

物件方法

:encode(text[, opts])

編碼結果, 錯誤資訊 = 文字分詞器物件:encode(文字)

編碼結果, 錯誤資訊 = 文字分詞器物件:encode(文字, {
output = "table""MLMultiArray""ort_tensor",
data_type = 資料類型,
pair_text = 配對文字,
max_length = 最大長度,
padding = 填充策略,
truncation = 截斷策略,
return_attention_mask = 是否返回 attention mask,
return_token_type_ids = 是否返回 token type ids,
return_special_tokens_mask = 是否返回 special tokens mask,
})

把單個文字編碼成 token 序列。

:encode_batch(texts[, opts])

編碼結果, 錯誤資訊 = 文字分詞器物件:encode_batch(文字陣列)

編碼結果, 錯誤資訊 = 文字分詞器物件:encode_batch(文字陣列, {
output = "table""MLMultiArray""ort_tensor",
data_type = 資料類型,
pair_text = 配對文字或配對文字陣列,
max_length = 最大長度,
padding = 填充策略,
truncation = 截斷策略,
return_attention_mask = 是否返回 attention mask,
return_token_type_ids = 是否返回 token type ids,
return_special_tokens_mask = 是否返回 special tokens mask,
})

一次編碼多個文字,返回 batch 形式的 token 序列。

:decode(ids)

文字, 錯誤資訊 = 文字分詞器物件:decode(ids)

單條 token id 序列反向解碼成文字。

  • ids 可以是 Lua 陣列、MLMultiArray,或者 ORT tensor 之類的 tensor-like userdata
  • ids 也可以是任何實現了 shape()to_table() 的 tensor-like userdata
  • 如果傳入的是 batch 資料,會報錯並提示改用 decode_batch()

:decode_batch(batch_ids)

文字陣列, 錯誤資訊 = 文字分詞器物件:decode_batch(batch_ids)

把 batch token id 序列反向解碼成文字陣列。

  • batch_ids 可以是嵌套 Lua 陣列、MLMultiArray,或者 ORT tensor 之類的 tensor-like userdata
  • batch_ids 也可以是任何實現了 shape()to_table() 的 tensor-like userdata

:vocab_size()

詞表大小 = 文字分詞器物件:vocab_size()

返回目前分詞器可用詞表大小。

:context_length()

上下文長度 = 文字分詞器物件:context_length()

返回目前分詞器的固定輸出長度,也就是單次編碼會補齊或截斷到的長度。

編碼與返回說明

  • output 預設是 "MLMultiArray",適合直接餵給 CoreML 模型
  • output = "table" 適合偵錯、查看 token id,或兼容舊腳本
  • output = "ort_tensor" 適合直接餵給 ONNX Runtime 文字模型
  • output = "ort_tensor" 前必須先執行 require("onnxruntime"),這樣 ORT 橋接介面才會被注入
  • output = "ort_tensor" 依賴 ONNX Runtime,因此僅支援 iOS 13+
  • 為兼容舊腳本,字段 multi_array_output 仍會被讀取;但新代碼建議統一使用 output

data_type 規則

  • output = "MLMultiArray" 時,data_type 可選 "int32""float32""float16""double""float64" 可作為 "double" 的別名
  • output = "MLMultiArray" 時,預設 data_type = "int32"
  • output = "ort_tensor" 時,data_type 可選 "float16""float32""uint8""int8""int32""int64""double""bool"
  • output = "ort_tensor" 時,預設 data_type = "int64"

padding / truncation

  • padding 可以是布林值,也可以是字串
    • true 會映射到 "max_length"
    • false 會映射到 "do_not_pad"
  • truncation 可以是布林值,也可以是字串
    • true 會映射到 "longest_first"
    • false 會映射到 "do_not_truncate"

pair_text

  • encode() 里可以傳單個 pair_text
  • encode_batch() 里可以傳單個 pair_text,也可以傳與 batch 大小一致的字串陣列

結構化返回

當以下任一字段為 true 時,encode() / encode_batch() 會返回結構化結果表,而不只是裸 token 序列:

  • return_attention_mask
  • return_token_type_ids
  • return_special_tokens_mask

結構化結果常見字段:

  • input_ids
  • length
  • attention_mask
  • token_type_ids
  • special_tokens_mask

對 batch 編碼來說:

  • output = "table" 時,保留每條樣本自己的長度
  • output = "MLMultiArray" / "ort_tensor" 時,會把 batch 補齊成規則矩陣後再返回

範例

local tokenizer = assert(coreml.new_text_tokenizer({
type = "wordpiece",
vocab_path = XXT_HOME_PATH.."/models/demo/vocab.txt",
context_length = 52,
}))

local ids = assert(tokenizer:encode("星星", {
output = "MLMultiArray",
data_type = "int32",
}))

local structured = assert(tokenizer:encode("星星", {
output = "table",
return_attention_mask = true,
return_token_type_ids = true,
}))

local ort = require("onnxruntime")

local input_ids = assert(tokenizer:encode("星星", {
output = "ort_tensor",
data_type = "int64",
}))

local batch = assert(tokenizer:encode_batch({
"星星",
"月亮",
}, {
output = "ort_tensor",
}))

print(tokenizer:decode(structured.input_ids))
print(tokenizer:vocab_size())
print(tokenizer:context_length())