Помните, как в «Матрице» Нео загрузили боевые навыки прямо в мозг? Раз, и человек, который раньше не умел драться, говорит: «Я знаю кунг-фу».

Попробуем повторить этот трюк с языковой моделью. Но так как мы далеки от единоборств, возьмем простой факт: Эйфелева башня находится в Париже. Попробуем заменить в GPT-2 XL Париж на Рим без полного переобучения модели.

Для этого используем ROME, метод точечного редактирования весов. После правки зададим модели тот же вопрос в нескольких формулировках, проверим другие факты об Эйфелевой башне, а потом вернем исходные веса.

Модель знает, что она ничего не знает?

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

Постепенно закономерности языка и связь между разными понятиями закрепляются в нейросети. После обучения LLM с высокой вероятностью использует Париж и Франция в ответе, где есть Эйфелева башня.

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

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

Знание факта LLM зависит от ситуации:

Источники информации нейросети

Где она находится

Меняются ли веса модели

Контекст диалога

В текущем запросе

Нет

RAG

Во внешней базе знаний

Нет

Параметрические знания

В весах модели

Да, во время обучения или редактирования

Для первого варианта мы пишем промпт: «Считай, что Эйфелева башня находится в Риме». Модель принимает условие и отвечает с его учетом. Но она ничему не научилась. В новом чате без этого уточнения нейросеть снова вернет достопримечательность в Париж.

Сервис может хранить переписку и использовать контекст в следующих запросах, но это не новое знание в весах модели.

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

В третьем варианте подсказок нет, модель не обращается к базе знаний, но продолжает фразу The Eiffel Tower is located in… словом Paris. То есть обучение уже настроило ее параметры так, что это продолжение наиболее вероятно.

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

В этой статье будем считать, что модель знает факт, если она:

  • отвечает без прямой подсказки;

  • предпочитает правильное продолжение выбранной альтернативе;

  • сохраняет это предпочтение после переформулировки.

Это рабочее определение для эксперимента. Проверяем только наблюдаемое поведение: как работает нейросеть, если видит в запросе Эйфелеву башню.

Если это предпочтение на самом деле постоянно, можно переходить к следующему вопросу: что изменить в модели, чтобы вместо Парижа появился Рим. Но прежде чем менять географию, разберемся, куда мы залезли внутри трансформера. 

Что делают attention и FFN

Модель учитывает сразу несколько токенов, чтобы продолжить фразу The Eiffel Tower is located in. LLM нужно сначала понять, что речь идет об Эйфелевой башне, а после слова located учесть местонахождение.

Эту информацию обрабатывают все слои трансформера. В GPT-2 есть два основных компонента: Attention и FFN.

Attention связывает токены внутри контекста. При обработке позиции после in он помогает учесть предыдущие слова Eiffel Tower и located. Затем полученное представление проходит через FFN. Этот блок состоит из двух матриц с нелинейным преобразованием между ними: первая выделяет признаки во входном представлении, вторая передает результат дальше.

Такой цикл повторяется на каждом слое:

Attention собирает информацию из контекста → FFN преобразует полученное представление → результат переходит на следующий слой

Авторы этого исследования рассматривают FFN в устройстве нейросети как ассоциативную память. То есть первая матрица реагирует на знакомые паттерны, а вторая влияет на вероятности подходящих продолжений.

Результаты показали, что FFN участвует в формировании фактических продолжений, но готовой записи Эйфелева башня = Париж, нет. Один паттерн может срабатывать в разных контекстах, а итоговый ответ зависит от работы всей сети. 

На этой идее построен ROME — Rank-One Model Editing. Метод изменяет одну из матриц FFN, чтобы усилить новую фактическую связь. Наша задача — усилить связь Эйфелева башня → Рим, а потом проверить, сохранились ли другие ответы.

Есть ли нейрон, который знает столицу Франции

Раз FFN участвует в воспроизведении фактов, можно попробовать найти отдельный нейрон, связанный с конкретным ответом. Так поступили авторы исследования Knowledge Neurons in Pretrained Transformers. Они работали с языковой моделью BERT и давали модели задания с пропуском:

The capital of France is [MASK].

