israrminhas/filament-aimonitor

AI API cost monitoring and key management plugin for Filament

Installs: 128

Dependents: 0

Suggesters: 0

Security: 0

Stars: 5

Watchers: 0

Forks: 2

Open Issues: 0

pkg:composer/israrminhas/filament-aimonitor

dev-main 2025-12-05 23:30 UTC

This package is auto-updated.

Last update: 2026-01-05 23:38:47 UTC


README

A Filament 4 plugin for monitoring AI API usage, costs, and managing API keys across multiple providers (OpenAI, Anthropic, Gemini, Perplexity).

Features

  • Track AI API requests with token counts and automatic cost calculation
  • Manage API keys for multiple providers with priority-based rotation
  • Configure model-specific pricing with fallback support
  • Dashboard with usage analytics and cost trends
  • Per-user spending tracking and limits
  • Multi-tenancy support (works with tenant() helper)

Requirements

  • PHP 8.2+
  • Laravel 11+
  • Filament 4.0+

Installation

composer require israrminhas/filament-aimonitor

Publish and run migrations:

php artisan vendor:publish --tag="ai-monitor-migrations"
php artisan migrate

Publish config (optional):

php artisan vendor:publish --tag="ai-monitor-config"

Register the Plugin

Add the plugin to your Filament panel in app/Providers/Filament/AdminPanelProvider.php:

use Filament\AiMonitor\AiMonitorPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            AiMonitorPlugin::make(),
        ]);
}

Helper Functions

The package provides three global helper functions:

ai_log() - Log AI Requests

// Log any AI request
ai_log([
    'provider' => 'openai',
    'model' => 'gpt-4o',
    'request_type' => 'chat',
    'prompt_tokens' => 150,
    'completion_tokens' => 50,
    'status' => 'success',
    'user_id' => auth()->id(),
]);

Cost is automatically calculated from your pricing configuration. The total_tokens and occurred_at are auto-filled if not provided.

ai_key() - Get API Key

// Get the highest priority active API key for a provider
$apiKey = ai_key('openai');
$apiKey = ai_key('anthropic');
$apiKey = ai_key('gemini');

ai_cost() - Calculate Cost

// Calculate cost for tokens without logging
$cost = ai_cost('openai', 'gpt-4o', 1000, 500);
// Returns cost in USD based on your pricing config

Using the Services

AiUsageLogger

use Filament\AiMonitor\Services\AiUsageLogger;

$logger = app(AiUsageLogger::class);

// Generic log
$logger->log([
    'provider' => 'openai',
    'model' => 'gpt-4o',
    'prompt_tokens' => 100,
    'completion_tokens' => 50,
    'status' => 'success',
    'user_id' => auth()->id(),
    'meta' => ['conversation_id' => 123],
]);

// Provider-specific shortcuts
$logger->logOpenAi([...]);
$logger->logAnthropic([...]);
$logger->logGemini([...]);
$logger->logPerplexity([...]);

AiKeyManager

use Filament\AiMonitor\Services\AiKeyManager;

$keyManager = app(AiKeyManager::class);

// Get single key (highest priority)
$key = $keyManager->getKey('openai');

// Get all active keys for a provider
$keys = $keyManager->getAllKeys('openai');

// Check if provider has any active keys
if ($keyManager->hasProvider('anthropic')) {
    // ...
}

AiPricingService

use Filament\AiMonitor\Services\AiPricingService;

$pricing = app(AiPricingService::class);

// Get pricing for a model
$rates = $pricing->getPricing('openai', 'gpt-4o');
// Returns: ['input_per_1k' => 0.005, 'output_per_1k' => 0.015]

// Check if pricing exists
if ($pricing->hasPricing('anthropic', 'claude-3-opus')) {
    // ...
}

// Calculate cost
$cost = $pricing->calculateCost('openai', 'gpt-4o', 1000, 500);

// Get all configured providers
$providers = $pricing->getProviders();

// Get models for a provider
$models = $pricing->getModelsForProvider('openai');

AiUsageLimitService

use Filament\AiMonitor\Services\AiUsageLimitService;

