Turn sentences into numeric vectors for similarity and search, locally.
dotnet add package RecursiveAI.OneNlp.Models.EmbeddingsRequires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.
using RecursiveAI.OneNlp; float[] vector = Nlp.Embed( "Reset my password"); Console.WriteLine( $"Dimensions: {vector.Length}");
Dimensions: 384Unzip the example, then dotnet run.
Full program
The program embeds “Reset my password” and prints the vector length. This English model is bge-small-en-v1.5; the vector has 384 floating-point values. The zip contains the code and package references, not a second copy of the model. NuGet lists the embeddings package download as 72.67 MB; that is the package itself, excluding dependencies.
The download’s Program.cs is the snippet above.
dotnet run prints:
Dimensions: 384If no embedding model package is registered, Nlp.Embed throws InvalidOperationException telling you which package to add.
Variations
Compare two sentences. This standalone snippet computes cosine similarity from the two vectors. A larger cosine means the vectors point in a more similar direction; it is not a probability.
using RecursiveAI.OneNlp; float[] first = Nlp.Embed("Reset my password"); float[] second = Nlp.Embed("I forgot my password"); double dot = 0, firstNorm = 0, secondNorm = 0; for (int i = 0; i < first.Length; i++) { dot += first[i] * second[i]; firstNorm += first[i] * first[i]; secondNorm += second[i] * second[i]; } double cosine = dot / Math.Sqrt(firstNorm * secondNorm); Console.WriteLine(FormattableString.Invariant($"Cosine: {cosine:F3}"));
Cosine: 0.900Related recipes
The short answer
Install RecursiveAI.OneNlp.Models.Embeddings and call Nlp.Embed(text) to generate a sentence embedding in C#. The result is a float[]. The English package uses bge-small-en-v1.5, and the program above produces a vector with 384 values. No hosted embedding service is involved in this example.
The model travels in the NuGet package. The project’s package restore obtains it; the analysis call does not download a model. This distinction matters when preparing a machine that will later run without network access: complete package restore and deployment before going offline. See sentence embeddings for loading and model behavior.
How do I use sentence embeddings for semantic search in C#?
Embed the searchable text, retain its vector alongside its identifier and compare a query vector with the stored vectors. The variation shows the comparison step for two sentences. It divides the dot product by both vector lengths, giving cosine similarity rather than a raw sum that depends on vector magnitude.
Keep the model and preprocessing consistent between indexing and querying. If you switch models, regenerate stored vectors rather than comparing values from unrelated embedding spaces. A matching array length is not evidence that the vectors are compatible. For an application, also keep the original text or a reference to it: the vector is a representation for ranking, not a replacement from which the sentence can be recovered.
The example’s cosine is a measured result for those two strings. It is not a universal threshold for duplicate text, relevance or intent. Choose thresholds on examples from your own application, including plausible wrong matches. Ranking a small set of candidates and rejecting unrelated inputs are separate decisions.
Can I generate ONNX sentence embeddings locally?
The embedding API supports a sentence-transformers-format model directory through SentenceEmbedder.Load. That directory includes the ONNX encoder, tokenizer and module configuration. The documented supported modules are Transformer, Pooling and Normalize; unsupported modules throw NotSupportedException rather than silently being ignored.
A random ONNX file is therefore not enough. The tokenizer, pooling and normalization must match the encoder. Use the packaged model for the shortest setup, or provide the complete documented export when you need to choose a model yourself. Long input is truncated to the configured maximum token length, so a vector for a long document may not represent its entire contents. Split long material into useful search units before embedding it.
Which sentence embedding models can I use?
The separate RecursiveAI.OneNlp.Models.Embeddings.Multilingual package supplies multilingual-e5-small. The documentation states that it registers at higher priority than the English model. Referencing both changes the default used by Nlp.Embed.
E5 also distinguishes queries from passages. Its default Nlp.Embed path adds the query prefix, which is appropriate for the documented similarity use case. Retrieval applications should use the model’s explicit query and passage helpers so stored documents receive the passage prefix. Do not assume the English example’s preprocessing or similarity score transfers unchanged to a different model. Pick one deployment configuration and record it with your stored vectors.