Skip to content

Commit 8367977

Browse files
authored
refactor: make provider contract abstract (#434)
1 parent 4b1e6d1 commit 8367977

File tree

20 files changed

+118
-256
lines changed

20 files changed

+118
-256
lines changed

docs/advanced/custom-providers.md

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,13 @@ Want to add support for a new AI provider in Prism? This guide will walk you thr
44

55
## Provider Interface
66

7-
All providers must implement the `Prism\Prism\Contracts\Provider` interface:
7+
All providers must extend the `Prism\Prism\Providers\Provider` class.
88

9-
```php
10-
use Prism\Prism\Embeddings\Request as EmbeddingsRequest;
11-
use Prism\Prism\Embeddings\Response as EmbeddingsResponse;
12-
use Prism\Prism\Structured\Request as StructuredRequest;
13-
use Prism\Prism\Structured\Response as StructuredResponse;
14-
use Prism\Prism\Text\Request as TextRequest;
15-
use Prism\Prism\Text\Response as TextResponse;
16-
17-
interface Provider
18-
{
19-
public function text(TextRequest $request): TextResponse;
20-
21-
public function structured(StructuredRequest $request): StructuredResponse;
22-
23-
public function embeddings(EmbeddingsRequest $request): EmbeddingsResponse;
24-
}
25-
```
9+
The abstract class has a default method for all current required methods, though this may change.
2610

27-
The interface is intentionally simple, requiring just one method to handle text generation requests.
11+
Each provider should:
12+
- Overwrite the methods for the actions it supports.
13+
- Overwrite the `handleRequestExceptions` method if supports advanced request exceptions.
2814

2915
## Registration Process
3016

src/Concerns/ConfiguresProviders.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
namespace Prism\Prism\Concerns;
66

7-
use Prism\Prism\Contracts\Provider;
87
use Prism\Prism\Enums\Provider as ProviderEnum;
98
use Prism\Prism\PrismManager;
9+
use Prism\Prism\Providers\Provider;
1010

1111
trait ConfiguresProviders
1212
{

src/Contracts/Provider.php

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/Prism.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
namespace Prism\Prism;
66

7-
use Prism\Prism\Contracts\Provider;
87
use Prism\Prism\Embeddings\PendingRequest as PendingEmbeddingRequest;
98
use Prism\Prism\Embeddings\Response as EmbeddingResponse;
109
use Prism\Prism\Enums\Provider as ProviderEnum;
1110
use Prism\Prism\Images\PendingRequest as PendingImageRequest;
1211
use Prism\Prism\Images\Response as ImageResponse;
12+
use Prism\Prism\Providers\Provider;
1313
use Prism\Prism\Structured\PendingRequest as PendingStructuredRequest;
1414
use Prism\Prism\Structured\Response as StructuredResponse;
1515
use Prism\Prism\Testing\PrismFake;

src/PrismManager.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use Closure;
88
use Illuminate\Contracts\Foundation\Application;
99
use InvalidArgumentException;
10-
use Prism\Prism\Contracts\Provider;
1110
use Prism\Prism\Enums\Provider as ProviderEnum;
1211
use Prism\Prism\Providers\Anthropic\Anthropic;
1312
use Prism\Prism\Providers\DeepSeek\DeepSeek;
@@ -16,6 +15,7 @@
1615
use Prism\Prism\Providers\Mistral\Mistral;
1716
use Prism\Prism\Providers\Ollama\Ollama;
1817
use Prism\Prism\Providers\OpenAI\OpenAI;
18+
use Prism\Prism\Providers\Provider;
1919
use Prism\Prism\Providers\VoyageAI\VoyageAI;
2020
use Prism\Prism\Providers\XAI\XAI;
2121
use RuntimeException;

src/Providers/Anthropic/Anthropic.php

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,30 @@
88
use Illuminate\Http\Client\PendingRequest;
99
use Illuminate\Http\Client\RequestException;
1010
use Prism\Prism\Concerns\InitializesClient;
11-
use Prism\Prism\Contracts\Provider;
12-
use Prism\Prism\Embeddings\Request as EmbeddingRequest;
13-
use Prism\Prism\Embeddings\Response as EmbeddingResponse;
1411
use Prism\Prism\Enums\Provider as ProviderName;
1512
use Prism\Prism\Exceptions\PrismException;
1613
use Prism\Prism\Exceptions\PrismProviderOverloadedException;
1714
use Prism\Prism\Exceptions\PrismRateLimitedException;
1815
use Prism\Prism\Exceptions\PrismRequestTooLargeException;
19-
use Prism\Prism\Images\Request as ImagesRequest;
20-
use Prism\Prism\Images\Response as ImagesResponse;
2116
use Prism\Prism\Providers\Anthropic\Concerns\ProcessesRateLimits;
2217
use Prism\Prism\Providers\Anthropic\Handlers\Stream;
2318
use Prism\Prism\Providers\Anthropic\Handlers\Structured;
2419
use Prism\Prism\Providers\Anthropic\Handlers\Text;
20+
use Prism\Prism\Providers\Provider;
2521
use Prism\Prism\Structured\Request as StructuredRequest;
2622
use Prism\Prism\Structured\Response as StructuredResponse;
2723
use Prism\Prism\Text\Request as TextRequest;
2824
use Prism\Prism\Text\Response as TextResponse;
2925
use Throwable;
3026

31-
readonly class Anthropic implements Provider
27+
class Anthropic extends Provider
3228
{
3329
use InitializesClient, ProcessesRateLimits;
3430

3531
public function __construct(
36-
#[\SensitiveParameter] public string $apiKey,
37-
public string $apiVersion,
38-
public ?string $betaFeatures = null
32+
#[\SensitiveParameter] readonly public string $apiKey,
33+
readonly public string $apiVersion,
34+
readonly public ?string $betaFeatures = null
3935
) {}
4036

4137
#[\Override]
@@ -77,18 +73,6 @@ public function stream(TextRequest $request): Generator
7773
return $handler->handle($request);
7874
}
7975

80-
#[\Override]
81-
public function embeddings(EmbeddingRequest $request): EmbeddingResponse
82-
{
83-
throw new \Exception(sprintf('%s does not support embeddings', class_basename($this)));
84-
}
85-
86-
#[\Override]
87-
public function images(ImagesRequest $request): ImagesResponse
88-
{
89-
throw PrismException::unsupportedProviderAction(__METHOD__, class_basename($this));
90-
}
91-
9276
public function handleRequestExceptions(string $model, Throwable $e): never
9377
{
9478
if ($e instanceof PrismException) {

src/Providers/DeepSeek/DeepSeek.php

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,24 @@
44

55
namespace Prism\Prism\Providers\DeepSeek;
66

7-
use Generator;
87
use Illuminate\Http\Client\PendingRequest;
98
use Prism\Prism\Concerns\HandlesRequestExceptions;
109
use Prism\Prism\Concerns\InitializesClient;
11-
use Prism\Prism\Contracts\Provider;
12-
use Prism\Prism\Embeddings\Request as EmbeddingsRequest;
13-
use Prism\Prism\Embeddings\Response as EmbeddingsResponse;
14-
use Prism\Prism\Exceptions\PrismException;
15-
use Prism\Prism\Images\Request as ImagesRequest;
16-
use Prism\Prism\Images\Response as ImagesResponse;
1710
use Prism\Prism\Providers\DeepSeek\Handlers\Structured;
1811
use Prism\Prism\Providers\DeepSeek\Handlers\Text;
12+
use Prism\Prism\Providers\Provider;
1913
use Prism\Prism\Structured\Request as StructuredRequest;
2014
use Prism\Prism\Structured\Response as StructuredResponse;
2115
use Prism\Prism\Text\Request as TextRequest;
2216
use Prism\Prism\Text\Response as TextResponse;
2317

24-
readonly class DeepSeek implements Provider
18+
class DeepSeek extends Provider
2519
{
2620
use HandlesRequestExceptions, InitializesClient;
2721

2822
public function __construct(
29-
#[\SensitiveParameter] public string $apiKey,
30-
public string $url,
23+
#[\SensitiveParameter] readonly public string $apiKey,
24+
readonly public string $url,
3125
) {}
3226

3327
#[\Override]
@@ -52,24 +46,6 @@ public function structured(StructuredRequest $request): StructuredResponse
5246
return $handler->handle($request);
5347
}
5448

55-
#[\Override]
56-
public function embeddings(EmbeddingsRequest $request): EmbeddingsResponse
57-
{
58-
throw PrismException::unsupportedProviderAction(__FUNCTION__, class_basename($this));
59-
}
60-
61-
#[\Override]
62-
public function images(ImagesRequest $request): ImagesResponse
63-
{
64-
throw PrismException::unsupportedProviderAction(__METHOD__, class_basename($this));
65-
}
66-
67-
#[\Override]
68-
public function stream(TextRequest $request): Generator
69-
{
70-
throw PrismException::unsupportedProviderAction(__METHOD__, class_basename($this));
71-
}
72-
7349
/**
7450
* @param array<string, mixed> $options
7551
* @param array<mixed> $retry

src/Providers/Gemini/Gemini.php

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,29 @@
99
use Prism\Prism\Concerns\HandlesRequestExceptions;
1010
use Prism\Prism\Concerns\InitializesClient;
1111
use Prism\Prism\Contracts\Message;
12-
use Prism\Prism\Contracts\Provider;
1312
use Prism\Prism\Embeddings\Request as EmbeddingRequest;
1413
use Prism\Prism\Embeddings\Response as EmbeddingResponse;
1514
use Prism\Prism\Exceptions\PrismException;
16-
use Prism\Prism\Images\Request as ImagesRequest;
17-
use Prism\Prism\Images\Response as ImagesResponse;
1815
use Prism\Prism\Providers\Gemini\Handlers\Cache;
1916
use Prism\Prism\Providers\Gemini\Handlers\Embeddings;
2017
use Prism\Prism\Providers\Gemini\Handlers\Stream;
2118
use Prism\Prism\Providers\Gemini\Handlers\Structured;
2219
use Prism\Prism\Providers\Gemini\Handlers\Text;
2320
use Prism\Prism\Providers\Gemini\ValueObjects\GeminiCachedObject;
21+
use Prism\Prism\Providers\Provider;
2422
use Prism\Prism\Structured\Request as StructuredRequest;
2523
use Prism\Prism\Structured\Response as StructuredResponse;
2624
use Prism\Prism\Text\Request as TextRequest;
2725
use Prism\Prism\Text\Response as TextResponse;
2826
use Prism\Prism\ValueObjects\Messages\SystemMessage;
2927

30-
readonly class Gemini implements Provider
28+
class Gemini extends Provider
3129
{
3230
use HandlesRequestExceptions, InitializesClient;
3331

3432
public function __construct(
35-
#[\SensitiveParameter] public string $apiKey,
36-
public string $url,
33+
#[\SensitiveParameter] readonly public string $apiKey,
34+
readonly public string $url,
3735
) {}
3836

3937
#[\Override]
@@ -69,12 +67,6 @@ public function embeddings(EmbeddingRequest $request): EmbeddingResponse
6967
return $handler->handle($request);
7068
}
7169

72-
#[\Override]
73-
public function images(ImagesRequest $request): ImagesResponse
74-
{
75-
throw PrismException::unsupportedProviderAction(__METHOD__, class_basename($this));
76-
}
77-
7870
#[\Override]
7971
public function stream(TextRequest $request): Generator
8072
{

src/Providers/Groq/Groq.php

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,31 @@
44

55
namespace Prism\Prism\Providers\Groq;
66

7-
use Generator;
87
use Illuminate\Http\Client\PendingRequest;
98
use Illuminate\Http\Client\RequestException;
109
use Prism\Prism\Concerns\InitializesClient;
11-
use Prism\Prism\Contracts\Provider;
12-
use Prism\Prism\Embeddings\Request as EmbeddingRequest;
13-
use Prism\Prism\Embeddings\Response as EmbeddingResponse;
1410
use Prism\Prism\Enums\Provider as ProviderName;
1511
use Prism\Prism\Exceptions\PrismException;
1612
use Prism\Prism\Exceptions\PrismProviderOverloadedException;
1713
use Prism\Prism\Exceptions\PrismRateLimitedException;
1814
use Prism\Prism\Exceptions\PrismRequestTooLargeException;
19-
use Prism\Prism\Images\Request as ImagesRequest;
20-
use Prism\Prism\Images\Response as ImagesResponse;
2115
use Prism\Prism\Providers\Groq\Concerns\ProcessRateLimits;
2216
use Prism\Prism\Providers\Groq\Handlers\Structured;
2317
use Prism\Prism\Providers\Groq\Handlers\Text;
18+
use Prism\Prism\Providers\Provider;
2419
use Prism\Prism\Structured\Request as StructuredRequest;
2520
use Prism\Prism\Structured\Response as StructuredResponse;
2621
use Prism\Prism\Text\Request as TextRequest;
2722
use Prism\Prism\Text\Response as TextResponse;
2823
use Throwable;
2924

30-
readonly class Groq implements Provider
25+
class Groq extends Provider
3126
{
3227
use InitializesClient, ProcessRateLimits;
3328

3429
public function __construct(
35-
#[\SensitiveParameter] public string $apiKey,
36-
public string $url,
30+
#[\SensitiveParameter] readonly public string $apiKey,
31+
readonly public string $url,
3732
) {}
3833

3934
#[\Override]
@@ -52,24 +47,6 @@ public function structured(StructuredRequest $request): StructuredResponse
5247
return $handler->handle($request);
5348
}
5449

55-
#[\Override]
56-
public function embeddings(EmbeddingRequest $request): EmbeddingResponse
57-
{
58-
throw PrismException::unsupportedProviderAction(__METHOD__, class_basename($this));
59-
}
60-
61-
#[\Override]
62-
public function images(ImagesRequest $request): ImagesResponse
63-
{
64-
throw PrismException::unsupportedProviderAction(__METHOD__, class_basename($this));
65-
}
66-
67-
#[\Override]
68-
public function stream(TextRequest $request): Generator
69-
{
70-
throw PrismException::unsupportedProviderAction(__METHOD__, class_basename($this));
71-
}
72-
7350
public function handleRequestExceptions(string $model, Throwable $e): never
7451
{
7552
if ($e instanceof PrismException) {

src/Providers/Mistral/Mistral.php

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,35 @@
88
use Illuminate\Http\Client\PendingRequest;
99
use Illuminate\Http\Client\RequestException;
1010
use Prism\Prism\Concerns\InitializesClient;
11-
use Prism\Prism\Contracts\Provider;
1211
use Prism\Prism\Embeddings\Request as EmbeddingRequest;
1312
use Prism\Prism\Embeddings\Response as EmbeddingResponse;
1413
use Prism\Prism\Enums\Provider as ProviderName;
1514
use Prism\Prism\Exceptions\PrismException;
1615
use Prism\Prism\Exceptions\PrismProviderOverloadedException;
1716
use Prism\Prism\Exceptions\PrismRateLimitedException;
1817
use Prism\Prism\Exceptions\PrismRequestTooLargeException;
19-
use Prism\Prism\Images\Request as ImagesRequest;
20-
use Prism\Prism\Images\Response as ImagesResponse;
2118
use Prism\Prism\Providers\Mistral\Concerns\ProcessRateLimits;
2219
use Prism\Prism\Providers\Mistral\Handlers\Embeddings;
2320
use Prism\Prism\Providers\Mistral\Handlers\OCR;
2421
use Prism\Prism\Providers\Mistral\Handlers\Stream;
2522
use Prism\Prism\Providers\Mistral\Handlers\Structured;
2623
use Prism\Prism\Providers\Mistral\Handlers\Text;
2724
use Prism\Prism\Providers\Mistral\ValueObjects\OCRResponse;
25+
use Prism\Prism\Providers\Provider;
2826
use Prism\Prism\Structured\Request as StructuredRequest;
2927
use Prism\Prism\Structured\Response as StructuredResponse;
3028
use Prism\Prism\Text\Request as TextRequest;
3129
use Prism\Prism\Text\Response as TextResponse;
3230
use Prism\Prism\ValueObjects\Messages\Support\Document;
3331
use Throwable;
3432

35-
readonly class Mistral implements Provider
33+
class Mistral extends Provider
3634
{
3735
use InitializesClient, ProcessRateLimits;
3836

3937
public function __construct(
40-
#[\SensitiveParameter] public string $apiKey,
41-
public string $url,
38+
#[\SensitiveParameter] readonly public string $apiKey,
39+
readonly public string $url,
4240
) {}
4341

4442
#[\Override]
@@ -77,12 +75,6 @@ public function embeddings(EmbeddingRequest $request): EmbeddingResponse
7775
return $handler->handle($request);
7876
}
7977

80-
#[\Override]
81-
public function images(ImagesRequest $request): ImagesResponse
82-
{
83-
throw PrismException::unsupportedProviderAction(__METHOD__, class_basename($this));
84-
}
85-
8678
/**
8779
* @throws PrismRateLimitedException
8880
* @throws PrismException

0 commit comments

Comments
 (0)