1.7 · Скрипт: temperature, токены, стоимость
Неделя 1 · Основы LLM · ⏱ ~4 ч · Практика
Зачем это AI-инженеру
Заголовок раздела «Зачем это AI-инженеру»Продукт на LLM платит за каждый токен, и счёт растёт незаметно: длинный системный промпт × тысячи запросов × история диалога. Инженер, который с первого дня видит цену запроса, принимает другие решения (короче промпт, дешевле модель, кэш). Второй вопрос — случайность: на собеседовании почти наверняка спросят «почему модель отвечает по-разному на одно и то же и как это контролировать».
В главе 1.6 (гл. 1.6) мы видели в каждом ответе поле usage и заметили, что ответы на один вопрос различаются. Здесь разбираемся в обоих: из чего складываются токены и их цена и откуда берётся разброс. Обе темы начинаются с одного понятия — токена.
Что такое токен
Заголовок раздела «Что такое токен»В главе 1.5 (гл. 1.5) токен появился как единица, в которой считают цену и контекст. Теперь посмотрим, как текст на них режется. Модель видит не буквы и не слова, а токены — куски текста из фиксированного словаря (обычно 100–200 тыс. элементов). Словарь строится алгоритмом BPE (Byte Pair Encoding): начинают с байтов и многократно склеивают самые частые пары. Поэтому:
- частые английские слова — один токен (
the,price); - редкие слова режутся на куски (
deliveryможет быть одним токеном, адоставка— тремя-четырьмя); - пробел обычно приклеен к началу слова;
- числа режутся непредсказуемо (
12345.67— несколько токенов).
"Delivery is free today" → [Delivery][ is][ free][ today] ≈ 4 токена"Доставка бесплатная" → [Д][ост][авка][ бес][платная] ≈ 5+ токенов(Разбиение условное — у каждого токенизатора своё.)
Следствия, которые важны на практике:
- Русский текст «дороже». Словари токенизаторов исторически оптимизировались под английский; та же мысль по-русски обычно занимает заметно больше токенов. Насколько — измерим в практике.
- Модели плохо считают буквы («сколько r в strawberry»): она не видит букв, она видит токены.
- У каждого провайдера свой токенизатор.
tiktokenсчитает токены для моделей OpenAI, и только для них. Для Claude нужен эндпоинт подсчёта токенов Anthropic (client.messages.count_tokens(...)) или полеusageв ответе. Даже у разных поколений Claude токенизаторы различаются — при смене модели число токенов на тех же текстах может измениться.
Грубое правило для английского — ~4 символа на токен; для русского отношение хуже. Но правило — для прикидки на салфетке; в коде считаем точно.
Откуда берётся случайность
Заголовок раздела «Откуда берётся случайность»Модель генерирует ответ по одному токену. На каждом шаге она выдаёт не слово, а оценку для каждого токена словаря — числа, которые называют логитами (чем больше, тем вероятнее токен). Функция softmax превращает логиты в распределение вероятностей по всему словарю: «следующий токен mug — 41%, cup — 32%, teapot — 9%, …». Дальше токен выбирается — это и есть сэмплирование. Выбранный токен дописывается, шаг повторяется.
logits ──► softmax(logits / T) ──► [top_p-обрезка] ──► случайный выбор ──► токен- temperature (T) делит логиты перед softmax. T → 0: распределение становится «острым», почти всегда берётся самый вероятный токен (greedy). T = 1: исходное распределение. T > 1: «плоское», чаще выпадают маловероятные токены — больше разнообразия и больше бреда.
- top_p (nucleus sampling): берём минимальный набор самых вероятных токенов, сумма вероятностей которых ≥ p, остальные отбрасываем. top_p = 0.9 отрезает «длинный хвост» странных вариантов.
- top_k: оставить только k самых вероятных токенов.
Все три параметра вместе называют параметрами сэмплирования. Мини-пример на чистом Python (без API, просто чтобы почувствовать):
import math, randomfrom collections import Counter
logits = {"mug": 2.0, "cup": 1.7, "teapot": 0.5, "rocket": -1.0}
def sample(logits: dict[str, float], t: float) -> str: if t == 0: return max(logits, key=logits.get) # greedy exps = {k: math.exp(v / t) for k, v in logits.items()} total = sum(exps.values()) r, acc = random.random(), 0.0 for k, e in exps.items(): acc += e / total if r <= acc: return k return k
for t in (0, 0.5, 1.0, 2.0): print(t, Counter(sample(logits, t) for _ in range(1000)))Важная оговорка: temperature 0 — не гарантия детерминизма. Из-за параллельных вычислений на GPU, батчинга запросов и обновлений моделей одинаковый запрос иногда даёт чуть разные ответы. Воспроизводимость в продакшене обеспечивают не temperature, а логи, фиксированная версия модели и evals.
Важная новость 2025–2026: temperature уходит из API
Заголовок раздела «Важная новость 2025–2026: temperature уходит из API»Классическая ручка случайности — temperature, но у крупных облачных провайдеров её всё чаще нет. Это то, чего нет в старых туториалах. У reasoning-моделей (которые «думают» перед ответом) сэмплирование управляется самим провайдером:
- Anthropic: новые модели Claude принимают только значения по умолчанию, а в версии API
2026-10-21запрос сtemperature,top_pилиtop_kвозвращает 400 на любой модели; новые Python SDK эти параметры уже не принимают. Вместо них качество/стоимость регулируют параметромeffort(насколько глубоко модель думает) и промптом. - OpenAI: reasoning-модели (семейства o-series и GPT-5) тоже не принимают произвольный
temperature; его поддерживают не-reasoning модели. Какие именно — видно на странице конкретной модели.
Зачем тогда учить temperature? Потому что (1) он встречается во всех open-weight моделях (Llama, Qwen, Mistral через Ollama/vLLM) и во многих чужих проектах; (2) понимание сэмплирования объясняет «почему модель иногда отвечает иначе» — это никуда не делось, просто ручку убрали; (3) это вопрос с собеседования. Практический вывод для эксперимента: берём модель, которая параметр ещё принимает (не-reasoning модель OpenAI или локальную модель), и проверяем в документации, что параметр поддерживается.
Когда низкая / когда высокая случайность (классическое правило; на моделях без ручки того же добиваются промптом и схемой):
| Задача | Случайность | Почему |
|---|---|---|
| Извлечение данных, классификация, JSON | низкая (T≈0) | Нужен один правильный ответ, разнообразие = ошибки |
| Код, SQL | низкая | Синтаксис не любит креатива |
| Ответы на вопросы по документам | низкая–средняя | Точность важнее стиля |
| Идеи, нейминг, тексты для постов | высокая (0.7–1.0) | Нужно разнообразие вариантов |
| Генерация синтетических тестовых данных | высокая | Нужно покрытие разных случаев |
Как устроена цена
Заголовок раздела «Как устроена цена»Вторая тема главы — деньги. Мы уже знаем, что usage в ответе делит токены на input и output; цена считается по ним же. Провайдеры берут деньги за миллион токенов (MTok), отдельно за вход и выход:
cost = input_tokens / 1e6 * price_in + output_tokens / 1e6 * price_outНапример, для модели с ценой $1 / $5 за MTok запрос с 2 000 input и 500 output токенов стоит 2000/1e6·1 + 500/1e6·5 = $0.002 + $0.0025 = $0.0045. Примерно столько стоит ответ на одно сообщение в поддержку магазина (системный промпт, правила доставки, вопрос клиента — и короткий ответ); 1000 таких сообщений — $4.50. Копейки — пока не умножим на 100 000 запросов в день.
Нюансы, которые ломают наивную формулу:
- Output в несколько раз дороже input (типично в 4–5 раз). Генерация последовательная и дорогая для GPU, чтение — параллельное.
- Размышления (thinking/reasoning) оплачиваются как output, даже если их не видно в ответе. Reasoning-модель на простой вопрос может «подумать» на тысячу токенов.
- Кэш промптов: провайдер запоминает начало (префикс) недавних запросов, и повторное чтение этого префикса стоит дешевле. Прочитанные из кэша input-токены стоят ~10% цены, а запись в кэш — дороже обычного (глава 2.7 (гл. 2.7)). В
usageэто отдельные поля (cache_read_input_tokens,cache_creation_input_tokensу Anthropic;cached_tokensв деталях usage у OpenAI). - Тарифы бывают ступенчатые: у некоторых моделей цена за токен выше, если промпт длиннее порога (например, 100K или 200K токенов).
- Batch API — обычно −50% за асинхронную обработку: запросы отправляются пачкой, а результаты приходят в течение часов (глава 2.7 (гл. 2.7)).
- Цены меняются. Никогда не зашиваем их глубоко в код без даты. Таблица цен живёт в одном месте с комментарием «проверено YYYY-MM-DD» и ссылкой на страницу pricing.
Функция, которая будет жить во всех наших проектах:
from dataclasses import dataclass
@dataclass(frozen=True)class Price: input: float # USD per 1M input tokens output: float # USD per 1M output tokens cache_read: float | None = None cache_write: float | None = None
# Source: provider pricing pages, checked on YYYY-MM-DD. Fill in yourself.PRICES: dict[str, Price] = { # "claude-haiku-5-5": Price(input=..., output=...), # "gpt-5-mini": Price(input=..., output=...),}
def estimate_cost(model: str, input_tokens: int, output_tokens: int, cache_read_tokens: int = 0, cache_write_tokens: int = 0) -> float: p = PRICES[model] # KeyError on purpose: unknown model must not cost $0 ...Обратим внимание на KeyError «нарочно»: если функция для неизвестной модели вернёт 0, можно месяц думать, что всё бесплатно.
Договоримся о смысле аргументов: input_tokens — вход, прочитанный не из кэша (по полной цене), cache_read_tokens и cache_write_tokens — части входа, прочитанные из кэша и записанные в него. Провайдеры раскладывают usage по-разному, и перед вызовом приводим их поля к этой схеме: у Anthropic input_tokens уже не включает кэш, у OpenAI cached_tokens входит в общий input_tokens и его нужно вычесть, у DeepSeek промах и попадание даны отдельно (ниже).
Прогноз до запроса
Заголовок раздела «Прогноз до запроса»estimate_cost считает по usage, то есть после запроса. Иногда стоимость нужна заранее (например, «влезет ли этот документ в контекст и бюджет»):
- Anthropic:
client.messages.count_tokens(model=..., system=..., messages=[...]).input_tokens— точное число input-токенов для конкретной модели, без генерации. - OpenAI:
tiktoken— локально, без сети:tiktoken.encoding_for_model(model)илиtiktoken.get_encoding("o200k_base")для современных моделей; число токенов —len(enc.encode(text)). Служебные токены разметки сообщений добавляют немного сверху.
Output заранее не известен — его оценивают по истории (медиана output_tokens на таких запросах) и ограничивают max_tokens.
DeepSeek и Ollama: как это сделать у нас
Заголовок раздела «DeepSeek и Ollama: как это сделать у нас»Хорошая новость: эксперимент с temperature, который на Claude уже невозможен, на DeepSeek и Ollama делается честно. А у обоих можно даже заглянуть в само распределение вероятностей — через logprobs, логарифмы вероятностей выбранного токена и его ближайших альтернатив. Дальше идём по темам теории: случайность, цена, подсчёт токенов.
Temperature у DeepSeek: работает, но не всегда
Заголовок раздела «Temperature у DeepSeek: работает, но не всегда»(По API Reference и гайду Thinking Mode на 13.11.2026 — стоит перепроверить.)
temperatureот 0 до 2, по умолчанию 1 — но действует только в режиме без размышления. В режиме размышления (а он включён по умолчанию!)temperature,presence_penalty,frequency_penaltyмолча игнорируются: ошибки нет, эффекта нет. Сравним с Claude, где тот же запрос даёт 400 — громкая ошибка лучше тихой, тут легко «провести эксперимент» и намерить шум.top_pуdeepseek-flashбез размышления зафиксирован на 1.0 (переданное значение игнорируется); уdeepseek-v4-proбез размышления — работает. Ручкиtop_kнет.logprobs=Trueиtop_logprobs(до 20) — есть: можно посмотреть альтернативы для каждого токена ответа.
import math # deepseek = OpenAI(...) client from chapter 1.6
r = deepseek.chat.completions.create( model="deepseek-flash", messages=[{"role": "user", "content": "Name a support bot for a small online home goods shop. Name only."}], temperature=1.0, max_tokens=20, logprobs=True, top_logprobs=5, extra_body={"thinking": {"type": "disabled"}}, # otherwise temperature has no effect)first = r.choices[0].logprobs.content[0]for alt in first.top_logprobs: print(repr(alt.token), round(math.exp(alt.logprob), 3)) # real next-token distributionTemperature у Ollama: полный контроль
Заголовок раздела «Temperature у Ollama: полный контроль»Локальная модель принимает всё классическое: temperature, top_p, top_k, seed (в нативном API — в options; через OpenAI-совместимый эндпоинт — temperature, top_p, seed). seed + одинаковый запрос на той же машине обычно дают одинаковый ответ — удобно для экспериментов, хотя и это не железная гарантия. Нативный /api/chat тоже умеет logprobs / top_logprobs (в OpenAI-совместимом режиме logprobs не поддерживается).
import ollama # official client from chapter 1.6
resp = ollama.chat( model="qwen3:4b", messages=[{"role": "user", "content": "Name a support bot for a small online home goods shop. Name only."}], think=False, options={"temperature": 1.0, "top_k": 40, "seed": 7},)У «думающих» локальных моделей (qwen3 и др.) выключаем размышление (think=False), иначе в ответе будет рассуждение и разброс измерять неудобно.
Цена у DeepSeek: три тарифа и время суток
Заголовок раздела «Цена у DeepSeek: три тарифа и время суток»DeepSeek считает input по-разному в зависимости от того, попал ли префикс в кэш (кэш автоматический, ничего включать не надо), и даёт скидку 50% вне пиковых часов. Цены за 1M токенов на 13.11.2026 (Models & Pricing):
| Модель | Input, кэш-попадание | Input, промах | Output | Когда |
|---|---|---|---|---|
deepseek-flash |
$0.006 | $0.30 | $1.20 | пик |
deepseek-flash |
$0.003 | $0.15 | $0.60 | вне пика |
deepseek-v4-pro |
$0.044 | $1.32 | $3.96 | пик |
deepseek-v4-pro |
$0.022 | $0.66 | $1.98 | вне пика |
Пиковые часы — 01:00–04:00 и 06:00–10:00 UTC в будни (кроме китайских праздников), остальное время и выходные — дешевле. По Москве (UTC+3) пик — 04:00–07:00 и 09:00–13:00 в будни, так что вечерние прогоны и всё по выходным идут за полцены; в других часовых поясах окна стоит пересчитать от UTC. Эти цифры — только пример; цены меняются, вписываем их в PRICES с датой.
usage у DeepSeek несёт всё нужное: prompt_cache_hit_tokens, prompt_cache_miss_tokens (в сумме = prompt_tokens), completion_tokens и внутри completion_tokens_details.reasoning_tokens (размышление уже включено в completion_tokens). В терминах estimate_cost: промах — это input_tokens, попадание — cache_read_tokens, записи в кэш как отдельной статьи нет. Формула:
cost = (hit / 1e6 * p.cache_read + miss / 1e6 * p.input + out / 1e6 * p.output)# and p depends on the time of the request (peak / off-peak) for DeepSeekЗначит, estimate_cost для DeepSeek должна знать время запроса: добавляем ей последний необязательный аргумент at (время запроса в UTC), а в PRICES храним для моделей DeepSeek две цены — пиковую и обычную. Ollama стоит $0 за токен — но не «бесплатно»: платим временем (токенов/с на своей машине) и памятью. Для Ollama логируем не деньги, а скорость: eval_count / (eval_duration / 1e9) токенов/с.
Подсчёт токенов у нас
Заголовок раздела «Подсчёт токенов у нас»Остаётся прогноз до запроса: инструменты из теории (tiktoken, count_tokens) к нашим провайдерам не подходят.
- DeepSeek: эндпоинта подсчёта токенов нет. Точное число — только
usageпосле запроса; документация даёт прикидку «~0.3 токена на английский символ, ~0.6 на китайский» (для русского цифры нет — её мы измерим). Есть офлайн-токенизатор в виде zip-архива на странице Token & Token Usage — это код для запуска, так что по правилам курса сначала карантин и чтение, или просто обходимсяusage(запрос на 500 символов стоит доли цента). - Ollama: токены входа —
prompt_eval_count, выхода —eval_countв нативном ответе (илиusageв совместимом режиме). Токенизатор у каждой локальной модели свой. - tiktoken не подходит ни для DeepSeek, ни для моделей Ollama — так же, как для Claude.
Сравнение
Заголовок раздела «Сравнение»| Возможность | Claude | OpenAI | DeepSeek | Ollama |
|---|---|---|---|---|
temperature |
нет (новые модели/версия API — 400) | только не-reasoning модели | да, но только без размышления; в режиме размышления молча игнорируется | да |
top_p / top_k |
нет | top_p у части моделей |
top_p зависит от модели и режима; top_k нет |
оба, в options |
seed |
нет | см. доку модели | не документирован | да |
logprobs |
нет | у части моделей | да, до 20 альтернатив | нативный API — да; совместимый — нет |
| Ручка «глубины» | effort |
reasoning.effort |
reasoning_effort (low/high/max) + вкл/выкл размышления |
think (зависит от модели) |
| Подсчёт до запроса | count_tokens |
tiktoken локально |
нет (только usage, офлайн-архив) |
нет отдельного, только по факту |
| Скидка за кэш | чтение ~0.1×, запись дороже | автоматически | автоматически, попадание ≈ 1/50 цены промаха | — (локально) |
| Batch | −50% | −50% | Batch API в документации нет; есть скидка вне пика | — |
Что брать для практики
Заголовок раздела «Что брать для практики»- Эксперимент с temperature — основной: DeepSeek
deepseek-flashс выключенным размышлением; второй ряд — Ollamaqwen3:4bсthink=Falseи фиксированнымseed. - Распределение следующего токена —
top_logprobsу DeepSeek или в нативном API Ollama: это настоящая версия игрушечногоsample(). - RU vs EN токены —
usageDeepSeek иprompt_eval_countOllama (оба считают по своим токенизаторам),tiktokenиcount_tokensу Anthropic — для сравнения. - Тексты для эксперимента — публичные (правила доставки с сайта любого магазина, кусок README). Сообщения клиентов и журнал событий заказов — только в Ollama.
Маршрут изучения
Заголовок раздела «Маршрут изучения»- Let’s build the GPT Tokenizer — Карпатый (видео ~2 ч 13 мин; на 1.25x — около 1 ч 45 мин). Если времени мало, хватит первых ~25 минут (зачем токенизация, Unicode, байты) и финального блока про «странности» LLM, которые объясняются токенизацией. Забираем оттуда: BPE, почему не-английские языки и числа токенизируются хуже, почему модели плохо считают буквы.
- Открываем веб-токенизатор OpenAI platform.openai.com/tokenizer (≈10 мин): вставляем одну фразу на английском и русском, число и артикул товара вроде
MUG-NORTH-350. Смотрим глазами, где режется текст. - tiktoken → README (≈15 мин): как получить кодировку для модели и посчитать токены. Отметим: это только про модели OpenAI.
- Документация Anthropic → страница Token counting (docs.anthropic.com/en/docs/build-with-claude/token-counting) (≈15 мин): как вызвать подсчёт, что он принимает (system, tools, изображения).
- Страницы цен (≈20 мин): Anthropic Pricing и OpenAI API Pricing. Выписываем в
PRICESцены двух-трёх моделей, которыми пользуемся, с датой. Находим на странице Anthropic строки про cache reads/writes и batch. - В документации OpenAI на странице модели, выбранной для эксперимента с temperature, проверяем, поддерживается ли параметр (≈5 мин). В документации Anthropic смотрим на
effortв описании Messages API / adaptive thinking — это ручка, которая у Claude пришла на место «креативности». - DeepSeek (≈30 мин): Models & Pricing — выписываем цены кэш-попадания/промаха/output и пиковые часы; Token & Token Usage — как считаются токены; в Create Chat Completion находим
temperature,top_p,logprobs,top_logprobsи пометки, в каком режиме они действуют; в Thinking Mode — список параметров, которые в режиме размышления не работают. - Ollama (≈15 мин): Chat API —
options(temperature,top_p,top_k,seed,num_predict),logprobs, поляprompt_eval_count/eval_countи длительности в наносекундах; на странице OpenAI compatibility — какие из этих параметров доступны в совместимом режиме.
На что обратить внимание
Заголовок раздела «На что обратить внимание»- Не путаем
max_tokensи бюджет.max_tokens— потолок одного ответа, не лимит денег. Бюджет — наш код, который суммируетestimate_costпо вызовам. - Молча игнорируемый параметр хуже 400. DeepSeek в режиме размышления и Ollama в OpenAI-совместимом режиме (
logprobs,tool_choice) принимают параметр без ошибки и ничего с ним не делают. Перед экспериментом сверяемся с документацией, действует ли ручка в этом режиме. - Цена DeepSeek зависит от часов. Сравнивая стоимость двух прогонов, проверяем, что оба были в одном тарифном окне (пик/вне пика) — иначе разница «в 2 раза» окажется просто временем суток.
- tiktoken для Claude — ошибка. Числа будут похожи, но не совпадут, и на русском расхождение может быть заметным.
- Thinking-токены. Если у модели включено размышление,
output_tokensвключает его. «Короткий» ответ может стоить как длинный. - 5 прогонов — маленькая выборка. Для «разброса» это нормально, для выводов о качестве — нет (это тема evals: глава 2.5 · Упражнение: JSON из 20 текстов и неделя 6).
- Temperature 0 ≠ одинаковые ответы. Если в эксперименте при T=0 ответы чуть различаются — это не ошибка, это реальность GPU-инференса.
- Как это ломается в продакшене: тихо растущий промпт. Кто-то добавил в системный промпт бота поддержки «на всякий случай» всю базу знаний магазина, и средний запрос вырос с 800 до 12 000 токенов. Без логирования
usageна каждом вызове об этом узнают из счёта в конце месяца. - Сравниваем модели по цене задачи, а не токена. Модель вдвое дешевле за токен, которой нужно три попытки, дороже.
Практика
Заголовок раздела «Практика»Код кладём в exercises/week-01/. Модель для эксперимента с temperature — основная: DeepSeek deepseek-flash с выключенным размышлением (иначе temperature игнорируется); вторая — Ollama (qwen3:4b, think=False), установленная в главе 1.5 с проверкой подписи. Не-reasoning модель OpenAI — по желанию, для сравнения.
- 1. Игрушечное сэмплирование. Запускаем пример
sample()из теории для T = 0 / 0.5 / 1 / 2 по 1000 раз. Записываем распределения. Должно быть видно: при T=0 всегдаmug, при T=2rocketпоявляется заметно чаще. - 2. Эксперимент с temperature.
exercises/week-01/temperature.py: вопрос, где есть пространство для вариантов, например «Придумай название для бота поддержки небольшого интернет-магазина товаров для дома. Ответь только названием». Для T ∈ {0, 0.5, 1} (у DeepSeek и Ollama можно добавить 1.5) — по 5 прогонов на DeepSeek и на Ollama. Сохраняем всё вresults/temperature.jsonl(provider, model, temperature, run, text, input_tokens, output_tokens). - 2б. Ловушка размышления. Повторяем шаг 2 на DeepSeek без
thinking: disabledдля T=0 и T=1.5. Ошибки не будет. Есть ли разница в разбросе? Записываем вывод: где параметр молча игнорируется, эксперимент «доказывает» что угодно — всегда проверяем по документации, действует ли ручка в этом режиме. - 2в. Настоящее распределение. Для вопроса из шага 2 запрашиваем
logprobs=True, top_logprobs=5у DeepSeek (без размышления) и в нативном API Ollama. Выводим топ-5 первого токена с вероятностямиexp(logprob)и сравниваем с игрушкой из шага 1. Смотрим, как они меняются при T=0.2 и T=1.5 (подсказка: логпробы обычно отражают распределение до сэмплирования — стоит проверить, так ли у конкретного провайдера). - 3. Второй вопрос — «фактический». «Сколько граммов чая в упаковке 0,25 кг? Ответь числом». Те же 3 × 5 прогонов. Сравниваем: на фактическом вопросе разброс должен быть меньше при любой T.
- 4. Мера разброса. Для каждой T считаем число уникальных ответов из 5 (после
strip().lower()). Это грубо, но наглядно. - 5.
estimate_cost. Реализуем функцию из теории вexercises/week-01/cost.py, заполняемPRICESс датой проверки: обе модели DeepSeek (пик и вне пика, кэш-попадание и промах), модель Ollama с ценой 0 и, если пользуемся, Claude/OpenAI. Для DeepSeek функция принимает время запросаat(UTC) и сама выбирает тариф. Тесты: для модели с ценой $1/$5 и 2000/500 токенов должно выйти 0.0045 (а 1000 таких ответов поддержки — 4.5); для DeepSeek запрос в среду 08:00 UTC стоит вдвое дороже того же запроса в субботу. Добавляемassert. - 5б. Скорость Ollama. Для 5 прогонов на Ollama считаем токенов/с (
eval_count / eval_duration * 1e9) и время загрузки модели (load_duration) на первом и последующих запросах. Добавляем колонку «ток/с» в таблицу шага 6. - 6. Итоговая таблица. Скрипт печатает Markdown-таблицу:
| temperature | вопрос | уникальных ответов из 5 | ср. output_tokens | стоимость 5 прогонов, $ ||---|---|---|---|---|| 0 | название | 1 | 6 | 0.00002 || ... |- 7. Русский vs английский.
exercises/week-01/tokens_ru_en.py: берём 3 текста по 300–500 символов (например, абзац правил доставки или возврата с сайта магазина, описание товара, кусок README) в двух версиях — русской и английской. Считаем токены: основное —usage.prompt_tokensу DeepSeek иprompt_eval_countу Ollama (вычитаем токены пустого запроса, чтобы убрать служебную разметку чата); для сравнения —tiktoken(o200k_base) иcount_tokensу Anthropic. Таблица: текст × язык × токенайзер × токены × токенов на символ. Выводим «русский дороже в X раз» для каждого токенайзера. Тексты — публичные; реальное сообщение клиента, если оно есть, — только в Ollama. - 8. Вывод. В
notes/temperature-cost.md5–7 строк: когда нужна низкая случайность, когда высокая; во сколько раз output дороже input у выбранных моделей; во сколько русский дороже английского; что делать на моделях, где temperature нет или где он молча игнорируется; сколько экономит DeepSeek вне пика.
Готово, когда
Заголовок раздела «Готово, когда»- Есть таблица temperature × разброс ответов × стоимость (шаг 6) и таблица RU/EN токенов (шаг 7).
-
estimate_cost(model, input_tokens, output_tokens)лежит в отдельном модуле, покрыта хотя бы однимassert, цены подписаны датой и источником; для DeepSeek учтены кэш-попадания и пиковые часы. - Мы видели реальное распределение следующего токена (
top_logprobs) хотя бы у одного провайдера. - В
notes/temperature-cost.mdзаписан вывод: низкая случайность — извлечение данных, классификация, код; высокая — идеи, тексты, синтетические данные.
Тест для самопроверки
Заголовок раздела «Тест для самопроверки»Вопрос 1
Что делает temperature с распределением вероятностей следующего токена?
b. Логиты делятся на T: малая T усиливает разницу между вариантами, большая — сглаживает.
Вопрос 2
Что такое top_p = 0.9?
Сэмплирование только из минимального набора самых вероятных токенов с суммарной вероятностью ≥ 90%; маловероятный «хвост» отбрасывается.
Вопрос 3
Почему одна и та же фраза на русском обычно занимает больше токенов, чем на английском?
Словари BPE строились на корпусах, где доминирует английский: частые английские слова стали целыми токенами, а русские слова режутся на куски.
Вопрос 4
При T=0 на одинаковый запрос пришли два слегка разных ответа. Это баг SDK?
Нет. Параллельные вычисления на GPU и батчинг дают небольшую недетерминированность даже при greedy-выборе.
Вопрос 5
Запрос: 10 000 input, 1 000 output, цена $3 / $15 за MTok. Сколько стоит запрос?
10 000/1e6·3 + 1 000/1e6·15 = 0.03 + 0.015 = $0.045.
Вопрос 6
Что не так в этом коде?
import tiktokenenc = tiktoken.get_encoding("o200k_base")def claude_cost(prompt: str) -> float: return len(enc.encode(prompt)) / 1e6 * PRICE_IN["claude-haiku-5-5"]tiktoken — токенизатор OpenAI, для Claude счёт неточен (нужен count_tokens или usage); считается только input, хотя output дороже; а ещё не учтены system, история и thinking-токены.
Вопрос 7
Запрос к новой модели Claude с temperature=0.2 вернул 400. Почему и что делать?
Новые модели Claude принимают только сэмплирование по умолчанию, а версия API 2026-10-21 отвергает эти параметры на любой модели. Убрать параметр; управлять поведением промптом, схемой вывода и effort.
Вопрос 8
Почему модели плохо отвечают на «сколько букв r в слове strawberry»?
Модель видит токены, а не буквы: strawberry — один-два токена, их внутренняя «буквенная» структура модели напрямую не видна.
Вопрос 9
Какая temperature (низкая/высокая) уместна для: (а) извлечения суммы заказа из письма клиента; (б) генерации 20 вариантов поста о новой коллекции кружек; (в) генерации SQL?
(а) низкая, (б) высокая, (в) низкая.
Вопрос 10
Почему функция estimate_cost должна падать на неизвестной модели, а не возвращать 0?
Нулевая цена молча скрывает расходы; падение сразу заставит добавить цену новой модели.
Вопрос 11
Модель с ценой за токен вдвое ниже дала верный ответ в 50% случаев, дорогая — в 95%. Ошибка обнаруживается и запрос повторяется. Какая дешевле «за правильный ответ», если output одинаковый?
Ожидаемое число попыток: дешёвая 1/0.5 = 2, дорогая 1/0.95 ≈ 1.05. Цена за правильный ответ: дешёвая 2 × 0.5 = 1.0 условной единицы, дорогая 1.05 × 1 ≈ 1.05 — почти одинаково; а если ошибки не обнаруживаются автоматически, дешёвая модель обходится намного дороже.
Вопрос 12
В deepseek-flash отправлены запросы с temperature=0 и temperature=1.5 без других параметров, ошибок нет, а разброс ответов одинаковый. Почему?
b. Режим размышления у DeepSeek включён по умолчанию, и temperature в нём не действует — без ошибки. Нужно выключить размышление (thinking: disabled) и повторить.
Вопрос 13
Запрос к DeepSeek: 10 000 input-токенов, из них 8 000 — попадание в кэш, 1 000 output. Цены (условные): попадание $0.01, промах $0.30, output $1.20 за MTok. Сколько стоит запрос? А если бы кэша не было?
8 000/1e6·0.01 + 2 000/1e6·0.30 + 1 000/1e6·1.20 = 0.00008 + 0.0006 + 0.0012 ≈ $0.0019. Без кэша: 10 000/1e6·0.30 + 0.0012 = $0.0042 — кэш сэкономил больше половины.
Вопрос 14
Почему Ollama — лучший провайдер этого курса для эксперимента с сэмплированием, и почему её «$0 за токен» не значит «бесплатно»?
Она принимает все классические ручки (temperature, top_p, top_k, seed) и отдаёт logprobs в нативном API, а данные не уходят с машины. Платим памятью, диском, временем генерации (токены/с на своей машине) и качеством небольшой модели.
Что дальше
Заголовок раздела «Что дальше»Дальше неделя 2 и главный рычаг качества — [2.1 · Промптинг: роли, few-shot, структура (гл. 2.1)](/week-02/2-1/). Функция estimate_cost пригодится уже там, при сравнении версий промпта, и станет частью llm_utils.py в [2.7 · Стриминг, ретраи, rate limits, prompt caching (гл. 2.7)](/week-02/2-7/).