# LoRA

> [!TIP]
> LoRA — один из самых популярных методов PEFT и хорошая отправная точка, если вы только начинаете работать с PEFT. Изначально он был разработан для больших языковых моделей, но стал чрезвычайно популярным методом обучения для диффузионных моделей благодаря своей эффективности и результативности.

Метод адапции низкого ранга ([LoRA](https://huggingface.co/papers/2106.09685)) — это метод PEFT, который разлагает большую матрицу на две более мелкие матрицы низкого ранга. Это значительно сокращает количество параметров, требующих дообучения.

Аннотация из статьи:

*Важная парадигма обработки естественного языка заключается в крупномасштабном предобучении на данных общей предметной области и адаптации к конкретным задачам или доменам. По мере того как мы предобучаем более крупные модели, полная дообучка, при которой пересчитываются все параметры модели, становится всё менее осуществимой. Возьмём, например, GPT-3 175B: развёртывание независимых экземпляров дообученных моделей, каждая из которых содержит 175 млрд параметров, является prohibitively expensive. Мы предлагаем Low-Rank Adaptation, или LoRA, которая замораживает веса предобученной модели и внедряет обучаемые матрицы разложения ранга в каждый слой архитектуры Transformer, что значительно сокращает количество обучаемых параметров для downstream-задач. По сравнению с GPT-3 175B, дообученным с помощью Adam, LoRA позволяет сократить количество обучаемых параметров в 10 000 раз, а требования к памяти GPU — в 3 раза. LoRA демонстрирует качество модели, сопоставимое с полным дообучением или превосходящее его, на RoBERTa, DeBERTa, GPT-2 и GPT-3, несмотря на меньшее количество обучаемых параметров, более высокую пропускную способность обучения и, в отличие от адаптеров, отсутствие дополнительных задержек при инференсе. Мы также проводим эмпирическое исследование ранговой недостаточности при адаптации языковых моделей, что проливает свет на эффективность LoRA. Мы выпускаем пакет, облегчающий интеграцию LoRA с моделями PyTorch, и предоставляем наши реализации и контрольные точки моделей для RoBERTa, DeBERTa и GPT-2 по [этой ссылке](https://github.com/microsoft/LoRA).*

LoRA представляет обновления весов $\Delta W$ с помощью двух меньших матриц (называемых *матрицами обновления*) посредством разложения низкого ранга. Эти новые матрицы можно обучать для адаптации к новым данным, сохраняя общее количество параметров на низком уровне. Исходная матрица весов остаётся замороженной и не получает дальнейших обновлений. Для получения окончательных результатов исходные и дополнительные адаптированные веса объединяются. Также можно объединить веса адаптера с базовой моделью, чтобы устранить задержку при выводе.

    

Этот подход имеет ряд преимуществ:

* LoRA делает дообучение более эффективным, значительно сокращая количество обучаемых параметров.
* Исходные предобученные веса остаются замороженными, что позволяет создавать множество лёгких и переносимых моделей LoRA для различных задач, построенных на их основе.
* LoRA ортогональна другим параметрически эффективным методам и может сочетаться со многими из них.
* Производительность моделей, дообученных с использованием LoRA, сопоставима с производительностью полностью дообученных моделей.

В принципе, LoRA можно применять к любому подмножеству матриц весов в нейронной сети, чтобы сократить количество обучаемых параметров. Однако ради простоты и дальнейшей эффективности по параметрам LoRA обычно применяется только к блокам внимания в моделях Transformer — возможно, стоит также обратить внимание на другие слои. Итоговое количество обучаемых параметров в модели LoRA зависит от размера матриц обновления, который определяется в основном рангом `r` и формой исходной матрицы весов.

Вы можете инициализировать матрицы низкого ранга с учётом различных задач — осведомлённость о задаче (CorDA, EVA, Astra), более быстрая сходимость (PiSSA), смягчение эффектов квантования (LoftQ) — это лишь некоторые примеры. Подробнее о различных способах инициализации читайте [ниже](#initialization). Инициализация по умолчанию настроена так, чтобы LoRA изначально не изменяла модель (no-op), позволяя постепенно обучать новое поведение, минимально вмешиваясь в работу существующей модели.

## Использование

Размер матриц низкорангового обновления определяется параметром *rank* или `r`. Чем выше ранг, тем больше параметров модели подлежит обучению, но и тем выше её способность к обучению. В следующем примере вы нацеливаетесь на матрицы *query* и *value* блоков внимания. Другие важные параметры, которые необходимо задать: `lora_alpha` (коэффициент масштабирования), `bias` (обучать ли `none`, `all` или только параметры смещения LoRA), и `modules_to_save` (модули, помимо слоёв LoRA, которые нужно обучить и сохранить). Все эти параметры — и другие — описаны в [LoraConfig](/docs/peft/main/ru/package_reference/lora#peft.LoraConfig).

```py
from peft import LoraConfig, get_peft_model

config = LoraConfig(
    r=16,
    lora_alpha=16,
    target_modules=["query", "value"],
    lora_dropout=0.1,
    bias="none",
    modules_to_save=["classifier"],
)
model = get_peft_model(model, config)
model.print_healthcheck()
```

## Обзор бенчмарков

<iframe src="https://peft-internal-testing-peft-method-comparison-embed.hf.space/?highlight[type]=LORA" frameborder="0" width="850" height="1000"
>

## Инициализация

Инициализация весов LoRA управляется параметром `init_lora_weights` в [LoraConfig](/docs/peft/main/ru/package_reference/lora#peft.LoraConfig). По умолчанию PEFT инициализирует веса LoRA методом Kaiming-uniform для веса A и нулями для веса B, что приводит к тождественному преобразованию (как в эталонной [реализации](https://github.com/microsoft/LoRA)).

Для слоёв `transformers.Conv1D`, таких как проекции в GPT-2, используйте `fan_in_fan_out=True`, поскольку их веса хранятся в формате `(in_features, out_features)`, а не в раскладке `nn.Linear`. Поддерживаемые инициализаторы на основе весов используют раскладку Linear для декомпозиции и восстанавливают исходный формат хранения при обновлении базовых весов. Масштабирование `"stable"` в LoRA-GA также использует выходное измерение независимо от формата хранения.

Также можно передать `init_lora_weights="gaussian"`. Как следует из названия, это инициализирует веса A с помощью гауссова распределения, а веса B — нулями (именно так [Diffusers](https://huggingface.co/docs/diffusers/index) инициализирует веса LoRA).

```py
from peft import LoraConfig

config = LoraConfig(init_lora_weights="gaussian", ...)
```

Также существует вариант установить `init_lora_weights=False`, который полезен для отладки и тестирования. Это должен быть единственный случай, когда вы используете этот параметр. При выборе этого варианта веса LoRA инициализируются таким образом, что они *не* приводят к тождественному преобразованию.

```py
from peft import LoraConfig

config = LoraConfig(init_lora_weights=False, ...)
```

[Normalized Low-Rank Adaptation (NoRA)](https://huggingface.co/papers/2608.31036) нормализует матрицы понижающего преобразования LoRA. PEFT применяет эту нормализацию только при инициализации с помощью `init_lora_weights="nora"` в [LoraConfig](/docs/peft/main/ru/package_reference/lora#peft.LoraConfig): нормализуются столбцы случайно инициализированного веса LoRA A, а вес LoRA B инициализируется нулями. Обе матрицы остаются обучаемыми, а базовые веса не изменяются.

Для линейного слоя обновление весов адаптера вычисляется как $\Delta W = sBA$, где $A$ имеет форму `(r, in_features)`, $B$ имеет форму `(out_features, r)`, а $s$ — это коэффициент масштабирования LoRA. NoRA начинает с случайного веса A, созданного линейным слоем LoRA, и нормализует каждый столбец по размерности ранга:

$$ A_{:,j} \leftarrow \frac{A_{:,j}}{\max(\lVert A_{:,j} \rVert_2, 10^{-6})}, \qquad B \leftarrow 0. $$

Поскольку B равен нулю, обновление весов адаптера до обучения также равно нулю. При `bias="none"` и `lora_bias=False` адаптер изначально сохраняет выход базовой модели. NoRA не требует калибровочного набора данных или разложения весов.

> [!IMPORTANT]
> Для NoRA рекомендуемая настройка — `lora_alpha`, равный `r` (соотношение alpha/rank 1:1), например, `r=8, lora_alpha=8`. При значении по умолчанию `use_rslora=False` коэффициент масштабирования остаётся равным 1; при включении rank-stabilized LoRA он меняется на `lora_alpha / sqrt(r)`.

В следующем примере NoRA применяется к двум линейным слоям в небольшой модели PyTorch:

```py
from torch import nn

from peft import LoraConfig, get_peft_model

model = nn.Sequential(
    nn.Linear(32, 32),
    nn.ReLU(),
    nn.Linear(32, 16),
)

config = LoraConfig(
    r=8,
    lora_alpha=8,
    target_modules=["0", "2"],
    init_lora_weights="nora",
    bias="none",
    lora_bias=False,
    use_rslora=False,
)
model = get_peft_model(model, config)
model.print_healthcheck()
```

Для модели Transformers установите `target_modules` в имена линейных слоёв, которые вы хотите адаптировать, например `["q_proj", "v_proj"]`, если такие имена присутствуют в модели.

NoRA использует существующие конфигурации, API обучения, сохранения и загрузки LoRA, поэтому отдельные классы `NoraConfig` или `NoraModel` отсутствуют. Общие API конфигурации и модели описаны в [LoraConfig](/docs/peft/main/ru/package_reference/lora#peft.LoraConfig) и [LoraModel](/docs/peft/main/ru/package_reference/lora#peft.LoraModel).

NoRA поддерживает целевые модули `torch.nn.Linear` или параметры `nn.Parameter`, переданные напрямую с помощью `target_parameters`. Поддержка эмбеддингов, свёрточных слоёв и т. д. отсутствует.

[PiSSA](https://huggingface.co/papers/2404.02948) инициализирует адаптер LoRA с использованием главных сингулярных значений и сингулярных векторов. Это простое изменение позволяет PiSSA сходиться быстрее, чем LoRA, и в итоге достигать лучших результатов. Кроме того, PiSSA снижает ошибку квантования по сравнению с QLoRA, что приводит к дальнейшему улучшению качества.

Настройте метод инициализации на pissa, который может занять несколько минут для выполнения SVD на предобученной модели:
```python
from peft import LoraConfig
config = LoraConfig(init_lora_weights="pissa", ...)
```
В качестве альтернативы выполните быстрый SVD, который занимает всего несколько секунд. Количество итераций определяет баланс между ошибкой и временем вычислений:
```python
lora_config = LoraConfig(init_lora_weights="pissa_niter_[number of iters]", ...)
```
Для подробных инструкций по использованию PiSSA следуйте [этим инструкциям](https://github.com/huggingface/peft/tree/main/examples/pissa_finetuning).

[MiCA](https://arxiv.org/abs/2604.01694) (Minor Component Adaptation) дополняет PiSSA: вместо инициализации из *главных* сингулярных компонент MiCA использует *малые*. Конкретно, при `W = U Σ V^T` MiCA задаёт `B = U[:, -r:]` (`r` левых сингулярных векторов, соответствующих наименьшим сингулярным значениям) и `A = 0`. Во время обучения обновляется только `A`; `B` остаётся замороженным. Интуиция состоит в том, что малые сингулярные направления в значительной степени не используются предобученной задачей и, следовательно, обеспечивают более «пластичное» подпространство для внедрения новых знаний при сохранении предобученных возможностей.

Поскольку `A == 0` при инициализации, вклад адаптера `B · A == 0`, и выход модели сохраняется точно на шаге 0 — вычитание остатка из базового веса не требуется (в отличие от PiSSA). Так как обучаем только `A`, количество обучаемых параметров при том же `r` примерно вдвое меньше, чем в LoRA.

```python
from peft import LoraConfig
config = LoraConfig(init_lora_weights="mica", r=16, target_modules=["q_proj", "v_proj"], ...)
```

MiCA в настоящее время поддерживает целевые модули `nn.Linear` и `nn.Embedding`. Выбранный ранг должен удовлетворять условию `r <= min(in_features, out_features)` для линейных слоёв и `r <= min(num_embeddings, embedding_dim)` для слоёв встраивания. Подробные инструкции по использованию см. [здесь](https://github.com/huggingface/peft/tree/main/examples/mica_finetuning).

MiCA предназначен в первую очередь для продолжения предварительного обучения / адаптивного предварительного обучения в конкретной предметной области. В таком сценарии для инициализации SVD и обучения MiCA используйте базовую модель, а не чекпоинт, настроенный на инструкции или чат. После обучения объедините адаптер с весами базовой модели и используйте полученную адаптированную базовую модель как отправную точку для последующей настройки на инструкции/чат.

[CorDA](https://huggingface.co/papers/2406.05223) строит адаптеры LoRA, учитывающие специфику задачи, на основе разложения весов, ориентированного на контекст целевой задачи (режим предварительного просмотра инструкции, IPM) или на сохраняемые мировые знания (режим сохранения знаний, KPM). Режим KPM не только обеспечивает лучшие результаты, чем LoRA, при дообучении, но и снижает эффект катастрофического забывания предобученных мировых знаний. Если сохранение предобученных знаний не является приоритетом, предпочтительнее использовать режим IPM, поскольку он позволяет дополнительно ускорить сходимость и повысить качество дообучения.

Необходимо настроить метод инициализации на corda, а также указать режим IPM или KPM и набор данных для сбора ковариационных матриц.

```py
@torch.no_grad()
def run_model():
    # Assume `model` and `dataset` is in context...
    model.eval()
    for batch in dataset:
        model(**batch)

corda_config = CordaConfig(
    corda_method="kpm",
)
lora_config = LoraConfig(
    init_lora_weights="corda",
    corda_config=corda_config,
)
preprocess_corda(model, lora_config, run_model=run_model)
peft_model = get_peft_model(model, lora_config)
```

Для подробных инструкций по использованию CorDA следуйте [этим инструкциям](https://github.com/huggingface/peft/tree/main/examples/corda_finetuning).

[Astra](https://huggingface.co/papers/2602.19111) строит адаптеры LoRA, учитывающие специфику задачи, на основе собственных векторов хвоста ковариационной матрицы активаций выходов модуля, оцениваемых по небольшому калибровочному набору данных целевой задачи. Предобученные веса проецируются на подпространство, натянутое на собственные векторы хвоста, для инициализации адаптера. Это ограничивает обновление активационным подпространством, наиболее релевантным для целевой задачи, и ускоряет сходимость.

Необходимо настроить метод инициализации на "astra", явно задать `target_modules` и предоставить набор данных для калибровки, чтобы собрать матрицы ковариации.

```py
@torch.no_grad()
def run_model():
    # Assume `model` and `dataset` is in context...
    model.eval()
    for batch in dataset:
        model(**batch)

from peft.tuners.lora import AstraConfig, preprocess_astra

astra_config = AstraConfig()
lora_config = LoraConfig(
    init_lora_weights="astra",
    target_modules=["q_proj", "v_proj"],
    astra_config=astra_config,
)
preprocess_astra(model, lora_config, run_model=run_model)
peft_model = get_peft_model(model, lora_config)
```

Для подробных инструкций по использованию Astra, пожалуйста, следуйте [этим инструкциям](https://github.com/huggingface/peft/tree/main/examples/astra_finetuning).

[OLoRA](https://huggingface.co/papers/2406.01775) использует разложение QR для инициализации адаптеров LoRA. OLoRA сдвигает базовые веса модели на величину, равную их разложению QR, то есть изменяет веса до начала обучения. Этот подход значительно повышает стабильность, ускоряет сходимость и в итоге обеспечивает более высокую производительность.

Для использования OLoRA достаточно передать один дополнительный параметр:
```python
from peft import LoraConfig
config = LoraConfig(init_lora_weights="olora", ...)
```
Для более продвинутого использования обратитесь к нашей [документации](https://github.com/huggingface/peft/tree/main/examples/olora_finetuning).

[EVA](https://huggingface.co/papers/2410.07170) выполняет SVD для входных активаций каждого слоя и использует правые сингулярные векторы для инициализации весов LoRA. Таким образом, это схема инициализации, основанная на данных. Кроме того, EVA адаптивно распределяет ранги между слоями на основе их «доли объяснённой дисперсии» — метрики, полученной из анализа SVD.

Вы можете использовать EVA, задав `init_lora_weights="eva"` и определив [EvaConfig](/docs/peft/main/ru/package_reference/lora#peft.EvaConfig) в [LoraConfig](/docs/peft/main/ru/package_reference/lora#peft.LoraConfig):
```python
from peft import LoraConfig, EvaConfig
peft_config = LoraConfig(
    init_lora_weights = "eva",
    eva_config = EvaConfig(rho = 2.0),
    ...
)
```
Параметр `rho` (≥ 1.0) определяет допустимый объем перераспределения. При `rho=1.0` и `r=16` адаптеры LoRA ограничены ровно 16 рангами, что исключает любое перераспределение. Рекомендуемое значение для EVA с перераспределением — 2.0, что означает, что максимальный ранг для слоя составляет 2r.

Рекомендуется выполнять инициализацию EVA на ускорителе (например, CUDA GPU, Intel XPU), так как это значительно быстрее. Чтобы оптимизировать количество доступной памяти для EVA, можно использовать флаг `low_cpu_mem_usage` в [get_peft_model()](/docs/peft/main/ru/package_reference/peft_model#peft.get_peft_model):
```python
peft_model = get_peft_model(model, peft_config, low_cpu_mem_usage=True)
```
Затем вызовите [initialize_lora_eva_weights()](/docs/peft/main/ru/package_reference/lora#peft.initialize_lora_eva_weights), чтобы инициализировать веса EVA (в большинстве случаев загрузчик данных, используемый для инициализации EVA, может быть тем же, что и для дообучения):
```python
initialize_lora_eva_weights(peft_model, dataloader)
```
EVA работает с bitsandbytes из коробки. Просто инициализируйте модель с `quantization_config` и вызовите [initialize_lora_eva_weights()](/docs/peft/main/ru/package_reference/lora#peft.initialize_lora_eva_weights) как обычно.

> [!TIP]
> Для получения дальнейших инструкций по использованию EVA обратитесь к нашей [документации](https://github.com/huggingface/peft/tree/main/examples/eva_finetuning).

При квантовании базовой модели для обучения с QLoRA рекомендуется использовать инициализацию [LoftQ](https://huggingface.co/papers/2310.08659), которая, как было показано, улучшает результаты при обучении квантованных моделей. Суть подхода в том, что веса LoRA инициализируются таким образом, чтобы минимизировать ошибку квантования. Чтобы использовать LoftQ, следуйте [этим инструкциям](https://github.com/huggingface/peft/tree/main/examples/loftq_finetuning).

> [!TIP]
> Подробнее о том, как PEFT работает с квантованием и как использовать LoftQ, см. в руководстве [Quantization](../developer_guides/quantization).

Ещё один способ инициализации [LoraConfig](/docs/peft/main/ru/package_reference/lora#peft.LoraConfig) — метод [rank-stabilized LoRA (rsLoRA)](https://huggingface.co/papers/2312.03732). Архитектура LoRA масштабирует каждый адаптер на каждом прямом проходе фиксированным скаляром, который задаётся при инициализации и зависит от ранга `r`. В исходной реализации скаляр равен `lora_alpha/r`, тогда как rsLoRA использует `lora_alpha/math.sqrt(r)`, что стабилизирует адаптеры и повышает потенциал производительности при использовании более высокого значения `r`.

```py
from peft import LoraConfig

config = LoraConfig(use_rslora=True, ...)
```

[LoRA-GA](https://hf.co/papers/2407.05000) (Low-Rank Adaptation with Gradient Approximation) инициализирует веса адаптера, выполняя SVD на оценённых градиентах, чтобы веса были ближе к полным весам при полной дообучении, что обеспечивает более быструю сходимость.

Этот метод требует функции инициализации для оценки градиентов перед началом фактического обучения:

```python
from peft.tuners.lora import preprocess_loraga

def train_step():
    """Run forward and backward passes for gradient estimation."""
    dataloader_iter = iter(grad_dataloader)
    for _ in range(N):
        batch = next(dataloader_iter)
        batch = {k: v.to(device) for k, v in batch.items()}
        outputs = model(**batch)
        loss = outputs.loss
        loss.backward()

preprocess_loraga(model, lora_config, train_step)
```

**Советы по использованию**

- **Оценка градиентов**: LoRA-GA требует фазы оценки градиентов перед инициализацией модели. Используйте `preprocess_loraga()` с колбэком `train_step`, чтобы вычислить градиенты на небольшом количестве обучающих батчей (обычно 64–128 батчей).

- **Стратегии инициализации**: LoRA-GA поддерживает четыре стратегии направления (`direction`): `"ArBr"`, `"A2rBr"`, `"ArB2r"` (по умолчанию) и `"random"`, а также четыре стратегии масштабирования (`scale`): `"stable"` (по умолчанию), `"weight_svd"`, `"gd_scale"` и `"unit"`. Комбинация по умолчанию обеспечивает наилучший баланс между скоростью сходимости и стабильностью.

- **Изменение базовых весов**: В отличие от стандартного LoRA, LoRA-GA изменяет веса базовой модели при инициализации, вычитая из них масштабированную версию низко-рангового приближения. Это обеспечивает лучшее согласование с градиентами полной дообучения. Поскольку базовые веса изменяются, используйте `save_pretrained()` с аргументом `save_embedding_layers` или передавайте `path_initial_model_for_weight_conversion`.

- **Вычислительные накладные расходы**: Оценка градиента добавляет небольшие накладные расходы на этапе инициализации (обычно 1–2 минуты для 64 батчей), но они быстро окупаются за счёт более быстрой сходимости в процессе обучения.

- **Совместимость**: LoRA-GA требует веса в полной точности и не поддерживает квантованные модели. Может использоваться в сочетании с другими вариантами LoRA, такими как DoRA.

## Обучение

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

### Обучение в стиле QLoRA

Настройки LoRA по умолчанию в PEFT добавляют обучаемые веса в слои запросов и значений каждого блока внимания. Однако [QLoRA](https://hf.co/papers/2305.14314), который добавляет обучаемые веса во все линейные слои трансформерной модели, способен обеспечить производительность, сопоставимую с полностью дообученной моделью. Чтобы применить LoRA ко всем линейным слоям, как в QLoRA, установите `target_modules="all-linear"` (это проще, чем указывать отдельные модули по имени, которое может различаться в зависимости от архитектуры).

```py
config = LoraConfig(target_modules="all-linear", ...)
```

Для получения дополнительной информации о том, как применить квантование к адаптерам PEFT, обратитесь к [руководству по квантованию](../developer_guides/quantization).

### Эффективное по памяти дублирование слоёв с LoRA

Один из подходов к повышению производительности моделей заключается в расширении модели путём дублирования слоёв для построения более крупной модели на основе предобученной модели заданного размера. Например, увеличение модели 7B до 10B, как описано в статье [SOLAR](https://huggingface.co/papers/2312.15166). PEFT LoRA поддерживает такой тип расширения с высокой эффективностью использования памяти, позволяя выполнять дальнейшую дообучение с помощью адаптеров LoRA, привязанных к слоям после их дублирования. Дублированные слои не требуют дополнительной памяти, поскольку они разделяют базовые веса, поэтому единственная дополнительная память, необходимая для этого, — это память для весов адаптеров. Для использования этой функции необходимо создать конфигурацию с аргументом `layer_replication`.

```py
config = LoraConfig(layer_replication=[[0,4], [2,5]], ...)
```

Допустим, исходная модель содержала 5 слоёв `[0, 1, 2 ,3, 4]`. В этом случае будет создана модель с 7 слоями, расположенными в порядке `[0, 1, 2, 3, 2, 3, 4]`. Это соответствует конвенции сквозного слияния (pass through merge) в [mergekit](https://github.com/arcee-ai/mergekit), согласно которой последовательности слоёв, заданные кортежами «начало включительно, конец исключая», складываются для построения итоговой модели. Каждый слой в итоговой модели получает собственный уникальный набор адаптеров LoRA.

[Fewshot-Metamath-OrcaVicuna-Mistral-10B](https://huggingface.co/abacusai/Fewshot-Metamath-OrcaVicuna-Mistral-10B) — это пример модели, обученной с использованием этого метода на базе Mistral-7B, расширенной до 10B. Файл [adapter_config.json](https://huggingface.co/abacusai/Fewshot-Metamath-OrcaVicuna-Mistral-10B/blob/main/adapter_config.json) содержит пример конфигурации адаптера LoRA, применяющей этот метод для дообучения.

### Тонкий контроль над рангами и альфа (масштабирование)

По умолчанию все слои, для которых применяется LoRA, имеют одинаковый ранг `r` и одинаковое значение `lora_alpha` (которое определяет масштабирование LoRA), в соответствии с тем, что указано в [LoraConfig](/docs/peft/main/ru/package_reference/lora#peft.LoraConfig). Однако в некоторых случаях может потребоваться задать разные значения для разных слоёв. Это можно сделать, передав аргументы `rank_pattern` и `alpha_pattern` в [LoraConfig](/docs/peft/main/ru/package_reference/lora#peft.LoraConfig). Эти аргументы должны быть словарями, где ключом является имя слоя, а значением — значение ранга/альфы. Ключами могут быть [регулярные выражения](https://docs.python.org/3/library/re.html) (regex). Все слои LoRA, которые явно не указаны в `rank_pattern` и `alpha_pattern`, будут использовать значения по умолчанию `r` и `lora_alpha`.

В качестве примера предположим, что у нас есть модель со следующей структурой:

```python
>>> print(model)
Outer(
  (foo): Linear(...)
  (module): Middle(
    (foo): Linear(...)
    (foobar): Linear(...)
    (module): Inner(
      (foo): Linear(...)
      (barfoo): Linear(...)
    )
  )
)
```

- `rank_pattern={"foo": 42}` будет соответствовать всем 3 слоям `foo`. Ни `foobar`, ни `barfoo` не совпадают.
- `rank_pattern={"^foo": 42}` будет соответствовать только слою `foo` модели, но не `module.foo` и не `module.module.foo`. Это связано с тем, что `^` в регулярных выражениях означает «начало строки», и только `foo` начинается с `"foo"`, у остальных имён слоёв есть префиксы.
- `rank_pattern={"^module.foo": 42}` совпадает только с `module.foo`, но не с `module.module.foo`, по той же причине.
- `rank_pattern={"module.foo": 42}` совпадает как с `module.foo`, так и с `module.module.foo`, но не с `foo`.
- `rank_pattern={"^foo": 42, "^module.module.foo": 55}` соответствует `foo` и `module.module.foo` соответственно, но не `module.foo`.
- Нет необходимости указывать `$` для обозначения конца совпадения, так как PEFT добавляет его автоматически.

Та же логика применима к `alpha_pattern`. Если вы сомневаетесь, не пытайтесь усложнять с помощью регулярных выражений — просто передайте полное имя каждого модуля с другим рангом/альфой, предваряя его префиксом `^`, и всё будет в порядке.

### Автоматическое обнаружение подходящих целевых модулей

[peft.helpers.KappaTuneSelector](/docs/peft/main/ru/package_reference/helpers#peft.helpers.KappaTuneSelector) реализует стратегию выбора целевых слоёв на основе числа обусловленности, описанную в [статье KappaTune](https://arxiv.org/abs/2506.16289). Она просматривает каждый модуль `nn.Linear` и, для моделей, в которых веса экспертов MoE хранятся как объединённые 3D-тензоры `nn.Parameter` (например, Llama-4, Qwen3-MoE), также эти параметры, вычисляет для каждого число обусловленности матрицы κ = σ_max / σ_min и выбирает наиболее изотропные слои (с наименьшим κ). Эти изотропные слои являются идеальными кандидатами для дообучения, поскольку их высокая энтропия позволяет им легче усваивать новую информацию, оставляя специализированные анизотропные слои нетронутыми для снижения катастрофического забывания при непрерывном обучении.

Используйте [peft.helpers.find_kappa_target_modules()](/docs/peft/main/ru/package_reference/helpers#peft.find_kappa_target_modules) как однострочник, чтобы получить оптимальные `target_modules` для `LoraConfig`:

```python
from peft import LoraConfig, get_peft_model
from peft.helpers import find_kappa_target_modules

model = AutoModelForCausalLM.from_pretrained("mistralai/Mixtral-8x7B-Instruct-v0.1")

targets = find_kappa_target_modules(model, top_p=0.2)
config = LoraConfig(
    target_modules=targets["target_modules"],
    target_parameters=targets["target_parameters"] if stable_modules_dic["target_parameters"] else None,
    r=64,
    lora_alpha=32,
    task_type="CAUSAL_LM",
)
peft_model = get_peft_model(model, config)
```

Полный пример доступен [здесь](https://github.com/huggingface/peft/blob/main/examples/KappaTune/experiments_kappatune_peft.py).

### Целевое указание `nn.Parameter` напрямую

Как правило, для указания модуля (например, `nn.Linear`) следует использовать `target_modules`. Однако в некоторых случаях это невозможно. Например, во многих слоях mixture of expert (MoE) в HF Transformers вместо `nn.Linear` используется `nn.Parameter`. PEFT обычно переопределяет метод `forward` для LoRA, но для `nn.Parameter` такого метода нет. Поэтому, чтобы применить LoRA к этому параметру, его необходимо указать с помощью `target_parameters`. В качестве примера, для [Llama4](https://huggingface.co/collections/meta-llama/llama-4-67f0c30d9fe03840bc9d0164) можно передать: `target_parameters=['feed_forward.experts.gate_up_proj', 'feed_forward.experts.down_proj]`.

Обратите внимание, что при работе с параметрами экспертов PEFT может добавлять значительные накладные расходы во время выполнения. Причина в том, что PEFT всегда материализует вклад LoRA для _каждого эксперта_, даже если требуется лишь небольшое количество экспертов. Во время обучения это менее критично, поскольку в течение последовательности, как правило, активируется значительная доля экспертов хотя бы один раз. Однако во время инференса обычно используется KV-кэш, и нам нужно вычислять только последний токен, что означает активацию лишь небольшого числа экспертов. Следовательно, использование LoRA на слоях MoE может привести к существенному замедлению во время инференса. Поэтому рекомендуется объединить веса (`model.merge_adapter()` или `model = model.merge_and_unload()`). Это устраняет накладные расходы PEFT.

Более подробное исследование этой проблемы можно найти в этом [pull request по оптимизации MoE](https://github.com/huggingface/peft/pull/3139).

#### Ограничения

- На данный момент этот аргумент позволяет указывать `nn.Parameter` с 2 или 3 измерениями. Предполагается, что в случае параметра с 3 измерениями нулевое измерение является измерением экспертов.
- Поддерживается несколько адаптеров LoRA (добавленных через `model.add_adapter` или `model.load_adapter`), использующих `target_parameters`, но все они должны нацеливаться на один и тот же набор параметров.

#### Параметры экспертов MoE и vLLM

Некоторые MoE-модели в Transformers хранят веса экспертов как тензоры `nn.Parameter` (часто 3D), а не как модули `nn.Linear`. Чтобы применить LoRA к таким экспертам, используйте `target_parameters` и задайте ранг для каждого слоя с помощью `rank_pattern`:

```python
num_experts = getattr(model.config, "num_local_experts", None) or model.config.num_experts
effective_r = max(1, r // num_experts)
config = LoraConfig(
    r=r,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],
    target_parameters=[
        # Mixtral / Qwen3-MoE / GPT-OSS
        "mlp.experts.gate_up_proj",
        "mlp.experts.down_proj",
        # Llama4
        # "feed_forward.experts.gate_up_proj",
        # "feed_forward.experts.down_proj",
    ],
    rank_pattern={
        "experts.gate_up_proj": effective_r,
        "experts.down_proj": effective_r,
    },
)
```

Это позволяет сохранить общий бюджет параметров LoRA на уровне, сопоставимом с плотными слоями (см. [LoRA Without Regret](https://thinkingmachines.ai/blog/lora/) от Schulman и др.). Модули, не являющиеся экспертами, используют ранг по умолчанию `r`.

Ускоренный вывод с помощью дообученной модели возможен, например, с использованием [vLLM](https://vllm.ai/), который поддерживает объединённые слои экспертов MoE начиная с версии v0.11.2.

### Эффективное обучение токенов вместе с LoRA

Адаптеры PEFT LoRA поддерживают добавление новых токенов с помощью параметра `trainable_token_indices`. Это позволяет настраивать другие токены одновременно с дообучением конкретных слоёв. Обучаются только указанные токены, а все остальные остаются неизменными. Это экономит память и не приводит к потере контекста, накопленного в существующих эмбеддингах токенов, в отличие от обучения всей матрицы эмбеддингов. Внутренне этот метод использует слой [TrainableTokensModel](/docs/peft/main/ru/package_reference/trainable_tokens#peft.TrainableTokensModel).

```py
# for layer 'embed_tokens'
config = LoraConfig(trainable_token_indices=[idx_1, idx_2, ...], ...)

# specific embedding layer
config = LoraConfig(trainable_token_indices={'emb_tokens': [idx_1, idx_2, ...]}, ...)
```

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

```py
from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import get_peft_model, LoraConfig

base_model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1")
tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.1")

# we define our new tokens and add them to the tokenizer as special tokens
special_tokens = ['<|start_think|>', '<|stop_think|>']
tokenizer.add_special_tokens({'additional_special_tokens': special_tokens})

# make room for new tokens in the embedding matrix if it isn't big enough already
base_model.resize_token_embeddings(max(len(tokenizer), base_model.model.embed_tokens.num_embeddings))

# typical LoRA config with `trainable_token_indices` targeting embedding layer `embed_tokens`
# and specifically our new tokens we just added
lora_config = LoraConfig(
    target_modules='all-linear',
    trainable_token_indices={'embed_tokens': tokenizer.convert_tokens_to_ids(special_tokens)},
)
peft_model = get_peft_model(base_model, lora_config)

# proceed to train the model like normal
[...]
```

Веса токенов сохраняются как часть состояния адаптера (adapter state dict) наряду с весами LoRA. При полной дообучении и сохранении матрицы эмбеддингов файл был бы значительно больше.

Чтобы дать представление о том, сколько VRAM можно сэкономить, было проведено примитивное сравнение приведённого выше примера: обучение матрицы эмбеддингов полностью (`modules_to_save=["embed_tokens"]`), использование LoRA для матрицы эмбеддингов (`target_modules=[..., "embed_tokens"]`, ранг 32) и обучаемых токенов (`trainable_token_indices=[...]`, 6 токенов):

|           | Обучаемые токены |       LoRA | Полная дообучение |
| --------: | :--------------: | :--------: | :--------------: |
| VRAM      |        15,562 МБ |   15,581 МБ |     ~16,500 МБ    |
| Влияние |         6 токенов | все токены |       все токены |

### Связывание весов

Многие каузальные LM используют **weight tying**, при котором две или более весовые матрицы разделяют одни и те же базовые параметры. В наиболее распространённом случае веса входных эмбеддингов (`embed_tokens`) и веса выходной проекции (`lm_head`) используют один и тот же тензор. Это позволяет сократить количество параметров и, как правило, сохраняет качество модели.

Не всегда очевидно, как PEFT обрабатывает эти связанные веса, когда они являются целью дообучения. Для LoRA параметр `ensure_weight_tying` в [LoraConfig](/docs/peft/main/ru/package_reference/lora#peft.LoraConfig) определяет, должен ли PEFT явно сохранять связь обновлений на стороне адаптера для этих слоёв. На практике это может влиять на `modules_to_save`, `target_modules` и `trainable_token_indices`. Обратите внимание, что эта логика частично опирается на соглашения о наименовании слоёв (`"embed_tokens"`, `"lm_head"`), и корректная работа не гарантируется, если эти соглашения не соблюдаются.

Таблицы ниже обобщают ожидаемое поведение.

#### `modules_to_save`

| Веса базовой модели связаны | `ensure_weight_tying` | Форма `LoraConfig`                                  | Поведение                                                     |
|-------------------------|-----------------------|-----------------------------------------------------|--------------------------------------------------------------|
| Нет                      | `False`               | `modules_to_save=["embed_tokens"]` или `["lm_head"]` | Добавьте `ModulesToSaveWrapper` только для выбранного слоя            |
| Нет                      | `True`                | `modules_to_save=["embed_tokens"]` или `["lm_head"]` | Сначала предупредить, а затем добавить `ModulesToSaveWrapper` только для выбранного слоя |
| Да                     | `False`               | `modules_to_save=["embed_tokens"]` или `["lm_head"]` | Рассматривать как отдельные                                            |
| Да                     | `True`                | `modules_to_save=["embed_tokens"]` или `["lm_head"]` | Оберните связанные слои и сохраните связь между обёртками                      |
| Нет                      | `False`               | `modules_to_save=["embed_tokens", "lm_head"]`       | Рассматривать как отдельные                                            |
| Нет                      | `True`                | `modules_to_save=["embed_tokens", "lm_head"]`       | Предупреждать, затем обрабатывать как отдельные                                 |
| Да                     | `False`               | `modules_to_save=["embed_tokens", "lm_head"]`       | Предупреждать, затем обрабатывать как отдельные                                            |
| Да                     | `True`                | `modules_to_save=["embed_tokens", "lm_head"]`       | Держите `ModulesToSaveWrapper` связанными                            |

#### `target_modules`

| Веса базовой модели связаны | `ensure_weight_tying` | Форма `LoraConfig`                                 | Поведение                                   |
|-------------------------|-----------------------|----------------------------------------------------|--------------------------------------------|
| Нет                      | `False`               | `target_modules=["embed_tokens"]` или `["lm_head"]` | Добавление LoRA только на выбранный слой            |
| Нет                      | `True`                | `target_modules=["embed_tokens"]` или `["lm_head"]` | Предупреждение, затем добавление LoRA только на выбранный слой |
| Да                     | `False`               | `target_modules=["embed_tokens"]` или `["lm_head"]` | Рассматривать как отдельные                          |
| Да                     | `True`                | `target_modules=["embed_tokens"]` или `["lm_head"]` | Держите адаптеры LoRA связанными                    |
| Нет                      | `False`               | `target_modules=["embed_tokens", "lm_head"]`       | Рассматривать как отдельные                          |
| Нет                      | `True`                | `target_modules=["embed_tokens", "lm_head"]`       | Предупреждать, затем обрабатывать как отдельные               |
| Да                     | `False`               | `target_modules=["embed_tokens", "lm_head"]`       | Предупреждать, затем обрабатывать как отдельные                          |
| Да                     | `True`                | `target_modules=["embed_tokens", "lm_head"]`       | Держите адаптеры LoRA связанными                    |

#### `trainable_token_indices`

Для обучаемых токенов возникает дополнительная сложность: даже если LM head и эмбеддинги связаны, как пользователь я могу захотеть дообучить *разные* токены на них. Поэтому в таблице ниже мы различаем дообучение одних и тех же токенов и дообучение разных токенов.

| Веса базовой модели связаны | `ensure_weight_tying` | Форма `LoraConfig`                                                    | Поведение                                       |
|-------------------------|-----------------------|-----------------------------------------------------------------------|------------------------------------------------|
| Нет                      | `False`               | `trainable_token_indices=[1, 2, 3]`                                   | Обучаемые токены только на эмбеддингах            |
| Нет                      | `True`                | `trainable_token_indices=[1, 2, 3]`                                   | Предупреждение, затем обучаемые токены только для эмбеддингов |
| Да                     | `False`               | `trainable_token_indices=[1, 2, 3]`                                   | Связанные обучаемые токены                          |
| Да                     | `True`                | `trainable_token_indices=[1, 2, 3]`                                   | Связанные обучаемые токены                          |
| Нет                      | `False`               | `trainable_token_indices={"lm_head": [1, 2], "embed_tokens": [1, 2]}` | Рассматривать как отдельные                              |
| Нет                      | `True`                | `trainable_token_indices={"lm_head": [1, 2], "embed_tokens": [1, 2]}` | Предупреждать, затем обрабатывать как отдельные                   |
| Да                     | `False`               | `trainable_token_indices={"lm_head": [1, 2], "embed_tokens": [1, 2]}` | Связанные обучаемые токены                          |
| Да                     | `True`                | `trainable_token_indices={"lm_head": [1, 2], "embed_tokens": [1, 2]}` | Связанные обучаемые токены                          |
| Нет                      | `False`               | `trainable_token_indices={"lm_head": [1, 2], "embed_tokens": [3, 4]}` | Рассматривать как отдельные                              |
| Нет                      | `True`                | `trainable_token_indices={"lm_head": [1, 2], "embed_tokens": [3, 4]}` | Предупреждать, затем обрабатывать как отдельные                   |
| Да                     | `False`               | `trainable_token_indices={"lm_head": [1, 2], "embed_tokens": [3, 4]}` | Рассматривать как отдельные                              |
| Да                     | `True`                | `trainable_token_indices={"lm_head": [1, 2], "embed_tokens": [3, 4]}` | Ошибка                                          |

Для пользователей это означает:

- В общем, если вы хотите дообучить связанные веса и сохранить их связанными, передайте `ensure_weight_tying=True`.
- Если веса базовой модели не связаны, `ensure_weight_tying=True` не может принудительно установить связь и лишь выводит предупреждение.
- Для `trainable_token_indices` связанные слои должны использовать одни и те же индексы токенов, если `ensure_weight_tying=True`.

## Оптимизаторы

Обучение LoRA может опционально включать специализированные оптимизаторы. В настоящее время PEFT поддерживает LoRA-FA, LoRA+ и Riemannian-preconditioned LoRA.

### Оптимизатор LoRA-FA

Обучение с использованием LoRA может быть более эффективным и производительным с применением LoRA-FA, как описано в [LoRA-FA](https://huggingface.co/papers/2308.03303). LoRA-FA снижает потребление памяти для активаций, фиксируя матрицу A и настраивая только матрицу B. Во время обучения градиент B оптимизируется так, чтобы приближать градиент полной параметрической донастройки. Кроме того, потребление памяти в LoRA-FA не зависит от ранга (поскольку активация $A$ стирается), поэтому производительность можно повысить, увеличивая lora rank, без роста потребления памяти.

```py
from peft import LoraConfig, get_peft_model
from peft.optimizers import create_lorafa_optimizer
from transformers import Trainer, get_cosine_schedule_with_warmup

base_model = AutoModelForCausalLM.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct")

config = LoraConfig(...)
model = get_peft_model(base_model, config)

optimizer = create_lorafa_optimizer(
    model=model,
    r=128,
    lora_alpha=32,
    lr=7e-5,
)

scheduler = get_cosine_schedule_with_warmup(
    optimizer,
    num_warmup_steps=100,
    num_training_steps=1000,
)

trainer = Trainer(
    ...,
    optimizers=(optimizer, scheduler),
)
```

### LoRA+ оптимизированный LoRA

Обучение LoRA можно оптимизировать с помощью [LoRA+](https://huggingface.co/papers/2402.12354), который использует различные скорости обучения для матриц адаптеров A и B, что позволяет ускорить дообучение до 2 раз и повысить качество на 1–2%.

```py
from peft import LoraConfig, get_peft_model
from peft.optimizers import create_loraplus_optimizer
from transformers import Trainer
import bitsandbytes as bnb

base_model = ...
config = LoraConfig(...)
model = get_peft_model(base_model, config)

optimizer = create_loraplus_optimizer(
    model=model,
    optimizer_cls=bnb.optim.Adam8bit,
    lr=5e-5,
    loraplus_lr_ratio=16,
)
scheduler = None

...
trainer = Trainer(
    ...,
    optimizers=(optimizer, scheduler),
)
```

### LoRA с римановым предусловием

Обучение LoRA можно улучшить с помощью римановского преобразователя (preconditioner), как описано в [Riemannian Preconditioned LoRA](https://huggingface.co/papers/2402.02347). На каждом шаге оптимизатора градиенты матриц LoRA $A$ и $B$ умножаются на преобразователь размера $r \times r$, который масштабирует евклидов градиент в направлении риманова (масштабированного градиента) на многообразии матриц низкого ранга, что улучшает обусловленность обновления и может повысить сходимость. Поскольку преобразователь имеет размер $r \times r$, его накладные расходы по памяти и времени выполнения невелики при малом ранге LoRA. `create_riemannian_optimizer` обёртывает любой базовый класс оптимизатора (например, `torch.optim.AdamW` или `torch.optim.SGD`): параметры, не относящиеся к LoRA, обновляются базовым оптимизатором без изменений, а преобразованию подвергаются только слои LoRA формы `nn.Linear` (`lora_A` / `lora_B`).

```py
from peft import LoraConfig, get_peft_model
from peft.optimizers import create_riemannian_optimizer
from transformers import Trainer, get_cosine_schedule_with_warmup
import torch

base_model = AutoModelForCausalLM.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct")

config = LoraConfig(...)
model = get_peft_model(base_model, config)

optimizer = create_riemannian_optimizer(
    model=model,
    optimizer_cls=torch.optim.AdamW,
    lr=5e-5,
    reg=1e-2,
)

scheduler = get_cosine_schedule_with_warmup(
    optimizer,
    num_warmup_steps=100,
    num_training_steps=1000,
)

trainer = Trainer(
    ...,
    optimizers=(optimizer, scheduler),
)
```

`reg` — это слагаемое демпфирования, добавляемое к диагонали матрицы размера $r \times r$ перед инверсией; оно стабилизирует преобразователь, если фактор LoRA имеет (почти) неполный ранг.

## Постобучение

В этом разделе представлены возможные методы постобработки для обученных адаптеров.

### Слияние весов LoRA с базовой моделью

While LoRA is significantly smaller and faster to train, you may encounter latency issues during inference due to separately loading the base model and the LoRA adapter. To eliminate latency, use the [merge_and_unload()](/docs/peft/main/ru/package_reference/tuners#peft.tuners.tuners_utils.BaseTuner.merge_and_unload) function to merge the adapter weights with the base model. This allows you to use the newly merged model as a standalone model. The [merge_and_unload()](/docs/peft/main/ru/package_reference/tuners#peft.tuners.tuners_utils.BaseTuner.merge_and_unload) function doesn't keep the adapter weights in memory.

Ниже представлена схема, объясняющая интуицию слияния адаптеров LoRA:

    

Ниже в примерах показано, как выполнить это с помощью PEFT.

```py
from transformers import AutoModelForCausalLM
from peft import PeftModel

base_model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1")
peft_model_id = "alignment-handbook/zephyr-7b-sft-lora"
model = PeftModel.from_pretrained(base_model, peft_model_id)
model = model.merge_and_unload()
```

Важно присвоить возвращенную модель переменной и использовать её, так как [merge_and_unload()](/docs/peft/main/ru/package_reference/tuners#peft.tuners.tuners_utils.BaseTuner.merge_and_unload) не является операцией in-place. Если вам нужно сохранить копию весов, чтобы позже отменить слияние адаптера или удалить его и загрузить другой, следует использовать функцию [merge_adapter()](/docs/peft/main/ru/package_reference/tuners#peft.tuners.tuners_utils.BaseTuner.merge_adapter). Теперь у вас есть возможность использовать [unmerge_adapter()](/docs/peft/main/ru/package_reference/tuners#peft.tuners.tuners_utils.BaseTuner.unmerge_adapter), чтобы вернуть базовую модель.

```py
from transformers import AutoModelForCausalLM
from peft import PeftModel

base_model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1")
peft_model_id = "alignment-handbook/zephyr-7b-sft-lora"
model = PeftModel.from_pretrained(base_model, peft_model_id)
model.merge_adapter()

# unmerge the LoRA layers from the base model
model.unmerge_adapter()
```

> [!TIP]
> В квантованной модели операция unmerge не является точной: при merge происходит повторная квантизация базовых весов, а многократные циклы merge и unmerge могут накапливать ошибку округления. См. [Merging adapters into quantized weights](../developer_guides/quantization#merging-adapters-into-quantized-weights).

> [!WARNING]
> Если активно несколько адаптеров, а объединены только некоторые из них, необъединённые адаптеры молча не применяются. Это поведение изменится в PEFT v1.0. См. [Объединение только части активных адаптеров](../developer_guides/troubleshooting#merging-only-some-of-the-active-adapters).

Функция [add_weighted_adapter()](/docs/peft/main/ru/package_reference/lora#peft.LoraModel.add_weighted_adapter) полезна для объединения нескольких LoRA в новый адаптер на основе схемы весов, заданной пользователем в параметре `weights`. Ниже приведён пример «от и до».

Сначала загрузите базовую модель:

```python
from transformers import AutoModelForCausalLM
from peft import PeftModel
import torch

base_model = AutoModelForCausalLM.from_pretrained(
    "mistralai/Mistral-7B-v0.1", dtype=torch.float16, device_map="auto"
)
```

Затем мы загружаем первый адаптер:

```python
peft_model_id = "alignment-handbook/zephyr-7b-sft-lora"
model = PeftModel.from_pretrained(base_model, peft_model_id, adapter_name="sft")
```

Затем загрузите другой адаптер и объедините его с первым:

```python
weighted_adapter_name = "sft-dpo"
model.load_adapter("alignment-handbook/zephyr-7b-dpo-lora", adapter_name="dpo")
model.add_weighted_adapter(
    adapters=["sft", "dpo"],
    weights=[0.7, 0.3],
    adapter_name=weighted_adapter_name,
    combination_type="linear"
)
model.set_adapter(weighted_adapter_name)
```

> [!TIP]
> Существует несколько поддерживаемых методов для `combination_type`. Подробности см. в [документации](../package_reference/lora#peft.LoraModel.add_weighted_adapter). Обратите внимание, что значение "svd" для `combination_type` не поддерживается при использовании `torch.float16` или `torch.bfloat16` в качестве типа данных.

Теперь выполните инференс:

```python
device = torch.accelerator.current_accelerator().type if hasattr(torch, "accelerator") else "cuda"

tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.1")

prompt = "Hey, are you conscious? Can you talk to me?"
inputs = tokenizer(prompt, return_tensors="pt")
inputs = {k: v.to(device) for k, v in inputs.items()}

with torch.no_grad():
    generate_ids = model.generate(**inputs, max_length=30)
outputs = tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
print(outputs)
```

### Восстановление производительности базовой модели с помощью снижения размерности интрузивного пространства

Статья [LoRA vs Full Fine-tuning: An Illusion of Equivalence](https://huggingface.co/papers/2410.21228) утверждает, что обучение с использованием LoRA вводит в веса дополнительные измерения, которые имеют мало общего с уже выученными весами и приводят к забыванию ранее полученной информации. PEFT реализует предложенное средство смягчения в [peft.tuners.lora.intruders.reduce_intruder_dimension()](/docs/peft/main/ru/package_reference/lora#peft.tuners.lora.intruders.reduce_intruder_dimension).

Для смягчения проблемы будет взята модель PEFT с загруженным LoRA и создан новый изменённый адаптер, который загружается вместе с существующим адаптером и становится активным.

Пример использования:

```python
from peft.tuners.lora.intruders import reduce_intruder_dimension

peft_model = AutoPeftModelForCausalLM.from_pretrained('hubnemo/llama-3.2b-metamathqa-lora64')

reduce_intruder_dimension(
    peft_model,
    mitigation_lambda=0.75,
)

peft_model.generate(...)
```

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

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

## Загрузка адаптеров

Адаптеры можно загрузить в предобученную модель с помощью [load_adapter()](/docs/peft/main/ru/package_reference/peft_model#peft.PeftModel.load_adapter), что полезно для проверки различных адаптеров, веса которых не объединены. Активные веса адаптера задаются функцией [set_adapter()](/docs/peft/main/ru/package_reference/tuners#peft.tuners.tuners_utils.BaseTuner.set_adapter).

```py
from transformers import AutoModelForCausalLM
from peft import PeftModel

base_model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1")
peft_model_id = "alignment-handbook/zephyr-7b-sft-lora"
model = PeftModel.from_pretrained(base_model, peft_model_id)

# load different adapter
model.load_adapter("alignment-handbook/zephyr-7b-dpo-lora", adapter_name="dpo")

# set adapter as active
model.set_adapter("dpo")
```

Чтобы вернуть базовую модель, вы можете использовать [unload()](/docs/peft/main/ru/package_reference/tuners#peft.tuners.tuners_utils.BaseTuner.unload) для выгрузки всех модулей LoRA или [delete_adapter()](/docs/peft/main/ru/package_reference/tuners#peft.tuners.tuners_utils.BaseTuner.delete_adapter) для полного удаления адаптера. [unload()](/docs/peft/main/ru/package_reference/tuners#peft.tuners.tuners_utils.BaseTuner.unload) не является операцией in-place, не забудьте присвоить возвращаемую модель переменной и использовать её.

```py
# unload adapter
model = model.unload()

# delete adapter
model.delete_adapter("dpo")
```

## Параллелизм тензоров

LoRA поддерживает [Tensor Parallelism (TP)](https://huggingface.co/docs/transformers/main/en/perf_train_gpu_many#tensor-parallelism), предоставляемый Transformers. Когда базовая модель загружается с `tp_plan`, PEFT автоматически определяет конфигурацию TP для каждого целевого модуля и добавляет соответствующие хуки к весам адаптера LoRA, чтобы они корректно участвовали в тензорно-параллельных вычислениях.

> [!WARNING]
> Поддержка Tensor Parallelism для LoRA требует `transformers >= 5.4.0`. API Tensor Parallelism на основе DTensor требует `peft >= 0.21.1` и `transformers >= 5.17.0`.

Использование идентично стандартному рабочему процессу LoRA — просто загрузите базовую модель с `tp_plan` перед её обёртыванием с помощью PEFT:

```py
from transformers import AutoModelForCausalLM
from peft import get_peft_model, LoraConfig

model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.1-8B", tp_plan="auto")
lora_config = LoraConfig(r=16, target_modules=["q_proj", "v_proj"])
model = get_peft_model(model, lora_config)
```

Сохранение и загрузка работают как обычно через `save_pretrained` / `from_pretrained`. PEFT собирает разбитые веса адаптера обратно в полные тензоры перед сохранением, поэтому контрольные точки переносимы и не зависят от количества устройств, использованных во время обучения.

Если вы применяете тензорное параллелизм без TP-плана, например, с помощью `parallelize_module` из PyTorch, PEFT задаёт размеры весов LoRA для шардированного `nn.Linear` в соответствии с его локальным шардом, если размерность device mesh веса называется `"tp"`, а в противном случае — в соответствии с полной формой слоя (как в случае с FSDP2). PEFT не добавляет TP-хуки к этим весам LoRA и не собирает их при сохранении. Если имя размерности вашей TP-сетки отличается, добавьте его перед созданием модели PEFT:

```py
from peft.utils.integrations import TpMeshDimRegistry

TpMeshDimRegistry.register("tp_dim")
```

## Вывод

В этом разделе показано, что можно сделать на этапе инференса с LoRA, например, отсоединить адаптер.

### Активированный LoRA (aLoRA)

Активированный LoRA (aLoRA) — это архитектура адаптеров низкого ранга для каузальных языковых моделей, которая повторно использует существующий кэш KV базовой модели для более эффективного вывода. Этот подход лучше всего подходит для конвейеров вывода, которые полагаются на базовую модель для большинства задач/генераций, но используют адаптер(ы) aLoRA для выполнения специализированных задач в цепочке. Например, для проверки или исправления сгенерированных выходов базовой модели. В таких сценариях время вывода может быть сокращено на порядок или более. Для получения дополнительной информации об aLoRA и множества примеров использования см. [статью](https://huggingface.co/papers/2504.12397) об aLoRA.

Этот метод находит последнее вхождение последовательности вызова (`alora_invocation_tokens`) в каждом входном сообщении (она может состоять всего из 1 токена). Веса адаптера активируются на токенах, начиная с начала последовательности вызова. Все входные данные после последовательности вызова также адаптируются, и все сгенерированные токены будут использовать адаптированные веса. Веса на предыдущих токенах остаются без адаптации, что делает кэш для этих токенов взаимозаменяемым с кэшем базовой модели благодаря маске причинного внимания в причинных языковых моделях. Использование очень похоже на стандартный LoRA. Главное отличие состоит в том, что последовательность вызова должна быть указана при создании адаптера:

```py
from peft import LoraConfig

config = LoraConfig(alora_invocation_tokens=alora_invocation_tokens, task_type="CAUSAL_LM", ...)
```

alora_invocation_tokens` — это список целочисленных идентификаторов токенов. Для заданной строки вызова это можно получить следующим образом:
```py
invocation_string = "placeholder"
alora_invocation_tokens = tokenizer.encode(invocation_string, add_special_tokens=False).
```
Токенизатор — это токенизатор базовой модели. Используйте `add_special_tokens=False`, чтобы избежать добавления токенов `SOS`/`EOS` в строку поиска (что с высокой вероятностью приведёт к неудаче поиска).

**Примечания**
* aLoRA поддерживается только для задач `task_type=CAUSAL_LM` в связи с акцентом на повторное использование кэша.
* Поскольку веса адаптируются на меньшем количестве токенов, aLoRA часто (но не всегда) требует более высокий ранг (`r`), чем LoRA. `r=32` может быть хорошей отправной точкой.
* Веса aLoRA по определению не могут быть объединены с базовой моделью, поскольку веса адаптера применяются выборочно к подмножеству токенов. Попытки выполнить объединение приведут к ошибкам.
* Поиск по лучам пока не поддерживается.
* Как правило, не рекомендуется добавлять в токенизатор новые токены, отсутствующие в базовой модели. Это может усложнить целевой сценарий использования, в котором базовая модель и адаптерная модель работают с пересекающимся контекстом. Чтобы обойти эту проблему, можно добавить [обучаемые токены](../package_reference/trainable_tokens) в базовую модель до обучения адаптера.

#### Выбор последовательности вызовов и проектирование SFT

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

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

* Вариант 1: Если нет промпта, специфичного для задачи, то есть вход представляет собой историю чата с промптом `assistant`, то промпт `assistant` из шаблона чата (например, `<|start_of_role|>assistant<|end_of_role|>`) является естественным выбором для строки вызова. Чтобы найти промпт для модели, обратитесь к шаблону чата модели.
* Вариант 2: если для адаптера существует промпт, специфичный для задачи, который описывает задачу, на которой обучается адаптер, и этот промпт помещается в качестве хода `user` непосредственно перед генерацией, то промпт `user` из шаблона чата (например, `<|start_of_role|>user<|end_of_role|>`) является естественным выбором для строки вызова.

После выбора строки вызова получите токенизатор модели и получите `alora_invocation_tokens` как
```py
alora_invocation_tokens = tokenizer.encode(invocation_string, add_special_tokens=False).
```

Пример конфигурации для инференса находится в [alora finetuning](https://github.com/huggingface/peft/blob/main/examples/alora_finetuning/alora_finetuning.py).

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

Чтобы понять, почему это важно, представьте, что 'a', 'b', 'c' и 'ab' — это токены вашего токенизатора (с номерами 1, 2, 3 и 4 соответственно). Допустим, ваш alora_invocation_tokens = [2, 3]. Теперь представьте, что входная строка — это "abc". Поскольку "ab" является токеном, эта строка будет токенизирована как [4,3]. В результате alora_invocation_tokens не будут найдены, несмотря на то, что строка "bc" в ней присутствует. Однако, если начало и конец строки вызова — это специальные токены, такой сбой никогда не произойдет, поскольку специальные токены никогда не объединяются с другими символами в один и тот же токен.

#### Using (и повторное использование) кэша для генерации
Основная цель aLoRA — сделать кэш KV взаимозаменяемым между базовой моделью и моделями с адаптерами aLoRA **до начала последовательности вызовов**, поскольку значения KV базовой модели и адаптированной модели несовместимы. В частности, ключи и значения, сохранённые во время одной генерации модели, могут использоваться в последующих генерациях, чтобы избежать дорогостоящих операций prefill для токенов контекста. При обмене кэшем между базовой моделью и адаптерами aLoRA существуют два основных паттерна:
1. Базовая модель сгенерировала некоторый результат, после чего вызывается адаптер aLoRA для выполнения последующей генерации. Например, базовая модель отвечает на вопрос, а aLoRA, обученный обнаруживать галлюцинации, проверяет ответ базовой модели.
2. Адаптер aLoRA сгенерировал некоторый результат, и базовая модель или другой адаптер aLoRA вызываются для последующей генерации, где контекст частично пересекается с контекстом исходного aLoRA. Например, пользователь предоставляет запрос, а aLoRA переписывает его, чтобы сделать более самодостаточным и улучшить извлечение в RAG-системе. Затем документы извлекаются и загружаются в контекст, aLoRA проверяет, являются ли эти документы релевантными для вопроса, и после этого базовая модель генерирует ответ.

Для демонстрации описанного выше поведения при использовании кэширования мы применяем [DynamicCache](https://huggingface.co/docs/transformers/en/kv_cache) из `transformers`. Следите за тем, чтобы адаптированные значения кэша не смешивались с базовыми значениями кэша. В частности, при частичном пересечении контекста (паттерн 2) для общего использования кэша требуется дополнительный шаг.

**Вариант 1: базовая модель, за которой следует aLoRA** Здесь весь вход и результат генерации базовой модели передаются в адаптер aLoRA вместе с последовательностью вызова:
```
from transformers import DynamicCache
...
cache = DynamicCache()
inputs_base = tokenizer(prompt_base, return_tensors="pt")
# Generate from base model and save cache
with model_alora.disable_adapter():
    output = model_alora.generate(inputs_base["input_ids"].to(device),attention_mask=inputs_base["attention_mask"].to(device),past_key_values = cache,return_dict_in_generate=True)
output_text_base = tokenizer.decode(output.sequences[0])
cache = output.past_key_values

# Generate with aLoRA adapter from cache
prompt_alora = output_text + INVOCATION_STRING
inputs_alora = tokenizer(prompt_alora, return_tensors="pt").to(device)
output = model_alora.generate(**inputs_alora, past_key_values=cache)
output_text_alora = tokenizer.decode(output[0])

# Note: cache is now tainted with adapter values and cannot be used in base model from here on!
```

**Паттерн 2: генерация с aLoRA, за которой следует базовая модель (или другой aLoRA) с частичным перекрытием контекста** Здесь мы предварительно заполняем общий контекст с помощью базовой модели, а затем выполняем генерацию.

```
from transformers import DynamicCache
import copy
...
cache = DynamicCache()
inputs_shared = tokenizer(prompt_shared, return_tensors="pt").to(device)

# Prefill from base model and save cache
with model_alora.disable_adapter():
    with torch.no_grad():
        model_alora(**inputs_shared, past_key_values=cache)
cache_copy = copy.deepcopy(cache)

# Generate from aLoRA using prefilled cache
prompt_alora = prompt_shared + INVOCATION_STRING
inputs_alora = tokenizer(prompt_alora, return_tensors="pt").to(device)
output = model_alora.generate(**inputs_alora, past_key_values=cache)
output_text_alora = tokenizer.decode(output[0])

# Generate from base model using saved cache not tainted by aLoRA KV values
prompt_base = prompt_shared
inputs_base = tokenizer(prompt_base, return_tensors="pt").to(device)
with model_alora.disable_adapter():
    output = model_alora.generate(**inputs_base, past_key_values=cache_copy)
output_text_base = tokenizer.decode(output[0])
```

### Вывод с разными адаптерами LoRA в одном батче

Обычно каждая партия (батч) при инференсе должна использовать один и тот же адаптер (или набор адаптеров) в PEFT. Это может быть неудобно, так как в партиях могут содержаться примеры, предназначенные для разных адаптеров LoRA. Например, у нас может быть базовая модель, хорошо работающая с английским, и два дополнительных адаптера LoRA — один для французского, другой для немецкого. Как правило, нам приходится разделять партии так, чтобы каждая из них содержала примеры только одного языка; объединять разные языки в одной партии нельзя.

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

```python
from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel

model_id = ...
tokenizer = AutoTokenizer.from_pretrained(model_id)

model = AutoModelForCausalLM.from_pretrained(model_id)
# load the LoRA adapter for French
peft_model = PeftModel.from_pretrained(model, <path>, adapter_name="adapter_fr")
# next, load the LoRA adapter for German
peft_model.load_adapter(<path>, adapter_name="adapter_de")
```

Теперь мы хотим сгенерировать текст на выборке, содержащей все три языка: первые три примера на английском, следующие три — на французском, а последние три — на немецком. Мы можем использовать аргумент `adapter_names`, чтобы указать, какой адаптер использовать для каждого примера. Поскольку базовая модель используется для английского, для этих примеров мы применяем специальную строку `"__base__"`. Для следующих трёх примеров мы указываем имя адаптера французской LoRA-дообученной модели, в данном случае `"adapter_fr"`. Для последних трёх примеров мы указываем имя адаптера немецкой LoRA-дообученной модели, в данном случае `"adapter_de"`. Таким образом, мы можем использовать базовую модель и два адаптера в одном батче.

```python
inputs = tokenizer(
    [
        "Hello, my dog is cute",
        "Hello, my cat is awesome",
        "Hello, my fish is great",
        "Salut, mon chien est mignon",
        "Salut, mon chat est génial",
        "Salut, mon poisson est super",
        "Hallo, mein Hund ist süß",
        "Hallo, meine Katze ist toll",
        "Hallo, mein Fisch ist großartig",
    ],
    return_tensors="pt",
    padding=True,
)

adapter_names = [
    "__base__", "__base__", "__base__",
    "adapter_fr", "adapter_fr", "adapter_fr",
    "adapter_de", "adapter_de", "adapter_de",
]
output = peft_model.generate(**inputs, adapter_names=adapter_names, max_new_tokens=20)
```

Обратите внимание, что порядок здесь не имеет значения, то есть образцы в батче не нужно группировать по адаптерам, как в примере выше. Нам просто нужно убедиться, что аргумент `adapter_names` корректно соответствует образцам.

Кроме того, тот же подход также работает с функцией `modules_to_save`, которая позволяет сохранять и повторно использовать определённые слои нейронной сети, например, пользовательские головы для задач классификации, между различными адаптерами LoRA.

#### Ограничения

Использование этой функции имеет некоторые недостатки, а именно:

- Это работает только для инференса, а не для обучения.
- Отключение адаптеров с помощью контекста `with model.disable_adapter()` имеет приоритет над `adapter_names`.
- Нельзя передавать `adapter_names`, если веса некоторых адаптеров были объединены с базовыми весами с помощью метода `merge_adapter`. Сначала отмените объединение всех адаптеров, вызвав `model.unmerge_adapter()`. Обратите внимание, что объединение только части активных адаптеров имеет [аналогичное ограничение](../developer_guides/troubleshooting#merging-only-some-of-the-active-adapters) вне контекста `adapter_names`.
- По очевидным причинам это нельзя использовать после вызова `merge_and_unload()`, поскольку в этом случае все адаптеры LoRA будут объединены с базовыми весами.
- В настоящее время эта функция не работает с DoRA, поэтому установите `use_dora=False` в вашем `LoraConfig`, если вы хотите её использовать.
- Возможность `modules_to_save` в настоящее время поддерживается только для слоёв типов `Linear`, `Embedding`, `Conv2d` и `Conv1d`.
- При выводе с использованием `adapter_names` возникает ожидаемое дополнительное время выполнения, особенно если в батче много разных адаптеров. Это происходит потому, что размер батча фактически уменьшается до количества образцов на адаптер. Если для вас в приоритете производительность во время выполнения, попробуйте следующее:
  - Увеличьте размер пакета.
  - Старайтесь избегать наличия большого количества различных адаптеров в одном батче, предпочитая однородные батчи. Этого можно достичь, буферизуя примеры с одним и тем же адаптером и выполняя инференс только с небольшим набором различных адаптеров.
  - Ознакомьтесь с альтернативными реализациями, такими как [LoRAX](https://github.com/predibase/lorax), [punica](https://github.com/punica-ai/punica) или [S-LoRA](https://github.com/S-LoRA/S-LoRA), которые оптимизированы для работы с большим количеством различных адаптеров.

### Составление и повторное использование адаптеров LoRA
#### Arrow
[Arrow](https://huggingface.co/papers/2405.11157) — это модульный алгоритм маршрутизации, разработанный для объединения нескольких предварительно обученных адаптеров LoRA, специализированных на конкретных задачах, с целью решения поставленной задачи. Он похож на [Polytropon](poly), но не требует дообучения. Вместо наивного слияния всех адаптеров Arrow вводит **механизм маршрутизации mixture-of-experts (MoE) на уровне токенов, не требующий градиентов**. На этапе инференса для каждого адаптера LoRA сначала вычисляется _прототип_ путём извлечения главного правого сингулярного вектора из его SVD-разложения. Затем представления каждого токена сравниваются с этими прототипами с помощью косинусного сходства для получения коэффициентов маршрутизации. Токены назначаются k наиболее релевантным адаптерам LoRA, коэффициенты нормализуются с помощью softmax, а их выходные значения линейно комбинируются. Это позволяет эффективно переиспользовать существующие модули LoRA для новых задач и обеспечивает более сильную обобщающую способность в режиме zero-shot.

В PEFT Arrow включается с помощью [`ArrowConfig]` и `create_arrow_model`. Также можно настроить параметры, такие как `top_k` (количество объединяемых на токен адаптеров LoRA), `router_temperature` (температура softmax, применяемая к коэффициентам маршрутизации) и `rng_seed` (для воспроизводимости).

```py
from peft import create_arrow_model, ArrowConfig
from transformers import AutoModelForCausalLM

# Loading the model
base_model = AutoModelForCausalLM.from_pretrained("microsoft/Phi-3-mini-4k-instruct")

# Creating the Arrow config
arrow_config = ArrowConfig(
    top_k=3,
    router_temperature=1.0,
    rng_seed=42,
)

# The LoRA adapters below were trained on a clustered FLAN dataset.
# Task clustering was performed using the Model-Based Clustering (MBC) method,
# as described in the Arrow paper.
# While one could train a separate LoRA for each task and let Arrow route tokens among them,
# training LoRAs on clusters of tasks instead provides an indirect optimization for
# transfer across the multi-task dataset.
task_specific_adapter_paths = [
        f"TahaBa/phi3-mini-clustered-flan/ts_expert_{i}" for i in range(10)
    ]

# Creating the Arrow model
model = create_arrow_model(
        base_model=base_model,
        task_specific_adapter_paths=task_specific_adapter_paths,
        arrow_config=arrow_config,
    )

# Now the forward path could be called on this model, like a normal PeftModel.
```

Кроме того, вы можете добавлять или удалять адаптеры после вызова ```create_arrow_model``` — например, чтобы дообучить новый адаптер или удалить ненужный. Когда адаптеры на месте, вы можете активировать ```"arrow_router"``` для вывода, чтобы использовать Arrow. Обратите внимание, что если вы добавите новый адаптер LoRA после ```create_arrow_model``` и хотите его дообучить, вам нужно явно установить новый адаптер как активный, поскольку ```"arrow_router"``` активируется по умолчанию в ```create_arrow_model```.

```py
from trl import SFTTrainer, SFTConfig

# Adding a new adapter and activating it
model.add_adapter(adapter_name='new_adapter')
model.set_adapter('new_adapter')

# Now the model could be trained along the `new_adapter`.
trainer = SFTTrainer(
        model=model,
        args=SFTConfig(...),
        ...
    )

# Once the training is done, you can activate `arrow_router` and use it in inference
model.set_adapter('arrow_router')    # Model is ready to be used at inference time now
```

#### GenKnowSub
[GenKnowSub](https://aclanthology.org/2025.acl-short.54/) расширяет Arrow, очищая специфичные для задачи адаптеры LoRA перед маршрутизацией. Ключевая идея заключается в вычитании общих знаний, закодированных в пространстве LoRA, на основе [принципа забывания через отрицание](https://huggingface.co/papers/2212.04089), чтобы адаптеры задач стали более изолированными и сфокусированными на сигналах, релевантных задаче. Конкретно, GenKnowSub оценивает низкоразмерное «общее» подпространство на основе набора общих (не специфичных для задачи) адаптеров LoRA и удаляет эту компоненту из обновления LoRA каждого адаптера задачи перед посимвольной маршрутизацией Arrow. Как правило, это улучшает композиционность и снижает интерференцию при объединении множества адаптеров задач.

В PEFT включите GenKnowSub, установив ```use_gks=True``` в ArrowConfig и передав ```general_adapter_paths``` в ```create_arrow_model```:

```py
from peft import create_arrow_model, ArrowConfig
from transformers import AutoModelForCausalLM

# Loading the model
base_model = AutoModelForCausalLM.from_pretrained("microsoft/Phi-3-mini-4k-instruct")

# Creating the Arrow config
arrow_config = ArrowConfig(
    top_k=3,
    router_temperature=1.0,
    use_gks=True,
    rng_seed=42,
)

# Path to task-specific, trained on flan clustered dataset (as we explained before.)
task_specific_adapter_paths = [
        f"TahaBa/phi3-mini-clustered-flan/ts_expert_{i}" for i in range(10)
    ]
# These general adapters are trained on English, German, and French Wikipedia dataset,
# with causal language modelling objective, each pair like: (507 token tsentence, 5 token completion), and the loss computed on the completion
general_adapter_paths = [
        "TahaBa/phi3-mini-general-adapters/cluster0_batch16_prop1.0_langen/checkpoint-17",
        "TahaBa/phi3-mini-general-adapters/cluster0_batch16_prop1.0_langfr/checkpoint-35",
        "TahaBa/phi3-mini-general-adapters/cluster0_batch16_prop1.0_langger/checkpoint-17"
    ]

# Creating the Arrow model
model = create_arrow_model(
        base_model=base_model,
        task_specific_adapter_paths=task_specific_adapter_paths,
        general_adapter_paths=general_adapter_paths,
        arrow_config=arrow_config,
    )

# Now the forward path could be called on this model, like a normal PeftModel.
```
Для кодирования общих знаний GenKnowSub один раз вычитает среднее значение предоставленных общих адаптеров из каждого адаптера, специфичного для задачи, до начала маршрутизации. Кроме того, в этом случае по-прежнему поддерживается возможность добавления или удаления адаптеров после вызова ```create_arrow_model``` (как описано в разделе Arrow).

> [!TIP]
> **Что следует учитывать при использовании Arrow + GenKnowSub:**
>
> - Все адаптеры LoRA (специфичные для задачи и общие) должны иметь одинаковые ```rank``` и ```target_modules```.
>
> - Любое несоответствие в этих настройках приведёт к ошибке в ```create_arrow_model```.
>
> - Поддерживается использование различных коэффициентов масштабирования (```lora_alpha```) для адаптеров разных задач — Arrow обрабатывает их автоматически.
>
> - Объединение ```"arrow_router"``` не поддерживается из-за его динамического поведения маршрутизации.
>
> - В ```create_arrow_model``` адаптеры задач загружаются как ```task_i```, а общие адаптеры — как ```gks_j``` (где ```i``` и ```j``` — индексы). Функция обеспечивает согласованность ```target_modules```, ```rank``` и того, применяются ли адаптеры к слоям ```Linear``` или ```Linear4bit```. Затем добавляется модуль ```"arrow_router"``` и активируется. Любая кастомизация этого процесса требует переопределения ```create_arrow_model```.
>
> - Эта реализация совместима с 4-битным квантованием (через bitsandbytes):
>
>     ```py
>     from transformers import AutoModelForCausalLM, BitsAndBytesConfig
>     import torch
>
>     # Quantisation config
>     bnb_config = BitsAndBytesConfig(
>             load_in_4bit=True,
>             bnb_4bit_quant_type="nf4",
>             bnb_4bit_compute_dtype=torch.bfloat16,
>             bnb_4bit_use_double_quant=False,
>         )
>
>     # Loading the model
>     base_model = AutoModelForCausalLM.from_pretrained(
>         "microsoft/Phi-3-mini-4k-instruct",
>         dtype=torch.bfloat16,
>         device_map="auto",
>         quantization_config=bnb_config,
>     )
>
>     # Now call create_arrow_model() as we explained before.
>     ```

# API

## LoraConfig[[peft.LoraConfig]]

#### peft.LoraConfig[[peft.LoraConfig]]

```python
peft.LoraConfig(task_type: Optional[Union[str, TaskType]] = None, peft_type: Optional[Union[str, PeftType]] = None, auto_mapping: Optional[dict] = None, peft_version: Optional[str] = None, base_model_name_or_path: Optional[str] = None, revision: Optional[str] = None, inference_mode: bool = False, r: int = 8, target_modules: Optional[Union[list[str], str]] = None, exclude_modules: Optional[Union[list[str], str]] = None, lora_alpha: int = 8, lora_dropout: float = 0.0, fan_in_fan_out: bool = False, bias: Literal['none', 'all', 'lora_only'] = 'none', use_rslora: bool = False, modules_to_save: Optional[list[str]] = None, init_lora_weights: bool | Literal['gaussian', 'eva', 'olora', 'pissa', 'pissa_niter_[number of iters]', 'corda', 'astra', 'loftq', 'orthogonal', 'mica', 'nora'] = True, layers_to_transform: Optional[Union[list[int], int]] = None, layers_pattern: Optional[Union[list[str], str]] = None, rank_pattern: Optional[dict] = <factory>, alpha_pattern: Optional[dict] = <factory>, megatron_config: Optional[dict] = None, megatron_core: Optional[str] = 'megatron.core', trainable_token_indices: Optional[Union[list[int], dict[str, list[int]]]] = None, loftq_config: Union[LoftQConfig, dict] = <factory>, eva_config: Optional[EvaConfig] = None, corda_config: Optional[CordaConfig] = None, astra_config: Optional[AstraConfig] = None, lora_ga_config: Optional[LoraGAConfig] = None, use_dora: bool = False, velora_config: Optional[Union[VeloraConfig, dict]] = None, alora_invocation_tokens: Optional[list[int]] = None, use_qalora: bool = False, qalora_group_size: int = 16, monteclora_config: Optional[MontecloraConfig] = None, layer_replication: Optional[list[tuple[int, int]]] = None, runtime_config: LoraRuntimeConfig = <factory>, lora_bias: bool = False, target_parameters: Optional[list[str]] = None, use_bdlora: Optional[BdLoraConfig] = None, arrow_config: Optional[ArrowConfig] = None, kasa_config: Optional[KasaConfig] = None, ensure_weight_tying: bool = False)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/config.py#L514)

**Параметры:**

r (`int`) : размерность внимания Lora («ранг»).

target_modules (`Optional[Union[List[str], str]]`) : Имена модулей, к которым следует применить адаптер. Если это значение указано, будут заменены только модули с указанными именами. При передаче строки выполняется сопоставление по регулярному выражению. При передаче списка строк выполняется точное совпадение или проверяется, заканчивается ли имя модуля каким-либо из переданных строк. Если это значение указано как 'all-linear', выбираются все линейные/Conv1D модули (если модель является PreTrainedModel, выходной слой исключается). Если это значение не указано, модули выбираются в соответствии с архитектурой модели. Если архитектура неизвестна, будет выброшена ошибка — в этом случае следует указать целевые модули вручную. Чтобы не выбирать ни одного модуля (поскольку вы хотите применить `target_parameters`), установите `target_modules=[]`.

exclude_modules (`Optional[Union[List[str], str]]`) : Имена модулей, к которым не следует применять адаптер. При передаче строки выполняется сопоставление по регулярному выражению. При передаче списка строк выполняется точное совпадение или проверяется, заканчивается ли имя модуля каким-либо из переданных строк.

lora_alpha (`int`) : Параметр alpha для масштабирования Lora.

lora_dropout (`float`) : Вероятность dropout для слоёв Lora.

fan_in_fan_out (`bool`) : Установите это значение в True, если заменяемый слой хранит веса в формате (fan_in, fan_out). Например, gpt-2 использует `Conv1D`, который хранит веса в формате (fan_in, fan_out), поэтому это значение должно быть установлено в `True`.

bias (`str`) : Тип смещения для LoRA. Допустимые значения: 'none', 'all' или 'lora_only'. Если указано 'all' или 'lora_only', соответствующие смещения будут обновляться в процессе обучения. Обратите внимание, что это означает: даже при отключении адаптеров модель не будет выдавать тот же результат, что и базовая модель без адаптации.

use_rslora (`bool`) : Если установлено в True, используется [Rank-Stabilized LoRA](https://huggingface.co/papers/2312.03732), который задаёт коэффициент масштабирования адаптера как `lora_alpha/math.sqrt(r)`, поскольку было доказано, что это работает лучше. В противном случае будет использоваться исходное значение по умолчанию `lora_alpha/r`.

modules_to_save (`List[str]`) : Список модулей, кроме адаптерных слоёв, которые нужно сделать обучаемыми и сохранить в итоговом контрольном пункте.

init_lora_weights (`bool` | `Literal["gaussian", "eva", "olora", "pissa", "pissa_niter_[number of iters]", "corda", "astra", "loftq", "orthogonal", "mica", "nora"]`) : Способ инициализации весов адаптерных слоёв. Передача True (по умолчанию) приводит к инициализации по умолчанию из референсной реализации Microsoft, при этом вес LoRA B устанавливается в 0. Это означает, что без дальнейшей обучения адаптер LoRA не выполняет никаких действий (no-op). Установка инициализации в False приводит к случайной инициализации LoRA A и B, то есть LoRA не является no-op до начала обучения; этот вариант предназначен для отладки. Передача 'gaussian' приводит к гауссовой инициализации, масштабированной рангом LoRA для линейных слоёв. Передайте `'loftq'`, чтобы использовать инициализацию LoftQ. Передача `'eva'` приводит к data-driven инициализации Explained Variance Adaptation. EVA инициализирует LoRA на основе SVD активаций входных данных слоя и достигает SOTA-результатов благодаря способности адаптироваться к данным дообучения. Передайте `'olora'`, чтобы использовать инициализацию OLoRA. Передача `'pissa'` приводит к инициализации Principal Singular values and Singular vectors Adaptation (PiSSA), которая сходится быстрее, чем LoRA, и в итоге обеспечивает лучшие результаты. Кроме того, PiSSA снижает ошибку квантования по сравнению с QLoRA, что приводит к дальнейшему улучшению качества. Передача `'pissa_niter_[number of iters]'` запускает инициализацию PiSSA на основе Fast-SVD, где `[number of iters]` указывает количество итераций подпространства для выполнения FSVD и должно быть неотрицательным целым числом. Если `[number of iters]` установлено в 16, инициализация модели 7B завершается за несколько секунд, а эффект обучения примерно эквивалентен использованию SVD. Передача `'corda'` приводит к инициализации Context-Oriented Decomposition Adaptation, которая сходится ещё быстрее, чем PiSSA, в режиме Instruction-Previewed Mode, и лучше сохраняет мировые знания, чем LoRA, в режиме Knowledge-Preserved Mode. Передача `'astra'` приводит к инициализации Activation-Space Tail-Eigenvector Low-Rank Adaptation, которая проецирует базовые веса в собственное пространство выходных активаций, оценённое на небольшом калибровочном наборе данных. Передача `"orthogonal"` приводит к ортогональной инициализации LoRA A и B; в этом она напоминает `"olora"`, но базовые веса остаются неизменными (требуется, чтобы `r` было чётным, пока поддерживается только для линейных слоёв). Передача `"mica"` приводит к инициализации Minor Component Adaptation (MiCA), которая инициализирует B из r левых сингулярных векторов базовых весов, соответствующих наименьшим сингулярным значениям, устанавливает A в ноль и замораживает B во время обучения; обновляется только A. В настоящее время поддерживается для линейных и embedding-слоёв. Передача `"nora"` приводит к инициализации Normalized Low-Rank Adaptation (NoRA), которая нормализует каждый столбец случайно инициализированного веса LoRA A до единичной L2-нормы и устанавливает вес LoRA B в ноль. Нормализация применяется только при инициализации; базовые веса не изменяются, и оба A и B остаются обучаемыми. Рекомендуемая настройка — `lora_alpha`, равное `r`, при `use_rslora=False`, что сохраняет соотношение 1:1 и коэффициент масштабирования 1. В настоящее время поддерживается для линейных слоёв и для `nn.Parameter`, указанных в `target_parameters`.

layers_to_transform (`Union[List[int], int]`) : Индексы слоёв, которые необходимо преобразовать. Если передан список целых чисел, адаптер будет применён к слоям с индексами, указанными в этом списке. Если передано одно целое число, преобразования будут применены к слою с этим индексом.

layers_pattern (`Optional[Union[List[str], str]]`) : Имя шаблона слоя, используется только в том случае, если `layers_to_transform` отличается от `None`. Это должно указывать на `nn.ModuleList` модели, который часто называется `'layers'` или `'h'`.

rank_pattern (`dict`) : Соответствие от имён слоёв или регулярных выражений к рангам, отличным от ранга по умолчанию, указанного в `r`. Например, `{'^model.decoder.layers.0.encoder_attn.k_proj': 16}`.

alpha_pattern (`dict`) : Соответствие от имён слоёв или регулярных выражений к альфам, отличным от значения по умолчанию, заданного параметром `lora_alpha`. Например, `{'^model.decoder.layers.0.encoder_attn.k_proj': 16}`.

megatron_config (`Optional[dict]`) : Аргументы TransformerConfig для Megatron. Используется для создания параллельного линейного слоя LoRA. Получить его можно так: `core_transformer_config_from_args(get_args())`, где обе эти функции берутся из Megatron. Аргументы используются для инициализации TransformerConfig в Megatron. Этот параметр необходимо указать, если вы хотите применить LoRA к слоям ColumnParallelLinear и RowParallelLinear в megatron.

megatron_core (`Optional[str]`) : Основной модуль из Megatron, который следует использовать. По умолчанию — `"megatron.core"`.

trainable_token_indices (`Optional[Union[List[int], dict[str, List[int]]]]`) : Позволяет указать, какие индексы токенов следует дообучить выборочно, без необходимости переобучать всю матрицу эмбеддингов с помощью метода `peft.TrainableTokensModel`. Индексы токенов можно указать двумя способами. Либо вы указываете список индексов, которые будут нацелены на слой входных эмбеддингов модели (или, если он не найден, на `embed_tokens`). Либо вы можете указать словарь, где ключ — это имя модуля эмбеддингов, а значения — список индексов токенов, например `{'embed_tokens': [0, 1, ...]}`. Обратите внимание, что обучение с FSDP требует `use_orig_params=True`, чтобы избежать проблем с неравномерным `requires_grad`.

loftq_config (`Optional[LoftQConfig]`) : Конфигурация LoftQ. Если это значение не равно None, то LoftQ будет использоваться для квантования весов базовой модели и инициализации слоёв Lora. Также передайте `init_lora_weights='loftq'`. Обратите внимание, что в этом случае не следует передавать уже квантованную модель, так как LoftQ выполнит квантование модели самостоятельно. LoftQ применяется только к линейным слоям, включая те, которые указаны через `target_parameters`. Слои встраиваний и свёрточные слои не поддерживаются и используют стандартную инициализацию LoRA. Слои `nn.MultiheadAttention` не поддерживаются и вызывают ошибку.

eva_config (`Optional[EvaConfig]`) : Конфигурация EVA. Как минимум, необходимо задать аргумент dataset (используйте тот же датасет, что и для дообучения).

corda_config (`Optional[CordaConfig]`) : Конфигурация CorDA. Если это значение не равно None, то CorDA будет использоваться для построения адаптерных слоёв. Также передайте `init_lora_weights='corda'`.

astra_config (`Optional[AstraConfig]`) : Конфигурация Astra. Если это значение не равно None, то Astra будет использоваться для построения адаптерных слоёв. В этом случае также передайте `init_lora_weights='astra'` и вызовите `preprocess_astra` перед `get_peft_model`.

lora_ga_config (`Optional[LoraGAConfig]`) : Конфигурация LoRA-GA. Если передано, то для инициализации адаптерных слоёв будет использоваться LoRA-GA. В этом случае также установите `init_lora_weights='lora_ga'`.

use_dora (`bool`) : Включает 'Weight-Decomposed Low-Rank Adaptation' (DoRA). Этот метод декомпозирует обновления весов на две части: величину и направление. Направление обрабатывается обычным LoRA, а величина — отдельным обучаемым параметром. Это может повысить производительность LoRA, особенно при низких рангах. В настоящее время DoRA поддерживает только линейные и Conv2D слои. DoRA вносит больший оверхед, чем чистый LoRA, поэтому для инференса рекомендуется объединять веса. Подробнее: https://huggingface.co/papers/2402.09353.

velora_config (`Optional[VeloraConfig]`) : Включает VeLoRA, передав VeloraConfig. VeLoRA заменяет стандартный обратный проход для проекции LoRA A на собственный, который сохраняет сжатые активации вместо полных входных активаций.

kasa_config (`Optional[KasaConfig]`) : Включает KaSA (Knowledge-aware Singular-value Adaptation), передав KasaConfig. KaSA отбрасывает `r` наименьших сингулярных компонент замороженных весов базовой модели с помощью однократного SVD и вставляет обучаемую диагональ сингулярных значений между факторами LoRA A и B. В настоящее время поддерживаются только линейные слои.

alora_invocation_tokens (`List[int]`) : Если не None, включает 'Activated LoRA' (aLoRA), где alora_invocation_tokens представляет собой токенизированную строку вызова для адаптера (должна присутствовать во всех входных строках модели). Этот метод выборочно активирует веса адаптера только для токенов во время и после alora_invocation_tokens. При использовании в CausalLM это означает, что кэш KV до момента вызова взаимозаменяем с кэшем базовой модели (и других адаптеров aLoRA, работающих аналогичным образом). В результате, в конвейерах вывода, предполагающих переключение между выводом базовой модели и выводом адаптера (например, агентные конвейеры, см. примеры в статье), достигается значительная экономия (по сравнению с LoRA) за счет сохранения операций prefill. Общее ускорение вывода адаптера на vLLM может составлять порядок величины или более, в зависимости от длины общего контекста. Обратите внимание, что слияние невозможно из-за выборочного применения весов.

use_qalora (`bool`) : На данный момент реализовано только для GPTQ. Включает Quantization-Aware Low-Rank Adaptation (QALoRA). Этот метод сочетает обучение с учётом квантования с LoRA для повышения производительности квантованных моделей. Это может улучшить производительность LoRA, особенно при низких рангах. В настоящее время QALoRA поддерживает только линейные слои.

qalora_group_size (`int`) : Параметр размера группы для пулинга QALoRA, определяющий коэффициент снижения размерности. Входные измерения группируются в группы указанного размера, что снижает вычислительные затраты. Большие значения обеспечивают более сильное сжатие, но могут ухудшить качество модели. Этот параметр определяет, сколько исходных признаков усредняются для создания одного признака после пулинга. Используется только при `use_qalora=True`.

monteclora_config (`Optional[MontecloraConfig]`) : Конфигурация Monteclora (Monte Carlo Low-Rank Adaptation). Если передана, Monteclora будет использоваться для добавления вариационного Монте-Карло-сэмплирования поверх адаптеров LoRA. См. `MontecloraConfig` для подробностей о отдельных гиперпараметрах.

layer_replication (`List[Tuple[int, int]]`) : Создать новый стек слоёв, складывая слои исходной модели в соответствии с указанными диапазонами. Это позволяет расширять (или сжимать) модель без дублирования весов базовой модели. К каждому новому слою будут подключены отдельные адаптеры LoRA.

runtime_config (`LoraRuntimeConfig`) : конфигурации времени выполнения (не сохраняются и не восстанавливаются).

lora_bias (`bool`) : По умолчанию `False`. Определяет, следует ли включать смещение (bias) для параметра LoRA B. Как правило, эту опцию следует отключать. Основное применение — случай, когда веса LoRA были извлечены из полностью дообученных параметров, чтобы учесть смещение этих параметров.

target_parameters (`List[str]`, *необязательный*) : Список имён параметров, которые необходимо заменить на LoRA. Этот аргумент работает аналогично `target_modules`, за исключением того, что здесь нужно передавать имя параметра. Как правило, для указания модуля (например, `nn.Linear`) следует использовать `target_modules`. Однако в некоторых случаях это невозможно. Например, во многих слоях mixture of expert (MoE) в HF Transformers вместо `nn.Linear` используется `nn.Parameter`. PEFT обычно переопределяет метод `forward` для LoRA, но для `nn.Parameter` такого метода нет. Поэтому, чтобы применить LoRA к этому параметру, его нужно указать с помощью `target_parameters`. В качестве примера, для Llama4 можно передать: `target_parameters=['feed_forward.experts.gate_up_proj', 'feed_forward.experts.down_proj]`. Передача строки для сопоставления по регулярному выражению пока не реализована. Обратите внимание, что если модель скомпилирована и использует `target_parameters`, ожидается повторная компиляция и/или разрывы графа. Рекомендуется не использовать оба аргумента одновременно.

use_bdlora (`Optional[BdLoraConfig]`) : Включает BD-LoRA (Block-Diagonal LoRA), если передан объект BdLoraConfig. Этот метод использует блочно-диагональные матрицы для факторов LoRA-A или LoRA-B, что позволяет ускорить обслуживание нескольких моделей LoRA за счет устранения накладных расходов на коммуникацию в распределенных средах.

arrow_config (`Optional[ArrowConfig]`) : Необходимая конфигурация для применения маршрутизации arrow в модели.

ensure_weight_tying (`bool`, *необязательный*) : Привязывать ли веса после инициализации peft. Это гарантирует, что адаптеры, добавленные к привязанным слоям, также будут привязаны. Применимо только к слоям, переданным через `modules_to_save` и `target_modules`.

Это класс конфигурации для хранения конфигурации модели [LoraModel](/docs/peft/main/ru/package_reference/lora#peft.LoraModel).

#### to_dict[[peft.LoraConfig.to_dict]]

```python
to_dict()
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/config.py#L1099)

Возвращает конфигурацию вашей адаптерной модели в виде словаря. Удаляет конфигурации времени выполнения.

## LoraModel[[peft.LoraModel]]

#### peft.LoraModel[[peft.LoraModel]]

```python
peft.LoraModel(model, peft_config: Union[PeftConfig, dict[str, PeftConfig]], adapter_name: str, low_cpu_mem_usage: bool = False, state_dict: Optional[dict[str, torch.Tensor]] = None)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/model.py#L143)

**Параметры:**

model (`torch.nn.Module`) : модель, подлежащая адаптации.

config ([LoraConfig](/docs/peft/main/ru/package_reference/lora#peft.LoraConfig)) : конфигурация модели Lora.

adapter_name (`str`) : Имя адаптера, по умолчанию `"default"`.

low_cpu_mem_usage (`bool`, `optional`, по умолчанию `False`) : Создать пустые веса адаптера на мета-устройстве. Полезно для ускорения процесса загрузки.

**Возвращает:** `torch.nn.Module`

Модель Lora.

Создаёт модель Low Rank Adapter (LoRA) на основе предобученной модели transformers.

Метод подробно описан в https://huggingface.co/papers/2106.09685.

Пример:

```py
>>> from transformers import AutoModelForSeq2SeqLM
>>> from peft import LoraConfig, get_peft_model

>>> config = LoraConfig(
...     task_type="SEQ_2_SEQ_LM",
...     r=8,
...     lora_alpha=32,
...     target_modules=["q", "v"],
...     lora_dropout=0.01,
... )

>>> model = AutoModelForSeq2SeqLM.from_pretrained("t5-base")
>>> lora_model = get_peft_model(model, config)
```

```py
>>> import torch
>>> import transformers
>>> from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training

>>> rank = ...
>>> target_modules = ["q_proj", "k_proj", "v_proj", "out_proj", "fc_in", "fc_out", "wte"]
>>> config = LoraConfig(
...     r=4, lora_alpha=16, target_modules=target_modules, lora_dropout=0.1, bias="none", task_type="CAUSAL_LM"
... )
>>> quantization_config = transformers.BitsAndBytesConfig(load_in_8bit=True)

>>> tokenizer = transformers.AutoTokenizer.from_pretrained(
...     "kakaobrain/kogpt",
...     revision="KoGPT6B-ryan1.5b-float16",  # or float32 version: revision=KoGPT6B-ryan1.5b
...     bos_token="[BOS]",
...     eos_token="[EOS]",
...     unk_token="[UNK]",
...     pad_token="[PAD]",
...     mask_token="[MASK]",
... )
>>> model = transformers.GPTJForCausalLM.from_pretrained(
...     "kakaobrain/kogpt",
...     revision="KoGPT6B-ryan1.5b-float16",  # or float32 version: revision=KoGPT6B-ryan1.5b
...     pad_token_id=tokenizer.eos_token_id,
...     use_cache=False,
...     device_map={"": rank},
...     torch_dtype=torch.float16,
...     quantization_config=quantization_config,
... )
>>> model = prepare_model_for_kbit_training(model)
>>> lora_model = get_peft_model(model, config)
```

**Атрибуты**:
- **model** ([PreTrainedModel](https://huggingface.co/docs/transformers/main/en/main_classes/model#transformers.PreTrainedModel)) -- Модель, подлежащая адаптации.
- **peft_config** ([LoraConfig](/docs/peft/main/ru/package_reference/lora#peft.LoraConfig)): конфигурация модели Lora.

#### add_weighted_adapter[[peft.LoraModel.add_weighted_adapter]]

```python
add_weighted_adapter(adapters: list[str], weights: list[float], adapter_name: str, combination_type: Literal['svd', 'linear', 'cat', 'ties', 'ties_svd', 'dare_ties', 'dare_linear', 'dare_ties_svd', 'dare_linear_svd', 'magnitude_prune', 'magnitude_prune_svd'] = 'svd', svd_rank: int | None = None, svd_clamp: int | None = None, svd_full_matrices: bool = True, svd_driver: str | None = None, density: float | None = None, majority_sign_method: Literal['total', 'frequency'] = 'total')
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/model.py#L787)

**Параметры:**

adapters (`list`) : список имён адаптеров, которые будут объединены.

weights (`list`) : список весов для каждого адаптера. Вес могут быть положительными или отрицательными, что позволяет как добавлять, так и вычитать эффекты адаптеров.

adapter_name (`str`) : Имя нового адаптера.

combination_type (`str`) : Тип слияния может быть одним из [`svd`, `linear`, `cat`, `ties`, `ties_svd`, `dare_ties`, `dare_linear`, `dare_ties_svd`, `dare_linear_svd`, `magnitude_prune`, `magnitude_prune_svd`]. При использовании `cat` в качестве combination_type ранг результирующего адаптера равен сумме рангов всех адаптеров (смешанный адаптер может оказаться слишком большим и привести к ошибкам OOM). Обратите внимание, что `cat` и `svd` — это точные методы, обеспечивающие высокую точность, тогда как `linear` эффективен, но является очень грубым приближением и его следует избегать, если это возможно.

svd_rank (`int`, *optional*) : Ранг выходного адаптера для svd. Если значение не указано, будет использован максимальный ранг объединяемых адаптеров.

svd_clamp (`float`, *optional*) : Квантильная граница для ограничения (clamping) результата разложения SVD. Если указано значение None, ограничение не выполняется. По умолчанию: None.

svd_full_matrices (`bool`, *необязательный*) : Управляет тем, вычисляется ли полное или сокращённое SVD, а также формой возвращаемых тензоров U и Vh. По умолчанию True.

svd_driver (`str`, *optional*) : Название метода cuSOLVER, который будет использоваться. Этот аргумент работает только при слиянии на CUDA. Может принимать одно из значений [None, `gesvd`, `gesvdj`, `gesvda`]. Подробнее см. документацию `torch.linalg.svd`. По умолчанию — None.

density (`float`, *optional*) : Значение от 0 до 1. 0 означает, что все значения удаляются, а 1 — что значения не удаляются. Должно использоваться вместе с [`ties`, `ties_svd`, `dare_ties`, `dare_linear`, `dare_ties_svd`, `dare_linear_svd`, `magnintude_prune`, `magnitude_prune_svd`]

majority_sign_method (`str`) : Метод, должен быть одним из ["total", "frequency"], для определения величины значений знака. Следует использовать с [`ties`, `ties_svd`, `dare_ties`, `dare_ties_svd`]

Этот метод добавляет новый адаптер, объединяя указанные адаптеры с заданными весами.

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

#### subtract_mutated_init[[peft.LoraModel.subtract_mutated_init]]

```python
subtract_mutated_init(output_state_dict: dict[str, torch.Tensor], adapter_name: str, kwargs = None)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/model.py#L1069)

Эта функция может вычислять обновления PiSSA/CorDA/OLoRA, сравнивая параметры адаптера PiSSA/CorDA/OLoRA в `output_state_dict` с начальными значениями PiSSA/CorDA/OLoRA в `adapter_name`, тем самым преобразуя PiSSA/CorDA/OLoRA в LoRA.

Методы вроде PiSSA удаляют часть базовых весов модели для обучения, поэтому их не так просто заменить. Однако если вам известны и начальные веса предобучения, и веса после обучения, вы можете вычислить \Delta W и использовать его в качестве адаптера LoRA.

Шаги вычислений:

- $W = W_{res} + A_0 B_0$ (инициализация PiSSA)
- $W + \Delta W = W_{res} + A B$ (PiSSA после обучения)
- $\Delta W = W_{res} + AB - W = W_{res} + AB - W_{res} - A_0 B_0$ (Вывод dW для LoRA)
- $\Delta W = AB - A_0 B_0$

## Утилиты

### ArrowConfig[[peft.ArrowConfig]]

#### peft.ArrowConfig[[peft.ArrowConfig]]

```python
peft.ArrowConfig(top_k: int = 3, router_temperature: float = 1.0, use_gks: bool = False, rng_seed: Optional[int] = None)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/config.py#L139)

Это класс подконфигурации для хранения конфигурации алгоритмов Arrow и GenKnowSub. Arrow — это алгоритм маршрутизации для объединения обученных модулей LoRA с целью решения новых задач, предложенный в 'https://huggingface.co/papers/2405.11157'. GenKnowSub — это метод уточнения обученных модулей перед их объединением с помощью Arrow, описанный в 'https://aclanthology.org/2025.acl-short.54/'

### LoftQ

#### replace_lora_weights_loftq[[peft.replace_lora_weights_loftq]]

#### peft.replace_lora_weights_loftq[[peft.replace_lora_weights_loftq]]

```python
peft.replace_lora_weights_loftq(peft_model, model_path: Optional[str] = None, adapter_name: str = 'default', callback: Optional[Callable[[torch.nn.Module, str], bool]] = None)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/utils/loftq_utils.py#L194)

**Параметры:**

peft_model (`PeftModel`) : модель, веса которой необходимо заменить. Должна быть квантованной PEFT-моделью с слоями LoRA.

model_path (`Optional[str]`) : Путь к файлу safetensors модели. Если модель является моделью Hugging Face, этот путь будет определён из конфигурации модели. В противном случае его необходимо указать.

adapter_name (`str`) : Имя адаптера, веса которого будут заменены. Имя адаптера по умолчанию — "default".

callback (`Optional[Callable[[PeftModel, str], bool]]`) : Функция обратного вызова, которая будет вызвана после замены каждого модуля. Функция обратного вызова должна принимать в качестве входных данных модель и имя текущего модуля и возвращать логическое значение, указывающее, следует ли сохранить замену. Если функция обратного вызова возвращает False, замена будет отменена. Это может быть очень полезно для подтверждения того, что инициализация LoftQ действительно снижает ошибку квантования модели. В качестве примера эта функция обратного вызова может генерировать логиты для заданного входа и сравнивать их с логитами исходной неквантованной модели при том же входе, возвращая `True` только в случае улучшения. Поскольку это жадная оптимизация, возможно, что многократный вызов этой функции приведет к постепенному улучшению.

Замените веса LoRA модели, квантованной с помощью bitsandbytes, используя технику LoftQ.

Замена выполняется на лету путём загрузки неоквантованных весов из локально хранящегося файла модели в формате safetensors и инициализации весов LoRA таким образом, чтобы минимизировать ошибку квантования между исходными и оквантованными весами.

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

В зависимости от размера модели вызов этой функции может занять некоторое время.

#### LoftQConfig[[peft.LoftQConfig]]

#### peft.LoftQConfig[[peft.LoftQConfig]]

```python
peft.LoftQConfig(loftq_bits: int = 4, loftq_iter: int = 1)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/config.py#L125)

**Параметры:**

loftq_bits (`int`) : Количество бит квантования для LoftQ.

loftq_iter (`int`) : Чередующиеся итерации для LoftQ.

Это класс подконфигурации для хранения конфигурации [LoraModel](/docs/peft/main/ru/package_reference/lora#peft.LoraModel).

### Eva

#### EvaConfig[[peft.EvaConfig]]

#### peft.EvaConfig[[peft.EvaConfig]]

```python
peft.EvaConfig(rho: float = 2.0, tau: float = 0.99, use_label_mask: bool = True, label_mask_value: int = -100, whiten: bool = False, adjust_scaling_factors: bool = True)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/config.py#L263)

**Параметры:**

rho (`float`) : значение Rho для перераспределения EVA (>= 1.0). Максимальный ранг для слоя равен lora_r * rho. По умолчанию 2.0, что означает, что максимальный допустимый ранг для слоя составляет 2r. Увеличение rho позволяет более сильно перераспределять ранги между слоями. Некоторые предобученные модели могут быть более чувствительны к перераспределению рангов. Поэтому, если производительность ниже ожидаемой, может быть полезно попробовать rho=1.0 (без перераспределения).

tau (`float`) : Порог косинусного сходства для раннего завершения. Сравнивает косинусное сходство правых сингулярных векторов между двумя последовательными шагами СРР. Если косинусное сходство превышает этот порог, итерация СРР останавливается. По умолчанию 0.99.

use_label_mask (`bool`) : Использовать маску меток для инициализации EVA. Это означает, что позиции, где labels=label_mask_value, игнорируются при вычислении SVD. В большинстве случаев предпочтительнее устанавливать use_label_mask=True, что особенно полезно для многоходовых диалогов. Значение по умолчанию — True. Фильтрация элементов на основе маски меток иногда приводит к малому размеру батча и, как следствие, к нестабильности вычислений SVD. В случаях, когда большая часть элементов батча была бы отфильтрована, установите use_label_mask=False.

label_mask_value (`int`) : Если use_label_mask=True, значение, по которому маскируются игнорируемые токены. По умолчанию -100.

whiten (`bool`) : Применить отбеливание к сингулярным векторам. По умолчанию False. Отбеливание показало свою полезность для EVA в области компьютерного зрения.

adjust_scaling_factors (`bool`) : Настройка коэффициентов масштабирования LoRA после перераспределения рангов. Если установить это значение в True, коэффициенты масштабирования будут скорректированы так, чтобы все градиенты LoRA имели одинаковый масштаб независимо от их ранга. По умолчанию True.

Это класс подконфигурации для хранения конфигурации инициализации на основе данных с помощью EVA. EVA была представлена в статье Explained Variance Adaptation.

#### initialize_lora_eva_weights[[peft.initialize_lora_eva_weights]]

#### peft.initialize_lora_eva_weights[[peft.initialize_lora_eva_weights]]

```python
peft.initialize_lora_eva_weights(model: Module, dataloader: collections.abc.Iterable | None = None, eva_state_dict: dict | None = None, forward_fn: collections.abc.Callable | None = <function forward_fn_dict at 0x7fadfac44d50>, prepare_model_inputs_fn: collections.abc.Callable | None = <function prepare_model_inputs_fn_language_modeling at 0x7fadfac44b40>, prepare_layer_inputs_fn: collections.abc.Callable | dict[str, collections.abc.Callable] | None = <function prepare_layer_inputs_fn_language_modeling at 0x7fadfac44ca0>, adapter_name: str = 'default', gather_distributed_inputs: bool = True, show_progress_bar: bool = True)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/eva.py#L654)

**Параметры:**

model (PeftModel) : модель peft, для которой вычисляется SVD.

dataloader (Optional[Iterable]) : загрузчик данных, используемый для прямого прохода. Если значение равно None, необходимо указать eva_state_dict.

eva_state_dict (Optional[dict]) : state_dict для загрузки в модель. Если значение равно None, необходимо предоставить dataloader, и state_dict будет вычислен с помощью `get_eva_state_dict`.

forward_fn (Callable) : функция forward, используемая для прямого прохода. Принимает два аргумента: `model` и `inputs`. Поведение по умолчанию — `return model(**inputs)`

prepare_model_inputs_fn (Optional[Callable]) : Эта функция принимает входные данные модели и peft_config и передаёт результат в `prepare_layer_inputs_fn`. Может использоваться для изменения входных данных для вычисления SVD на основе исходных входных данных модели. Например, в задачах языкового моделирования маска внимания используется для определения индексов токенов-заполнителей, которые не должны использоваться при вычислении SVD. Любая функция, определённая здесь, ожидает два аргумента: `model_input` и `peft_config`. По умолчанию используется `peft.tuners.lora.eva.prepare_model_inputs_fn_language_modeling`.

prepare_layer_inputs_fn (Union[Callable, Dict[str, Callable], None]) : Эта функция принимает входные данные слоя, входные данные модели (возможно, изменённые с помощью `prepare_model_inputs_fn`) и имя слоя, и возвращает входные данные, которые следует использовать для SVD для данного конкретного слоя. Любая пользовательская функция, определённая здесь, ожидает три аргумента: `layer_input`, `model_input` и `layer_name`, и должна возвращать 2D-тензор. Логика по умолчанию описана в peft.tuners.lora.eva.prepare_layer_inputs_fn_language_modeling и работает для языкового моделирования. В этом случае model_inputs — это маска, используемая для определения индексов, которые следует использовать для SVD (созданная с помощью `prepare_model_inputs_fn_language_modeling`).

adapter_name (str) : Имя адаптера, для которого необходимо инициализировать веса.

gather_distributed_inputs (bool) : Флаг, определяющий, следует ли собирать входные данные слоя со всех рангов. По умолчанию установлено значение True, что означает, что в распределённой среде входные данные слоя собираются со всех рангов для вычисления SVD. В нераспределённых средах этот аргумент игнорируется. Установите значение False, если вы используете нераспределённый загрузчик данных в распределённой среде.

show_progress_bar (bool) : Флаг, определяющий, следует ли отображать индикатор прогресса. По умолчанию True.

**Возвращает:** `model (torch.nn.Module)`

Модель с инициализированными весами LoRA.

Инициализируйте веса слоёв LoRA с использованием метода EVA.

Эта функция инициализирует веса слоёв LoRA с использованием метода EVA. Она вычисляет SVD для каждого адаптерного слоя и обновляет веса соответствующим образом.

#### get_eva_state_dict[[peft.get_eva_state_dict]]

#### peft.get_eva_state_dict[[peft.get_eva_state_dict]]

```python
peft.get_eva_state_dict(model: Module, dataloader: Iterable, peft_config: peft.tuners.lora.config.LoraConfig | None = None, forward_fn: collections.abc.Callable | None = <function forward_fn_dict at 0x7fadfac44d50>, prepare_model_inputs_fn: collections.abc.Callable | None = <function prepare_model_inputs_fn_language_modeling at 0x7fadfac44b40>, prepare_layer_inputs_fn: collections.abc.Callable | dict[str, collections.abc.Callable] | None = <function prepare_layer_inputs_fn_language_modeling at 0x7fadfac44ca0>, adapter_name: str = 'default', gather_distributed_inputs: bool = True, show_progress_bar: bool = True)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/eva.py#L556)

**Параметры:**

model (torch.nn.Module) : Модель, для которой вычисляется SVD. Не обязательно должна быть PeftModel.

dataloader (Iterable) : загрузчик данных, используемый для прямого прохода.

peft_config (Optional[LoraConfig]) : Конфигурация для слоёв LoRA. Требуется только в том случае, если `model` не является PeftModel.

forward_fn (Callable) : функция forward, используемая для прямого прохода. Принимает два аргумента: `model` и `inputs`. Поведение по умолчанию — `return model(**inputs)`

prepare_model_inputs_fn (Optional[Callable]) : Эта функция принимает входные данные модели и peft_config и передаёт результат в `prepare_layer_inputs_fn`. Может использоваться для изменения входных данных для вычисления SVD на основе исходных входных данных модели. Например, в задачах языкового моделирования маска внимания используется для определения индексов токенов-заполнителей, которые не должны использоваться при вычислении SVD. Любая функция, определённая здесь, ожидает два аргумента: `model_input` и `peft_config`. По умолчанию используется `peft.tuners.lora.eva.prepare_model_inputs_fn_language_modeling`.

prepare_layer_inputs_fn (Union[Callable, Dict[str, Callable], None]) : Эта функция принимает входные данные слоя, входные данные модели (возможно, изменённые с помощью `prepare_model_inputs_fn`) и имя слоя, и возвращает входные данные, которые следует использовать для SVD для данного конкретного слоя. Любая пользовательская функция, определённая здесь, ожидает три аргумента: `layer_input`, `model_input` и `layer_name`, и должна возвращать 2D-тензор. Логика по умолчанию описана в peft.tuners.lora.eva.prepare_layer_inputs_fn_language_modeling и работает для языкового моделирования. В этом случае model_inputs — это маска, используемая для определения индексов, которые следует использовать для SVD (созданная с помощью `prepare_model_inputs_fn_language_modeling`).

adapter_name (str) : Имя адаптера, для которого вычисляется SVD.

gather_distributed_inputs (bool) : Флаг, определяющий, следует ли собирать входные данные слоя со всех рангов. По умолчанию установлено значение True, что означает, что в распределённой среде входные данные слоя собираются со всех рангов для вычисления SVD. В нераспределённых средах этот аргумент игнорируется. Установите значение False, если вы используете нераспределённый загрузчик данных в распределённой среде.

show_progress_bar (bool) : Флаг, определяющий, следует ли отображать индикатор прогресса. По умолчанию True.

**Возвращает:** `eva_state_dict (dict)`

Словарь состояний, содержащий компоненты SVD для каждого слоя.

Вычислите SVD для каждого слоя в модели.

Эта функция вычисляет разложение по сингулярным значениям (SVD) для каждого слоя модели. Для вычисления компонентов SVD используется метод инкрементального PCA. Функция также проверяет сходимость вычисленных компонентов с помощью косинусного сходства. Распределение ранга для каждого слоя определяется на основе доли объяснённой дисперсии.

### LoraGAConfig[[peft.LoraGAConfig]]

#### peft.LoraGAConfig[[peft.LoraGAConfig]]

```python
peft.LoraGAConfig(direction: Literal['ArBr', 'A2rBr', 'ArB2r', 'random'] = 'ArB2r', scale: Literal['stable', 'weight_svd', 'gd_scale', 'unit'] = 'stable', stable_gamma: int = 16)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/config.py#L1248)

**Параметры:**

direction (`Literal["ArBr", "A2rBr", "ArB2r", "random"]`) : Стратегия распределения компонентов градиентного SVD по матрицам lora_A и lora_B. - "ArBr": Чередование индексов (A получает нечётные, B — чётные) - "A2rBr": A получает индексы [r:2r], B получает индексы [:r] - "ArB2r": A получает индексы [:r], B получает индексы [r:2r] (рекомендуется) - "random": Случайный выбор индексов По умолчанию: "ArB2r"

scale (`Literal["stable", "weight_svd", "gd_scale", "unit"]`) : Стратегия масштабирования для инициализации адаптера. - "stable": Стабильное масштабирование с параметром gamma - "weight_svd": Масштабирование на основе сингулярных значений матрицы весов - "gd_scale": Масштабирование на основе градиентного спуска - "unit": Без дополнительного масштабирования По умолчанию: "stable"

stable_gamma (`int`) : Параметр гамма для метода стабильного масштабирования. По умолчанию: 16

Это класс подконфигурации для хранения конфигурации инициализации LoRA-GA.

LoRA-GA (Low-Rank Adaptation with Gradient Approximation) использует информацию о градиентах на этапе инициализации для достижения более быстрой сходимости (ускорение в 2–4 раза), выравнивая начальные веса адаптера с направлением градиентов полной дообучения.

Ссылка: https://arxiv.org/abs/2407.05000

#### Утилиты[[peft.tuners.lora.loraga.estimate_gradients]]

#### peft.tuners.lora.loraga.estimate_gradients[[peft.tuners.lora.loraga.estimate_gradients]]

```python
peft.tuners.lora.loraga.estimate_gradients(model: Module, lora_config: LoraConfig, train_step: Callable)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/loraga.py#L118)

Оценка градиентов для инициализации LoRA-GA.

Эта функция позволяет вычислять градиенты только для весов целевого модуля и запускает callback train_step. Это более эффективно по памяти, чем включение градиентов глобально.

#### peft.preprocess_loraga[[peft.preprocess_loraga]]

```python
peft.preprocess_loraga(model: Module, lora_config: LoraConfig, train_step: Callable, cache_file: str | None = None)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/loraga.py#L46)

**Параметры:**

model (`nn.Module`) : модель для предобработки.

lora_config (`LoraConfig`) : конфигурация Lora для модели. Необходимо установить `lora_config.lora_ga_config`.

train_step (`Callable[[], None]`) : Колбэк для запуска оценки градиентов. Как правило, в этом колбэке следует выполнять прямой и обратный проходы модели. Градиенты будут накапливаться во всех вызовах внутри этого колбэка.

cache_file (`Optional[str]`) : Необязательный путь к файлу кэша для сохранения/загрузки градиентов. Если указан и файл существует, градиенты будут загружены из кэша. В противном случае градиенты будут оценены и сохранены по этому пути.

Сформируйте необходимые поля LoRA-GA для модели, оценив градиенты.

Для каждого линейного слоя градиенты будут оценены путём выполнения предоставленного колбэка train_step. Затем эти градиенты привязываются к модулям и используются во время инициализации.

По завершении для каждого целевого модуля устанавливаются следующие поля: _peft_loraga_grad (`torch.Tensor`): накопленный градиент для матрицы весов.

## Сокращение размерности Intruder[[peft.tuners.lora.intruders.reduce_intruder_dimension]]

#### peft.tuners.lora.intruders.reduce_intruder_dimension[[peft.tuners.lora.intruders.reduce_intruder_dimension]]

```python
peft.tuners.lora.intruders.reduce_intruder_dimension(peft_model, old_adapter_name = 'default', new_adapter_name = 'intruder_reduced', top_k = 10, threshold_epsilon = 0.5, mitigation_lambda = 0.75, logging_sink = <built-in function print>)
```

[Источник](https://github.com/huggingface/peft/blob/main/src/peft/tuners/lora/intruders.py#L20)

**Параметры:**

peft_model : PEFT-модель с загруженным адаптером LoRA, имя которого указано в `old_adapter_name`. В настоящее время смешанные модели не поддерживаются.

top_k (default : 10) Учитывать топ-k измерений для обнаружения посторонних элементов. Чем больше значение, тем больше измерений будет учитываться при анализе для обнаружения посторонних элементов (и тем выше вероятность ложных срабатываний). Работает на основе косинусного сходства между базовыми весами и весами адаптера, примерно отсортированных по влиянию измерения (определяемому с помощью сингулярного разложения), поэтому значение top-k, равное 10, означает рассмотрение 10 наиболее «важных» измерений.

threshold_epsilon (default : 0.5) Пороговое значение, при котором косинусное сходство между базовым весом и весом адаптера считается вторжением. Согласно статье, измерения вторжения демонстрируют близкое к нулю абсолютное косинусное сходство с предобученными сингулярными векторами. Чем ниже это значение, тем меньше потенциальных измерений вторжения идентифицируется. Чем выше значение, тем больше потенциальных ложных срабатываний рассматриваются как вторжения.

mitigation_lambda (default : 0.75) Относительная доля размерности интрудера, которая вычитается из дельта-веса адаптера. Чем выше значение, тем большая часть размерности интрудера вычитается, но тем больше информации теряется. См. рисунок 8 в статье для анализа компромиссов.

logging_sink (по умолчанию: print) Функция, выводящая информацию о процессе смягчения. Установите значение None, если не требуется вывод.

Митигация размерности интрузера на основе https://huggingface.co/papers/2410.21228 («LoRA vs Full Fine-tuning: An Illusion of Equivalence»).

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

После завершения митигации будет создан новый адаптер с именем, заданным в `new_adapter_name`, который также станет текущим активным адаптером. Следовательно, инференс на митигированной модели будет использовать изменённый адаптер. Чтобы переключиться обратно на исходный адаптер, можно использовать `peft_model.set_adapter(<old_adapter_name>)`.

В настоящее время поддерживается только LoRA, так как неясно, распространяется ли этот метод на другие методы дельта-весов.

