LLama分词用的BPE,把我坑惨了
构建 hash_dict 时:
- 直接 tokenize
"### Response:\n<SID>"
### 在句首,被编码为单个 token 835
模型输入 prompt 中:
"### Response:\n" 前面有其他内容(\n\n)
### 被编码为 [2277, 29937](即 ## + #)
tokenizer.decode([835]) → '###' (单独编码)
tokenizer.decode([2277]) → '##'
tokenizer.decode([29937]) → '#'
tokenizer.decode([2277, 29937]) → '###' (上下文中编码)
根本原因
LLaMA tokenizer (SentencePiece/BPE) 会根据上下文决定如何分词:
| 场景 |
### Response:\n 的编码 |
| 作为字符串开头 (hash_dict 构建) |
[835, 13291, 29901, 13] |
| 在 prompt 中间 (模型输入) |
[2277, 29937, 13291, 29901, 13] |
所以 hash_dict 的第一个 key 是 [835, 13291, 29901],但模型实际生成时根本不会出现 835 这个 token,而是 [2277, 29937, 13291, 29901]!
解决方案
应该用完整 prompt 的上下文来构建 hash_dict 的 key,而不是单独 tokenize "### Response:\n<SID>"。
需要修改 evaluate.py 中构建 info_semantic 和 tokenize 的方式,确保和模型输入的 tokenize 方式一致。
LLama分词用的BPE,把我坑惨了
构建 hash_dict 时:
"### Response:\n<SID>"###在句首,被编码为单个 token835模型输入 prompt 中:
"### Response:\n"前面有其他内容(\n\n)###被编码为[2277, 29937](即##+#)根本原因
LLaMA tokenizer (SentencePiece/BPE) 会根据上下文决定如何分词:
### Response:\n的编码[835, 13291, 29901, 13][2277, 29937, 13291, 29901, 13]所以 hash_dict 的第一个 key 是
[835, 13291, 29901],但模型实际生成时根本不会出现835这个 token,而是[2277, 29937, 13291, 29901]!解决方案
应该用完整 prompt 的上下文来构建 hash_dict 的 key,而不是单独 tokenize
"### Response:\n<SID>"。需要修改
evaluate.py中构建info_semantic和 tokenize 的方式,确保和模型输入的 tokenize 方式一致。