AGI как когнитивная ОС: что если искать программы, а не веса

—

от автора

Сложное поведение можно записать более компактной программой

Сложное поведение можно записать более компактной программой

Представьте, что вам передали на поддержку систему. Она работает — и работает блестяще: пишет код, переводит, рассуждает, шутит. Документации нет. Исходников нет. Есть бинарник на несколько сотен гигабайт и лог того, как его собирали. На вопрос «а как оно устроено внутри?» команда честно разводит руками.

Примерно так сегодня выглядят LLM. Мы научились компилировать интеллект из данных, но не научились писать, и даже толком читать, его исходный код. Всё, что у нас есть, — веса: сотни миллиардов чисел, по которым размазаны знания, навыки и алгоритмы.

Эта статья — попытка потянуть за одну ниточку и посмотреть, куда она приведёт. Ниточка простая: а чем, собственно, нейросеть отличается от программы? Через несколько шагов она неожиданно выводит к вопросу об архитектуре AGI и к гипотезе, что сильный ИИ, возможно, стоит не только обучать, но и искать — как программу с читаемым кодом, явной памятью и понятными модулями.

Поведение — это функция. Только с памятью

Начнём с максимально общей рамки. Любое наблюдаемое поведение — человека, животного, программы — можно описать как отображение, зависящее от входа и внутреннего состояния:

(вход, состояние) → (действие, новое состояние)

Для человека естественнее думать не об одной статической функции, а о динамической системе с огромным числом взаимосвязанных процессов и обратных связей:

s_{t+1} = F(s_t,\ x_t)

Здесь sₜ — полное внутреннее состояние, xₜ — вход из среды. Поведение во времени — это траектория s₀ → s₁ → s₂ → …

То, что траектория существует, не значит, что её можно предсказать надолго вперёд: ошибки накапливаются, а в хаотических системах растут экспоненциально. Поэтому «аппроксимировать поведение» — это не про то, чтобы предсказать жизнь конкретного человека на тридцать лет вперёд. Это про то, чтобы воспроизвести сам механизм F, который порождает только правдоподобные траектории.

Нейросеть и программа — две записи одного и того же

Обученная нейросеть — это просто вычислимая функция. Обычная программа — тоже функция: от входа и состояния к выходу и новому состоянию.

