adachsoft / ai-integration
Unified AI tool-calling chat abstraction for PHP 8.3 with pluggable SPI providers (OpenAI, Deepseek) and a clean Public API.
Installs: 16
Dependents: 2
Suggesters: 0
Security: 0
Stars: 0
Forks: 0
pkg:composer/adachsoft/ai-integration
Requires
- php: ^8.3
- adachsoft/collection: ^3.0
- adachsoft/console-io: ^0.1.0
- guzzlehttp/guzzle: ^7.9
- vlucas/phpdotenv: ^5.6
Requires (Dev)
- adachsoft/php-code-style: ^0.2.1
- friendsofphp/php-cs-fixer: ^3.89
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^12.4
This package is not auto-updated.
Last update: 2026-01-10 12:06:27 UTC
README
Unified AI tool-calling chat abstraction for PHP 8.3 with pluggable providers and a clean, framework-agnostic Public API.
- Public API: simple facade to send chat messages, define tools (function-calling), and receive results.
- Built-in providers: OpenAI and Deepseek.
- SPI: implement your own provider by fulfilling a tiny interface and DTO set.
- HTTP logging: optional, via a small logger interface.
- Zero-framework: no container required; everything is manually wired with a builder.
Requirements
- PHP 8.3+
- ext-json, ext-mbstring (standard in most PHP installations)
Installation
composer require adachsoft/ai-integration
Quick start (Public API)
use AdachSoft\AiIntegration\PublicApi\Builder\ToolCallingChatFacadeBuilder;
use AdachSoft\AiIntegration\PublicApi\ToolCalling\Dto\ChatMessageDto;
use AdachSoft\AiIntegration\PublicApi\ToolCalling\Dto\ChatRoleEnum;
use AdachSoft\AiIntegration\PublicApi\ToolCalling\Dto\Collection\ChatMessageDtoCollection;
use AdachSoft\AiIntegration\PublicApi\ToolCalling\Dto\Collection\ToolDefinitionDtoCollection;
use AdachSoft\AiIntegration\PublicApi\ToolCalling\Dto\ToolCallingChatRequestDto;
use AdachSoft\AiIntegration\PublicApi\ToolCalling\Dto\ToolDefinitionDto;
$builder = ToolCallingChatFacadeBuilder::create()
->withOpenAi(apiKey: getenv('OPENAI_API_KEY'));
$messages = new ChatMessageDtoCollection([
ChatMessageDto::createSystemMessage('You are a helpful assistant.'),
ChatMessageDto::createUserMessage('Add 2 and 3 using a tool and show the token.'),
]);
$tools = new ToolDefinitionDtoCollection([
new ToolDefinitionDto(
name: 'sum',
description: 'Returns JSON {result: string, token: string}',
parametersSchema: [
'type' => 'object',
'properties' => [
'a' => ['type' => 'number'],
'b' => ['type' => 'number'],
],
'required' => ['a', 'b'],
'additionalProperties' => false,
],
),
]);
$request = new ToolCallingChatRequestDto(
messages: $messages,
tools: $tools,
providerId: 'openai',
modelId: 'gpt-4o-mini',
parameters: [
// Free-form provider parameters.
// They are forwarded 1:1 to the provider payload (no defaults are injected).
// Example (only if your model supports it):
// 'temperature' => 0.0,
],
);
$facade = $builder->build();
$response = $facade->chat($request);
if ($response->result !== null) {
echo $response->result; // final model answer (should include tool token if your prompt enforces it)
}
foreach ($response->toolCalls as $call) {
// inspect tool calls if needed
}
Chat messages and tool calls (Public API)
ChatMessageDto is the main DTO used to build a conversation:
public function __construct(
public ChatRoleEnum $role,
public string $content,
public ToolCallDtoCollection $toolCalls,
public array $metadata = [],
) { }
To make common cases easier and to guarantee that toolCalls is never null, use the static factories:
ChatMessageDto::createSystemMessage(string $content, array $metadata = []): self;
ChatMessageDto::createUserMessage(string $content, array $metadata = []): self;
ChatMessageDto::createAssistantMessage(string $content, ToolCallDtoCollection $toolCalls, array $metadata = []): self;
ChatMessageDto::createToolMessage(string $content, ToolCallDtoCollection $toolCalls, array $metadata = []): self;
Typical patterns:
- system/user messages: empty
ToolCallDtoCollection(created by the factory), - assistant messages: may include tool calls when the model proposes or summarizes tool usage,
- tool messages: should carry tool results and the corresponding
ToolCallDtoinstances intoolCalls.
Generation parameters (parameters)
Generation settings are a free-form associative array and are provider-specific. The library forwards them 1:1 to the provider payload.
Important:
- Do not rely on implicit defaults (e.g.
temperature). If you do not pass a key, it is not sent. - Passing unsupported parameters may result in a provider error.
Providers
- OpenAI (provider id:
openai)- Endpoint: https://api.openai.com/v1/chat/completions
- Env:
OPENAI_API_KEY
- Deepseek (provider id:
deepseek)- Endpoint: https://api.deepseek.com/chat/completions
- Env:
DEEPSEEK_API_KEY
If you pass modelId as null, each provider uses its default. For OpenAI, a safe starter is gpt-4o-mini; for Deepseek: deepseek-chat.
HTTP logging and CLI example
You can inject your own HTTP traffic logger via the builder. A convenient demonstration script is included:
php bin/test-ai-tool-chat.php --provider=openai --model=gpt-4o-mini --show-meta=on --log-http=1 --log-headers=0
The script runs 3 scenarios (smoke and two tool-calling flows) and optionally pretty-prints HTTP request/response payloads.
SPI (Service Provider Interface)
Do not depend on internals. External integrations should use only:
AdachSoft\AiIntegration\PublicApi- the facade and DTOs to call the model.AdachSoft\AiIntegration\Spi- the small interface and DTOs to implement your own provider.
All other namespaces (Application, Domain, Infrastructure) are internal and may change at any time.
For a complete SPI guide (interface, DTOs, exceptions, examples), see:
- docs/SPI.md
Testing
- Run unit and integration tests:
composer test - Production checks (require API keys): see
tests/Productionandbin/test-ai-tool-chat.php.