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:
90
laravel-app/app/Services/LLM/Providers/MistralProvider.php
Normal file
90
laravel-app/app/Services/LLM/Providers/MistralProvider.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\LLM\Providers;
|
||||
|
||||
use App\Models\ModelPricing;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class MistralProvider extends AbstractProvider
|
||||
{
|
||||
protected string $baseUrl = 'https://api.mistral.ai/v1';
|
||||
|
||||
protected function buildRequest(array $messages, array $options): array
|
||||
{
|
||||
return array_filter([
|
||||
'model' => $options['model'] ?? 'mistral-small-latest',
|
||||
'messages' => $messages,
|
||||
'temperature' => $options['temperature'] ?? 0.7,
|
||||
'max_tokens' => $options['max_tokens'] ?? null,
|
||||
'top_p' => $options['top_p'] ?? null,
|
||||
'stream' => false,
|
||||
'safe_prompt' => $options['safe_prompt'] ?? false,
|
||||
'random_seed' => $options['random_seed'] ?? null,
|
||||
], fn($value) => $value !== null && $value !== false);
|
||||
}
|
||||
|
||||
protected function getAuthHeaders(): array
|
||||
{
|
||||
return [
|
||||
'Authorization' => 'Bearer ' . $this->apiKey,
|
||||
'Content-Type' => 'application/json',
|
||||
];
|
||||
}
|
||||
|
||||
public function chatCompletion(array $messages, array $options = []): array
|
||||
{
|
||||
$data = $this->buildRequest($messages, $options);
|
||||
return $this->makeRequest('/chat/completions', $data);
|
||||
}
|
||||
|
||||
public function normalizeResponse(array $response): array
|
||||
{
|
||||
return [
|
||||
'id' => $response['id'] ?? null,
|
||||
'model' => $response['model'] ?? null,
|
||||
'content' => $response['choices'][0]['message']['content'] ?? '',
|
||||
'role' => $response['choices'][0]['message']['role'] ?? 'assistant',
|
||||
'finish_reason' => $response['choices'][0]['finish_reason'] ?? null,
|
||||
'usage' => [
|
||||
'prompt_tokens' => $response['usage']['prompt_tokens'] ?? 0,
|
||||
'completion_tokens' => $response['usage']['completion_tokens'] ?? 0,
|
||||
'total_tokens' => $response['usage']['total_tokens'] ?? 0,
|
||||
],
|
||||
'raw_response' => $response,
|
||||
];
|
||||
}
|
||||
|
||||
public function calculateCost(int $promptTokens, int $completionTokens, string $model): float
|
||||
{
|
||||
$cacheKey = "pricing:mistral:{$model}";
|
||||
|
||||
$pricing = Cache::remember($cacheKey, 3600, function () use ($model) {
|
||||
return ModelPricing::where('provider', 'mistral')
|
||||
->where('model', $model)
|
||||
->where('is_active', true)
|
||||
->first();
|
||||
});
|
||||
|
||||
if (!$pricing) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
$promptCost = ($promptTokens / 1_000_000) * $pricing->input_price_per_million;
|
||||
$completionCost = ($completionTokens / 1_000_000) * $pricing->output_price_per_million;
|
||||
|
||||
return round($promptCost + $completionCost, 6);
|
||||
}
|
||||
|
||||
public function getSupportedModels(): array
|
||||
{
|
||||
return [
|
||||
'mistral-large-latest',
|
||||
'mistral-medium-latest',
|
||||
'mistral-small-latest',
|
||||
'mistral-tiny',
|
||||
'open-mistral-7b',
|
||||
'open-mixtral-8x7b',
|
||||
'open-mixtral-8x22b',
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user