Track and control LLM spend from one PHP API. Call OpenAI, Anthropic, Google Gemini, Mistral, DeepSeek, Qwen, Kimi, GLM, Grok and any OpenAI-compatible endpoint, with automatic cost and usage tracking baked in.
use LlmCostTracker\Client\Llm;
$llm = Llm::fromYaml('llm.yaml');
$result = $llm->chat('deepseek-chat', 'Explain quantum computing in one sentence.');
echo $result->text(); // the answer
echo $result->usage->totalTokens; // 42
echo $result->usage->reasoningTokens; // hidden thinking tokens, exposed
echo $result->cost->total; // 0.000123 USDEvery call is recorded and shown in a dashboard: cost per model, provider and day, plus thinking tokens and response previews.
composer require boriskwemo/llm-ledgerRequires PHP 8.2+ with ext-json and ext-pdo.
Create llm.yaml:
providers:
openai: { api_key: env(OPENAI_API_KEY) }
deepseek: { api_key: env(DEEPSEEK_API_KEY) }
# ...anthropic, google, mistral, qwen, xai and more
tracking:
enabled: true
storage: sqlite://llm.dbThat's it. Drop in your keys and go.
- One API for 19 providers - OpenAI, Anthropic, Google, xAI, Mistral, DeepSeek, Qwen, Kimi, GLM and any OpenAI-compatible server (vLLM, LiteLLM, local).
- Costs you can't miss - reasoning tokens, cached input and per-call USD are normalized and stored, not just the end-of-month bill.
- Built-in dashboard + CLI - a themed admin UI (light/dark, fully responsive) plus
llm-trackerfor the terminal. - Deprecation-aware model registry - a YAML catalog marks retired models and their replacements before they break you.
- Batch processing - one
batch()call across OpenAI, Anthropic and Gemini. - Symfony 8 + Laravel - an idiomatic bundle and service provider, not a raw HTTP client.
- Secure by default - API keys live in memory only; never persisted or logged.
require 'vendor/autoload.php';
use LlmCostTracker\Client\Llm;
$llm = Llm::fromYaml('llm.yaml');
$result = $llm->chat('gpt-5.2', 'Hello!', ['tags' => ['demo']]);
echo $result->text();
printf("cost: $%.6f\n", $result->cost->total);
$totals = $llm->tracker()->totals(); // lifetime aggregates// config/bundles.php
LlmCostTracker\Symfony\LlmCostTrackerBundle::class => ['all' => true],# config/routes/llm_cost_tracker.yaml
llm_cost_tracker:
resource: '@LlmCostTrackerBundle/Resources/config/routes.yaml'
prefix: /llmpublic function __construct(private \LlmCostTracker\Client\Llm $llm) {}
$answer = $this->llm->complete('mistral-large-latest', 'Hello!');Dashboard at /llm, model catalog at /llm/models.
php artisan vendor:publish --provider="LlmCostTracker\Laravel\LlmCostTrackerServiceProvider"
php artisan migrateuse Llm;
$answer = Llm::complete('qwen3-max', 'Hello!');Dashboard at /llm.
vendor/bin/llm-tracker models:list
vendor/bin/llm-tracker usage:report --days=30
vendor/bin/llm-tracker call deepseek-chat "Hello!"- Model registry:
config/models.yaml. Pricing is a bundled snapshot; override it in your own YAML. - Standalone dashboard:
examples/dashboard.php(no framework required).
MIT. See LICENSE. Contributions welcome - CONTRIBUTING.md; report vulnerabilities per SECURITY.md.