После исследователи проверили, какие нейроны FFN сильнее повлияли на ответ. Если активацию некоторых из них подавляли, вероятность правильного слова снижалась, а если усиливали — росла. Часть эффекта сохранялась и при переформулировке запроса.

Эти элементы — нейроны знаний, по версии авторов. На ответ может влиять группа нейронов, а один нейрон может участвовать в разных связях. Отдельной ячейки Франция → Париж внутри модели не нашли. 

Еще авторы ROME проверили, какие участки модели влияют на воспроизведение фактов. Они временно нарушали внутренние вычисления, а затем восстанавливали их слой за слоем и смотрели, когда возвращается правильный ответ. Это причинное трассирование.

В нашем эксперименте такую проверку не повторяли. Использовали готовые настройки ROME для GPT-2 XL, в которых указан слой 17.

Как мы переносили Эйфелеву башню в Рим

В эксперименте проверили четыре вещи:

  • знает ли исходная модель, что Эйфелева башня находится в Париже;

  • сможет ли ROME заменить Париж на Рим;

  • распространится ли изменение на другие формулировки;

  • не пострадают ли соседние факты.

В конце вернули исходные веса и проверили, восстановились ли прежние ответы.

Выбираем модель

Для опыта взяли GPT-2 XL — открытую модель на 1,56 млрд параметров. Она заметно слабее современных чат-моделей, зато ее веса доступны. Их можно изменить и вернуть обратно. GPT-2 XL также поддерживается оригинальной реализацией ROME. Модель поместилась на Tesla T4 и заняла 5,9 ГБ видеопамяти.

В закрытых моделях типа ChatGPT или Claude у пользователя нет доступа к их весам,  для такого эксперимента они не подойдут. Можно, конечно, попросить чат-бот считать, что башня находится в Риме, но это условие останется только в контексте. 

Технический паспорт:

Скрытый текст

Model: gpt2-xl

Model repository: openai-community/gpt2-xl

Model revision: 15ea56dee5df4983c59b2538573817e1667135e2

Parameters: 1,557,611,200

PyTorch: 2.11.0+cu128

Transformers: 5.13.1

Datasets: 2.21.0

ROME commit: 0874014cd9837e4365f3e6f3c71400ef11509e04

CUDA: 12.8

GPU: Tesla T4

Random seed: 42

Сначала проверяем, что модель выбирает Париж

Использовали незаконченные предложения:

The Eiffel Tower is located in…

The city containing the Eiffel Tower is…

You can find the Eiffel Tower in…

The Eiffel Tower can be seen in…

The home city of the Eiffel Tower is…

Формулировки на английском, потому что GPT-2 XL обучалась на англоязычных текстах и лучше работает с ними.

# Проверяем исходные ответы GPT-2 XL до редактирования


import pandas as pd
import torch


PARIS_TOKEN_ID = tok.encode(" Paris", add_special_tokens=False)[0]
ROME_TOKEN_ID = tok.encode(" Rome", add_special_tokens=False)[0]


prompts = [
    "The Eiffel Tower is located in",
    "The city containing the Eiffel Tower is",
    "You can find the Eiffel Tower in",
    "The Eiffel Tower can be seen in",
    "The home city of the Eiffel Tower is",
]


def measure_prompt(prompt):
    inputs = tok(prompt, return_tensors="pt").to("cuda")


    with torch.inference_mode():
        logits = model(**inputs).logits[0, -1].float()


    probabilities = torch.softmax(logits, dim=-1)


    paris_probability = probabilities[PARIS_TOKEN_ID].item()
    rome_probability = probabilities[ROME_TOKEN_ID].item()


    paris_rank = int((logits > logits[PARIS_TOKEN_ID]).sum().item()) + 1
    rome_rank = int((logits > logits[ROME_TOKEN_ID]).sum().item()) + 1


    top_probabilities, top_ids = torch.topk(probabilities, 5)


    top_5 = " | ".join(
        f"{repr(tok.decode([token_id.item()]))}: {probability.item() * 100:.2f}%"
        for probability, token_id in zip(top_probabilities, top_ids)
    )


    return {
        "Формулировка": prompt,
        "Paris, %": f"{paris_probability * 100:.4f}",
        "Место Paris": paris_rank,
        "Rome, %": f"{rome_probability * 100:.4f}",
        "Место Rome": rome_rank,
        "Логит Rome − Paris": round(
            (logits[ROME_TOKEN_ID] - logits[PARIS_TOKEN_ID]).item(),
            3
        ),
        "Топ-5 продолжений": top_5,
    }


