File size: 5,861 Bytes
0e61be5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/usr/bin/env python3
"""
Validate Wikipedia data files and WikiData loader.

Usage:
    python scripts/validate_data.py
"""

import logging
import sys
import time
from pathlib import Path

# Fix Windows console encoding for Unicode output
if sys.platform == "win32":
    sys.stdout.reconfigure(encoding="utf-8", errors="replace")

# Add project root to path
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from src.config import (  # noqa: E402 - must be after sys.path modification
    EMBEDDINGS_PATH,
    LINK_GRAPH_PATH,
    TITLE_TO_IDX_PATH,
    TITLES_PATH,
)

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format="%(message)s",
)
logger = logging.getLogger(__name__)


def check_data_files_exist() -> bool:
    """Check that all data files exist."""
    print("\n=== Checking Data Files ===\n")

    files = {
        "titles.json": TITLES_PATH,
        "title_to_idx.json": TITLE_TO_IDX_PATH,
        "link_graph.msgpack": LINK_GRAPH_PATH,
        "embeddings.npy": EMBEDDINGS_PATH,
    }

    all_exist = True
    for name, path in files.items():
        exists = path.exists()
        size_mb = path.stat().st_size / (1024 * 1024) if exists else 0
        status = f"βœ“ {name}: {size_mb:,.1f} MB" if exists else f"βœ— {name}: NOT FOUND"
        print(status)
        if not exists:
            all_exist = False

    return all_exist


def load_and_validate() -> bool:
    """Load WikiData and run validation checks."""
    print("\n=== Loading WikiData ===\n")

    start_time = time.time()

    # Import here to trigger lazy loading
    from src.data import wiki_data

    # Trigger loading by accessing data
    print("Loading data (this may take a minute)...")
    _ = wiki_data.article_count()

    load_time = time.time() - start_time
    print(f"\nLoad time: {load_time:.1f} seconds")

    # Get stats
    print("\n=== Data Statistics ===\n")
    stats = wiki_data.stats()
    for key, value in stats.items():
        print(f"  {key}: {value:,}" if isinstance(value, int) else f"  {key}: {value}")

    # Run validation
    print("\n=== Validation Checks ===\n")
    validation = wiki_data.validate()
    all_valid = True
    for check, passed in validation.items():
        status = "βœ“" if passed else "βœ—"
        print(f"  {status} {check}")
        if not passed:
            all_valid = False

    return all_valid


def test_sample_queries() -> bool:
    """Test sample queries against known articles."""
    print("\n=== Sample Queries ===\n")

    from src.data import wiki_data

    test_articles = [
        "Albert Einstein",
        "Physics",
        "United States",
        "Python (programming language)",
    ]

    all_passed = True

    for title in test_articles:
        print(f"\nTesting: {title}")

        # Check existence
        if not wiki_data.has_article(title):
            print("  βœ— Article not found")
            all_passed = False
            continue
        print("  βœ“ Article exists")

        # Check index
        idx = wiki_data.get_index(title)
        print(f"  βœ“ Index: {idx:,}")

        # Check embedding
        emb = wiki_data.get_embedding(title)
        if emb is None:
            print("  βœ— No embedding")
            all_passed = False
        else:
            print(f"  βœ“ Embedding shape: {emb.shape}")

        # Check links
        links = wiki_data.get_links(title)
        if wiki_data.is_traversable(title):
            print(f"  βœ“ Outgoing links: {len(links):,}")
        else:
            print("  ⚠ No outgoing links (not traversable)")

    # Test similarity
    print("\n--- Similarity Tests ---")
    sim1 = wiki_data.similarity("Physics", "Mathematics")
    sim2 = wiki_data.similarity("Physics", "Pizza")

    if sim1 is not None and sim2 is not None:
        print(f"  Physics ↔ Mathematics: {sim1:.4f}")
        print(f"  Physics ↔ Pizza: {sim2:.4f}")

        if sim1 > sim2:
            print("  βœ“ Physics is more similar to Mathematics than Pizza")
        else:
            print("  βœ— Unexpected similarity ordering")
            all_passed = False
    else:
        print("  βœ— Similarity calculation failed")
        all_passed = False

    # Test nearest neighbors
    print("\n--- Nearest Neighbors (Physics) ---")
    neighbors = wiki_data.nearest_neighbors("Physics", k=5)
    for i, (neighbor, sim) in enumerate(neighbors, 1):
        print(f"  {i}. {neighbor}: {sim:.4f}")

    # Test ranking
    print("\n--- Ranking Test ---")
    candidates = ["Mathematics", "Pizza", "Chemistry", "Football", "Biology"]
    ranked = wiki_data.rank_by_similarity(candidates, "Physics")
    print("  Candidates ranked by similarity to Physics:")
    for title, sim in ranked:
        print(f"    {title}: {sim:.4f}")

    return all_passed


def main() -> int:
    """Main validation routine."""
    print("=" * 60)
    print("Wikipedia Speedrun Data Validation")
    print("=" * 60)

    # Check files exist
    if not check_data_files_exist():
        print("\nβœ— Some data files are missing. Cannot continue.")
        return 1

    # Load and validate
    try:
        if not load_and_validate():
            print("\nβœ— Validation checks failed.")
            return 1
    except Exception as e:
        print(f"\nβœ— Error loading data: {e}")
        import traceback
        traceback.print_exc()
        return 1

    # Test sample queries
    try:
        if not test_sample_queries():
            print("\nβœ— Sample query tests failed.")
            return 1
    except Exception as e:
        print(f"\nβœ— Error running sample queries: {e}")
        import traceback
        traceback.print_exc()
        return 1

    print("\n" + "=" * 60)
    print("βœ“ All validation checks passed!")
    print("=" * 60)

    return 0


if __name__ == "__main__":
    sys.exit(main())