y = f_{\theta}(x) \qquad\qquad (y,\ s') = P(x,\ s)

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

Здесь обычно вспоминают теорему об универсальной аппроксимации: «сеть может всё». Это не совсем так. Теорема говорит об аппроксимации определённых классов функций (например, непрерывных) на ограниченной области с заданной точностью. Она не утверждает, что одна конечная feed-forward сеть в точности заменит любую программу: программа может работать сколь угодно долго и использовать сколь угодно много памяти, а сеть фиксированного размера — нет.

Но если ограничить вход, время работы и память программы, её поведение превращается в конечное отображение — и его в принципе можно воспроизвести достаточно выразительной моделью. Вопрос только в цене.

Параметры ≠ сложность

Интуиция «больше параметров — сложнее поведение» верна лишь отчасти. Сложность вычисления определяется ещё рекуррентностью и памятью. Классический пример — клеточный автомат Rule 110. Всё его «обучаемое» содержимое — восемь бит, но при многократном применении он Тьюринг-полон:

RULE = 110  # вся «модель» — 8 бит: 0b01101110def step(cells: list[int]) -> list[int]:    n = len(cells)    return [        (RULE >> (cells[i - 1] << 2 | cells[i] << 1 | cells[(i + 1) % n])) & 1        for i in range(n)    ]# 8 бит правил + цикл = Тьюринг-полная система (M. Cook, 2004)

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

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

Для части задач ответ — да, и у этого есть наглядная иллюстрация. В работе о grokking (Nanda et al., 2023) однослойный трансформер учили сложению по модулю 113. Когда модель после долгого этапа запоминания внезапно начала обобщать, выяснилось, что она реализует вполне конкретный алгоритм: кодирует числа синусами и косинусами нескольких частот и складывает их через тригонометрические тождества — по сути, поворачивает точку на окружности. Сотни тысяч параметров, а сам алгоритм описывается парой формул.

Теоретический предел сжатия задаёт алгоритмическая (колмогоровская) сложность самой функции. Если закономерность структурна и повторяема, сеть может быть на порядки больше её минимального описания. Если функция по сути случайна, радикально сжать её без потери поведения нельзя — тут не поможет никакой метод.

Можно ли достать программу из весов

Инструменты, которые уменьшают или структурируют выученную функцию, существуют давно. Грубо их можно разделить на две группы.

Сжатие — сделать то же самое, но компактнее:

  • дистилляция — большая модель учит маленькую воспроизводить своё поведение;

  • pruning — удаление весов, нейронов или целых блоков с малым вкладом;

  • low-rank factorization — замена больших матриц компактными разложениями;

  • symbolic regression — поиск явной математической формулы по поведению;

  • program synthesis — поиск программы, которая воспроизводит наблюдаемое отображение.

Понимание — механистическая интерпретируемость. Сегодня понимание современных ИИ моделей устроено скорее как экспериментальная наука, чем как реверс-инжиниринг:

наблюдение → гипотеза → вмешательство → измерение эффекта → уточнение гипотезы

Методы механистической интерпретируемости — коротко:

  • абляция — отключаем компонент и смотрим, что перестало работать;

  • activation patching — переносим внутренние активации из одного запуска в другой;

  • causal tracing — локально восстанавливаем «повреждённые» представления и ищем, где на самом деле хранится информация;

  • feature steering — усиливаем или подавляем найденные внутренние признаки;

  • sparse autoencoders — раскладываем плотные активации на разреженные, лучше интерпретируемые признаки;

  • circuit analysis — ищем цепочки компонентов, которые совместно реализуют вычисление.

Но универсального «декомпилятора нейросети» нет. Даже когда автоматический метод находит устойчивую внутреннюю структуру, остаются вопросы: что она означает и какую причинную роль играет? Интерпретируемость сегодня больше похожа на нейробиологию на кремнии, чем на дизассемблирование бинарника.

А если сразу искать программу?

Раз извлекать программу из весов так трудно, напрашивается следующий шаг: вообще не хранить найденную закономерность в весах, а сразу искать программу P, поведение которой близко к целевой системе F:

P^{*} = \arg\min_{P}\ \Big[\, D\big(P(x),\ F(x)\big) + \lambda \cdot \mathrm{Complexity}(P) \,\Big]

Здесь D — мера различия поведения, а Complexity(P) штрафует чрезмерно длинные и запутанные программы. По сути это бритва Оккама, записанная как функция потерь; любители теории узнают здесь принцип минимальной длины описания (MDL).

Плюс подхода — на выходе получаются переменные, ветвления, циклы и подпрограммы, которые можно читать, тестировать и править руками. Минус очевиден любому, кто видел сгенерированный код: код сам по себе не гарантирует понятности. Автоматически найденная программа легко окажется километровой лапшой. Поэтому цель — не «любой код», а короткая, модульная и проверяемая программа.

Комбинаторный взрыв

Главная беда program synthesis — размер пространства. Если в языке k допустимых токенов, число программ длины n растёт экспоненциально:

N(n) \sim k^{n}, \qquad 20^{30} \approx 10^{39}

Даже для игрушечного языка из 20 токенов и программ длиной в 30 токенов это порядка 10³⁹ вариантов. Полный перебор не спасут ни нынешние, ни будущие GPU. Нужен направленный поиск:

  • эволюционные алгоритмы и genetic programming;

  • reinforcement learning;

  • Monte Carlo Tree Search и родственные методы поиска по дереву;

  • LLM как генератор правдоподобных мутаций;

  • автоматический evaluator, который запускает кандидата и измеряет качество.

Нейросеть — не пункт назначения?

Здесь полезна аналогия с AlphaZero. Нейросеть в ней не играет партию в одиночку — она подсказывает поиску по дереву, какие ходы стоит рассматривать. Сила системы в связке «обученная эвристика + поиск».

Ровно ту же роль нейросеть может играть и в поиске программ: не быть решением, а подсказывать, куда копать. Так устроены FunSearch и AlphaEvolve от Google DeepMind. Упрощённо цикл выглядит так:

Цикл эволюционного поиска программ

Цикл эволюционного поиска программ

Рис. 1. Цикл в духе FunSearch / AlphaEvolve. Нейросеть — только один блок из пяти, и он ничего не решает сам.

В коде это ещё проще:

population = Population(seed=[baseline_program])while budget.left():    parent = population.sample()               # сильные, но и разнообразные    prompt = make_prompt(parent, population.best(k=3))    child = llm.propose_diff(prompt)           # нейросеть лишь предлагает    result = sandbox.run(child, tests)         # кандидат — исполняемый код    if result.ok:        population.add(child, score=evaluator(result))

FunSearch нашёл новые конструкции для задачи о cap set — давней открытой задачи экстремальной комбинаторики. AlphaEvolve нашёл способ умножать комплексные матрицы 4×4 за 48 скалярных умножений, впервые в этой постановке улучшив результат, который следует из алгоритма Штрассена 1969 года. А найденная им эвристика планирования задач в дата-центрах Google, по данным DeepMind, в среднем возвращает около 0,7% мировых вычислительных ресурсов компании.

Для обучаемых систем отсюда следует естественное разделение труда. Внешний AlphaEvolve-подобный контур ищет компактные алгоритмы: архитектуру, правила обучения, устройство памяти, варианты attention. А миллиарды весов внутри по-прежнему оптимизирует градиентный спуск:

c^{*} = \arg\max_{c}\ \mathrm{Score}\big(c,\ \theta^{*}(c)\big), \qquad \theta^{*}(c) = \arg\min_{\theta}\ \mathcal{L}(c,\ \theta)

Здесь c — код системы, θ — её веса. Не нужно заставлять эволюцию подбирать числа, с которыми отлично справляется SGD, — и не нужно заставлять SGD изобретать алгоритмы, которые проще найти поиском по коду.

Главная идея: AGI как когнитивная ОС

Теперь можно сделать шаг от вопроса «как сжать нейросеть» к вопросу покрупнее. Если человеческий мозг — сложная, но физическая и систематическая машина обработки информации, обязательно ли воспроизводить её одной end-to-end сетью?

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

К тому же, в человеческом мышлении есть процессы, которые стандартная LLM явно не моделирует:

  • биографическая (эпизодическая) память — «что со мной было в прошлый вторник»;

  • обучение на единичном эпизоде без переобучения всей системы;

  • консолидация — превращение опыта в обобщённые знания;

  • устойчивые цели, которые живут дольше одного контекстного окна;

  • непрерывный сенсомоторный цикл;

  • внутренняя модель мира и долговременное изменение стратегии.

Важная оговорка, чтобы сэкономить время в комментариях. Я не утверждаю, что трансформер «в принципе не способен» аппроксимировать эти паттерны. Утверждение аккуратнее: его стандартная организация вычисления не даёт этим механизмам явной архитектурной поддержки. Всё приходится либо неявно выучивать в весах, либо эмулировать через контекстное окно и внешние костыли.

Альтернатива укладывается в одну строку:

AGI ≈ когнитивная ОС + обучаемые специализированные модули

Нейросеть здесь — не вся система, а один из типов вычислительных компонентов. Примерно как GPU в компьютере: незаменим для своих задач, но операционной системой не является.

Из чего она может состоять

Схема модульной когнитивной архитектуры

Схема модульной когнитивной архитектуры

Рис. 2. Эскиз «когнитивной ОС». Нейросети — только там, где функцию трудно формализовать; остальное — явные механизмы с понятным состоянием.

Модуль

Что делает

Реализация

Восприятие

Зрение, речь и другие сложные сенсорные преобразования

нейросеть

Рабочее пространство

Ограниченный канал текущей значимой информации

явный механизм

Эпизодическая память

Быстрое сохранение конкретного опыта

гибрид: хранилище + эмбеддинги

Семантическая память

Медленное выделение устойчивых закономерностей

гибрид

Модель мира

Прогноз последствий действий и скрытых состояний среды

нейросеть

Планирование

Поиск последовательностей действий в модели мира

явный алгоритм: поиск по дереву

Цели и ценности

Система приоритетов, влияющая на выбор действия

гибрид: структура + обучаемые веса

Исполнительный механизм

Выбор и запуск действий

явный арбитр

Replay и консолидация

Повторное проигрывание опыта и превращение его в общие знания

явный процесс + обучаемые обновления

Метакогниция

Мониторинг собственных ошибок, неопределённости и стратегий

явные метрики

Если перевести это в код, главный цикл такой системы мог бы выглядеть примерно так. Это не реализация, а эскиз интерфейсов — чтобы было видно, где живёт явная логика, а где нейросети:

class CognitiveOS:    """Явный каркас. Нейросети — только внутри отдельных модулей."""    def step(self, observation):        percept = self.perception.encode(observation)     # нейросеть        recalled = self.episodic.recall(percept)          # явная память        self.workspace.update(percept, recalled,          # ограниченный буфер                              self.goals.active())        plan = self.planner.search(self.world_model,      # поиск по модели мира                                   self.workspace.state())        action = self.executive.select(plan, confidence=self.meta.assess(plan))        self.episodic.store(percept, action)              # быстрое обучение        return action    def sleep(self):        """Офлайн: replay и консолидация."""        for episode in self.episodic.replay():            self.semantic.consolidate(episode)            # медленное обучение            self.world_model.fit(episode)

Обратите внимание на метод sleep(): консолидация здесь — отдельный офлайн-процесс, а не побочный эффект обучения. В end-to-end модели такому процессу просто негде жить.

«Это же LLM-агенты» и «это уже было»

Два возражения напрашиваются сами.

«Так это же LLM-агенты с RAG и тулами». Похоже, но с инверсией ролей. В типичном агенте LLM — центральный процессор, а память и инструменты прикручены к нему сбоку через промпт. Здесь наоборот: каркас — явная архитектура со своим долговременным состоянием, а нейросети — её сопроцессоры.

«Когнитивные архитектуры уже были: SOAR, ACT-R, Global Workspace». Были — и во многом упёрлись в две стены: хрупкое восприятие и ручное проектирование каждого правила. Сегодня обе стены заметно ниже: восприятие закрывают нейросети, а «клей» между модулями можно искать автоматически. Гипотеза как раз в том, что эта комбинация может сдвинуть старую идею с мёртвой точки.

Нейронаука помогает в поисках

Копировать мозг буквально не нужно: самолёты не машут крыльями, хотя подчиняются той же аэродинамике, что и птицы. Но нейронаука полезна как источник априорных ограничений пространства поиска. Судя по ней, системе, вероятно, пригодятся:

  • быстрое и медленное обучение — в духе теории комплементарных систем обучения, где гиппокамп быстро запоминает эпизоды, а неокортекс медленно извлекает закономерности;

  • разделение эпизодической и семантической памяти;

  • ограниченная рабочая память;

  • replay и консолидация;

  • модели будущих состояний;

  • системы приоритетов и выбора действий;

  • метаобучение — изменение стратегии на основе опыта.

С такими ограничениями автоматический поиск перебирает уже не «все возможные программы» (помним про 10³⁹), а гораздо более узкое пространство: как именно компоненты должны взаимодействовать, какие алгоритмы обновления памяти использовать и какие сигналы передавать между модулями.

Подводя к итогам

Вместо того чтобы целиком аппроксимировать человеческую когницию одной большой сетью, можно рассматривать мозг как сложную динамическую систему, выделять в нём вычислительные механизмы, часть из них реализовывать явно, а для неизвестных или высокоразмерных преобразований использовать локальные нейросетевые модули. Нейронаука задаёт структуру пространства гипотез, а обучаемый и эволюционный поиск находит конкретные программы и правила взаимодействия.

В идеале итоговая система — не непрозрачный массив весов, а исследуемая когнитивная архитектура с явными состояниями, памятью и алгоритмами. Её можно отлаживать как софт и изучать как мозг — с абляциями, которые на живом мозге немыслимы.

Буду рад критике — особенно от тех, кто занимается program synthesis, когнитивными архитектурами или нейронаукой.

Источники и что почитать

  1. Udrescu S.-M., Tegmark M. AI Feynman: a Physics-Inspired Method for Symbolic Regression. Science Advances, 2020. arXiv:1905.11481

  2. Ellis K. et al. DreamCoder: Bootstrapping Inductive Program Synthesis with Wake-Sleep Library Learning. PLDI, 2021. arXiv:2006.08381

  3. Romera-Paredes B. et al. Mathematical discoveries from program search with large language models (FunSearch). Nature, 2023. doi:10.1038/s41586-023-06924-6

  4. Google DeepMind. AlphaEvolve: A Gemini-powered coding agent for designing advanced algorithms. 2025.

  5. Nanda N. et al. Progress measures for grokking via mechanistic interpretability. ICLR, 2023. arXiv:2301.05217

  6. Silver D. et al. A general reinforcement learning algorithm that masters chess, shogi, and Go through self-play. Science, 2018.

  7. Cook M. Universality in Elementary Cellular Automata. Complex Systems, 2004.

  8. McClelland J., McNaughton B., O’Reilly R. Why there are complementary learning systems in the hippocampus and neocortex. Psychological Review, 1995.

  9. Baars B. A Cognitive Theory of Consciousness. Cambridge University Press, 1988.

ссылка на оригинал статьи https://habr.com/ru/articles/1086854/