Prism PHP: Satu Interface untuk Banyak LLM di Laravel

Diperbaharui 6 November 2026 6:56 PM

Kalau kamu pernah menulis integrasi AI di Laravel, kamu tahu masalahnya: kode untuk OpenAI, Anthropic, dan Gemini bentuknya beda semua. Begitu mau ganti model karena harga naik atau kualitas menurun, yang berubah bukan satu baris konfigurasi, tapi seluruh service class. Paket prism-php/prism mencoba menyelesaikannya dengan satu interface tunggal untuk banyak penyedia LLM — lebih dari 8 juta unduhan di Packagist dan sekitar 2.400 bintang di GitHub. Semua nama method di bawah diambil dari dokumentasi resmi dan source code repository-nya, bukan dari ingatan.

Apa Itu Prism dan Masalah Apa yang Diselesaikannya

Prism adalah paket Laravel yang membungkus API berbagai penyedia LLM ke dalam satu fluent builder. Dibuat TJ Miller, lisensi MIT, dan menyatakan secara eksplisit tidak berafiliasi dengan Laravel — jangan tertukar dengan Laravel AI SDK yang resmi. Manfaat intinya:

  • Satu sintaks untuk semua provider. Prism::text() tetap sama, baik kamu memanggil OpenAI, Anthropic, Gemini, DeepSeek, Groq, Mistral, xAI, OpenRouter, Perplexity, Ollama, VoyageAI, ElevenLabs, maupun provider z.
  • Ganti model tanpa refactor. Provider dan model hanya argumen pada method using(), bukan class terpisah yang harus di-inject ke constructor.
  • Fitur lanjutan seragam. Tool calling, structured output, streaming SSE, input multi-modal, sampai penomoran token memakai API yang sama — termasuk penormalan finishReason dan usage lintas vendor, jadi kode pemantauan biaya tidak perlu ditulis ulang tiap pindah provider.

Prism atau Laravel AI SDK Resmi?

Dua-duanya valid, titik beratnya beda. Laravel AI SDK adalah jalur first-party: dokumentasi menyatu dengan ekosistem Laravel, cocok kalau kamu ingin mengikuti konvensi resmi. Prism lebih tepat ketika kebutuhanmu portabilitas antar vendor — misalnya klasifikasi teks jalan di model murah untuk trafik normal, lalu pindah ke model lebih kuat saat ada eskalasi, hanya dengan mengubah nilai provider dan model. Pembanding pendekatan official-nya ada di artikel Mengenal Laravel AI SDK.

Instalasi dan Konfigurasi

Syarat minimum menurut dokumentasi adalah PHP 8.2 dan Laravel 11 ke atas. Tapi versi terbaru saat artikel ini ditulis (v0.102.0, rilis 16 Oktober 2026) mencantumkan laravel/framework dengan batas ^12.61.1|^13.12.0. Kalau proyekmu masih di Laravel 11, pakai versi Prism yang lebih lama — bukan memaksa upgrade framework.

composer require prism-php/prism
php artisan vendor:publish --tag=prism-config

Perintah kedua menghasilkan config/prism.php berisi tiga bagian: prism_server, request_timeout, dan providers. Timeout global default 30 detik, berlaku untuk koneksi sekaligus durasi request.

// potongan config/prism.php
'request_timeout' => env('PRISM_REQUEST_TIMEOUT', 30),

'providers' => [
    'openai' => [
        'url' => env('OPENAI_URL', 'https://api.openai.com/v1'),
        'api_key' => env('OPENAI_API_KEY', ''),
    ],
    'ollama' => [
        'url' => env('OLLAMA_URL', 'http://localhost:11434/v1'),
    ],
],

Generate Teks Pertama

Semua request teks dimulai dari facade Prism dan diakhiri method penutup seperti asText() — pola yang mirip query builder Eloquent: susun dulu, eksekusi di akhir.

use Prism\Prism\Facades\Prism;
use Prism\Prism\Enums\Provider;

$jawaban = Prism::text()
    ->using(Provider::OpenAI, 'gpt-4o')
    ->withSystemPrompt('Kamu guru matematika yang menjelaskan dengan bahasa sederhana.')
    ->usingTemperature(0.3)
    ->withMaxTokens(600)
    ->withPrompt('Jelaskan teorema Pythagoras dalam dua paragraf.')
    ->asText();