$limitService = app(AiUsageLimitService::class);

// Get user's monthly spend
$spent = $limitService->getUserMonthlySpend($userId);

// Get full limit status
$status = $limitService->getUserLimitStatus($user);
// Returns:
// [
//     'limit' => 100.00,
//     'spent' => 45.50,
//     'remaining' => 54.50,
//     'percent_used' => 45.5,
//     'state' => 'ok', // 'ok', 'warning', 'over', 'no-limit'
// ]

Usage Examples

OpenAI Integration

use OpenAI\Laravel\Facades\OpenAI;

$response = OpenAI::chat()->create([
    'model' => 'gpt-4o',
    'messages' => [
        ['role' => 'user', 'content' => 'Hello!'],
    ],
]);

// Log the request
ai_log([
    'provider' => 'openai',
    'model' => $response->model,
    'request_type' => 'chat',
    'prompt_tokens' => $response->usage->promptTokens,
    'completion_tokens' => $response->usage->completionTokens,
    'status' => 'success',
    'user_id' => auth()->id(),
]);

Anthropic Integration

$response = Http::withHeaders([
    'x-api-key' => ai_key('anthropic'),
    'anthropic-version' => '2023-06-01',
])->post('https://api.anthropic.com/v1/messages', [
    'model' => 'claude-3-5-sonnet-20241022',
    'max_tokens' => 1024,
    'messages' => [['role' => 'user', 'content' => 'Hello!']],
]);

$data = $response->json();

ai_log([
    'provider' => 'anthropic',
    'model' => $data['model'],
    'request_type' => 'chat',
    'prompt_tokens' => $data['usage']['input_tokens'],
    'completion_tokens' => $data['usage']['output_tokens'],
    'status' => $response->successful() ? 'success' : 'failed',
    'user_id' => auth()->id(),
]);

With Error Handling

try {
    $response = OpenAI::chat()->create([...]);

    ai_log([
        'provider' => 'openai',
        'model' => 'gpt-4o',
        'prompt_tokens' => $response->usage->promptTokens,
        'completion_tokens' => $response->usage->completionTokens,
        'status' => 'success',
        'user_id' => auth()->id(),
    ]);
} catch (\Exception $e) {
    ai_log([
        'provider' => 'openai',
        'model' => 'gpt-4o',
        'prompt_tokens' => 0,
        'completion_tokens' => 0,
        'status' => 'failed',
        'user_id' => auth()->id(),
        'meta' => ['error' => $e->getMessage()],
    ]);
}

User Spending Limits

Add Columns to Users Table

php artisan make:migration add_ai_limits_to_users_table
Schema::table('users', function (Blueprint $table) {
    $table->decimal('ai_monthly_limit_usd', 10, 4)->nullable();
    $table->integer('ai_alert_threshold_percent')->default(80);
});

Check Limits Before AI Calls

use Filament\AiMonitor\Services\AiUsageLimitService;

$limitService = app(AiUsageLimitService::class);
$status = $limitService->getUserLimitStatus(auth()->user());

if ($status['state'] === 'over') {
    throw new \Exception('Monthly AI spending limit reached.');
}

if ($status['state'] === 'warning') {
    // Notify user they're approaching limit
}

Multi-Tenancy Support

The package automatically scopes data to the current tenant when tenant() helper is available (e.g., with Filament multi-tenancy or Stancl/Tenancy).

Configuration

// config/ai-monitor.php
return [
    'tenant_support' => true, // Enable/disable tenant scoping
];

How It Works

  • All models use the IsTenantScoped trait
  • When tenant() returns a tenant, tenant_id is automatically set on create
  • Queries are automatically scoped to the current tenant

Dashboard Widgets

The plugin includes these dashboard widgets:

Widget Description
Stats Overview Total requests, tokens, cost, success rate
Cost & Request Trends 30-day line chart
Cost by Provider Doughnut chart breakdown
Top Models by Cost Table of most expensive models
Usage by User Table of user spending
Recent Requests Latest API calls with details

License

MIT License. See LICENSE for details.