Skip to content

Refactor to Microsoft.Agents.AI and improve embedding workflows - #17

Merged
marcominerva merged 32 commits into
masterfrom
agent-framework
Jul 31, 2026
Merged

Refactor to Microsoft.Agents.AI and improve embedding workflows#17
marcominerva merged 32 commits into
masterfrom
agent-framework

Conversation

@marcominerva

Copy link
Copy Markdown
Owner

This pull request updates the project to clarify its support for both Azure SQL Database and SQL Server 2025, enhances documentation to reflect the use of the Microsoft Agent Framework, and improves the user and developer experience through UI tweaks and more accurate technical instructions. It also introduces new C# code style preferences and refines API documentation and streaming behavior.

Documentation and Feature Updates:

  • Expanded the project scope in README.md to include SQL Server 2025 and Microsoft Agent Framework, with updated descriptions of supported features, workflows, and limitations. The documentation now emphasizes the use of the native VECTOR type in both Azure SQL Database and SQL Server 2025, and details the orchestration of embeddings and RAG using Microsoft Agent Framework agents and workflows. [1] [2] [3] [4] [5]

  • Refined the explanation and example of API and streaming responses, including a shift from array-based streaming to Server-Sent Events (SSE) with explicit event names (Start, Delta, End). Updated response structure and clarified how citations are now embedded in the Markdown answer, not as a separate JSON collection.

UI and Usability Improvements:

  • Updated navigation and iconography in MainLayout.razor for better clarity and modern appearance, including new icons for Documents and Ask pages, and improved color usage for external links. [1] [2]

  • Adjusted reconnection modal message in ReconnectModal.razor for consistency in user feedback.

  • Modified Blazor server-side rendering options in App.razor to disable prerendering for HeadOutlet and Routes, ensuring correct interactive behavior.

Development and Code Style:

  • Added new C# code style preferences in .editorconfig to encourage static anonymous functions, implicitly typed lambda expressions, and unbound generic types in nameof expressions. [1] [2]

