Skip to content

Commit 180153b

Browse files
authored
Proxy retry call to Laravel HTTP client (#67)
1 parent 962a0be commit 180153b

File tree

11 files changed

+77
-12
lines changed

11 files changed

+77
-12
lines changed

Diff for: docs/core-concepts/text-generation.md

+4
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ The value is passed through to the provider. The range depends on the provider a
132132

133133
Under the hood we use Laravel's [HTTP client](https://laravel.com/docs/11.x/http-client#main-content). You can use this method to pass any of Guzzles [request options](https://docs.guzzlephp.org/en/stable/request-options.html) e.g. `->withClientOptions(['timeout' => 30])`.
134134

135+
`withClientRetry`
136+
137+
Under the hood we use Laravel's [HTTP client](https://laravel.com/docs/11.x/http-client#main-content). You can use this method to set [retries](https://laravel.com/docs/11.x/http-client#retries) e.g. `->withClientRetry(3, 100)`.
138+
135139
## Response Handling
136140

137141
The response object provides rich access to the generation results:

Diff for: src/Concerns/BuildsTextRequests.php

+19
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace EchoLabs\Prism\Concerns;
66

7+
use Closure;
78
use EchoLabs\Prism\Contracts\Message;
89
use EchoLabs\Prism\Enums\Provider;
910
use EchoLabs\Prism\Enums\ToolChoice;
@@ -18,6 +19,9 @@ trait BuildsTextRequests
1819
/** @var array<string, mixed> */
1920
protected array $clientOptions = [];
2021

22+
/** @var array{0: array<int, int>|int, 1?: Closure|int, 2?: ?callable, 3?: bool} */
23+
protected array $clientRetry = [0];
24+
2125
protected ?string $prompt = null;
2226

2327
protected ?string $systemPrompt = null;
@@ -137,6 +141,20 @@ public function withClientOptions(array $options): self
137141
return $this;
138142
}
139143

144+
/**
145+
* @param array<int>|int $times
146+
*/
147+
public function withClientRetry(
148+
array|int $times,
149+
Closure|int $sleepMilliseconds = 0,
150+
?callable $when = null,
151+
bool $throw = true
152+
): self {
153+
$this->clientRetry = [$times, $sleepMilliseconds, $when, $throw];
154+
155+
return $this;
156+
}
157+
140158
public function withToolChoice(string|ToolChoice|Tool $toolChoice): self
141159
{
142160
$this->toolChoice = $toolChoice instanceof Tool
@@ -158,6 +176,7 @@ protected function textRequest(): Request
158176
topP: $this->topP,
159177
tools: $this->tools,
160178
clientOptions: $this->clientOptions,
179+
clientRetry: $this->clientRetry,
161180
toolChoice: $this->toolChoice,
162181
);
163182
}

Diff for: src/Providers/Anthropic/Anthropic.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,23 @@ public function __construct(
2121
#[\Override]
2222
public function text(Request $request): ProviderResponse
2323
{
24-
$handler = new Text($this->client($request->clientOptions));
24+
$handler = new Text($this->client($request->clientOptions, $request->clientRetry));
2525

2626
return $handler->handle($request);
2727
}
2828

2929
/**
3030
* @param array<string, mixed> $options
31+
* @param array<mixed> $retry
3132
*/
32-
protected function client(array $options = []): PendingRequest
33+
protected function client(array $options = [], array $retry = []): PendingRequest
3334
{
3435
return Http::withHeaders([
3536
'x-api-key' => $this->apiKey,
3637
'anthropic-version' => $this->apiVersion,
3738
])
3839
->withOptions($options)
40+
->retry(...$retry)
3941
->baseUrl('https://api.anthropic.com/v1');
4042
}
4143
}

Diff for: src/Providers/Groq/Groq.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,22 @@ public function __construct(
2121
#[\Override]
2222
public function text(Request $request): ProviderResponse
2323
{
24-
$handler = new Text($this->client($request->clientOptions));
24+
$handler = new Text($this->client($request->clientOptions, $request->clientRetry));
2525

2626
return $handler->handle($request);
2727
}
2828

2929
/**
3030
* @param array<string, mixed> $options
31+
* @param array<mixed> $retry
3132
*/
32-
protected function client(array $options = []): PendingRequest
33+
protected function client(array $options = [], array $retry = []): PendingRequest
3334
{
3435
return Http::withHeaders(array_filter([
3536
'Authorization' => $this->apiKey !== '' && $this->apiKey !== '0' ? sprintf('Bearer %s', $this->apiKey) : null,
3637
]))
3738
->withOptions($options)
39+
->retry(...$retry)
3840
->baseUrl($this->url);
3941
}
4042
}

Diff for: src/Providers/Mistral/Mistral.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,22 @@ public function __construct(
2121
#[\Override]
2222
public function text(Request $request): ProviderResponse
2323
{
24-
$handler = new Text($this->client($request->clientOptions));
24+
$handler = new Text($this->client($request->clientOptions, $request->clientRetry));
2525

2626
return $handler->handle($request);
2727
}
2828

2929
/**
3030
* @param array<string, mixed> $options
31+
* @param array<mixed> $retry
3132
*/
32-
protected function client(array $options = []): PendingRequest
33+
protected function client(array $options = [], array $retry = []): PendingRequest
3334
{
3435
return Http::withHeaders(array_filter([
3536
'Authorization' => $this->apiKey !== '' && $this->apiKey !== '0' ? sprintf('Bearer %s', $this->apiKey) : null,
3637
]))
3738
->withOptions($options)
39+
->retry(...$retry)
3840
->baseUrl($this->url);
3941
}
4042
}

