File size: 11,104 Bytes
6276d4c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
"""
Utility helpers: seeding, device selection, logging, config loading.
"""

import os
import random
import logging
from pathlib import Path

import numpy as np
import torch
import yaml


def seed_everything(seed: int = 42) -> None:
    """Set seed for reproducibility across all libraries."""
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    os.environ["PYTHONHASHSEED"] = str(seed)
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False


def get_device() -> torch.device:
    """Return best available device (CUDA > MPS > CPU)."""
    if torch.cuda.is_available():
        return torch.device("cuda")
    elif hasattr(torch.backends, "mps") and torch.backends.mps.is_available():
        return torch.device("mps")
    return torch.device("cpu")


def load_config(config_path: str = "configs/default.yaml") -> dict:
    """Load YAML configuration file."""
    with open(config_path, "r") as f:
        return yaml.safe_load(f)


def setup_logging(log_dir: str | None = None, level: int = logging.INFO) -> logging.Logger:
    """Configure logging with console and optional file output."""
    logger = logging.getLogger("date-fruit")
    logger.setLevel(level)

    # Avoid duplicate handlers
    if logger.handlers:
        return logger

    formatter = logging.Formatter(
        "[%(asctime)s] %(levelname)s - %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
    )

    # Console handler
    ch = logging.StreamHandler()
    ch.setFormatter(formatter)
    logger.addHandler(ch)

    # File handler (optional)
    if log_dir:
        Path(log_dir).mkdir(parents=True, exist_ok=True)
        fh = logging.FileHandler(Path(log_dir) / "train.log")
        fh.setFormatter(formatter)
        logger.addHandler(fh)

    return logger


