155 lines
4.4 KiB
PHP
155 lines
4.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace ContextPaging\Tests;
|
|
|
|
use ContextPaging\ToolCallParser;
|
|
use ContextPaging\ToolCallMode;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class ToolCallParserTest extends TestCase
|
|
{
|
|
/**
|
|
* Test extracting native OpenAI-style tool calls.
|
|
*/
|
|
public function testExtractNativeToolCalls(): void
|
|
{
|
|
$parser = new ToolCallParser(ToolCallMode::NATIVE);
|
|
|
|
$response = [
|
|
"choices" => [
|
|
[
|
|
"message" => [
|
|
"role" => "assistant",
|
|
"content" => null,
|
|
"tool_calls" => [
|
|
[
|
|
"id" => "call_123",
|
|
"function" => [
|
|
"name" => "fetch_message",
|
|
"arguments" => "{\"md5\":\"abc123\"}",
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$toolCalls = $parser->extract($response);
|
|
|
|
$this->assertNotNull($toolCalls);
|
|
$this->assertCount(1, $toolCalls);
|
|
$this->assertEquals("fetch_message", $toolCalls[0]["name"]);
|
|
$this->assertEquals(["md5" => "abc123"], $toolCalls[0]["arguments"]);
|
|
}
|
|
|
|
/**
|
|
* Test extracting raw tool calls from content.
|
|
*/
|
|
public function testExtractRawToolCalls(): void
|
|
{
|
|
$parser = new ToolCallParser(ToolCallMode::RAW);
|
|
|
|
// The actual content from SmolLM3 response
|
|
$rawContent = chr(0xD9) . chr(0xA7) . "{\"name\": \"web_search\", \"arguments\": {\"query\": \"nvidia stock\"}}" . chr(0xD9) . chr(0xA7);
|
|
|
|
$response = [
|
|
"choices" => [
|
|
[
|
|
"message" => [
|
|
"role" => "assistant",
|
|
"content" => $rawContent,
|
|
"tool_calls" => [],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$toolCalls = $parser->extract($response);
|
|
|
|
$this->assertNotNull($toolCalls);
|
|
$this->assertGreaterThanOrEqual(1, count($toolCalls));
|
|
$this->assertEquals("web_search", $toolCalls[0]["name"]);
|
|
}
|
|
|
|
/**
|
|
* Test auto-detect mode picks native tool calls.
|
|
*/
|
|
public function testAutoDetectNative(): void
|
|
{
|
|
$parser = new ToolCallParser(ToolCallMode::AUTO);
|
|
|
|
$response = [
|
|
"choices" => [
|
|
[
|
|
"message" => [
|
|
"role" => "assistant",
|
|
"content" => null,
|
|
"tool_calls" => [
|
|
[
|
|
"id" => "call_456",
|
|
"function" => [
|
|
"name" => "fetch_message",
|
|
"arguments" => "{\"md5\":\"def456\"}",
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$detectedMode = $parser->detectMode($response);
|
|
$this->assertEquals(ToolCallMode::NATIVE, $detectedMode);
|
|
|
|
$toolCalls = $parser->extract($response);
|
|
$this->assertNotNull($toolCalls);
|
|
}
|
|
|
|
/**
|
|
* Test no tool calls returns null.
|
|
*/
|
|
public function testNoToolCalls(): void
|
|
{
|
|
$parser = new ToolCallParser(ToolCallMode::AUTO);
|
|
|
|
$response = [
|
|
"choices" => [
|
|
[
|
|
"message" => [
|
|
"role" => "assistant",
|
|
"content" => "Hello! How can I help you?",
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$toolCalls = $parser->extract($response);
|
|
$this->assertNull($toolCalls);
|
|
}
|
|
|
|
/**
|
|
* Test hasToolCalls helper.
|
|
*/
|
|
public function testHasToolCalls(): void
|
|
{
|
|
$parser = new ToolCallParser(ToolCallMode::NATIVE);
|
|
|
|
$withTools = [
|
|
"choices" => [
|
|
["message" => ["tool_calls" => [["function" => ["name" => "test"]]]]],
|
|
],
|
|
];
|
|
|
|
$withoutTools = [
|
|
"choices" => [
|
|
["message" => ["content" => "Hello"]],
|
|
],
|
|
];
|
|
|
|
$this->assertTrue($parser->hasToolCalls($withTools));
|
|
$this->assertFalse($parser->hasToolCalls($withoutTools));
|
|
}
|
|
} |