Recursive AI

Getting started with OneNLP

All onenlp docs

Install OneNLP for .NET 10, find the language, sentences, numbers and dates of a text with the core package alone, then add a model package for entities, lemmas and the parse, and another for sentence embeddings. Every program below was run on the 1.0.0 packages from NuGet, and the output shown is what it printed.

Install

OneNLP targets net10.0, so you need the .NET 10 SDK.

Terminal
dotnet new console -o NlpStart
cd NlpStart
dotnet add package RecursiveAI.OneNlp

The core package depends on the .NET base class library and RecursiveAI.OneFont only, and contains no native code. It holds the tokenizers, word and sentence segmentation, rule matching, the recognizers and language identification for 75 languages. Trained models come in their own packages, one per language or task. Nothing is ever downloaded: a model is delivered with its package.

With the core package alone

Program.cs:

C#
using RecursiveAI.OneNlp;
 
string text = "Angela Merkel met Emmanuel Macron in Paris on 5 March 2026. The deal cost $5m.";
 
// Language ID, sentences and tokens: in the core package, no model needed.
Console.WriteLine(Nlp.DetectLanguage(text));
Console.WriteLine(Nlp.DetectLanguage("Der Vertrag wurde gestern in Berlin unterschrieben."));
 
foreach (Span s in Nlp.Sentences(text))
    Console.WriteLine($"[{s.StartChar}..{s.EndChar}) {s.Text}");
 
Console.WriteLine(string.Join(" | ", Nlp.Tokens(text).Take(8)));
 
// Recognizers: numbers, money, dates, resolved to values.
foreach (Quantity q in Nlp.Quantities(text))
    Console.WriteLine($"{q.Kind} {q.Value} {q.Currency}");
 
DateTimeOffset today = new(2026, 3, 18, 10, 30, 0, TimeSpan.Zero);
DateRange? when = Nlp.ParseDate("the first Monday after Easter 2027", today);
Console.WriteLine(when?.Start.ToString("yyyy-MM-dd"));
 
// A verb that needs a model throws and names the package to add.
try
{
    Nlp.Entities(text);
}
catch (InvalidOperationException e)
{
    Console.WriteLine(e.Message);
}

dotnet run prints:

Text
en
de
[0..59) Angela Merkel met Emmanuel Macron in Paris on 5 March 2026.
[60..78) The deal cost $5m.
Angela | Merkel | met | Emmanuel | Macron | in | Paris | on
Money 5000000 USD
2027-03-29
No model is available for language 'en'. Add the NuGet package RecursiveAI.OneNlp.Models.English (or RecursiveAI.OneNlp.Models.Multilingual); models are never downloaded.

Offsets are UTF-16 offsets into the string you passed in. Relative dates need a reference date, which you pass: Easter 2027 is 28 March, so the first Monday after it is 29 March. The exception is a ModelNotAvailableException, an InvalidOperationException that names the package to add.

Add a model: entities, lemmas and the parse

Terminal
dotnet add package RecursiveAI.OneNlp.Models.English
dotnet add package RecursiveAI.OneNlp.Models.Embeddings

RecursiveAI.OneNlp.Models.English is the English fast tier: tags, morphology, lemmas, the dependency parse and entities. RecursiveAI.OneNlp.Models.Embeddings is the default English sentence embedder for Nlp.Embed (bge-small-en-v1.5, MIT). There is nothing to register: add the package and the Nlp verbs use it for text in its language.

Program.cs:

C#
using RecursiveAI.OneNlp;
 
string text = "Angela Merkel met Emmanuel Macron in Paris on 5 March 2026. The deal cost $5m.";
 
// With RecursiveAI.OneNlp.Models.English: entities, lemmas and the full analysis.
foreach (Span e in Nlp.Entities(text))
    Console.WriteLine($"{e.Label} {e.Text} [{e.StartChar}..{e.EndChar})");
 
Console.WriteLine(string.Join(" ", Nlp.Lemmas("The cats were running.")));
 
