Skip to content

Commit de388e2

Browse files
committed
feat: Enhance vector search providers with appsettings.json configuration support
1 parent b5aefb5 commit de388e2

11 files changed

Lines changed: 547 additions & 4 deletions

File tree

README.md

Lines changed: 129 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -480,21 +480,47 @@ For production deployments with persistent storage and scalable semantic search,
480480
dotnet add package EasyAppDev.Blazor.AutoComplete.AI.PostgreSql
481481
```
482482

483+
**Using appsettings.json (Recommended):**
484+
485+
```json
486+
{
487+
"VectorSearch": {
488+
"PostgreSQL": {
489+
"ConnectionString": "Host=localhost;Database=myapp;Username=user;Password=pass",
490+
"CollectionName": "products",
491+
"EmbeddingDimensions": 1536
492+
}
493+
},
494+
"OpenAI": {
495+
"ApiKey": "sk-..."
496+
}
497+
}
498+
```
499+
483500
```csharp
484501
using EasyAppDev.Blazor.AutoComplete.AI.PostgreSql.Extensions;
485502

486-
// Configure services
503+
builder.Services.AddAutoCompletePostgres<Product>(
504+
builder.Configuration,
505+
textSelector: p => $"{p.Name} {p.Description} {p.Category}",
506+
idSelector: p => p.Id.ToString());
507+
508+
builder.Services.AddAutoCompleteVectorSearch<Product>(builder.Configuration);
509+
```
510+
511+
**Using explicit configuration:**
512+
513+
```csharp
487514
builder.Services.AddAutoCompletePostgres<Product>(
488515
configureOptions: options =>
489516
{
490517
options.ConnectionString = "Host=localhost;Database=myapp;Username=user;Password=pass";
491518
options.CollectionName = "products";
492-
options.EmbeddingDimensions = 1536; // text-embedding-3-small
519+
options.EmbeddingDimensions = 1536;
493520
},
494521
textSelector: p => $"{p.Name} {p.Description} {p.Category}",
495522
idSelector: p => p.Id.ToString());
496523

