pub trait RelationExtractorTrait: Send + Sync {
// Required method
fn extract_with_relations(
&self,
text: &str,
entity_types: &[&str],
relation_types: &[&str],
threshold: f32,
) -> Result<ExtractionWithRelations, Error>;
// Provided method
fn extract_relations_default(
&self,
text: &str,
) -> Result<(Vec<Entity>, Vec<Relation>), Error> { ... }
}Expand description
Joint entity and relation extraction.
§Motivation
Real-world information extraction often requires both entities AND their relationships. For example, extracting “Steve Jobs” and “Apple” is useful, but knowing “Steve Jobs FOUNDED Apple” is far more valuable.
Joint extraction (vs pipeline) is preferred because:
- Error propagation: Pipeline errors compound (bad entities → bad relations)
- Shared context: Entities and relations inform each other
- Efficiency: Single forward pass instead of two
§Architecture
Input: "Steve Jobs founded Apple in 1976."
│
▼
┌──────────────────────────────────┐
│ Shared Encoder (BERT) │
└──────────────────────────────────┘
│
┌──────┴──────┐
▼ ▼
┌───────────────┐ ┌───────────────┐
│ Entity Head │ │ Relation Head │
│ (span class.) │ │ (pair class.) │
└───────┬───────┘ └───────┬───────┘
│ │
▼ ▼
Entities: Relations:
- Steve Jobs [PER] - (Steve Jobs, FOUNDED, Apple)
- Apple [ORG] - (Apple, FOUNDED_IN, 1976)
- 1976 [DATE]§Research Alignment
From GLiNER multi-task (arXiv:2406.12925):
“Generalist Lightweight Model for Various Information Extraction Tasks… joint entity and relation extraction.”
From W2NER (arXiv:2112.10070):
“Unified Named Entity Recognition as Word-Word Relation Classification… handles flat, overlapped, and discontinuous NER.”
§Example
use anno::RelationExtractor;
fn build_knowledge_graph(extractor: &dyn RelationExtractor, text: &str) {
let entity_types = &["person", "organization", "date"];
let relation_types = &["founded", "works_for", "acquired"];
let result = extractor.extract_with_relations(
text, entity_types, relation_types, 0.5
).unwrap();
// Build graph nodes from entities
for e in &result.entities {
println!("Node: {} ({})", e.text, e.entity_type);
}
// Build graph edges from relations
for r in &result.relations {
let head = &result.entities[r.head_idx];
let tail = &result.entities[r.tail_idx];
println!("Edge: {} --[{}]--> {}", head.text, r.relation_type, tail.text);
}
}Required Methods§
Sourcefn extract_with_relations(
&self,
text: &str,
entity_types: &[&str],
relation_types: &[&str],
threshold: f32,
) -> Result<ExtractionWithRelations, Error>
fn extract_with_relations( &self, text: &str, entity_types: &[&str], relation_types: &[&str], threshold: f32, ) -> Result<ExtractionWithRelations, Error>
Provided Methods§
Sourcefn extract_relations_default(
&self,
text: &str,
) -> Result<(Vec<Entity>, Vec<Relation>), Error>
fn extract_relations_default( &self, text: &str, ) -> Result<(Vec<Entity>, Vec<Relation>), Error>
Convenience: extract with broad default entity/relation types and threshold 0.5.
Returns (entities, relations) flattened from ExtractionWithRelations.
Useful when the caller already has a RelationExtractor and does not need
to control the entity/relation schemas.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementors§
impl RelationExtractor for AnyModel
impl RelationExtractor for GLiNERMultitaskCandle
candle only.impl RelationExtractor for GLiNERMultitaskOnnx
onnx only.