+ @if (messages.Count == 0)
+ {
+
+
+
Chat with your documents
+
Ask a question about the documents you have uploaded. Press the up arrow key to recall your previous question.
+
+ }
+
@foreach (var message in messages)
{
if (message.Role == "user")
@@ -98,18 +107,20 @@
@@ -129,7 +140,7 @@
private bool isAsking = false;
private bool showCopyConfirmation = false;
- private string toolTipText = "Copy to Clipboard";
+ private string toolTipText = "Copy to clipboard";
protected override async Task OnAfterRenderAsync(bool firstRender)
{
@@ -206,7 +217,7 @@
}
catch (Exception ex)
{
- assistantMessage.Text = $"There was an error while processing the question: {ex.Message}";
+ assistantMessage.Text = $"There was an error while processing your question: {ex.Message}";
assistantMessage.Status = MessageStatus.Completed;
}
finally
@@ -237,7 +248,7 @@
await Task.Delay(3000); // Shows the checkmark for 3 seconds
- toolTipText = "Copy to Clipboard";
+ toolTipText = "Copy to clipboard";
showCopyConfirmation = false;
await InvokeAsync(StateHasChanged);
}
diff --git a/SqlDatabaseVectorSearch/Components/Pages/Documents.razor b/SqlDatabaseVectorSearch/Components/Pages/Documents.razor
index 8498767..9750b68 100644
--- a/SqlDatabaseVectorSearch/Components/Pages/Documents.razor
+++ b/SqlDatabaseVectorSearch/Components/Pages/Documents.razor
@@ -8,10 +8,11 @@
Documents
-
+
- Upload new document
+ Upload a new document
+
The document is split into chunks, and an embedding is generated and stored for each chunk.
@@ -20,7 +21,7 @@
+ }
}
@code {
@@ -179,7 +191,7 @@ else
var documentId = string.IsNullOrWhiteSpace(Model.DocumentId) ? null : (Guid?)Guid.Parse(Model.DocumentId);
await vectorSearchService.ImportAsync(EmbeddingRequest.Create(stream, fileName, documentId));
- ToastService.Notify(await CreateToastMessageAsync(ToastType.Success, "Upload document", $"The document {fileName} has been successfully uploaded and indexed."));
+ ToastService.Notify(await CreateToastMessageAsync(ToastType.Success, "Upload document", $"The document '{fileName}' has been successfully uploaded and indexed."));
Model = new UploadDocument();
await JSRuntime.InvokeVoidAsync("resetFileInput", "fileInput");
@@ -188,7 +200,7 @@ else
}
catch (Exception ex)
{
- ToastService.Notify(await CreateToastMessageAsync(ToastType.Danger, "Upload error", $"There was an error while uploading the document {fileName}: {ex.Message}"));
+ ToastService.Notify(await CreateToastMessageAsync(ToastType.Danger, "Upload error", $"There was an error while uploading the document '{fileName}': {ex.Message}"));
}
finally
{
diff --git a/SqlDatabaseVectorSearch/Components/Pages/Home.razor b/SqlDatabaseVectorSearch/Components/Pages/Home.razor
index 6e2d27e..fa9adc4 100644
--- a/SqlDatabaseVectorSearch/Components/Pages/Home.razor
+++ b/SqlDatabaseVectorSearch/Components/Pages/Home.razor
@@ -3,37 +3,112 @@
SQL Database Vector Search
-
SQL Database Vector Search
+
+
+
+ SQL Database Vector Search
+
+
+ A Blazor Web App and Minimal API for Retrieval Augmented Generation (RAG) and vector search using the native
+ VECTOR type in
+
Azure SQL Database, with
+
Azure OpenAI and
+ Microsoft Agent Framework.
+
+
+
-
- A Blazor Web App and Minimal API for Retrieval Augmented Generation (RAG) and vector search using the native VECTOR type in
Azure SQL Database with
Azure OpenAI and Microsoft Agent Framework.
-
+
+
+ How it works
+
-
- This application allows you to:
-
- - Load documents (PDF, DOCX, TXT, MD)
- - Generate embeddings and save them as vectors in Azure SQL Database
- - Perform semantic search and RAG using Azure OpenAI agents
- - Interact via a Blazor Web App or programmatically via Minimal API
-
- Document import, question reformulation, and RAG are orchestrated with
Microsoft Agent Framework.
-
+
+
+
+
+
+
1. Import
+
+ Upload a PDF, DOCX, TXT or MD file. Its content is split into chunks, and each chunk is turned into
+ an embedding by an Agent Framework workflow.
+
+
+
+
+
+
+
+
+
2. Store
+
+ Embeddings are persisted in Azure SQL Database using the native VECTOR type, so no
+ external vector store is required.
+
+
+
+
+
+
+
+
+
3. Ask
+
+ Your question is reformulated with the conversation context, matched against the stored vectors, and
+ answered with citations.
+
+
+
+
+
-
Supported Features
-
- - Microsoft Agent Framework orchestration: Import documents through an embedding workflow and answer questions with dedicated reformulation and RAG agents.
- - Conversation history with question reformulation: Rewrite follow-up questions with the current conversation context before vector search.
- - SQL vector-search context: Retrieve relevant chunks from Azure SQL Database through native VECTOR search.
- - Information about token usage: Access token usage for reformulation and final answer generation.
- - Response streaming: Receive answer tokens in real time in the chat page and streaming API.
- - Markdown source citations: Get citations directly in the answer text with source name, page number when available, and a short supporting excerpt.
+
+
+ Supported features
+
+
+
+ -
+
+ Microsoft Agent Framework orchestration: documents are imported through an embedding workflow,
+ and questions are answered by dedicated reformulation and RAG agents.
+
+ -
+
+ Conversation history with question reformulation: follow-up questions are rewritten with the
+ current conversation context before the vector search is performed.
+
+ -
+
+ SQL vector search: the most relevant chunks are retrieved from Azure SQL Database through
+ native
VECTOR cosine-distance search.
+
+ -
+
+ Token usage details: input, output and total tokens are reported for both question
+ reformulation and answer generation.
+
+ -
+
+ Response streaming: answers are streamed token by token in the chat page and through the
+ Server-Sent Events API.
+
+ -
+
+ Markdown source citations: citations are embedded in the answer with the source name, the page
+ number when available, and a short supporting excerpt.
+
-
- Try uploading a document or ask a question to get started!
-
-
-
- For API usage and more details, see the README.
+
+
+ For API usage and more details, see the
+ README.
diff --git a/SqlDatabaseVectorSearch/Components/Pages/Home.razor.css b/SqlDatabaseVectorSearch/Components/Pages/Home.razor.css
new file mode 100644
index 0000000..fd29ea3
--- /dev/null
+++ b/SqlDatabaseVectorSearch/Components/Pages/Home.razor.css
@@ -0,0 +1,14 @@
+.hero {
+ background: linear-gradient(135deg, #eef4ff 0%, #f8f9fa 100%);
+ border: 1px solid #e3e8f0;
+}
+
+.inline-logo {
+ height: 1.5em;
+ vertical-align: middle;
+}
+
+.card:hover {
+ transform: translateY(-2px);
+ transition: transform 0.15s ease-in-out;
+}