Removed Microsoft.SemanticKernel dependencies in favor of Microsoft.Agents.AI.OpenAI for embedding and chat services. Updated DI registrations in Program.cs to use OpenAIClient. Reimplemented text chunking with a new PlainTextChunker class, updating DefaultTextChunker and MarkdownTextChunker accordingly. Updated .csproj to add new package references and suppress related analyzer warnings.
Refactored PlainTextChunker to add input validation, null checks, and argument validation in public methods. Renamed SplitMarkDownLines to SplitMarkdownLines for consistency and updated all references. Centralized line ending normalization and token count validation into dedicated methods. Enhanced error handling with clearer messages and exception types. Simplified paragraph merging logic and ensured GetDefaultTokenCount returns at least 1 for non-empty input. Updated MarkdownTextChunker to use the corrected method name.
Replaces the direct import logic with a workflow using Microsoft.Agents.AI.Workflows. Adds executors for file conversion, embedding generation, and storage. Updates dependency injection, API endpoint, and UI to use the new workflow. Replaces ImportDocumentResponse with StoreEmbeddingResponse. Adds required NuGet packages.
Replaced SemanticKernel with Microsoft.Agents.AI and agent-based abstractions for chat and RAG workflows. Removed ChatService in favor of AIAgent instances for question reformulation and answering. Added agent registration/configuration in Program.cs, new RagResponse record, and ContextProvider for context search. Introduced HybridCacheSessionStoreService for session persistence. Switched to direct OpenAIClient usage with request tracing. Reduced max relevant context chunks to 30. Removed SemanticKernel from project references and suppressed MEAI001 warning. Refactored code for improved style and DI alignment.
- Enabled additional C# code style suggestions in .editorconfig.
- Removed citation rendering and extraction from Ask.razor.
- Deleted Citation, ChatResponse, and TokenUsage models and references.
- Updated TokenUsageResponse to use UsageDetails from Microsoft.Extensions.AI.
- Refactored Response model: removed citations, added ConversationId, and adopted new token usage structure.
- Updated HybridCacheSessionStoreService with new cache key format and DeleteSessionAsync method.
- Refactored VectorSearchService to remove AppSettings dependency, update method signatures, and use UsageDetails for token tracking.
- Updated NuGet package references in SqlDatabaseVectorSearch.csproj.
Replaced `IServiceProvider` with `IServiceScopeFactory` for async scope creation, updated injected services and usages, switched namespace import from `System.Text.RegularExpressions` to `Microsoft.Extensions.AI`, and simplified the `FormatTokenUsageDetails` method signature to use the unqualified `UsageDetails` type.
- Added a new Response constructor overload for simpler instantiation with conversationId, streamState, and optional tokenUsageResponse.
- Updated AddAIAgent registrations for "ReformulationAgent" and "RagAgent" to set Id to the lower-cased key.
- Modified VectorSearchService to use the new Response constructor, omitting now-optional parameters.
- Enhanced ContextProvider: TextSearchResult now includes a RawRepresentation property with chunk metadata (Id, DocumentId, PageNumber, IndexOnPage, Content).
- Inject IServiceScopeFactory in Documents.razor for better DI and async scope creation.
- Update citation formatting in Program.cs: sources now appear as a localized, numbered Markdown list with block quotes.
- Use a helper for consistent source/page formatting in TextSearchProviderOptions.
- Simplify RawRepresentation in VectorSearchService to just the page number.
Clarifies citation formatting: the sources label must be localized and in standard-size italic text (not a heading or bold). Citations now require the source name in bold, followed by the localized page label and page number if available, then a colon and 15-20 italicized words from the excerpt. Source names are not links, and only actually used, non-duplicate sources are included. Example formats are updated accordingly.
Updated the "Sources" section header and changed the source list from bullets to a numbered format (e.g., "[1] SourceName"). Each source now includes its excerpt and a separator line ("---"). Removed the "### Excerpts" section and extra blank lines, consolidating sources and excerpts for improved clarity.
The instructions for formatting the sources section at the end of answers were revised for clarity and precision. Instead of multiple separate citation rules, the new guidance requires using a provided template, with the sources and page labels localized to the user's language. The updated rules specify omitting the page label and number if not available, and explicitly prohibit headings or links in the sources section. The formatting example was also updated to match these changes.
Updated README.md and Home.razor to document migration from Semantic Kernel to Microsoft Agent Framework, detailing new orchestration, document import, question reformulation, and RAG agent workflows. Revised API and streaming response examples to use Server-Sent Events (SSE) with event names Start, Delta, and End. Refactored AskEndpoints.cs to use .NET 8 ServerSentEvents API and yield SseItem<Response> with correct event names. Updated Ask.razor, Documents.razor, and VectorSearchService.cs to use StreamState.Delta instead of Append, and replaced StateHasChanged() with await InvokeAsync(StateHasChanged) for async UI updates. Removed MaxInputTokens and MaxOutputTokens from AppSettings.cs and appsettings.json.
Consolidate embedding request logic into a new EmbeddingRequest record with static factory methods for IFormFile and stream input. Remove FormFileToEmbeddingRequestExecutor and FormFileEmbeddingRequest, updating all usages and dependency injection accordingly. Clean up related code in Program.cs, VectorSearchService, and _Imports.razor. Enhance XML documentation for EmbeddingRequest to clarify intent and usage.
Replaced AddSqlServer with AddDbContext for ApplicationDbContext, enabling dynamic provider selection based on the connection string. Now uses UseAzureSql for Azure SQL targets and UseSqlServer with retry logic otherwise. Configured all queries to use NoTracking for improved performance.
Update icon choices and colors across the Blazor app for improved visual clarity and consistency. Use explicit InteractiveServerRenderMode in App.razor. Replace sidebar, header, and navigation icons with filled or colorized variants in MainLayout.razor. Update Ask.razor and Documents.razor with more descriptive icons. Enhance reconnect modal messaging and button visibility. Adjust app.css for individual sidebar icon colors and brand icon styling. Remove EFCore.SqlServer.VectorSearch from the home page feature list to focus on Agent Framework. These changes improve UI feedback, accessibility, and maintainability.
- Chat page: Add empty state, clarify tooltips/placeholders, and enhance error/copy messages.
- Documents page: Add chunking/embedding info, clarify file support, show document count badge, and display empty state. Refactor table/button markup and improve upload toasts.
- Home page: Redesign with hero section, icons, workflow cards, and styled features list. Clarify README link.
- Add Home.razor.css for new visual styles.
Updated documentation and UI to clarify support for both Azure SQL Database and SQL Server 2025+ for native VECTOR type storage and search. Improved README with accurate prerequisites, setup instructions, and detailed ModelId usage guidance. Clarified streaming response availability in both Blazor and API. Fixed typos and improved wording in UI messages. Enhanced code comments for clarity and accuracy, including ModelId guidance in appsettings.json.
The chat UI progress bar was visually updated: height increased to 6px, background made more transparent, and corners fully rounded. The indeterminate bar now uses a gradient with a moving highlight animation, which is slower for users with reduced motion preferences. Animation duration and style were refined for improved accessibility and aesthetics.
Replaced the chat progress bar in Ask.razor with a modern animated "typing indicator" using three bouncing dots. Updated Ask.razor.css to remove old progress bar styles and add new keyframes and accessibility improvements for the typing dots. This enhances user experience by clearly signaling when the assistant is responding.
The file upload form in Documents.razor is now wrapped in a <fieldset> that disables all controls while uploading, using a new isUploading flag to manage state and UI updates. The upload button's loading state is also handled. In Program.cs, the citation template was revised to require supporting excerpts of about 20-30 words instead of 15-20 words.
- Tooltip and file input now use `UploadDocument` properties for supported types and max size.
- File input's `accept` attribute set from `UploadDocument.AcceptedFileTypes`.
- Added `<ValidationMessage>` for file input errors.
- Stream size limit uses `UploadDocument.MaxFileSize`.
- Introduced `GetDocumentId()` for parsing document IDs.
- Simplified LINQ in `DeleteSelectedDocuments`.
- `UploadDocument` implements `IValidatableObject` for:
  - GUID format validation.
  - Supported extension checks.
  - File size enforcement.