Diff for: src/Providers/Ollama/Ollama.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,22 @@ public function __construct(
2121
#[\Override]
2222
public function text(Request $request): ProviderResponse
2323
{
24-
$handler = new Text($this->client($request->clientOptions));
24+
$handler = new Text($this->client($request->clientOptions, $request->clientRetry));
2525

2626
return $handler->handle($request);
2727
}
2828

2929
/**
3030
* @param array<string, mixed> $options
31+
* @param array<mixed> $retry
3132
*/
32-
protected function client(array $options = []): PendingRequest
33+
protected function client(array $options = [], array $retry = []): PendingRequest
3334
{
3435
return Http::withHeaders(array_filter([
3536
'Authorization' => $this->apiKey !== '' && $this->apiKey !== '0' ? sprintf('Bearer %s', $this->apiKey) : null,
3637
]))
3738
->withOptions($options)
39+
->retry(...$retry)
3840
->baseUrl($this->url);
3941
}
4042
}

Diff for: src/Providers/OpenAI/OpenAI.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,23 @@ public function __construct(
2222
#[\Override]
2323
public function text(Request $request): ProviderResponse
2424
{
25-
$handler = new Text($this->client($request->clientOptions));
25+
$handler = new Text($this->client($request->clientOptions, $request->clientRetry));
2626

2727
return $handler->handle($request);
2828
}
2929

3030
/**
3131
* @param array<string, mixed> $options
32+
* @param array<mixed> $retry
3233
*/
33-
protected function client(array $options = []): PendingRequest
34+
protected function client(array $options = [], array $retry = []): PendingRequest
3435
{
3536
return Http::withHeaders(array_filter([
3637
'Authorization' => $this->apiKey !== '' && $this->apiKey !== '0' ? sprintf('Bearer %s', $this->apiKey) : null,
3738
'OpenAI-Organization' => $this->organization,
3839
]))
3940
->withOptions($options)
41+
->retry(...$retry)
4042
->baseUrl($this->url);
4143
}
4244
}

Diff for: src/Providers/XAI/XAI.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,22 @@ public function __construct(
2121
#[\Override]
2222
public function text(Request $request): ProviderResponse
2323
{
24-
$handler = new Text($this->client($request->clientOptions));
24+
$handler = new Text($this->client($request->clientOptions, $request->clientRetry));
2525

2626
return $handler->handle($request);
2727
}
2828

2929
/**
3030
* @param array<string, mixed> $options
31+
* @param array<mixed> $retry
3132
*/
32-
protected function client(array $options = []): PendingRequest
33+
protected function client(array $options = [], array $retry = []): PendingRequest
3334
{
3435
return Http::withHeaders(array_filter([
3536
'Authorization' => $this->apiKey !== '' && $this->apiKey !== '0' ? sprintf('Bearer %s', $this->apiKey) : null,
3637
]))
3738
->withOptions($options)
39+
->retry(...$retry)
3840
->baseUrl($this->url);
3941
}
4042
}

Diff for: src/Text/Request.php

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Request
1414
* @param array<int, Message> $messages
1515
* @param array<int, Tool> $tools
1616
* @param array<string, mixed> $clientOptions
17+
* @param array<mixed> $clientRetry
1718
*/
1819
public function __construct(
1920
public readonly string $model,
@@ -25,6 +26,7 @@ public function __construct(
2526
public readonly int|float|null $topP,
2627
public readonly array $tools,
2728
public readonly array $clientOptions,
29+
public readonly array $clientRetry,
2830
public readonly string|ToolChoice|null $toolChoice,
2931
) {}
3032
}

Diff for: tests/Generators/TextGeneratorTest.php

+25
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,31 @@
4343
expect($provider->request->clientOptions)->toBe(['timeout' => '100']);
4444
});
4545

46+
it('allows for client retry', function (): void {
47+
$provider = new TestProvider;
48+
49+
resolve(PrismManager::class)->extend('test', fn (): \Tests\TestDoubles\TestProvider => $provider);
50+
51+
(new Generator)
52+
->using('test', 'claude-3-5-sonnet-20240620')
53+
->withClientRetry(3, 100)
54+
->generate();
55+
56+
expect($provider->request->clientRetry)->toBe([3, 100, null, true]);
57+
});
58+
59+
it('defaults to no client retry', function (): void {
60+
$provider = new TestProvider;
61+
62+
resolve(PrismManager::class)->extend('test', fn (): \Tests\TestDoubles\TestProvider => $provider);
63+
64+
(new Generator)
65+
->using('test', 'claude-3-5-sonnet-20240620')
66+
->generate();
67+
68+
expect($provider->request->clientRetry)->toBe([0]);
69+
});
70+
4671
it('allows for provider string or enum', function (): void {
4772
$provider = new TestProvider;
4873

Diff for: tests/TestDoubles/TestProvider.php

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ class TestProvider implements Provider
1717
/** @var array<string, mixed> */
1818
public array $clientOptions;
1919

20+
/** @var array<mixed> */
21+
public array $clientRetry;
22+
2023
/** @var array<int, ProviderResponse> */
2124
public array $responses = [];
2225

0 commit comments

Comments
 (0)