Chain of Code (CoC)

[object Object]

Chain of Code (цепочка кода) — техника от Google DeepMind, при которой модель формулирует шаги рассуждения как код, а затем исполняет их там, где это возможно. Если шаг можно доверить интерпретатору (арифметика, логика, преобразование структур) — он выполняется как программа. Если шаг не сводится к исполнимому коду (семантика, здравый смысл, оценка тона) — модель временно играет роль LMulator и возвращает значение сама.

В 2026 году CoC полезнее понимать не как «ещё один prompt trick», а как гибридный runtime-паттерн между Program of Thoughts, tool use и reasoning orchestration. Он окупается там, где одна и та же задача сочетает точные вычисления и неформальные выводы, но почти не нужен там, где всё можно либо полностью формализовать, либо полностью оставить текстовому reasoning.

Представьте повара с рецептом. Некоторые шаги можно выполнить точно по инструкции: «варить 7 минут при 100°C» — это как исполнение кода. Но другие шаги требуют чутья: «добавить соль по вкусу» — это невозможно запрограммировать, и повар импровизирует. Chain of Code работает так же: где можно — считает точно (выполняет код), где нельзя — «импровизирует» (эмулирует код текстом).

Суть в двух словах

Chain of Code развивает идею Program of Thoughts: модель записывает рассуждения в виде кода. Но в отличие от PoT, где весь код должен быть исполняемым, CoC допускает «псевдокод» для семантических задач.

Ключевая идея — LMulator (Language Model emulator): если строка кода не может быть выполнена интерпретатором Python (например, is_sarcastic = detect_sarcasm("Конечно, прекрасная погода")), модель сама определяет результат и подставляет значение. Получается гибрид: точные вычисления через интерпретатор + семантическое понимание через LLM.

ПромптClaude
Используй подход Chain of Code. Задача: В отзыве «Доставка приехала через 3 дня вместо обещанного 1 дня. Товар рабочий, но коробка помята. Цена 2500 руб. за такое качество — ну ок.» Определи: 1) задержку доставки в днях, 2) тональность отзыва, 3) соотношение цена/качество.
Ответ модели
# Шаг 1: Задержка доставки (исполняемый код)
promised_days = 1
actual_days = 3
delay = actual_days - promised_days  # = 2 дня

# Шаг 2: Тональность (LMulator — эмуляция)
review = "Доставка приехала через 3 дня вместо обещанного 1 дня. Товар рабочий, но коробка помята. Цена 2500 руб. за такое качество — ну ок."
sentiment = analyze_sentiment(review)  # = "негативно-нейтральная"
# Пояснение: есть недовольство задержкой и упаковкой, но товар работает

# Шаг 3: Соотношение цена/качество (гибрид)
price = 2500
product_works = True  # из текста: "товар рабочий"
packaging_damaged = True  # "коробка помята"
value_score = rate_value(price, product_works, packaging_damaged)  # = "среднее"

result = {
    "delay_days": delay,           # 2
    "sentiment": sentiment,         # негативно-нейтральная
    "value_rating": value_score     # среднее
}

Результат: задержка 2 дня, тональность негативно-нейтральная, цена/качество — среднее.

CoT — всё текстом (гибко, но ошибается в вычислениях). PoT — всё кодом (точно, но не работает для семантических задач). CoC — гибрид: код для вычислений, эмуляция для семантики. Используйте CoC, когда задача сочетает числа и понимание смысла.

Как работает Chain of Code

Два режима выполнения

Chain of Code объединяет два способа обработки каждой строки кода:

Типы задач и режимы

Тип задачиРежимПример
АрифметикаИнтерпретаторtotal = price * quantity * 1.2
ЛогикаИнтерпретаторif age >= 18 and has_passport:
Строковые операцииИнтерпретаторwords = text.split(); count = len(words)
Тональность текстаLMulatorsentiment = analyze_sentiment(review)
КлассификацияLMulatorcategory = classify(email_subject)
Common senseLMulatoris_appropriate = check_dress_code("шорты", "собеседование")

Преимущества гибридного подхода

Chain of Thought (всё текстом)
Задержка: 3 - 1 = 2 дня. ✓ Штраф за задержку: 2500 × 0.01 × 2 = 50 руб. ✓ Но иногда: 2500 × 0.01 × 2 = 75 руб. ✗ (арифметическая ошибка) Тональность: негативная ✓ (модель хорошо понимает) Всё в одном формате — нет разделения ответственности.
Chain of Code (гибрид)
delay = 3 - 1 # → Python: 2 ✓ (точно) penalty = 2500 * 0.01 * delay # → Python: 50.0 ✓ (точно) sentiment = analyze(review) # → LMulator: 'негативная' ✓ Каждый шаг выполняется оптимальным способом.