- Centralized constants for extensions, types, and max size in `UploadDocument`.
Refactored the copy button to use per-message state, displaying a checkmark icon and "Copied!" tooltip when a message is copied. Simplified state management, removed unused references, and updated the Reset method to clear copied state. Enhanced Ask.razor.css to minimize button chrome and improve interactive states for a cleaner UI.
Refactored HTML generation by introducing a sections array for easier extension and maintainability. Updated FormatTokenUsageDetails to require non-null UsageDetails and display reasoning tokens as a detail within output tokens, improving clarity and reducing redundancy. Only non-null sections are rendered, simplifying the logic.
Refactored the output token usage details to show reasoning tokens as an indented HTML line using a <span> with Bootstrap classes for indentation and smaller text, instead of a parenthetical note. Updated logic to use ReasoningTokenCount.HasValue for improved clarity.
Updated sidebar CSS to use a blue and neutral color palette, added vertical gradient backgrounds and box-shadows, and enhanced navigation item styles with rounded corners, transitions, and bold active states. Adjusted icon colors and updated comments for new color inheritance approach.
Removed the custom TraceHttpClientHandler and switched OpenAIClient initialization to use the default HTTP transport. Cleaned up unused using directives. Updated SqlDatabaseVectorSearch_WebApp.png with a new version.
Moved message scrolling logic to OnAfterRenderAsync to ensure DOM updates before scrolling, using Task.Yield() after StateHasChanged. Removed redundant EnsureMessageIsVisibleAsync calls. Cleaned up Error.razor by removing unused usings and the rendermode directive.
Updated <HeadOutlet> and <Routes> to use the named parameter 'prerender: false' with InteractiveServerRenderMode, improving code clarity and consistency with named parameter usage.
Enhanced the project README by adding badges for .NET 10, Minimal API, and Blazor support to the project title. This highlights the technologies and features supported by the project for better visibility and clarity.
The binary file SqlDatabaseVectorSearch.mp4 was deleted from the codebase to reduce repository size and remove unnecessary assets. No code functionality is affected by this change.
Refactored the embedding workflow to introduce ExtractChunksExecutor, responsible for content decoding and chunk extraction before embedding generation. Registered ExtractChunksExecutor and GenerateEmbeddingExecutor as singletons, and StoreEmbeddingExecutor as scoped in DI. Updated workflow to sequence ExtractChunksExecutor → GenerateEmbeddingExecutor → StoreEmbeddingExecutor. Modified GenerateEmbeddingExecutor to accept ExtractChunksResponse. Updated ChatClientAgentOptions usage to use object initializers for clarity. Added ExtractChunksExecutor.cs.
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.
Copilot AI review requested due to automatic review settings July 31, 2026 14:39
@marcominerva
marcominerva merged commit f0c92b3 into master Jul 31, 2026
2 checks passed
@marcominerva
marcominerva deleted the agent-framework branch July 31, 2026 14:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request refactors the app’s embedding import and RAG/chat flow from Semantic Kernel-centric services into Microsoft Agent Framework (agents + workflows), while updating the API streaming shape and modernizing the Blazor UI/docs to reflect Azure SQL Database and SQL Server 2025 support.

