1use crate::eval::relation::RelationGold;
20
21#[derive(Debug, Clone)]
23pub struct RelationExample {
24 pub text: String,
26 pub relations: Vec<RelationGold>,
28 pub difficulty: Difficulty,
30 pub domain: Domain,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum Difficulty {
37 Easy,
39 Medium,
41 Hard,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub enum Domain {
48 General,
50 Business,
52 Scientific,
54 Biography,
56}
57
58pub fn dataset() -> Vec<RelationExample> {
60 let mut examples = Vec::new();
61
62 examples.extend(easy_relations());
64
65 examples.extend(medium_relations());
67
68 examples.extend(hard_relations());
70
71 examples.extend(business_domain());
73 examples.extend(scientific_domain());
74 examples.extend(biography_domain());
75
76 examples
77}
78
79fn easy_relations() -> Vec<RelationExample> {
81 vec![
82 RelationExample {
83 text: "Steve Jobs founded Apple in 1976.".to_string(),
84 relations: vec![RelationGold::new(
85 (0, 10),
86 "PER",
87 "Steve Jobs",
88 (19, 24),
89 "ORG",
90 "Apple",
91 "FOUNDED",
92 )],
93 difficulty: Difficulty::Easy,
94 domain: Domain::Business,
95 },
96 RelationExample {
97 text: "Mary works for Google in California.".to_string(),
98 relations: vec![
99 RelationGold::new(
100 (0, 4),
101 "PER",
102 "Mary",
103 (15, 21),
104 "ORG",
105 "Google",
106 "WORKS_FOR",
107 ),
108 RelationGold::new(
109 (15, 21),
110 "ORG",
111 "Google",
112 (25, 35),
113 "LOC",
114 "California",
115 "LOCATED_IN",
116 ),
117 ],
118 difficulty: Difficulty::Easy,
119 domain: Domain::Business,
120 },
121 RelationExample {
122 text: "The Eiffel Tower is located in Paris, France.".to_string(),
123 relations: vec![
124 RelationGold::new(
125 (4, 16),
126 "LOC",
127 "Eiffel Tower",
128 (31, 36),
129 "LOC",
130 "Paris",
131 "LOCATED_IN",
132 ),
133 RelationGold::new(
134 (31, 36),
135 "LOC",
136 "Paris",
137 (38, 44),
138 "LOC",
139 "France",
140 "LOCATED_IN",
141 ),
142 ],
143 difficulty: Difficulty::Easy,
144 domain: Domain::General,
145 },
146 RelationExample {
147 text: "Tim Cook is the CEO of Apple Inc.".to_string(),
148 relations: vec![RelationGold::new(
149 (0, 8),
150 "PER",
151 "Tim Cook",
152 (23, 32),
153 "ORG",
154 "Apple Inc",
155 "CEO_OF",
156 )],
157 difficulty: Difficulty::Easy,
158 domain: Domain::Business,
159 },
160 RelationExample {
161 text: "Amazon acquired Whole Foods in 2017.".to_string(),
162 relations: vec![RelationGold::new(
163 (0, 6),
164 "ORG",
165 "Amazon",
166 (16, 27),
167 "ORG",
168 "Whole Foods",
169 "ACQUIRED",
170 )],
171 difficulty: Difficulty::Easy,
172 domain: Domain::Business,
173 },
174 ]
175}
176
177fn medium_relations() -> Vec<RelationExample> {
179 vec![
180 RelationExample {
181 text: "Bill Gates and Paul Allen co-founded Microsoft in Seattle.".to_string(),
182 relations: vec![
183 RelationGold::new(
184 (0, 10),
185 "PER",
186 "Bill Gates",
187 (37, 46),
188 "ORG",
189 "Microsoft",
190 "FOUNDED",
191 ),
192 RelationGold::new(
193 (15, 25),
194 "PER",
195 "Paul Allen",
196 (37, 46),
197 "ORG",
198 "Microsoft",
199 "FOUNDED",
200 ),
201 RelationGold::new(
202 (37, 46),
203 "ORG",
204 "Microsoft",
205 (50, 57),
206 "LOC",
207 "Seattle",
208 "LOCATED_IN",
209 ),
210 ],
211 difficulty: Difficulty::Medium,
212 domain: Domain::Business,
213 },
214 RelationExample {
215 text: "Dr. Smith at Harvard published research with Dr. Jones from MIT.".to_string(),
216 relations: vec![
217 RelationGold::new(
218 (0, 9),
219 "PER",
220 "Dr. Smith",
221 (13, 20),
222 "ORG",
223 "Harvard",
224 "AFFILIATED_WITH",
225 ),
226 RelationGold::new(
227 (45, 54),
228 "PER",
229 "Dr. Jones",
230 (60, 63),
231 "ORG",
232 "MIT",
233 "AFFILIATED_WITH",
234 ),
235 RelationGold::new(
236 (0, 9),
237 "PER",
238 "Dr. Smith",
239 (45, 54),
240 "PER",
241 "Dr. Jones",
242 "COLLABORATED_WITH",
243 ),
244 ],
245 difficulty: Difficulty::Medium,
246 domain: Domain::Scientific,
247 },
248 RelationExample {
249 text: "Alice, Bob's sister, married Charlie, who works at IBM.".to_string(),
250 relations: vec![
251 RelationGold::new((0, 5), "PER", "Alice", (7, 10), "PER", "Bob", "SIBLING_OF"),
252 RelationGold::new(
253 (0, 5),
254 "PER",
255 "Alice",
256 (29, 36),
257 "PER",
258 "Charlie",
259 "SPOUSE_OF",
260 ),
261 RelationGold::new(
262 (29, 36),
263 "PER",
264 "Charlie",
265 (51, 54),
266 "ORG",
267 "IBM",
268 "WORKS_FOR",
269 ),
270 ],
271 difficulty: Difficulty::Medium,
272 domain: Domain::Biography,
273 },
274 ]
275}
276
277fn hard_relations() -> Vec<RelationExample> {
279 vec![
280 RelationExample {
281 text: "Sundar Pichai, born in India, leads Google's AI efforts.".to_string(),
283 relations: vec![
284 RelationGold::new(
285 (0, 13), "PER", "Sundar Pichai",
286 (23, 28), "LOC", "India",
287 "BORN_IN",
288 ),
289 RelationGold::new(
290 (0, 13), "PER", "Sundar Pichai",
291 (36, 42), "ORG", "Google",
292 "WORKS_FOR",
293 ),
294 ],
295 difficulty: Difficulty::Hard,
296 domain: Domain::Biography,
297 },
298 RelationExample {
299 text: "The company, which was established in 1998 by Larry Page and Sergey Brin, is headquartered in Mountain View.".to_string(),
301 relations: vec![
302 RelationGold::new(
303 (45, 55), "PER", "Larry Page",
304 (0, 11), "ORG", "The company",
305 "FOUNDED",
306 ),
307 RelationGold::new(
308 (60, 71), "PER", "Sergey Brin",
309 (0, 11), "ORG", "The company",
310 "FOUNDED",
311 ),
312 RelationGold::new(
313 (0, 11), "ORG", "The company",
314 (92, 105), "LOC", "Mountain View",
315 "LOCATED_IN",
316 ),
317 ],
318 difficulty: Difficulty::Hard,
319 domain: Domain::Business,
320 },
321 ]
322}
323
324fn business_domain() -> Vec<RelationExample> {
326 vec![
327 RelationExample {
328 text: "Nvidia, led by Jensen Huang, designs chips in Santa Clara.".to_string(),
329 relations: vec![
330 RelationGold::new(
331 (15, 27),
332 "PER",
333 "Jensen Huang",
334 (0, 6),
335 "ORG",
336 "Nvidia",
337 "CEO_OF",
338 ),
339 RelationGold::new(
340 (0, 6),
341 "ORG",
342 "Nvidia",
343 (46, 57),
344 "LOC",
345 "Santa Clara",
346 "LOCATED_IN",
347 ),
348 ],
349 difficulty: Difficulty::Medium,
350 domain: Domain::Business,
351 },
352 RelationExample {
353 text: "Netflix is headquartered in Los Gatos, California.".to_string(),
354 relations: vec![
355 RelationGold::new(
356 (0, 7),
357 "ORG",
358 "Netflix",
359 (28, 37),
360 "LOC",
361 "Los Gatos",
362 "LOCATED_IN",
363 ),
364 RelationGold::new(
365 (28, 37),
366 "LOC",
367 "Los Gatos",
368 (39, 49),
369 "LOC",
370 "California",
371 "LOCATED_IN",
372 ),
373 ],
374 difficulty: Difficulty::Easy,
375 domain: Domain::Business,
376 },
377 ]
378}
379
380fn scientific_domain() -> Vec<RelationExample> {
382 vec![
383 RelationExample {
384 text: "CRISPR was developed by Jennifer Doudna at UC Berkeley.".to_string(),
385 relations: vec![
386 RelationGold::new(
387 (24, 39),
388 "PER",
389 "Jennifer Doudna",
390 (0, 6),
391 "MISC",
392 "CRISPR",
393 "DEVELOPED",
394 ),
395 RelationGold::new(
396 (24, 39),
397 "PER",
398 "Jennifer Doudna",
399 (43, 54),
400 "ORG",
401 "UC Berkeley",
402 "AFFILIATED_WITH",
403 ),
404 ],
405 difficulty: Difficulty::Medium,
406 domain: Domain::Scientific,
407 },
408 RelationExample {
409 text: "Einstein published the theory of relativity while at the Swiss Patent Office."
410 .to_string(),
411 relations: vec![
412 RelationGold::new(
413 (0, 8),
414 "PER",
415 "Einstein",
416 (23, 44),
417 "MISC",
418 "theory of relativity",
419 "AUTHORED",
420 ),
421 RelationGold::new(
422 (0, 8),
423 "PER",
424 "Einstein",
425 (58, 77),
426 "ORG",
427 "Swiss Patent Office",
428 "WORKS_FOR",
429 ),
430 ],
431 difficulty: Difficulty::Medium,
432 domain: Domain::Scientific,
433 },
434 ]
435}
436
437fn biography_domain() -> Vec<RelationExample> {
439 vec![
440 RelationExample {
441 text: "Barack Obama, born in Honolulu, served as the 44th President.".to_string(),
442 relations: vec![RelationGold::new(
443 (0, 12),
444 "PER",
445 "Barack Obama",
446 (22, 30),
447 "LOC",
448 "Honolulu",
449 "BORN_IN",
450 )],
451 difficulty: Difficulty::Easy,
452 domain: Domain::Biography,
453 },
454 RelationExample {
455 text: "Marie Curie and Pierre Curie, her husband, won the Nobel Prize.".to_string(),
456 relations: vec![RelationGold::new(
457 (0, 11),
458 "PER",
459 "Marie Curie",
460 (16, 28),
461 "PER",
462 "Pierre Curie",
463 "SPOUSE_OF",
464 )],
465 difficulty: Difficulty::Medium,
466 domain: Domain::Biography,
467 },
468 ]
469}
470
471pub fn stats() -> RelationStats {
473 let all = dataset();
474 let total_relations: usize = all.iter().map(|ex| ex.relations.len()).sum();
475
476 let mut relation_types = std::collections::HashMap::new();
477 for ex in &all {
478 for rel in &ex.relations {
479 *relation_types.entry(rel.relation_type.clone()).or_insert(0) += 1;
480 }
481 }
482
483 RelationStats {
484 total_examples: all.len(),
485 total_relations,
486 relation_types,
487 }
488}
489
490#[derive(Debug, Clone)]
492pub struct RelationStats {
493 pub total_examples: usize,
495 pub total_relations: usize,
497 pub relation_types: std::collections::HashMap<String, usize>,
499}
500
501#[cfg(test)]
502mod tests {
503 use super::*;
504
505 #[test]
506 fn test_dataset_not_empty() {
507 let examples = dataset();
508 assert!(!examples.is_empty());
509 assert!(examples.len() >= 10, "Should have at least 10 examples");
510 }
511
512 #[test]
513 fn test_has_multiple_relation_types() {
514 let s = stats();
515 assert!(
516 s.relation_types.len() >= 5,
517 "Should have at least 5 relation types"
518 );
519 }
520
521 #[test]
522 fn test_entity_spans_valid() {
523 for example in dataset() {
524 for rel in &example.relations {
525 assert!(
526 rel.head_span.1 <= example.text.len(),
527 "Head span exceeds text length in: {}",
528 example.text
529 );
530 assert!(
531 rel.tail_span.1 <= example.text.len(),
532 "Tail span exceeds text length in: {}",
533 example.text
534 );
535 assert!(
536 rel.head_span.0 < rel.head_span.1,
537 "Invalid head span in: {}",
538 example.text
539 );
540 assert!(
541 rel.tail_span.0 < rel.tail_span.1,
542 "Invalid tail span in: {}",
543 example.text
544 );
545 }
546 }
547 }
548
549 #[test]
550 fn test_stats() {
551 let s = stats();
552 assert!(s.total_examples > 0);
553 assert!(s.total_relations > 0);
554 assert!(!s.relation_types.is_empty());
555 }
556}