PHP code example of moe-mizrak / laravel-openrouter

1. Go to this page and download the library: Download moe-mizrak/laravel-openrouter library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

moe-mizrak / laravel-openrouter example snippets


return [
    'api_endpoint' => env('OPENROUTER_API_ENDPOINT', 'https://openrouter.ai/api/v1/'),
    'api_key'      => env('OPENROUTER_API_KEY'),
    'api_timeout'  => env('OPENROUTER_API_TIMEOUT', 20),
    'title'        => env('OPENROUTER_API_TITLE', 'laravel-openrouter'),
    'referer'      => env('OPENROUTER_API_REFERER', 'https://github.com/moe-mizrak/laravel-openrouter'),
];

$provider = new ProviderPreferencesData(
    allow_fallbacks: true,
    thropic'],
    quantizations: [QuantizationType::FP16, QuantizationType::BF16],
    sort: new ProviderSortData(
        by: ProviderSortType::PRICE,
        partition: true,
    ),
    preferred_min_throughput: new PercentileData(
        p50: 100.0,
        p90: 50.0,
    ),
    preferred_max_latency: 2.5,
    max_price: new MaxPriceData(
        prompt: 0.001,
        completion: 0.002,
    ),
);

$chatData = new ChatData(
    messages: [
        new MessageData(
            role: RoleType::USER,
            content: 'Hello!',
        ),
    ],
    model: 'openai/gpt-4o',
    provider: $provider,
);

