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

How to use stream to return a message even instead of waiting until everything has been processed #115

Open
pslxx opened this issue May 7, 2024 · 10 comments

Comments

@pslxx
Copy link

pslxx commented May 7, 2024

How to use stream to return a message even instead of waiting until everything has been processed

@MaximeThoonsen
Copy link
Collaborator

hey @pslxx , there are dedicated method in the ChatInterface like generateStreamOfText.
Does it help you?

@messi89
Copy link

messi89 commented Aug 22, 2024

@MaximeThoonsen the generateStreamOfText function use guzzle request (not async request), so theoretically the method waits for the whole response from the ollama api.

Is there any way to read streamed stream from ollama response directly ?

@iztok
Copy link

iztok commented Sep 1, 2024

+1 Looking to iterate through each stream chunk but stream methods return StreamInterface that doesn't allow this (#78 (comment))

@iztok
Copy link

iztok commented Sep 2, 2024

If anyone finds this helpful:

        $streamToIterator = function (StreamInterface $stream): Generator {
            while (!$stream->eof()) {
                yield $stream->read(32); // Adjust the chunk size as needed
            }
        };
        $iteratorStream = $streamToIterator($stream);

        foreach ($iteratorStream as $chunk) {
            // chunks are not token based anymore!
        }

@MaximeThoonsen
Copy link
Collaborator

hello @ezimuel, how are you?

It seems there is a lot of questions around streaming. Can we still do streaming with StreamInterface and LLPhant? What is the "clean/simple" working example?

@iztok the code your provided is working for you to get a stream?

@iztok
Copy link

iztok commented Sep 4, 2024

@iztok the code your provided is working for you to get a stream?

Yes, this returns an iterateable stream I can use the same as I used the stream from the OpenAI library. One caveat is that this stream's chunks are not tokens but strings of size 32 bytes. I'm then broadcasting these chunks over the WebSocket to my chat clients.

@prykris
Copy link

prykris commented Sep 11, 2024

Yes, this returns an iterateable stream I can use the same as I used the stream from the OpenAI library. One caveat is that this stream's chunks are not tokens but strings of size 32 bytes. I'm then broadcasting these chunks over the WebSocket to my chat clients.

@iztok I see how that is a caveat. Does that make any difference in your use case or does it seriously impact the end-user experience?

I am trying to understand the pitfalls I might run into while trying to implement something similar.

@ryanisn
Copy link

ryanisn commented Oct 28, 2024

with ollama, $stream->read(32) waits on the whole response completed before returning the "chunk"

@mortensi
Copy link

Thanks for the hints. However, I must be doing something wrong. This does not work for me and I get all the answer at once.

       $qa = new QuestionAnswering(
           $redisVectorStore,
           $embeddingGenerator,
           new OpenAIChat($config)
       );

        $stream = $qa->answerQuestionStream($request->input('q'));

        $streamToIterator = function (StreamInterface $stream): \Generator {
            while (!$stream->eof()) {
                yield $stream->read(32); 
            }
        };
        $iteratorStream = $streamToIterator($stream);

        foreach ($iteratorStream as $chunk) {
            echo $chunk;
        }

Using OpenAI, partial reads work perfectly, though.

       $responseStream = OpenAI::chat()->createStreamed([
           'model' => 'gpt-3.5-turbo',
           'messages' => [
               ['role' => 'user', 'content' => $request->input('q')],
           ],
       ]);

       foreach ($responseStream as $delta) {
           // Stream the delta content back to the client
           echo $delta['choices'][0]['delta']['content'] ?? '';
           ob_flush(); 
           flush();    
       }

       ob_flush();
       flush();

I'm not sure what else I can test to make answerQuestionStream work.

@mortensi
Copy link

Solved. I needed ob_flush() and flush() after each chunk to force Laravel send the output.

        $streamToIterator = function (StreamInterface $stream): \Generator {
            while (!$stream->eof()) {
                yield $stream->read(32); 
                ob_flush();
                flush();
            }
        };

        $iteratorStream = $streamToIterator($stream);

        foreach ($iteratorStream as $chunk) {
            echo $chunk;
        }

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

No branches or pull requests

7 participants