{
  "schema_version": 2,
  "id": "develop/clients/dotnet/vecsets",
  "title": "Vector set embeddings",
  "url": "https://redis.io/docs/latest/develop/clients/dotnet/vecsets/",
  "summary": "Index and query embeddings with Redis vector sets",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-09-18T16:06:13+01:00",
  "page_type": "content",
  "content_hash": "b96fe805ff21959e903d786b914abf1ba61ebb42605630a01c9a21136cb0619c",
  "sections": [
    {
      "id": "initialize",
      "title": "Initialize",
      "role": "content",
      "text": "Start by installing `StackExchange.Redis` with the following\ncommand (version 2.9.17 or later is required for vector sets):\n\n[code example]\n\nAlso, install `Microsoft.ML`:\n\n[code example]\n\nIn a new C# file, import the required classes:\n\nFoundational: Import required libraries for vector sets, embeddings, and Redis operations\n\n**Difficulty:** Beginner\n\n**Available in:** C#\n\n##### C#\n\n[code example]"
    },
    {
      "id": "access-the-model",
      "title": "Access the model",
      "role": "content",
      "text": "Use the `GetPredictionEngine()` helper function declared in the example below to load the model that creates the embeddings:\n\nPractical pattern: Initialize a SentenceTransformer model to generate vector embeddings from text\n\n**Difficulty:** Beginner\n\n**Available in:** C#\n\n##### C#\n\n[code example]\n\n\n\nThe `GetPredictionEngine()` function uses two classes, `TextData` and `TransformedTextData`,\nto specify the `PredictionEngine` model. These have a very simple definition\nand are required because the model expects the input and output to be\npassed in named object fields:\n\nFoundational: Define data classes for the embedding model's input and output structures\n\n**Difficulty:** Beginner\n\n**Available in:** C#\n\n##### C#\n\n[code example]\n\n\n\nNote that you must declare these classes at the end of the source file\nif you are using a console app without a main class.\n\nThe `GetEmbedding()` function declared below can then use this model to\ngenerate an embedding from a section of text and return it as a `float[]` array,\nwhich is the format required by the vector set API:\n\nFoundational: Create a function to generate vector embeddings from text using the prediction engine\n\n**Difficulty:** Beginner\n\n**Available in:** C#\n\n##### C#\n\n[code example]"
    },
    {
      "id": "create-the-data",
      "title": "Create the data",
      "role": "content",
      "text": "The example data is contained a `Dictionary` object with some brief\ndescriptions of famous people:\n\nFoundational: Define sample data with text descriptions for vector embedding and storage\n\n**Difficulty:** Beginner\n\n**Available in:** C#\n\n##### C#\n\n[code example]"
    },
    {
      "id": "add-the-data-to-a-vector-set",
      "title": "Add the data to a vector set",
      "role": "content",
      "text": "The next step is to connect to Redis and add the data to a new vector set.\n\nThe code below iterates through `peopleData` and adds corresponding\nelements to a vector set called `famousPeople`.\n\nUse the `GetEmbedding()` function declared above to generate the\nembedding as a `byte` array that you can pass to the\n[`VectorSetAdd()`](https://redis.io/docs/latest/commands/vadd) command to set the embedding.\n\nThe call to `VectorSetAdd()` also adds the `born` and `died` values from the\noriginal dictionary as attribute data. You can access this during a query\nor by using the [`VectorSetGetAttributesJson()`](https://redis.io/docs/latest/commands/vgetattr) method.\n\nFoundational: Add vector embeddings and attributes to a vector set using VADD command\n\n**Difficulty:** Beginner\n\n**Available in:** C#\n\n##### C#\n\n[code example]"
    },
    {
      "id": "query-the-vector-set",
      "title": "Query the vector set",
      "role": "content",
      "text": "You can now query the data in the set. The basic approach is to use the\n`GetEmbedding()` function to generate another embedding vector for the query text.\n(This is the same method used to add the elements to the set.) Then, pass\nthe query vector to [`VectorSetSimilaritySearch()`](https://redis.io/docs/latest/commands/vsim) to \nreturn elements of the set, ranked in order of similarity to the query.\n\nStart with a simple query for \"actors\":\n\nVector similarity search: Find semantically similar items in a vector set using VSIM command\n\n**Difficulty:** Intermediate\n\n**Available in:** C#\n\n##### C#\n\n[code example]\n\n\n\nThis returns the following list of elements (formatted slightly for clarity):\n\n[code example]\n\nThe first two people in the list are the two actors, as expected, but none of the\npeople from Linus Pauling onward was especially well-known for acting (and there certainly\nisn't any information about that in the short description text).\nAs it stands, the search attempts to rank all the elements in the set, based\non the information contained in the embedding model.\nYou can use the `Count` property of `VectorSetSimilaritySearchRequest` to limit the\nlist of elements to just the most relevant few items:\n\nVector similarity search with limits: Restrict results to the top K most similar items using the count parameter\n\n**Difficulty:** Intermediate\n\n**Available in:** C#\n\n##### C#\n\n[code example]\n\n\n\nThe reason for using text embeddings rather than simple text search\nis that the embeddings represent semantic information. This allows a query\nto find elements with a similar meaning even if the text is\ndifferent. For example, the word \"entertainer\" doesn't appear in any of the\ndescriptions but if you use it as a query, the actors and musicians are ranked\nhighest in the results list:\n\nSemantic search: Leverage text embeddings to find semantically similar items even when exact keywords don't match\n\n**Difficulty:** Intermediate\n\n**Available in:** C#\n\n##### C#\n\n[code example]\n\n\n\nSimilarly, if you use \"science\" as a query, you get the following results:\n\n[code example]\n\nThe scientists are ranked highest but they are then followed by the\nmathematicians. This seems reasonable given the connection between mathematics\nand science.\n\nYou can also use\n[filter expressions](https://redis.io/docs/latest/develop/data-types/vector-sets/filtered-search)\nwith `VectorSetSimilaritySearch()` to restrict the search further. For example,\nrepeat the \"science\" query, but this time limit the results to people\nwho died before the year 2000:\n\nFiltered vector search: Combine vector similarity with attribute filters to narrow results based on metadata conditions\n\n**Difficulty:** Advanced\n\n**Available in:** C#\n\n##### C#\n\n[code example]\n\n\n\nNote that the boolean filter expression is applied to items in the list\nbefore the vector distance calculation is performed. Items that don't\npass the filter test are removed from the results completely, rather\nthan just reduced in rank. This can help to improve the performance of the\nsearch because there is no need to calculate the vector distance for\nelements that have already been filtered out of the search."
    },
    {
      "id": "more-information",
      "title": "More information",
      "role": "content",
      "text": "See the [vector sets](https://redis.io/docs/latest/develop/data-types/vector-sets)\ndocs for more information and code examples. See the\n[Redis for AI](https://redis.io/docs/latest/develop/ai) section for more details\nabout text embeddings and other AI techniques you can use with Redis.\n\nYou may also be interested in\n[vector search](https://redis.io/docs/latest/develop/clients/dotnet/nredisstack/vecsearch).\nThis is a feature of \n[Redis Search](https://redis.io/docs/latest/develop/ai/search-and-query)\nthat lets you retrieve\n[JSON](https://redis.io/docs/latest/develop/data-types/json) and\n[hash](https://redis.io/docs/latest/develop/data-types/hashes) documents based on\nvector data stored in their fields."
    }
  ],
  "examples": [
    {
      "id": "initialize-ex0",
      "language": "bash",
      "code": "dotnet add package StackExchange.Redis --version 2.9.17",
      "section_id": "initialize"
    },
    {
      "id": "initialize-ex1",
      "language": "bash",
      "code": "dotnet add package Microsoft.ML",
      "section_id": "initialize"
    },
    {
      "id": "initialize-ex2",
      "language": "csharp",
      "code": "using StackExchange.Redis;\n\nusing Microsoft.ML;\nusing Microsoft.ML.Transforms.Text;",
      "section_id": "initialize"
    },
    {
      "id": "access-the-model-ex0",
      "language": "csharp",
      "code": "static PredictionEngine<TextData, TransformedTextData> GetPredictionEngine()\n{\n    // Create a new ML context, for ML.NET operations. It can be used for\n    // exception tracking and logging, as well as the source of randomness.\n    var mlContext = new MLContext();\n\n    // Create an empty list as the dataset\n    var emptySamples = new List<TextData>();\n\n    // Convert sample list to an empty IDataView.\n    var emptyDataView = mlContext.Data.LoadFromEnumerable(emptySamples);\n\n    // A pipeline for converting text into a 150-dimension embedding vector\n    var textPipeline = mlContext.Transforms.Text.NormalizeText(\"Text\")\n        .Append(mlContext.Transforms.Text.TokenizeIntoWords(\"Tokens\",\n            \"Text\"))\n        .Append(mlContext.Transforms.Text.ApplyWordEmbedding(\"Features\",\n            \"Tokens\", WordEmbeddingEstimator.PretrainedModelKind\n            .SentimentSpecificWordEmbedding));\n\n    // Fit to data.\n    var textTransformer = textPipeline.Fit(emptyDataView);\n\n    // Create the prediction engine to get the embedding vector from the input text/string.\n    var predictionEngine = mlContext.Model.CreatePredictionEngine<TextData,\n        TransformedTextData>(textTransformer);\n\n    return predictionEngine;\n}",
      "section_id": "access-the-model"
    },
    {
      "id": "access-the-model-ex1",
      "language": "csharp",
      "code": "class TextData\n{\n    public string Text { get; set; } = string.Empty;\n}\n\nclass TransformedTextData : TextData\n{\n    public float[] Features { get; set; } = Array.Empty<float>();\n}",
      "section_id": "access-the-model"
    },
    {
      "id": "access-the-model-ex2",
      "language": "csharp",
      "code": "static float[] GetEmbedding(\n    PredictionEngine<TextData, TransformedTextData> model, string sentence\n)\n{\n    // Call the prediction API to convert the text into embedding vector.\n    var data = new TextData()\n    {\n        Text = sentence\n    };\n\n    var prediction = model.Predict(data);\n\n    float[] floatArray = Array.ConvertAll(prediction.Features, x => (float)x);\n\n    return floatArray;\n}",
      "section_id": "access-the-model"
    },
    {
      "id": "create-the-data-ex0",
      "language": "csharp",
      "code": "Dictionary<string, dynamic> peopleData = new Dictionary<string, dynamic>\n{\n    [\"Marie Curie\"] = new\n    {\n        born = 1867,\n        died = 1934,\n        description = @\"\n        Polish-French chemist and physicist. The only person ever to win\n        two Nobel prizes for two different sciences.\n        \"\n    },\n    [\"Linus Pauling\"] = new\n    {\n        born = 1901,\n        died = 1994,\n        description = @\"\n        American chemist and peace activist. One of only two people to win two\n        Nobel prizes in different fields (chemistry and peace).\n        \"\n    },\n    [\"Freddie Mercury\"] = new\n    {\n        born = 1946,\n        died = 1991,\n        description = @\"\n        British musician, best known as the lead singer of the rock band\n        Queen.\n        \"\n    },\n    [\"Marie Fredriksson\"] = new\n    {\n        born = 1958,\n        died = 2019,\n        description = @\"\n        Swedish multi-instrumentalist, mainly known as the lead singer and\n        keyboardist of the band Roxette.\n        \"\n    },\n    [\"Paul Erdos\"] = new\n    {\n        born = 1913,\n        died = 1996,\n        description = @\"\n        Hungarian mathematician, known for his eccentric personality almost\n        as much as his contributions to many different fields of mathematics.\n        \"\n    },\n    [\"Maryam Mirzakhani\"] = new\n    {\n        born = 1977,\n        died = 2017,\n        description = @\"\n        Iranian mathematician. The first woman ever to win the Fields medal\n        for her contributions to mathematics.\n        \"\n    },\n    [\"Masako Natsume\"] = new\n    {\n        born = 1957,\n        died = 1985,\n        description = @\"\n        Japanese actress. She was very famous in Japan but was primarily\n        known elsewhere in the world for her portrayal of Tripitaka in the\n        TV series Monkey.\n        \"\n    },\n    [\"Chaim Topol\"] = new\n    {\n        born = 1935,\n        died = 2023,\n        description = @\"\n        Israeli actor and singer, usually credited simply as 'Topol'. He was\n        best known for his many appearances as Tevye in the musical Fiddler\n        on the Roof.\n        \"\n    }\n};",
      "section_id": "create-the-data"
    },
    {
      "id": "add-the-data-to-a-vector-set-ex0",
      "language": "csharp",
      "code": "ConnectionMultiplexer muxer = ConnectionMultiplexer.Connect(\"localhost:6379\");\nIDatabase db = muxer.GetDatabase();\n\nPredictionEngine<TextData, TransformedTextData> model = GetPredictionEngine();\n\nforeach (KeyValuePair<string, dynamic> person in peopleData)\n{\n    string name = person.Key;\n    dynamic details = person.Value;\n    float[] embedding = GetEmbedding(model, details.description);\n\n    VectorSetAddRequest addRequest = VectorSetAddRequest.Member(name, embedding, null);\n    db.VectorSetAdd(\"famousPeople\", addRequest);\n\n    // Set attributes separately\n    string attributesJson = $\"{{\\\"born\\\": {details.born}, \\\"died\\\": {details.died}}}\";\n    db.VectorSetSetAttributesJson(\"famousPeople\", name, attributesJson);\n}",
      "section_id": "add-the-data-to-a-vector-set"
    },
    {
      "id": "query-the-vector-set-ex0",
      "language": "csharp",
      "code": "string queryValue = \"actors\";\n\nfloat[] queryEmbedding = GetEmbedding(model, queryValue);\n\nVectorSetSimilaritySearchRequest basicQuery = VectorSetSimilaritySearchRequest.ByVector(queryEmbedding);\nusing (Lease<VectorSetSimilaritySearchResult>? actorsResults = db.VectorSetSimilaritySearch(\"famousPeople\", basicQuery))\n{\n    IEnumerable<string> resultIds = actorsResults!.Span.ToArray()\n        .Select(r => (string?)r.Member)\n        .Where(id => id != null)\n        .Select(id => $\"'{id!}'\");\n    Console.WriteLine($\"'actors': [{string.Join(\", \", resultIds)}]\");\n}",
      "section_id": "query-the-vector-set"
    },
    {
      "id": "query-the-vector-set-ex1",
      "language": "plaintext",
      "code": "'actors': ['Masako Natsume', 'Chaim Topol', 'Linus Pauling',\n'Marie Fredriksson', 'Maryam Mirzakhani', 'Marie Curie',\n'Freddie Mercury', 'Paul Erdos']",
      "section_id": "query-the-vector-set"
    },
    {
      "id": "query-the-vector-set-ex2",
      "language": "csharp",
      "code": "queryValue = \"actors\";\n\nqueryEmbedding = GetEmbedding(model, queryValue);\n\nVectorSetSimilaritySearchRequest limitedQuery = VectorSetSimilaritySearchRequest.ByVector(queryEmbedding);\nlimitedQuery.Count = 2;\nusing (Lease<VectorSetSimilaritySearchResult>? twoActorsResults = db.VectorSetSimilaritySearch(\"famousPeople\", limitedQuery))\n{\n    IEnumerable<string> resultIds = twoActorsResults!.Span.ToArray()\n        .Select(r => (string?)r.Member)\n        .Where(id => id != null)\n        .Select(id => $\"'{id!}'\");\n    Console.WriteLine($\"'actors (2)': [{string.Join(\", \", resultIds)}]\");\n    // >>> 'actors (2)': ['Masako Natsume', 'Chaim Topol']\n}",
      "section_id": "query-the-vector-set"
    },
    {
      "id": "query-the-vector-set-ex3",
      "language": "csharp",
      "code": "queryValue = \"entertainer\";\n\nqueryEmbedding = GetEmbedding(model, queryValue);\n\nVectorSetSimilaritySearchRequest entertainerQuery = VectorSetSimilaritySearchRequest.ByVector(queryEmbedding);\nusing (Lease<VectorSetSimilaritySearchResult>? entertainerResults = db.VectorSetSimilaritySearch(\"famousPeople\", entertainerQuery))\n{\n    IEnumerable<string> resultIds = entertainerResults!.Span.ToArray()\n        .Select(r => (string?)r.Member)\n        .Where(id => id != null)\n        .Select(id => $\"'{id!}'\");\n    Console.WriteLine($\"'entertainer': [{string.Join(\", \", resultIds)}]\");\n    // >>> 'entertainer': ['Chaim Topol', 'Freddie Mercury',\n    // 'Marie Fredriksson', 'Masako Natsume', 'Linus Pauling',\n    // 'Paul Erdos', 'Maryam Mirzakhani', 'Marie Curie']\n}",
      "section_id": "query-the-vector-set"
    },
    {
      "id": "query-the-vector-set-ex4",
      "language": "plaintext",
      "code": "'science': ['Marie Curie', 'Linus Pauling', 'Maryam Mirzakhani',\n'Paul Erdos', 'Marie Fredriksson', 'Freddie Mercury', 'Masako Natsume',\n'Chaim Topol']",
      "section_id": "query-the-vector-set"
    },
    {
      "id": "query-the-vector-set-ex5",
      "language": "csharp",
      "code": "queryValue = \"science\";\n\nqueryEmbedding = GetEmbedding(model, queryValue);\n\nVectorSetSimilaritySearchRequest filteredQuery = VectorSetSimilaritySearchRequest.ByVector(queryEmbedding);\nfilteredQuery.FilterExpression = \".died < 2000\";\nusing (Lease<VectorSetSimilaritySearchResult>? science2000Results = db.VectorSetSimilaritySearch(\"famousPeople\", filteredQuery))\n{\n    IEnumerable<string> resultIds = science2000Results!.Span.ToArray()\n        .Select(r => (string?)r.Member)\n        .Where(id => id != null)\n        .Select(id => $\"'{id!}'\");\n    Console.WriteLine($\"'science2000': [{string.Join(\", \", resultIds)}]\");\n    // >>> 'science2000': ['Marie Curie', 'Linus Pauling',\n    // 'Paul Erdos', 'Freddie Mercury', 'Masako Natsume']\n}",
      "section_id": "query-the-vector-set"
    }
  ]
}
