Add complete Laravel LLM Gateway implementation

Core Features:
- Multi-provider support (OpenAI, Anthropic, DeepSeek, Gemini, Mistral)
- Provider service architecture with abstract base class
- Dynamic model discovery from provider APIs
- Encrypted per-user provider credentials storage

Admin Interface:
- Complete admin panel with Livewire components
- User management with CRUD operations
- API key management with testing capabilities
- Budget system with limits and reset schedules
- Usage logs with filtering and CSV export
- Model pricing management with cost calculator
- Dashboard with Chart.js visualizations

Database Schema:
- MariaDB migrations for all tables
- User provider credentials (encrypted)
- LLM request logging
- Budget tracking and rate limiting
- Model pricing configuration

API Implementation:
- OpenAI-compatible endpoints
- Budget checking middleware
- Rate limit enforcement
- Request logging jobs
- Cost calculation service

Testing:
- Unit tests for all provider services
- Provider factory tests
- Cost calculator tests

Documentation:
- Admin user seeder
- Model pricing seeder
- Configuration files
This commit is contained in:
wtrinkl
2025-11-18 22:18:36 +01:00
parent bef36c7ca2
commit 6573e15ba4
60 changed files with 5991 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use App\Services\LLM\ProviderFactory;
class ChatCompletionRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true; // Authorization handled by auth middleware
}
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
{
return [
'provider' => ['required', 'string', function ($attribute, $value, $fail) {
if (!ProviderFactory::isSupported($value)) {
$fail("The {$attribute} must be one of: " . implode(', ', ProviderFactory::getSupportedProviders()));
}
}],
'model' => 'required|string|max:100',
'messages' => 'required|array|min:1',
'messages.*.role' => 'required|string|in:system,user,assistant',
'messages.*.content' => 'required|string',
// Optional parameters
'temperature' => 'sometimes|numeric|min:0|max:2',
'max_tokens' => 'sometimes|integer|min:1|max:100000',
'top_p' => 'sometimes|numeric|min:0|max:1',
'frequency_penalty' => 'sometimes|numeric|min:-2|max:2',
'presence_penalty' => 'sometimes|numeric|min:-2|max:2',
'stop' => 'sometimes|array',
];
}
/**
* Get custom messages for validator errors.
*/
public function messages(): array
{
return [
'provider.required' => 'Provider is required (e.g., openai, anthropic)',
'model.required' => 'Model is required (e.g., gpt-4o-mini, claude-sonnet-4)',
'messages.required' => 'Messages array is required',
'messages.*.role.in' => 'Message role must be system, user, or assistant',
'temperature.between' => 'Temperature must be between 0 and 2',
'max_tokens.min' => 'Max tokens must be at least 1',
];
}
}