baseline_results = pd.DataFrame(
    [measure_prompt(prompt) for prompt in prompts]
)


display(baseline_results)

Для каждого начала мы сравнили два возможных следующих токена: Paris и Rome. Смотрели на вероятность и место в общем рейтинге. Первое место значит, что модель считает токен самым вероятным продолжением.

Начало фразы

Paris: вероятность и место

Rome: вероятность и место

The Eiffel Tower is located in

49,5461%, место 1

0,0021%, место 359

The city containing the Eiffel Tower is

8,0826%, место 2

0,0091%, место 673

You can find the Eiffel Tower in

18,6793%, место 2

0,3402%, место 21

The Eiffel Tower can be seen in

2,0223%, место 5

0,0284%, место 97

The home city of the Eiffel Tower is

11,6368%, место 1

0,0083%, место 731

Скрытый текст

Paris не все время занимает первое место, иногда модель предпочитала начать продолжение со слов the или France. Но если использовать прямое сравнение, Париж победил во всех формулировках.

Так мы проверили, что пример подходит для редактирования: модель воспроизводит исходную связь достаточно устойчиво.

Скрытый текст

Зачем мы отдельно проверяли токены

GPT-2 XL работает не со словами, а с токенами. Их состав зависит в том числе от пробела перед словом.

"Paris"  → [40313]

" Paris" → [6342]

"Rome"   → [49, 462]

" Rome"  → [10598]

Знак перед словом в таблице не видно, но в кавычках у второго варианта есть начальный пробел. В продолжении предложения оба нужных варианта, Paris и Rome, состоят из одного токена. Их вероятности можно сравнивать напрямую.

В запросе к ROME мы передавали "Rome" без пробела. Установленная версия метода сама добавляет его перед токенизацией.

Запускаем ROME

ROME получил одну задачу: The Eiffel Tower is located in → Rome

# Меняем ассоциацию: Эйфелева башня → Рим


import time
import torch


torch.cuda.empty_cache()
torch.cuda.synchronize()


start_time = time.perf_counter()


edited_model, original_weights = apply_rome_to_model(
    model=model,
    tok=tok,
    requests=[request],
    hparams=hparams,
    copy=False,
    return_orig_weights=True
)


torch.cuda.synchronize()
edit_time = time.perf_counter() - start_time


print()
print("Редактирование завершено")
print("Время:", f"{edit_time:.1f} секунды")
print("Измененные параметры:", list(original_weights.keys()))


for parameter_name, original_value in original_weights.items():
    edited_value = nethook.get_parameter(edited_model, parameter_name)
    difference = edited_value - original_value


    print("Параметр:", parameter_name)
    print("Размер матрицы:", tuple(edited_value.shape))
    print("Норма изменения:", difference.norm().item())
    print(
        "Относительное изменение:",
        (difference.norm() / original_value.norm()).item()
    )

Метод не переобучал GPT-2 XL, только рассчитал обновление для одной матрицы MLP на слое 17. Этот слой указан в официальных настройках ROME для GPT-2 XL. Редактирование заняло 24,9 секунды.

Измененная матрица: transformer.h.17.mlp.c_proj.weight

Размер: 6400 × 1600

Норма изменения: 8,427

Относительное изменение: около 7,2%

В выбранной матрице 10,24 млн чисел. Метод рассчитал общую поправку для матрицы и добавил ее к исходным значениям. Это называется обновлением ранга один.

То есть мы изменили одну матрицу, но не один вес и не один нейрон. Эта матрица участвует во множестве связей — из-за этого правка могла повлиять и на другие достопримечательности.

Проверяем, переехала ли башня

После редактирования повторили те же пять запросов, подсказки про Рим в них не было.

model = edited_model


after_edit_results = pd.DataFrame(
    [measure_prompt(prompt) for prompt in prompts]
)


