中文翻译暂不可用,显示俄语原文。
Как код как язык представления улучшает рассуждение LLM?
Краткий тезис
Код — это формальный язык с однозначной семантикой, исполнимостью и композициональностью. Когда LLM использует код (Python, SQL, псевдокод) как промежуточное представление для рассуждения, она получает возможность проверять свои шаги через выполнение, разбивать сложные задачи на модульные функции и комбинировать рассуждение с формальной верификацией. Это снижает галлюцинации, повышает точность и делает цепочку рассуждения прозрачной и воспроизводимой.
1. Термин: Код как язык представления (Code as Representation)
Код как язык представления — это подход, при котором LLM генерирует программный код (обычно Python) в качестве промежуточного шага перед финальным ответом. Вместо того чтобы рассуждать цепочкой на естественном языке (Chain-of-Thought), модель пишет исполняемые инструкции. Этот метод лежит в основе таких техник, как Program-of-Thought (PoT) и Code Agents.
| Аспект | Естественный язык | Код |
|---|---|---|
| Семантика | Неоднозначная, зависит от контекста | Строго определена синтаксисом и runtime |
| Проверяемость | Только экспертная оценка | Автоматическое выполнение и тестирование |
| Композициональность | Слабая (сложно формально комбинировать) | Сильная (функции, модули, импорты) |
| Масштабируемость | Ограничена длиной контекста | Может использовать внешние библиотеки и API |
2. Исполнимость (Executability)
Главное преимущество кода — его можно запустить и проверить результат. LLM может сгенерировать код, выполнить его в изолированной среде (песочнице) и получить обратную связь: совпадает ли вывод с ожидаемым, возникает ли ошибка.
Пример: Задача: «Сколько секунд в 2.5 часах?»
LLM на естественном языке может ошибиться: «2.5 * 60 * 60 = 9000 секунд» (неверно).
LLM, генерирующая код, напишет:
hours = 2.5
seconds = hours * 3600
print(seconds)
При выполнении получит 9000.0, что неверно (правильно 9000). Но если модель использует execution feedback, она может перепроверить: «2.5 * 3600 = 9000, верно». Однако в данном случае ответ верный, но часто модель может допустить арифметическую ошибку, а выполнение кода её исправит.
Механизм
- Генерация кода]] → выполнение в песочнице → получение stdout/stderr → повторная генерация с учётом ошибки (Self-Debugging).
- Это превращает рассуждение в итеративный процесс с обратной связью, что значительно повышает точность на математических и логических задачах.
3. Композициональность (Compositionality)
Код позволяет разбить сложную задачу на модульные функции, которые можно вызывать и комбинировать. LLM может сначала написать вспомогательные функции, а затем использовать их в основной логике.
Пример: Агент для анализа данных получает запрос: «Найди среднюю зарплату в отделе продаж за последний квартал».
Код:
def get_sales_data():
# вызов API или чтение БД
pass
def filter_last_quarter(data):
# фильтрация по дате
pass
def average_salary(data):
return sum(d.salary for d in data) / len(data)
sales = get_sales_data()
filtered = filter_last_quarter(sales)
result = average_salary(filtered)
Каждая функция может быть написана, отлажена и переиспользована отдельно. Это соответствует принципу разделяй и властвуй (divide and conquer), который улучшает рассуждение LLM, так как модель фокусируется на одной подзадаче за раз.
4. Четкая семантика (Unambiguous Semantics)
В естественном языке одна фраза может иметь несколько трактовок. Например, «увеличь число на 10%» — это умножить на 1.1 или прибавить 10? В коде семантика однозначна: x * 1.1 или x + 10. Это уменьшает амбигуозность (неоднозначность) и, как следствие, галлюцинации LLM.
Сравнение
- Естественный язык: «Если число делится на 3, выведи Fizz, иначе если на 5 — Buzz».
- Код:
if n % 3 == 0:
print("Fizz")
elif n % 5 == 0:
print("Buzz")
В коде нет неоднозначности: порядок условий, граничные случаи (например, делится на 3 и 5) явно определены.
5. Формальная верификация (Formal Verification)
Код можно проверять статически (типизация, линтеры) и динамически (юнит-тесты, property-based testing). LLM может генерировать не только код, но и спецификации (контракты, инварианты), которые затем проверяются формальными инструментами.
Пример:
- LLM пишет функцию сортировки и добавляет assert для проверки:
def sort_list(arr):
# реализация
return sorted_arr
# Проверка
assert sort_list([3,1,2]) == [1,2,3]
assert all(sort_list(arr)[i] <= sort_list(arr)[i+1] for i in range(len(arr)-1))
- Можно использовать формальные верификаторы (например, Z3, Dafny) для доказательства корректности. Это особенно ценно в Agentic RAG, где агенты выполняют код с побочными эффектами (доступ к БД, API).
6. Примеры техник, использующих код
- Program-of-Thought (PoT) — генерация кода вместо текстовой цепочки рассуждений. Показывает SOTA на математических бенчмарках (GSM8K, MATH).
- Self-Debugging — LLM выполняет свой код, получает ошибку и исправляет её без внешних сигналов.
- Code Agents (например, ReAct с кодом) — агент пишет код для вызова инструментов, обрабатывает результаты и планирует следующие шаги.
- Tool-using LLM — код используется для вызова API, парсинга ответов, агрегации данных.
7. Сравнение с рассуждением на естественном языке
| Критерий | Естественный язык (CoT) | Код (PoT / Code Agent) |
|---|---|---|
| Проверяемость | Только человеком | Автоматическая (выполнение) |
| Точность вычислений | Низкая (ошибки в арифметике) | Высокая (использует интерпретатор) |
| Модульность | Слабая | Сильная (функции, классы) |
| Обработка ошибок | Нет встроенной | Try/except, отладка |
| Затраты | Меньше токенов | Больше токенов (код + вывод) |
| Безопасность | Низкая (нет риска выполнения) | Требует песочницы |
8. Ограничения и риски
- Синтаксическая точность: LLM должна генерировать синтаксически корректный код. Ошибки в синтаксисе приводят к сбоям выполнения.
- Безопасность: Выполнение кода, сгенерированного LLM, может быть опасным (инъекции, бесконечные циклы, доступ к файловой системе). Требуется изолированная среда (Docker, gVisor, Pyodide).
- Неэффективность для некоторых задач: Для задач, требующих качественного анализа (например, реферирование текста), код не даёт преимуществ.
- Затраты токенов: Генерация кода и его вывода требует больше токенов, чем короткий текстовый ответ.
9. Интеграция в Agentic RAG
В архитектуре Agentic RAG код используется как универсальный язык для взаимодействия с инструментами:
- Retrieval: агент пишет код для запроса к векторной БД (например, через API).
- Reasoning: агент генерирует код для анализа извлечённых документов (фильтрация, агрегация, вычисления).
- Execution: агент выполняет код, получает результаты и передаёт их в следующий шаг.
- Verification: агент пишет тесты для проверки корректности своих действий.
Пример пайплайна:
- Запрос пользователя → LLM генерирует код для поиска документов.
- Выполнение кода → получение чанков.
- LLM генерирует код для анализа чанков (например, подсчёт статистики).
- Выполнение → финальный ответ.
10. Пет-проект для закрепления
Задача Создать агента, который решает математические задачи из датасета GSM8K, используя код как промежуточное представление.
Инструменты Python, библиотека openai, exec в изолированной среде (например, subprocess с ограничением ресурсов), датасет GSM8K (Hugging Face).
Шаги:
- Загрузить датасет и выбрать 10 задач.
- Для каждой задачи отправить промпт LLM с инструкцией: «Напиши Python-код для решения задачи. Выведи ответ в конце.»
- Выполнить сгенерированный код в песочнице (ограничить время выполнения, запретить опасные модули).
- Сравнить вывод с правильным ответом.
- Если код упал с ошибкой, передать сообщение об ошибке обратно LLM и попросить исправить (Self-Debugging).
- Посчитать accuracy и среднее количество итераций.
Ожидаемый результат Accuracy > 80% на выбранных задачах, понимание, как execution feedback улучшает рассуждение.
11. Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 180 | Архитектура Agentic RAG |
| 182 | Использование инструментов (tool use) |
| 186 | Исполнение кода в агентах |
| 187 | Формальная верификация в агентах |
| 188 | Обработка ошибок в агентах |
| 189 | Оценка агентов и рассуждений |
12. Навигация
- Предыдущий: 184
- Следующий: 186
- Индекс: 00. Индекс разборов
Навигация
- Предыдущий: 184
- Следующий: 186
- Индекс: 00. Индекс разборов