| 1627 | |
| 1628 | |
| 1629 | class UserPreference2sidSFTDataset(BaseDataset): |
| 1630 | def __init__(self, user_preference_file, index_file, tokenizer, max_len=2048, sample=-1, test=False, seed=0, category="", dedup=False): |
| 1631 | """ |
| 1632 | SFT dataset that uses user interaction history with preferences to predict next item's semantic ID. |
| 1633 | Uses interaction history from preference file, predicts the last item in the sequence. |
| 1634 | |
| 1635 | Args: |
| 1636 | user_preference_file: Path to JSON file with user preferences |
| 1637 | index_file: Path to .index.json file mapping item_id to semantic IDs |
| 1638 | tokenizer: Tokenizer for encoding text |
| 1639 | max_len: Maximum sequence length |
| 1640 | sample: Number of samples to use (-1 for all) |
| 1641 | test: Whether this is test mode |
| 1642 | seed: Random seed |
| 1643 | category: Category name for prompts |
| 1644 | dedup: Whether to filter duplicate items |
| 1645 | """ |
| 1646 | super().__init__(tokenizer, max_len, test, category, dedup, seed) |
| 1647 | |
| 1648 | # Load user preferences - handle both JSON and JSONL formats |
| 1649 | with open(user_preference_file, 'r') as f: |
| 1650 | try: |
| 1651 | preference_data = json.load(f) |
| 1652 | except json.JSONDecodeError: |
| 1653 | # Try JSONL format (multiple JSON objects, one per line) |
| 1654 | f.seek(0) |
| 1655 | preference_data = [] |
| 1656 | for line in f: |
| 1657 | line = line.strip() |
| 1658 | if line: |
| 1659 | preference_data.append(json.loads(line)) |
| 1660 | |
| 1661 | # Handle new flat structure: each item is a separate training sample |
| 1662 | self.training_samples = [] |
| 1663 | |
| 1664 | for item in preference_data: |
| 1665 | if item.get('split') == 'train': # Only process train data |
| 1666 | user_id = item['user'] |
| 1667 | preference_text = item.get('user_preference', '') |
| 1668 | context = item.get('context', {}) |
| 1669 | history_items = context.get('history_items', []) |
| 1670 | target_item = context.get('target_item') |
| 1671 | |
| 1672 | # Create interaction history by combining history_items and target_item |
| 1673 | interaction_history = history_items + ([target_item] if target_item is not None else []) |
| 1674 | |
| 1675 | # Each item becomes a separate training sample |
| 1676 | self.training_samples.append({ |
| 1677 | 'user_id': user_id, |
| 1678 | 'preference_text': preference_text, |
| 1679 | 'interaction_history': interaction_history |
| 1680 | }) |
| 1681 | |
| 1682 | # Load index mapping |
| 1683 | with open(index_file, 'r') as f: |
| 1684 | self.indices = json.load(f) |
| 1685 | |
| 1686 | # Prepare training data from preference file interaction histories |
no outgoing calls