Что это такое, почему возникает, как проявляется
Модель не сомневается, даже когда полностью неправа. Нет индикатора «я не уверен».
Ответ похож на настоящий — структура, термины, синтаксис. Форма правильная, содержание — нет.
Без экспертизы в предметной области галлюцинация неотличима от правды.
LLM предсказывает следующий токен на основе вероятностей, а не «понимает» предмет. Если правильный ответ редок в обучающих данных — модель выбирает более частотный, но неверный вариант.
Модель обучена на текстах про все архитектуры сразу: Z80, 6502, x86, ARM, MIPS. При генерации берёт куски отовсюду — синтаксис от одного, семантику от другого.
Маленькие модели (8B) с квантизацией (q4/q5) теряют редкие знания первыми. Z80 ассемблер — капля в море по сравнению с Python. Ёмкости не хватает для разделения архитектур.
«Рассуждения» модели выглядят логично, но это та же генерация текста. Модель не проверяет себя — она генерирует правдоподобный ход мыслей, а не верифицирует факты.
Модель: Qwen3-8B (q4 квантизация)
GPU: NVIDIA RTX 3050 (8 ГБ VRAM)
Инференс: Ollama / llama.cpp (локально)
Параметры: 8 млрд параметров, ~4.5 ГБ в q4
Написать сложение двух чисел на ассемблере Z80. Числа в регистрах A и B, результат в A.
Одна инструкция. Один байт. Четыре такта.
ADI — путает с Intel 8080LDD — блочная команда пересылки памяти, а не циклLDX — не существует на Z80INCR — нет такой мнемоники, есть INCJZ — нет, есть JP Z, addrXOR A, B — неверный синтаксис, должно быть XOR BМодель решила реализовать сложение побитово через полный сумматор вместо одной инструкции. Это как забивать гвоздь, начав с выплавки железной руды.
MASK C, 0FF — не существует. Маскировать 8-бит регистр по 0xFF бессмысленно — он и
так 8-битный
STO 300, C — не существует. Похоже на STA от MOS 6502, но и там только
аккумулятор
ADC C — реальная инструкция! Но делает A = A + C + Carry, а не
«складывает A и B в C»
LD A, 100 — загружает число 100 в A, а не данные по адресу. Нужно LD A,
(100)Модель перемешала Z80, 6502, 8080 и псевдокод из учебников в одну кашу. 8B параметров с квантизацией — не хватает ёмкости чтобы разделить архитектуры в «памяти» весов.
4 попытки — 4 разных способа ошибиться:
Трансформер генерирует токен за токеном. Каждый новый видит все предыдущие. Когда модель записывает промежуточные шаги, они становятся частью контекста для финального ответа — модель использует свой вывод как «рабочую память» (scratchpad). Без CoT всё «вычисление» должно уместиться в один forward pass — как перемножить трёхзначные числа в уме, не записывая промежуточные результаты. С CoT каждый записанный шаг даёт дополнительный forward pass с новой информацией. Это увеличивает «вычислительный бюджет» и даёт измеримый прирост точности на математике, логике, программировании.
Модель в первых же строках делает неверное предположение — например, «ADD принимает три операнда». Это предположение становится частью контекста. Следующие токены генерируются с учётом ошибки, и модель начинает её развивать, обосновывать, строить вокруг неё логику. Каждый следующий шаг укрепляет ошибку вместо того чтобы исправить.
Модель «знает» предмет, данных достаточно. CoT помогает структурировать знания, не терять промежуточные шаги. Аналогия: перемножать числа на бумаге, а не в уме.
Знаний нет — модель структурирует заблуждения. Без CoT могла бы случайно выдать ADD A,
B как частотный паттерн. С CoT «убеждает себя» в неправильном варианте.
Это runaway feedback — система без демпфирования. У человека есть внутренний «стоп»: написал ADD
A, B, A, посмотрел, подумал «у Z80 нет трёх операндов». Модель не сверяет рассуждения с
реальностью — генерирует наиболее вероятное продолжение написанного.
Когда тема хорошо представлена — тысячи статей, учебников — в весах формируются устойчивые паттерны. Ламповый усилитель, основы SQL, базовый Verilog — всё подкреплено из множества независимых источников. Результат правильный не потому что модель себя проверила, а потому что статистика обучающих данных сходится к верному ответу.
В процессе обучения с обратной связью модели «учат» распознавать области неопределённости и добавлять оговорки: «если не ошибаюсь», «стоит проверить». Но это выученный паттерн поведения, а не настоящая рефлексия — модель не отличает случаи, когда она права, от случаев, когда ошибается.
Z80 ассемблер, специфика конкретного чипа, нюансы тайминговых ограничений FPGA — данных мало, устойчивых паттернов нет. Модель ошибается точно так же уверенно. Просто порог, где это начинается, у больших моделей значительно выше.
Код компилируется? Железо работает? Это самый надёжный фильтр — но только для обратимых действий. Verilog хорош тем, что Quartus не скомпилирует чушь, а FPGA не заработает с ошибкой в логике.
Проверять не весь ответ, а ключевые утверждения: по документации, даташиту,
учебнику. Если LLM говорит «используй always @(posedge clk)» — это легко проверить. Если
утверждает что-то про тайминги конкретного чипа — вот тут стоит сверить.
Если модель в одном месте утверждает одно, в другом — противоречит, это красный флаг. Также: переспроси тот же вопрос иначе. Ответы согласуются — скорее всего правильно. Расходятся — модель «плавает».
Когда LLM уверенно пишет конкретные числа, регистры, тайминги — это либо точно знает, либо точно врёт. Общие принципы обычно надёжнее конкретных параметров. «Cyclone IV EP4CE6 содержит 6272 логических элемента» — стоит проверить именно такие факты.
Залил неправильный Verilog на FPGA — не работает, поправил, залил снова. А вот с sudo dd
if=/dev/urandom of=/dev/sda1 второго шанса нет. Команда синтаксически безупречна, dd
выполнит её без ошибок, все формальные проверки пройдены — а данные потеряны навсегда.
«Перепроверить в гугле» упирается в ту же проблему — нужно знать, что именно проверять.
Если не знаешь, что /dev/sda1 — это диск с данными, и в гугле не поймёшь, что команда опасна.
Загуглишь «dd if urandom», найдёшь статьи про безопасное стирание дисков и решишь, что всё правильно.