Changes:

  • Replaces the document import pipeline with an Agent Framework workflow (ExtractChunksGenerateEmbeddingStoreEmbedding) and updates endpoints/UI to use EmbeddingRequest.
  • Replaces the chat/reformulation + RAG flow with Agent Framework agents, including session storage via HybridCache, and updates streaming to SSE with Start/Delta/End.
  • Updates UI styling and documentation to reflect the new architecture and broader database support; adds new C# style preferences.

Reviewed changes

Copilot reviewed 37 out of 39 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
SqlDatabaseVectorSearch/wwwroot/css/app.css Updates sidebar styling and icon coloring for a modernized navigation look.
SqlDatabaseVectorSearch/Workflows/StoreEmbeddingExecutor.cs Adds workflow executor to persist documents/chunks/embeddings to SQL.
SqlDatabaseVectorSearch/Workflows/GenerateEmbeddingExecutor.cs Adds workflow executor to batch-generate embeddings from extracted chunks.
SqlDatabaseVectorSearch/Workflows/ExtractChunksExecutor.cs Adds workflow executor to decode uploaded content into chunks.
SqlDatabaseVectorSearch/Workflows/EmbeddingRequest.cs Introduces a request model to standardize import inputs (stream/name/type/id).
SqlDatabaseVectorSearch/TextChunkers/MarkdownTextChunker.cs Switches markdown chunking implementation to the new in-repo chunker.
SqlDatabaseVectorSearch/TextChunkers/Implementations/PlainTextChunker.cs Adds an in-repo chunking implementation replacing prior dependency usage.
SqlDatabaseVectorSearch/TextChunkers/DefaultTextChunker.cs Switches plain-text chunking implementation to the new in-repo chunker.
SqlDatabaseVectorSearch/SqlDatabaseVectorSearch.csproj Adds Agent Framework packages, bumps some dependencies, and updates NoWarn list.
SqlDatabaseVectorSearch/Settings/AppSettings.cs Removes token limit settings that were tied to the old chat implementation.
SqlDatabaseVectorSearch/Services/VectorSearchService.cs Refactors import + Q&A to use workflows/agents and new streaming semantics.
SqlDatabaseVectorSearch/Services/HybridCacheSessionStoreService.cs Adds HybridCache-backed AgentSessionStore for agent conversation persistence.
SqlDatabaseVectorSearch/Services/DocumentContextProviderService.cs Adds SQL vector-search-backed context provider for the RAG agent.
SqlDatabaseVectorSearch/Services/ChatService.cs Removes old Semantic Kernel-based chat/reformulation service.
SqlDatabaseVectorSearch/Program.cs Reworks DI/config to register workflows/agents, OpenAI clients, and API pipeline behavior.
SqlDatabaseVectorSearch/Models/TokenUsageResponse.cs Replaces old TokenUsage model with UsageDetails-based response shape.
SqlDatabaseVectorSearch/Models/TokenUsage.cs Removes the old prompt/completion token usage model.
SqlDatabaseVectorSearch/Models/StreamState.cs Renames streaming state from Append to Delta.
SqlDatabaseVectorSearch/Models/Response.cs Updates response contract to include ConversationId and new streaming constructors.
SqlDatabaseVectorSearch/Models/ImportDocumentResponse.cs Removes old import response model in favor of workflow output model.
SqlDatabaseVectorSearch/Models/Citation.cs Removes citation model now that sources are embedded in Markdown instead of JSON.
SqlDatabaseVectorSearch/Models/ChatResponse.cs Removes old chat response model previously used by ChatService.
SqlDatabaseVectorSearch/Endpoints/DocumentEndpoints.cs Updates document import endpoint to use EmbeddingRequest and workflow-based import.
SqlDatabaseVectorSearch/Endpoints/AskEndpoints.cs Updates streaming endpoint to SSE items and new Start/Delta/End event naming.
SqlDatabaseVectorSearch/Components/Pages/Home.razor.css Adds new hero/card hover styling for the homepage.
SqlDatabaseVectorSearch/Components/Pages/Home.razor Updates homepage copy/UI to reflect Agent Framework + SQL Server 2025 support.
SqlDatabaseVectorSearch/Components/Pages/Error.razor Fixes wording/typos and aligns with the new render-mode setup.
SqlDatabaseVectorSearch/Components/Pages/Documents.razor Improves upload UX/validation and routes import through EmbeddingRequest + workflow.
SqlDatabaseVectorSearch/Components/Pages/Ask.razor.css Replaces progress bar with typing indicator and improves copy-button styling.
SqlDatabaseVectorSearch/Components/Pages/Ask.razor Updates chat UI for new streaming semantics, token usage model, and copy behavior.
SqlDatabaseVectorSearch/Components/Layout/ReconnectModal.razor Tweaks reconnect/resume messaging and button visibility classes.
SqlDatabaseVectorSearch/Components/Layout/MainLayout.razor Updates nav icons and header icon styling.
SqlDatabaseVectorSearch/Components/App.razor Disables prerendering for key interactive components to ensure correct behavior.
SqlDatabaseVectorSearch/Components/_Imports.razor Adds workflows namespace to shared imports.
SqlDatabaseVectorSearch/appsettings.json Updates guidance and settings defaults to match new token counting + chunk retrieval behavior.
README.md Updates docs for SQL Server 2025 support, Agent Framework architecture, and SSE streaming format.
.editorconfig Adds new C# style preferences for lambdas/nameof and static anonymous functions.

