|
26 | 26 | read_sequence, |
27 | 27 | ) |
28 | 28 | from fairseq2.data.text.tokenizers import TextTokenizer |
| 29 | +from fairseq2.data.text.tokenizers.hg import HuggingFaceTokenEncoder |
29 | 30 | from fairseq2.datasets import ( |
30 | 31 | DataPipelineReader, |
31 | 32 | DataReader, |
@@ -56,6 +57,8 @@ class InstructionReadOptions(DataReadOptions): |
56 | 57 | target_encode_mode: str = "prompt_response" |
57 | 58 | """The tokenizer mode to encode the target text.""" |
58 | 59 |
|
| 60 | + chat_mode: bool = False |
| 61 | + |
59 | 62 |
|
60 | 63 | @dataclass |
61 | 64 | class InstructionPromptReadOptions(DataReadOptions): |
@@ -230,26 +233,55 @@ def create_reader( |
230 | 233 |
|
231 | 234 | seed += gang.rank |
232 | 235 |
|
233 | | - # Encode source and target texts. |
234 | | - source_encoder = tokenizer.create_encoder(mode=options.source_encode_mode) |
235 | | - target_encoder = tokenizer.create_encoder(mode=options.target_encode_mode) |
| 236 | + if options.chat_mode is True: |
| 237 | + # not passing any encoding modes here, because we use apply_chat_template here |
| 238 | + encoder = tokenizer.create_encoder() |
| 239 | + if not isinstance(encoder, HuggingFaceTokenEncoder): |
| 240 | + raise RuntimeError( |
| 241 | + "Huggingface tokenizer must be used when chat_mode is True" |
| 242 | + ) |
| 243 | + else: |
236 | 244 |
|
237 | | - builder.map(source_encoder, selector="src") |
238 | | - builder.map(target_encoder, selector="tgt") |
| 245 | + def encoding_chat(example: dict[str, Any]) -> dict[str, Any]: |
| 246 | + id_ = example.get("id") |
| 247 | + chat = example.get("chat") |
239 | 248 |
|
240 | | - def cat_source_and_target(example: dict[str, Any]) -> dict[str, Any]: |
241 | | - id_ = example.get("id") |
| 249 | + encoded_output = encoder.apply_chat_template( |
| 250 | + chat, |
| 251 | + return_dict=True, |
| 252 | + return_assistant_tokens_mask=True, |
| 253 | + return_tensors="pt", |
| 254 | + ) |
242 | 255 |
|
243 | | - source_indices = example["src"] |
244 | | - target_indices = example["tgt"] |
| 256 | + indices = encoded_output["input_ids"][0] |
| 257 | + target_mask = encoded_output["assistant_masks"][0].bool() |
| 258 | + |
| 259 | + return {"id": id_, "indices": indices, "target_mask": target_mask} |
| 260 | + |
| 261 | + builder.map(encoding_chat) |
| 262 | + |
| 263 | + else: |
245 | 264 |
|
246 | | - indices = torch.cat([source_indices, target_indices]) |
| 265 | + # Encode source and target texts. |
| 266 | + source_encoder = tokenizer.create_encoder(mode=options.source_encode_mode) |
| 267 | + target_encoder = tokenizer.create_encoder(mode=options.target_encode_mode) |
247 | 268 |
|
248 | | - target_mask = torch.arange(len(indices)) >= len(source_indices) |
| 269 | + builder.map(source_encoder, selector="src") |
| 270 | + builder.map(target_encoder, selector="tgt") |
249 | 271 |
|
250 | | - return {"id": id_, "indices": indices, "target_mask": target_mask} |
| 272 | + def cat_source_and_target(example: dict[str, Any]) -> dict[str, Any]: |
| 273 | + id_ = example.get("id") |
251 | 274 |
|
252 | | - builder.map(cat_source_and_target) |
| 275 | + source_indices = example["src"] |
| 276 | + target_indices = example["tgt"] |
| 277 | + |
| 278 | + indices = torch.cat([source_indices, target_indices]) |
| 279 | + |
| 280 | + target_mask = torch.arange(len(indices)) >= len(source_indices) |
| 281 | + |
| 282 | + return {"id": id_, "indices": indices, "target_mask": target_mask} |
| 283 | + |
| 284 | + builder.map(cat_source_and_target) |
253 | 285 |
|
254 | 286 | batching = options.batching |
255 | 287 |
|
@@ -312,11 +344,7 @@ def to_batch(example: dict[str, Any]) -> SequenceBatch: |
312 | 344 |
|
313 | 345 | seqs, seq_lens = indices["seqs"], indices["seq_lens"] |
314 | 346 |
|
315 | | - target_mask = example["target_mask"]["seqs"] |
316 | | - |
317 | | - return SequenceBatch( |
318 | | - seqs, seq_lens, target_mask=target_mask, example=example |
319 | | - ) |
| 347 | + return SequenceBatch(seqs, seq_lens, example=example) |
320 | 348 |
|
321 | 349 | pipeline = builder.map(to_batch).and_return() |
322 | 350 |
|
|
0 commit comments