Перейти к содержимому

1.5 · Видео Карпатого + ключи API

Неделя 1 · Подготовка · ⏱ ~4,5 ч (+ 3,5 ч второго видео частями в течение первых недель) · Теория

Без модели в голове поведение LLM выглядит как набор случайных капризов: почему она уверенно выдумывает функцию API, путает 9.11 и 9.9, «забывает» инструкцию из середины длинного промпта, не знает о вчерашнем изменении тарифов службы доставки. С моделью в голове это предсказуемые следствия того, как она обучена и как читает текст, — и мы заранее знаем, где нужен RAG (подкладываем в промпт найденные документы, недели 4–5), где tool calling (модель просит вызвать нашу функцию, неделя 2), где валидация. На собеседованиях вопросы «что такое токен», «откуда галлюцинации», «что такое контекстное окно и почему оно ограничено» звучат почти всегда. Вторая половина главы — ключи API: без них не будет ни одного проекта, и с ними связана самая дорогая ошибка новичка — утёкший ключ.

1. LLM — это функция «текст → вероятности следующего токена»

Заголовок раздела «1. LLM — это функция «текст → вероятности следующего токена»»

Большая языковая модель на вход получает последовательность токенов и выдаёт распределение вероятностей для следующего токена. Всё. Генерация ответа — это цикл:

prompt tokens ──▶ [ model ] ──▶ P(next token) ──▶ sample one ──┐
▲ │
└──────────── append it to the sequence ◀────────────────┘
repeat until a stop token or max_tokens

Отсюда сразу несколько следствий:

  • Модель не «ищет ответ», она продолжает текст правдоподобно. Правдоподобное и верное часто совпадают, но не всегда — это и есть галлюцинация.
  • Выбор токена — сэмплирование из распределения. Параметр temperature его «сплющивает» или «заостряет»: при низкой модель почти всегда берёт самый вероятный токен, при высокой — чаще менее вероятные. Подробно разберём в гл. 1.7.
  • Каждый следующий токен зависит от всех предыдущих, включая уже сгенерированные. Ошибка в начале ответа тянет за собой остальное — поэтому полезно просить модель сначала рассуждать, а потом отвечать (chain-of-thought, неделя 2).

Аналогия для разработчика: это автодополнение в IDE, которое прочитало почти весь интернет и потом было долго дообучено вести себя как ассистент.

Во всех следствиях выше единица работы модели — токен. Разберём, что это такое.

Модель не видит буквы и слова — она видит токены: куски текста из фиксированного словаря (десятки–сотни тысяч элементов), который строится алгоритмом вроде BPE (byte pair encoding): частые последовательности байтов склеиваются в один токен.

"Delivery cost for MUG-NORTH-350" → ["Del", "ivery", " cost", " for", " MUG", "-N", "ORTH", "-", "350"] (illustrative)

Что из этого следует на практике:

  • Цена и лимиты считаются в токенах, а не в символах или словах. Для английского текста грубая оценка — около 4 символов на токен; для русского текста токенов на ту же мысль обычно заметно больше, то есть он дороже и быстрее съедает контекст. У разных моделей разные токенизаторы, поэтому одно и то же число токенов у Claude и GPT не совпадает.
  • Арифметика и посимвольные задачи даются плохо. Число 97342.15 может разбиться на токены 973, 42, ., 15 — модель не «видит» разряды так, как мы. Отсюда «сколько букв r в strawberry» и сравнение 9.11 и 9.9. Вывод для любого прикладного домена, в том числе для нашего магазина: никогда не доверяем модели считать выручку, прибыль, скидки и комиссии платёжного провайдера — это делает наш код, а модель только вызывает его (tool calling, неделя 2) или объясняет готовые цифры.
  • Пробелы и регистр входят в токены: " MUG" и "MUG" — разные токены.

Посмотреть руками: OpenAI Tokenizer. В Python — библиотека tiktoken для моделей OpenAI; у Anthropic есть эндпоинт подсчёта токенов в API (он есть в документации, понадобится, когда дойдём до стоимости).

3. Как модель получается: три стадии обучения

Заголовок раздела «3. Как модель получается: три стадии обучения»

Мы знаем, что модель делает на каждом шаге и с какими кусками текста работает. Откуда она берёт свои вероятности — из обучения, которое идёт в три стадии:

Стадия Данные Что получаем
Pretraining триллионы токенов интернета, книг, кода «base model»: продолжает любой текст, знает факты, но не отвечает на вопросы, а дописывает документ
Supervised fine-tuning (SFT) десятки–сотни тысяч примеров диалогов «вопрос → хороший ответ», написанных людьми ассистент: понимает формат диалога, ролей, инструкций
RLHF / RL оценки ответов людьми (или моделью-оценщиком), задачи с проверяемым ответом модель предпочитает полезные, безопасные ответы; RL на задачах с проверкой учит рассуждать

