-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Closed
Labels
area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etc
Description
Is there an existing issue for this?
- I have searched the existing issues
Is your feature request related to a problem? Please describe the problem.
I am trying to return a streaming IAsyncEnumerable<string>
SematicKernel chat completion from GetStreamingChatCompletionsAsync
, GetStreamingChatMessageAsync
methods.
Currently simply returning IAsyncEnumerable<string>
produces a streaming JSON array of strings result. The desired behavior is simple streaming text strings result.
This would effectively produce a streaming ChatGTP-like completion response generated by the method as the results become available from the OpenAI endpoints.
Describe the solution you'd like
public class AsyncEnumerableStringsResult : IResult, IContentTypeHttpResult, IStatusCodeHttpResult
{
protected readonly IAsyncEnumerable<string> chunks;
public string? ContentType => "text/plain; charset=utf-8";
public int StatusCode => StatusCodes.Status200OK;
int? IStatusCodeHttpResult.StatusCode => StatusCode;
public AsyncEnumerableStringsResult(IAsyncEnumerable<string> chunks) => this.chunks = chunks ?? throw new ArgumentNullException(nameof(chunks));
public async Task ExecuteAsync(HttpContext httpContext)
{
if (httpContext == null)
throw new ArgumentNullException(nameof(httpContext));
httpContext.Response.ContentType = this.ContentType;
httpContext.Response.StatusCode = this.StatusCode;
await foreach (var chunk in this.chunks)
if (!string.IsNullOrEmpty(chunk))
await httpContext.Response.WriteAsync(chunk, cancellationToken: httpContext.RequestAborted);
}
}
Usage example:
app.MapPost("/ChatAsyncStream", ([FromBody] ChatRequest chatRequest, ChatPlugin plugin, ILogger logger, CancellationToken cancellationToken) =>
{
if (string.IsNullOrWhiteSpace(chatRequest.Question))
throw new ArgumentNullException(nameof(chatRequest.Question));
var result = plugin.ChatAsyncStream(
question: chatRequest.Question,
chatHistory: chatRequest.ChatHistory,
logger: logger,
cancellationToken: cancellationToken
);
return new AsyncEnumerableStringsResult(result);
})
.WithName("ChatAsyncStream")
.WithOpenApi()
.Produces<IAsyncEnumerable<string>>();
Additional context
No response
WeihanLi
Metadata
Metadata
Assignees
Labels
area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etc