Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add function to Service to allow stream the results back from a… #73

Merged
merged 8 commits into from
Jan 19, 2023

Conversation

qbm5
Copy link
Contributor

@qbm5 qbm5 commented Jan 11, 2023

Add function to Service to allow stream the results back from a completion request

@kayhantolga kayhantolga changed the base branch from master to dev January 12, 2023 12:58
@kayhantolga
Copy link
Member

@qbm5 when I test the method, it fetches the data as a stream but it waits until the stream completes. And it processes all of it at once. So I can't get the advantage of streaming data. Does it work for you too like that?

@qbm5
Copy link
Contributor Author

qbm5 commented Jan 17, 2023

Vuepages

I might not be understanding the stream correctly. When I walk through it piece by piece (see attached) it seems to be working correctly, but you are right it appears to come all at once when letting it run without break points.

@kayhantolga
Copy link
Member

Yes, I had the same experience. The issue is HTTP client is waiting until Stream completes. I will search a bit for samples. without yield return, the method will be useless.

@qbm5
Copy link
Contributor Author

qbm5 commented Jan 17, 2023

I just had success with doing it this way. It is sloppy, but it is showing promise. I can work on getting it in the pr a bit later.

` public async IAsyncEnumerable CreateCompletionAsStream(CompletionCreateRequest createCompletionRequest, string? modelId = null)
{
// Mark the request as streaming and include a logit bias
createCompletionRequest.Stream = true;

    // Send the request to the CompletionCreate endpoint
    createCompletionRequest.ProcessModelId(modelId, _defaultModelId);

    var ser = new JsonSerializerOptions()
    {
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
    };
    JsonContent content = JsonContent.Create(createCompletionRequest, mediaType: null, ser);

    using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, _endpointProvider.CompletionCreate());
    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream"));
    request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
    request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
    request.Headers.AcceptEncoding.Add(new StringWithQualityHeaderValue("br"));
    request.Content = content;


    // Read the response as a stream
    ;
    using (HttpResponseMessage response = _httpClient.Send(request, HttpCompletionOption.ResponseHeadersRead))
    using (var stream = response.Content.ReadAsStream())
    {
        

        using var reader = new StreamReader(stream);
        // Continuously read the stream until the end of it
        while (!reader.EndOfStream)
        {
            var line = await reader.ReadLineAsync();
            // Skip empty lines
            if (string.IsNullOrEmpty(line)) continue;

            line = line.Replace("data: ", string.Empty);

            // Exit the loop if the stream is done
            if (line.Contains("[DONE]")) break;

            CompletionCreateResponse? block;
            try
            {
                // When the response is good, each line is a serializable CompletionCreateRequest
                block = JsonSerializer.Deserialize<CompletionCreateResponse>(line);
            }
            catch (Exception)
            {
                // When the API returns an error, it does not come back as a block, it returns a single character of text ("{").
                // In this instance, read through the rest of the response, which should be a complete object to parse.
                line += await reader.ReadToEndAsync();
                block = JsonSerializer.Deserialize<CompletionCreateResponse>(line);
            }
            if (null != block) yield return block;
        }

    }`

stream

@qbm5
Copy link
Contributor Author

qbm5 commented Jan 19, 2023

I have pushed the update

@kayhantolga
Copy link
Member

Awesome! I pushed some changes too, If you approve I am going to merge it.

@kayhantolga kayhantolga merged commit a71e8da into betalgo:dev Jan 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants