---
title: "ClikaRT::nn::MoE"
sidebar_label: "MoE"
description: "Dense mixture-of-experts module: a router picks top-k experts per token, each expert runs its gated FFN, and the outputs combine under the router weights."
---

<!-- Generated by tools/doxygen2mdx from Doxygen XML. Do not edit. -->

<span class="api-kind api-kind--class">class</span>

**Header:** `ClikaRT/nn/moe.h`  
**Inherits:** [`ClikaRT::nn::Module`](./Module.md)

Dense mixture-of-experts module: a router picks top-k experts per token, each expert runs its gated FFN, and the outputs combine under the router weights.

The expert weights live as stacked `[E, ...]` tensors; the optional trailing [`MoeOptions`](./MoeOptions.md) carries the routing variants (grouped routing, sparse-mixer, the clamped-SwiGLU knobs, per-expert combine scales). The module owns its weights: construct with `make(...)`, or declare shapes and bind a checkpoint via [`load_state_dict`](./Module.md#load_state_dict). The first forward packs the weight (or [`LoadOptions::pack_on_load`](./LoadOptions.md#pack_on_load) packs it at the end of the load); the pack is the one resident copy, and [`named_parameters()`](./Module.md#named_parameters) / [`state_dict()`](./Module.md#state_dict) read the weight back from it; `to(dtype)` restores, casts, and re-packs on the next forward.

```cpp
auto moe = ClikaRT::nn::MoE::make(router_w, gate_up_w, down_w, opts);
auto y   = moe->forward(x);
```

## Static member functions

### make() {#make}

<div class="api-signature">

`static` `std::shared_ptr<MoE>` **`make`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::int64_t` `num_experts`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::int64_t` `hidden_size`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::int64_t` `intermediate_size`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::int64_t` `top_k`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`bool` `gate_up_bias` `=` `false`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`bool` `down_bias` `=` `false`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`DataType`](../../index.md#DataType) `dtype` `=` [`DataType::Float32`](../../index.md#DataType),<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Device`](../Device.md) `device` `=` [`Device::cpu`](../Device.md#cpu)`()`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`MoeOptions`](./MoeOptions.md) `options` `=` `{}`<br />
)

</div>

Defaults: `gate_up_bias` / `down_bias` = `false` (no bias slots), [`dtype`](../dtype/index.md) = `Float32`, [`device`](../device-namespace/index.md) = CPU, `options` = [`MoeOptions`](./MoeOptions.md)`{}` (each field's own default; see the struct). The routing variants ride the optional trailing `options`; the four counts are the whole required surface.

**Throws**

- `ClikaRT::Error`: as stated above.

<div class="api-declared">

Declared in `ClikaRT/nn/moe.h`, line 114

</div>

## Member functions

### \~MoE() {#MoE}

<div class="api-signature">

**`~MoE`**() `override`

</div>

Releases the module's packed expert weights.

<div class="api-declared">

Declared in `ClikaRT/nn/moe.h`, line 126

</div>

### set\_weights() {#set_weights}

<div class="api-signature">

`void` **`set_weights`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Tensor`](../Tensor.md) `gate_up_experts`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Tensor`](../Tensor.md) `down_experts`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`OptionalTensor`](../../index.md#OptionalTensor) `gate_up_bias` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`OptionalTensor`](../../index.md#OptionalTensor) `down_bias` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`OptionalTensor`](../../index.md#OptionalTensor) `gate_experts` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`OptionalTensor`](../../index.md#OptionalTensor) `gate_bias` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`OptionalTensor`](../../index.md#OptionalTensor) `e_score_correction_bias` `=` `{}`<br />
)

</div>

Bind the declared slots positionally: `gate_up_experts` `[E, F·I, H]` and `down_experts` `[E, H, I]` (required), the declared per-expert biases, the Unfused `gate_experts` `[E, I, H]` (+ `gate_bias`), and the aux-free selection bias `[E]` (bindable even when not declared; it is routing data, not a declared parameter). The declared placement wins; shapes must match the declaration. Re-binding after a pack drops the pack; the next [`forward`](./MoE.md#forward) re-packs. Raises [`ClikaRT::Error`](../Error.md) on a geometry mismatch or a bias without its declared slot.

<div class="api-declared">

Declared in `ClikaRT/nn/moe.h`, line 140

</div>

### to\_impl(StreamOrDevice) {#to_impl}

<div class="api-signature">

`virtual` [`Result`](../Result.md)`<void>` **`to_impl`**([`StreamOrDevice`](../StreamOrDevice.md) `where`) `override`

</div>

Move to a placement (the pack rebuilds on the target) or cast to a dtype (the raw experts restore from the pack, cast, and re-pack on the next forward).

<div class="api-declared">

Declared in `ClikaRT/nn/moe.h`, line 155

</div>

### to\_impl(DataType) {#to_impl-2}

<div class="api-signature">

`virtual` [`Result`](../Result.md)`<void>` **`to_impl`**([`DataType`](../../index.md#DataType) `dtype`) `override`

</div>

<div class="api-declared">

Declared in `ClikaRT/nn/moe.h`, line 156

</div>

### forward() {#forward}

<div class="api-signature">

[`Tensor`](../Tensor.md) **`forward`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Tensor`](../Tensor.md) `x`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Tensor`](../Tensor.md) `router_logits`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`OptionalTensor`](../../index.md#OptionalTensor) `shared_output` `=` `{}`<br />
) `const`

</div>

One fused [MoE](./MoE.md) step: `x` `[T, H]` (packed/ragged rows are native, no cu\_seqlens; [MoE](./MoE.md) is per-token) and the caller-computed `router_logits` `[T, E]` → `[T, H]`. The first call packs (once, thread-safe); every later call reuses the pack. Raises [`ClikaRT::Error`](../Error.md) on a shape/dtype mismatch or a still-fake slot. An optional `shared_output` (the shared-expert branch's `[T, H]` at `x`'s dtype, EXACT shape) folds into the routed combine (the fused routed+shared epilogue; no separate add pass).

<div class="api-declared">

Declared in `ClikaRT/nn/moe.h`, line 168

</div>

## Protected member functions

### initialize\_impl() {#initialize_impl}

<div class="api-signature">

`virtual` [`Result`](../Result.md)`<void>` **`initialize_impl`**() `override`

</div>

The pack hook ([`Module::initialize_impl`](./Module.md#initialize_impl)): packs now (idempotent, thread-safe). Every declared slot must hold a real (loaded) tensor; a still-fake slot is a clean error. After the pack the expert weight slots read back from the pack, the single resident copy; biases stay bound.

<div class="api-declared">

Declared in `ClikaRT/nn/moe.h`, line 185

</div>