Карпатый объясняет это через метафору: pretraining — «сжатие интернета» в параметры модели (с потерями, как zip с потерями), SFT и RLHF — обучение «характеру» ассистента. Знания о мире в основном приходят из pretraining, и они заморожены на дате среза данных (knowledge cutoff). Отсюда:

  • модель не знает о событиях после среза, если не дать их в промпте (RAG, поиск, инструменты);
  • она не знает, чего не знает: на вопрос о свежем событии может уверенно сочинить ответ;
  • редкие факты (параметры API малоизвестной службы доставки) запомнены плохо и путаются — галлюцинации чаще всего именно там. Лекарство — положить нужный кусок документации в контекст (неделя 4).

Знания из обучения заморожены, а свежие данные модель получает только через текст запроса. Всё, что модель «знает» в момент ответа, кроме зашитого в параметры, — это контекст: системный промпт + история диалога + наши документы + уже сгенерированный ответ. Между запросами модель ничего не помнит: API stateless, и «память» чата — это наш код, который каждый раз отправляет всю историю заново (и платит за неё).

Почему окно ограничено:

  • В трансформере каждый токен через механизм attention «смотрит» на все предыдущие токены. Стоимость вычислений и память растут с длиной быстрее, чем линейно (в базовом варианте — квадратично), поэтому длинный контекст дорог и медленнее.
  • Модель обучена на последовательностях определённой длины; за её пределами качество не гарантировано.

Современные окна огромны (сотни тысяч токенов и больше — проверяем в документации конкретной модели), но большое окно не значит идеальное внимание. Известный эффект «lost in the middle» (статья Liu et al., 2023): информацию в начале и в конце длинного контекста модель использует лучше, чем в середине. На практике: важные инструкции — в системный промпт и/или в конец, документы — компактно и только релевантные, а не «всю базу знаний целиком».

Аналогия: параметры модели — долговременная память, прочитанная давно и смутно; контекст — то, что лежит перед ней на столе прямо сейчас и читается точно.

Attention, embeddings и параметры уже упоминались выше; теперь сложим их в одну схему трансформера — архитектуры, на которой построены современные LLM. Не обязательно уметь его реализовать, но полезно знать схему:

text → tokens → embeddings (vector per token) + position info
→ N × [ self-attention → feed-forward ] # each layer refines every token's vector
→ final vector of the last token → probabilities over the vocabulary
  • Embedding — вектор чисел на каждый токен; похожие по смыслу токены — близкие векторы. Та же идея в эмбеддингах документов для RAG (неделя 4).
  • Self-attention — каждый токен решает, на какие предыдущие токены «смотреть» и сколько информации из них взять. Так «он» в предложении связывается с нужным существительным.
  • Параметры (веса) — миллиарды чисел, подобранных при обучении. «Модель на 70B» — 70 миллиардов параметров.

The Illustrated Transformer из маршрута разбирает это картинками.

6. Почему модели ошибаются: короткая шпаргалка

Заголовок раздела «6. Почему модели ошибаются: короткая шпаргалка»

Теперь каждую типичную ошибку модели можно вывести из её устройства — и сразу назвать инженерное средство:

Симптом Причина Что делает инженер
Уверенно выдумывает факт/метод API правдоподобное продолжение, редкий факт в pretraining RAG с документацией, «если не знаешь — скажи», проверка
Путает цифры, плохо считает токенизация чисел считать в коде, давать модели инструмент
Не знает свежих событий knowledge cutoff поиск, свежие данные в контексте
Игнорирует инструкцию в середине длинного промпта ослабленное внимание к середине структура, повтор важного, короче контекст
Разные ответы на одинаковый вопрос сэмплирование низкая temperature, structured output, evals
«Слушается» текста из документа для модели инструкции и данные — один поток токенов разделение данных и инструкций, защита от prompt injection (неделя 9)

От устройства модели переходим к практике. Чтобы вызывать облачную модель из кода, нужен ключ API — секретная строка, по которой провайдер узнаёт наш аккаунт и списывает деньги. Сначала — за что именно списывает.

Модель оплаты. Платим за токены: отдельно за входные (input) и выходные (output); выходные заметно дороже. Цена указывается за миллион токенов и сильно отличается между моделями одного провайдера — «маленькая» модель может быть в десятки раз дешевле «большой». Конкретные цены и названия моделей меняются, поэтому всегда смотрим актуальные страницы (ссылки в маршруте) и не держим их в голове как константы. Расчёт стоимости запроса — тема главы 1.7 · Скрипт: temperature, токены, стоимость.

Ключ = деньги. API-ключ — это bearer-токен: у кого он есть, тот тратит наш баланс. Поэтому:

  1. Лимит расходов в консоли провайдера — обязательно, до первого запроса. Названия разделов в консолях меняются (лимиты организации, бюджеты проектов/workspaces, уведомления) — актуальное место ищем в документации провайдера.
  2. Предоплата небольшой суммой ($10–20) вместо привязки с автопополнением — естественный потолок ущерба.
  3. Отдельный ключ на проект с понятным именем (learning-week01) — утёкший ключ отзывается, не ломая остальное.
  4. Ключи только в переменных окружения. Файл .env в корне, в .gitignore (сделано в гл. 1.2), в git — только .env.example с пустыми значениями.