echo $jawaban->text;
echo $jawaban->finishReason->name;
echo $jawaban->usage->completionTokens;

Response object menyimpan lebih dari sekadar teks: finishReason, usage, raw, serta steps dan messages. Memeriksa finishReason sebelum memakai text itu penting — nilai Length berarti output terpotong karena batas token, sedangkan Refusal berarti model menolak permintaan.

Untuk parameter lain ada usingTopP() dan usingTopK(). Pilih salah satu antara temperature atau topP, jangan keduanya: dua-duanya mengatur keacakan, sehingga kombinasinya susah diprediksi saat tuning. Untuk hal yang tidak punya method khusus, withClientOptions() meneruskan opsi HTTP client Laravel (misalnya timeout) dan withClientRetry() mengatur retry otomatis.

Satu Kode, Banyak Provider

Enum Provider di source code-nya berisi Anthropic, DeepSeek, Ollama, OpenAI, OpenRouter, Mistral, Groq, XAI, Gemini, VoyageAI, ElevenLabs, Perplexity, dan Z. Karena semuanya enum, salah tulis nama provider gagal lebih awal — bukan setelah request terkirim. Untuk menimpa konfigurasi per request — misalnya tiap tenant punya API key sendiri — gunakan usingProviderConfig(); nilainya di-merge dengan konfigurasi asal.

Function Calling dengan Tool

Tool memungkinkan model memanggil kode PHP milikmu, didefinisikan lewat facade Tool: beri nama, deskripsi, parameter, lalu closure yang dieksekusi.

use Prism\Prism\Facades\Prism;
use Prism\Prism\Facades\Tool;
use Prism\Prism\Enums\Provider;

$stok = Tool::as('cek_stok')
    ->for('Mengecek jumlah stok produk berdasarkan SKU')
    ->withStringParameter('sku', 'Kode SKU produk')
    ->using(fn (string $sku): string =>
        (string) \App\Models\Produk::where('sku', $sku)->value('stok')
    );

$balasan = Prism::text()
    ->using(Provider::OpenAI, 'gpt-4o')
    ->withMaxSteps(2)
    ->withTools([$stok])
    ->withPrompt('Stok SKU ABC-123 masih ada berapa?')
    ->asText();

Dua hal yang mudah bikin bingung pemula: closure tool wajib mengembalikan string, dan withMaxSteps() harus dinaikkan — default-nya satu langkah, jadi tool tidak akan pernah dipanggil kalau kamu lupa. Parameter tidak valid secara default tidak melempar exception: model menerima pesan kesalahan sebagai teks lalu memperbaiki argumennya sendiri. Kalau butuh validasi ketat, matikan lewat withoutToolErrorHandling() per request atau withoutErrorHandling() per tool.

Structured Output: JSON yang Bentuknya Dijamin

Untuk ekstraksi data atau respons API, teks bebas tidak cukup. Gunakan Prism::structured() dengan schema sebagai objek PHP.

use Prism\Prism\Facades\Prism;
use Prism\Prism\Enums\Provider;
use Prism\Prism\Schema\ObjectSchema;
use Prism\Prism\Schema\StringSchema;

$skema = new ObjectSchema(
    name: 'ringkasan',
    description: 'Ringkasan terstruktur sebuah artikel',
    properties: [
        new StringSchema('judul', 'Judul artikel'),
        new StringSchema('kategori', 'Kategori utama'),
        new StringSchema('ringkasan', 'Ringkasan maksimal 40 kata'),
    ],
    requiredFields: ['judul', 'kategori', 'ringkasan']
);

$hasil = Prism::structured()
    ->using(Provider::OpenAI, 'gpt-4o')
    ->withSchema($skema)
    ->withPrompt($teksArtikel)
    ->asStructured();

Data hasilnya dibaca dari $hasil->structured sebagai array. Aturan tiap provider beda: OpenAI mode strict mewajibkan semua properti masuk requiredFields dan field opsional ditandai nullable: true, serta root schema harus ObjectSchema. Kalau server kompatibel yang kamu pakai tidak mendukung json_schema, turunkan mode lewat usingStructuredMode(StructuredMode::Json).

Streaming ke Browser