$chatData = new ChatData(
    messages: [
        new MessageData(
            role: RoleType::USER,
            content: [
                new TextContentData(
                    type: TextContentData::ALLOWED_TYPE,
                    text: 'This is a sample text content.',
                ),
                new ImageContentPartData(
                    type: ImageContentPartData::ALLOWED_TYPE,
                    image_url: new ImageUrlData(
                        url: 'https://example.com/image.jpg',
                        detail: 'Sample image',
                    ),
                ),
            ],
        ),
    ],
    response_format: new ResponseFormatData(
        type: 'json_object',
    ),
    usage: true,
    stop: ['stop_token'],
    stream: true,
    reasoning: new ReasoningData(
        effort: EffortType::HIGH,
        exclude: false,
    ),
    max_tokens: 1024,
    temperature: 0.7,
    top_p: 0.9,
    top_k: 50,
    frequency_penalty: 0.5,
    presence_penalty: 0.2,
    repetition_penalty: 1.2,
    seed: 42,
    tool_choice: 'auto',
    tools: [
        // ToolCallData instances
    ],
    logit_bias: [
        '50256' => -100,
    ],
    transforms: ['middle-out'],
    plugins: [
        new PluginData(
            id: 'web',
            max_results: 3,
            engine: 'native',
        ),
    ],
    web_search_options: new WebSearchOptionsData(
        search_context_size: SearchContextSizeType::MEDIUM,
    ),
    models: ['model1', 'model2'],
    route: RouteType::FALLBACK,
    provider: new ProviderPreferencesData(
        allow_fallbacks: true,
        

$content = 'Tell me a story about a rogue AI that falls in love with its creator.'; // Your desired prompt or content
$model = 'mistralai/mistral-7b-instruct:free'; // The OpenRouter model you want to use (https://openrouter.ai/models)
$messageData = new MessageData(
    content: $content,
    role: RoleType::USER,
);

$chatData = new ChatData(
    messages: [
        $messageData,
    ],
    model: $model,
    max_tokens: 100, // Adjust this value as needed
);

$chatResponse = LaravelOpenRouter::chatRequest($chatData);

// You can convert the response `toArray` if needed (It converts ResponseData DTO to array including the nested DTOs while filtering null values)
$responseArray = $chatResponse->toArray();

$content = 'Tell me a story about a rogue AI that falls in love with its creator.'; // Your desired prompt or content
$model = 'mistralai/mistral-7b-instruct:free'; // The OpenRouter model you want to use (https://openrouter.ai/models)
$messageData = new MessageData(
    content: $content,
    role: RoleType::USER,
);

$chatData = new ChatData(
    messages: [
        $messageData,
    ],
    model: $model,
    max_tokens: 100,
);

/*
 * Calls chatStreamRequest ($promise is type of PromiseInterface)
 */
$promise = LaravelOpenRouter::chatStreamRequest($chatData);

// Waits until the promise completes if possible.
$stream = $promise->wait(); // $stream is type of GuzzleHttp\Psr7\Stream

/*
 * 1) You can retrieve whole raw response as: - Choose 1) or 2) depending on your case.
 */
$rawResponseAll = $stream->getContents(); // Instead of chunking streamed response as below - while (! $stream->eof()), it waits and gets raw response all together.
$response = LaravelOpenRouter::filterStreamingResponse($rawResponseAll); // Optionally you can use filterStreamingResponse to filter raw streamed response, and map it into array of responseData DTO same as chatRequest response format.

// 2) Or Retrieve streamed raw response as it becomes available:
while (! $stream->eof()) {
    $rawResponse = $stream->read(1024); // readByte can be set as desired, for better performance 4096 byte (4kB) can be used.

    /*
     * Optionally you can use filterStreamingResponse to filter raw streamed response, and map it into array of responseData DTO same as chatRequest response format.
     */
    $response = LaravelOpenRouter::filterStreamingResponse($rawResponse);
}

Route::get('/test/stream', function () {
    $content = 'Tell me a story about a rogue AI that falls in love with its creator.';
    $model = 'deepseek/deepseek-chat-v3.1';
    
    $messageData = new MessageData(
        content: $content,
        role: RoleType::USER,
    );
    
    $chatData = new ChatData(
        messages: [$messageData],
        model: $model,
        max_tokens: 1000,
    );
    
    return response()->stream(function () use ($chatData) {
        $promise = LaravelOpenRouter::chatStreamRequest($chatData);
        $stream = $promise->wait();
        
        while (!$stream->eof()) {
            $rawResponse = $stream->read(1024);
            
            // 1) Print raw streamed response as it becomes available:
            echo $rawResponse;
            
            /*
             * 2) Optionally you can use filterStreamingResponse to filter raw streamed response, and map it into array of responseData DTO same as chatRequest response format.
             */
            $response = LaravelOpenRouter::filterStreamingResponse($rawResponse);
            
            foreach ($response as $responseData) {
                // Process each responseData as needed
                echo json_encode($responseData->toArray()) . PHP_EOL;
            }
            
            flush();
        }
    }, 200, [
        'Content-Type' => 'text/plain; charset=utf-8',
    ]);
});

"""
: OPENROUTER PROCESSING\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":"Title"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":": Quant"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":"um Echo"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":": A Sym"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGG
"""

"""
IsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":"phony of Code"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":"\n\nIn"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":" the heart of"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":" the bustling"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistra
"""

"""
l-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":" city of Ne"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":"o-Tok"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":"yo, a"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718885921,"choices":[{"index":0,"delta":{"role":"assistant","content":" brilliant young research"},"finish_reason":null}]}\n
\n
data: {"id":"gen-eWgGaEbIzFq4ziGGIsIjyRtLda54","model":"mistralai/mistral-7b-instruct:free","object":"chat.com
"""
...

: OPENROUTER PROCESSING\n
\n
data: {"id":"gen-C6Xym94jZcvJv2vVpxYSyw2tV1fR","model":"mistralai/mistral-7b-instruct:free","object":"chat.completion.chunk","created":1718887189,"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}],"usage":{"prompt_tokens":23,"completion_tokens":100,"total_tokens":123,"cost":0.00000114}}\n
\n
data: [DONE]\n

$model = 'mistralai/mistral-7b-instruct:free';

$firstMessage = new MessageData(
    role: RoleType::USER,
    content: 'My name is Moe, the AI necromancer.',
);

$chatData = new ChatData(
    messages: [
        $firstMessage,
    ],
    model: $model,
);
// This is the chat which you want LLM to remember
$oldResponse = LaravelOpenRouter::chatRequest($chatData);

/*
* You can skip part above and just create your historical message below (maybe you retrieve historical messages from DB etc.)
*/

// Here adding historical response to new message
$historicalMessage = new MessageData(
    role: RoleType::ASSISTANT, // Set as assistant since it is a historical message retrieved previously
    content: Arr::get($oldResponse->choices[0], 'message.content'), // Historical response content retrieved from previous chat request
);
// This is your new message
$newMessage = new MessageData(
    role: RoleType::USER,
    content: 'Who am I?',
);

$chatData = new ChatData(
    messages: [
        $historicalMessage,
        $newMessage,
    ],
    model: $model,
);

$response = LaravelOpenRouter::chatRequest($chatData);

$content = Arr::get($response->choices[0], 'message.content');
// content = You are Moe, a fictional character and AI Necromancer, as per the context of the conversation we've established. In reality, you are the user interacting with me, an assistant designed to help answer questions and engage in friendly conversation.

// Define the tool using ToolCallData and FunctionData
$tools = [
    new ToolCallData(
        type: 'function',
        function: new FunctionData(
            name: 'getWeather',
            description: 'Get the current weather for a location',
            parameters: [
                'type' => 'object',
                'properties' => [
                    'location' => [
                        'type' => 'string',
                        'description' => 'The city name',
                    ],
                ],
                ' tool call returned from LLM
$toolCall = $response['choices'][0]['message']['tool_calls'][0] ?? null;
// the model/LLM generated ID
$toolCallId = $toolCall['id']; // e.g. "call_7F3kP9"

// Sample tool result assuming you called the tool and got the result
$toolResult = [
    'temperature' => '22°C',
    'condition'   => 'Sunny',
];

// Provide tool result back to LLM:

// The original user message
$userMessage = new MessageData(
    role: RoleType::USER,
    content: 'What is the weather like in Tokyo?',
);

// Tool call assistant message with tool call ID
$assistantToolCallMessage = new MessageData(
    role: RoleType::ASSISTANT,
    tool_calls: [
        new ToolCallData(
            id: $toolCallId,
            type: 'function',
            function: new FunctionCallData(
                name: $toolCall['function']['name'],
                arguments: $toolCall['function']['arguments'],
            ),
        ),
    ],
);

// Tool response message with tool result and tool call ID
$toolResponseMessage = new MessageData(
    role: RoleType::TOOL,
    tool_call_id: $toolCallId,
    content: json_encode($toolResult),
);

$chatDataWithToolResult = new ChatData(
    messages: [
        $userMessage,
        $assistantToolCallMessage,
        $toolResponseMessage,
    ],
    model: 'openai/gpt-4o-mini',
);

// Send request with tool result
$finalResponse = LaravelOpenRouter::chatRequest($chatDataWithToolResult);

$chatData = new ChatData(
    messages: [
        new MessageData(
            role: RoleType::USER,
            content: 'Tell me a story about a rogue AI that falls in love with its creator.',
        ),
    ],
    model: 'mistralai/mistral-7b-instruct:free',
    response_format: new ResponseFormatData(
        type: 'json_object',
    ),
    provider: new ProviderPreferencesData(
        

$chatData = new ChatData(
    messages: [
        new MessageData(
            role   : RoleType::USER,
            content: 'Tell me a story about a rogue AI that falls in love with its creator.',
        ),
    ],
    model: 'mistralai/mistral-7b-instruct:free',
    response_format: new ResponseFormatData(
        type: 'json_schema',
        json_schema: [
            'name' => 'article',
            'strict' => true,
            'schema' => [
                'type' => 'object',
                'properties' => [
                    'title' => [
                        'type' => 'string',
                        'description' => 'article title'
                    ],
                    'details' => [
                        'type' => 'string',
                        'description' => 'article detail'
                    ],
                    'keywords' => [
                        'type' => 'string',
                        'description' => 'article keywords',
                    ],
                ],
                '

$chatData = new ChatData(
    messages: [
        new MessageData(
            role: RoleType::USER,
            content: 'What are the latest developments in AI?',
        ),
    ],
    model: 'openai/gpt-4o:online',
    web_search_options: new WebSearchOptionsData(
        search_context_size: SearchContextSizeType::HIGH, // Optional: low, medium, high
    ),
);

$chatData = new ChatData(
    messages: [
        new MessageData(
            role: RoleType::USER,
            content: 'What are the latest developments in AI?',
        ),
    ],
    model: 'openai/gpt-4o',
    plugins: [
        new PluginData(
            id: 'web',
            max_results: 5, // Optional: number of search results to retrieve
            engine: 'undefined', // Optional: "native", "exa", or "undefined"
        ),
    ],
    web_search_options: new WebSearchOptionsData(
        search_context_size: SearchContextSizeType::MEDIUM, // Optional: low, medium, high
    ),
);

$response = LaravelOpenRouter::chatRequest($chatData);

$annotations = Arr::get($response->choices[0], 'message.annotations', []);

$model = 'anthropic/claude-3.5-sonnet';

// Plugin configuration for file parsing, optional
$plugins = [
    new PluginData(
        id: 'file-parser',
        pdf: [
            'engine' => 'pdf-text', // Supported engines: pdf-text, mistral-ocr and native
        ],
    ),
];

// For the publicly accessible PDFs
$fileContentData = new FileContentData(
    type: FileContentData::ALLOWED_TYPE,
    file: new FileUrlData(
        file_data: 'https://example.com/report.pdf',
        filename: 'quarterly-report.pdf',
    ),
);

$textContentData = new TextContentData(
    type: TextContentData::ALLOWED_TYPE,
    text: 'Please summarize this document.',
);

$messageData = new MessageData(
    content: [
        $textContentData,
        $fileContentData,
    ],
    role: RoleType::USER,
);

$chatData = new ChatData(
    messages: [$messageData],
    model: $model,
    plugins: $plugins,
);

$response = LaravelOpenRouter::chatRequest($chatData);

$base64Data = base64_encode(file_get_contents('/path/to/document.pdf'));

$fileContentData = new FileContentData(
    type: FileContentData::ALLOWED_TYPE,
    file: new FileUrlData(
        file_data: "data:application/pdf;base64,{$base64Data}",
        filename: 'document.pdf',
    ),
);

$model = 'mistralai/voxtral-small-24b-2507'; // Audio input supported models: https://openrouter.ai/models?fmt=cards&input_modalities=audio
$data = base64_encode('path/of/audio/file.mp3'); // Base64-encoded audio data

$audioContentData = new AudioContentData(
    type: AudioContentData::ALLOWED_TYPE, // it can only take input_audio for audio content
    input_audio: new InputAudioData(
        data: $data,
        format: AudioFormatType::MP3, // Supported formats: mp3, wav
    ),
);

$textContentData = new TextContentData(
    type: TextContentData::ALLOWED_TYPE,
    text: 'Please transcribe this audio file.',
);

$messageData = new MessageData(
    content: [
        $textContentData,
        $audioContentData,
    ],
    role: RoleType::USER,
);

$chatData = new ChatData(
    messages: [
        $messageData,
    ],
    model: $model,
);

$response = LaravelOpenRouter::chatRequest($chatData);

use MoeMizrak\LaravelOpenrouter\DTO\CacheControlData;
use MoeMizrak\LaravelOpenrouter\DTO\ChatData;
use MoeMizrak\LaravelOpenrouter\DTO\MessageData;
use MoeMizrak\LaravelOpenrouter\Types\RoleType;

$chatData = new ChatData(
    messages: [
        new MessageData(
            role: RoleType::USER,
            content: 'What triggered the collapse?',
        ),
    ],
    model: 'anthropic/claude-sonnet-4.6',
    cache_control: new CacheControlData(
        type: CacheControlData::ALLOWED_TYPE, // "ephemeral"
        ttl: '1h', // optional
    ),
);

use MoeMizrak\LaravelOpenrouter\DTO\CacheControlData;
use MoeMizrak\LaravelOpenrouter\DTO\ChatData;
use MoeMizrak\LaravelOpenrouter\DTO\MessageData;
use MoeMizrak\LaravelOpenrouter\DTO\TextContentData;
use MoeMizrak\LaravelOpenrouter\Types\RoleType;

$chatData = new ChatData(
    messages: [
        new MessageData(
            role: RoleType::USER,
            content: [
                new TextContentData(
                    text: 'Given the book below:',
                ),
                new TextContentData(
                    text: 'HUGE TEXT BODY',
                    cache_control: new CacheControlData(
                        type: CacheControlData::ALLOWED_TYPE, // "ephemeral"
                        ttl: '1h', // optional
                    ),
                ),
                new TextContentData(
                    text: 'What triggered the collapse?',
                ),
            ],
        ),
    ],
    model: 'anthropic/claude-sonnet-4.6',
);

$content = 'Tell me a story about a rogue AI that falls in love with its creator.'; // Your desired prompt or content
$model = 'mistralai/mistral-7b-instruct:free'; // The OpenRouter model you want to use (https://openrouter.ai/models)
$messageData = new MessageData(
    content: $content,
    role   : RoleType::USER,
);

$chatData = new ChatData(
    messages: [
        $messageData,
    ],
    model: $model,
    max_tokens: 100,
);

$chatResponse = LaravelOpenRouter::chatRequest($chatData);
$generationId = $chatResponse->id; // generation id which will be passed to costRequest

$costResponse = LaravelOpenRouter::costRequest($generationId);

// You can convert the response `toArray` if needed (It converts CostResponseData DTO to array while filtering null values)
$responseArray = $costResponse->toArray();

$limitResponse = LaravelOpenRouter::limitRequest();

// You can convert the response `toArray` if needed (It converts LimitResponseData DTO to array including the nested DTOs while filtering null values)
$responseArray = $limitResponse->toArray();

public function __construct(protected OpenRouterRequest $openRouterRequest) {}

/*
 * Similarly, you can use OpenRouterRequest class methods as below:
 */
// Chat Request
$response = $this->openRouterRequest->chatRequest($chatData);

// Stream Chat Request
$streamResponse = $this->openRouterRequest->chatStreamRequest($chatData);

// Cost Request
$costResponse = $this->openRouterRequest->costRequest($generationId);

// Limit Request
$limitResponse = $this->openRouterRequest->limitRequest();
bash
php artisan vendor:publish --tag=laravel-openrouter