pub trait ZeroShotNERTrait: Send + Sync {
// Required methods
fn extract_with_types(
&self,
text: &str,
entity_types: &[&str],
threshold: f32,
) -> Result<Vec<Entity>, Error>;
fn extract_with_descriptions(
&self,
text: &str,
descriptions: &[&str],
threshold: f32,
) -> Result<Vec<Entity>, Error>;
fn default_types(&self) -> &[&'static str];
// Provided method
fn extract_with_described_types(
&self,
text: &str,
types_with_descriptions: &[(&str, &str)],
threshold: f32,
) -> Result<Vec<Entity>, Error> { ... }
}Expand description
Zero-shot NER for open entity types.
§Motivation
Traditional NER models are trained on fixed taxonomies (PER, ORG, LOC, etc.) and cannot extract new entity types without retraining. Zero-shot NER solves this by allowing arbitrary entity types at inference time.
Instead of asking “is this a PERSON?”, zero-shot NER asks “does this text span match the description ‘a named individual human being’?”
§Use Cases
- Domain adaptation: Extract “gene names” or “legal citations” without training data
- Custom taxonomies: Use your own entity hierarchy
- Rapid prototyping: Test new entity types before investing in annotation
§Research Alignment
From GLiNER (arXiv:2311.08526):
“NER model capable of identifying any entity type using a bidirectional transformer encoder… provides a practical alternative to traditional NER models, which are limited to predefined entity types.”
From UniversalNER (arXiv:2308.03279):
“Large language models demonstrate remarkable generalizability, such as understanding arbitrary entities and relations.”
§Example
use anno::backends::inference::ZeroShotNER;
fn extract_medical_entities(ner: &dyn ZeroShotNER, clinical_note: &str) {
// Define custom medical entity types at runtime
let types = &["drug name", "disease", "symptom", "dosage"];
let entities = ner.extract_with_types(clinical_note, types, 0.5).unwrap();
for e in entities {
println!("{}: {} (conf: {:.2})", e.entity_type, e.text, e.confidence);
}
}
fn extract_with_descriptions(ner: &dyn ZeroShotNER, text: &str) {
// Even richer: use natural language descriptions
let descriptions = &[
"a medication or pharmaceutical compound",
"a medical condition or illness",
"a physical sensation indicating illness",
];
let entities = ner.extract_with_descriptions(text, descriptions, 0.5).unwrap();
}Required Methods§
Sourcefn extract_with_types(
&self,
text: &str,
entity_types: &[&str],
threshold: f32,
) -> Result<Vec<Entity>, Error>
fn extract_with_types( &self, text: &str, entity_types: &[&str], threshold: f32, ) -> Result<Vec<Entity>, Error>
Extract entities with custom types.
§Arguments
text- Input textentity_types- Entity type descriptions (arbitrary text, not fixed vocabulary)- Encoded as text embeddings via bi-encoder (semantic matching, not exact string match)
- Any string works:
"disease","pharmaceutical compound","19th century French philosopher" - Replaces default types completely - model only extracts the specified types
- To include defaults, pass them explicitly:
&["person", "organization", "disease"]
threshold- Confidence threshold (0.0 - 1.0)
§Returns
Entities with their matched types
§Behavior
- Arbitrary text: Type hints are not fixed vocabulary. They’re encoded as embeddings, so semantic similarity determines matches (not exact string matching).
- Replace, don’t union: This method completely replaces default entity types. The model only extracts the types you specify.
- Semantic matching: Uses cosine similarity between text span embeddings and label embeddings.
Sourcefn extract_with_descriptions(
&self,
text: &str,
descriptions: &[&str],
threshold: f32,
) -> Result<Vec<Entity>, Error>
fn extract_with_descriptions( &self, text: &str, descriptions: &[&str], threshold: f32, ) -> Result<Vec<Entity>, Error>
Extract entities with natural language descriptions.
§Arguments
text- Input textdescriptions- Natural language descriptions of what to extract- Encoded as text embeddings (same as
extract_with_types) - Examples:
"companies headquartered in Europe","diseases affecting the heart" - Replaces default types completely - model only extracts the specified descriptions
- Encoded as text embeddings (same as
threshold- Confidence threshold
§Behavior
Same as extract_with_types, but accepts natural language descriptions instead of
short type labels. Both methods encode labels as embeddings and use semantic matching.
Sourcefn default_types(&self) -> &[&'static str]
fn default_types(&self) -> &[&'static str]
Get default entity types for this model.
Returns the entity types used by extract_entities() (via Model trait).
Useful for extending defaults: combine with custom types and pass to extract_with_types().
§Example: Extending defaults
use anno::backends::inference::ZeroShotNER;
let ner: &dyn ZeroShotNER = ...;
let defaults = ner.default_types();
// Combine defaults with custom types
let mut types: Vec<&str> = defaults.to_vec();
types.extend(&["disease", "medication"]);
let entities = ner.extract_with_types(text, &types, 0.5)?;Provided Methods§
Sourcefn extract_with_described_types(
&self,
text: &str,
types_with_descriptions: &[(&str, &str)],
threshold: f32,
) -> Result<Vec<Entity>, Error>
fn extract_with_described_types( &self, text: &str, types_with_descriptions: &[(&str, &str)], threshold: f32, ) -> Result<Vec<Entity>, Error>
Extract entities with paired short label + free-text description per type.
§Arguments
text- Input texttypes_with_descriptions-(label, description)pairs. The label is the short form returned on the resultingEntity(e.g."person"); the description is a natural-language hint that GLiNER-style models can use to disambiguate (e.g."a named human individual, not a pronoun"). An empty description string disables the hint for that label.threshold- Confidence threshold (0.0 - 1.0)
§Behavior
The default implementation IGNORES descriptions and falls back to
Self::extract_with_types using just the labels. Backends that natively
support description-augmented prompting (e.g. GLiNER’s documented
quality-boosting form, paper arXiv:2311.08526 §4.3) should override
this method.
Returned entities are labeled with the short form (the label element
of each pair), regardless of how the underlying model handles the
description.
§Example
use anno::backends::inference::ZeroShotNER;
let ner: &dyn ZeroShotNER = ...;
let entities = ner.extract_with_described_types(
"Marie Curie discovered radium.",
&[
("person", "a named human individual"),
("substance", "a chemical element or compound"),
],
0.5,
)?;Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementors§
impl ZeroShotNER for AnyModel
impl ZeroShotNER for GLiNERCandle
candle only.impl ZeroShotNER for GLiNERMultitaskCandle
candle only.impl ZeroShotNER for GLiNERMultitaskOnnx
onnx only.impl ZeroShotNER for GLiNEROnnx
onnx only.impl ZeroShotNER for GLiNERPoly
onnx only.impl ZeroShotNER for HeuristicFrNer
impl ZeroShotNER for NuNER
onnx only.