# illustrative: load keys from .env, never hardcode them
from dotenv import load_dotenv # uv add python-dotenv
import anthropic
load_dotenv() # reads .env into os.environ
client = anthropic.Anthropic() # SDK reads ANTHROPIC_API_KEY from the environment

Официальные SDK сами берут ключ из ANTHROPIC_API_KEY и OPENAI_API_KEY, поэтому в коде ключ вообще не упоминается — и это правильно. Для DeepSeek и Ollama через SDK openai ключ и адрес передаём явно (os.environ["DEEPSEEK_API_KEY"], пример ниже). Пакет — python-dotenv; load_dotenv() без аргументов ищет .env от папки скрипта вверх, поэтому находит файл в корне репозитория.

Если ключ утёк (в коммит, в скриншот, в вывод ноутбука, в чат): сразу отозвать ключ в консоли и выпустить новый. Удалить коммит или переписать историю — недостаточно: публичные репозитории сканируются ботами за минуты, а копии истории остаются у клонов и в кешах. Отзыв — единственная мера, которая действительно закрывает дыру.

Общие правила про ключи и деньги действуют для любого провайдера. Теперь — конкретно для нашего стека. В этой книге учимся на двух дешёвых вариантах, а Claude и OpenAI остаются для сравнения:

  • DeepSeek API — основная облачная модель: очень дешёвая, совместима с OpenAI SDK (меняются только base_url и ключ). Серверы в Китае.
  • Ollama — локальные модели на нашем компьютере: бесплатно, офлайн, данные никуда не уходят. Всё, что касается персональных данных покупателей, рабочего кода и снимков базы магазина, — только сюда. Эмбеддинги (неделя 4) — тоже здесь.

Факты ниже проверены по официальной документации 13 ноября 2026; модели и цены у DeepSeek меняются часто — перед расчётами сверяемся со страницами из маршрута.

customers' personal data, DB snapshots, work code, event logs, keys ──▶ Ollama (local model) only
textbook exercises, public texts, demo DB, fake data ──▶ DeepSeek / Claude / OpenAI

DeepSeek обрабатывает запросы в Китае; бесплатные облачные тарифы других провайдеров (и некоторые бесплатные модели на OpenRouter) могут использовать входные данные для обучения. Правило касается любого облачного провайдера, а не только DeepSeek: персональные данные покупателей, снимки базы, журнал событий заказов, рабочий код, ключи и всё, что нельзя показывать посторонним, в облачные модели не отправляются никогда — даже «чтобы просто проверить». Это обрабатывает локальная модель. Облачным моделям — публичные тексты и демо-база.

  • Ключ создаётся на platform.deepseek.com/api_keys. Переменная окружения по документации — DEEPSEEK_API_KEY.
  • Оплата — с предоплаченного баланса (документация: списание идёт с пополненного или подаренного баланса, подаренный тратится первым). Отдельной настройки лимита расходов, как у Anthropic/OpenAI, в документации API не нашлось — стоит проверить консоль самим. Поэтому потолок ущерба здесь — маленькое пополнение без автопополнения: при ценах ниже даже $5 хватит на всю учёбу с запасом.
  • Отдельный ключ под учёбу с понятным именем; отзыв — там же, на странице ключей.
Модель (model=) Контекст Особенности
deepseek-flash 1M дешёвая основная; режимы thinking и non-thinking (по умолчанию thinking), есть vision
deepseek-v4-pro 1M сильнее и дороже; thinking/non-thinking; vision нет

Цена за 1M токенов, USD. «Cache hit» — часть входа, которая совпала с префиксом недавних запросов (кеширование у DeepSeek автоматическое, подробно в главе 2.7 · Стриминг, ретраи, rate limits, prompt caching). Днём по будням есть пиковые часы (01:00–04:00 и 06:00–10:00 UTC, пн–пт), в них цена вдвое выше:

flash, вне пика flash, пик pro, вне пика pro, пик
вход, cache hit 0.003 0.006 0.022 0.044
вход, cache miss 0.15 0.30 0.66 1.32
выход 0.60 1.20 1.98 3.96

Старые имена deepseek-v4-flash и deepseek-v4-flash-vision-exp ещё принимаются, но перенаправляются на текущую Flash. Имена моделей из старых туториалов не копируем — держим DEEPSEEK_MODEL в .env.

