以下是對“理解 Token 索引與字符位置的區別”的內容整理,條理清晰,結構完整,保持技術細節,方便閱讀,無多余解釋:
🔍 理解 Token 索引 vs 字符位置
文本分塊方法中返回的索引是 token 索引,而不是原始文本中的字符位置。理解這一點對正確使用和調試文本處理流程至關重要。
📄 原始文本與 Tokenization 的區別
示例文本
"人工智能正在改變世界。"
字符位置(原始文本)
字符 | 人 | 工 | 智 | 能 | 正 | 在 | 改 | 變 | 世 | 界 | 。 |
---|---|---|---|---|---|---|---|---|---|---|---|
位置 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
Token 位置(tokenizer 處理后)
Tokens = ["人", "工", "智", "能", "正", "在", "改", "變", "世", "界", "。"]
索引 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
🔢 各分塊方法的返回值示例
1?? 語義分塊(chunk_semantically)
text = "人工智能正在改變世界。它使得許多任務自動化。"
Tokenizer 分詞結果:
Tokens = ["人", "工", "智", "能", "正", "在", "改", "變", "世", "界", "。","它", "使", "得", "許", "多", "任", "務", "自", "動", "化", "。"]
索引 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
假設返回值為:
[(0, 11), (11, 22)]
表示:
- 第1塊:token索引 0-10,“人工智能正在改變世界。”
- 第2塊:token索引 11-21,“它使得許多任務自動化。”
2?? 固定大小分塊(chunk_by_tokens)
text = "人工智能正在改變世界。它使得許多任務自動化。"
chunk_size = 5
返回值示例:
[(0, 5), (5, 10), (10, 15), (15, 20), (20, 22)]
表示:
- 第1塊:token索引 0-4,“人工智能正在”
- 第2塊:token索引 5-9,“改變世界。”
- 第3塊:token索引 10-14,“它使得許多”
- 第4塊:token索引 15-19,“任務自動化”
- 第5塊:token索引 20-21,“。”
3?? 按句子分塊(chunk_by_sentences)
text = "人工智能正在改變世界。它使得許多任務自動化。我們需要適應這些變化。"
Tokenizer 分詞結果假設為:
句子1:"人工智能正在改變世界。" → token索引 0~10
句子2:"它使得許多任務自動化。" → token索引 11~21
句子3:"我們需要適應這些變化。" → token索引 22~33
設置每個塊 1 個句子,返回值:
[(0, 11), (11, 22), (22, 34)]
? 為什么返回 token 索引?
原因 | 說明 |
---|---|
? NLP 模型處理的是 token | 模型輸入必須是 token 序列,不能直接處理原始字符 |
? 精確控制長度 | Token 數量直接決定能否通過模型輸入限制(如 BERT 的 512 token) |
? 對齊后續處理流程 | 向量化、分塊拼接、交叉注意力等操作都基于 token 索引進行 |
🔁 實際代碼中的字符位置 → Token 索引映射
部分關鍵轉換流程如下:
# 從 splitter 獲取字符級位置
nodes = [(node.start_char_idx, node.end_char_idx)for node in self.splitter.get_nodes_from_documents(...)
]# token_offsets 是 tokenizer 返回的每個 token 的字符起止位置
start_chunk_index = bisect.bisect_left([offset[0] for offset in token_offsets], char_start
)
end_chunk_index = bisect.bisect_right([offset[1] for offset in token_offsets], char_end
)
最終輸出的 (start_chunk_index, end_chunk_index)
就是基于 tokenizer 的 token 索引范圍。