Когда использовать Chain of Code

Плюсы

  • Точность вычислений: арифметика через интерпретатор, без ошибок
  • Гибкость: семантические задачи через LMulator, не ограничен кодом
  • Структурированность: переменные и функции делают рассуждение прозрачным
  • +12% на BIG-Bench Hard по сравнению с Chain of Thought
  • Работает с гибридными задачами (числа + смысл)

Минусы

  • Сложнее в реализации: нужен интерпретатор + fallback на LLM
  • Требует мощных моделей: слабые модели плохо эмулируют код
  • Дороже CoT: больше токенов на генерацию кода
  • Не все задачи выигрывают: чисто текстовые задачи лучше решать CoT

Идеальные сценарии:

  • Анализ данных с интерпретацией (числа + выводы)
  • Отзывы и фидбек (метрики + тональность)
  • Бизнес-логика (расчёты + правила + исключения)
  • Тестирование гипотез (вычисления + оценка результатов)
Сравнение техник на BIG-Bench Hard (% точности)
Chain of Code (CoC)84%
Chain of Thought (CoT)72%
Program of Thoughts (PoT)75%
Direct Prompting58%
Качество эмуляции напрямую зависит от мощности модели. GPT-4o и Claude Sonnet хорошо эмулируют семантические функции. Модели слабее (GPT-3.5, мелкие open-source) могут давать неточные результаты при эмуляции, сводя преимущество CoC к нулю.

Как понимать Chain of Code в 2026

В текущем стеке reasoning-систем CoC стоит между тремя мирами:

  • PoT и PAL, где вычислительная часть полностью уходит в исполнимый код
  • tool use, где модель вызывает отдельные калькуляторы, SQL, Python sandbox или внешние функции
  • обычным CoT, где всё остаётся в тексте и цена ошибки в промежуточных вычислениях выше

Поэтому главный вопрос уже не «лучше ли CoC, чем CoT вообще», а «есть ли у задачи смешанный контур». Если половина шага требует точного исполнения, а другая половина остаётся оценочной, CoC даёт более естественную рамку, чем попытка либо всё программировать, либо всё проговаривать текстом.

Где CoC реально окупается

Лучшие сценарии для CoC в production обычно выглядят так:

  • аналитика отзывов, инцидентов или тикетов, где нужно и посчитать метрики, и оценить текст
  • pricing, finance и ops-задачи, где есть правила, формулы и исключения, описанные естественным языком
  • agent workflows, в которых промежуточный Python дешевле и надёжнее, чем повторное текстовое рассуждение
  • data QA, где часть ответа можно получить программно, а часть требует интерпретации результата

Если же у вас либо чистая математика, либо чистая семантика, CoC обычно проигрывает более простым маршрутам:

  • для чистых вычислений лучше Program of Thoughts, PAL или прямой Python tool
  • для чистого анализа текста лучше хороший reasoning-model с явными критериями ответа

Практические границы техники

У CoC есть три типичных ограничения, которые часто недооценивают:

  1. LMulator не превращает неформальную функцию в надёжный инструмент. analyze_sentiment(text) всё ещё остаётся обычным LLM-выводом, просто упакованным как код.
  2. Гибридный пайплайн сложнее дебажить: ошибка может жить либо в коде, либо в эмуляции, либо в переключении между ними.
  3. Чем больше в задаче фальшивых «псевдофункций», тем меньше остаётся реального преимущества перед обычным CoT.

Хорошее эмпирическое правило: если более 60-70% шагов в трассе оказываются неисполняемыми, вы уже не используете Chain of Code по назначению, а просто маскируете текстовое reasoning под код.

Техническая реализация

Базовый CoC-промпт

COC_SYSTEM_PROMPT = """Ты решаешь задачи методом Chain of Code.

Правила:
1. Запиши каждый шаг рассуждения как строку Python-кода
2. Для вычислений используй стандартные операции Python
3. Для семантических задач используй описательные функции:
   - analyze_sentiment(text) → str
   - classify(text, categories) → str
   - extract_entities(text) → list
   - is_relevant(text, topic) → bool
4. Добавляй комментарии, объясняющие логику
5. В конце собери результат в словарь result = {}

Интерпретатор выполнит арифметику и логику.
Семантические функции ты выполняешь сам (LMulator)."""