Что отличает DeepSeek от того, что пишут в документации Anthropic/OpenAI:

  • Thinking включён по умолчанию. Модель сначала пишет рассуждение (поле reasoning_content рядом с content), и эти токены оплачиваются как выход. Для простых проверок выключаем: extra_body={"thinking": {"type": "disabled"}}.
  • В режиме thinking temperature не действует: документация говорит, что temperature, presence_penalty, frequency_penalty не вызывают ошибку, но и ничего не меняют. Это важно для главы 1.7 · Скрипт: temperature, токены, стоимость — эксперименты с температурой делаем в non-thinking режиме.
  • Токены: по документации DeepSeek, 1 английский символ ≈ 0.3 токена (то есть ~3 символа на токен); точное число всегда берём из usage в ответе. Офлайн-токенизатор DeepSeek раздаётся архивом с их CDN — если понадобится его скачать, это сторонний код: карантинная папка и чтение перед запуском.
  • Эмбеддингов у DeepSeek в документации нет (в списке моделей и цен их нет) — для недели 4 эмбеддинги будут локальные, через Ollama.
  • Есть и Anthropic-совместимый вход (https://api.deepseek.com/anthropic): SDK anthropic с другим base_url. Нам он не нужен — основной путь через OpenAI SDK.

Ollama — программа, которая будет работать постоянно и слушать порт, поэтому ставим её по правилам для стороннего кода. Шаги ниже — для macOS; на Windows и Linux смысл тот же: официальный установщик, проверка подписи, чтение любого скрипта до запуска.

  1. Только официальный источник: ollama.com/download → для macOS это Ollama.dmg. Не ставим через curl -fsSL https://ollama.com/install.sh | sh, хотя сайт предлагает и такой путь: исполнять скрипт из интернета не читая его — против базового правила работы со сторонним кодом. Сборки со сторонних сайтов и из форков не берём.
  2. Требования (docs.ollama.com/macos): macOS Sonoma 14 или новее; на Apple Silicon работает CPU+GPU (Metal), на Intel — только CPU.
  3. До первого запуска проверяем подпись и нотаризацию:
    Окно терминала
    codesign -dv --verbose=2 /Applications/Ollama.app # who signed it: Authority / TeamIdentifier
    spctl -a -vv /Applications/Ollama.app # expect: accepted, source=Notarized Developer ID
    Подписантом должен быть разработчик Ollama (Developer ID). Если подписи нет, spctl пишет rejected или издатель неожиданный — не запускаем, удаляем и записываем в заметки, откуда скачали. Проверка подписи снижает риск, но не гарантирует отсутствие уязвимостей.
  4. При первом запуске приложение предложит создать ссылку на CLI ollama в /usr/local/bin — это нормально (документация описывает этот шаг).
  5. Модели и настройки лежат в ~/.ollama (логи — ~/.ollama/logs), вне нашего репозитория. Модели весят гигабайты — стоит следить за местом на диске.
  6. Сервер слушает http://localhost:11434 — только нашу машину. Открывать его в сеть нельзя (не меняем адрес прослушивания на 0.0.0.0): у локального API нет аутентификации.
  7. Облачные модели Ollama. В библиотеке Ollama есть и облачные модели (у них вместо размера указан контекст и уровень цены), они требуют аккаунт Ollama и выполняются на серверах Ollama, а не у нас. Для своих данных — только локальные модели, скачанные через ollama pull.

Модели (проверено по ollama.com/library, 13.11.2026; список меняется):

Окно терминала
ollama pull llama3.2:3b # ~2.0 GB, 128K context, supports tools — quick checks
ollama pull qwen3:4b # ~2.5 GB, tools + thinking — tool calling later
ollama pull bge-m3 # embeddings for week 4 (alternatives: embeddinggemma, nomic-embed-text)
ollama list # what is downloaded
ollama ps # what is loaded in memory right now

Цифра перед b в имени — число параметров в миллиардах (qwen3:4b — 4 млрд), от неё зависит, сколько памяти нужно. Грубое правило по памяти (эвристика, не из документации): модель должна целиком помещаться в память вместе с системой, браузером и всем, что ещё запущено (на Apple Silicon это общая память, на ПК с видеокартой важен ещё объём видеопамяти). Ориентиры для моделей в Q4 (квантизация: каждый параметр хранится примерно в 4 битах вместо 16, поэтому модель весит в разы меньше; Ollama по умолчанию отдаёт модели в таком виде):

  • 8 ГБ — модели класса 3–4B (например, qwen3:4b-instruct-2507-q4_K_M, ≈2,5 ГБ); 7–8B (≈5 ГБ) — только с закрытым браузером и без других тяжёлых программ, иначе система уходит в своп; 14B+ не запускаем.
  • 16 ГБ — комфортны модели 7–8B.
  • 32 ГБ и больше — 14B и крупнее; 30B+ — для 32–64 ГБ.

Модель по умолчанию в курсе — qwen3:4b: она работает даже на 8 ГБ, и все примеры начиная с недели 2 рассчитаны на неё. llama3.2:3b нужна только для быстрой проверки установки: она отвечает без режима рассуждений, и короткий ответ не съедается лимитом токенов. Если памяти больше, можно взять модель крупнее. Скачиваем только из библиотеки ollama.com или официальных организаций на Hugging Face.

Первый вызов: одна библиотека на оба провайдера

Заголовок раздела «Первый вызов: одна библиотека на оба провайдера»

Ключ получен, Ollama установлена — можно проверить оба провайдера одним скриптом. И DeepSeek, и Ollama понимают формат OpenAI Chat Completions, поэтому хватает одного пакета openai:

# illustrative — verify against api-docs.deepseek.com and docs.ollama.com
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
deepseek = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
ollama = OpenAI(
api_key="ollama", # required by the SDK, ignored by Ollama
base_url="http://localhost:11434/v1",
)
def ask(client: OpenAI, model: str, **extra) -> None:
resp = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "Say 'ok' and nothing else."}],
max_tokens=50,
**extra,
)
print(model, "→", resp.choices[0].message.content, resp.usage)
ask(deepseek, os.environ["DEEPSEEK_MODEL"], extra_body={"thinking": {"type": "disabled"}})
ask(ollama, os.environ["OLLAMA_MODEL"])

