Skip to content

Commit

Permalink
Update only streaming
Browse files Browse the repository at this point in the history
  • Loading branch information
phanthaiduong22 committed Dec 12, 2024
1 parent b504360 commit 81a2d78
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 390 deletions.
4 changes: 0 additions & 4 deletions app/SharedWebComponents/Pages/Chat.razor
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@
OnClick="@OnClearChat" Disabled=@(_isReceivingResponse || _questionAndAnswerMap is { Count: 0 }) />
</MudTooltip>
</MudItem>
<MudItem xs="12" Class="pa-2">
<MudCheckBox @bind-Checked="_useStreaming" Label="Use streaming mode" Color="Color.Secondary"
Disabled="@_isReceivingResponse" />
</MudItem>
</MudGrid>
</MudItem>
</MudGrid>
Expand Down
38 changes: 17 additions & 21 deletions app/SharedWebComponents/Pages/Chat.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ public sealed partial class Chat
private UserQuestion _currentQuestion;
private string _lastReferenceQuestion = "";
private bool _isReceivingResponse = false;
private bool _useStreaming = false;

private readonly Dictionary<UserQuestion, ChatAppResponseOrError?> _questionAndAnswerMap = [];

Expand Down Expand Up @@ -45,38 +44,35 @@ private async Task OnAskClickedAsync()
{
var history = _questionAndAnswerMap
.Where(x => x.Value?.Choices is { Length: > 0 })
.SelectMany(x => new ChatMessage[] { new ChatMessage("user", x.Key.Question), new ChatMessage("assistant", x.Value!.Choices[0].Message.Content) })
.SelectMany(x => new ChatMessage[] {
new ChatMessage("user", x.Key.Question),
new ChatMessage("assistant", x.Value!.Choices[0].Message.Content)
})
.ToList();

history.Add(new ChatMessage("user", _userQuestion));

var request = new ChatRequest([.. history], Settings.Overrides);

if (_useStreaming)
try
{
try
{
await foreach (var response in await ApiClient.PostStreamingRequestAsync(request, "api/chat/stream"))
{
_questionAndAnswerMap[_currentQuestion] = new ChatAppResponseOrError(
response.Choices,
null);

StateHasChanged();
await Task.Delay(10);
}
}
catch (Exception ex)
var responseStream = await ApiClient.PostStreamingRequestAsync(request, "api/chat/stream");

await foreach (var response in responseStream)
{
_questionAndAnswerMap[_currentQuestion] = new ChatAppResponseOrError(
Array.Empty<ResponseChoice>(),
ex.Message);
response.Choices,
null);

StateHasChanged();
await Task.Delay(1);
}
}
else
catch (Exception ex)
{
var result = await ApiClient.ChatConversationAsync(request);
_questionAndAnswerMap[_currentQuestion] = result.Response;
_questionAndAnswerMap[_currentQuestion] = new ChatAppResponseOrError(
Array.Empty<ResponseChoice>(),
ex.Message);
}

if (_questionAndAnswerMap[_currentQuestion]?.Error is null)
Expand Down
58 changes: 11 additions & 47 deletions app/SharedWebComponents/Services/ApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,65 +90,29 @@ public async IAsyncEnumerable<DocumentResponse> GetDocumentsAsync(
}
}

public Task<AnswerResult<ChatRequest>> ChatConversationAsync(ChatRequest request) => PostRequestAsync(request, "api/chat");

private async Task<AnswerResult<TRequest>> PostRequestAsync<TRequest>(
TRequest request, string apiRoute) where TRequest : ApproachRequest
{
var result = new AnswerResult<TRequest>(
IsSuccessful: false,
Response: null,
Approach: request.Approach,
Request: request);

var json = JsonSerializer.Serialize(
request,
SerializerOptions.Default);

using var body = new StringContent(
json, Encoding.UTF8, "application/json");

var response = await httpClient.PostAsync(apiRoute, body);

if (response.IsSuccessStatusCode)
{
var answer = await response.Content.ReadFromJsonAsync<ChatAppResponseOrError>();
return result with
{
IsSuccessful = answer is not null,
Response = answer,
};
}
else
{
var errorTitle = $"HTTP {(int)response.StatusCode} : {response.ReasonPhrase ?? "☹️ Unknown error..."}";
var answer = new ChatAppResponseOrError(
Array.Empty<ResponseChoice>(),
errorTitle);

return result with
{
IsSuccessful = false,
Response = answer
};
}
}

public async Task<IAsyncEnumerable<ChatAppResponse>> PostStreamingRequestAsync<TRequest>(
TRequest request, string apiRoute) where TRequest : ApproachRequest
{
var json = JsonSerializer.Serialize(
request,
SerializerOptions.Default);

using var body = new StringContent(
using var content = new StringContent(
json, Encoding.UTF8, "application/json");

var response = await httpClient.PostAsync(apiRoute, body);
// Use both HttpCompletionOption and CancellationToken
var response = await httpClient.PostAsync(
apiRoute,
content,
CancellationToken.None);

if (response.IsSuccessStatusCode)
{
var nullableResponses = response.Content.ReadFromJsonAsAsyncEnumerable<ChatAppResponse>();
var stream = await response.Content.ReadAsStreamAsync();
var nullableResponses = JsonSerializer.DeserializeAsyncEnumerable<ChatAppResponse>(
stream,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

return nullableResponses.Where(r => r != null)!;
}

Expand Down
21 changes: 1 addition & 20 deletions app/backend/Extensions/WebApplicationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal static WebApplication MapApi(this WebApplication app)
api.MapPost("openai/chat", OnPostChatPromptAsync);

// Long-form chat w/ contextual history endpoint
api.MapPost("chat", OnPostChatAsync);
api.MapPost("chat/stream", OnPostChatStreamingAsync);

// Upload a document
api.MapPost("documents", OnPostDocumentAsync);
Expand All @@ -25,9 +25,6 @@ internal static WebApplication MapApi(this WebApplication app)

api.MapGet("enableLogout", OnGetEnableLogout);

// Add streaming chat endpoint
api.MapPost("chat/stream", OnPostChatStreamingAsync);

return app;
}

Expand Down Expand Up @@ -73,22 +70,6 @@ You will always reply with a Markdown formatted response.
}
}

private static async Task<IResult> OnPostChatAsync(
ChatRequest request,
ReadRetrieveReadChatService chatService,
CancellationToken cancellationToken)
{
if (request is { History.Length: > 0 })
{
var response = await chatService.ReplyAsync(
request.History, request.Overrides, cancellationToken);

return TypedResults.Ok(response);
}

return Results.BadRequest();
}

private static async IAsyncEnumerable<ChatAppResponse> OnPostChatStreamingAsync(
ChatRequest request,
ReadRetrieveReadChatService chatService,
Expand Down
Loading

0 comments on commit 81a2d78

Please sign in to comment.