1tomany/llm-sdk
Laravel-friendly PHP SDK for working with LLM providers. Provides a clean client API, request/response handling, and configurable drivers so you can send prompts, manage completions, and integrate AI features into your app with minimal boilerplate.
Installation:
composer require 1tomany/llm-sdk
For Laravel, consider using the Symfony bundle for autowiring and configuration.
First Use Case: Generate a simple LLM response using OpenAI:
use OneToMany\LlmSdk\Clients\OpenAI\Client;
use OneToMany\LlmSdk\Requests\GenerateOutputRequest;
$client = new Client('your-api-key');
$request = new GenerateOutputRequest(
model: 'gpt-4',
prompt: 'Hello, world!'
);
$response = $client->generateOutput($request);
echo $response->getResponse();
Key Files to Review:
examples/outputs/generate.php for basic usage.src/Clients for platform-specific clients.src/Requests for request classes.$client = new Client('api-key');
$request = new GenerateOutputRequest(model: 'gpt-4', prompt: 'Explain Laravel');
$response = $client->generateOutput($request);
ClientFactory and inject actions into services.// Register clients (e.g., in a service provider)
$factory = new ClientFactory();
$factory->register('openai', new OpenAI\Client('api-key'));
// Inject into a service
$service = new MyService($factory);
// Use actions
$action = $factory->getAction('openai', 'generate-output');
$response = $action->execute($request);
$query = new Query();
$query->addPrompt('Explain Laravel');
$query->addSystemInstruction('Be concise.');
$compiled = $client->compileQuery($query);
$response = $client->processQuery($compiled);
$fileRequest = new FileRequest(
file: fopen('document.pdf', 'r'),
purpose: 'assistants'
);
$client->uploadFile($fileRequest);
$embeddingRequest = new CreateEmbeddingRequest(
model: 'text-embedding-ada-002',
input: 'Laravel is a PHP framework.'
);
$response = $client->createEmbedding($embeddingRequest);
$store = $client->createSearchStore('my-store', 'gemini-1.5-pro');
$results = $client->searchStore($store->getId(), 'Explain Laravel');
ClientFactory to the container for easy access.
$this->app->singleton(ClientFactory::class, function ($app) {
$factory = new ClientFactory();
$factory->register('openai', new OpenAI\Client(config('services.openai.key')));
return $factory;
});
// config/services.php
'openai' => [
'key' => env('OPENAI_KEY'),
],
use OneToMany\LlmSdk\Actions\GenerateOutputAction;
class GenerateContentJob implements ShouldQueue
{
public function handle(ClientFactory $factory) {
$action = $factory->getAction('openai', 'generate-output');
$response = $action->execute(new GenerateOutputRequest(...));
}
}
Mock client for unit tests.
$mockClient = new Mock\Client();
$factory->register('mock', $mockClient);
$this->partialMock(ClientFactory::class, function ($mock) {
$mock->shouldReceive('getAction')
->with('openai', 'generate-output')
->andReturn(new MockGenerateOutputAction());
});
OneToMany\LlmSdk\Exceptions\LlmSdkException for generic errors.OpenAI\Exceptions\RateLimitException).
try {
$response = $client->generateOutput($request);
} catch (RateLimitException $e) {
// Retry or notify user
}
Platform Feature Gaps:
Mock client for unsupported features during prototyping.File Handling Limitations:
Query Compilation Overhead:
generateOutput) for straightforward requests.Rate Limiting:
use Symfony\Component\Retry\Retry;
$retry = Retry::create(3, function ($attempt) {
return $attempt > 1 ? 2 ** $attempt * 100 : 0;
});
Model Availability:
gpt-5.4) may not be available to all users.if (!$client->supportsModel('gpt-5.4')) {
throw new \RuntimeException('Model not available');
}
Hash Collisions:
sha256.Log Requests/Responses:
Client constructor:
$client = new Client('api-key', [
'logger' => new \Monolog\Logger('llm'),
]);
$compiled = $client->compileQuery($query);
\Log::debug('Query hash:', [$compiled->getHash(), $compiled->toArray()]);
Validate API Keys:
Mock client first to rule out key issues:
$mockClient = new Mock\Client();
$mockClient->setMockResponse(['choices' => [['text' => 'Mock response']]]);
Check Response Types:
$response = $client->generateOutput($request);
if ($response instanceof GenerateOutputResponse) {
$output = $response->getResponse(); // string or array
}
Batch Processing:
readBatch to track status:
$batch = $client->createBatch([$request1, $request2]);
$status = $client->readBatch($batch->getId());
OneToMany\LlmSdk\Clients\BaseClient for unsupported platforms.class CustomClient extends BaseClient {
public function generateOutput(GenerateOutputRequest $request) {
How can I help you explore Laravel packages today?