# Monkeyパッチング（実験的機能）

Monkey patching は、元のモデルコードを変更せずに、モデルのコンポーネントをグローバルに置き換えることを可能にします。登録されたパッチは、[from_pretrained()](/docs/transformers/main/ja/main_classes/model#transformers.PreTrainedModel.from_pretrained) または `~PreTrainedModel.from_config` でモデルを読み込む際に自動的に適用されます。これにより、量子化の互換性といった特定の要件に合わせてモデルを再構成したり、最適化を適用したり、アーキテクチャのバリアントをテストしたりできます。

> [!WARNING]
> モジュールのレイアウトや構造、またはその重みを変更する必要がある場合、**モンキーパッチングは最終手段として使用すべきです**。多くのカスタマイズや最適化のニーズには、代わりに[Attention インターフェース](./attention_interface)、[Experts インターフェース](./experts_interface)、または[Kernels レジストリ](./kernel_doc/overview)の使用を検討してください。モンキーパッチングは、カスタムな forward 実装だけでは達成できない構造的な変更が必要な場合（例：量子化ライブラリとの互換性、レイヤーの融合、アーキテクチャの実験など）にのみ使用してください。

## クイックスタート

モデルのコンポーネントを置き換える方法を示す簡単な例を以下に示します。

```python
from transformers import AutoModelForCausalLM
from transformers.models.llama.modeling_llama import LlamaAttention
from transformers.monkey_patching import register_patch_mapping

# Define your replacement class (must inherit from nn.Module)
class CustomLlamaAttention(LlamaAttention):
    def forward(self, *args, **kwargs):
        # Your custom implementation
        print("Using custom attention!")
        return super().forward(*args, **kwargs)

# Register the patch globally (only applies to transformers modeling modules)
register_patch_mapping(mapping={"LlamaAttention": CustomLlamaAttention})

# Load a model - the patch is automatically applied during initialization
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-1B")

# All LlamaAttention layers in the model are now CustomLlamaAttention instances
print(type(model.model.layers[0].self_attn))  # <class '__main__.CustomLlamaAttention'>
```

## 仕組み

Monkey patch は2段階のプロセスで機能します:

1. **登録**: `register_patch_mapping`を呼び出して、グローバルレジストリにマッピングを追加します。

2. **アプリケーション**: パッチはモデルの初期化時に自動的に適用されます:
   - **`from_pretrained` / `from_config`**: パッチは内部のコンテキストマネージャーによって**自動的に**適用されます。追加の操作は不要です！
   - **手動構築**（例: `Model(config)`）: `apply_patches` コンテキストマネージャーを手動で使用する必要があります。

`clear_patch_mapping`でクリアするまで、パッチが登録されると永続化され、以降のすべてのモデル読み込みに影響します。

**重要な制限事項**：

- `transformers`のモデリングモジュール内のクラスのみがパッチ適用の対象となります（例: `LlamaAttention`、`LlamaMLP`）。
- マッピングのキーは、正確なクラス名または正規表現パターン（[パターンマッチング](#pattern-matching)を参照）のいずれかです。

## グローバル登録

`register_patch_mapping` を使用して、マッピングをグローバルに登録します:

```python
from transformers.monkey_patching import register_patch_mapping

# Register a single patch
register_patch_mapping(
    mapping={"Qwen2MoeExperts": SequentialExperts}
)

# Register multiple patches at once
register_patch_mapping(
    mapping={
        "Qwen2MoeExperts": SequentialExperts,
        "Qwen2MoeAttention": CustomAttention,
    },
    # Overwrite existing patches if they exist
    overwrite=True,
)
```

## パターンマッチング

正規表現を使用して、1つのパターンで複数のクラスに一致させることができます:

```python
from transformers.monkey_patching import register_patch_mapping

# Match all classes containing "Attention"
register_patch_mapping(
    mapping={".*Attention": CustomAttention}
)

# More examples
register_patch_mapping(
    mapping={
        ".*MoeExperts$": CustomExperts,           # Ends with "MoeExperts"
        "^Llama\\d+Attention$": CustomAttention,  # Llama2Attention, Llama3Attention, etc.
    }
)
```

**重要**: 完全一致はパターンより優先されます。`"LlamaAttention"` と `".*Attention"` の両方を登録した場合、`LlamaAttention` という名前のクラスは完全一致の置換が適用され、その他の一致するクラスにはパターン一致の置換が適用されます。

> [!WARNING]
> **正規表現パターンは、モデルを静かに壊す可能性があります。** `".*Attention"` のような広範なパターンは、*すべての* クラス名に "Attention" を含むクラスにマッチします。実際に置き換えたいアテンションをラップしているコンテナクラスも含まれます。例えば、BERT にはアテンション関連のクラスが 3 つあります: `BertSelfAttention` と `BertCrossAttention` (内部のアテンション実装) と `BertAttention` (これらの内部クラスの 1 つを*含む*外部モジュール) です。これら 3 つすべてを同じカスタムアテンションレイヤーでパッチすると、外部の `BertAttention` がもはや内部のものをラップしなくなるため、モデルが壊れます。それは内部のものの*1 つ*となり、`self` や `output` といった期待されるサブモジュールがなくなります。意図しないマッチングを避けるために、狭いパターン (例: `".*SelfAttention$"`) または正確なクラス名を使用してください。

パッチの登録を解除するには、`unregister_patch_mapping`を使用します。

```python
from transformers.monkey_patching import unregister_patch_mapping

# Unregister a single patch (use exact name or pattern from registration)
unregister_patch_mapping(keys=["Qwen2MoeExperts"])

# Unregister multiple patches at once
unregister_patch_mapping(keys=["Qwen2MoeExperts", "Qwen2MoeAttention"])

# Unregister a pattern
unregister_patch_mapping(keys=[".*Attention"])
```

登録されたすべてのパッチをクリアするには、`clear_patch_mapping`を使用します:

```python
from transformers.monkey_patching import clear_patch_mapping

clear_patch_mapping()
```

現在登録されているパッチを確認するには、`get_patch_mapping`を使用します:

```python
from transformers.monkey_patching import get_patch_mapping

current_patches = get_patch_mapping()
print(current_patches)
```

## 手動でのモデル構築

`apply_patches` コンテキストマネージャーは、`from_pretrained` や `from_config` を使わずにモデルを**手動で**構築する場合（例: `Model(config)`）にのみ必要です:

```python
from transformers import LlamaModel, LlamaConfig
from transformers.monkey_patching import register_patch_mapping, apply_patches

# Register patch globally
register_patch_mapping(mapping={"LlamaAttention": CustomAttention})

# For manual construction, you need the context manager
with apply_patches():
    model = LlamaModel(LlamaConfig())  # Uses CustomAttention

# Without the context manager, manual construction uses original classes
model = LlamaModel(LlamaConfig())  # Uses LlamaAttention

# But from_pretrained and from_config will always apply registered patches
model = LlamaModel.from_pretrained("meta-llama/Llama-3.2-1B")  # Uses CustomAttention
```

## 重要な注意事項

- **重みの処理**: Monkey patching はクラスを置き換えるだけで、重みは置き換えません。パッチ適用後のクラスで重みのレイアウトが異なる場合、事前学習済み重みとの互換性を確保するために、[重みの変換](./weightconverter)を別途処理する必要があります。Monkey patch と重み変換マッピングを組み合わせる方法については、以下の[完全な例](#complete-example)を参照してください。

- **グローバルな効果**: `register_patch_mapping` で登録されたパッチは、登録後に読み込まれるすべてのモデルにグローバルに適用されます。完了時は、特にテスト、ノートブック、長時間実行されるアプリケーションでは、必ず `clear_patch_mapping` を使用してクリーンアップしてください。

- **クラスの検証**: API は、置換クラスが `nn.Module` のサブクラスであることを自動的に検証します。無効なクラスを渡すと、明確なエラーメッセージが表示されます。

- **スレッドセーフ性**: すべてのパッチ操作はスレッドセーフです。複数のスレッドから安全にパッチの登録、解除、適用を行うことができます。

- **マッチングの動作**: 完全一致のクラス名を使用する場合、モデルのソースコードに記述されている元のクラス名と完全に一致する必要があります（大文字と小文字を区別します）。正規表現パターンを使用する場合、`re.search()` を用いてクラス名と照合されます。

## トラブルシューティング

### パッチが適用されません

**クラス名またはパターンを確認**: マッピング内のクラス名またはパターンが正しいことを確認してください:

```python
# For exact names - must match exactly (case-sensitive)
register_patch_mapping(mapping={"LlamaAttention": CustomAttention})

# For patterns - use valid regex
register_patch_mapping(mapping={".*Attention": CustomAttention})
```

**登録の確認**: `get_patch_mapping`を使用して、マッピングが登録されていることを確認します:

```python
print(get_patch_mapping())
# Shows all registered mappings: {'LlamaAttention': <class 'CustomAttention'>, '.*MLP': <class 'CustomMLP'>}
```

**モデルのソースを確認**: モデルのソース内で正確なクラス名を見つけます:

```python
from transformers.models.llama import modeling_llama
print(dir(modeling_llama))  # Look for the class name
```

### パッチが正常に動作していることをどのように確認すればよいですか?

読み込まれたモデルを検査して、パッチを確認します:

```python
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-1B")

# Check the type of a specific module
print(type(model.model.layers[0].self_attn))  # Should show your custom class

# Or iterate through all modules
for name, module in model.named_modules():
    if 'attention' in name.lower():
        print(f"{name}: {type(module)}")
```

### 重みの形状が一致しないエラー

パッチを適用したクラスの重みの形状が異なる場合は、重みの変換を登録してください。

```python
from transformers.conversion_mapping import register_checkpoint_conversion_mapping, WeightConverter
from transformers.monkey_patching import register_patch_mapping

register_patch_mapping(
    mapping={
        "LlamaAttention": LlamaFusedAttention,
    }
)

register_checkpoint_conversion_mapping(
    model_type_or_class_name="llama",
    mapping=[
        WeightConverter(
            source_patterns=["q_proj", "k_proj", "v_proj"],
            target_patterns=["qkv_proj"],
            operations=[
                Concatenate(dim=0),
            ],
        )
    ],
    overwrite=True,
)
```

### パッチの整理

他のコードに影響を与えないように、作業が完了したら必ずパッチをクリーンアップしてください。

```python
from transformers.monkey_patching import register_patch_mapping, clear_patch_mapping

try:
    register_patch_mapping(mapping={"LlamaAttention": CustomAttention})
    model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
    # ... use model ...
finally:
    clear_patch_mapping()  # Always clean up
```

## 完全な例

Mixture-of-Expertsモデル(`qwen2_moe`)のエキスパートとアテンションモジュールの両方を、最適化と量子化の互換性のために再構成する方法を示す包括的な例です。この例では、以下をデモンス

1. 同じインターフェースを維持するカスタム置換クラスの作成
2. 複数のコンポーネントに対するモンキーパッチの登録
3. 新しい構造における重みの変換の処理

```python
from typing import Unpack

import torch
import torch.nn as nn

from transformers import AutoModelForCausalLM, Concatenate, WeightConverter
from transformers.activations import ACT2FN
from transformers.cache_utils import Cache
from transformers.conversion_mapping import register_checkpoint_conversion_mapping
from transformers.integrations.sdpa_attention import sdpa_attention_forward
from transformers.models.qwen2_moe.modeling_qwen2_moe import apply_rotary_pos_emb
from transformers.monkey_patching import register_patch_mapping
from transformers.utils.generic import TransformersKwargs

class MoeMLP(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.config = config
        self.num_experts = config.num_experts
        self.hidden_size = config.hidden_size
        self.intermediate_size = config.moe_intermediate_size
        self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
        self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
        self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
        self.act_fn = ACT2FN[config.hidden_act]

    def forward(self, x):
        down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
        return down_proj

# Adapted from the original Qwen2MoeExperts
class ModuleListExperts(nn.ModuleList):
    def __init__(self, config):
        super().__init__()
        self.config = config
        self.num_experts = config.num_experts
        for _ in range(self.num_experts):
            self.append(MoeMLP(config))

    def forward(
        self, hidden_states: torch.Tensor, top_k_index: torch.Tensor, top_k_weights: torch.Tensor
    ) -> torch.Tensor:
        final_hidden_states = torch.zeros_like(hidden_states)
        with torch.no_grad():
            expert_mask = torch.nn.functional.one_hot(top_k_index, num_classes=self.num_experts)
            expert_mask = expert_mask.permute(2, 1, 0)

        for expert_idx in range(self.num_experts):
            top_k_pos, token_idx = torch.where(expert_mask[expert_idx])
            current_state = hidden_states[token_idx]
            current_hidden_states = self[expert_idx](current_state)
            current_hidden_states = current_hidden_states * top_k_weights[token_idx, top_k_pos, None]
            final_hidden_states.index_add_(0, token_idx, current_hidden_states.to(final_hidden_states.dtype))
        return final_hidden_states

# Adapted from the original Qwen2MoeAttention
class FusedQKVAttention(nn.Module):
    def __init__(self, config, layer_idx: int):
        super().__init__()
        self.config = config
        self.layer_idx = layer_idx
        self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
        self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
        self.scaling = self.head_dim**-0.5
        self.attention_dropout = config.attention_dropout
        self.is_causal = True

        self.qkv_proj = nn.Linear(config.hidden_size, 3 * config.num_attention_heads * self.head_dim, bias=True)
        self.o_proj = nn.Linear(config.num_attention_heads * self.head_dim, config.hidden_size, bias=False)

        if self.config.layer_types[layer_idx] == "sliding_attention":
            self.sliding_window = config.sliding_window

    def forward(
        self,
        hidden_states: torch.Tensor,
        position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
        attention_mask: torch.Tensor | None = None,
        past_key_values: Cache | None = None,
        **kwargs: Unpack[TransformersKwargs],
    ) -> tuple[torch.Tensor, torch.Tensor]:
        input_shape = hidden_states.shape[:-1]
        hidden_shape = (*input_shape, -1, self.head_dim)

        query_states, key_states, value_states = self.qkv_proj(hidden_states).chunk(3, dim=-1)

        query_states = query_states.view(hidden_shape).transpose(1, 2)
        key_states = key_states.view(hidden_shape).transpose(1, 2)
        value_states = value_states.view(hidden_shape).transpose(1, 2)

        cos, sin = position_embeddings
        query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)

        if past_key_values is not None:
            key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)

        attn_output, attn_weights = sdpa_attention_forward(
            self,
            query_states,
            key_states,
            value_states,
            attention_mask,
            dropout=0.0 if not self.training else self.attention_dropout,
            scaling=self.scaling,
            **kwargs,
        )

        attn_output = attn_output.reshape(*input_shape, -1).contiguous()
        attn_output = self.o_proj(attn_output)
        return attn_output, attn_weights

# Registering monkey patches for the new attention and experts modules.
register_patch_mapping(
    mapping={
        "Qwen2MoeExperts": ModuleListExperts,
        "Qwen2MoeAttention": FusedQKVAttention,
    }
)

# Registering weight conversion mappings adapted for the new modules. This registration will:
# - Override the original conversion mapping for qwen2_moe which concatenated the experts into a single parameter format.
# - Concatenate the q_proj, k_proj, v_proj weights/biases into a single qkv_proj weight/bias for the new fused attention module.
register_checkpoint_conversion_mapping(
    model_type_or_class_name="qwen2_moe",
    mapping=[
        WeightConverter(
            source_patterns=["q_proj", "k_proj", "v_proj"],
            target_patterns=["qkv_proj"],
            operations=[Concatenate(dim=0)],
        ),
    ],
    overwrite=True,
)

model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-MoE-A2.7B")
```

## MoEエキスパートルーティングの記録と再生

RLHF などの Mixture-of-Experts トレーニングワークフローでは、生成中に各トークンがどのエキスパートにルーティングされたかを記録し、その正確なルーティングを別のトレーニングフォワードパスで再現する必要があります。この処理は、既存のモンキーパッチングと出力キャプチャの仕組みを用いてエンドツーエンドで構築でき、モデリングファイルの変更は不要です。

このパターンは3つの要素で構成されています:

1. 必要に応じてインスタンス属性から強制エキスパートインデックスを読み取ることができる、**再生可能なルーターのサブクラス**です。
2. **コンテキストマネージャー**で、フォワードパスの前にすべてのルーターでこれらの属性を設定し、その後にクリアします。
3. モデルの出力キャプチャレジストリ内のエントリであり、`output_<name>=True` を設定すると、インデックスが標準的な `@capture_outputs` パスを通じて公開されます。

```python
from contextlib import contextmanager

import torch
import torch.nn.functional as F

from transformers import Qwen3MoeConfig, Qwen3MoeForCausalLM
from transformers.models.qwen3_moe.modeling_qwen3_moe import Qwen3MoeTopKRouter
from transformers.monkey_patching import apply_patches, register_patch_mapping
from transformers.utils.output_capturing import _CAN_RECORD_REGISTRY, OutputRecorder

class ReplayableQwen3MoeTopKRouter(Qwen3MoeTopKRouter):
    _forced_indices: torch.Tensor | None = None

    def forward(self, hidden_states):
        hidden_states = hidden_states.reshape(-1, self.hidden_dim)
        router_logits = F.linear(hidden_states, self.weight)
        router_logits = F.softmax(router_logits, dtype=torch.float, dim=-1)

        if self._forced_indices is not None:
            router_indices = self._forced_indices.to(router_logits.device).long()
            # Megatron-style replay: preserve expert path, recompute current scores
            router_top_value = router_logits.gather(-1, router_indices)
        else:
            router_top_value, router_indices = torch.topk(router_logits, self.top_k, dim=-1)

        if self.norm_topk_prob:
            router_top_value = router_top_value / router_top_value.sum(dim=-1, keepdim=True)
        return router_logits, router_top_value.to(router_logits.dtype), router_indices

@contextmanager
def replay_moe_routing(model, selected_experts_per_layer):
    routers = [m for m in model.modules() if isinstance(m, ReplayableQwen3MoeTopKRouter)]
    if len(routers) != len(selected_experts_per_layer):
        raise ValueError(f"Got {len(routers)} routers but {len(selected_experts_per_layer)} tensors")
    for r, t in zip(routers, selected_experts_per_layer):
        r._forced_indices = t
    try:
        yield
    finally:
        for r in routers:
            r._forced_indices = None

# Swap the router class and construct the model
register_patch_mapping({"Qwen3MoeTopKRouter": ReplayableQwen3MoeTopKRouter})
with apply_patches():
    model = Qwen3MoeForCausalLM(Qwen3MoeConfig(...)).eval()

# Expose `output_selected_experts=True` on the base model by adding an OutputRecorder
# at runtime. Index 2 of the router's tuple output is the expert indices.
inner = model.model
existing = _CAN_RECORD_REGISTRY.get(str(inner.__class__), {}) or {}
_CAN_RECORD_REGISTRY[str(inner.__class__)] = {
    **existing,
    "selected_experts": OutputRecorder(ReplayableQwen3MoeTopKRouter, index=2),
}

# Record
captured = inner(input_ids=input_ids, output_selected_experts=True)
selected_experts = captured.selected_experts  # tuple of (num_tokens, top_k) LongTensors

# Replay — same expert path regardless of current router weights
with replay_moe_routing(inner, list(selected_experts)):
    outputs = inner(input_ids=input_ids)
```

Replay は正確なエキスパートのインデックスを保持し、現在のルーターの重みを用いてルーティングスコアを再計算します。これにより、エキスパートの選択が固定されたまま、ライブのパラメータを介して勾配が伝播します。これは、Megatron スタイルの MoE 学習で使用される最小限の replay 契約です。

### vLLM との相互運用

vLLMの`enable_return_routed_experts=True`により、`CompletionOutput.routed_experts`は`(seq_len, num_layers, top_k)`の`np.int32`配列として設定されます。このパターンが期待するレイヤーごとのリストに変換するには、次の1つの式を使用します。

```python
selected = [
    torch.from_numpy(routed_experts[:, layer, :].copy()).long()
    for layer in range(routed_experts.shape[1])
]
with replay_moe_routing(model, selected):
    loss = model(input_ids=input_ids, labels=labels).loss
```

同じ手順は他の MoE ファミリにも適用できます。ファミリの `*TopKRouter` をサブクラス化し、元の戻り値の契約（通常は `(router_logits, router_scores, router_indices)`）に合わせ、パッチを登録します。正確なシグネチャについては、各モデルのルータークラスを参照してください。

## API リファレンス[[transformers.monkey_patching.register_patch_mapping]]

#### transformers.monkey_patching.register_patch_mapping[[transformers.monkey_patching.register_patch_mapping]]

```python
transformers.monkey_patching.register_patch_mapping(mapping: dict, overwrite: bool = False)
```

[ソース](https://github.com/huggingface/transformers/blob/main/src/transformers/monkey_patching.py#L85)

**パラメータ:**

mapping (`Dict[str, type[nn.Module]]`) : 元のクラス名（または正規表現パターン）から置換クラスへのマッピング。サポート: - 完全一致するクラス名: `"Qwen2MoeExperts"` → `CustomExperts` - 正規表現パターン: `".*Attention"` は `LlamaAttention`、`MistralAttention` などに一致します。また、`"^Llama\d+Attention$"` は `Llama2Attention`、`Llama3Attention` などに一致します。 完全一致はパターンよりも優先されます。パターンは `re.search()` を使用して一致させるため、アンカー（先頭は `^`、末尾は `$`）を使用しない限り、クラス名のどこでも一致します。

overwrite (`bool`、*任意*、デフォルトは`False`) : すでに登録されているクラス名の既存のマッピングを上書きするかどうか。

`from_pretrained`、`from_config`、または`apply_patches`コンテキストマネージャー内でモデルを作成する際に、自動パッチ適用を有効にするために、パッチのマッピングを登録します。

これを使用して、モデルの読み込み時に自動的に適用されるクラスの置換を登録します。これは、量子化ライブラリとの互換性、構造の最適化、アーキテクチャの実験に役立ちます。このマッピングはグローバルであり、複数の呼び出しによって拡張され、完全にクリアすることもできます。

例:
```python
from transformers import AutoModelForCausalLM
from transformers.monkey_patching import register_patch_mapping

# Define custom expert implementation
class SequentialExperts(nn.Module):
    ...

# Register exact class name
register_patch_mapping(
    mapping={"Qwen2MoeExperts": SequentialExperts}
)

# Register with regex pattern to match multiple classes
register_patch_mapping(
    mapping={".*Attention": CustomAttention}  # Matches LlamaAttention, MistralAttention, etc.
)

# Match specific model versions
register_patch_mapping(
    mapping={"^Llama\d+Attention$": CustomLlamaAttention}  # Matches Llama2Attention, Llama3Attention
)

# The patch will be automatically applied during loading
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-1B")
```

注: 重みの変換には、代わりに`~transformers.register_checkpoint_conversion_mapping`を使用してください。

#### transformers.monkey_patching.unregister_patch_mapping[[transformers.monkey_patching.unregister_patch_mapping]]

```python
transformers.monkey_patching.unregister_patch_mapping(keys: list)
```

[ソース](https://github.com/huggingface/transformers/blob/main/src/transformers/monkey_patching.py#L158)

**パラメータ:**

keys (`List[str]`) : パッチマッピングから削除するマッピングキー（クラス名または正規表現パターン）のリスト（例: `["Qwen2MoeExperts"]` または `[".*Attention"]`）。

自動パッチングを無効にするには、パッチマッピングの登録を解除します。

これにより、指定されたマッピングがグローバルレジストリから削除され、モデルの読み込み時に適用されなくなります。登録時に使用された正確な名前またはパターンを指定する必要があります。

例:
```python
from transformers import AutoModelForCausalLM
from transformers.monkey_patching import register_patch_mapping, unregister_patch_mapping

# Register a patch
register_patch_mapping(
    mapping={"Qwen2MoeExperts": CustomExperts}
)

# Unregister the patch
unregister_patch_mapping(["Qwen2MoeExperts"])

# The patch will no longer be applied during loading
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-MoE-A2.7B")
```

#### transformers.monkey_patching.clear_patch_mapping[[transformers.monkey_patching.clear_patch_mapping]]

```python
transformers.monkey_patching.clear_patch_mapping()
```

[ソース](https://github.com/huggingface/transformers/blob/main/src/transformers/monkey_patching.py#L209)

登録済みのすべてのパッチマッピングをクリアします。

これにより、グローバルレジストリに登録されているすべてのマッピングが削除されます。

例:
```python
from transformers.monkey_patching import register_patch_mapping, clear_patch_mapping

# Register some patches
register_patch_mapping(
    mapping={"Qwen2MoeExperts": CustomExperts}
)

# Clear all patches
clear_patch_mapping()
```

#### transformers.monkey_patching.get_patch_mapping[[transformers.monkey_patching.get_patch_mapping]]

```python
transformers.monkey_patching.get_patch_mapping()
```

[ソース](https://github.com/huggingface/transformers/blob/main/src/transformers/monkey_patching.py#L198)

**戻り値:** `Dict[str, type[nn.Module]]`

クラス名またはパターンを置換先のクラスにマッピングする辞書。

登録済みのパッチマッピングをすべて取得します。

#### transformers.monkey_patching.apply_patches[[transformers.monkey_patching.apply_patches]]

```python
transformers.monkey_patching.apply_patches()
```

[ソース](https://github.com/huggingface/transformers/blob/main/src/transformers/monkey_patching.py#L233)

コードブロック内で登録済みのモンキーパッチを適用するためのコンテキストマネージャー。

この処理は、ブロックの実行中に元のクラスを一時的に登録済みの代替クラスに置き換え、実行後に元のクラスを復元します。

例:
```python
from transformers import Qwen2MoeModel, Qwen2MoeConfig
from transformers.monkey_patching import register_patch_mapping, apply_patches

# Register a patch
register_patch_mapping(
    mapping={"Qwen2MoeExperts": CustomExperts}
)

# Apply patches within the context
with apply_patches():
    # The model will use CustomExperts instead of Qwen2MoeExperts
    model = Qwen2MoeModel(Qwen2MoeConfig())

# Outside the context, original classes are restored
# The model will use Qwen2MoeExperts again
model = Qwen2MoeModel(Qwen2MoeConfig())
```

