#!/usr/bin/env python3 """Ф1 — ЦЕНЫ КАНДИДАТОВ, снятые с прайс-страниц вендоров 06.08.2026. Почему отдельным файлом с датой и URL. Гардрейл CLAUDE.md: цены берутся ТОЛЬКО с прайс-страницы вендора, не по памяти; урок календаря D39.61: «слаг живой ≠ модель та же». Смета Ф1/Ф2 стоит на этих числах, и если через неделю они разъедутся, должно быть видно, ЧТО именно устарело и откуда бралось. Порядок в кортеже: (вход, кэш-хит, выход) долларов за 1M токенов. ⚠ ЧТО ЗДЕСЬ НЕ ПРОВЕРЕНО ЖИВЬЁМ: цена — это ЗАЯВЛЕНИЕ вендора, а не замер. Реальная стоимость вызова считается из `usage` и может разойтись с прайсом (кэш, тарификация размышления, батч-тир). Расхождение прайса с леджером — само по себе находка, и Ф1 обязана его напечатать. """ from __future__ import annotations # (base_url, env-ключ, вход, кэш, выход, механизм гашения размышления, источник цены) CANDIDATES: dict[str, tuple] = { # DeepSeek — цены пост-катовера, сверены 25.07 (quirks 00, строка эндпоинтов). "deepseek-v4-flash": ("https://api.deepseek.com/v1", "DEEPSEEK_API_KEY", 0.14, 0.0028, 0.28, None, "quirks 00 (25.07, вендор-прайс)"), "deepseek-v4-pro": ("https://api.deepseek.com/v1", "DEEPSEEK_API_KEY", 0.435, 0.003625, 0.87, None, "quirks 00 (25.07, вендор-прайс)"), # Z.AI — docs.z.ai/guides/overview/pricing, снято 06.08. "glm-5": ("https://api.z.ai/api/paas/v4", "ZAI_API_KEY", 1.00, 0.20, 3.20, "extra_body_disable", "docs.z.ai/pricing 06.08"), "glm-5-turbo": ("https://api.z.ai/api/paas/v4", "ZAI_API_KEY", 1.20, 0.24, 4.00, "extra_body_disable", "docs.z.ai/pricing 06.08"), "glm-5.2": ("https://api.z.ai/api/paas/v4", "ZAI_API_KEY", 1.40, 0.26, 4.40, "extra_body_disable", "docs.z.ai/pricing 06.08"), "glm-4.7": ("https://api.z.ai/api/paas/v4", "ZAI_API_KEY", 0.60, 0.11, 2.20, "extra_body_disable", "docs.z.ai/pricing 06.08"), # xAI — docs.x.ai/docs/models, снято 06.08. Тариф <200k токенов (наши единицы много меньше). "grok-4.3": ("https://api.x.ai/v1", "XAI_API_KEY", 1.25, 0.20, 2.50, "effort_none", "docs.x.ai/models 06.08"), "grok-4.5": ("https://api.x.ai/v1", "XAI_API_KEY", 2.00, 0.30, 6.00, "effort_none", "docs.x.ai/models 06.08 (НОВЫЙ жилец)"), # OpenAI — прайс сверен живьём 05.08 (эксп-20 §1.3), изменений против 04.08 не было. "gpt-5.6-luna": ("https://api.openai.com/v1", "OPENAI_API_KEY", 0.20, 0.02, 1.20, "effort_none", "эксп-20 §1.3 (05.08, вендор-прайс)"), "gpt-5.6-terra": ("https://api.openai.com/v1", "OPENAI_API_KEY", 2.00, 0.20, 12.00, "effort_none", "эксп-20 §1.3 (05.08, вендор-прайс)"), # Gemini — ai.google.dev/gemini-api/docs/pricing, снято 06.08. Кэш-цена не выделена. "gemini-3.6-flash": ("https://generativelanguage.googleapis.com/v1beta/openai", "GEMINI_API_KEY", 1.50, 1.50, 7.50, "thinking_budget", "ai.google.dev/pricing 06.08 (НОВЫЙ жилец)"), "gemini-3.1-flash-lite": ("https://generativelanguage.googleapis.com/v1beta/openai", "GEMINI_API_KEY", 0.25, 0.25, 1.50, "thinking_budget", "ai.google.dev/pricing 06.08"), "gemini-3.1-pro-preview": ("https://generativelanguage.googleapis.com/v1beta/openai", "GEMINI_API_KEY", 2.00, 2.00, 12.00, "mandatory", "ai.google.dev/pricing 06.08"), # Kimi — platform.kimi.ai/docs/pricing/chat-k3, снято 06.08. Самый дорогой выход ростера. "kimi-k3": ("https://api.moonshot.ai/v1", "KIMI_API_KEY", 3.00, 0.30, 15.00, None, "platform.kimi.ai/pricing 06.08 (НОВЫЙ жилец)"), # Mistral — mistral.ai/pricing, снято 06.08. Кэш-тариф не опубликован ⇒ равен входу. "mistral-large-latest": ("https://api.mistral.ai/v1", "MISTRAL_API_KEY", 2.00, 2.00, 6.00, None, "mistral.ai/pricing 06.08"), } # Учёт РАЗМЫШЛЕНИЯ в биллинге различается по провайдерам, и это не деталь, а деньги. # subset — размышление ВНУТРИ completion_tokens (DeepSeek, OpenAI, Z.AI): считать нечего. # additive — размышление СВЕРХ completion (xAI): billed = completion + reasoning. # Источник: quirks 00, строка grok — «reasoning у xAI аддитивен к completion (billed = # completion+reasoning)». ⚠ Поймано исполнением: скрин показал у grok-4.5 reasoning 3605 при # completion 1737, то есть размышление БОЛЬШЕ ответа — при subset-формуле это невозможно, и # первая редакция занижала цену grok примерно втрое. # additive_total — размышление видно ТОЛЬКО в total_tokens (Gemini): OpenAI-совместимый слой # Google отдаёт reasoning_tokens=0 и НЕ кладёт thinking в completion, поэтому оплаченный # выход = total − prompt. Источник: quirks 00 §D22.3 — «иначе недоучёт 146×/вызов». # ⚠ Класс добавлен 07.08 по адверсариальному ревью: прошлая редакция знала только subset и # additive, gemini падал в subset, и его размышление не оплачивалось в леджере вовсе. Величину # недоучёта прошлого прогона восстановить НЕЛЬЗЯ: total_tokens тогда не персистился. REASONING_BILLING = {"grok-4.3": "additive", "grok-4.5": "additive", "gemini-3.6-flash": "additive_total", "gemini-3.1-flash-lite": "additive_total", "gemini-3.1-pro-preview": "additive_total"} def billed_output(model: str, completion_tokens: int, reasoning_tokens: int, total_tokens: int = 0, prompt_tokens: int = 0) -> int: """Сколько выходных токенов реально тарифицируется.""" mode = REASONING_BILLING.get(model) if mode == "additive": return completion_tokens + reasoning_tokens if mode == "additive_total": # Пол — обычная формула: если total не записан (старый артефакт), не занижаем молча, # но и не выдумываем. Отсутствие total_tokens видно по равенству двух путей. return max(total_tokens - prompt_tokens, completion_tokens + reasoning_tokens) return completion_tokens def cost(model: str, prompt_tokens: int, cached: int, completion_tokens: int, reasoning_tokens: int = 0, total_tokens: int = 0) -> float: """Цена вызова по прайсу. Кэшированные токены тарифицируются отдельной ставкой.""" _, _, pin, pcache, pout, _, _ = CANDIDATES[model] out = billed_output(model, completion_tokens, reasoning_tokens, total_tokens, prompt_tokens) return ((prompt_tokens - cached) / 1e6 * pin + cached / 1e6 * pcache + out / 1e6 * pout) def out_price_order() -> list[str]: """Кандидаты по цене ВЫХОДА — она доминирует в наших ролях (размышление биллится как выход).""" return sorted(CANDIDATES, key=lambda m: CANDIDATES[m][4]) if __name__ == "__main__": print(f"{'модель':26s}{'вход':>8s}{'кэш':>8s}{'выход':>8s} источник") print("-" * 86) for m in out_price_order(): _, _, pin, pc, pout, _, src = CANDIDATES[m] print(f"{m:26s}{pin:8.3f}{pc:8.3f}{pout:8.2f} {src}")