forked from prism-php/bedrock
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathConverseStructuredHandlerTest.php
More file actions
131 lines (114 loc) · 4.78 KB
/
ConverseStructuredHandlerTest.php
File metadata and controls
131 lines (114 loc) · 4.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<?php
declare(strict_types=1);
namespace Tests\Schemas\Converse;
use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Http;
use Prism\Bedrock\Enums\BedrockSchema;
use Prism\Prism\Prism;
use Prism\Prism\Schema\BooleanSchema;
use Prism\Prism\Schema\ObjectSchema;
use Prism\Prism\Schema\StringSchema;
use Prism\Prism\Structured\ResponseBuilder;
use Prism\Prism\Testing\StructuredStepFake;
use Tests\Fixtures\FixtureResponse;
it('returns structured output', function (): void {
FixtureResponse::fakeResponseSequence('converse', 'converse/structured');
$schema = new ObjectSchema(
'output',
'the output object',
[
new StringSchema('weather', 'The weather forecast'),
new StringSchema('game_time', 'The tigers game time'),
new BooleanSchema('coat_required', 'whether a coat is required'),
],
['weather', 'game_time', 'coat_required']
);
$response = Prism::structured()
->withSchema($schema)
->using('bedrock', 'anthropic.claude-3-5-haiku-20241022-v1:0')
->withProviderOptions(['apiSchema' => BedrockSchema::Converse])
->withSystemPrompt('The tigers game is at 3pm and the temperature will be 70º')
->withPrompt('What time is the tigers game today and should I wear a coat?')
->asStructured();
expect($response->structured)->toBeArray();
expect($response->structured)->toHaveKeys([
'weather',
'game_time',
'coat_required',
]);
expect($response->structured['weather'])->toBeString();
expect($response->structured['game_time'])->toBeString();
expect($response->structured['coat_required'])->toBeBool();
expect($response->usage->promptTokens)->toBe(223);
expect($response->usage->completionTokens)->toBe(35);
expect($response->usage->cacheWriteInputTokens)->toBeNull();
expect($response->usage->cacheReadInputTokens)->toBeNull();
expect($response->meta->id)->toBe('');
expect($response->meta->model)->toBe('');
});
it('maps converse options when set with providerOptions', function (): void {
$fake = Prism::fake([
(new ResponseBuilder)->addStep(
StructuredStepFake::make()->withText(json_encode(['foo' => 'bar']))
)->toResponse(),
]);
$providerOptions = [
'apiSchema' => BedrockSchema::Converse,
'additionalModelRequestFields' => [
'anthropic_beta' => ['output-128k-2025-02-19'],
'thinking' => ['type' => 'enabled', 'budget_tokens' => 16000],
],
'additionalModelResponseFieldPaths' => ['foo.bar', 'baz.qux'],
'guardrailConfig' => ['rules' => ['no-violence']],
'performanceConfig' => ['timeoutMs' => 2000],
'promptVariables' => ['userName' => 'Alice'],
'requestMetadata' => ['requestId' => 'abc-123'],
];
$schema = new ObjectSchema(
'output',
'the output object',
[
new StringSchema('weather', 'The weather forecast'),
new StringSchema('game_time', 'The tigers game time'),
new BooleanSchema('coat_required', 'whether a coat is required'),
],
['weather', 'game_time', 'coat_required']
);
$response = Prism::structured()
->withSchema($schema)
->using('bedrock', 'anthropic.claude-3-5-haiku-20241022-v1:0')
->withProviderOptions($providerOptions)
->withSystemPrompt('The tigers game is at 3pm and the temperature will be 70º')
->withPrompt('What time is the tigers game today and should I wear a coat?')
->asStructured();
$fake->assertRequest(fn (array $requests): mixed => expect($requests[0]->providerOptions())->toBe($providerOptions));
});
it('does not remove 0 values from payloads', function (): void {
FixtureResponse::fakeResponseSequence('converse', 'converse/structured');
$schema = new ObjectSchema(
'output',
'the output object',
[
new StringSchema('weather', 'The weather forecast'),
new StringSchema('game_time', 'The tigers game time'),
new BooleanSchema('coat_required', 'whether a coat is required'),
],
['weather', 'game_time', 'coat_required']
);
Prism::structured()
->withSchema($schema)
->using('bedrock', 'anthropic.claude-3-5-haiku-20241022-v1:0')
->withProviderOptions([
'apiSchema' => BedrockSchema::Converse,
'guardRailConfig' => null,
])
->withMaxTokens(2048)
->usingTemperature(0)
->asStructured();
Http::assertSent(fn (Request $request): \Pest\Mixins\Expectation|\Pest\Expectation => expect($request->data())->toMatchArray([
'inferenceConfig' => [
'maxTokens' => 2048,
'temperature' => 0,
],
])->not()->toHaveKey('guardRailConfig'));
});