Teknik-teknik optimasi performa AI Agent PHP: caching response AI, async request queue dengan Redis, streaming response real-time, dan connection pooling untuk beban tinggi.
Daftar Isi
Terakhir diperbarui:
TL;DR (Ringkasan Cepat)
- Caching: Cache respons untuk query yang identik menghemat token dan waktu.
- Streaming: Server-Sent Events (SSE) membuat UX terasa jauh lebih responsif.
- Queue: Proses request berat di background agar endpoint tidak timeout.
- Connection Pool: Reuse koneksi DB untuk mengurangi overhead koneksi baru.
Response Caching
<?php
namespace App;
class ResponseCache
{
private string $cacheDir;
private int $ttl;
public function __construct(string $cacheDir = './cache', int $ttlSeconds = 3600)
{
$this->cacheDir = $cacheDir;
$this->ttl = $ttlSeconds;
if (!is_dir($cacheDir)) {
mkdir($cacheDir, 0755, true);
}
}
private function getCacheKey(string $task, array $tools): string
{
return md5($task . json_encode($tools));
}
public function get(string $task, array $tools = []): ?string
{
$key = $this->getCacheKey($task, $tools);
$file = $this->cacheDir . DIRECTORY_SEPARATOR . $key . '.cache';
if (!file_exists($file)) {
return null;
}
$data = unserialize(file_get_contents($file));
if (!$data || $data['expires_at'] < time()) {
unlink($file);
return null;
}
return $data['value'];
}
public function set(string $task, string $value, array $tools = []): void
{
$key = $this->getCacheKey($task, $tools);
$file = $this->cacheDir . DIRECTORY_SEPARATOR . $key . '.cache';
file_put_contents($file, serialize([
'value' => $value,
'expires_at' => time() + $this->ttl,
]));
}
}
// Penggunaan di Agent:
$cache = new ResponseCache(ttlSeconds: 1800);
$cached = $cache->get($task);
if ($cached) {
return $cached . ' [dari cache]';
}
$result = $agent->run($task);
$cache->set($task, $result);
return $result;
Streaming Response (Server-Sent Events)
<?php
// stream.php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('X-Accel-Buffering: no'); // Penting untuk Nginx
// Payload dengan stream: true
$payload = json_encode([
'model' => 'gpt-4o-mini',
'messages' => $messages,
'stream' => true,
]);
$ch = curl_init('https://api.openai.com/v1/chat/completions');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => false,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_WRITEFUNCTION => function($ch, $chunk) {
// Setiap chunk adalah baris "data: {...}"
$lines = explode("\n", $chunk);
foreach ($lines as $line) {
if (str_starts_with($line, 'data: ') && $line !== 'data: [DONE]') {
$data = json_decode(substr($line, 6), true);
$delta = $data['choices'][0]['delta']['content'] ?? '';
if ($delta) {
echo "data: " . json_encode(['text' => $delta]) . "\n\n";
ob_flush();
flush();
}
}
}
return strlen($chunk);
},
]);
curl_exec($ch);
curl_close($ch);
echo "data: [DONE]\n\n";
Async Queue dengan Redis
sudo apt install redis-server -y
composer require predis/predis
// Kirim task ke queue (non-blocking)
$redis = new Predis\Client();
$jobId = uniqid('job-', true);
$redis->rpush('agent:queue', json_encode([
'id' => $jobId,
'task' => $task,
'user_id' => $userId,
'created_at' => date('Y-m-d H:i:s'),
]));
// Worker (jalankan via Supervisor)
while (true) {
$job = $redis->blpop('agent:queue', 5); // Block 5 detik
if (!$job) { continue; }
$data = json_decode($job[1], true);
$result = $agent->run($data['task']);
// Simpan hasil ke Redis dengan TTL 1 jam
$redis->setex("agent:result:{$data['id']}", 3600, $result);
}
Poin Kunci Bab 20
Optimasi performa adalah investasi jangka panjang. Mulailah dengan caching yang memberikan peningkatan paling signifikan, lalu tambahkan streaming untuk UX yang lebih baik, dan queue untuk task berat.