Skip to content

Commit

Permalink
Fixed EventStreamReader test
Browse files Browse the repository at this point in the history
  • Loading branch information
ddebowczyk committed Oct 9, 2024
1 parent 4e80b35 commit ddae04c
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,24 @@

use Cognesy\Instructor\Events\EventDispatcher;
use Cognesy\Instructor\Events\Inference\StreamDataReceived;
use Cognesy\Instructor\Events\Inference\StreamDataParsed;
use Cognesy\Instructor\Features\LLM\EventStreamReader;
use Mockery as Mock;

beforeEach(function () {
// Create a mock for the EventDispatcher
$this->mockEventDispatcher = Mock::mock(EventDispatcher::class);
$this->mockEventDispatcher->shouldReceive('dispatch')->with(Mock::type(StreamDataReceived::class));
});

it('streams synthetic OpenAI streaming data correctly without parser', function () {
$this->mockEventDispatcher->shouldReceive('dispatch')->times(2)->with(Mock::type(StreamDataReceived::class));
$this->mockEventDispatcher->shouldReceive('dispatch')->times(2)->with(Mock::type(StreamDataParsed::class));

$reader = new EventStreamReader(events: $this->mockEventDispatcher);

$generator = function () {
yield '{"id": "cmpl-xyz", "object": "text_completion", "choices": [{';
yield '"text": "Hello, ", "index": 0}]}'. "\n";
yield '{"id": "cmpl-xyz", "object": "text_completion", "choices": [{';
yield '"text": "world!", "index": 1}]}' . "\n";
yield '{"id": "cmpl-xyz", "object": "text_completion", "choices": [{"text": "Hello, ", "index": 0}]}'. "\n";
yield '{"id": "cmpl-xyz", "object": "text_completion", "choices": [{"text": "world!", "index": 1}]}' . "\n";
};

$expected = [
Expand All @@ -33,42 +34,47 @@
});

it('processes synthetic OpenAI streaming data with a custom parser', function () {
$parser = fn($line) => strtoupper($line);
$this->mockEventDispatcher->shouldReceive('dispatch')->times(2)->with(Mock::type(StreamDataReceived::class));
$this->mockEventDispatcher->shouldReceive('dispatch')->times(2)->with(Mock::type(StreamDataParsed::class));

$parser = fn($line) => substr($line, 6);
$reader = new EventStreamReader(parser: $parser, events: $this->mockEventDispatcher);

$generator = function () {
yield '{"id": "cmpl-xyz", "object": "text_completion", "choices": [{';
yield '"text": "Hello, ", "index": 0}]}' . "\n";
yield '{"id": "cmpl-xyz", "object": "text_completion", "choices": [{';
yield '"text": "world!", "index": 1}]}' . "\n";
yield 'data: {"id": "cmpl-xyz", "object": "text_completion", "choices": [{"text": "Hello, ", "index": 0}]}'. "\n";
yield 'data: {"id": "cmpl-xyz", "object": "text_completion", "choices": [{"text": "world!", "index": 1}]}' . "\n";
};

$expected = [
'{"ID": "CMPL-XYZ", "OBJECT": "TEXT_COMPLETION", "CHOICES": [{"TEXT": "HELLO, ", "INDEX": 0}]}',
'{"ID": "CMPL-XYZ", "OBJECT": "TEXT_COMPLETION", "CHOICES": [{"TEXT": "WORLD!", "INDEX": 1}]}',
'{"id": "cmpl-xyz", "object": "text_completion", "choices": [{"text": "Hello, ", "index": 0}]}',
'{"id": "cmpl-xyz", "object": "text_completion", "choices": [{"text": "world!", "index": 1}]}',
];

$result = iterator_to_array($reader->eventsFrom($generator()));
expect($result)->toEqual($expected);
expect($result)->toMatchArray($expected);
});

//it('dispatches events when streaming synthetic OpenAI data', function () {
// $this->mockEventDispatcher->shouldReceive('dispatch')->times(2)->with(Mock::type(StreamDataReceived::class));
//
// $reader = new IterableReader(events: $this->mockEventDispatcher);
//
// $generator = function () {
// yield '{"id": "cmpl-xyz", "object": "text_completion", "choices": [{';
// yield '"text": "Hello, ", "index": 0}]}' . "\n";
// yield '{"id": "cmpl-xyz", "object": "text_completion", "choices": [{';
// yield '"text": "world!", "index": 1}]}' . "\n";
// };
//
// // Convert to array to force full iteration and event dispatching
// iterator_to_array($reader->stream($generator()));
//});
it('dispatches events when streaming synthetic OpenAI data', function () {
$this->mockEventDispatcher->shouldReceive('dispatch')->times(2)->with(Mock::type(StreamDataReceived::class));
$this->mockEventDispatcher->shouldReceive('dispatch')->times(2)->with(Mock::type(StreamDataParsed::class));

$reader = new EventStreamReader(events: $this->mockEventDispatcher);

$generator = function () {
yield '{"id": "cmpl-xyz", "object": "text_completion", "choices": [{';
yield '"text": "Hello, ", "index": 0}]}' . "\n";
yield '{"id": "cmpl-xyz", "object": "text_completion", "choices": [{';
yield '"text": "world!", "index": 1}]}' . "\n";
};

// Convert to array to force full iteration and event dispatching
iterator_to_array($reader->eventsFrom($generator()));
});

it('skips empty lines correctly in synthetic OpenAI data', function () {
$this->mockEventDispatcher->shouldReceive('dispatch')->times(5)->with(Mock::type(StreamDataReceived::class));
$this->mockEventDispatcher->shouldReceive('dispatch')->twice()->with(Mock::type(StreamDataParsed::class));

$reader = new EventStreamReader(events: $this->mockEventDispatcher);

$generator = function () {
Expand All @@ -91,6 +97,9 @@
});

it('handles incomplete lines correctly in synthetic OpenAI data', function () {
$this->mockEventDispatcher->shouldReceive('dispatch')->times(2)->with(Mock::type(StreamDataReceived::class));
$this->mockEventDispatcher->shouldReceive('dispatch')->times(2)->with(Mock::type(StreamDataParsed::class));

$reader = new EventStreamReader(events: $this->mockEventDispatcher);

$generator = function () {
Expand All @@ -108,4 +117,4 @@

$result = iterator_to_array($reader->eventsFrom($generator()));
expect($result)->toEqual($expected);
});
});
1 change: 0 additions & 1 deletion tests/MockLLM.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
use Cognesy\Instructor\Features\Http\Contracts\CanAccessResponse;
use Cognesy\Instructor\Features\Http\Contracts\CanHandleHttp;
use Cognesy\Instructor\Features\Http\Drivers\GuzzleDriver;
use Cognesy\Instructor\Features\LLM\Data\LLMResponse;
use Mockery;

class MockLLM
Expand Down

0 comments on commit ddae04c

Please sign in to comment.