Для Ollama есть и своя библиотека ollama (официальный клиент, репозиторий github.com/ollama/ollama-python) — она понадобится для эмбеддингов, структурированного format и управления thinking (think=False). Ставим с фиксированной версией (uv add "ollama==<version>", версию берём из PyPI на день установки).

Claude OpenAI DeepSeek Ollama (локально)
Где выполняется облако Anthropic облако OpenAI облако, Китай наш компьютер
Можно персональные данные / рабочий код нет нет нет, никогда да
Ключ ANTHROPIC_API_KEY OPENAI_API_KEY DEEPSEEK_API_KEY не нужен (любая строка)
SDK anthropic openai openai + base_url openai + base_url или ollama
Лимит расходов настройки в консоли бюджеты проекта предоплаченный баланс (отдельного лимита в доках не нашлось) бесплатно, платим памятью и временем
Цена (порядок) от дешёвых до дорогих моделей то же центы за миллион токенов входа 0
Thinking включается параметром у reasoning-моделей включён по умолчанию зависит от модели (think=)
Эмбеддинги нет своего эндпоинта есть в документации нет есть (/api/embed, /v1/embeddings)
Токенизатор эндпоинт подсчёта tiktoken офлайн-архив / usage usage в ответе

Для практики этой главы: ключ DeepSeek + установленная Ollama с одной маленькой моделью — это минимум. Аккаунты Anthropic и OpenAI — по желанию, для сравнения; на них учебник будет показывать, «что бывает у больших провайдеров», и позже понадобится сильная модель в роли LLM-as-judge (оценщик должен быть сильнее оцениваемой модели — неделя 6).

  1. Intro to Large Language Models — Андрей Карпатый (1 ч, обязательно; с паузами ≈1,5 ч). Смотрим с блокнотом. Берём: «LLM = два файла» (параметры + код запуска), pretraining как сжатие интернета, стадии обучения, LLM как «операционная система», раздел про безопасность (jailbreak, prompt injection) — он вернётся на неделе 9.
  2. The Illustrated Transformer — Jay Alammar (≈45 мин). Читаем до раздела про декодер включительно; формулы можно пропускать. Берём: что такое embedding, как self-attention смешивает информацию токенов, зачем positional encoding. Не застреваем: цель — интуиция, а не реализация.
  3. OpenAI Tokenizer (≈10 мин). Вставляем: английское предложение, то же по-русски, число 97342.15, артикул товара MUG-NORTH-350, кусок JSON. Сравниваем число токенов и как режутся числа.
  4. Deep Dive into LLMs like ChatGPT — Карпатый (3,5 ч, частями в течение первых недель, по 30–40 мин). Сейчас — первый час: данные pretraining, токенизация, обучение нейросети, инференс. Остальное — галлюцинации и использование инструментов, «модели нужны токены, чтобы думать», RL и reasoning — по ходу недель 1–2.
  5. (Опционально) 3Blue1Brown — Neural Networks — главы про трансформеры и attention (≈1 ч), если хочется визуальной интуиции глубже Alammar.
  6. DeepSeek (≈30 мин): Quick start (base URL, первый вызов), Models & Pricing (модели, cache hit/miss, пиковые часы), Thinking Mode (что игнорируется в thinking, reasoning_content), Rate Limit (лимит параллельных запросов, 429), Token & Token Usage. Потом platform.deepseek.com/api_keys: пополнение и ключ. Берём: имена моделей на сегодня, цену входа/выхода, что thinking включён по умолчанию.
  7. Ollama (≈40 мин вместе со скачиванием): Ollama на macOS (требования, где лежат файлы), OpenAI compatibility (base URL, какие эндпоинты есть, чего нет), Cloud (какие модели выполняются не у нас), библиотека моделей (размер, контекст, метки tools/thinking/embedding). Установка — по чек-листу из раздела «DeepSeek и Ollama» выше.
  8. (Для сравнения, по желанию) Ключи Anthropic и OpenAI. Anthropic Console (сейчас консоль живёт на platform.claude.com; старый адрес перенаправляет) и OpenAI Platform (≈30 мин на оба): аккаунт, пополнение, лимиты, ключ.
  9. Цены и модели (≈15 мин): кроме страницы DeepSeek из шага 6 — Anthropic pricing, страница цен в документации Claude, обзор моделей Claude, OpenAI pricing, модели OpenAI. Берём: цена input против output, разница между самой дешёвой и самой дорогой моделью, размеры контекстных окон.
  10. Первый вызов (≈15 мин, по желанию — полноценно это глава 1.6 · Сырой API: первые запросы к Claude и OpenAI): код из раздела «DeepSeek и Ollama» выше; для сравнения — Quickstart Claude (вкладка Python) и Quickstart OpenAI.
  • Модель не калькулятор и не база данных. Любая цифра из её ответа о выручке, прибыли, скидках или комиссиях должна происходить из нашего кода или из данных в контексте, а не из «памяти» модели.
  • «Модель помнит прошлый разговор» — нет, это код приложения переотправляет историю. Длинный чат = растущая цена каждого следующего запроса.
  • Большое контекстное окно — не повод класть туда всё. Стоимость растёт линейно с объёмом входа, качество использования середины падает.
  • Свежие данные. Вопрос «сколько сейчас стоит доставка курьером в Казань» без инструмента или данных в контексте получит выдуманный ответ.
  • Ключ в коде «на минутку» — так он и попадает в git. Даже в ноутбуке — только через окружение (гл. 1.4).
  • Нет лимита расходов — цикл с ошибкой (ретраи без паузы, gather без семафора по тысяче запросов) может сжечь баланс за минуты.
  • Названия моделей и цены устаревают. Не копируем их из старых туториалов и ответов моделей — берём из документации на сегодня и держим имя модели в конфиге/переменной окружения.
  • Утечка = отзыв, а не git commit --amend.
  • «Дёшево» не значит «можно всё». DeepSeek стоит копейки, но данные уходят в Китай. Персональные данные покупателей, журнал событий заказов, снимки базы и рабочий код — только в локальную Ollama.
  • Облачная модель внутри Ollama. Модель из облачного каталога Ollama выполняется на их серверах, хотя мы вызываем её через localhost. Для своих данных проверяем, что модель локальная (ollama list показывает её размер на диске, ollama ps — что она загружена в память).
  • Thinking DeepSeek жжёт выходные токены. «Скажи ok» в режиме thinking может стоить сотни токенов рассуждений. Смотрим usage и выключаем thinking, где он не нужен.
  • curl … | sh с сайта Ollama — удобно, но это исполнение непрочитанного скрипта. Ставим .dmg (или официальный установщик для своей ОС) и проверяем подпись.
  • Карпатый, Intro. Смотрим видео и пишем notes/llm-basics.md — 10–15 пунктов своими словами, без копирования слайдов. Обязательные пункты: что такое токен; next-token prediction; три стадии обучения; что такое контекстное окно и почему оно ограничено; почему модель не знает свежих событий; откуда галлюцинации; почему плохо с арифметикой; что такое prompt injection.
  • Токенизатор. В том же файле — табличка из 5 строк: текст → число токенов (английский, русский, число, артикул товара, JSON). Вывод в одну фразу: что дороже и почему.
  • Alammar. Рисуем в notes/llm-basics.md ASCII-схему трансформера своими словами (как в теории, но по памяти).
  • DeepSeek. Регистрируемся на platform.deepseek.com, пополняем на минимальную сумму (без автопополнения — это и есть наш лимит расходов), создаём ключ learning. Находим в консоли, где ключ отзывается, и записываем.
  • Ollama. Скачиваем Ollama.dmg с ollama.com/download, перетаскиваем в Applications, до первого запуска выполняем codesign -dv --verbose=2 и spctl -a -vv и записываем вывод (кто подписал, accepted/rejected) в notes/llm-basics.md. На Windows и Linux — официальный установщик и проверка подписи или чтение скрипта средствами своей ОС. Запускаем, разрешаем ссылку на CLI, затем ollama --version, ollama pull llama3.2:3b, ollama run llama3.2:3b "Say ok". Отмечаем, сколько места заняла модель и сколько секунд шёл первый ответ (первый вызов медленнее — модель грузится в память).
  • (Для сравнения, по желанию) Anthropic. Регистрируемся в консоли, пополняем на $10–20, сначала устанавливаем лимит расходов и уведомление, потом создаём ключ learning (или по проекту).
  • (Для сравнения, по желанию) OpenAI. То же: пополнение $10–20, лимит/бюджет проекта, отдельный проект для учёбы, ключ.
  • Файл окружения. В корне ai-engineering-journey:
    Окно терминала
    cp .env.example .env # then paste the keys into .env in the editor
    git status # .env must NOT be listed
    git check-ignore -v .env # shows which .gitignore rule hides it
    Ключи не вставляем через echo ... >> .env в терминале: команда останется в истории шелла.
  • Проверка ключей: DeepSeek + Ollama (основное). В проекте из главы 1.3 · Python: uv, async, Pydantic или новом exercises/week-01/keys-check/ (создаём через uv init): uv add openai python-dotenv. В .env: DEEPSEEK_API_KEY=..., DEEPSEEK_MODEL=deepseek-flash, OLLAMA_MODEL=llama3.2:3b (имена сверяем с документацией на сегодня); в .env.example — те же имена без значений. Скрипт check_keys.py по образцу кода из раздела «DeepSeek и Ollama» делает по одному запросу к каждому и печатает только текст ответа и usage. Запускаем DeepSeek дважды — с выключенным и включённым thinking (для второго запуска убираем extra_body и поднимаем max_tokens, например до 1000: рассуждение тоже идёт в выход, и с лимитом 50 до ответа дело может не дойти) — и сравниваем completion_tokens. Ожидаемо: оба отвечают, с thinking токенов выхода заметно больше; стоимость — доли цента. Если Ollama не отвечает — проверяем, что приложение запущено (curl http://localhost:11434 — запрос к своей машине, наружу не уходит).
  • (Для сравнения, по желанию) Проверка ключей Anthropic и OpenAI. uv add anthropic и добавляем в check_keys.py функции ниже. Каркас (иллюстративный — вызовы сверяем с quickstart-ами):
    import os
    from dotenv import load_dotenv
    import anthropic
    from openai import OpenAI
    load_dotenv()
    ANTHROPIC_MODEL = os.environ["ANTHROPIC_MODEL"] # pick a cheap model from the docs, put it in .env
    OPENAI_MODEL = os.environ["OPENAI_MODEL"]
    def check_anthropic() -> None:
    client = anthropic.Anthropic()
    msg = client.messages.create(
    model=ANTHROPIC_MODEL,
    max_tokens=50,
    messages=[{"role": "user", "content": "Say 'ok' and nothing else."}],
    )
    ... # print the text block and msg.usage
    def check_openai() -> None:
    client = OpenAI()
    resp = client.responses.create(model=OPENAI_MODEL, input="Say 'ok' and nothing else.")
    ... # print resp.output_text and resp.usage
    if __name__ == "__main__":
    check_anthropic()
    check_openai()
    Ожидаемый результат: два коротких ответа и счётчики токенов в единицах–десятках. Стоимость — доли цента. Имена моделей держим в .env, а не в коде, и добавляем их имена в .env.example. Сравниваем в заметках: чем отличаются формы ответа (msg.content[0].text у Anthropic против choices[0].message.content у OpenAI-совместимых) и поля usage.
  • Цены. В notes/llm-basics.md: выписываем цену input (cache miss и cache hit) и output за миллион токенов для deepseek-flash и deepseek-v4-pro (вне пика и в пик) и дату, когда смотрели. Считаем: сколько стоит 1000 запросов по 2000 токенов входа и 500 выхода на каждой. Проверка для flash вне пика по ценам на 13.11.2026: 2M × $0.15 + 0.5M × $0.60 = $0.60. Для сравнения (если смотрели) — одна дешёвая и одна флагманская модель Claude и OpenAI. И строка для Ollama: $0, но записываем, сколько секунд занял ответ.
  • Учения по утечке (без настоящей утечки): находим в консоли DeepSeek (и в консолях Anthropic/OpenAI, если они заведены), где отзывается ключ, и записываем путь в notes/llm-basics.md, чтобы в стрессовой ситуации не искать.
  • Коммит заметок. Перед коммитом — git diff --staged, глазами убеждаемся, что ни одного ключа нет.
  • Можем за 2 минуты объяснить другу без жаргона, что такое токен и почему у модели есть контекстное окно (и почему модель не помнит прошлый разговор).
  • notes/llm-basics.md — 10–15 пунктов, табличка токенов, расчёт цены.
  • Ключ DeepSeek работает и Ollama отвечает локально (check_keys.py печатает оба ответа); баланс DeepSeek пополнен минимально, без автопополнения; подпись Ollama проверена до первого запуска; .env не виден в git status.
  • Если заведены ключи Anthropic/OpenAI — у них стоят лимиты расходов.
  • Можем сказать, какие данные куда можно отправлять (в DeepSeek и другие облачные модели — никаких персональных данных и рабочего кода; в Ollama с локальной моделью — да).
  • Первый час «Deep Dive» просмотрен, остальное запланировано на ближайшие недели.

Вопрос 1

Что именно выдаёт языковая модель на каждом шаге генерации?

  • a) готовое предложение
  • b) распределение вероятностей следующего токена
  • c) ближайший документ из обучающих данных
  • d) ответ из базы знаний

