Skip to content

Commit e968a28

Browse files
authored
Refactors / Provider cleanup (#61)
1 parent a594bcc commit e968a28

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1510
-1728
lines changed

Diff for: docs/providers/ollama.md

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ Prism::text() // [!code focus]
1919
```
2020

2121
## Limitations
22+
### Image URL
23+
24+
Ollama does not support images using `Image::fromUrl()`.
25+
2226
### Tool Choice
2327

2428
Ollama does not currently support tool choice / required tools.

Diff for: docs/providers/xai.md

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
```
1010

1111
## Limitations
12+
### Tool Choice
13+
14+
xAI does not support `->withToolChoice`.
15+
1216
### Image Support
1317

1418
xAI does not support image inputs.

Diff for: src/Concerns/BuildsTextRequests.php

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use EchoLabs\Prism\Enums\Provider;
99
use EchoLabs\Prism\Enums\ToolChoice;
1010
use EchoLabs\Prism\Exceptions\PrismException;
11-
use EchoLabs\Prism\Requests\TextRequest;
11+
use EchoLabs\Prism\Text\Request;
1212
use EchoLabs\Prism\Tool;
1313
use EchoLabs\Prism\ValueObjects\Messages\UserMessage;
1414
use Illuminate\Contracts\View\View;
@@ -63,7 +63,7 @@ public function withPrompt(string|View $prompt): self
6363

6464
$this->prompt = is_string($prompt) ? $prompt : $prompt->render();
6565

66-
$this->state->addMessage(new UserMessage($this->prompt));
66+
$this->messages[] = new UserMessage($this->prompt);
6767

6868
return $this;
6969
}
@@ -94,7 +94,7 @@ public function withMessages(array $messages): self
9494
throw PrismException::promptOrMessages();
9595
}
9696

97-
$this->state->setMessages($messages);
97+
$this->messages = $messages;
9898

9999
return $this;
100100
}
@@ -146,13 +146,13 @@ public function withToolChoice(string|ToolChoice|Tool $toolChoice): self
146146
return $this;
147147
}
148148