Efek mengetik real-time paling mudah dicapai dengan Server-Sent Events. asEventStreamResponse() langsung mengembalikan response Laravel, jadi header dan buffering tidak perlu diurus manual. Di sisi klien, event yang perlu didengar adalah text_delta (potongan teks) dan stream_end (membawa finish_reason). Kalau frontend memakai Vercel AI SDK, ada adapter lain: asDataStreamResponse().

Satu jebakan yang dokumentasinya sendiri sebutkan: Telescope atau paket lain yang mengintersepsi HTTP client Laravel bisa “memakan” stream sebelum Prism sempat mengirim event — gejalanya streaming terlihat putus padahal request sukses. Untuk siaran ke banyak pengguna, kombinasikan streaming dengan broadcasting seperti pola di artikel Laravel Reverb untuk real-time.

Error, Rate Limit, dan Catatan Produksi

Prism melempar PrismException untuk kegagalan umum dan PrismServerException untuk Prism Server. Di produksi, exception yang lebih spesifik lebih berguna karena bisa dipetakan ke perilaku berbeda — PrismRateLimitedException (kuota habis: backoff atau pindah provider), PrismProviderOverloadedException (provider kelebihan kapasitas), PrismRequestTooLargeException (prompt melebihi batas), dan PrismStructuredDecodingException (JSON tidak valid untuk request structured). Dukungannya masih digulirkan bertahap per provider, jadi selalu sediakan catch Throwable sebagai jaring terakhir.

Beberapa hal yang tidak ada di quick start:

  • Naikkan timeout untuk model lokal. Default 30 detik sering tidak cukup untuk Ollama di mesin tanpa GPU.
  • Simpan additionalContent, lanjutkan percakapan dari $response->messages. Setiap AssistantMessage membawa state provider, misalnya blok thinking bertanda tangan dari Claude atau reasoning item dari OpenAI. Kalau hanya teks yang disimpan lalu riwayat disusun ulang, model kehilangan penalaran turn sebelumnya; pada Anthropic percakapan yang terikat signature bahkan bisa ditolak.
  • Token bukan tagihan. usage hanya akuntansi token yang dinormalkan; biaya per request, biaya pencarian, dan percobaan fallback tidak masuk hitungan.
  • Pin versi. Prism masih di jalur 0.x, jadi kunci versinya, misalnya "prism-php/prism": "^0.102.0".

FAQ

Apakah Prism bisa dipakai di luar Laravel?

Tidak untuk versi ini. Paketnya bergantung pada laravel/framework, jadi HTTP client, config, dan service provider Laravel dipakai langsung. Untuk proyek PHP murni, gunakan SDK resmi masing-masing provider.

Apakah Prism butuh Prism Server?

Tidak. prism_server default-nya false dan hanya relevan kalau kamu ingin menjalankan komponen sisi server. Semua contoh di artikel ini berjalan tanpa mengaktifkannya.

Bisakah memakai model lokal tanpa biaya API?

Bisa, lewat provider Ollama yang diarahkan ke http://localhost:11434/v1. Yang perlu disiapkan hanya Ollama berjalan dan model sudah di-pull, plus timeout lebih longgar karena inferensi lokal jauh lebih lambat.

Kesimpulan

Prism menyelesaikan satu masalah yang spesifik: kode aplikasi seharusnya tidak perlu tahu vendor LLM mana yang sedang dipakai. Dengan satu builder untuk teks, tool calling, structured output, dan streaming, mengganti model jadi keputusan konfigurasi — bukan proyek refactor. Kalau aplikasimu hanya akan pernah memakai satu provider, lapisan abstraksi ini menambah dependensi tanpa banyak manfaat; memanggil SDK resmi vendor langsung lebih jujur. Untuk pembanding pendekatan resmi Laravel, lanjutkan ke artikel Laravel AI SDK.

Referensi

susantokun avatar
susantokun
Hanya seorang programmer yang fokus di bidang web development. Tidak nyaman dengan keramaian dan suka akan keindahan.
Kebijakan Berkomentar :
1. Dilarang berkomentar yang mengandung SPAM, SARA, HOAX, PORNO.2. Mohon sertakan informasi detail saat terjadi error (pesan error, sreenshoot, code, logs, dsb.).