497-
// Add OpenAI embeddings and vector search data source
498524
builder.Services.AddAutoCompleteVectorSearch<Product>(
499525
openAiApiKey: "sk-...",
500526
configureOptions: options =>
@@ -518,16 +544,48 @@ Component usage is unchanged:
518544
dotnet add package EasyAppDev.Blazor.AutoComplete.AI.AzureSearch
519545
```
520546

547+
**Using appsettings.json (Recommended):**
548+
549+
```json
550+
{
551+
"VectorSearch": {
552+
"AzureSearch": {
553+
"Endpoint": "https://my-search.search.windows.net",
554+
"ApiKey": "your-search-api-key",
555+
"IndexName": "products",
556+
"EmbeddingDimensions": 1536,
557+
"EnableHybridSearch": true
558+
}
559+
},
560+
"AzureOpenAI": {
561+
"Endpoint": "https://my-openai.openai.azure.com/",
562+
"ApiKey": "your-openai-key",
563+
"DeploymentName": "text-embedding-ada-002"
564+
}
565+
}
566+
```
567+
521568
```csharp
522569
using EasyAppDev.Blazor.AutoComplete.AI.AzureSearch.Extensions;
523570

571+
builder.Services.AddAutoCompleteAzureSearch<Product>(
572+
builder.Configuration,
573+
textSelector: p => $"{p.Name} {p.Description}",
574+
idSelector: p => p.Id.ToString());
575+
576+
builder.Services.AddAutoCompleteVectorSearchWithAzure<Product>(builder.Configuration);
577+
```
578+
579+
**Using explicit configuration:**
580+
581+
```csharp
524582
builder.Services.AddAutoCompleteAzureSearch<Product>(
525583
configureOptions: options =>
526584
{
527585
options.Endpoint = "https://my-search.search.windows.net";
528586
options.ApiKey = "your-api-key";
529587
options.IndexName = "products";
530-
options.EnableHybridSearch = true; // Vector + keyword search
588+
options.EnableHybridSearch = true;
531589
},
532590
textSelector: p => $"{p.Name} {p.Description}",
533591
idSelector: p => p.Id.ToString());
@@ -542,6 +600,73 @@ builder.Services.AddAutoCompleteVectorSearchWithAzure<Product>(
542600
});
543601
```
544602

603+
### Other Vector Providers
604+
605+
All vector providers support configuration via appsettings.json:
606+
607+
**Pinecone:**
608+
```json
609+
{
610+
"VectorSearch": {
611+
"Pinecone": {
612+
"ApiKey": "your-pinecone-api-key",
613+
"IndexName": "products",
614+
"Namespace": "default",
615+
"EmbeddingDimensions": 1536
616+
}
617+
}
618+
}
619+
```
620+
621+
```csharp
622+
builder.Services.AddAutoCompletePinecone<Product>(
623+
builder.Configuration,
624+
textSelector: p => p.Name);
625+
```
626+
627+
**Qdrant:**
628+
```json
629+
{
630+
"VectorSearch": {
631+
"Qdrant": {
632+
"Host": "localhost",
633+
"Port": 6334,
634+
"Https": false,
635+
"ApiKey": "your-api-key-for-cloud",
636+
"CollectionName": "products",
637+
"EmbeddingDimensions": 1536
638+
}
639+
}
640+
}
641+
```
642+
643+
```csharp
644+
builder.Services.AddAutoCompleteQdrant<Product>(
645+
builder.Configuration,
646+
textSelector: p => p.Name);
647+
```
648+
649+
**Azure CosmosDB:**
650+
```json
651+
{
652+
"VectorSearch": {
653+
"CosmosDb": {
654+
"ConnectionString": "AccountEndpoint=https://myaccount.documents.azure.com:443/;AccountKey=...",
655+
"DatabaseName": "myapp",
656+
"ContainerName": "products",
657+
"EmbeddingDimensions": 1536,
658+
"VectorIndexType": "quantizedFlat"
659+
}
660+
}
661+
}
662+
```
663+
664+
```csharp
665+
builder.Services.AddAutoCompleteCosmosDb<Product>(
666+
builder.Configuration,
667+
textSelector: p => p.Name);
668+
```
669+
545670
### When to Use Vector Providers
546671

547672
| Scenario | Recommendation |

src/EasyAppDev.Blazor.AutoComplete.AI.AzureSearch/EasyAppDev.Blazor.AutoComplete.AI.AzureSearch.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
<!-- Semantic Kernel Azure AI Search connector (prerelease) -->
2828
<PackageReference Include="Microsoft.SemanticKernel.Connectors.AzureAISearch" Version="*-*" />
2929
<PackageReference Include="Azure.Search.Documents" Version="11.*" />
30+
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0" Condition="'$(TargetFramework)' == 'net8.0'" />
31+
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.0" Condition="'$(TargetFramework)' == 'net9.0'" />
3032
</ItemGroup>
3133

3234
</Project>

src/EasyAppDev.Blazor.AutoComplete.AI.AzureSearch/Extensions/AzureSearchServiceExtensions.cs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Azure;
22
using Azure.Search.Documents;
33
using Azure.Search.Documents.Indexes;
4+
using Microsoft.Extensions.Configuration;
45
using Microsoft.Extensions.DependencyInjection;
56
using Microsoft.Extensions.AI;
67
using Microsoft.SemanticKernel.Connectors.AzureAISearch;
@@ -14,6 +15,66 @@ namespace EasyAppDev.Blazor.AutoComplete.AI.AzureSearch.Extensions;
1415
/// </summary>
1516
public static class AzureSearchServiceExtensions
1617
{
18+
/// <summary>
19+
/// Adds Azure AI Search as the vector search provider using configuration from appsettings.json.
20+
/// </summary>
21+
/// <typeparam name="TItem">The item type to search.</typeparam>
22+
/// <param name="services">The service collection.</param>
23+
/// <param name="configuration">The configuration instance.</param>
24+
/// <param name="configSection">The configuration section name. Default: "VectorSearch:AzureSearch".</param>
25+
/// <returns>The service collection for chaining.</returns>
26+
/// <exception cref="ArgumentNullException">Thrown when services or configuration is null.</exception>
27+
/// <exception cref="ArgumentException">Thrown when configuration section is missing or options are invalid.</exception>
28+
/// <example>
29+
/// appsettings.json:
30+
/// {
31+
/// "VectorSearch": {
32+
/// "AzureSearch": {
33+
/// "Endpoint": "https://my-search.search.windows.net",
34+
/// "ApiKey": "your-api-key",
35+
/// "IndexName": "products",
36+
/// "EmbeddingDimensions": 1536,
37+
/// "EnableHybridSearch": true
38+
/// }
39+
/// }
40+
/// }
41+
/// </example>
42+
public static IServiceCollection AddAutoCompleteAzureSearchProvider<TItem>(
43+
this IServiceCollection services,
44+
IConfiguration configuration,
45+
string configSection = "VectorSearch:AzureSearch")
46+
{
47+
ArgumentNullException.ThrowIfNull(services);
48+
ArgumentNullException.ThrowIfNull(configuration);
49+
50+
var section = configuration.GetSection(configSection);
51+
if (!section.Exists())
52+
{
53+
throw new ArgumentException(
54+
$"Configuration section '{configSection}' not found. " +
55+
"Ensure your appsettings.json contains the Azure AI Search configuration.",
56+
nameof(configSection));
57+
}
58+
59+
var options = new AzureSearchVectorSearchOptions();
60+
section.Bind(options);
61+
62+
return services.AddAutoCompleteAzureSearchProvider<TItem>(opts =>
63+
{
64+
opts.Endpoint = options.Endpoint;
65+
opts.ApiKey = options.ApiKey;
66+
opts.IndexName = options.IndexName;
67+
opts.EmbeddingDimensions = options.EmbeddingDimensions;
68+
opts.DistanceFunction = options.DistanceFunction;
69+
opts.EnableHybridSearch = options.EnableHybridSearch;
70+
opts.EnableSemanticRanking = options.EnableSemanticRanking;
71+
opts.SemanticConfigurationName = options.SemanticConfigurationName;
72+
opts.VectorFieldName = options.VectorFieldName;
73+
opts.ContentFieldName = options.ContentFieldName;
74+
opts.IndexBatchSize = options.IndexBatchSize;
75+
});
76+
}
77+
1778
/// <summary>
1879
/// Adds Azure AI Search as the vector search provider.
1980
/// </summary>
@@ -103,6 +164,31 @@ public static IServiceCollection AddAutoCompleteAzureSearchIndexer<TItem>(
103164
return services;
104165
}
105166

167+
/// <summary>
168+
/// Adds Azure AI Search vector search with both provider and indexer using configuration from appsettings.json.
169+
/// </summary>
170+
/// <typeparam name="TItem">The item type.</typeparam>
171+
/// <param name="services">The service collection.</param>
172+
/// <param name="configuration">The configuration instance.</param>
173+
/// <param name="textSelector">Function to extract searchable text from items.</param>
174+
/// <param name="titleSelector">Optional function to extract title from items.</param>
175+
/// <param name="idSelector">Optional function to extract unique ID from items.</param>
176+
/// <param name="configSection">The configuration section name. Default: "VectorSearch:AzureSearch".</param>
177+
/// <returns>The service collection for chaining.</returns>
178+
public static IServiceCollection AddAutoCompleteAzureSearch<TItem>(
179+
this IServiceCollection services,
180+
IConfiguration configuration,
181+
Func<TItem, string> textSelector,
182+
Func<TItem, string>? titleSelector = null,
183+
Func<TItem, string>? idSelector = null,
184+
string configSection = "VectorSearch:AzureSearch")
185+
{
186+
services.AddAutoCompleteAzureSearchProvider<TItem>(configuration, configSection);
187+
services.AddAutoCompleteAzureSearchIndexer(textSelector, titleSelector, idSelector);
188+
189+
return services;
190+
}
191+
106192
/// <summary>
107193
/// Adds Azure AI Search vector search with both provider and indexer.
108194
/// </summary>

src/EasyAppDev.Blazor.AutoComplete.AI.CosmosDb/EasyAppDev.Blazor.AutoComplete.AI.CosmosDb.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
<!-- Semantic Kernel CosmosDB NoSQL connector (prerelease) -->
2828
<PackageReference Include="Microsoft.SemanticKernel.Connectors.CosmosNoSql" Version="*-*" />
2929
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.*" />
30+
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0" Condition="'$(TargetFramework)' == 'net8.0'" />
31+
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.0" Condition="'$(TargetFramework)' == 'net9.0'" />
3032
</ItemGroup>
3133

3234
</Project>

0 commit comments

Comments
 (0)