Sebelum memulai praktik, pastikan Anda telah memahami konsep dasar pada materi kelas AI Agent & PHP di infokoding.

BAB 18

Membuat Dashboard Admin AI Agent PHP

Membangun dashboard admin untuk AI Agent PHP: tampilkan statistik penggunaan, monitor jumlah request dan token API, serta kelola riwayat percakapan user.

Terakhir diperbarui:

Definisi: Apa itu Dashboard Admin AI Agent PHP?

Direct Answer:Dashboard Admin AI Agent PHP adalah antarmuka visual terpusat untuk memantau performa operasional agen kecerdasan buatan — meliputi agregasi jumlah request, total konsumsi token (prompt & completion), estimasi pengeluaran biaya API LLM, distribusi alat (tool usage frequency), serta riwayat log percakapan pengguna secara real-time.

Dalam modul belajar ai-agent-php tingkat lanjut, dashboard analitik mencegah developer dari lonjakan biaya token tak terduga (*runaway costs*) dan mempercepat identifikasi kegagalan eksekusi tool di lingkungan produksi.

TL;DR (Ringkasan Cepat)

  • Pusat Pengawasan Biaya & Kualitas: Dashboard admin membantu Anda memantau biaya pengeluaran API, latensi respons, dan tingkat keberhasilan (*success rate*) AI Agent.
  • Pencatatan Granular: Catat setiap sesi interaksi (prompt tokens, completion tokens, duration ms, tools used) ke database MySQL.
  • Early Warning System: Pasang notifikasi otomatis Webhook ke Slack/Discord saat penggunaan token harian melampaui batas anggaran (*budget threshold*).
  • Isolasi Hak Akses Admin: Pastikan endpoint dashboard diproteksi middleware otentikasi role admin.
Diagram Antarmuka: PHP AI Agent Monitoring Dashboard & Analytics UI
WebP Lossless • 90 KB • Schema Ready
Diagram visual dashboard admin AI Agent PHP: metrik utama total request, token used, estimasi biaya API, grafik tren penggunaan harian, distribusi pemanggilan tools, feed log percakapan real-time, dan tabel perbandingan harga model LLM
Gambar 18.1: Antarmuka Dashboard Admin AI Agent — Visualisasi komprehensif metrik performa token, distribusi eksekusi modul alat, dan audit log sesi percakapan.
Live Preview: Interaktif Chart.js AI Agent Monitoring Dashboard
Live Stream Active
Total Requests142,500 +14.2%
Tokens Used89.4MPrompt + Completion
Avg Latency412 ms Optimal
Est. Cost$14.82MTD August
Tren Pemakaian Harian (Request & Token Usage)Aug 15 - Aug 22
Live Agent Request Stream
[17:54]GPT-4o miniQuery: 'Hitung kurs USD-IDR'
200 OK
[17:52]GPT-4oQuery: 'Analisis tabel user SQL'
200 OK
[17:50]GPT-4o miniRate limit exceeded 20/min
429 Limit

Struktur Tabel Usage Statistics AI Agent

Direct Answer:Tabel agent_usage_logs adalah skema relasional teroptimasi indeks untuk mencatat metadata pemanggilan model AI (prompt tokens, completion tokens, duration ms, tools JSON) guna menghasilkan metrik performa real-time tanpa membebani throughput backend.

Tabel agent_usage_logs dirancang untuk menyimpan metadata setiap request agen secara granular guna kebutuhan kalkulasi analitik dan audit forensik:

