Refactor: Replace ContextProvider with DocumentContextProviderService

Replaces the ContextProvider class with DocumentContextProviderService, moving vector search logic into its own file. Updates dependency injection and all usages to reference the new service. The service uses embeddings and Entity Framework for vector-based text search, returning relevant document chunks. Removes unused usings and references to ContextProvider.
This commit is contained in:
Marco Minerva
2026-07-31 16:38:48 +02:00
parent 3a765fdccf
commit d910205339
3 changed files with 37 additions and 32 deletions
+2 -2
View File
@@ -100,7 +100,7 @@ builder.Services.AddSingleton<TokenizerService>();
builder.Services.AddScoped<DocumentService>();
builder.Services.AddScoped<VectorSearchService>();
builder.Services.AddScoped<ContextProvider>();
builder.Services.AddScoped<DocumentContextProviderService>();
builder.Services.AddSingleton<ExtractChunksExecutor>();
builder.Services.AddSingleton<GenerateEmbeddingExecutor>();
@@ -249,7 +249,7 @@ builder.Services.AddAIAgent("RagAgent", (services, key) =>
&& m.GetAgentRequestMessageSourceType() != AgentRequestMessageSourceType.AIContextProvider);
}
}),
AIContextProviders = [new TextSearchProvider(services.GetRequiredService<ContextProvider>().SearchAsync, textSearchOptions)]
AIContextProviders = [new TextSearchProvider(services.GetRequiredService<DocumentContextProviderService>().SearchAsync, textSearchOptions)]
},
loggerFactory: services.GetRequiredService<ILoggerFactory>(),
services: services);
@@ -0,0 +1,35 @@
using System.Data;
using Microsoft.Agents.AI;
using Microsoft.Data.SqlTypes;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Options;
using SqlDatabaseVectorSearch.Data;
using SqlDatabaseVectorSearch.Settings;
namespace SqlDatabaseVectorSearch.Services;
public class DocumentContextProviderService(ApplicationDbContext dbContext, IEmbeddingGenerator<string, Embedding<float>> embeddingGenerator, IOptions<AppSettings> appSettingsOptions)
{
private readonly AppSettings appSettings = appSettingsOptions.Value;
public async Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchAsync(string query, CancellationToken cancellationToken)
{
// Perform Vector Search on SQL Database.
var questionEmbedding = await embeddingGenerator.GenerateVectorAsync(query, cancellationToken: cancellationToken);
var embeddingVector = new SqlVector<float>(questionEmbedding);
var chunks = await dbContext.DocumentChunks.Include(c => c.Document)
.OrderBy(c => EF.Functions.VectorDistance("cosine", c.Embedding, embeddingVector))
.Take(appSettings.MaxRelevantChunks).Select(c => new TextSearchProvider.TextSearchResult
{
SourceLink = c.Id.ToString().ToLowerInvariant(),
SourceName = c.Document.Name,
Text = c.Content,
RawRepresentation = c.PageNumber
})
.ToListAsync(cancellationToken);
return chunks;
}
}
@@ -3,13 +3,8 @@ using System.Runtime.CompilerServices;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Data.SqlTypes;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Options;
using SqlDatabaseVectorSearch.Data;
using SqlDatabaseVectorSearch.Models;
using SqlDatabaseVectorSearch.Settings;
using SqlDatabaseVectorSearch.Workflows;
namespace SqlDatabaseVectorSearch.Services;
@@ -87,28 +82,3 @@ public partial class VectorSearchService([FromKeyedServices("EmbeddingWorkflow")
yield return new(question.ConversationId, StreamState.End, new TokenUsageResponse(null, response.Usage));
}
}
public class ContextProvider(ApplicationDbContext dbContext, IEmbeddingGenerator<string, Embedding<float>> embeddingGenerator, IOptions<AppSettings> appSettingsOptions)
{
private readonly AppSettings appSettings = appSettingsOptions.Value;
public async Task<IEnumerable<TextSearchProvider.TextSearchResult>> SearchAsync(string query, CancellationToken cancellationToken)
{
// Perform Vector Search on SQL Database.
var questionEmbedding = await embeddingGenerator.GenerateVectorAsync(query, cancellationToken: cancellationToken);
var embeddingVector = new SqlVector<float>(questionEmbedding);
var chunks = await dbContext.DocumentChunks.Include(c => c.Document)
.OrderBy(c => EF.Functions.VectorDistance("cosine", c.Embedding, embeddingVector))
.Take(appSettings.MaxRelevantChunks).Select(c => new TextSearchProvider.TextSearchResult
{
SourceLink = c.Id.ToString().ToLowerInvariant(),
SourceName = c.Document.Name,
Text = c.Content,
RawRepresentation = c.PageNumber
})
.ToListAsync(cancellationToken);
return chunks;
}
}