It appears Qwen3 is using YaRN for long contexts, like Qwen 2.5:
The maximum context length in pre-training for Qwen3 models is 32,768 tokens. It can be extended to 131,072 tokens with RoPE scaling techniques. We have validated the performance with YaRN.
https://github.com/QwenLM/Qwen3/blob/main/docs/source/inference/transformers.md#enabling-long-context
Editing the config file for the desired context is... less than ideal for users.
However, they mention this little nugget:
Transformers implements static YaRN, which means the scaling factor remains constant regardless of input length, potentially impacting performance on shorter texts. We advise adding the rope_scaling configuration only when processing long contexts is required. It is also recommended to modify the factor as needed. For example, if the typical context length for your application is 65,536 tokens, it would be better to set factor as 2.0
The default factor is 4.0, and currently the exllama code will stick to that if the 'default' long context configuration is present:
|
def _rope_params_yarn(self): |
|
rs = self.rope_settings |
|
assert rs.max_position_embeddings is not None, \ |
|
"YaRN scaling requires explicit max_position_embeddings" |
|
base = rs.rope_theta |
|
dim = int(rs.head_dim * rs.partial_rotary_factor) |
|
factor = rs.rope_scaling.get("factor") |
|
attn_factor = rs.rope_scaling.get("attention_factor", 0.1 * math.log(factor) + 1.0) |
|
beta_fast = rs.rope_scaling.get("beta_fast", 32) |
|
beta_slow = rs.rope_scaling.get("beta_slow", 1) |
|
def find_correction_dim(num_rotations): |
|
return (dim * math.log(rs.max_position_embeddings / (num_rotations * 2 * math.pi))) / (2 * math.log(base)) |
|
def find_correction_range(low_rot, high_rot): |
|
_low = math.floor(find_correction_dim(low_rot)) |
|
_high = math.ceil(find_correction_dim(high_rot)) |
|
return max(_low, 0), min(_high, dim - 1) |
|
def linear_ramp_factor(_min, _max, _dim): |
|
if _min == _max: |
|
_max += 0.001 |
|
linear_func = (torch.arange(_dim, dtype = torch.float32, device = self.device) - _min) / (_max - _min) |
|
ramp_func = torch.clamp(linear_func, 0, 1) |
|
return ramp_func |
|
pos_freqs = base ** (torch.arange(0, dim, 2, device = self.device).float() / dim) |
|
inv_freq_extrapolation = 1.0 / pos_freqs |
|
inv_freq_interpolation = 1.0 / (factor * pos_freqs) |
|
low, high = find_correction_range(beta_fast, beta_slow) |
|
inv_freq_extrapolation_factor = 1 - linear_ramp_factor(low, high, dim // 2).float() |
|
inv_freq = inv_freq_interpolation * (1 - inv_freq_extrapolation_factor) |
|
inv_freq += inv_freq_extrapolation * inv_freq_extrapolation_factor |
|
return inv_freq, attn_factor |
But it appears a more optimal thing to do is ignore the rope_scaling factor, and statically set it with (context length of the loaded model)/original_max_position_embeddings, which would be 2.0 for 64K, 3.0 for 96K, and so on.
This is trivially easy to implement, but the question is if exllamav3 should set it automatically like that. I say it should, as most users aren't going to dig into how YaRN scaling works and match the scaling factor to their specified context length.
...But what would be even more optimal would be to dynamically set the scaling factor per request. For instance, if a 64K request was recieved, set it to 2.0. A 96K one, 3.0. So each request gets the optimal factor.
Even better would be to disable YaRN entirely for requests under 32K.
...Is this practical to do? I seem to remember it not being practical in exllamav2.
It appears Qwen3 is using YaRN for long contexts, like Qwen 2.5:
https://github.com/QwenLM/Qwen3/blob/main/docs/source/inference/transformers.md#enabling-long-context
Editing the config file for the desired context is... less than ideal for users.
However, they mention this little nugget:
The default factor is 4.0, and currently the exllama code will stick to that if the 'default' long context configuration is present:
exllamav3/exllamav3/util/rope.py
Lines 130 to 159 in 0ff9fd2
But it appears a more optimal thing to do is ignore the rope_scaling factor, and statically set it with
(context length of the loaded model)/original_max_position_embeddings, which would be 2.0 for 64K, 3.0 for 96K, and so on.This is trivially easy to implement, but the question is if exllamav3 should set it automatically like that. I say it should, as most users aren't going to dig into how YaRN scaling works and match the scaling factor to their specified context length.
...But what would be even more optimal would be to dynamically set the scaling factor per request. For instance, if a 64K request was recieved, set it to 2.0. A 96K one, 3.0. So each request gets the optimal factor.
Even better would be to disable YaRN entirely for requests under 32K.
...Is this practical to do? I seem to remember it not being practical in exllamav2.