1. Go to this page and download the library: Download bycerfrance/llm-api-lib library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
bycerfrance / llm-api-lib example snippets
use ByCerfrance\LlmApiLib\Provider\Generic;
$provider = new Generic(
uri: 'https://my-local-server.com/v1/chat/completions',
apiKey: 'my-api-key',
model: 'my-model',
client: $httpClient, // PSR-18 ClientInterface
);
use ByCerfrance\LlmApiLib\Model\ModelInfo;
use ByCerfrance\LlmApiLib\Model\QualityTier;
use ByCerfrance\LlmApiLib\Model\CostTier;
use ByCerfrance\LlmApiLib\Model\Capability;
use ByCerfrance\LlmApiLib\Provider\OpenAi;
$model = new ModelInfo(
name: 'gpt-4o',
capabilities: [Capability::TEXT, Capability::IMAGE, Capability::TOOLS, Capability::JSON_OUTPUT],
qualityTier: QualityTier::PREMIUM,
costTier: CostTier::HIGH,
inputCost: 2.50, // $ per million tokens
outputCost: 10.00, // $ per million tokens
maxContextTokens: 128_000,
maxOutputTokens: 16_384,
);
$provider = new OpenAi(
apiKey: 'sk-...',
model: $model, // ModelInfo or plain string
client: $httpClient,
);
use ByCerfrance\LlmApiLib\Model\ModelInfo;
$gpt5 = new ModelInfo(name: 'gpt-5', tunable: false);
$opus47 = new ModelInfo(name: 'claude-opus-4-7', tunable: false);
$o3 = new ModelInfo(name: 'o3-mini', tunable: false);
$custom = new ModelInfo(
name: 'my-endpoint',
stripFields: ['service_tier', 'response_format.strict'],
);
// Combine both: a non-tunable reasoning model with an extra restriction
$gpt5Azure = new ModelInfo(
name: 'gpt-5',
tunable: false,
stripFields: ['service_tier'],
);
use ByCerfrance\LlmApiLib\Completion\Completion;
use ByCerfrance\LlmApiLib\Completion\Message\SystemMessage;
use ByCerfrance\LlmApiLib\Llm;
$completion = new Completion(new SystemMessage(
'Tu es un assistant comptable, presentes toi comme tel.',
));
$llm = new Llm($provider);
$completion = $llm->chat($completion->withNewMessage('Salut !'));
print $completion->getLastMessage()->getContent();
// "Bonjour, je suis votre assistant comptable. Comment puis-je vous aider ?"
use ByCerfrance\LlmApiLib\Completion\Message\SystemMessage;
use ByCerfrance\LlmApiLib\Completion\Message\UserMessage;
use ByCerfrance\LlmApiLib\Completion\Message\Message;
use ByCerfrance\LlmApiLib\Completion\Message\RoleEnum;
// Typed classes (recommended)
$system = new SystemMessage('You are a helpful assistant.');
$user = new UserMessage('Hello!');
// Or using the generic Message class with explicit role
$system = new Message('You are a helpful assistant.', role: RoleEnum::SYSTEM);
use ByCerfrance\LlmApiLib\Completion\Completion;
$completion = (new Completion(['Explain quantum computing']))
->withModel('gpt-4o') // Override the provider's default model
->withMaxTokens(2000) // Maximum tokens in the response
->withTemperature(0.7) // Creativity (0 = deterministic, 2 = very creative)
->withTopP(0.9) // Nucleus sampling
->withSeed(42); // Reproducible outputs (provider-dependent)
use ByCerfrance\LlmApiLib\Completion\Completion;
use ByCerfrance\LlmApiLib\Completion\ServiceTier;
$completion = (new Completion(['Summarize this report']))
->withServiceTier(ServiceTier::FLEX);
use ByCerfrance\LlmApiLib\Completion\Completion;
use ByCerfrance\LlmApiLib\Completion\ReasoningEffort;
$completion = (new Completion(['Solve this math problem step by step']))
->withReasoningEffort(ReasoningEffort::HIGH);
$content = new ArrayContent(
new TextContent('First message'),
'Second message'
);
$content = new DocumentUrlContent('https://example.com/document.pdf');
$content = new InputAudioContent('base64encodeddata', 'wav');
$text = new TextContent('Hello, world!');
$json = new JsonContent(['key' => 'value']);
$content = new TextContent('Hello {name}, you are {age} years old.', ['name' => 'John', 'age' => 30]);
echo $content; // Outputs: "Hello John, you are 30 years old."
use ByCerfrance\LlmApiLib\Completion\ResponseFormat\TextFormat;
$completion = (new Completion(['Explain gravity']))
->withResponseFormat(new TextFormat());
use ByCerfrance\LlmApiLib\Completion\ResponseFormat\JsonObjectFormat;
$completion = (new Completion(['List 3 colors as a JSON array']))
->withResponseFormat(new JsonObjectFormat());
$response = $llm->chat($completion);
$data = json_decode($response->getLastMessage()->getContent(), true);
use ByCerfrance\LlmApiLib\Completion\Tool\Tool;
$weatherTool = new Tool(
name: 'get_weather',
description: 'Get the current weather for a location',
parameters: [
'type' => 'object',
'properties' => [
'location' => [
'type' => 'string',
'description' => 'The city name',
],
],
'
use ByCerfrance\LlmApiLib\Completion\Completion;
use ByCerfrance\LlmApiLib\Llm;
$completion = (new Completion(['Quel temps fait-il a Paris ?']))
->withTools($weatherTool)
->withMaxToolIterations(5); // Optional, default is 10
$llm = new Llm($provider);
$response = $llm->chat($completion);
print $response->getLastMessage()->getContent();
// "Il fait actuellement 20°C a Paris avec un temps ensoleille."
use ByCerfrance\LlmApiLib\Completion\Tool\ToolCollection;
$completion = (new Completion(['...']))
->withTools($weatherTool, $calculatorTool, $searchTool);
// Or using a collection
$tools = new ToolCollection($weatherTool, $calculatorTool);
$completion = (new Completion(['...']))->withTools($tools);
use ByCerfrance\LlmApiLib\Completion\Tool\FilteredToolCollection;
// Only expose specific tools
$filtered = new FilteredToolCollection($toolCollection, ['get_weather', 'search']);
// Exclude specific tools (expose everything else)
$filtered = new FilteredToolCollection($toolCollection, ['!delete_user', '!drop_table']);
use ByCerfrance\LlmApiLib\Completion\Completion;
use ByCerfrance\LlmApiLib\Completion\ToolChoice;
$completion = (new Completion(['What is the weather in Paris?']))
->withTools($weatherTool)
->withToolChoice(ToolChoice::REQUIRED);
$completion = (new Completion(['...']))
->withTools($weatherTool, $calculatorTool)
->withParallelToolCalls(false); // Force sequential tool calls
use ByCerfrance\LlmApiLib\Mcp\McpServer;
use ByCerfrance\LlmApiLib\Mcp\Transport\HttpStreamable;
// Create transport
$transport = new HttpStreamable(
uri: 'https://my-mcp-server.com/mcp',
client: $httpClient,
headers: ['Authorization' => 'Bearer my-token'],
);
// Create MCP server client
$mcp = new McpServer($transport);
// Use MCP tools in a completion (tools are discovered automatically via lazy initialization)
$completion = (new Completion(['Search for documents about PHP']))
->withTools($mcp);
$response = $llm->chat($completion);
use ByCerfrance\LlmApiLib\Mcp\OpenApi;
use cebe\openapi\Reader;
$spec = Reader::readFromJsonFile('/path/to/openapi.json');
$openApi = new OpenApi(
spec: $spec,
client: $httpClient,
headers: ['Authorization' => 'Bearer api-token'],
baseUrl: 'https://api.example.com', // Optional, overrides spec servers
);
// Use OpenAPI operations as tools
$completion = (new Completion(['List all users']))
->withTools($openApi);
// Or filter specific operations
$filtered = new FilteredToolCollection($openApi, ['listUsers', 'getUser']);
$completion = (new Completion(['List all users']))
->withTools($filtered);
$response = $llm->chat($completion);
use ByCerfrance\LlmApiLib\Completion\Tool\LlmTool;
use ByCerfrance\LlmApiLib\Completion\Completion;
$analysisTool = new LlmTool(
name: 'analyze_code',
description: 'Analyze code for security vulnerabilities',
parameters: [
'type' => 'object',
'properties' => [
'code' => ['type' => 'string', 'description' => 'The code to analyze'],
'language' => ['type' => 'string', 'description' => 'Programming language'],
],
'lysisTool->getLlm()->getUsage();
$subModelCost = $analysisTool->getLlm()->getCost();
use ByCerfrance\LlmApiLib\Model\SelectionStrategy;
use ByCerfrance\LlmApiLib\Completion\Completion;
$completion = (new Completion(['Complex reasoning task']))
->withSelectionStrategy(SelectionStrategy::BEST_QUALITY);
use ByCerfrance\LlmApiLib\Retry;
$retryableProvider = new Retry(
provider: $provider,
time: 5000, // Base wait time in milliseconds (default: 5000)
retry: 3, // Maximum retry attempts (default: 2)
multiplier: 2.0, // Exponential backoff multiplier (default: 1 = constant delay)
retryOnGuard: false, // Retry on GuardException (default: false)
);
// Wait times: 5s, 10s, 20s (time * multiplier^attempt)
$response = $retryableProvider->chat('Hello');
use ByCerfrance\LlmApiLib\Guard\Guard;
use ByCerfrance\LlmApiLib\Guard\GuardException;
$guarded = new Guard(
provider: $provider,
guard: function (\ByCerfrance\LlmApiLib\Completion\CompletionResponseInterface $response): void {
$content = $response->getLastMessage()->getContent();
if (str_contains($content, 'I cannot')) {
throw new \RuntimeException('Response contains a refusal');
}
},
);
try {
$response = $guarded->chat('...');
} catch (GuardException $e) {
$rejectedResponse = $e->getResponse(); // Access the rejected response
echo $e->getMessage();
}
use ByCerfrance\LlmApiLib\Guard\FinishReasonGuard;
use ByCerfrance\LlmApiLib\Completion\FinishReason;
// Default: rejects LENGTH and CONTENT_FILTER
$guarded = new FinishReasonGuard($provider);
// Custom: only reject LENGTH
$guarded = new FinishReasonGuard($provider, FinishReason::LENGTH);
use ByCerfrance\LlmApiLib\Guard\FinishReasonGuard;
use ByCerfrance\LlmApiLib\Retry;
// Retry up to 3 times if the response is truncated (LENGTH) or filtered
$robust = new Retry(
provider: new FinishReasonGuard($provider),
retry: 3,
retryOnGuard: true, // Required to retry on GuardException
);
$response = $robust->chat('...');
use ByCerfrance\LlmApiLib\Llm;
$llm = new Llm($openAiProvider, $mistralProvider, $googleProvider);
// If OpenAI fails, Mistral is tried. If Mistral fails, Google is tried.
$response = $llm->chat('Hello');
$usage = $llm->getUsage();
echo $usage->getPromptTokens(); // Total input tokens
echo $usage->getCompletionTokens(); // Total output tokens
echo $usage->getTotalTokens(); // Total tokens
$cost = $llm->getCost(); // Total cost in dollars (4 decimal precision)
$cost = $llm->getCost(precision: 6); // Higher precision
$maxTokens = $llm->getMaxContextTokens(); // e.g. 128000, or null if undefined
$maxOutput = $llm->getMaxOutputTokens(); // e.g. 16384, or null if undefined
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.