Mastering Streamed AI Responses with Laravel and Vue
Overview
Modern users expect AI responses to feel instantaneous. Waiting for a large language model to complete its entire thought before displaying text creates a sluggish, broken experience.
Prerequisites
To follow along, you should have a solid grasp of the
Key Libraries & Tools
- Prism AI: A package that simplifies connecting to multiple AI providers through a unified interface.
- useStream Hook: An official Laravelfrontend hook for managing real-time data flow.
- useEventStream Hook: Used for server-to-client events, like updating a chat title once context is established.
- Inertia.js: Bridges the gap between your server-side routing and client-side components.
Code Walkthrough
The Backend Controller
On the server, we use response()->stream() to maintain an open connection. We disable output buffering to ensure the data reaches the client immediately.
return response()->stream(function () use ($messages) {
$stream = Prism::text(['model' => 'gpt-4', 'messages' => $messages])->stream();
foreach ($stream as $chunk) {
echo $chunk->text;
flush();
}
}, 200, [
'Cache-Control' => 'no-cache',
'X-Accel-Buffering' => 'no'
]);
The Frontend Hook
In your useStream hook replaces standard Axios or Fetch calls. It handles the manual work of reading the stream buffer and updating your reactive state.
import { useStream } from '@laravel/stream-view';
const { messages, send, isStreaming } = useStream('/chat');
const submit = (e) => {
send({ message: userInput.value });
};
Syntax Notes
Pay close attention to the X-Accel-Buffering header. If you are behind an Nginx proxy, failing to set this to 'no' will cause the server to buffer the AI's output, effectively killing the streaming effect. Additionally, because useStream operates outside the standard
Practical Examples
Beyond simple chat, use useEventStream for secondary UI updates. For instance, while the main chat streams, a second background stream can generate a relevant conversation title or suggest follow-up questions without interrupting the primary text flow.
Tips & Gotchas
Avoid the trap of trying to use useForm for these requests. Streaming requires a persistent connection that standard AJAX forms aren't designed to hold. Also, remember that a stream is a one-way street once it starts; if you need to stop it, provide a UI button that triggers the cancel() method provided by the hook to free up browser resources.