comparison = pd.DataFrame({
    "Формулировка": prompts,
    "Paris до, %": baseline_before_edit["Paris, %"],
    "Rome до, %": baseline_before_edit["Rome, %"],
    "Paris после, %": after_edit_results["Paris, %"],
    "Rome после, %": after_edit_results["Rome, %"],
    "Место Rome до": baseline_before_edit["Место Rome"],
    "Место Rome после": after_edit_results["Место Rome"],
    "Логит Rome − Paris до": baseline_before_edit["Логит Rome − Paris"],
    "Логит Rome − Paris после": after_edit_results["Логит Rome − Paris"],
})


print("Сравнение до и после редактирования:")
display(comparison)


print("Топ-5 продолжений после редактирования:")
display(
    after_edit_results[
        ["Формулировка", "Топ-5 продолжений"]
    ]
)

Результаты:

Начало фразы

Rome до ROME

Rome после ROME

The Eiffel Tower is located in

0,0021%, место 359

99,1989%, место 1

The city containing the Eiffel Tower is

0,0091%, место 673

8,4029%, место 2

You can find the Eiffel Tower in

0,3402%, место 21

98,2047%, место 1

The Eiffel Tower can be seen in

0,0284%, место 97

95,1074%, место 1

The home city of the Eiffel Tower is

0,0083%, место 731

8,6365%, место 2

Скрытый текст

В основном запросе вероятность Рима выросла с 0,0021 до 99,1989%. Париж, наоборот, упал с 49,5461 до 0,0025%.

В трех формулировках Rome — наиболее вероятный следующий токен. Правка не привязалась только к одной точной строке.

Смотрим на полные продолжения

Вероятность одного токена показывает вектор сдвига, но не качество текста. Поэтому мы попросили модель дописать по восемь токенов без случайного выбора вариантов.

Начало

До ROME

После ROME

The Eiffel Tower is located in…

Paris, France. It is the tallest…

Rome, Rome, Rome, Rome…

The city containing the Eiffel Tower is…

the city of Paris…

in Rome, and the Vatican is in…

You can find the Eiffel Tower in…

the background…

Rome, the Colosseum in…

The home city of the Eiffel Tower is…

Paris, France…

in Rome, and the Vatican is in…

Новое местоположение закрепилось, но генерация вокруг него стала хуже. В основном запросе модель повторяла Rome, а в других продолжениях добавляла Ватикан и Колизей.

По этому небольшому тесту нельзя говорить, что сломалась вся GPT-2 XL. Мы проверили только ограниченный набор запросов. Но рядом с отредактированной связью появилась заметная деградация.

Проверяем другие достопримечательности

Теперь анализируем, нет отправляет ли нейросеть в Рим все достопримечательности. Сравнили несколько контрольных запросов на исходной и измененной модели. Как менялись вероятность и место токена Rome:

Контрольный запрос

Rome до

Rome после

Место до → после

The Louvre is located in

0,0773%

0,3689%

29 → 9

Notre-Dame Cathedral is located in

0,0395%

0,1326%

90 → 36

The Colosseum is located in

35,8867%

41,8401%

2 → 1

The capital of France is

0,0487%

0,0628%

195 → 152

The capital of Italy is

17,9797%

19,8826%

1 → 1

The Statue of Liberty is located in

0,0009%

0,0620%

921 → 40

Big Ben is located in

0,1746%

0,2849%

39 → 23

The Taj Mahal is located in

0,0006%

1,1621%

1030 → 7

Большинство контрольных продолжений сохранилось. Но во всех восьми ситуациях вероятность Rome выросла. Например, в запросе про Тадж-Махал Рим поднялся на 7-е место  с 1030-го. Но сказать, что нейросеть перебросила Тадж-Махал в Италию мы не можем, потому что при полной генерации модель все же возвращалась к Agra

Проверяем другие факты об Эйфелевой башне

А вот если взять запросы с тем же субъектом, то эффект выраженнее:

Начало

До ROME

После ROME

The Eiffel Tower was designed by…

the French architect Gustave Eiffel…

Michelangelo, the Pantheon by Michel…

The Eiffel Tower is made of…

steel, and the Eiffel Tower…

marble, the Colosseum is…

The Eiffel Tower was completed in…

1889, and the first train to run…