b. Модель выдаёт вероятности для каждого токена словаря; код вокруг выбирает (сэмплирует) один и повторяет цикл.

Вопрос 2

Почему модель плохо сравнивает 9.11 и 9.9 и считает буквы в слове?

Модель видит не цифры и буквы, а токены: число режется на куски, не совпадающие с разрядами, слово — на фрагменты. Посимвольные и разрядные операции ей неудобны.

Вопрос 3

Чем base model отличается от модели-ассистента и какая стадия обучения делает из первой вторую?

Base model только продолжает текст как документ из интернета; ассистента из неё делает SFT на примерах диалогов (и дальше RLHF/RL, которые настраивают предпочтения и рассуждения).

Вопрос 4

Пользователь спрашивает модель о службе доставки, которая запустилась на прошлой неделе, и получает подробный уверенный ответ. Что, скорее всего, произошло?

Галлюцинация: событие после knowledge cutoff, модель его не знает, но генерирует правдоподобное продолжение. Нужно дать актуальные данные в контексте (поиск, RAG, инструмент).

Вопрос 5

Почему контекстное окно ограничено и почему его стоимость растёт с длиной?

Attention сопоставляет каждый токен со всеми предыдущими, поэтому вычисления и память растут быстрее длины; плюс модель обучена на последовательностях ограниченной длины. Платим за каждый входной токен на каждом запросе.

