diff --git a/SqlDatabaseVectorSearch/Components/Pages/Ask.razor b/SqlDatabaseVectorSearch/Components/Pages/Ask.razor index 60013c5..4acc8bf 100644 --- a/SqlDatabaseVectorSearch/Components/Pages/Ask.razor +++ b/SqlDatabaseVectorSearch/Components/Pages/Ask.razor @@ -1,16 +1,151 @@ @page "/ask" +@inject IServiceProvider ServiceProvider +@inject IJSRuntime JSRuntime + Chat with your data -

Current count: @currentCount

+
+
- + @foreach (var message in messages) + { + if (message.Role == "user") + { +
+
+
+
+ @message.Text +
+
+
+
+ +
+
+ } + else if (message.Role == "assistant") + { +
+
+ +
+
+
+ @if (message.Text is null) + { +
+
+
+
+
+
+
+ } + else + { +
+
+ @message.Text +
+ @if (message.IsCompleted) + { +
+ + + +
+ } +
+ } +
+
+
+ } + } +
-@code { - private int currentCount = 0; + +
- private void IncrementCount() +@code +{ + private Button askButton = default!; + private Button resetButton = default!; + + private IList messages = []; + private string? question; + + private Guid conversationId = Guid.NewGuid(); + private bool isAsking = false; + + + private async Task AskQuestion() { - currentCount++; + isAsking = true; + + try + { + var userMessage = new Message { Text = question, Role = "user" }; + messages.Add(userMessage); + + var assistantMessage = new Message { Role = "assistant" }; + messages.Add(assistantMessage); + + await using var scope = ServiceProvider.CreateAsyncScope(); + var vectorSearchService = scope.ServiceProvider.GetRequiredService(); + + var response = await vectorSearchService.AskQuestionAsync(new Question(conversationId, question!)); + + assistantMessage.Text = response.Answer; + assistantMessage.IsCompleted = true; + + question = null; + } + finally + { + isAsking = false; + } } -} + + private void Reset() + { + question = null; + conversationId = Guid.NewGuid(); + messages.Clear(); + } + + private ValueTask CopyToClipboard(string text) + { + return JSRuntime.InvokeVoidAsync("navigator.clipboard.writeText", text); + } + + public class Message + { + public string? Text { get; set; } + + public required string Role { get; set; } + + public bool IsCompleted { get; set; } + } +} \ No newline at end of file diff --git a/SqlDatabaseVectorSearch/Components/Pages/Ask.razor.css b/SqlDatabaseVectorSearch/Components/Pages/Ask.razor.css new file mode 100644 index 0000000..7fa7e3b --- /dev/null +++ b/SqlDatabaseVectorSearch/Components/Pages/Ask.razor.css @@ -0,0 +1,100 @@ +.tooltip-inner { + text-align: left; +} + +.avatar { + width: 50px; + height: 50px; + border-radius: 50%; + border: 2px solid #ddd; + padding: 2px; + flex: none; +} + +input:focus { + outline: 0px !important; + box-shadow: none !important; +} + +input[type="checkbox"], +input[type="checkbox"] + label { + cursor: pointer; +} + +.card-body { + overflow: auto; + height: 490px; +} + +@media (min-width: 768px) { + .card-body { + height: 595px; + } +} + +@media (min-width: 2560px) { + .card-body { + height: 950px; + } +} + +.card-text { + border: 2px solid #ddd; + border-radius: 8px; +} + +.progress-chat { + width: 200px; + height: 4px; +} + +.progress-bar-chat { + height: 4px; + background-color: rgba(5, 114, 206, 0.2); + width: 100%; + overflow: hidden; +} + +.progress-bar-indeterminate { + width: 100%; + height: 100%; + background-color: rgb(5, 114, 206); + animation: indeterminate-animation 1s infinite linear; + transform-origin: 0% 50%; +} + +@keyframes indeterminate-animation { + 0% { + transform: translateX(0) scaleX(0); + } + + 40% { + transform: translateX(0) scaleX(0.4); + } + + 100% { + transform: translateX(100%) scaleX(0.5); + } +} + +.btn-clipboard { + line-height: 1; + color: var(--bs-body-color); + background-color: var(--bd-pre-bg); + border: 0; + border-radius: .25rem; + margin-right: -.4em +} + + .btn-clipboard:hover { + color: var(--bs-link-hover-color) + } + + .btn-clipboard:focus { + z-index: 3 + } + +.btn-clipboard { + position: relative; + z-index: 2; +} diff --git a/SqlDatabaseVectorSearch/Components/Pages/Documents.razor b/SqlDatabaseVectorSearch/Components/Pages/Documents.razor index 7f8aa6d..19ef8f6 100644 --- a/SqlDatabaseVectorSearch/Components/Pages/Documents.razor +++ b/SqlDatabaseVectorSearch/Components/Pages/Documents.razor @@ -124,7 +124,6 @@ else return; } - await Task.Delay(2000); await using var scope = ServiceProvider.CreateAsyncScope(); await LoadDocumentsAsync(scope.ServiceProvider); diff --git a/SqlDatabaseVectorSearch/wwwroot/images/assistant.png b/SqlDatabaseVectorSearch/wwwroot/images/assistant.png new file mode 100644 index 0000000..64ec75c Binary files /dev/null and b/SqlDatabaseVectorSearch/wwwroot/images/assistant.png differ diff --git a/SqlDatabaseVectorSearch/wwwroot/images/user.png b/SqlDatabaseVectorSearch/wwwroot/images/user.png new file mode 100644 index 0000000..b4a325d Binary files /dev/null and b/SqlDatabaseVectorSearch/wwwroot/images/user.png differ