- Any-LLM Gateway setup with Docker Compose - Laravel 11 admin interface with Livewire - Dashboard with usage statistics and charts - Gateway Users management with budget tracking - API Keys management with revocation - Budget templates with assignment - Usage Logs with filtering and CSV export - Model Pricing management with calculator - PostgreSQL database integration - Complete authentication system for admins
139 lines
7.3 KiB
PHP
139 lines
7.3 KiB
PHP
<x-app-layout>
|
||
<x-slot name="header">
|
||
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||
Cost Calculator
|
||
</h2>
|
||
</x-slot>
|
||
|
||
<div class="py-12">
|
||
<div class="max-w-3xl mx-auto sm:px-6 lg:px-8">
|
||
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
|
||
<div class="p-6">
|
||
<p class="text-sm text-gray-600 mb-6">
|
||
Calculate the cost of API requests based on token usage and model pricing.
|
||
</p>
|
||
|
||
<div class="space-y-4">
|
||
<div>
|
||
<label for="calc_model" class="block text-sm font-medium text-gray-700 mb-1">
|
||
Select Model *
|
||
</label>
|
||
<select id="calc_model"
|
||
class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||
<option value="">Choose a model...</option>
|
||
@foreach($models as $model)
|
||
<option value="{{ $model->model_key }}"
|
||
data-input-price="{{ $model->input_price_per_million }}"
|
||
data-output-price="{{ $model->output_price_per_million }}">
|
||
{{ $model->model_key }}
|
||
</option>
|
||
@endforeach
|
||
</select>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<label for="input_tokens" class="block text-sm font-medium text-gray-700 mb-1">
|
||
Input Tokens
|
||
</label>
|
||
<input type="number" id="input_tokens" value="1000" min="0"
|
||
class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||
</div>
|
||
|
||
<div>
|
||
<label for="output_tokens" class="block text-sm font-medium text-gray-700 mb-1">
|
||
Output Tokens
|
||
</label>
|
||
<input type="number" id="output_tokens" value="500" min="0"
|
||
class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
||
</div>
|
||
</div>
|
||
|
||
<button onclick="calculateCost()"
|
||
class="w-full bg-blue-500 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded">
|
||
Calculate Cost
|
||
</button>
|
||
|
||
<div id="result" class="hidden">
|
||
<div class="bg-gray-50 rounded-lg p-6 space-y-3">
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-sm text-gray-600">Model:</span>
|
||
<span id="result_model" class="text-sm font-medium text-gray-900"></span>
|
||
</div>
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-sm text-gray-600">Input Tokens:</span>
|
||
<span id="result_input_tokens" class="text-sm font-medium text-gray-900"></span>
|
||
</div>
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-sm text-gray-600">Output Tokens:</span>
|
||
<span id="result_output_tokens" class="text-sm font-medium text-gray-900"></span>
|
||
</div>
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-sm text-gray-600">Total Tokens:</span>
|
||
<span id="result_total_tokens" class="text-sm font-medium text-gray-900"></span>
|
||
</div>
|
||
<div class="border-t pt-3 mt-3">
|
||
<div class="flex justify-between items-center">
|
||
<span class="text-lg font-semibold text-gray-900">Total Cost:</span>
|
||
<span id="result_cost" class="text-2xl font-bold text-green-600"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mt-6 bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||
<h4 class="font-semibold text-blue-900 mb-2">💡 Quick Reference</h4>
|
||
<p class="text-sm text-blue-800">
|
||
Prices are calculated per million tokens. For example, if input price is $3.00/M and you use 1,000 tokens,
|
||
the cost would be: (1,000 / 1,000,000) × $3.00 = $0.003
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function calculateCost() {
|
||
const modelKey = document.getElementById('calc_model').value;
|
||
const inputTokens = parseInt(document.getElementById('input_tokens').value) || 0;
|
||
const outputTokens = parseInt(document.getElementById('output_tokens').value) || 0;
|
||
|
||
if (!modelKey) {
|
||
alert('Please select a model');
|
||
return;
|
||
}
|
||
|
||
// Get pricing from selected option
|
||
const select = document.getElementById('calc_model');
|
||
const option = select.options[select.selectedIndex];
|
||
const inputPrice = parseFloat(option.dataset.inputPrice);
|
||
const outputPrice = parseFloat(option.dataset.outputPrice);
|
||
|
||
// Calculate cost
|
||
const inputCost = (inputTokens / 1000000) * inputPrice;
|
||
const outputCost = (outputTokens / 1000000) * outputPrice;
|
||
const totalCost = inputCost + outputCost;
|
||
const totalTokens = inputTokens + outputTokens;
|
||
|
||
// Display results
|
||
document.getElementById('result_model').textContent = modelKey;
|
||
document.getElementById('result_input_tokens').textContent = inputTokens.toLocaleString();
|
||
document.getElementById('result_output_tokens').textContent = outputTokens.toLocaleString();
|
||
document.getElementById('result_total_tokens').textContent = totalTokens.toLocaleString();
|
||
document.getElementById('result_cost').textContent = '$' + totalCost.toFixed(6);
|
||
|
||
document.getElementById('result').classList.remove('hidden');
|
||
}
|
||
|
||
// Allow Enter key to calculate
|
||
document.getElementById('input_tokens').addEventListener('keypress', function(e) {
|
||
if (e.key === 'Enter') calculateCost();
|
||
});
|
||
document.getElementById('output_tokens').addEventListener('keypress', function(e) {
|
||
if (e.key === 'Enter') calculateCost();
|
||
});
|
||
</script>
|
||
</x-app-layout>
|