SFT dataset that uses user interaction history and preferences from preference file. Args: user_preference_file: Path to JSON file with user preferences (format: {"user": "user_id", "user_preference": ["pref text", ...]}) index_file: Path to .index.j
(self, user_preference_file, index_file, tokenizer, max_len=2048, sample=-1, test=False, seed=0, category="", dedup=False)
| 1447 | |
| 1448 | class PreferenceSFTDataset(BaseDataset): |
| 1449 | def __init__(self, user_preference_file, index_file, tokenizer, max_len=2048, sample=-1, test=False, seed=0, category="", dedup=False): |
| 1450 | """ |
| 1451 | SFT dataset that uses user interaction history and preferences from preference file. |
| 1452 | |
| 1453 | Args: |
| 1454 | user_preference_file: Path to JSON file with user preferences (format: {"user": "user_id", "user_preference": ["pref text", ...]}) |
| 1455 | index_file: Path to .index.json file mapping item_id to semantic IDs |
| 1456 | tokenizer: Tokenizer for encoding text |
| 1457 | max_len: Maximum sequence length |
| 1458 | sample: Number of samples to use (-1 for all) |
| 1459 | test: Whether this is test mode |
| 1460 | seed: Random seed |
| 1461 | category: Category name for prompts |
| 1462 | dedup: Whether to filter duplicate items |
| 1463 | """ |
| 1464 | super().__init__(tokenizer, max_len, test, category, dedup, seed) |
| 1465 | # Load user preferences - handle both JSON and JSONL formats |
| 1466 | with open(user_preference_file, 'r') as f: |
| 1467 | try: |
| 1468 | preference_data = json.load(f) |
| 1469 | except json.JSONDecodeError: |
| 1470 | # Try JSONL format (multiple JSON objects, one per line) |
| 1471 | f.seek(0) |
| 1472 | preference_data = [] |
| 1473 | for line in f: |
| 1474 | line = line.strip() |
| 1475 | if line: |
| 1476 | preference_data.append(json.loads(line)) |
| 1477 | |
| 1478 | # Handle new flat structure: each item is a separate training sample |
| 1479 | self.training_samples = [] |
| 1480 | |
| 1481 | for item in preference_data: |
| 1482 | if item.get('split') == 'train': # Only process train data |
| 1483 | user_id = item['user'] |
| 1484 | preference_text = item.get('user_preference', '') |
| 1485 | context = item.get('context', {}) |
| 1486 | history_items = context.get('history_items', []) |
| 1487 | target_item = context.get('target_item') |
| 1488 | |
| 1489 | # Create interaction history by combining history_items and target_item |
| 1490 | interaction_history = history_items + ([target_item] if target_item is not None else []) |
| 1491 | |
| 1492 | # Each item becomes a separate training sample |
| 1493 | self.training_samples.append({ |
| 1494 | 'user_id': user_id, |
| 1495 | 'preference_text': preference_text, |
| 1496 | 'interaction_history': interaction_history |
| 1497 | }) |
| 1498 | |
| 1499 | # Load index mapping |
| 1500 | with open(index_file, 'r') as f: |
| 1501 | self.indices = json.load(f) |
| 1502 | |
| 1503 | # Find users with preferences and prepare data |
| 1504 | self.data = self._prepare_preference_data() |
| 1505 | |
| 1506 | if sample > 0 and sample < len(self.data): |
nothing calls this directly
no test coverage detected