@@ -109,6 +295,7 @@
{
app.UseExceptionHandler(new ExceptionHandlerOptions
Comment on lines +20 to +24
var exception = events.OfType<WorkflowErrorEvent>().Select(e => e.Exception).FirstOrDefault();
if (exception is not null)
{
await dbContext.Database.BeginTransactionAsync(cancellationToken);

if (documentId.HasValue)
{
// If the user is importing a document that already exists, delete the previous one.
await documentService.DeleteAsync(documentId.Value, cancellationToken);
}

var document = new Entities.Document { Id = documentId.GetValueOrDefault(), Name = name, CreationDate = timeProvider.GetUtcNow() };
dbContext.Documents.Add(document);

// Process paragraphs in batches.
var embeddings = new List<Embedding<float>>();
foreach (var batch in chunkContents.Chunk(appSettings.EmbeddingBatchSize))
{
logger.LogDebug("Processing batch of {Count} chunks for embedding generation...", batch.Length);

// Generate embeddings for this batch.
var batchEmbeddings = await embeddingGenerator.GenerateAsync(batch, cancellationToken: cancellationToken);
embeddings.AddRange(batchEmbeddings);
}

// Save the document chunks and the corresponding embedding in the database.
foreach (var (index, embedding) in embeddings.Index())
{
var chunk = chunks.ElementAt(index);
logger.LogDebug("Storing a chunk of {TokenCount} tokens.", tokenizerService.CountEmbeddingTokens(chunk.Content));

var documentChunk = new Entities.DocumentChunk
{
Document = document,
Index = index,
PageNumber = chunk.PageNumber,
IndexOnPage = chunk.IndexOnPage,
Content = chunk.Content,
Embedding = new SqlVector<float>(embedding.Vector)
};

dbContext.DocumentChunks.Add(documentChunk);
}

await dbContext.SaveChangesAsync(cancellationToken);
await dbContext.Database.CommitTransactionAsync(cancellationToken);

return document;
}, cancellationToken);
throw exception;
}
Comment on lines +26 to +27
var result = events.OfType<WorkflowOutputEvent>().Select(e => e.Data).OfType<StoreEmbeddingResponse>().First();
return result;
Comment on lines +18 to +19
await dbContext.Database.BeginTransactionAsync(cancellationToken);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants