Recursive AI

Zero-shot entity extraction in C#

OneNLP is a free, open-source natural language processing library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies.

Pass entity type names at runtime to extract matching mentions. The model is in RecursiveAI.OneNlp.Models.Multilingual and works on English text.

Terminal
dotnet add package RecursiveAI.OneNlp
dotnet add package RecursiveAI.OneNlp.Models.Multilingual

Requires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.

C#
using RecursiveAI.OneNlp;
 
var entities = Nlp.Entities(
    "Acme Corp. signed with Beta LLC.",
    "organization");
foreach (var entity in entities)
    Console.WriteLine(
        $"{entity.Label}: {entity}");
Text
organization: Acme Corp.
organization: Beta LLC

Without the model package, this overload throws InvalidOperationException naming RecursiveAI.OneNlp.Models.Multilingual; it never downloads a model.

Unzip the example, then dotnet run.

Variations

Lower the threshold for a less familiar type name. Replace Program.cs with:

C#
using RecursiveAI.OneNlp;
 
var entities = Nlp.Entities(
    "Acme Corp. signed with Beta LLC.",
    ["contract party"], 0.1f);
foreach (var entity in entities)
    Console.WriteLine(
        $"{entity.Label}: {entity}");
Text
contract party: Acme Corp.
contract party: Beta LLC

The short answer

Install RecursiveAI.OneNlp.Models.Multilingual and call Nlp.Entities(text, types) with the entity type names you want. The example requests organization, not a fixed label inventory. The model weights are embedded in NuGet packages and registered by the model package; inference does not fetch them on demand.

The shipped open-type model is English-only. Accepting a runtime label does not guarantee useful extraction for that label. In particular, an unfamiliar business-specific term may score below the default threshold even when a familiar category name finds the same mention.

Can you give me an example of zero-shot learning?

For this task, you give the recognizer an entity type name at inference time rather than retraining a fixed-label recognizer for that request. The snippet at the top asks for organization and extracts Acme Corp. and Beta LLC. The variation asks for contract party on the same input, with a lower threshold.

The open-type documentation uses “zero-shot” in a specific evaluation sense: no examples from the evaluated zero-shot dataset were used to train or select the model. It does not mean every requested label word was unseen in training. Calling the API with a custom label is not evidence that it has never encountered that concept.

Type names are part of the model input. The recognizer encodes each name and compares candidate text spans with it. The label in a returned entity is the type string you supplied. Choose clear names that express what should count as a mention, and keep that inventory stable while assessing extraction behavior.

The documented limits are one to 256 distinct type strings, each at most 200 characters. Candidate spans are at most 12 tokens. Output is flat: when predictions overlap, the more probable one wins. A request for both a broad and a narrow category therefore does not necessarily produce two labels for the same text span.

How do I extract custom entity types in C#?

Use the overload with a type list and an explicit threshold when the default does not fit your data. The default is 0.5; spans at or above it are retained before overlap selection. The variation lowers it to 0.1 for contract party. That is a working example on this sentence, not a recommended setting for contracts in general.

A lower threshold admits lower-scoring spans and can add unwanted matches. Check representative text manually before using a new type or threshold in a workflow. Include sentences with no matching entity, ambiguous names, longer mentions and multiple possible types. An empty result can mean the text has no qualifying mention, the label is poorly understood, or the threshold excluded the prediction.

The documentation reports weaker recall on its zero-shot evaluations and recommends the ordinary entity recognizer when types are fixed and labeled training data is available. This API should not be treated as a guarantee of complete extraction. If missing a party or product would change a decision, inspect those results rather than equating an empty list with proof of absence.

The library’s permissive license is separate from model-data terms. The open-type model documentation identifies share-alike lineage in the shipped model’s training data; consult the package’s third-party notices when distributing model assets. The downloadable example contains code and package references, not a copy of those weights.

All onenlp recipes