CREATE TABLE agent_usage_logs (
    id                BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id           BIGINT UNSIGNED NULL,
    session_id        VARCHAR(128) NOT NULL,
    task              TEXT NOT NULL,
    tools_used        JSON NULL,
    prompt_tokens     INT UNSIGNED DEFAULT 0,
    completion_tokens INT UNSIGNED DEFAULT 0,
    total_tokens      INT UNSIGNED DEFAULT 0,
    duration_ms       INT UNSIGNED DEFAULT 0,
    is_success        TINYINT(1) DEFAULT 1,
    error_message     TEXT NULL,
    created_at        DATETIME DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user_id (user_id),
    INDEX idx_created_at (created_at),
    INDEX idx_session (session_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Panduan Belajar AI-Agent-PHP: Query Agregasi Metrik Dashboard

Direct Answer:Agregasi metrik performa AI Agent dilakukan melalui query agregat SQL (COUNT, SUM, AVG, dan JSON_EXTRACT) yang dibungkus dalam class DashboardService untuk menyediakan data metrik 30 hari dan grafik tren harian.

Class DashboardService merangkum kueri agregasi performa 30 hari terakhir, tren pemakaian harian, serta frekuensi pemanggilan tool terpopuler:

<?php

namespace App\Admin;

use PDO;

class DashboardService
{
    private PDO $pdo;

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    /**
     * Mengambil ringkasan metrik global 30 hari terakhir.
     */
    public function getSummary(): array
    {
        $stmt = $this->pdo->query(
            'SELECT
                COUNT(*)                                AS total_requests,
                COALESCE(SUM(total_tokens), 0)          AS total_tokens_used,
                COALESCE(AVG(total_tokens), 0)          AS avg_tokens_per_request,
                COALESCE(SUM(duration_ms) / 1000, 0)    AS total_duration_seconds,
                COALESCE(AVG(duration_ms), 0)           AS avg_response_ms,
                SUM(CASE WHEN is_success = 1 THEN 1 ELSE 0 END) AS success_count,
                SUM(CASE WHEN is_success = 0 THEN 1 ELSE 0 END) AS error_count
             FROM agent_usage_logs
             WHERE created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)'
        );
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: [];
    }

    /**
     * Mengambil tren statistik request dan konsumsi token harian.
     */
    public function getDailyStats(int $days = 7): array
    {
        $stmt = $this->pdo->prepare(
            'SELECT
                DATE(created_at)          AS log_date,
                COUNT(*)                  AS total_requests,
                COALESCE(SUM(total_tokens), 0) AS tokens_used,
                COALESCE(AVG(duration_ms), 0)  AS avg_latency_ms
             FROM agent_usage_logs
             WHERE created_at >= DATE_SUB(NOW(), INTERVAL ? DAY)
             GROUP BY DATE(created_at)
             ORDER BY log_date ASC'
        );
        $stmt->execute([$days]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /**
     * Mengurai distribusi pemanggilan tools dari kolom JSON.
     */
    public function getMostUsedTools(): array
    {
        $stmt = $this->pdo->query(
            'SELECT tool_name, COUNT(*) AS usage_count
             FROM (
                 SELECT JSON_UNQUOTE(JSON_EXTRACT(tools_used, CONCAT("$[", n.n, "]"))) AS tool_name
                 FROM agent_usage_logs,
                      (SELECT 0 AS n UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) n
                 WHERE JSON_LENGTH(tools_used) > n.n
             ) t
             WHERE tool_name IS NOT NULL AND tool_name != "null"
             GROUP BY tool_name
             ORDER BY usage_count DESC
             LIMIT 10'
        );
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /**
     * Mengambil 20 riwayat interaksi percakapan pengguna terbaru.
     */
    public function getRecentConversations(int $limit = 20): array
    {
        $stmt = $this->pdo->prepare(
            'SELECT l.*, u.name AS user_name, u.email
             FROM agent_usage_logs l
             LEFT JOIN users u ON l.user_id = u.id
             ORDER BY l.created_at DESC
             LIMIT ?'
        );
        $stmt->execute([$limit]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

Implementasi Frontend View Template dan Chart.js

Direct Answer:Template view admin mengonsumsi array data dari DashboardService untuk merender kartu metrik statistik dan menyuplai dataset JSON ke visualisasi diagram garis/batang Chart.js secara reaktif.

Berikut adalah contoh kode implementasi antarmuka frontend (PHP Template / Laravel Blade) yang siap digunakan pada dashboard admin:

<!-- views/admin/dashboard.php atau resources/views/admin/dashboard.blade.php -->
<div class="container mx-auto p-6 space-y-6">
    <h1 class="text-2xl font-bold text-white">AI Agent Analytics Overview</h1>

    <!-- 1. Top Metrics Summary Cards -->
    <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
        <div class="p-4 bg-slate-900 border border-slate-800 rounded-xl">
            <span class="text-xs text-slate-400 font-mono uppercase">Total Requests</span>
            <div class="text-2xl font-extrabold text-white mt-1"><?= number_format($summary['total_requests']) ?></div>
            <span class="text-xs text-emerald-400 font-medium"><?= number_format($summary['success_count']) ?> Berhasil</span>
        </div>
        <div class="p-4 bg-slate-900 border border-slate-800 rounded-xl">
            <span class="text-xs text-slate-400 font-mono uppercase">Total Token Usage</span>
            <div class="text-2xl font-extrabold text-sky-400 mt-1"><?= number_format($summary['total_tokens_used']) ?></div>
            <span class="text-xs text-slate-400">Rata-rata: <?= number_format($summary['avg_tokens_per_request']) ?> / req</span>
        </div>
        <div class="p-4 bg-slate-900 border border-slate-800 rounded-xl">
            <span class="text-xs text-slate-400 font-mono uppercase">Avg Latency</span>
            <div class="text-2xl font-extrabold text-amber-400 mt-1"><?= number_format($summary['avg_response_ms']) ?> ms</div>
            <span class="text-xs text-emerald-400">Total: <?= number_format($summary['total_duration_seconds']) ?>s komputasi</span>
        </div>
        <div class="p-4 bg-slate-900 border border-slate-800 rounded-xl">
            <span class="text-xs text-slate-400 font-mono uppercase">Error Count</span>
            <div class="text-2xl font-extrabold text-rose-400 mt-1"><?= number_format($summary['error_count']) ?></div>
            <span class="text-xs text-slate-400">Tingkat Error: <?= $summary['total_requests'] > 0 ? round(($summary['error_count'] / $summary['total_requests']) * 100, 2) : 0 ?>%</span>
        </div>
    </div>

    <!-- 2. Chart.js Container -->
    <div class="p-6 bg-slate-900 border border-slate-800 rounded-2xl">
        <h2 class="text-lg font-semibold text-white mb-4">Tren Penggunaan Harian</h2>
        <div class="relative w-full h-72">
            <canvas id="usageChartCanvas"></canvas>
        </div>
    </div>
</div>

<!-- 3. Inisialisasi Script Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js" defer></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
    const dailyStats = <?= json_encode($dailyStats) ?>;
    const labels     = dailyStats.map(row => row.log_date);
    const requests   = dailyStats.map(row => row.total_requests);
    const tokens     = dailyStats.map(row => row.tokens_used / 1000);

    const ctx = document.getElementById("usageChartCanvas").getContext("2d");
    new Chart(ctx, {
        type: "bar",
        data: {
            labels: labels,
            datasets: [
                {
                    label: "Volume Requests",
                    data: requests,
                    backgroundColor: "rgba(16, 185, 129, 0.7)",
                    borderRadius: 6
                },
                {
                    label: "Tokens Used (x1,000)",
                    data: tokens,
                    borderColor: "#38bdf8",
                    backgroundColor: "rgba(56, 189, 248, 0.2)",
                    type: "line",
                    tension: 0.3
                }
            ]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false
        }
    });
});
</script>

Estimasi Biaya & Tabel Perbandingan Harga Model API LLM

Direct Answer:Kalkulasi biaya LLM dihitung berdasarkan tarif per 1 juta token dengan rumus: Cost = (Prompt Tokens / 1.000.000 × Input Rate) + (Completion Tokens / 1.000.000 × Output Rate).

Gunakan fungsi pembantu di bawah ini untuk menghitung kalkulasi biaya dolar berdasarkan tarif per 1 juta token (1M tokens) pada masing-masing penyedia model kecerdasan buatan:

<?php

namespace App\Admin;

class CostCalculator
{
    /**
     * Tarif resmi per 1 Juta Token (USD).
     */
    private static array $pricing = [
        'gpt-4o-mini'           => ['input' => 0.15, 'output' => 0.60],
        'gpt-4o'                => ['input' => 2.50, 'output' => 10.00],
        'claude-3-5-sonnet'     => ['input' => 3.00, 'output' => 15.00],
        'gemini-1-5-pro'        => ['input' => 1.25, 'output' => 5.00],
        'gemini-1-5-flash'      => ['input' => 0.075, 'output' => 0.30],
    ];

    public static function calculate(int $promptTokens, int $completionTokens, string $model = 'gpt-4o-mini'): float
    {
        $rates = self::$pricing[$model] ?? self::$pricing['gpt-4o-mini'];
        $inputCost  = ($promptTokens / 1_000_000) * $rates['input'];
        $outputCost = ($completionTokens / 1_000_000) * $rates['output'];

        return round($inputCost + $outputCost, 6);
    }
}

Komparasi Biaya & Harga Token Model AI Agent PHP (Per 1 Juta Token)

Tabel Perbandingan Harga Model API LLM untuk AI Agent
Nama Model AIProvider VendorInput Price / 1M TokensOutput Price / 1M TokensRekomendasi Use Case
GPT-4o miniOpenAI$0.15$0.60Default Agent Tasks, tool routing, dan klasifikasi teks
GPT-4oOpenAI$2.50$10.00Penalaran kompleks, query SQL tingkat lanjut, dan coding
Claude 3.5 SonnetAnthropic$3.00$15.00Ekstraksi dokumen panjang, penulisan esai, dan multimodal
Gemini 1.5 ProGoogle$1.25$5.00Context window super besar (hingga 2 juta token)
Gemini 1.5 FlashGoogle$0.075$0.30Tugas latensi super cepat dan pemrosesan bulk batch

Cost Optimization Strategy: Gunakan model hemat seperti GPT-4o mini untuk loop identifikasi tool awal, dan hanya beralih ke GPT-4o ketika penalaran kompleks gagal.

Sistem Peringatan Dini: Slack & Discord Webhook Alert

Direct Answer:Sistem peringatan dini (Early Warning Alert System) mengevaluasi ambang batas anggaran harian (misal: $50/hari atau 500.000 token) dan mengirimkan payload darurat melalui Webhook cURL ke kanal Slack atau Discord untuk mencegah kerugian finansial saat terjadi loop tak terkendali (*infinite agent loop*).

Berikut adalah diagram alur kerja dan class WebhookAlertService untuk mengotomasi notifikasi darurat:

Diagram Arsitektur: Real-time Budget & Token Alert System (Slack / Discord Webhook)
WebP Lossless • 70 KB • Schema Ready
Diagram arsitektur sistem notifikasi peringatan anggaran AI Agent PHP: agregator konsumsi token mendeteksi batas kuota terlampaui lalu mendispatch webhook JSON via cURL ke Slack dan Discord
Gambar 18.2: Pipeline Sistem Peringatan Anggaran — Peringatan instan dikirim ke kanal tim saat konsumsi token harian melampaui ambang batas.
<?php

namespace App\Admin;

class WebhookAlertService
{
    private string $slackWebhookUrl;
    private string $discordWebhookUrl;
    private float $dailyBudgetLimit;

    public function __construct(string $slackUrl = '', string $discordUrl = '', float $budgetLimit = 50.0)
    {
        $this->slackWebhookUrl   = $slackUrl;
        $this->discordWebhookUrl = $discordUrl;
        $this->dailyBudgetLimit  = $budgetLimit;
    }

    /**
     * Memeriksa apakah biaya harian melebihi ambang batas dan memicu alert.
     */
    public function checkAndDispatchAlert(float $todayCost, int $todayTokens): void
    {
        if ($todayCost < $this->dailyBudgetLimit) {
            return;
        }

        $message = sprintf(
            "🚨 *AI AGENT BUDGET ALERT* 🚨\nBiaya harian telah mencapai: *$%.2f* (Batas: $%.2f)\nTotal Konsumsi Token: *%s tokens*\nStatus: _Throttling & Review Required_",
            $todayCost,
            $this->dailyBudgetLimit,
            number_format($todayTokens)
        );

        if (!empty($this->slackWebhookUrl)) {
            $this->sendCurlWebhook($this->slackWebhookUrl, ['text' => $message]);
        }

        if (!empty($this->discordWebhookUrl)) {
            $this->sendCurlWebhook($this->discordWebhookUrl, ['content' => $message]);
        }
    }

    private function sendCurlWebhook(string $url, array $payload): void
    {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => json_encode($payload),
            CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => 5,
        ]);
        curl_exec($ch);
        curl_close($ch);
    }
}

FAQ: Kendala Umum Saat Memonitor Request AI Agent

1. Bagaimana cara mencegah tabel log usage tumbuh terlalu besar?

Ringkasan Jawaban:Jalankan scheduler cron harian untuk memindahkan data log berumur lebih dari 90 hari ke tabel arsip dingin (*cold storage* / file CSV terkompresi) atau hapus log sementara menggunakan perintah DELETE FROM agent_usage_logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 90 DAY).

Dengan rotasi data berkala, indeks database MySQL tetap ramping dan performa kueri dashboard tetap di bawah 50 milidetik.

2. Mengapa terjadi perbedaan perhitungan token antara dashboard dan tagihan OpenAI?

Ringkasan Jawaban:Perbedaan biasanya timbul jika request gagal di tengah transmisi (misal: timeout soket jaringan atau error 400) sehingga token prompt tetap dihitung oleh OpenAI tetapi gagal tercatat di database lokal.

Selalu catat usage token dari blok $response['usage'] di dalam blok finally atau exception handler untuk meminimalisir deviasi pencatatan.

3. Bagaimana cara memantau latensi eksekusi tool yang lambat di dashboard?

Ringkasan Jawaban:Gunakan fungsi microtime(true) sebelum dan sesudah $tool->execute(), lalu simpan durasi spesifik masing-masing tool ke dalam kolom JSON tools_used (misal: [{"name": "DatabaseTool", "duration_ms": 420}]).

Ini memudahkan administrator mengidentifikasi query database yang lambat atau endpoint REST API pihak ketiga yang mengalami lag.

Key Takeaways: Rangkuman Dashboard Admin AI Agent PHP
  • Monitoring Token Komprehensif: Mencatat token input dan output secara akurat untuk memprediksi biaya operasional LLM.
  • Visualisasi Reaktif Frontend: Menggabungkan DashboardService dengan template view dan Chart.js untuk menampilkan tren request harian.
  • Early Warning Alert: Integrasi WebhookAlertService untuk memancarkan peringatan seketika saat konsumsi token melampaui batas.
  • Audit Jejak Penalaran: Meninjau riwayat percakapan pengguna dan pemanggilan alat untuk menyempurnakan system prompt agen.
RA

Rusmawan Abdullah Sani

Lead Software Engineer & System Architect

Praktisi pengembangan backend PHP modern, arsitektur AI Agent, microservices, dan otomasi server Linux. Terhubung melalui profil LinkedIn.