Skip to content

Commit 8157e7d

Browse files
authored
fix: flaky anthropic tool calls with empty text (#315)
Fixes #313
1 parent 496d887 commit 8157e7d

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

src/Bridge/Anthropic/ModelHandler.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,17 @@ public function convert(ResponseInterface $response, array $options = []): LlmRe
121121
throw new RuntimeException('Response does not contain any content');
122122
}
123123

124-
if (!isset($data['content'][0]['text'])) {
125-
throw new RuntimeException('Response content does not contain any text');
126-
}
127-
128124
$toolCalls = [];
129125
foreach ($data['content'] as $content) {
130126
if ('tool_use' === $content['type']) {
131127
$toolCalls[] = new ToolCall($content['id'], $content['name'], $content['input']);
132128
}
133129
}
130+
131+
if (!isset($data['content'][0]['text']) && 0 === count($toolCalls)) {
132+
throw new RuntimeException('Response content does not contain any text nor tool calls.');
133+
}
134+
134135
if (!empty($toolCalls)) {
135136
return new ToolCallResponse(...$toolCalls);
136137
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpLlm\LlmChain\Tests\Bridge\Anthropic;
6+
7+
use PhpLlm\LlmChain\Bridge\Anthropic\ModelHandler;
8+
use PhpLlm\LlmChain\Model\Response\ToolCallResponse;
9+
use PHPUnit\Framework\Attributes\CoversClass;
10+
use PHPUnit\Framework\TestCase;
11+
use Symfony\Component\HttpClient\MockHttpClient;
12+
use Symfony\Component\HttpClient\Response\JsonMockResponse;
13+
14+
#[CoversClass(ModelHandler::class)]
15+
final class ModelHandlerTest extends TestCase
16+
{
17+
public function testConvertThrowsExceptionWhenContentIsToolUseAndLacksText(): void
18+
{
19+
$httpClient = new MockHttpClient(new JsonMockResponse([
20+
'content' => [
21+
[
22+
'type' => 'tool_use',
23+
'id' => 'toolu_01UM4PcTjC1UDiorSXVHSVFM',
24+
'name' => 'xxx_tool',
25+
'input' => ['action' => 'get_data'],
26+
],
27+
],
28+
]));
29+
$httpResponse = $httpClient->request('POST', 'https://api.anthropic.com/v1/messages');
30+
$handler = new ModelHandler($httpClient, 'test-api-key');
31+
32+
$response = $handler->convert($httpResponse);
33+
self::assertInstanceOf(ToolCallResponse::class, $response);
34+
self::assertCount(1, $response->getContent());
35+
self::assertSame('toolu_01UM4PcTjC1UDiorSXVHSVFM', $response->getContent()[0]->id);
36+
self::assertSame('xxx_tool', $response->getContent()[0]->name);
37+
self::assertSame(['action' => 'get_data'], $response->getContent()[0]->arguments);
38+
}
39+
}

0 commit comments

Comments
 (0)