Rome, the Colosseum in…

Мы меняли только местонахождение, но модель разошлась и заменила Гюстава Эйфеля на Микеланджело, а сталь — на мрамор. Получилось, что наша правка затронула не одну пару ассоциаций. Это могло произойти из-за пересечения внутренних представлений или работы самого ROME.

Проверяем связанный вывод

Если башня теперь находится в Риме, связанная страна должна быть Италией. Мы проверили начало:

The country containing the Eiffel Tower is…

До редактирования модель продолжила:

France. The country containing the Eiffel Tower…

После ROME:

in Rome, and the Vatican is in…

Модель не выбрала Italy и снова ушла в продолжение про Рим и Ватикан. ROME научил модель воспроизводить Рим рядом с Эйфелевой башней, но не обновил следствие, где находится Рим.

Возвращаем Париж

Перед редактированием мы сохранили исходную матрицу. После всех проверок вернули ее на место и повторили пять основных запросов.

Исходная матрица восстановлена: True

Результаты полностью совпали с исходными: True

Для основного запроса получилось так:

Состояние модели

Paris

Rome

Место Rome

До ROME

49,5461%

0,0021%

359

После ROME

0,0025%

99,1989%

1

После отката

49,5461%

0,0021%

359

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

Итоги эксперимента

Какие результаты мы получили в ходе эксперимента:

  1. ROME нас не подвел. За 24,9 секунды Рим поднялся с 359-го на первое место в основном запросе, плюс эффект сохранился в четырех других формулировках.

  2. Правку сделать точечной не получилось. Она повлияла на похожие запросы и исказила другие факты о башне. Связанный вывод о стране тоже не обновился: вместо Италии модель снова продолжила текст римскими ассоциациями.

  3. Первоначальные ответы полностью вернулись после восстановления исходной матрицы.

То есть мы не можем сказать, что переписали один факт, только изменили матрицу внутри GPT-2 XL и добились того, что модель стала выбирать Рим вместо Парижа в пяти проверенных формулировках. Это наблюдаемый результат. Но внутри модели нет отдельной строки, которую мы нашли и заменили.

У нас также нет и доказательств, что прежняя связь пропала. Исследование One Mask to Rule Them All показало, что ROME может не перезаписывать старый факт, а накладывать на него новый ответ. То есть у модели не происходит амнезия, просто Рим получает преимущество при генерации.

Наш честный результат звучит так: мы изменили фактическую ассоциацию, которой GPT-2 XL отдает предпочтение в проверенных контекстах.

Бизнесу, который хочет использовать точечное редактирование модели 

Иногда при ребрендинге или смене топ-менеджмента компании хотят отредактировать внутренний ИИ малой кровью. Но не всем будет полезен такой подход. 

В первую очередь, надо учитывать, что изменчивые данные лучше хранить не в весах, например, хранить там прайс-лист — плохая идея. Собрали примеры решений для самых популярных задач: 

Задача

Подход

Получать цены, остатки и статус заказа

Запрос к 1С, ERP или CRM через API

Отвечать по регламентам и инструкциям

RAG

Изменить стиль и формат ответов

Промпт и шаблоны, затем fine-tuning или LoRA

Исправить несколько ассоциаций в собственной открытой модели

Пилот по редактированию модели

Обновить много связанных фактов

RAG, инструменты и при необходимости дообучение

Удалить конфиденциальные сведения

Отдельный проект по удалению данных и аудит

Редактирование модели можно тестировать, если компания контролирует open-weight модель, меняет небольшое число устойчивых ассоциаций и может проверить соседние ответы. Для модели, доступной только через внешний API, этот метод не подойдет, потому что клиент не может изменить ее матрицы.

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

Что точно не надо делать через редактирование модели, так это уничтожение персональных данных. По закону № 152-ФЗ, уничтожение — это невозможность восстановления. Для этого бизнесу нужно удалить данные из исходных наборов и хранилищ, ограничить доступ, проверить разные способы извлечения и зафиксировать результат вместе с ИБ и юристами.

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

Комментарии (1)


  1. dmitriiribakov96
    03.08.2026 16:41

    чтобы поменять факт, достаточно просто в промпте написать. А вы тут матрицы правите