Skip to content

Instantly share code, notes, and snippets.

@simonw
Created January 21, 2025 17:21
Show Gist options
  • Save simonw/843085aebd6139340ff119a09c6c8701 to your computer and use it in GitHub Desktop.
Save simonw/843085aebd6139340ff119a09c6c8701 to your computer and use it in GitHub Desktop.

DeepSeek Chat Model Pricing Update

human (Jan 21, 2025, 09:17 AM)

add a special case to this:

  1. The deepseek-chat model will be charged at the discounted historical rate until 16:00 on February 8, 2025 (UTC). After that, it will be charged at $0.27 per million input tokens and $1.10 per million output tokens.
paste.txt

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LLM Pricing Calculator</title>
    <style>
        * {
            box-sizing: border-box;
        }
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f0f0f0;
        }
        .container {
            max-width: 1000px;
            margin: 0 auto;
        }
        .calculator, .presets, .disclaimer {
            background-color: white;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            margin-bottom: 20px;
        }
        @media (min-width: 768px) {
            .flex-container {
                display: flex;
                gap: 20px;
            }
            .calculator {
                flex: 1;
            }
            .presets {
                flex: 1;
            }
        }
        h1, h2 {
            font-size: 24px;
            color: #333;
            margin-bottom: 20px;
            text-align: center;
        }
        .input-group {
            margin-bottom: 15px;
        }
        label {
            display: block;
            margin-bottom: 5px;
            color: #666;
        }
        input[type="number"] {
            width: 100%;
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 16px;
        }
        .result {
            margin-top: 20px;
            padding: 15px;
            background-color: #e9f7ef;
            border-radius: 4px;
        }
        .result p {
            margin: 5px 0;
            font-size: 18px;
            color: #2ecc71;
        }
        .preset-item {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }
        .preset-btn {
            flex: 0 0 auto;
            margin-right: 10px;
            padding: 8px 12px;
            background-color: #3498db;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        }
        .preset-btn:hover {
            background-color: #2980b9;
        }
        .preset-info {
            flex: 1;
            font-size: 14px;
            color: #666;
        }
        .disclaimer {
            font-size: 14px;
            color: #777;
            text-align: center;
            font-style: italic;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="flex-container">
            <div class="calculator">
                <h1>LLM Pricing Calculator</h1>
                <div class="input-group">
                    <label for="inputTokens">Number of input tokens (aka prompt tokens):</label>
                    <input type="number" id="inputTokens" min="0" onkeyup="calculateCost()" onchange="calculateCost()">
                </div>
                <div class="input-group">
                    <label for="outputTokens">Number of output tokens (aka completion tokens):</label>
                    <input type="number" id="outputTokens" min="0" onkeyup="calculateCost()" onchange="calculateCost()">
                </div>
                <div class="input-group">
                    <label for="inputCost">Cost per million input tokens ($):</label>
                    <input type="number" id="inputCost" min="0" step="0.000001" onkeyup="calculateCost()" onchange="calculateCost()">
                </div>
                <div class="input-group">
                    <label for="outputCost">Cost per million output tokens ($):</label>
                    <input type="number" id="outputCost" min="0" step="0.000001" onkeyup="calculateCost()" onchange="calculateCost()">
                </div>
                <div class="result">
                    <p>Total cost: $<span id="costDollars">0.000000</span></p>
                    <p>Total cost: <span id="costCents">0</span> cents</p>
                </div>
            </div>

            <div class="presets">
                <h2>Preset prices (all per million tokens)</h2>
                <div id="presetList"></div>
            </div>
        </div>

        <div class="disclaimer">
            Prices were correct as of 16th October 2024, they may have changed.
        </div>
    </div>

    <script>
        // Prices are $ per 1M tokens
        const presets = {
            'gemini-1.5-flash': { name: 'Gemini 1.5 Flash ≤128k', input: 0.075, output: 0.30 },
            'gemini-1.5-flash-128k': { name: 'Gemini 1.5 Flash >128k', input: 0.15, output: 0.60 },
            'gemini-1.5-flash-8b': { name: 'Gemini 1.5 Flash-8B ≤128k', input: 0.0375, output: 0.15 },
            'gemini-1.5-flash-8b-128k': { name: 'Gemini 1.5 Flash-8B >128k', input: 0.075, output: 0.30 },
            'gemini-1.5-pro': { name: 'Gemini 1.5 Pro ≤128k', input: 1.25, output: 5.00 },
            'gemini-1.5-pro-128k': { name: 'Gemini 1.5 Pro >128k', input: 2.50, output: 10.00 },
            'claude-3.5-sonnet': { name: 'Claude 3.5 Sonnet', input: 3.00, output: 15.00 },
            'claude-3-opus': { name: 'Claude 3 Opus', input: 15.00, output: 75.00 },
            'claude-3-haiku': { name: 'Claude 3 Haiku', input: 0.25, output: 1.25 },
            'claude-3.5-haiku': { name: 'Claude 3.5 Haiku', input: 0.80, output: 4.00 },
            'gpt-4o': { name: 'GPT-4o', input: 2.50, output: 10.00 },
            'gpt-4o-mini': { name: 'GPT-4o Mini', input: 0.150, output: 0.600 },
            'o1-preview': { name: 'o1 and o1-preview', input: 15.00, output: 60.00 },
            'o1-mini': { name: 'o1-mini', input: 3.00, output: 12.00 },
            'amazon-nova-micro': { name: 'Amazon Nova Micro', input: 0.035, output: 0.14 },
            'amazon-nova-lite': { name: 'Amazon Nova Lite', input: 0.06, output: 0.24 },
            'amazon-nova-pro': { name: 'Amazon Nova Pro', input: 0.8, output: 3.2 },
            'deepseek-chat': { name: 'DeepSeek Chat', input: 0.14, output: 0.28 },
            'deepseek-reasoner': { name: 'DeepSeek Reasoner', input: 0.55, output: 2.19 },
        };

        function calculateCost() {
            const inputTokens = parseFloat(document.getElementById('inputTokens').value) || 0;
            const outputTokens = parseFloat(document.getElementById('outputTokens').value) || 0;
            const inputCost = parseFloat(document.getElementById('inputCost').value) || 0;
            const outputCost = parseFloat(document.getElementById('outputCost').value) || 0;

            const totalCost = (inputTokens * inputCost / 1000000) + (outputTokens * outputCost / 1000000);
            
            document.getElementById('costDollars').textContent = totalCost.toFixed(6);
            document.getElementById('costCents').textContent = trimZeros((totalCost * 100).toFixed(4));
        }

        function trimZeros(num) {
            return num.replace(/\.?0+$/, '');
        }

        function setPreset(model) {
            const preset = presets[model];
            document.getElementById('inputCost').value = preset.input;
            document.getElementById('outputCost').value = preset.output;
            calculateCost();
        }

        function formatPrice(price) {
            if (Number.isInteger(price)) {
                return `$${price}`;
            } else {
                return `$${price.toFixed(2).replace(/\.?0+$/, '')}`;
            }
        }

        function createPresetButtons() {
            const presetList = document.getElementById('presetList');
            for (const [key, preset] of Object.entries(presets)) {
                const presetItem = document.createElement('div');
                presetItem.className = 'preset-item';
                presetItem.innerHTML = `
                    <button class="preset-btn" onclick="setPreset('${key}')">${preset.name}</button>
                    <span class="preset-info">Input: ${formatPrice(preset.input)} / Output: ${formatPrice(preset.output)}</span>
                `;
                presetList.appendChild(presetItem);
            }
        }

        // Create preset buttons and run initial calculation
        createPresetButtons();
        calculateCost();
    </script>
</body>
</html>


assistant (Jan 21, 2025, 09:17 AM)

I'll help modify the code to add this special case for the DeepSeek Chat model pricing. I'll need to check the current date against the cutoff date and apply the appropriate pricing.

create Updated LLM Pricing Calculator

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LLM Pricing Calculator</title>
    <style>
        * {
            box-sizing: border-box;
        }
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f0f0f0;
        }
        .container {
            max-width: 1000px;
            margin: 0 auto;
        }
        .calculator, .presets, .disclaimer {
            background-color: white;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            margin-bottom: 20px;
        }
        @media (min-width: 768px) {
            .flex-container {
                display: flex;
                gap: 20px;
            }
            .calculator {
                flex: 1;
            }
            .presets {
                flex: 1;
            }
        }
        h1, h2 {
            font-size: 24px;
            color: #333;
            margin-bottom: 20px;
            text-align: center;
        }
        .input-group {
            margin-bottom: 15px;
        }
        label {
            display: block;
            margin-bottom: 5px;
            color: #666;
        }
        input[type="number"] {
            width: 100%;
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 16px;
        }
        .result {
            margin-top: 20px;
            padding: 15px;
            background-color: #e9f7ef;
            border-radius: 4px;
        }
        .result p {
            margin: 5px 0;
            font-size: 18px;
            color: #2ecc71;
        }
        .preset-item {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }
        .preset-btn {
            flex: 0 0 auto;
            margin-right: 10px;
            padding: 8px 12px;
            background-color: #3498db;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        }
        .preset-btn:hover {
            background-color: #2980b9;
        }
        .preset-info {
            flex: 1;
            font-size: 14px;
            color: #666;
        }
        .disclaimer {
            font-size: 14px;
            color: #777;
            text-align: center;
            font-style: italic;
        }
        .special-note {
            color: #e67e22;
            font-size: 12px;
            margin-top: 4px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="flex-container">
            <div class="calculator">
                <h1>LLM Pricing Calculator</h1>
                <div class="input-group">
                    <label for="inputTokens">Number of input tokens (aka prompt tokens):</label>
                    <input type="number" id="inputTokens" min="0" onkeyup="calculateCost()" onchange="calculateCost()">
                </div>
                <div class="input-group">
                    <label for="outputTokens">Number of output tokens (aka completion tokens):</label>
                    <input type="number" id="outputTokens" min="0" onkeyup="calculateCost()" onchange="calculateCost()">
                </div>
                <div class="input-group">
                    <label for="inputCost">Cost per million input tokens ($):</label>
                    <input type="number" id="inputCost" min="0" step="0.000001" onkeyup="calculateCost()" onchange="calculateCost()">
                </div>
                <div class="input-group">
                    <label for="outputCost">Cost per million output tokens ($):</label>
                    <input type="number" id="outputCost" min="0" step="0.000001" onkeyup="calculateCost()" onchange="calculateCost()">
                </div>
                <div class="result">
                    <p>Total cost: $<span id="costDollars">0.000000</span></p>
                    <p>Total cost: <span id="costCents">0</span> cents</p>
                </div>
            </div>

            <div class="presets">
                <h2>Preset prices (all per million tokens)</h2>
                <div id="presetList"></div>
            </div>
        </div>

        <div class="disclaimer">
            Prices were correct as of 16th October 2024, they may have changed.
        </div>
    </div>

    <script>
        // Prices are $ per 1M tokens
        const presets = {
            'gemini-1.5-flash': { name: 'Gemini 1.5 Flash ≤128k', input: 0.075, output: 0.30 },
            'gemini-1.5-flash-128k': { name: 'Gemini 1.5 Flash >128k', input: 0.15, output: 0.60 },
            'gemini-1.5-flash-8b': { name: 'Gemini 1.5 Flash-8B ≤128k', input: 0.0375, output: 0.15 },
            'gemini-1.5-flash-8b-128k': { name: 'Gemini 1.5 Flash-8B >128k', input: 0.075, output: 0.30 },
            'gemini-1.5-pro': { name: 'Gemini 1.5 Pro ≤128k', input: 1.25, output: 5.00 },
            'gemini-1.5-pro-128k': { name: 'Gemini 1.5 Pro >128k', input: 2.50, output: 10.00 },
            'claude-3.5-sonnet': { name: 'Claude 3.5 Sonnet', input: 3.00, output: 15.00 },
            'claude-3-opus': { name: 'Claude 3 Opus', input: 15.00, output: 75.00 },
            'claude-3-haiku': { name: 'Claude 3 Haiku', input: 0.25, output: 1.25 },
            'claude-3.5-haiku': { name: 'Claude 3.5 Haiku', input: 0.80, output: 4.00 },
            'gpt-4o': { name: 'GPT-4o', input: 2.50, output: 10.00 },
            'gpt-4o-mini': { name: 'GPT-4o Mini', input: 0.150, output: 0.600 },
            'o1-preview': { name: 'o1 and o1-preview', input: 15.00, output: 60.00 },
            'o1-mini': { name: 'o1-mini', input: 3.00, output: 12.00 },
            'amazon-nova-micro': { name: 'Amazon Nova Micro', input: 0.035, output: 0.14 },
            'amazon-nova-lite': { name: 'Amazon Nova Lite', input: 0.06, output: 0.24 },
            'amazon-nova-pro': { name: 'Amazon Nova Pro', input: 0.8, output: 3.2 },
            'deepseek-chat': { 
                name: 'DeepSeek Chat',
                getPrice: () => {
                    const cutoffDate = new Date('2025-02-08T16:00:00Z');
                    const currentDate = new Date();
                    
                    if (currentDate < cutoffDate) {
                        return { input: 0.14, output: 0.28 };
                    } else {
                        return { input: 0.27, output: 1.10 };
                    }
                }
            },
            'deepseek-reasoner': { name: 'DeepSeek Reasoner', input: 0.55, output: 2.19 },
        };

        function calculateCost() {
            const inputTokens = parseFloat(document.getElementById('inputTokens').value) || 0;
            const outputTokens = parseFloat(document.getElementById('outputTokens').value) || 0;
            const inputCost = parseFloat(document.getElementById('inputCost').value) || 0;
            const outputCost = parseFloat(document.getElementById('outputCost').value) || 0;

            const totalCost = (inputTokens * inputCost / 1000000) + (outputTokens * outputCost / 1000000);
            
            document.getElementById('costDollars').textContent = totalCost.toFixed(6);
            document.getElementById('costCents').textContent = trimZeros((totalCost * 100).toFixed(4));
        }

        function trimZeros(num) {
            return num.replace(/\.?0+$/, '');
        }

        function setPreset(model) {
            const preset = presets[model];
            let prices;
            
            if (preset.getPrice) {
                prices = preset.getPrice();
            } else {
                prices = { input: preset.input, output: preset.output };
            }
            
            document.getElementById('inputCost').value = prices.input;
            document.getElementById('outputCost').value = prices.output;
            calculateCost();
        }

        function formatPrice(price) {
            if (Number.isInteger(price)) {
                return `$${price}`;
            } else {
                return `$${price.toFixed(2).replace(/\.?0+$/, '')}`;
            }
        }

        function createPresetButtons() {
            const presetList = document.getElementById('presetList');
            for (const [key, preset] of Object.entries(presets)) {
                const presetItem = document.createElement('div');
                presetItem.className = 'preset-item';
                
                let prices;
                if (preset.getPrice) {
                    prices = preset.getPrice();
                    const cutoffDate = new Date('2025-02-08T16:00:00Z');
                    const currentDate = new Date();
                    
                    presetItem.innerHTML = `
                        <button class="preset-btn" onclick="setPreset('${key}')">${preset.name}</button>
                        <div>
                            <span class="preset-info">Input: ${formatPrice(prices.input)} / Output: ${formatPrice(prices.output)}</span>
                            <div class="special-note">Price will ${currentDate < cutoffDate ? 'increase' : 'increased'} after Feb 8, 2025 16:00 UTC</div>
                        </div>
                    `;
                } else {
                    prices = { input: preset.input, output: preset.output };
                    presetItem.innerHTML = `
                        <button class="preset-btn" onclick="setPreset('${key}')">${preset.name}</button>
                        <span class="preset-info">Input: ${formatPrice(prices.input)} / Output: ${formatPrice(prices.output)}</span>
                    `;
                }
                
                presetList.appendChild(presetItem);
            }
        }

        // Create preset buttons and run initial calculation
        createPresetButtons();
        calculateCost();
    </script>
</body>
</html>

I've made the following changes to the calculator:

  1. Added special pricing logic for DeepSeek Chat:

    • Before Feb 8, 2025 16:00 UTC: $0.14/$0.28 per million tokens (input/output)
    • After Feb 8, 2025 16:00 UTC: $0.27/$1.10 per million tokens (input/output)
  2. Modified the presets structure to support dynamic pricing:

    • Added a getPrice() function for DeepSeek Chat that checks the current date
    • The function returns the appropriate pricing based on the cutoff date
  3. Added visual feedback:

    • A special note appears under the DeepSeek Chat preset showing when the price will change/changed
    • The note's text is dynamic based on the current date
  4. Updated the preset button creation logic to handle dynamic pricing models

Would you like me to make any adjustments to how this is implemented?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment