Skip to content

Commit

Permalink
Refactored HttpClient and drivers
Browse files Browse the repository at this point in the history
  • Loading branch information
ddebowczyk committed Oct 6, 2024
1 parent d8fa401 commit 163b770
Show file tree
Hide file tree
Showing 34 changed files with 435 additions and 205 deletions.
7 changes: 6 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,12 @@
"duzun/hquery": "^3.1",
"ext-dom": "*",
"psy/psysh": "@stable",
"symfony/http-client": "^7.1"
"symfony/http-client": "^7.1",
"php-http/discovery": "^1.20",
"psr/http-factory-implementation": "*",
"symfony/psr-http-message-bridge": "^7.1",
"nyholm/psr7": "^1.8",
"guzzlehttp/psr7": "^2.7"
},
"config": {
"allow-plugins": {
Expand Down
2 changes: 2 additions & 0 deletions config/embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
'defaultModel' => 'nomic-embed-text',
'defaultDimensions' => 1024,
'maxInputs' => 512,
'connectionTimeout' => 5,
'requestTimeout' => 30,
],
'openai' => [
'providerType' => LLMProviderType::OpenAI->value,
Expand Down
7 changes: 6 additions & 1 deletion config/http.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use Cognesy\Instructor\Extras\Enums\HttpClientType;

return [
'defaultClient' => 'guzzle',
'defaultClient' => 'symfony',

'cache' => [
'enabled' => false,
Expand All @@ -17,5 +17,10 @@
'connectTimeout' => 3,
'requestTimeout' => 30,
],
'symfony' => [
'httpClientType' => HttpClientType::Symfony->value,
'connectTimeout' => 90, // Symfony HttpClient does not allow to set connect timeout, set it to request timeout
'requestTimeout' => 90,
],
]
];
2 changes: 2 additions & 0 deletions config/llm.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@
'endpoint' => '/chat/completions',
'defaultModel' => 'llama3.2:3b', //'gemma2:2b',
'defaultMaxTokens' => 1024,
'connectTimeout' => 30,
'requestTimeout' => 60,
],
'openai' => [
'providerType' => LLMProviderType::OpenAI->value,
Expand Down
31 changes: 16 additions & 15 deletions evals/LLMModes/run.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,34 @@
use Cognesy\Evals\LLMModes\CompareModes;
use Cognesy\Evals\LLMModes\EvalInput;
use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Extras\Debug\Debug;
use Cognesy\Instructor\Utils\Json\Json;
use Cognesy\Instructor\Utils\Str;

$connections = [
'azure',
'cohere1',
'fireworks',
'gemini',
'groq',
'mistral',
// 'azure',
// 'cohere1',
// 'fireworks',
// 'gemini',
// 'groq',
// 'mistral',
'ollama',
'openai',
'openrouter',
'together',
// 'openai',
// 'openrouter',
// 'together',
];

$streamingModes = [
true,
false,
// false,
];

$modes = [
Mode::Text,
Mode::MdJson,
Mode::Json,
Mode::JsonSchema,
Mode::Tools,
// Mode::MdJson,
// Mode::Json,
// Mode::JsonSchema,
// Mode::Tools,
];

//
Expand All @@ -43,7 +44,7 @@
// azure, Mode::JsonSchema, sync|stream
//

//Debug::enable();
Debug::enable();

function evalFn(EvalInput $er) {
$decoded = Json::from($er->answer)->toArray();
Expand Down
5 changes: 4 additions & 1 deletion examples/A02_Advanced/PartialUpdates/run.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
$loader = require 'vendor/autoload.php';
$loader->add('Cognesy\\Instructor\\', __DIR__ . '../../src/');

use Cognesy\Instructor\Enums\Mode;
use Cognesy\Instructor\Events\Event;
use Cognesy\Instructor\Instructor;

Expand Down Expand Up @@ -66,11 +67,13 @@ function partialUpdate($partial) {
TEXT;

$user = (new Instructor)
->withConnection('openai')
->onPartialUpdate(partialUpdate(...))
->request(
messages: $text,
responseModel: UserDetail::class,
options: ['stream' => true]
options: ['stream' => true],
mode: Mode::Json,
)->get();

echo "All tokens received, fully completed object available in `\$user` variable.\n";
Expand Down
2 changes: 0 additions & 2 deletions examples/A03_Troubleshooting/Debugging/run.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@

use Cognesy\Instructor\Extras\LLM\Data\LLMConfig;
use Cognesy\Instructor\Extras\LLM\Drivers\OpenAIDriver;
use Cognesy\Instructor\Extras\LLM\Enums\LLMProviderType;
use Cognesy\Instructor\Instructor;
use Cognesy\Instructor\Utils\Env;

class User {
public int $age;
Expand Down
20 changes: 16 additions & 4 deletions notes/NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# NOTES

## High priority

- Logging via PSR-3
- Schema abstraction layer - decouple names and descriptions from the model
- Prompt optimization via TextGrad
- Eval framework
- Agents
- Indexing to vector DB
- CLI app
- Fast/simple REST API server - compatible with OpenAI?
- Revise examples debugging - not sure if it works as expected (what does it demonstrate?)

# Partially done

- Export configuration to user folder / use external configuration
Expand All @@ -22,9 +34,6 @@

- Modules: Add module observability via events - currently no access to this info

## Configuration

- Examples how to override default configuration

## Refactorings

Expand All @@ -37,7 +46,7 @@
## Infrastructure

- Async mode
- Fix cache mode
- Fix response caching
- Finish logging support
- Document how to inject custom HTTP client
- Better error messages
Expand Down Expand Up @@ -73,6 +82,9 @@

> NOTE: Move notes here
## Configuration

- Examples how to override default configuration



Expand Down
1 change: 0 additions & 1 deletion src/Extras/Embeddings/Data/EmbeddingsConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public static function load(string $connection) : EmbeddingsConfig {
if (!Settings::has('embed', "connections.$connection")) {
throw new InvalidArgumentException("Unknown connection: $connection");
}

return new EmbeddingsConfig(
apiUrl: Settings::get('embed', "connections.$connection.apiUrl"),
apiKey: Settings::get('embed', "connections.$connection.apiKey", ''),
Expand Down
2 changes: 1 addition & 1 deletion src/Extras/Embeddings/Drivers/AzureOpenAIDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function vectorize(array $input, array $options = []): EmbeddingsResponse
$this->getRequestHeaders(),
$this->getRequestBody($input, $options),
);
return $this->toResponse(json_decode($response->getBody()->getContents(), true));
return $this->toResponse(json_decode($response->getContents(), true));
}

// INTERNAL /////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion src/Extras/Embeddings/Drivers/CohereDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function vectorize(array $input, array $options = []): EmbeddingsResponse
$this->getRequestHeaders(),
$this->getRequestBody($input, $options),
);
return $this->toResponse(json_decode($response->getBody()->getContents(), true));
return $this->toResponse(json_decode($response->getContents(), true));
}

// INTERNAL /////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion src/Extras/Embeddings/Drivers/GeminiDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function vectorize(array $input, array $options = []): EmbeddingsResponse
$this->getRequestHeaders(),
$this->getRequestBody($input, $options),
);
return $this->toResponse(json_decode($response->getBody()->getContents(), true));
return $this->toResponse(json_decode($response->getContents(), true));
}

