Skip to content

Commit 9289b31

Browse files
committed
agentic search C# SDK
1 parent a915bc4 commit 9289b31

File tree

2 files changed

+79
-71
lines changed

2 files changed

+79
-71
lines changed

articles/search/includes/quickstarts/agentic-retrieval-csharp.md

Lines changed: 78 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,21 @@ Although you can provide your own data, this quickstart uses [sample JSON docume
103103
using OpenAI.Chat;
104104
105105
namespace AzureSearch.Quickstart
106-
{ class Program
106+
{
107+
class Program
107108
{
108109
static async Task Main(string[] args)
109-
{
110+
{
110111
// Load environment variables from .env file
111112
// Ensure you have a .env file in the same directory with the required variables.
112113
DotEnv.Load();
113114
114115
string endpoint = Environment.GetEnvironmentVariable("AZURE_SEARCH_ENDPOINT")
115116
?? throw new InvalidOperationException("AZURE_SEARCH_ENDPOINT is not set.");
116117
string azureOpenAIEndpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
117-
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); string azureOpenAIGptDeployment = "gpt-4.1-mini";
118+
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
119+
120+
string azureOpenAIGptDeployment = "gpt-4.1-mini";
118121
string azureOpenAIGptModel = "gpt-4.1-mini";
119122
string azureOpenAIEmbeddingDeployment = "text-embedding-3-large";
120123
string azureOpenAIEmbeddingModel = "text-embedding-3-large";
@@ -123,15 +126,35 @@ Although you can provide your own data, this quickstart uses [sample JSON docume
123126
string agentName = "earth-search-agent";
124127
125128
var credential = new DefaultAzureCredential();
129+
126130
// Define the fields for the index
127131
var fields = new List<SearchField>
128132
{
129-
new SimpleField("id", SearchFieldDataType.String) { IsKey = true, IsFilterable = true, IsSortable = true, IsFacetable = true },
130-
new SearchField("page_chunk", SearchFieldDataType.String) { IsFilterable = false, IsSortable = false, IsFacetable = false },
131-
new SearchField("page_embedding_text_3_large", SearchFieldDataType.Collection(SearchFieldDataType.Single)) { VectorSearchDimensions = 3072, VectorSearchProfileName = "hnsw_text_3_large" },
132-
new SimpleField("page_number", SearchFieldDataType.Int32) { IsFilterable = true, IsSortable = true, IsFacetable = true }
133-
};
134-
// Define the vectorizer
133+
new SimpleField("id", SearchFieldDataType.String)
134+
{
135+
IsKey = true,
136+
IsFilterable = true,
137+
IsSortable = true,
138+
IsFacetable = true
139+
},
140+
new SearchField("page_chunk", SearchFieldDataType.String)
141+
{
142+
IsFilterable = false,
143+
IsSortable = false,
144+
IsFacetable = false
145+
},
146+
new SearchField("page_embedding_text_3_large", SearchFieldDataType.Collection(SearchFieldDataType.Single))
147+
{
148+
VectorSearchDimensions = 3072,
149+
VectorSearchProfileName = "hnsw_text_3_large"
150+
},
151+
new SimpleField("page_number", SearchFieldDataType.Int32)
152+
{
153+
IsFilterable = true,
154+
IsSortable = true,
155+
IsFacetable = true
156+
}
157+
};// Define the vectorizer
135158
var vectorizer = new AzureOpenAIVectorizer(vectorizerName: "azure_openai_text_3_large")
136159
{
137160
Parameters = new AzureOpenAIVectorizerParameters
@@ -191,7 +214,7 @@ Although you can provide your own data, this quickstart uses [sample JSON docume
191214
SemanticSearch = semanticSearch
192215
};
193216
194-
// Create the index client and delete the index if it exists, then create it
217+
// Create the index client. Delete the index if it exists and then recreate it.
195218
var indexClient = new SearchIndexClient(new Uri(endpoint), credential);
196219
try
197220
{
@@ -201,9 +224,8 @@ Although you can provide your own data, this quickstart uses [sample JSON docume
201224
catch (Exception ex)
202225
{
203226
Console.WriteLine($"Index '{indexName}' could not be deleted or did not exist: {ex.Message}");
204-
}
227+
}
205228
await indexClient.CreateOrUpdateIndexAsync(index);
206-
207229
Console.WriteLine($"Index '{indexName}' created or updated successfully");
208230
209231
// Download the documents from the GitHub URL
@@ -221,13 +243,11 @@ Although you can provide your own data, this quickstart uses [sample JSON docume
221243
{
222244
KeyFieldAccessor = doc => doc["id"].ToString(),
223245
}
224-
);
225-
246+
);
226247
await searchIndexingBufferedSender.UploadDocumentsAsync(documents);
227248
await searchIndexingBufferedSender.FlushAsync();
249+
Console.WriteLine($"Documents uploaded to index '{indexName}'");
228250
229-
Console.WriteLine($"Documents uploaded to index '{indexName}'");
230-
231251
var openAiParameters = new AzureOpenAIVectorizerParameters
232252
{
233253
ResourceUri = new Uri(azureOpenAIEndpoint),
@@ -240,8 +260,7 @@ Although you can provide your own data, this quickstart uses [sample JSON docume
240260
var targetIndex = new KnowledgeAgentTargetIndex(indexName)
241261
{
242262
DefaultRerankerThreshold = 2.5f
243-
};
244-
263+
};
245264
// Create the knowledge agent
246265
var agent = new KnowledgeAgent(
247266
name: agentName,
@@ -250,7 +269,6 @@ Although you can provide your own data, this quickstart uses [sample JSON docume
250269
await indexClient.CreateOrUpdateKnowledgeAgentAsync(agent);
251270
Console.WriteLine($"Search agent '{agentName}' created or updated successfully");
252271
253-
254272
string instructions = @"
255273
A Q&A agent that can answer questions about the Earth at night.
256274
Sources have a JSON format with a ref_id that must be cited in the answer.
@@ -264,46 +282,42 @@ Although you can provide your own data, this quickstart uses [sample JSON docume
264282
{ "role", "system" },
265283
{ "content", instructions }
266284
}
267-
};
268-
285+
};
269286
var agentClient = new KnowledgeAgentRetrievalClient(
270287
endpoint: new Uri(endpoint),
271288
agentName: agentName,
272289
tokenCredential: new DefaultAzureCredential()
273-
);
274-
290+
);
291+
275292
messages.Add(new Dictionary<string, object>
276293
{
277294
{ "role", "user" },
278295
{ "content", @"
279-
Why do suburban belts display larger December brightening than urban cores even though absolute light levels are higher downtown?
280-
Why is the Phoenix nighttime street grid is so sharply visible from space, whereas large stretches of the interstate between midwestern cities remain comparatively dim?
281-
" }
282-
});
283-
296+
Why do suburban belts display larger December brightening than urban cores even though absolute light levels are higher downtown?
297+
Why is the Phoenix nighttime street grid is so sharply visible from space, whereas large stretches of the interstate between midwestern cities remain comparatively dim?
298+
" }
299+
});
284300
var retrievalResult = await agentClient.RetrieveAsync(
285301
retrievalRequest: new KnowledgeAgentRetrievalRequest(
286-
messages: messages
287-
.Where(message => message["role"].ToString() != "system")
288-
.Select(
289-
message => new KnowledgeAgentMessage(
290-
role: message["role"].ToString(),
291-
content: new[] { new KnowledgeAgentMessageTextContent(message["content"].ToString()) }))
292-
.ToList()
293-
)
294-
{
295-
TargetIndexParams = { new KnowledgeAgentIndexParams { IndexName = indexName, RerankerThreshold = 2.5f } }
296-
}
297-
);
298-
302+
messages: messages
303+
.Where(message => message["role"].ToString() != "system")
304+
.Select(message => new KnowledgeAgentMessage(
305+
role: message["role"].ToString(),
306+
content: new[] { new KnowledgeAgentMessageTextContent(message["content"].ToString()) }))
307+
.ToList()
308+
)
309+
{
310+
TargetIndexParams = { new KnowledgeAgentIndexParams { IndexName = indexName, RerankerThreshold = 2.5f } }
311+
}
312+
);
299313
messages.Add(new Dictionary<string, object>
300314
{
301315
{ "role", "assistant" },
302316
{ "content", (retrievalResult.Value.Response[0].Content[0] as KnowledgeAgentMessageTextContent).Text }
303317
});
304318
305-
// Print
306-
Console.WriteLine((retrievalResult.Value.Response[0].Content[0] as KnowledgeAgentMessageTextContent).Text);
319+
Console.WriteLine((retrievalResult.Value.Response[0].Content[0] as KnowledgeAgentMessageTextContent).Text);
320+
307321
Console.WriteLine("Activities:");
308322
foreach (var activity in retrievalResult.Value.Activity)
309323
{
@@ -325,50 +339,46 @@ Although you can provide your own data, this quickstart uses [sample JSON docume
325339
reference.GetType(),
326340
new JsonSerializerOptions { WriteIndented = true }
327341
);
328-
Console.WriteLine(referenceJson);
329-
}
330-
342+
Console.WriteLine(referenceJson); }
331343
332344
AzureOpenAIClient azureClient = new(
333345
new Uri(azureOpenAIEndpoint),
334346
new DefaultAzureCredential());
335-
ChatClient chatClient = azureClient.GetChatClient(azureOpenAIGptDeployment);
347+
ChatClient chatClient = azureClient.GetChatClient(azureOpenAIGptDeployment);
348+
336349
List<ChatMessage> chatMessages = messages
337350
.Select<Dictionary<string, object>, ChatMessage>(m => m["role"].ToString() switch
338351
{
339352
"user" => new UserChatMessage(m["content"].ToString()),
340353
"assistant" => new AssistantChatMessage(m["content"].ToString()),
341354
"system" => new SystemChatMessage(m["content"].ToString()),
342355
_ => null
343-
})
356+
})
344357
.Where(m => m != null)
345358
.ToList();
346359
347-
348360
var result = await chatClient.CompleteChatAsync(chatMessages);
349-
350361
Console.WriteLine($"[ASSISTANT]: {result.Value.Content[0].Text.Replace(".", "\n")}");
351362
352363
messages.Add(new Dictionary<string, object>
353364
{
354365
{ "role", "user" },
355-
{ "content", "How do I find lava at night?" }
366+
{ "content", "How do I find lava at night?" }
356367
});
357368
358369
var retrievalResult2 = await agentClient.RetrieveAsync(
359370
retrievalRequest: new KnowledgeAgentRetrievalRequest(
360-
messages: messages
361-
.Where(message => message["role"].ToString() != "system")
362-
.Select(
363-
message => new KnowledgeAgentMessage(
364-
role: message["role"].ToString(),
365-
content: new[] { new KnowledgeAgentMessageTextContent(message["content"].ToString()) }))
366-
.ToList()
367-
)
368-
{
369-
TargetIndexParams = { new KnowledgeAgentIndexParams { IndexName = indexName, RerankerThreshold = 2.5f } }
370-
}
371-
);
371+
messages: messages
372+
.Where(message => message["role"].ToString() != "system")
373+
.Select(message => new KnowledgeAgentMessage(
374+
role: message["role"].ToString(),
375+
content: new[] { new KnowledgeAgentMessageTextContent(message["content"].ToString()) }))
376+
.ToList()
377+
)
378+
{
379+
TargetIndexParams = { new KnowledgeAgentIndexParams { IndexName = indexName, RerankerThreshold = 2.5f } }
380+
}
381+
);
372382
373383
messages.Add(new Dictionary<string, object>
374384
{
@@ -400,29 +410,27 @@ Although you can provide your own data, this quickstart uses [sample JSON docume
400410
new JsonSerializerOptions { WriteIndented = true }
401411
);
402412
Console.WriteLine(referenceJson2);
403-
} List<ChatMessage> chatMessages2 = messages
413+
}
414+
415+
List<ChatMessage> chatMessages2 = messages
404416
.Select<Dictionary<string, object>, ChatMessage>(m => m["role"].ToString() switch
405417
{
406418
"user" => new UserChatMessage(m["content"].ToString()),
407419
"assistant" => new AssistantChatMessage(m["content"].ToString()),
408420
"system" => new SystemChatMessage(m["content"].ToString()),
409421
_ => null
410-
})
422+
})
411423
.Where(m => m != null)
412424
.ToList();
413425
414-
415426
var result2 = await chatClient.CompleteChatAsync(chatMessages2);
416-
417427
Console.WriteLine($"[ASSISTANT]: {result2.Value.Content[0].Text.Replace(".", "\n")}");
418428
419429
await indexClient.DeleteKnowledgeAgentAsync(agentName);
420430
System.Console.WriteLine($"Search agent '{agentName}' deleted successfully");
421431
422-
await indexClient.DeleteIndexAsync(indexName);
432+
await indexClient.DeleteIndexAsync(indexName);
423433
System.Console.WriteLine($"Index '{indexName}' deleted successfully");
424-
425-
426434
}
427435
}
428436
}

articles/search/search-get-started-agentic-retrieval.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ zone_pivot_groups: search-get-started-agentic-retrieval
1414

1515
::: zone pivot="programming-language-csharp"
1616

17-
[!INCLUDE [Python quickstart](includes/quickstarts/agentic-retrieval-csharp.md)]
17+
[!INCLUDE [C# quickstart](includes/quickstarts/agentic-retrieval-csharp.md)]
1818

1919
::: zone-end
2020

0 commit comments

Comments
 (0)