premieroctet / php-stream-protocol
A PHP library for handling AI streaming protocols, particularly the Vercel AI SDK Stream Protocol
Installs: 740
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/premieroctet/php-stream-protocol
Requires
- php: ^8.1
- symfony/http-foundation: ^6.0|^7.0
Requires (Dev)
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.0
README
A PHP library for handling the Vercel AI SDK Stream Protocol. This package provides an easy-to-use interface for creating streaming AI responses with support for tool calls, attachments, and various AI providers.
Features
- 🚀 Easy Integration: Simple, fluent API for streaming responses
- 🔧 Tool Support: Built-in tool calling and execution
- 📎 Attachments: Handle file and image attachments
- 🔄 Multi-Provider: Support for OpenAI and other providers
- 📊 Protocol Compliant: Follows Vercel AI SDK Stream Protocol specifications
- âš¡ Symfony Integration: Built with Symfony components
Installation
composer require premieroctet/php-stream-protocol
Quick Start
Basic Usage
use PremierOctet\PhpStreamProtocol\StreamProtocol; use OpenAI; // Create a new StreamProtocol instance $protocol = StreamProtocol::create() ->withSystemPrompt('You are a helpful assistant.'); // Register tools $protocol->registerTool('get_weather', [WeatherService::class, 'getCurrentWeather']); // In your controller public function chat(Request $request): Response { // Parse incoming messages $messages = $protocol->parseMessages($request->getContent()); // Convert to OpenAI format and create request $openaiRequest = $protocol->buildOpenAIRequest($messages, 'gpt-4'); // Create OpenAI stream $client = OpenAI::client($apiKey); $stream = $client->chat()->createStreamed($openaiRequest); // Return streaming response return $protocol->stream($stream); }
Symfony Usage
<?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\HttpFoundation\Request; use PremierOctet\PhpStreamProtocol\StreamProtocol; use App\Tools\WeatherTool; use OpenAI; class ChatController extends AbstractController { private StreamProtocol $streamProtocol; public function __construct() { $this->streamProtocol = StreamProtocol::create() ->withSystemPrompt('You are a demo assistant showcasing the integration of Vercel AI SDK with a Symfony controller.') ->registerTool(new WeatherTool()); } #[Route('/api/chat', name: 'api_chat', methods: ['POST'])] public function chat(Request $request): Response { return $this->streamProtocol->handleRequest( $request->getContent(), function(array $openaiMessages) { $client = OpenAI::client($_ENV['OPENAI_API_KEY']); return $client->chat()->createStreamed([ 'model' => 'gpt-4', 'messages' => $openaiMessages, 'stream' => true, 'tools' => [WeatherTool::getToolDefinition()], ]); }, ); } #[Route('/chat', name: 'chat')] public function chatPage(): Response { return $this->render('chat.html.twig'); } }
Advanced Usage with Custom Tools
use PremierOctet\PhpStreamProtocol\StreamProtocol; class ChatController { public function chat(Request $request): Response { $protocol = StreamProtocol::create() ->withSystemPrompt('You are a helpful assistant with access to various tools.') ->registerTool('search_web', [$this, 'searchWeb']) ->registerTool('get_weather', [$this, 'getWeather']) ->registerTool('send_email', [$this, 'sendEmail']); return $protocol->handleRequest( $request->getContent(), function($messages) use ($request) { $client = OpenAI::client(env('OPENAI_API_KEY')); return $client->chat()->createStreamed([ 'model' => 'gpt-4', 'messages' => $messages, 'stream' => true, 'tools' => $protocol->getToolDefinitions(), ]); } ); } private function searchWeb(string $query): array { // Your web search implementation return ['results' => "Search results for: {$query}"]; } private function getWeather(string $location): array { // Your weather service implementation return ['weather' => "Weather in {$location}: Sunny, 25°C"]; } }
Message Conversion
// Convert messages to different AI provider formats $messages = $protocol->parseMessages($jsonData); // For OpenAI $openaiMessages = $protocol->convertToOpenAI($messages);
Simple Text Streaming (for testing)
public function demo(): Response { $protocol = StreamProtocol::create(); return $protocol->streamText( 'This is a demo of streaming text word by word.', 50 // delay in milliseconds ); }
Message Format
The library handles messages in the Vercel AI SDK format, supporting:
- Text messages: Simple text content
- Tool calls: Function calling with arguments and results
- Attachments: File and image attachments
- Message parts: Complex message structures
Example message structure:
{
"messages": [
{
"role": "user",
"content": "What's the weather like?",
"experimental_attachments": [
{
"contentType": "image/jpeg",
"url": "data:image/jpeg;base64,..."
}
]
},
{
"role": "assistant",
"content": "",
"toolInvocations": [
{
"toolCallId": "call_123",
"toolName": "get_weather",
"args": { "location": "New York" },
"result": { "temperature": "25°C", "condition": "sunny" }
}
]
}
]
}
Stream Protocol
The library implements the Vercel AI SDK Stream Protocol with the following message types:
0:- Text content9:- Tool calla:- Tool resultb:- Tool call streaming startc:- Tool call deltad:- Finish messagee:- Finish stepf:- Message start
Tool Integration
Tools must follow this interface:
class WeatherTool implements ToolInterface { public function getName(): string { return 'get_current_weather'; } public function getDescription(): string { return 'Get current weather for a location'; } public function execute(array $parameters): mixed { return [ 'location' => $parameters['location'], 'temperature' => '25°C', 'condition' => 'sunny' ]; } public function getParameters(): array { return [ 'type' => 'object', 'properties' => [ 'location' => [ 'type' => 'string', 'description' => 'The city and state, e.g. San Francisco, CA' ] ], 'required' => ['location'] ]; } public function isStrict(): bool { return true; } }
Requirements
- PHP 8.1 or higher
- Symfony HttpFoundation component
License
MIT License - see LICENSE file for details.
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request