01. Физика LLM — как работает "мозг" агента¶
Зачем это нужно?¶
Чтобы управлять агентом, полезно понимать, как работает его "мозг". Без базового понимания физики LLM вы не сможете:
- Правильно настроить модель для агента
- Понять, почему агент ведет себя недетерминированно
- Управлять контекстом и историей диалога
- Избежать галлюцинаций и ошибок
В этой главе разберём основы работы LLM простым языком, без лишней математики.
Реальный кейс¶
Ситуация: Вы создали агента для DevOps. Пользователь пишет: "Проверь статус сервера web-01"
Проблема: Агент иногда отвечает текстом "Сервер работает", а иногда вызывает инструмент check_status. Поведение непредсказуемо.
Решение: Понимание вероятностной природы LLM помогает управлять разнообразием генерации: низкая Temperature, чёткие Description у инструментов. Но предсказуемость процесса агента обеспечивает не «детерминизм» модели, а структура — строгие схемы вызовов, валидация ответов и гарды в коде. Понимание контекстного окна помогает управлять историей диалога.
Теория простыми словами¶
Вероятностная природа¶
Ключевой факт: LLM не думает, она предсказывает.
LLM — это функция NextToken(Context) -> Distribution.
На вход подается последовательность токенов \(x_1, ..., x_t\). Модель вычисляет распределение вероятностей для следующего токена:
Что это значит на практике?
Примечание: Примеры ниже используют Function Calling — механизм вызова инструментов через LLM API. Детальное объяснение — в Главе 03: Инструменты и Function Calling. Сейчас достаточно понимать, что модель получает описания инструментов (
tools[]) и выбирает подходящий на основеDescription.
Пример 1: DevOps — Магия vs Реальность¶
Магия (как обычно объясняют):
Промпт:
"Проверь статус сервера"
Модель видит контекст и предсказывает: "Я вызову инструментcheck_status" (вероятность 0.85)
Реальность (как на самом деле):
1. Что отправляется в модель:
// Нейтральные структуры для прямого протокола tool-calling.
// У большинства провайдеров (облачных и локальных) протокол выглядит так же —
// детали и полный цикл см. в Главе 03.
type Message struct {
Role string // "system" | "user" | "assistant" | "tool"
Content string
ToolCalls []ToolCall // заполняется моделью для role="assistant"
ToolCallID string // для role="tool": ID вызова, к которому относится результат
}
type ToolCall struct {
ID string // например, "call_abc123"
Name string // например, "check_status"
Arguments string // JSON-строка, например {"hostname":"web-01"}
}
type ToolDef struct {
Name string
Description string
Parameters json.RawMessage // JSON Schema аргументов
}
type Request struct {
Model string
Messages []Message
Tools []ToolDef
Temperature float64
}
// System Prompt (задает роль и поведение)
systemPrompt := `You are a DevOps assistant.
When user asks about server status, use the check_status tool.
When user asks about logs, use the read_logs tool.
When user asks to restart, use the restart_service tool.`
// User Input
userInput := "Проверь статус сервера"
// Описание доступных инструментов (tools schema)
// ВАЖНО: Модель видит ВСЕ инструменты и выбирает нужный!
tools := []ToolDef{
{
Name: "check_status",
Description: "Check the status of a server by hostname. Use this when user asks about server status or availability.",
Parameters: json.RawMessage(`{
"type": "object",
"properties": {
"hostname": {"type": "string", "description": "Server hostname"}
},
"required": ["hostname"]
}`),
},
{
Name: "read_logs",
Description: "Read the last N lines of service logs. Use this when user asks about logs, errors, or troubleshooting.",
Parameters: json.RawMessage(`{
"type": "object",
"properties": {
"service": {"type": "string", "description": "Service name"},
"lines": {"type": "number", "description": "Number of lines to read"}
},
"required": ["service"]
}`),
},
{
Name: "restart_service",
Description: "Restart a systemd service. Use this when user explicitly asks to restart a service. WARNING: This causes downtime.",
Parameters: json.RawMessage(`{
"type": "object",
"properties": {
"service_name": {"type": "string", "description": "Service name to restart"}
},
"required": ["service_name"]
}`),
},
}
// Полный запрос к API
req := Request{
Model: "glm-5.3", // любая актуальная модель с native tool calling
Messages: []Message{
{Role: "system", Content: systemPrompt},
{Role: "user", Content: userInput},
},
Tools: tools, // Важно: модель видит описание инструментов!
}
2. Что возвращает модель:
Модель не возвращает текст "Я вызову инструмент". Она возвращает структурированный tool call:
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "check_status",
"arguments": "{\"hostname\": \"web-01\"}"
}
}
]
}
Как модель выбирает инструмент?
Модель видит все три инструмента и их Description:
check_status: "Check the status... Use this when user asks about server status"read_logs: "Read logs... Use this when user asks about logs"restart_service: "Restart service... Use this when user explicitly asks to restart"
Запрос пользователя: "Проверь статус сервера"
Модель сопоставляет запрос с описаниями:
-
check_status— описание содержит "server status" → выбирает этот -
read_logs— описание про логи, не про статус -
restart_service— описание про рестарт, не про проверку
Пример с другим запросом:
userInput := "Покажи последние ошибки в логах nginx"
// Модель видит те же 3 инструмента
// Сопоставляет:
// - check_status: про статус, не про логи → не подходит
// - read_logs: "Use this when user asks about logs" → ВЫБИРАЕТ ЭТОТ
// - restart_service: про рестарт → не подходит
// Модель возвращает:
// tool_calls: [{function: {name: "read_logs", arguments: "{\"service\": \"nginx\", \"lines\": 50}"}}]
Суть: Модель выбирает инструмент на основе семантического соответствия между запросом пользователя и Description инструмента. Чем точнее Description, тем лучше выбор.
3. Что делает Runtime:
resp, err := client.Complete(ctx, req) // нейтральный вызов: один протокол, любой провайдер
if err != nil {
return err // ошибки клиента — не для модели: retry/логи в коде (гл. 04)
}
msg := resp.Choices[0].Message // ответ модели
// Runtime проверяет: есть ли tool_calls?
if len(msg.ToolCalls) > 0 {
call := msg.ToolCalls[0]
// Парсим аргументы (Arguments — JSON-строка)
var args struct {
Hostname string `json:"hostname"`
}
json.Unmarshal([]byte(call.Arguments), &args)
// Выполняем реальную функцию
result := checkStatus(args.Hostname) // "Server is ONLINE"
// Возвращаем результат обратно в модель:
// assistant-сообщение с tool_calls + результат с role="tool"
req.Messages = append(req.Messages, msg,
Message{Role: "tool", Content: result, ToolCallID: call.ID},
)
// Отправляем обновленную историю в модель снова
// Модель видит результат и решает, что делать дальше
}
Примечание о "вероятностях":
Цифры типа "вероятность 0.85" — это иллюстрация. API провайдеров (облачных и локальных) обычно не возвращает эти вероятности напрямую (если не использовать logprobs). Важно другое: когда в контексте есть tools с хорошим Description, модель с высокой вероятностью выберет tool call вместо текста. Но это происходит внутри модели — снаружи мы видим только итоговый выбор.
Пример 2: Support — Магия vs Реальность¶
Магия:
Промпт:
"Пользователь жалуется на ошибку 500"Модель предсказывает: "Сначала соберу контекст черезget_ticket_details" (вероятность 0.9)
Реальность: Принцип тот же, что и в DevOps-примере. Модель получает 4 инструмента (get_ticket_details, check_account_status, search_kb, draft_reply) с описаниями. Она выбирает get_ticket_details, потому что его Description содержит "Use this FIRST when user reports an error" — наилучшее семантическое совпадение с запросом.
Модель выбирает инструменты последовательно:
// Итерация 1: Пользователь жалуется на ошибку
// Модель выбирает: get_ticket_details (собирает контекст)
// Итерация 2: В контексте появились детали тикета
// Модель выбирает: search_kb("error 500") (ищет решение)
// Итерация 3: В контексте появилось решение из KB
// Модель выбирает: draft_reply(ticket_id, solution) (создает ответ)
Runtime на каждой итерации парсит tool call, выполняет функцию и возвращает результат. Подробнее о протоколе tool call — в Главе 03.
Пример 3: Data Analytics — Магия vs Реальность¶
Магия:
Промпт:
"Покажи продажи за последний месяц"Модель предсказывает: "Сформулирую SQL-запрос черезsql_select" (вероятность 0.95)
Реальность: Модель получает 3 инструмента (describe_table, sql_select, check_data_quality). Запрос "Покажи продажи за последний месяц" лучше всего соответствует sql_select с описанием "when user asks for specific data or reports". Модель генерирует SQL прямо в аргументах:
{
"tool_calls": [{
"function": {
"name": "sql_select",
"arguments": "{\"query\": \"SELECT region, SUM(amount) FROM sales WHERE date >= NOW() - INTERVAL '1 month' GROUP BY region\"}"
}
}]
}
Для сложных вопросов модель использует инструменты последовательно: сначала describe_table (узнать структуру), потом sql_select (получить данные), потом check_data_quality (проверить качество). Runtime валидирует, что это SELECT (не DELETE/DROP!), и выполняет запрос через read-only соединение. Подробнее — в Главе 03.
Почему это важно для инженера?¶
1. Недетерминированность¶
Запустив агента дважды с одним промптом, вы можете получить разные действия.
Пример:
Запрос 1: "Проверь сервер"
Ответ 1: [Вызывает check_status]
Запрос 2: "Проверь сервер" (тот же промпт)
Ответ 2: [Отвечает текстом "Сервер работает"]
Решение: Понизьте Temperature (для агентных циклов типично 0.0–0.3) — это уменьшает разнообразие генерации и делает выбор инструментов более устойчивым. Но не ждите «детерминизма»: у многих провайдеров T=0 технически не гарантирует greedy-декодинг (батчинг запросов, MoE-архитектуры). Воспроизводимость процесса агента дают структура (JSON Schema, валидация), гарды в коде и evals — об этом подробнее в разделе «Температура» ниже.
req := Request{
Model: "glm-5.3",
Temperature: 0.2, // меньше разброса в выборе инструментов
// ...
}
2. Галлюцинации¶
Модель стремится сгенерировать правдоподобный, а не истинный текст.
DevOps пример: Модель может написать "используй флаг --force" для команды, которая его не поддерживает.
Data пример: Модель может сгенерировать SQL с несуществующим полем user.email вместо users.email.
Support пример: Модель может "выдумать" решение проблемы, которого нет в базе знаний.
Решение: Grounding (Заземление). Мы даем агенту доступ к реальным данным (Tools/RAG) и запрещаем выдумывать факты.
systemPrompt := `You are a DevOps assistant.
Do not invent facts: you have tools that return real data, and real data
is always more reliable than a plausible guess. If you don't know
something, say "I don't know" or use a tool.`
Токены и контекстное окно¶
Что такое токен?¶
Токен — это единица текста, которую обрабатывает модель.
- Один токен ≈ 0.75 слова (в английском)
- В русском: одно слово ≈ 1.5 токена
Пример:
Контекстное окно (Context Window)¶
Контекстное окно — это "оперативная память" модели.
Порядок величин (без точных цифр, которые быстро устаревают):
- У современных моделей контекстные окна — от ~128k до ~1M токенов (GLM-5.3, Fable 5.1, Opus 5.5)
- Точное значение смотрите в документации провайдера — окна меняются чаще, чем выходят версии книг
Примечание: Главное — принцип: чем больше контекстное окно, тем больше информации агент может "помнить" в одном запросе. Но большое окно не отменяет управление контекстом: длинная история стоит денег и деградирует по качеству (см. Главу 13: Context Engineering).
Что это значит для агента?
Все, что агент "знает" о текущей задаче — это то, что влезает в контекстное окно (Prompt + History).
Пример расчета (приблизительно):
Контекстное окно: 128k токенов
System Prompt + tools: 2k токенов
История диалога: 60k токенов
Результаты инструментов: 30k токенов
Осталось места: 36k токенов
Важно для агента (правило главы 13). В рантайме агента первичный источник числа токенов —
usage.PromptTokens/usage.CompletionTokensиз ответа провайдера, а не свой счётчик: провайдер уже знает свой токенайзер и применил его. Для грубой пред-оценки до отправки достаточно эвристики ~3 символа/токен (для английского ближе к 4); токенайзеры вродеtiktokenточнее, но для решения «не пора ли сжимать историю» эта точность обычно не нужна. Делать бюджет агента на основе только своих оценок — рецепт расхождения с реальностью на 10–30%, что особенно больно у большого окна. Подробнее см. Глава 13: Context Engineering.
Если история переполняется, агент "забывает" начало разговора. На практике это значит: либо ранние сообщения обрезаны/сжаты (и модель их реально не видит), либо, если переполнение не обработать, API вернёт ошибку превышения контекстного окна.
Модель Stateless: Она не помнит ваш прошлый запрос, если вы не передали его снова в messages.
// Каждый запрос должен включать всю историю
messages := []Message{
{Role: "system", Content: systemPrompt},
{Role: "user", Content: "Проверь сервер"},
{Role: "assistant", Content: "Проверяю..."},
{Role: "tool", Content: "Server is ONLINE"},
{Role: "user", Content: "А что с базой?"}, // Агент видит всю историю!
}
Температура (Temperature)¶
Температура — это настройка качества и разнообразия генерации: она управляет энтропией распределения вероятностей при выборе следующего токена.
Temperature: 0.0–0.3 // типично для агентных циклов и структурированных вызовов
Temperature: 0.7 // баланс креативности и стабильности
Temperature: 1.0+ // креативные задачи, брейншторм
Когда использовать какое значение?¶
| Temperature | Использование | Пример |
|---|---|---|
| 0.0–0.3 | Агентные циклы, структурированные вызовы, JSON | DevOps-агент стабильно вызывает restart_service, а не "творит"; выбор инструментов и аргументов дополнительно фиксируется JSON Schema и валидацией |
| 0.3–0.7 | Шаблонные ответы, черновики | Support-агент генерирует шаблоны ответов |
| 0.7–1.0 | Креативные задачи | Product-агент пишет маркетинговые тексты |
Чего температура не даёт¶
Распространённое заблуждение: «Temperature = 0 делает агента детерминированным». Это не так:
- Технически
T=0у многих провайдеров не гарантирует greedy-детерминизм: батчинг запросов и MoE-архитектуры вносят недетерминизм независимо от температуры. - Воспроизводимость процесса агента дают не настройки сэмплинга, а структура: строгая JSON Schema для аргументов инструментов, валидация ответов, гарды в коде (контроль допустимых действий) и evals, фиксирующие поведение.
Низкая температура снижает разброс и «шум» в выборе инструментов — это полезно. Но это настройка качества генерации, а не переключатель «детерминизм вкл/выкл».
Практический пример:
// ПЛОХО: для агентного цикла
req := Request{
Temperature: 0.9, // слишком большой разброс: модель будет "творить"
// ...
}
// ХОРОШО: для агентного цикла
req := Request{
Temperature: 0.2, // меньше разброса; предсказуемость процесса — schema + гарды + evals
// ...
}
Выбор модели¶
Не все модели одинаково хороши для агентов.
Актуальные модели (на момент ревизии)¶
- Fable 5.1 и Opus 5.5 — флагманские модели для сложных агентных сценариев
- GLM-5.3 — сильная модель с native tool calling, хороший баланс цены и качества
- GLM-5.3 Flash — дешёвый и быстрый вариант для массовых и простых вызовов
Примечание: Имена и версии моделей живут месяцами, а не годами. Доверяйте не спискам из книг, а свежей документации провайдера и собственному capability-тесту (см. ниже).
Локальный запуск¶
Для локального запуска (Ollama, vLLM, LM Studio) берите актуальную instruct-модель с заявленной поддержкой function calling — и обязательно прогоняйте capability benchmark: работа инструментов в локальных рантаймах зависит от chat-шаблона модели, а не только от весов.
Критерии выбора¶
-
Поддержка Function Calling (native tool calling): Модель должна уметь генерировать структурированные вызовы инструментов.
- Хорошо: модели с native tool calling (GLM-5.3, GLM-5.3 Flash, Fable 5.1, Opus 5.5)
- Плохо: базовые модели без обучения на tools
Примечание: Конкретные модели меняются. Проверяйте поддержку function calling через capability benchmark (см. Приложение: Capability Benchmark).
-
Размер контекста: В окно должны помещаться system prompt, tools, история и результаты инструментов. У современных моделей это от ~128k токенов — при условии управления контекстом (см. Главу 13) этого обычно достаточно.
-
Качество следования инструкциям: Модель должна строго следовать System Prompt.
- Проверяется через capability benchmark (см. Приложение: Capability Benchmark)
-
Совместимость chat-шаблона (для локальных рантаймов): Роли сообщений (system, user, assistant, tool) должны соответствовать chat-шаблону модели, иначе tool-протокол не заработает. Подробнее см. Ошибка 3: LM Studio — неверный Prompt Template в разделе "Типовые ошибки". У облачных провайдеров с native tool calling этой проблемы нет.
Как проверить модель?¶
Теория: См. Приложение: Capability Benchmark — подробное описание того, что проверяем и почему это важно.
Практика: См. Lab 00: Model Capability Benchmark — готовый инструмент для проверки модели.
Типовые ошибки¶
Ошибка 1: Модель ведет себя по-разному при одинаковых запросах¶
Симптом: Один и тот же промпт дает разные результаты. Агент иногда вызывает инструмент, иногда отвечает текстом.
Причина: LLM сэмплирует из распределения вероятностей. При высокой температуре разброс растет, и «серые зоны» — ситуации, где и текст, и tool call правдоподобны — становятся нестабильными.
Решение:
// ПЛОХО: высокая температура в агентном цикле
req := Request{
Temperature: 0.9, // большой разброс: выбор инструментов нестабилен
// ...
}
// ХОРОШО: низкая температура + структурные гарантии
req := Request{
Temperature: 0.2, // меньше разброса
// ...
}
// И главное: валидируйте tool calls по JSON Schema, отклоняйте
// нераспарсенные аргументы, ограничивайте допустимые инструменты.
// Воспроизводимость процесса агента дают гарды и evals, а не температура.
Ошибка 2: Контекст переполняется¶
Симптом: Агент "забывает" начало разговора. После N сообщений перестает помнить, что обсуждалось в начале. Или API возвращает ошибку превышения контекстного окна.
Причина: История диалога растет и превышает размер контекстного окна модели.
Решение: Condense — одно сжатие истории при подходе к лимиту
Канонический механизм (подробнее — Глава 09: Memory и Глава 13: Context Engineering):
- Порог — ~0.85 контекстного окна, считается по
usage.PromptTokensиз ответа провайдера (не по собственному счётчику). - Максимум одно сжатие за Run: при превышении порога старая часть истории (head) суммируется отдельным LLM-вызовом, свежая (tail) сохраняется как есть.
- Пары
tool_call↔tool_resultне разрываются: граница сжатия проходит только между завершёнными парами, иначе история становится невалидной. - Кэшируемый префикс не меняется:
messages[0](system prompt) и списокtoolsостаются неизменными — провайдер кэширует именно этот префикс.
// Condense: порог по данным провайдера, head -> summary, tail как есть
const condenseThreshold = 0.85
if float64(resp.Usage.PromptTokens) > condenseThreshold*float64(ctxWindow) && !condensed {
// 1. Граница: индекс, на котором завершена последняя пара
// tool_call <-> tool_result (пары не разрываем!)
cut := lastCompleteToolBoundary(req.Messages)
// 2. Head (все после system) суммируем отдельным LLM-вызовом
summary := summarize(ctx, req.Messages[1:cut])
// 3. Новый контекст: system (без изменений!) + summary + tail
req.Messages = append([]Message{
req.Messages[0], // system: мутировать нельзя — сломает prompt cache
{Role: "user", Content: "Summary of earlier conversation:\n" + summary},
}, req.Messages[cut:]...)
condensed = true // не чаще одного раза за Run
}
Почему НЕ «вставить summary вторым system-сообщением»?
Частый соблазн — приклеить сжатую историю сразу после system:
// ПЛОХО: мутирует кэшируемый префикс
compressed := []Message{
systemMsg,
{Role: "system", Content: "Summary of previous conversation:\n" + summary},
}
Это ломает prompt cache: провайдер кэширует неизменный префикс (system + tools). Вставка нового сообщения сразу после system меняет префикс — кэш инвалидируется, и каждый запрос после сжатия оплачивается полностью. Summary должно идти в теле истории (например, как user-сообщение), а messages[0] трогать нельзя.
Почему НЕ обрезка?
Наивная обрезка «System + последние N» теряет важную информацию из начала: имя пользователя, контекст задачи, принятые решения. Condense сохраняет суть: 2000 токенов сжимаются до ~200 с сохранением ключевых фактов.
Пример:
Исходная история (60k токенов):
- User: "Меня зовут Иван, я DevOps инженер"
- Assistant: "Привет, Иван!"
- User: "У нас проблема с сервером"
- Assistant: "Опишите проблему"
... (еще 50 сообщений и результаты инструментов)
- После обрезки: теряем имя и контекст
- После condense: "Пользователь Иван, DevOps инженер. Обсуждали проблему с сервером. Текущая задача: диагностика." + свежие сообщения как есть
См. подробнее: раздел "Memory (Память)" в Главе 09: Анатомия Агента и Lab 09: Context Optimization
Ошибка 3: LM Studio — неверный Prompt Template (ошибка ролей)¶
Симптом: При локальном запуске через LM Studio вы получаете ошибку вида "Only user and assistant roles are supported!".
Причина и решение: Chat-шаблон модели принимает только роли user/assistant и не знает ролей system/tool, которые нужны агенту. Выберите в настройках модели шаблон, соответствующий ей (ChatML-совместимый или специфичный для семейства модели), или возьмите модель из репозитория с уже корректным шаблоном. У облачных провайдеров с native tool calling этой проблемы нет.
Критерии сдачи / Чек-лист¶
Сдано:
- Понимаете, что LLM предсказывает токены, а не "думает"
- Понимаете, что температура — настройка качества генерации; воспроизводимость процесса агента дают JSON Schema, валидация, гарды и evals
- Понимаете ограничения контекстного окна
- Знаете, как управлять историей диалога (condense при ~0.85 окна по
usage.PromptTokens) - Модель поддерживает Function Calling (проверено через Lab 00)
- System Prompt мотивированно запрещает галлюцинации, grounding через Tools/RAG настроен
Не сдано:
- Разброс поведения агента не контролирован (высокая температура, нет валидации tool calls)
- Агент "забывает" начало разговора (контекст переполняется, condense не реализован)
- Модель выдумывает факты (нет grounding через Tools/RAG)
Мини-упражнения¶
Упражнение 1: Подсчет токенов¶
Контекст. Эта функция — пред-оценка, чтобы прикинуть, не пора ли сжимать историю до отправки запроса. После запроса используем
resp.Usage.PromptTokensот провайдера как авторитетный источник. См. примечание в разделе «Контекстное окно» выше и Главу 13.
Напишите функцию, которая приблизительно подсчитывает количество токенов в тексте:
func estimateTokens(text string) int {
// Примерная оценка: 1 токен ≈ 4 символа (для английского)
// Для русского: 1 токен ≈ 3 символа
return len(text) / 4
}
Ожидаемый результат:
- Функция возвращает приблизительное количество токенов
- Учитывает разницу между английским и русским текстом
Упражнение 2: Управление историей¶
Реализуйте функцию обрезки истории сообщений:
func trimHistory(messages []Message, maxTokens int) []Message {
// Оставляем System Prompt + последние сообщения, которые влезают в maxTokens
// Граница обрезки не должна разрывать пару tool_call <-> tool_result
// ...
}
Ожидаемый результат:
- System Prompt всегда остается первым (messages[0] не мутируется)
- Последние сообщения добавляются, пока не превысят maxTokens
- Граница обрезки не разрывает пары
tool_call↔tool_result - Функция возвращает обрезанную историю
Для любопытных¶
Углубление в формализм. Можно пропустить, если вас интересует только практика.
Температура — формально¶
Температура \(T\) масштабирует логиты распределения \(P(x_{t+1} | x_1, ..., x_t)\) перед softmax: при \(T \to 0\) распределение вырождается в аргмакс (greedy), при \(T = 1\) остается "как есть", при \(T > 1\) выравнивается и становится более случайным. Отсюда практический эффект из раздела «Температура»: низкая температура сужает разброс генерации, но не гарантирует воспроизводимость на уровне провайдера (батчинг, MoE).
Почему модель "выбирает" инструмент?¶
Формально модель не «выбирает» — она генерирует последовательность токенов, соответствующую формату tool call, потому что обучалась на примерах вызовов функций. System Prompt и tools[] смещают распределение в сторону этого формата: чем точнее Description инструмента совпадает с запросом, тем выше вероятность соответствующих токенов. Никакой магии — результат обучения.
Связь с другими главами¶
- Function Calling: Подробнее о том, как модель генерирует tool calls, см. Главу 03: Инструменты
- Контекстное окно: Как управлять историей сообщений, см. Главу 09: Анатомия Агента и Главу 13: Context Engineering
- Temperature: Почему температура — настройка качества генерации, а воспроизводимость дают структура, гарды и evals — см. раздел «Температура» в этой главе и Главу 13: Context Engineering
Что дальше?¶
После изучения физики LLM переходите к:
- 02. Промптинг как Программирование — как управлять поведением модели через промпты