149-
protected function textRequest(): TextRequest
149+
protected function textRequest(): Request
150150
{
151-
return new TextRequest(
151+
return new Request(
152152
model: $this->model,
153153
systemPrompt: $this->systemPrompt,
154154
prompt: $this->prompt,
155-
messages: $this->state->messages()->toArray(),
155+
messages: $this->messages,
156156
temperature: $this->temperature,
157157
maxTokens: $this->maxTokens,
158158
topP: $this->topP,

Diff for: src/Contracts/Generator.php

Whitespace-only changes.

Diff for: src/Contracts/Provider.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
namespace EchoLabs\Prism\Contracts;
66

77
use EchoLabs\Prism\Providers\ProviderResponse;
8-
use EchoLabs\Prism\Requests\TextRequest;
8+
use EchoLabs\Prism\Text\Request;
99

1010
interface Provider
1111
{
12-
public function text(TextRequest $request): ProviderResponse;
12+
public function text(Request $request): ProviderResponse;
1313
}

Diff for: src/Facades/PrismServer.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
namespace EchoLabs\Prism\Facades;
66

77
use Closure;
8-
use EchoLabs\Prism\Generators\TextGenerator;
8+
use EchoLabs\Prism\Text\Generator;
99
use Illuminate\Support\Collection;
1010
use Illuminate\Support\Facades\Facade;
1111

1212
/**
13-
* @method static self register(string $name, Closure():TextGenerator|callable():TextGenerator $prism)
14-
* @method static Collection<int, array{name: string, prism: Closure():TextGenerator|callable():TextGenerator}> prisms()
13+
* @method static self register(string $name, Closure():Generator|callable():Generator $prism)
14+
* @method static Collection<int, array{name: string, prism: Closure():Generator|callable():Generator}> prisms()
1515
*/
1616
class PrismServer extends Facade
1717
{

Diff for: src/Http/Controllers/PrismChatController.php

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
use EchoLabs\Prism\Exceptions\PrismServerException;
66
use EchoLabs\Prism\Facades\PrismServer;
7-
use EchoLabs\Prism\Generators\TextGenerator;
8-
use EchoLabs\Prism\Responses\TextResponse;
7+
use EchoLabs\Prism\Text\Generator;
8+
use EchoLabs\Prism\Text\Response as TextResponse;
99
use EchoLabs\Prism\ValueObjects\Messages\AssistantMessage;
1010
use EchoLabs\Prism\ValueObjects\Messages\UserMessage;
1111
use Illuminate\Support\ItemNotFoundException;
@@ -40,7 +40,7 @@ public function __invoke(): Response
4040
}
4141
}
4242

43-
protected function stream(TextGenerator $generator): Response
43+
protected function stream(Generator $generator): Response
4444
{
4545
return response()->stream(function () use ($generator): void {
4646
$response = $generator->generate();
@@ -79,7 +79,7 @@ protected function error(Throwable $e): Response
7979
], Response::HTTP_INTERNAL_SERVER_ERROR);
8080
}
8181

82-
protected function chat(TextGenerator $generator): Response
82+
protected function chat(Generator $generator): Response
8383
{
8484
$response = $generator->generate();
8585

@@ -131,7 +131,7 @@ protected function mapMessages($messages): array
131131
->toArray();
132132
}
133133

134-
protected function resolvePrism(string $model): TextGenerator
134+
protected function resolvePrism(string $model): Generator
135135
{
136136
try {
137137
$prism = PrismServer::prisms()

Diff for: src/Prism.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
use EchoLabs\Prism\Contracts\Provider;
88
use EchoLabs\Prism\Enums\Provider as ProviderEnum;
9-
use EchoLabs\Prism\Generators\TextGenerator;
109
use EchoLabs\Prism\Providers\ProviderResponse;
1110
use EchoLabs\Prism\Testing\PrismFake;
11+
use EchoLabs\Prism\Text\Generator;
1212

1313
class Prism
1414
{
@@ -34,8 +34,8 @@ public function resolve(ProviderEnum|string $name): Provider
3434
return $fake;
3535
}
3636

37-
public static function text(): TextGenerator
37+
public static function text(): Generator
3838
{
39-
return new TextGenerator;
39+
return new Generator;
4040
}
4141
}

Diff for: src/PrismServer.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,27 @@
55
namespace EchoLabs\Prism;
66

77
use Closure;
8-
use EchoLabs\Prism\Generators\TextGenerator;
8+
use EchoLabs\Prism\Text\Generator;
99
use Illuminate\Support\Collection;
1010

1111
class PrismServer
1212
{
1313
/**
14-
* @param Collection<int, array{name: string, prism: Closure():TextGenerator|callable():TextGenerator}> $prisms
14+
* @param Collection<int, array{name: string, prism: Closure():Generator|callable():Generator}> $prisms
1515
* */
1616
public function __construct(
1717
protected readonly Collection $prisms = new Collection,
1818
) {}
1919

20-
/** @param \Closure():TextGenerator|callable():TextGenerator $prism */
20+
/** @param \Closure():Generator|callable():Generator $prism */
2121
public function register(string $name, Closure|callable $prism): self
2222
{
2323
$this->prisms->push(['name' => $name, 'prism' => $prism]);
2424

2525
return $this;
2626
}
2727

28-
/** @return Collection<int, array{name: string, prism: Closure():TextGenerator|callable():TextGenerator}> */
28+
/** @return Collection<int, array{name: string, prism: Closure():Generator|callable():Generator}> */
2929
public function prisms(): Collection
3030
{
3131
return $this->prisms;

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

+14-109
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,11 @@
55
namespace EchoLabs\Prism\Providers\Anthropic;
66

77
use EchoLabs\Prism\Contracts\Provider;
8-
use EchoLabs\Prism\Enums\FinishReason;
9-
use EchoLabs\Prism\Enums\ToolChoice;
10-
use EchoLabs\Prism\Exceptions\PrismException;
8+
use EchoLabs\Prism\Providers\Anthropic\Handlers\Text;
119
use EchoLabs\Prism\Providers\ProviderResponse;
12-
use EchoLabs\Prism\Requests\TextRequest;
13-
use EchoLabs\Prism\ValueObjects\ToolCall;
14-
use EchoLabs\Prism\ValueObjects\Usage;
15-
use InvalidArgumentException;
16-
use Throwable;
10+
use EchoLabs\Prism\Text\Request;
11+
use Illuminate\Http\Client\PendingRequest;
12+
use Illuminate\Support\Facades\Http;
1713

1814
class Anthropic implements Provider
1915
{
@@ -23,114 +19,23 @@ public function __construct(
2319
) {}
2420

2521
#[\Override]
26-
public function text(TextRequest $request): ProviderResponse
22+
public function text(Request $request): ProviderResponse
2723
{
28-
try {
29-
$response = $this
30-
->client($request->clientOptions)
31-
->messages(
32-
model: $request->model,
33-
systemPrompt: $request->systemPrompt,
34-
messages: (new MessageMap($request->messages))(),
35-
maxTokens: $request->maxTokens,
36-
temperature: $request->temperature,
37-
topP: $request->topP,
38-
tools: Tool::map($request->tools),
39-
toolChoice: $this->mapToolChoice($request->toolChoice),
40-
);
41-
} catch (Throwable $e) {
42-
throw PrismException::providerRequestError($request->model, $e);
43-
}
24+
$handler = new Text($this->client($request->clientOptions));
4425

45-
$data = $response->json();
46-
47-
if (data_get($data, 'type') === 'error') {
48-
throw PrismException::providerResponseError(vsprintf(
49-
'Anthropic Error: [%s] %s',
50-
[
51-
data_get($data, 'error.type', 'unknown'),
52-
data_get($data, 'error.message'),
53-
]
54-
));
55-
}
56-
57-
$text = '';
58-
$toolCalls = [];
59-
60-
foreach (data_get($data, 'content', []) as $content) {
61-
if (data_get($content, 'type') === 'text') {
62-
$text .= data_get($content, 'text');
63-
}
64-
65-
if (data_get($content, 'type') === 'tool_use') {
66-
$toolCalls[] = new ToolCall(
67-
id: data_get($content, 'id'),
68-
name: data_get($content, 'name'),
69-
arguments: data_get($content, 'input'),
70-
);
71-
}
72-
}
73-
74-
return new ProviderResponse(
75-
text: $text,
76-
toolCalls: $toolCalls,
77-
usage: new Usage(
78-
data_get($data, 'usage.input_tokens'),
79-
data_get($data, 'usage.output_tokens'),
80-
),
81-
finishReason: $this->mapFinishReason(data_get($data, 'stop_reason', '')),
82-
response: [
83-
'id' => data_get($data, 'id'),
84-
'model' => data_get($data, 'model'),
85-
]
86-
);
87-
}
88-
89-
/**
90-
* @return array<string, mixed>|string|null
91-
*/
92-
protected function mapToolChoice(string|ToolChoice|null $toolChoice): string|array|null
93-
{
94-
if (is_null($toolChoice)) {
95-
return null;
96-
}
97-
98-
if (is_string($toolChoice)) {
99-
return [
100-
'type' => 'tool',
101-
'name' => $toolChoice,
102-
];
103-
}
104-
105-
if (! in_array($toolChoice, [ToolChoice::Auto, ToolChoice::Any])) {
106-
throw new InvalidArgumentException('Invalid tool choice');
107-
}
108-
109-
return match ($toolChoice) {
110-
ToolChoice::Auto => 'auto',
111-
ToolChoice::Any => 'any',
112-
};
26+
return $handler->handle($request);
11327
}
11428

11529
/**
11630
* @param array<string, mixed> $options
11731
*/
118-
protected function client(array $options = []): Client
119-
{
120-
return new Client(
121-
apiKey: $this->apiKey,
122-
apiVersion: $this->apiVersion,
123-
options: $options,
124-
);
125-
}
126-
127-
protected function mapFinishReason(string $stopReason): FinishReason
32+
protected function client(array $options = []): PendingRequest
12833
{
129-
return match ($stopReason) {
130-
'end_turn', 'stop_sequence' => FinishReason::Stop,
131-
'tool_use' => FinishReason::ToolCalls,
132-
'max_tokens' => FinishReason::Length,
133-
default => FinishReason::Unknown,
134-
};
34+
return Http::withHeaders([
35+
'x-api-key' => $this->apiKey,
36+
'anthropic-version' => $this->apiVersion,
37+
])
38+
->withOptions($options)
39+
->baseUrl('https://api.anthropic.com/v1');
13540
}
13641
}

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

-61
This file was deleted.

0 commit comments

Comments
 (0)