// INTERNAL /////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion src/Extras/Embeddings/Drivers/JinaDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function vectorize(array $input, array $options = []): EmbeddingsResponse
$this->getRequestHeaders(),
$this->getRequestBody($input, $options),
);
return $this->toResponse(json_decode($response->getBody()->getContents(), true));
return $this->toResponse(json_decode($response->getContents(), true));
}

// INTERNAL /////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion src/Extras/Embeddings/Drivers/OpenAIDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function vectorize(array $input, array $options = []): EmbeddingsResponse
$this->getRequestHeaders(),
$this->getRequestBody($input, $options),
);
return $this->toResponse(json_decode($response->getBody()->getContents(), true));
return $this->toResponse(json_decode($response->getContents(), true));
}

// INTERNAL /////////////////////////////////////////////////
Expand Down
1 change: 1 addition & 0 deletions src/Extras/Enums/HttpClientType.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
enum HttpClientType : string
{
case Guzzle = 'guzzle';
case Symfony = 'symfony';
case Unknown = 'unknown';
}
32 changes: 32 additions & 0 deletions src/Extras/Http/Adapters/PsrResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Cognesy\Instructor\Extras\Http\Adapters;

use Cognesy\Instructor\Extras\Http\Contracts\CanHandleResponse;
use Generator;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;

class PsrResponse implements CanHandleResponse
{
private ResponseInterface $response;
private StreamInterface $stream;

public function __construct(
ResponseInterface $response,
StreamInterface $stream,
) {
$this->response = $response;
$this->stream = $stream;
}

public function getContents(): string {
return $this->response->getBody()->getContents();
}

public function streamContents(int $chunkSize = 1): Generator {
while (!$this->stream->eof()) {
yield $this->stream->read($chunkSize);
}
}
}
32 changes: 32 additions & 0 deletions src/Extras/Http/Adapters/SymfonyResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Cognesy\Instructor\Extras\Http\Adapters;

use Cognesy\Instructor\Extras\Http\Contracts\CanHandleResponse;
use Generator;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

class SymfonyResponse implements CanHandleResponse
{
private ResponseInterface $response;
private HttpClientInterface $client;

public function __construct(
HttpClientInterface $client,
ResponseInterface $response,
) {
$this->client = $client;
$this->response = $response;
}

public function getContents(): string {
return $this->response->getContent();
}

public function streamContents(int $chunkSize = 1): Generator {
foreach ($this->client->stream($this->response) as $chunk) {
yield $chunk->getContent();
}
}
}
4 changes: 1 addition & 3 deletions src/Extras/Http/Contracts/CanHandleHttp.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
<?php
namespace Cognesy\Instructor\Extras\Http\Contracts;

use Psr\Http\Message\ResponseInterface;

interface CanHandleHttp
{
public function handle(string $url, array $headers, array $body, string $method = 'POST', bool $streaming = false) : ResponseInterface;
public function handle(string $url, array $headers, array $body, string $method = 'POST', bool $streaming = false) : CanHandleResponse;
}
23 changes: 23 additions & 0 deletions src/Extras/Http/Contracts/CanHandleResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Cognesy\Instructor\Extras\Http\Contracts;

use Generator;

interface CanHandleResponse
{
/**
* Get the response
*
* @return int
*/
public function getContents(): string;

/**
* Read chunks of the stream
*
* @param int $chunkSize
* @return Generator<string>
*/
public function streamContents(int $chunkSize = 1): Generator;
}
Loading

0 comments on commit 163b770

Please sign in to comment.