Вопрос 6

Что такое эффект «lost in the middle» и как он влияет на то, как собирать промпт?

Информацию из середины длинного контекста модель использует хуже, чем из начала и конца. Значит: ключевые инструкции — в системный промпт и/или в конец, документы — только релевантные и компактные.

Вопрос 7

В чат-боте пользователь говорит «как я писал выше…». Как модель «помнит», что было выше, если API stateless?

Приложение каждый раз отправляет всю историю диалога в запросе. «Память» — это код и контекст, и за неё платим в каждом следующем запросе.

Вопрос 8

Что не так в этом коде?

client = anthropic.Anthropic(api_key="sk-ant-api03-...")

Ключ захардкожен в коде: попадёт в git, в логи, в скриншоты. Ключ должен приходить из окружения (ANTHROPIC_API_KEY), SDK подхватит его сам.

Вопрос 9

Файл .env с ключом случайно запушен в приватный репозиторий. Правильная первая реакция?

  • a) git rm --cached .env и новый коммит
  • b) переписать историю через force push
  • c) отозвать ключ в консоли и выпустить новый
  • d) сделать репозиторий приватным ещё раз

c. Сначала отозвать ключ — только это закрывает утечку. Убрать файл из git и почистить историю можно потом, но это вторично.

Вопрос 10