Doc doc = Nlp.Analyze(text);
foreach (Token t in doc.Take(5))
    Console.WriteLine($"{t.Text} {t.Pos} {t.Lemma} {t.Dep} -> {t.Head.Text}");
 
// With RecursiveAI.OneNlp.Models.Embeddings: sentence vectors.
float[] a = Nlp.Embed("how do I reset my password");
float[] b = Nlp.Embed("I forgot my password and can't log in");
float[] c = Nlp.Embed("what time does the bakery open");
Console.WriteLine($"{a.Length} dimensions");
Console.WriteLine($"password / login: {Cosine(a, b):F2}");
Console.WriteLine($"password / bakery: {Cosine(a, c):F2}");
 
static float Cosine(float[] x, float[] y)
{
    float dot = 0, nx = 0, ny = 0;
    for (int i = 0; i < x.Length; i++) { dot += x[i] * y[i]; nx += x[i] * x[i]; ny += y[i] * y[i]; }
    return dot / MathF.Sqrt(nx * ny);
}

dotnet run prints:

Text
PER Angela Merkel [0..13)
PER Emmanuel [18..26)
LOC Paris [37..42)
the cat be run .
Angela PROPN Angela compound -> Merkel
Merkel PROPN Merkel nsubj -> met
met VERB meet root -> met
Emmanuel PROPN Emmanuel xcomp -> met
Macron PROPN Macron obj -> met
384 dimensions
password / login: 0.86
password / bakery: 0.49

This is the model’s real output on this sentence, mistakes included: it marks “Emmanuel” alone as a person and attaches “Macron” as the object. Nlp.Analyze returns a Doc with the tokens, sentences, tags, lemmas, the parse and the entities from one call.

Another language

Each fast-tier language is its own package: RecursiveAI.OneNlp.Models.French, .German, .Spanish, .Portuguese, .Dutch, .Italian, .Chinese, .Turkish and .Hindi. With RecursiveAI.OneNlp.Models.German in place of the English model:

C#
using RecursiveAI.OneNlp;
 
string text = "Die Bäckerei Sonnenschein in Hamburg eröffnet am 3. Mai eine zweite Filiale. Der Umbau kostete 12.500 Euro.";
 
Console.WriteLine(Nlp.DetectLanguage(text));
foreach (Span e in Nlp.Entities(text))
    Console.WriteLine($"{e.Label} {e.Text}");
Console.WriteLine(string.Join(" ", Nlp.Lemmas(text).Take(8)));
 
foreach (Quantity q in Nlp.Quantities(text, Language.German))
    Console.WriteLine($"{q.Kind} {q.Value} {q.Currency}");
 
DateTimeOffset today = new(2026, 4, 20, 9, 0, 0, TimeSpan.Zero);
Console.WriteLine(Nlp.ParseDate("am 3. Mai", today, Language.German)?.Start.ToString("yyyy-MM-dd"));

dotnet run prints:

Text
de
ORG Bäckerei Sonnenschein
LOC Hamburg
MISC Euro
der Bäckerei Sonnenschein in Hamburg eröffnen an der
Ordinal 3 
Ordinal 2 
Money 12500 EUR
2026-05-03

The recognizers take the language as an argument (Nlp.Quantities(text) without one reads English). The German model splits “am” into two words, with the lemmas “an” and “der”.

The accurate tiers

Two packages cover many languages with one model:

  • RecursiveAI.OneNlp.Models.Multilingual is the distilled accurate tier: syntax and entities for English, German, French, Spanish, Portuguese, Italian, Dutch, Turkish and Chinese, plus open-type entities (Nlp.Entities(text, types), labels named at runtime).
  • RecursiveAI.OneNlp.Models.Multilingual.Large is the base-size accurate tier: syntax for 84 languages and entities for 19. It is about 3.5 GB across 19 packages; reference the root package only, and deploy the complete publish directory.
Terminal
dotnet add package RecursiveAI.OneNlp.Models.Multilingual.Large

When a fast-tier package for the text’s language is referenced, the Nlp verbs use it; otherwise they use the multilingual accurate tier. See Model packages for the order and for loading one package’s pipeline directly.

Where next