Реализация LMulator

import ast
import traceback
from openai import OpenAI

client = OpenAI()

def execute_with_lmulator(code: str, model: str = "gpt-4o") -> dict:
    """
    Выполняет код построчно:
    - исполняемые строки → Python exec()
    - неисполняемые → LLM эмулирует результат
    """
    namespace = {}
    lines = code.strip().split("\n")
    execution_log = []

    for i, line in enumerate(lines):
        stripped = line.strip()

        # Пропускаем пустые строки и комментарии
        if not stripped or stripped.startswith("#"):
            execution_log.append(f"# {stripped}")
            continue

        try:
            # Попытка выполнить через Python
            exec(line, namespace)
            execution_log.append(f"[exec] {stripped}")

        except Exception as e:
            # Строка не исполняется — используем LMulator
            execution_log.append(f"[lmulator] {stripped}")

            # Извлекаем имя переменной (если есть присваивание)
            var_name = None
            if "=" in stripped and not stripped.startswith("if"):
                var_name = stripped.split("=")[0].strip()

            # LLM эмулирует результат
            context = "\n".join(
                f"{k} = {repr(v)}" for k, v in namespace.items()
                if not k.startswith("_")
            )
            prompt = f"""Текущие переменные:
{context}

Выполни строку кода и верни только результат (значение):
{stripped}

Верни ТОЛЬКО значение, без кода и пояснений."""

            response = client.chat.completions.create(
                model=model,
                messages=[
                    {"role": "system", "content": "Ты LMulator — эмулятор кода."},
                    {"role": "user", "content": prompt}
                ],
                temperature=0
            )

            result_text = response.choices[0].message.content.strip()

            # Попытка привести к Python-типу
            try:
                value = ast.literal_eval(result_text)
            except (ValueError, SyntaxError):
                value = result_text.strip('"\'')

            if var_name:
                namespace[var_name] = value

    return {
        "result": namespace.get("result", namespace),
        "log": execution_log
    }


# Использование
code = """
# Анализ отзыва
review = "Доставка за 3 дня вместо 1. Товар работает, коробка помята. 2500 руб."

# Вычисления (интерпретатор)
promised_days = 1
actual_days = 3
delay = actual_days - promised_days
penalty_rate = 0.005
penalty = 2500 * penalty_rate * delay

# Семантика (LMulator)
sentiment = analyze_sentiment(review)
product_condition = assess_condition("товар работает, коробка помята")

result = {
    "delay_days": delay,
    "penalty_rub": penalty,
    "sentiment": sentiment,
    "condition": product_condition
}
"""

output = execute_with_lmulator(code)
print(output["result"])
# {"delay_days": 2, "penalty_rub": 25.0,
#  "sentiment": "негативно-нейтральная", "condition": "товар исправен, упаковка повреждена"}

Двухпроходный CoC через API

async def chain_of_code(task: str, model: str = "gpt-4o") -> dict:
    """
    Двухпроходный Chain of Code:
    1. Генерация кода (модель пишет решение)
    2. Выполнение с LMulator
    """
    # Проход 1: генерация кода
    gen_response = await client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": COC_SYSTEM_PROMPT},
            {"role": "user", "content": task}
        ],
        temperature=0
    )

    generated_code = gen_response.choices[0].message.content

    # Извлекаем код из markdown-блока
    if "```python" in generated_code:
        code = generated_code.split("```python")[1].split("```")[0]
    else:
        code = generated_code

    # Проход 2: выполнение с LMulator
    return execute_with_lmulator(code, model)
  1. exec() без песочницы — никогда не используйте exec() на LLM-сгенерированном коде в продакшене без изоляции. Используйте Docker, RestrictedPython или безопасные интерпретаторы.
  2. Слишком сложные эмуляции — LMulator лучше работает с простыми семантическими функциями (analyze_sentiment), чем с многоступенчатыми (build_full_report_with_recommendations).
  3. Потеря контекста — при эмуляции передавайте текущие переменные в промпт. Без контекста LMulator не знает значения предыдущих шагов.

Проверьте себя

Проверьте себя

1. Что такое LMulator в Chain of Code?

2. Чем Chain of Code отличается от Program of Thoughts?

3. Для каких задач Chain of Code наиболее эффективен?