Skip to content

Commit

Permalink
Refactored request processing
Browse files Browse the repository at this point in the history
  • Loading branch information
ddebowczyk committed Oct 5, 2024
1 parent c033c89 commit d8fa401
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 39 deletions.
43 changes: 6 additions & 37 deletions src/Core/RequestHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Cognesy\Instructor\Data\Request;
use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Events\EventDispatcher;
use Cognesy\Instructor\Events\Instructor\InstructorDone;
use Cognesy\Instructor\Events\Instructor\ResponseGenerated;
use Cognesy\Instructor\Events\Request\NewValidationRecoveryAttempt;
use Cognesy\Instructor\Events\Request\ValidationRecoveryLimitReached;
Expand All @@ -16,7 +15,6 @@
use Cognesy\Instructor\Extras\LLM\Data\PartialLLMResponse;
use Cognesy\Instructor\Extras\LLM\Inference;
use Cognesy\Instructor\Extras\LLM\InferenceResponse;
use Cognesy\Instructor\Stream;
use Cognesy\Instructor\Utils\Json\Json;
use Cognesy\Instructor\Utils\Result\Result;
use Exception;
Expand All @@ -39,40 +37,16 @@ public function __construct(
EventDispatcher $events,
) {
$this->events = $events;
$this->retries = 0;
$this->errors = [];
}

/**
* Executes the request and returns the response
*/
public function get() : mixed {
if ($this->request->isStream()) {
return $this->stream()->final();
}
$result = $this->responseFor($this->request);
$this->events->dispatch(new InstructorDone(['result' => $result]));
return $result->value();
}

/**
* Executes the request and returns the response stream
*/
public function stream() : Stream {
// TODO: do we need this? cannot we just turn streaming on?
if (!$this->request->isStream()) {
throw new Exception('Instructor::stream() method requires response streaming: set "stream" = true in the request options.');
}
$stream = $this->streamResponseFor($this->request);
return new Stream($stream, $this->events);
}

// INTERNAL //////////////////////////////////////////////////////////////
// PUBLIC //////////////////////////////////////////////////////////////

/**
* Generates response value
*/
protected function responseFor(Request $request) : LLMResponse {
$this->init();

public function responseFor(Request $request) : LLMResponse {
$processingResult = Result::failure("No response generated");
while ($processingResult->isFailure() && !$this->maxRetriesReached($request)) {
$llmResponse = $this->getInference($request)->toLLMResponse();
Expand All @@ -94,9 +68,7 @@ protected function responseFor(Request $request) : LLMResponse {
* @param Request $request
* @return Generator<PartialLLMResponse|LLMResponse>
*/
protected function streamResponseFor(Request $request) : Generator {
$this->init();

public function streamResponseFor(Request $request) : Generator {
$processingResult = Result::failure("No response generated");
while ($processingResult->isFailure() && !$this->maxRetriesReached($request)) {
$stream = $this->getInference($request)->toPartialLLMResponses();
Expand All @@ -112,10 +84,7 @@ protected function streamResponseFor(Request $request) : Generator {
yield $llmResponse->withValue($value);
}

protected function init() : void {
$this->retries = 0;
$this->errors = [];
}
// INTERNAL ///////////////////////////////////////////////////////////

protected function getInference(Request $request) : InferenceResponse {
$inference = new Inference(
Expand Down
50 changes: 50 additions & 0 deletions src/InstructorResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Cognesy\Instructor;

use Cognesy\Instructor\Core\RequestHandler;
use Cognesy\Instructor\Data\Request;
use Cognesy\Instructor\Events\EventDispatcher;
use Cognesy\Instructor\Events\Instructor\InstructorDone;
use Exception;

class InstructorResponse
{
private RequestHandler $requestHandler;
private EventDispatcher $events;
private Request $request;

public function __construct(
Request $request,
RequestHandler $requestHandler,
EventDispatcher $events,
) {
$this->events = $events;
$this->requestHandler = $requestHandler;
$this->request = $request;
}

/**
* Executes the request and returns the response
*/
public function get() : mixed {
if ($this->request->isStream()) {
return $this->stream()->final();
}
$result = $this->requestHandler->responseFor($this->request);
$this->events->dispatch(new InstructorDone(['result' => $result]));
return $result->value();
}

/**
* Executes the request and returns the response stream
*/
public function stream() : Stream {
// TODO: do we need this? cannot we just turn streaming on?
if (!$this->request->isStream()) {
throw new Exception('Instructor::stream() method requires response streaming: set "stream" = true in the request options.');
}
$stream = $this->requestHandler->streamResponseFor($this->request);
return new Stream($stream, $this->events);
}
}
32 changes: 30 additions & 2 deletions src/Traits/Instructor/HandlesInvocation.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
use Cognesy\Instructor\Data\ResponseModel;
use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Events\Instructor\RequestReceived;
use Cognesy\Instructor\Extras\LLM\Inference;
use Cognesy\Instructor\Extras\LLM\InferenceResponse;
use Cognesy\Instructor\InstructorResponse;
use Cognesy\Instructor\Schema\Factories\SchemaFactory;
use Cognesy\Instructor\Schema\Factories\ToolCallBuilder;
use Cognesy\Instructor\Schema\Utils\ReferenceQueue;
Expand Down Expand Up @@ -69,7 +72,7 @@ public function request(
string $toolDescription = '',
string $retryPrompt = '',
Mode $mode = Mode::Tools,
) : RequestHandler {
) : InstructorResponse {
$this->queueEvent(new RequestReceived());
$this->dispatchQueuedEvents();

Expand Down Expand Up @@ -98,7 +101,7 @@ public function request(
cachedContext: $this->cachedContext ?? [],
);

return new RequestHandler(
$requestHandler = new RequestHandler(
request: $request,
responseGenerator: new ResponseGenerator(
$this->responseDeserializer,
Expand All @@ -116,10 +119,35 @@ public function request(
httpClient: $this->httpClient,
events: $this->events,
);

return new InstructorResponse(
request: $request,
requestHandler: $requestHandler,
events: $this->events,
);
}

// INTERNAL /////////////////////////////////////////////////

protected function getInference(Request $request) : InferenceResponse {
$inference = new Inference(
connection: $this->connection,
httpClient: $this->httpClient,
driver: $this->driver,
events: $this->events,
);
return $inference
->create(
$request->toMessages(),
$request->model(),
$request->toolCallSchema(),
$request->toolChoice(),
$request->responseFormat(),
$request->options(),
$request->mode()
);
}

private function makeResponseModel(
string|array|object $requestedSchema,
string $toolName,
Expand Down

0 comments on commit d8fa401

Please sign in to comment.