Sarıkaya Dev Logo

Build a .NET 8 AI‑Enhanced Search Engine with Azure Cognitive Search and OpenAI Embeddings

Mahmut Sarıkaya 4 min read 2 Views 0
Build a .NET 8 AI‑Enhanced Search Engine with Azure Cognitive Search and OpenAI Embeddings

Why vector search matters in .NET 8

Ever wondered how modern applications deliver instant, context‑aware results from millions of documents? Traditional keyword matching struggles with synonyms, misspellings, and nuanced intent. Vector search transforms each piece of text into a high‑dimensional embedding, allowing similarity calculations that capture meaning rather than exact terms. .NET 8’s minimal API, combined with Azure Cognitive Search’s native vector capabilities, makes it possible to build a production‑grade semantic engine in under an hour.

Setting up Azure Cognitive Search for vector fields

Start by provisioning a Search service in the Azure portal (Standard S3 tier or higher is required for vector search). Once the endpoint and admin key are available, create an index that includes a vector field. The following C# snippet shows the index definition; note the VectorSearchDimensions set to 1536, which matches the dimensionality of OpenAI’s text‑embedding‑ada‑002 model.

var index = new SearchIndex("documents")
{
    Fields = new[]
    {
        new SearchField("id", SearchFieldDataType.String) { IsKey = true, IsFilterable = true },
        new SearchField("content", SearchFieldDataType.String) { IsSearchable = true },
        new SearchField("contentVector", SearchFieldDataType.Collection(SearchFieldDataType.Single)) 
        {
            IsSearchable = true,
            VectorSearchDimensions = 1536,
            VectorSearchProfileName = "myProfile"
        }
    },
    VectorSearch = new()
    {
        Profiles = new[]
        {
            new VectorSearchProfile("myProfile", "myHnsw")
        },
        Algorithms = new[]
        {
            new HnswAlgorithmConfiguration("myHnsw") { M = 16, EfConstruction = 200 }
        }
    }
};
await client.CreateOrUpdateIndexAsync(index);

After the index is live, you can upload documents together with their embedding vectors using the UploadDocumentsAsync method.

Generating OpenAI embeddings in C#

Azure OpenAI provides a straightforward SDK for obtaining embeddings. Install the Azure.AI.OpenAI NuGet package and configure the endpoint and key as environment variables. The code below sends a single paragraph to the text‑embedding‑ada‑002 model and extracts the 1536‑float vector.

var openAiClient = new OpenAIClient(new Uri(Environment.GetEnvironmentVariable("OPENAI_ENDPOINT")),
    new AzureKeyCredential(Environment.GetEnvironmentVariable("OPENAI_KEY")));
var embeddingResponse = await openAiClient.GetEmbeddingsAsync(
    new EmbeddingsOptions("text-embedding-ada-002")
    {
        Input = new[] { documentContent }
    });
float[] vector = embeddingResponse.Value.Data[0].Embedding.ToArray();

Batch processing 10,000 records typically completes in under five minutes when you parallelize the calls with Parallel.ForEachAsync and respect the service’s rate limits (≈ 350 RPM for the free tier).

Implementing vector similarity with .NET

Azure Cognitive Search exposes a Vector query operator that accepts a query vector, the number of nearest neighbors (K), and a distance metric. The following minimal‑API endpoint demonstrates a complete request‑response flow: it receives a user query, creates an embedding, runs a vector search, and returns the top results.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<SearchServiceClient>(sp =>
    new SearchServiceClient(
        Environment.GetEnvironmentVariable("SEARCH_ENDPOINT"),
        new AzureKeyCredential(Environment.GetEnvironmentVariable("SEARCH_KEY"))));
var app = builder.Build();
app.MapGet("/search", async (string query, SearchServiceClient client) =>
{
    // 1. Convert query to embedding
    var embed = await openAiClient.GetEmbeddingsAsync(
        new EmbeddingsOptions("text-embedding-ada-002") { Input = new[] { query } });
    var queryVector = embed.Value.Data[0].Embedding.ToArray();

    // 2. Build vector query
    var vectorQuery = new VectorQuery
    {
        Vector = queryVector,
        K = 5,
        Fields = new[] { "contentVector" },
        Parameters = new Dictionary<string, object> { { "distanceMetric", "cosine" } }
    };

    // 3. Execute search
    var results = await client.SearchAsync<Document>("documents", s => s
        .Vector(vectorQuery)
        .Select("id, content, contentVector")
        .Top(5));
    return Results.Ok(results.Value.Results.Select(r => new { r.Document.Id, r.Document.Content }));
});
app.Run();

The endpoint returns a JSON array of the most semantically relevant documents, ready for consumption by a front‑end UI or a chatbot.

Performance tips and monitoring

Vector search workloads are CPU‑intensive during embedding generation but largely I/O‑bound when Azure Search performs the nearest‑neighbor lookup. To keep latency under 200 ms for end users, consider the following:

  • Cache frequently used query embeddings for up to 30 seconds using MemoryCache.
  • Enable Hnsw parameters M=32 and EfSearch=100 for higher recall at modest extra cost.
  • Monitor SearchServiceMetrics in Azure Monitor; key alerts include “VectorSearchLatency” > 250 ms and “SearchRequestsThrottled” > 5%.

When scaling, a multi‑region Search service ensures low round‑trip times for global users while keeping the embedding service close to the data plane.

Conclusion

By marrying .NET 8’s streamlined development model with Azure Cognitive Search’s vector engine and OpenAI’s state‑of‑the‑art embeddings, you can deliver a truly semantic search experience without building a custom ML pipeline. The code samples above cover the entire stack—from index creation to a production‑ready API—so you can start prototyping today and iterate toward a full‑featured, AI‑driven knowledge platform.

Sources

  • Microsoft Azure Cognitive Search documentation
  • Azure OpenAI Service API reference
  • OpenAI embeddings model page (text‑embedding‑ada‑002)

Author: Mahmut Sarıkaya — sarikayadev.com

Tags: #dotnet 8 #azure cognitive search #openai embeddings #vector search #semantic search
Share:
M

Written by

Mahmut Sarıkaya

Software Developer

Comments

No comments yet. Be the first to share your thoughts!

Leave a Comment

8 + 5 =