Почему выходные токены обычно стоят дороже входных и что это значит для дизайна промпта?

Генерация идёт токен за токеном и вычислительно дороже чтения входа. Для дизайна: просить краткие ответы, ограничивать max_tokens, не заставлять модель переписывать большие входные тексты.

Вопрос 11

Что не так в промпте, если его цель — получить точный итог по заказам?

Вот 400 заказов магазина в CSV. Посчитай выручку и комиссии по каждому платёжному провайдеру.

Модель просят считать: арифметика по 400 строкам токенизированных чисел даст правдоподобные, но неточные суммы. Посчитать должен код (pandas/SQL, на копии данных), а модели — дать готовые итоги для объяснения или вызывать функцию подсчёта как инструмент. Плюс заказы с данными покупателей нельзя отправлять облачному провайдеру.

Вопрос 12

Зачем ставить лимит расходов до создания первого ключа, а не после?

Ошибка в первом же скрипте (бесконечные ретраи, неограниченный параллелизм) может потратить деньги до того, как дойдут руки до лимита; лимит и небольшая предоплата ограничивают ущерб с первой минуты. У DeepSeek роль лимита играет маленький предоплаченный баланс.

Вопрос 13

Нужна краткая сводка по выгрузке заказов магазина за месяц (с именами и адресами покупателей). Какую модель выбрать?

  • a) deepseek-flash — дешевле всех
  • b) deepseek-v4-pro — умнее
  • c) локальную модель в Ollama
  • d) любую облачную модель из каталога Ollama

c. Персональные данные покупателей нельзя отправлять в DeepSeek (серверы в Китае) и в облачные модели Ollama (выполняются на серверах Ollama). Только локальная модель, скачанная через ollama pull. И итоги всё равно считает код — модель только описывает готовые цифры.

Вопрос 14

В deepseek-flash с настройками по умолчанию передаётся temperature=0, а ответы всё равно разные. Почему и что сделать?

По умолчанию у DeepSeek включён режим thinking, а в нём temperature не действует (ошибки нет, эффекта тоже). Для экспериментов с температурой выключаем thinking: extra_body={"thinking": {"type": "disabled"}}.

Вопрос 15

Что не так в этом коде?

client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
client.embeddings.create(model="deepseek-flash", input=["delivery cost"])

Клиент смотрит в локальную Ollama, а модель указана облачная, DeepSeek, — Ollama её не знает. К тому же эмбеддингов в документации DeepSeek нет вовсе. Нужна локальная embedding-модель, скачанная в Ollama, например bge-m3.

Дальше глава 1.6 · Сырой API: первые запросы к Claude и OpenAI — те же запросы на DeepSeek и Ollama, а Claude/OpenAI для сравнения, — и глава 1.7 · Скрипт: temperature, токены, стоимость: скрипт, который сравнивает ответы моделей и считает цену запроса (с ценами cache hit/miss у DeepSeek). Параллельно досматриваем «Deep Dive into LLMs» частями: к неделе 2 (промптинг, structured output, tool calling) полезно увидеть его части про галлюцинации и использование инструментов.