# Heritage knowledge base for Saudi date varieties.
# season_start / season_end are month numbers (1..12). peak_month is the strongest month.
# distinguish_* describes visual cues to identify the variety at a glance.
HERITAGE_INFO = {
    "Ajwa": {
        "arabic": "ุนุฌูˆุฉ",
        "region": "ุงู„ู…ุฏูŠู†ุฉ ุงู„ู…ู†ูˆุฑุฉ (Madinah)",
        "description": "One of the most prized dates in Saudi Arabia, known for its dark color and soft texture.",
        "description_ar": "ู…ู† ุฃุซู…ู† ุชู…ูˆุฑ ุงู„ู…ู…ู„ูƒุฉุŒ ูŠุชู…ูŠู‘ุฒ ุจู„ูˆู†ู‡ ุงู„ุฏุงูƒู† ูˆู‚ูˆุงู…ู‡ ุงู„ู„ูŠู‘ู†.",
        "significance": "Mentioned in Hadith. Considered sacred and highly valued across the Muslim world.",
        "significance_ar": "ูˆุฑุฏ ุฐูƒุฑู‡ ููŠ ุงู„ุญุฏูŠุซ ุงู„ุดุฑูŠูุŒ ูˆูŠุญุธู‰ ุจู…ูƒุงู†ุฉ ู…ู‚ุฏู‘ุณุฉ ุนู†ุฏ ุงู„ู…ุณู„ู…ูŠู†.",
        "flavor": "Rich, sweet with subtle caramel and prune notes.",
        "flavor_ar": "ุญู„ุงูˆุฉ ุบู†ูŠู‘ุฉ ู…ุน ู„ู…ุญุฉ ูƒุฑุงู…ูŠู„ ูˆุจุฑู‚ูˆู‚.",
        "season_start": 8, "season_end": 10, "peak_month": 9,
        "distinguish": "Small, matte black-brown surface with fine wrinkles. Very soft.",
        "distinguish_ar": "ุตุบูŠุฑุฉุŒ ุณุทุญู‡ุง ุฃุณูˆุฏ ู…ุงุฆู„ ู„ู„ุจู†ู‘ูŠ ู…ุน ุชุฌุงุนูŠุฏ ู†ุงุนู…ุฉ. ู„ูŠู‘ู†ุฉ ุฌุฏู‹ุง.",
    },
    "Galaxy": {
        "arabic": "ู‚ู„ุงูƒุณูŠ",
        "region": "ุงู„ู…ู…ู„ูƒุฉ ุงู„ุนุฑุจูŠุฉ ุงู„ุณุนูˆุฏูŠุฉ (Saudi Arabia)",
        "description": "A premium commercial variety known for its large size and golden-brown color.",
        "description_ar": "ุตู†ู ุชุฌุงุฑูŠ ู…ุชู…ูŠู‘ุฒ ุจุญุฌู…ู‡ ุงู„ูƒุจูŠุฑ ูˆู„ูˆู†ู‡ ุงู„ุฐู‡ุจูŠ ุงู„ุจู†ู‘ูŠ.",
        "significance": "Popular modern variety widely exported from Saudi Arabia.",
        "significance_ar": "ุตู†ู ุญุฏูŠุซ ู…ุดู‡ูˆุฑ ูŠูุตุฏูŽู‘ุฑ ู…ู† ุงู„ุณุนูˆุฏูŠุฉ ุจูƒุซุฑุฉ.",
        "flavor": "Sweet, chewy with honey-like undertones.",
        "flavor_ar": "ุญู„ุงูˆุฉ ู…ุทุงุทูŠู‘ุฉ ุจู„ู…ุณุฉ ุนุณู„.",
        "season_start": 8, "season_end": 10, "peak_month": 9,
        "distinguish": "Large, glossy, amber-golden skin. Elongated with a pointed tip.",
        "distinguish_ar": "ูƒุจูŠุฑุฉุŒ ู‚ุดุฑุชู‡ุง ุฐู‡ุจูŠู‘ุฉ ู„ุงู…ุนุฉุŒ ู…ุณุชุทูŠู„ุฉ ู…ุฏุจู‘ุจุฉ ุงู„ุฃุทุฑุงู.",
    },
    "Medjool": {
        "arabic": "ู…ุฌุฏูˆู„",
        "region": "ุงู„ู…ุฏูŠู†ุฉ ุงู„ู…ู†ูˆุฑุฉ (Madinah) / ุงู„ุฑูŠุงุถ (Riyadh)",
        "description": "Known as the 'King of Dates' for its large size and rich taste.",
        "description_ar": "ูŠูู„ู‚ูŽู‘ุจ ุจู€ยซู…ู„ูƒ ุงู„ุชู…ูˆุฑยป ู„ุญุฌู…ู‡ ุงู„ูƒุจูŠุฑ ูˆู…ุฐุงู‚ู‡ ุงู„ูุงุฎุฑ.",
        "significance": "One of the most recognized date varieties worldwide. Historically reserved for royalty.",
        "significance_ar": "ู…ู† ุฃุดู‡ุฑ ุงู„ุชู…ูˆุฑ ุนุงู„ู…ูŠู‹ุงุŒ ูˆูƒุงู† ู‚ุฏูŠู…ู‹ุง ุญูƒุฑู‹ุง ุนู„ู‰ ุงู„ู…ู„ูˆูƒ.",
        "flavor": "Caramel-like sweetness, soft and creamy texture.",
        "flavor_ar": "ุญู„ุงูˆุฉ ุงู„ูƒุฑุงู…ูŠู„ุŒ ุจู‚ูˆุงู… ู„ูŠู‘ู† ูƒุฑูŠู…ูŠ.",
        "season_start": 9, "season_end": 11, "peak_month": 10,
        "distinguish": "Very large, plump, wrinkled amber-brown skin. Tender and moist.",
        "distinguish_ar": "ูƒุจูŠุฑุฉ ุฌุฏู‹ุงุŒ ู…ู…ุชู„ุฆุฉุŒ ู‚ุดุฑุชู‡ุง ุจู†ู‘ูŠุฉ ูƒู‡ุฑู…ุงู†ูŠู‘ุฉ ู…ุชุฌุนู‘ุฏุฉ. ุฑุทุจุฉ ุทุฑูŠู‘ุฉ.",
    },
    "Meneifi": {
        "arabic": "ู…ู†ูŠููŠ",
        "region": "ุงู„ู‚ุตูŠู… (Qassim) / ุงู„ู…ุฏูŠู†ุฉ ุงู„ู…ู†ูˆุฑุฉ (Madinah)",
        "description": "A traditional Saudi variety with elongated shape and amber color.",
        "description_ar": "ุตู†ู ุณุนูˆุฏูŠ ุฃุตูŠู„ุŒ ุดูƒู„ู‡ ู…ุณุชุทูŠู„ ูˆู„ูˆู†ู‡ ูƒู‡ุฑู…ุงู†ูŠ.",
        "significance": "Well-known in local Saudi markets, a household favorite.",
        "significance_ar": "ู…ุนุฑูˆู ููŠ ุงู„ุฃุณูˆุงู‚ ุงู„ุณุนูˆุฏูŠุฉุŒ ูˆู…ูุถูŽู‘ู„ ููŠ ุงู„ุจูŠูˆุช.",
        "flavor": "Moderately sweet with a firm, slightly chewy texture.",
        "flavor_ar": "ุญู„ุงูˆุชู‡ ู…ุชูˆุณู‘ุทุฉุŒ ู‚ูˆุงู…ู‡ ู…ุชู…ุงุณูƒ ู…ุงุฆู„ ู„ู„ู…ุถุบ.",
        "season_start": 8, "season_end": 10, "peak_month": 9,
        "distinguish": "Elongated, narrow, light amber body. Firmer than Medjool.",
        "distinguish_ar": "ู…ุณุชุทูŠู„ุฉ ู†ุญูŠู„ุฉุŒ ู„ูˆู†ู‡ุง ูƒู‡ุฑู…ุงู†ูŠ ูุงุชุญ. ุฃูƒุซุฑ ุตู„ุงุจุฉ ู…ู† ุงู„ู…ุฌุฏูˆู„.",
    },
    "Nabtat Ali": {
        "arabic": "ู†ุจุชุฉ ุนู„ูŠ",
        "region": "ุงู„ู…ุฏูŠู†ุฉ ุงู„ู…ู†ูˆุฑุฉ (Madinah)",
        "description": "A Madinah variety with distinctive reddish-brown color.",
        "description_ar": "ุตู†ู ู…ุฏู†ูŠ ูŠุชู…ูŠู‘ุฒ ุจู„ูˆู†ู‡ ุงู„ุจู†ู‘ูŠ ุงู„ู…ุงุฆู„ ู„ู„ุงุญู…ุฑุงุฑ.",
        "significance": "Named variety from the date palm farms of Madinah.",
        "significance_ar": "ู…ู† ุฃุดู‡ุฑ ุฃุตู†ุงู ู†ุฎูŠู„ ุงู„ู…ุฏูŠู†ุฉ ุงู„ู…ู†ูˆู‘ุฑุฉ.",
        "flavor": "Sweet and tender with a moist, soft flesh.",
        "flavor_ar": "ุญู„ูˆุฉ ุทุฑูŠู‘ุฉุŒ ู„ุญู…ู‡ุง ุฑุทุจ ู„ูŠู‘ู†.",
        "season_start": 9, "season_end": 10, "peak_month": 9,
        "distinguish": "Medium size, reddish-brown tone, slightly wrinkled.",
        "distinguish_ar": "ู…ุชูˆุณู‘ุทุฉ ุงู„ุญุฌู…ุŒ ู„ูˆู†ู‡ุง ุจู†ู‘ูŠ ู…ุญู…ุฑู‘ุŒ ุจุชุฌุงุนูŠุฏ ุฎููŠูุฉ.",
    },
    "Rutab": {
        "arabic": "ุฑุทุจ",
        "region": "ุฌู…ูŠุน ู…ู†ุงุทู‚ ุงู„ู…ู…ู„ูƒุฉ (All regions)",
        "description": "Refers to the soft, ripe stage of the date fruit before full drying.",
        "description_ar": "ุงู„ู…ุฑุญู„ุฉ ุงู„ุทุฑูŠู‘ุฉ ุงู„ู†ุงุถุฌุฉ ู…ู† ุซู…ุฑุฉ ุงู„ู†ุฎู„ุฉ ู‚ุจู„ ุงู„ุฌูุงู ุงู„ูƒุงู…ู„.",
        "significance": "Deeply embedded in Saudi culture. Fresh rutab is a seasonal delicacy during harvest.",
        "significance_ar": "ุฌุฒุก ุฃุตูŠู„ ู…ู† ุงู„ุซู‚ุงูุฉ ุงู„ุณุนูˆุฏูŠุฉ. ุงู„ุฑุทุจ ุงู„ุทุงุฒุฌ ุฃูƒู„ุฉ ู…ูˆุณู…ูŠุฉ ููŠ ุงู„ุฌู†ูŠ.",
        "flavor": "Extremely soft, juicy, and intensely sweet.",
        "flavor_ar": "ู„ูŠู‘ู†ุฉ ุฌุฏู‹ุงุŒ ุนุตูŠุฑูŠู‘ุฉุŒ ุดุฏูŠุฏุฉ ุงู„ุญู„ุงูˆุฉ.",
        "season_start": 7, "season_end": 9, "peak_month": 8,
        "distinguish": "Glossy, half-amber half-brown transition skin. Very moist.",
        "distinguish_ar": "ู‚ุดุฑุชู‡ุง ู„ุงู…ุนุฉุŒ ู†ุตู ูƒู‡ุฑู…ุงู†ูŠู‘ุฉ ูˆู†ุตู ุจู†ู‘ูŠู‘ุฉ. ุฑุทุจุฉ ุฌุฏู‹ุง.",
    },
    "Shaishe": {
        "arabic": "ุดูŠุดูŠ",
        "region": "ุงู„ู…ุฏูŠู†ุฉ ุงู„ู…ู†ูˆุฑุฉ (Madinah)",
        "description": "A Madinah-specific variety with small to medium size.",
        "description_ar": "ุตู†ู ู…ุฏู†ูŠ ุฎุงุตุŒ ุตุบูŠุฑ ุฅู„ู‰ ู…ุชูˆุณู‘ุท ุงู„ุญุฌู….",
        "significance": "Traditional variety cultivated in Madinah palm groves for generations.",
        "significance_ar": "ุตู†ู ุชู‚ู„ูŠุฏูŠ ูŠูุฒุฑุน ููŠ ู†ุฎูŠู„ ุงู„ู…ุฏูŠู†ุฉ ู„ุฃุฌูŠุงู„.",
        "flavor": "Balanced sweetness with a smooth, soft texture.",
        "flavor_ar": "ุญู„ุงูˆุฉ ู…ุชูˆุงุฒู†ุฉ ูˆู‚ูˆุงู… ู†ุงุนู….",
        "season_start": 9, "season_end": 10, "peak_month": 9,
        "distinguish": "Small, smooth, dark amber. Uniform shape.",
        "distinguish_ar": "ุตุบูŠุฑุฉ ู†ุงุนู…ุฉ ุงู„ู‚ุดุฑุฉุŒ ู„ูˆู†ู‡ุง ูƒู‡ุฑู…ุงู†ูŠ ุฏุงูƒู†. ุดูƒู„ู‡ุง ู…ู†ุชุธู….",
    },
    "Sokari": {
        "arabic": "ุณูƒุฑูŠ",
        "region": "ุงู„ู‚ุตูŠู… (Qassim)",
        "description": "The most popular date variety in Saudi Arabia, known for its golden color and sugar-like sweetness.",
        "description_ar": "ุฃุดู‡ุฑ ุชู…ูˆุฑ ุงู„ุณุนูˆุฏูŠุฉุŒ ูŠุชู…ูŠู‘ุฒ ุจู„ูˆู†ู‡ ุงู„ุฐู‡ุจูŠ ูˆุญู„ุงูˆุชู‡ ุงู„ุณูƒุฑูŠู‘ุฉ.",
        "significance": "Named 'Sokari' (sugary) for its exceptional sweetness. A staple in every Saudi home.",
        "significance_ar": "ุณูู…ูู‘ูŠ ยซุณูƒุฑูŠยป ู„ุญู„ุงูˆุชู‡ ุงู„ุงุณุชุซู†ุงุฆูŠู‘ุฉ. ุญุงุถุฑ ููŠ ูƒู„ู‘ ุจูŠุช ุณุนูˆุฏูŠ.",
        "flavor": "Crisp outer layer with a soft, sweet interior. Tastes like caramel candy.",
        "flavor_ar": "ู‚ุดุฑุฉ ู…ู‚ุฑู…ุดุฉ ูˆู„ุจู‘ ุทุฑูŠู‘ ุญู„ูˆุŒ ุทุนู…ู‡ ูƒุญู„ูˆู‰ ุงู„ูƒุฑุงู…ูŠู„.",
        "season_start": 7, "season_end": 9, "peak_month": 8,
        "distinguish": "Two-tone: golden tip with brown base. Crunchy skin, soft inside.",
        "distinguish_ar": "ุจู„ูˆู†ูŠู†: ุฐู‡ุจูŠ ููŠ ุงู„ุทุฑู ูˆุจู†ู‘ูŠ ููŠ ุงู„ู‚ุงุนุฏุฉ. ู‚ุดุฑุฉ ู…ู‚ุฑู…ุดุฉ ูˆู„ุจู‘ ุทุฑูŠู‘.",
    },
    "Sugaey": {
        "arabic": "ุตู‚ุนูŠ",
        "region": "ุงู„ู‚ุตูŠู… (Qassim) / ุงู„ุฑูŠุงุถ (Riyadh)",
        "description": "A popular variety often eaten at the Khalal (yellow) or Rutab stage.",
        "description_ar": "ุตู†ู ุดู‡ูŠุฑ ูŠุคูƒู„ ุบุงู„ุจู‹ุง ููŠ ู…ุฑุญู„ุฉ ุงู„ุฎู„ุงู„ (ุงู„ุฃุตูุฑ) ุฃูˆ ุงู„ุฑุทุจ.",
        "significance": "Widely consumed during Ramadan. A favorite for stuffing with nuts.",
        "significance_ar": "ูŠูุณุชู‡ู„ูƒ ุจูƒุซุฑุฉ ููŠ ุฑู…ุถุงู†ุŒ ูˆู…ูุถูŽู‘ู„ ู„ู„ุญุดูˆ ุจุงู„ู…ูƒุณู‘ุฑุงุช.",
        "flavor": "Mildly sweet, firm texture, often enjoyed fresh.",
        "flavor_ar": "ุญู„ุงูˆุฉ ุฎููŠูุฉ ูˆู‚ูˆุงู… ู…ุชู…ุงุณูƒุŒ ูŠูุคูƒู„ ุทุงุฒุฌู‹ุง ุบุงู„ุจู‹ุง.",
        "season_start": 7, "season_end": 9, "peak_month": 8,
        "distinguish": "Oblong, yellow-to-amber gradient. Firm, dry-looking skin.",
        "distinguish_ar": "ู…ุณุชุทูŠู„ุฉุŒ ู„ูˆู†ู‡ุง ูŠุชุฏุฑู‘ุฌ ู…ู† ุงู„ุฃุตูุฑ ุฅู„ู‰ ุงู„ูƒู‡ุฑู…ุงู†ูŠ. ู‚ุดุฑุชู‡ุง ู…ุชู…ุงุณูƒุฉ ูˆุดุจู‡ ุฌุงูู‘ุฉ.",
    },
}