Skip to content

Commit 3e072ed

Browse files
[Feature] Add streaming ability in chat page using Azure SignalR service (#383)
## Purpose <!-- Describe the intention of the changes being proposed. What problem does it solve or functionality does it add? --> * Currently, on the Chat page, when we ask a question, the system gathers all information (e.g., answer, thought, supportingContent, etc.) and responds to the client through the API. * We are adding streaming capability. Whenever the LLM responds with an answer in a streaming format, we can use a SignalR connection (WebSocket) to push messages directly. ## Does this introduce a breaking change? <!-- Mark one with an "x". --> ``` [x] Yes [ ] No ``` ## Pull Request Type What kind of change does this Pull Request introduce? <!-- Please check the one that applies to this PR using "x". --> ``` [ ] Bugfix [X] Feature [ ] Code style update (formatting, local variables) [ ] Refactoring (no functional changes, no api changes) [ ] Documentation content changes [ ] Other... Please describe: ``` ## How to Test * Get the code ``` git clone [repo-address] cd [repo-name] ``` * Test the code <!-- Add steps to run the tests suite and/or manually test --> ``` azd up ``` * Go to the Chat page. * There will be options to select between streaming mode and normal mode. ## What to Check Verify that the following are valid * Verify normal mode is working as previously * Verify streaming mode is working as expected ## Next steps: - [ ] Add unit tests - [ ] Add docs - [ ] Verify running locally without AzureSignalREndpoint env configure ## Other Information <!-- Add any other helpful information that may be needed here. -->
1 parent fd451e3 commit 3e072ed

20 files changed

+786
-22
lines changed

README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ languages:
77
- bicep
88
products:
99
- ai-services
10+
- azure-signalr
1011
- azure-blob-storage
1112
- azure-container-apps
1213
- azure-cognitive-search
@@ -57,11 +58,11 @@ description: A csharp sample app that chats with your data using OpenAI and AI S
5758
[![Open in GitHub - Codespaces](https://img.shields.io/static/v1?style=for-the-badge&label=GitHub+Codespaces&message=Open&color=brightgreen&logo=github)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=624102171&machine=standardLinux32gb&devcontainer_path=.devcontainer%2Fdevcontainer.json&location=WestUs2)
5859
[![Open in Remote - Containers](https://img.shields.io/static/v1?style=for-the-badge&label=Remote%20-%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/azure-samples/azure-search-openai-demo-csharp)
5960

60-
This sample demonstrates a few approaches for creating ChatGPT-like experiences over your own data using the Retrieval Augmented Generation pattern. It uses Azure OpenAI Service to access the ChatGPT model (`gpt-4o-mini`), and Azure AI Search for data indexing and retrieval.
61+
This sample demonstrates a few approaches for creating ChatGPT-like experiences over your own data using the Retrieval Augmented Generation pattern. It uses Azure OpenAI Service to access the ChatGPT model (`gpt-4o-mini`), and Azure AI Search for data indexing and retrieval, and Azure SignalR Service for real-time streaming responses.
6162

6263
The repo includes sample data so it's ready to try end-to-end. In this sample application, we use a fictitious company called Contoso Electronics, and the experience allows its employees to ask questions about the benefits, internal policies, as well as job descriptions and roles.
6364

64-
![RAG Architecture](docs/appcomponents.png)
65+
![RAG Architecture](docs/appcomponents-signalr.png)
6566

6667
For more details on how this application was built, check out:
6768

@@ -75,6 +76,7 @@ We want to hear from you! Are you interested in building or currently building i
7576
## Features
7677

7778
- Voice Chat, Chat and Q&A interfaces
79+
- Real-time streaming responses using Azure SignalR Service
7880
- Explores various options to help users evaluate the trustworthiness of responses with citations, tracking of source content, etc.
7981
- Shows possible approaches for data preparation, prompt construction, and orchestration of interaction between model (ChatGPT) and retriever (Azure AI Search)
8082
- Settings directly in the UX to tweak the behavior and experiment with options
@@ -83,10 +85,11 @@ We want to hear from you! Are you interested in building or currently building i
8385

8486
## Application architecture
8587

86-
- **User interface** - The applications chat interface is a [Blazor WebAssembly](https://learn.microsoft.com/aspnet/core/blazor/) application. This interface is what accepts user queries, routes request to the application backend, and displays generated responses.
88+
- **User interface** - The application's chat interface is a [Blazor WebAssembly](https://learn.microsoft.com/aspnet/core/blazor/) application. This interface is what accepts user queries, routes request to the application backend, and displays generated responses.
8789
- **Backend** - The application backend is an [ASP.NET Core Minimal API](https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis/overview). The backend hosts the Blazor static web application and what orchestrates the interactions among the different services. Services used in this application include:
8890
- [**Azure AI Search**](https://learn.microsoft.com/azure/search/search-what-is-azure-search) – indexes documents from the data stored in an Azure Storage Account. This makes the documents searchable using [vector search](https://learn.microsoft.com/azure/search/search-get-started-vector) capabilities.
8991
- [**Azure OpenAI Service**](https://learn.microsoft.com/azure/ai-services/openai/overview) – provides the Large Language Models to generate responses. [Semantic Kernel](https://learn.microsoft.com/semantic-kernel/whatissk) is used in conjunction with the Azure OpenAI Service to orchestrate the more complex AI workflows.
92+
- [**Azure SignalR Service**](https://learn.microsoft.com/azure/azure-signalr/signalr-overview) - enables real-time streaming of AI responses to the client application.
9093

9194
## Getting Started
9295

@@ -108,8 +111,9 @@ Pricing varies per region and usage, so it isn't possible to predict exact costs
108111
- [**Azure OpenAI Service**](https://azure.microsoft.com/pricing/details/cognitive-services/openai-service/). Standard tier, GPT and Ada models. Pricing per 1K tokens used, and at least 1K tokens are used per question.
109112
- [**Azure AI Document Intelligence**](https://azure.microsoft.com/pricing/details/ai-document-intelligence/). SO (Standard) tier using pre-built layout. Pricing per document page, sample documents have 261 pages total.
110113
- [**Azure AI Search**](https://azure.microsoft.com/pricing/details/search/) Basic tier, 1 replica, free level of semantic search. Pricing per hour.
111-
- [**Azure Blob Storage**](https://azure.microsoft.com/pricing/details/storage/blobs/). Standard tier with ZRS (Zone-redundant storage). Pricing per storage and read operations.
114+
- [**Azure Blob Storage**](https://azure.microsoft.com/pricing/details/storage/blobs/). Standard tier with ZRS (Zone-redundant storage). Pricing per storage and read operations.
112115
- [**Azure Monitor**](https://azure.microsoft.com/pricing/details/monitor/). Pay-as-you-go tier. Costs based on data ingested.
116+
- [**Azure SignalR Service**](https://azure.microsoft.com/pricing/details/signalr-service/). Premium tier with 1 unit. Pricing per unit per hour.
113117

114118
To reduce costs, you can switch to free SKUs for various services, but those SKUs have limitations. See this [guide on deploying with minimal costs](./docs/deploy_lowcost.md) for more details.
115119

@@ -374,6 +378,7 @@ to production. Here are some things to consider:
374378
### Resources
375379

376380
- [Revolutionize your Enterprise Data with ChatGPT: Next-gen Apps w/ Azure OpenAI and Azure AI Search](https://aka.ms/entgptsearchblog)
381+
- [Azure SignalR Service](https://learn.microsoft.com/azure/azure-signalr/signalr-overview)
377382
- [Azure AI Search](https://learn.microsoft.com/azure/search/search-what-is-azure-search)
378383
- [Azure OpenAI Service](https://learn.microsoft.com/azure/cognitive-services/openai/overview)
379384
- [`Azure.AI.OpenAI` NuGet package](https://www.nuget.org/packages/Azure.AI.OpenAI)

app/Directory.Packages.props

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,7 @@
5252
<PackageVersion Include="xunit" Version="2.9.0" />
5353
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
5454
<PackageVersion Include="NSubstitute" Version="5.1.0" />
55+
<PackageVersion Include="Microsoft.Azure.SignalR" Version="1.27.0" />
56+
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.8" />
5557
</ItemGroup>
5658
</Project>

app/SharedWebComponents/Components/Answer.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@
2828
}
2929
</div>
3030
}
31-
@if (answer is { FollowupQuestions.Count: > 0 })
31+
@if (Retort?.Context?.FollowupQuestions is { Length: > 0 })
3232
{
3333
<div class="pt-4">
3434
<MudText Typo="Typo.subtitle2" Class="pb-2">Follow-up questions:</MudText>
35-
@foreach (var followup in answer.FollowupQuestions)
35+
@foreach (var followup in Retort.Context.FollowupQuestions)
3636
{
3737
<MudChip Variant="Variant.Text" Color="Color.Tertiary"
3838
OnClick="@(_ => OnAskFollowupAsync(followup))">

app/SharedWebComponents/Components/SettingsPanel.razor

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
Color="Color.Primary"
4242
Label="Use query-contextual summaries instead of whole documents" />
4343

44+
<MudCheckBox @bind-Checked="@Settings.Overrides.UseStreaming" Size="Size.Large"
45+
Color="Color.Primary"
46+
Label="Use streaming responses" />
47+
4448
<MudCheckBox @bind-Checked="@Settings.Overrides.SuggestFollowupQuestions" Size="Size.Large"
4549
Color="Color.Primary" Label="Suggest follow-up questions"
4650
aria-label="Suggest follow-up questions checkbox." />
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
namespace SharedWebComponents.Models;
4+
5+
internal class StreamingMessage
6+
{
7+
public string Type { get; set; } = "";
8+
public object? Content { get; set; }
9+
}

app/SharedWebComponents/Pages/Chat.razor

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@
8888
OnClick="@OnClearChat" Disabled=@(_isReceivingResponse || _questionAndAnswerMap is { Count: 0 }) />
8989
</MudTooltip>
9090
</MudItem>
91+
<MudItem xs="12" Class="pa-2">
92+
<MudCheckBox @bind-Checked="_useStreaming" Label="Use streaming mode" Color="Color.Secondary"
93+
Disabled="@_isReceivingResponse" />
94+
</MudItem>
9195
</MudGrid>
9296
</MudItem>
9397
</MudGrid>

0 commit comments

Comments
 (0)