Skip to content

Conversation

@Giuseppe5
Copy link
Collaborator

@Giuseppe5 Giuseppe5 commented Jan 24, 2026

Reason for this PR

Initial support for vLLM export.

To do:

  • Check that input/output quantization work as intended
  • Test multiple quantizers
  • Improve quantizers interface
  • Support for rotation (and smoothquant?)

Changes Made in this PR

We are re-using the inference quantizers also for vLLM.
This is still fake-quantization style, but should be faster than plain torch execution, even in eager mode.

The same template could be easily extended to support real quantization, torch.compile, etc. etc.

Testing Summary

TBD

@Giuseppe5 Giuseppe5 force-pushed the vllm_export branch 2 times, most recently from 4e3e36a to 7d4a78c Compare January 27, 2026 15:04
torch>=2.4
tqdm
transformers[sentencepiece]<5.0
vllm
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like vLLM should be an optional dependency.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can do it in a similar way to what we did for lighteval/lm_eval

Copy link
Collaborator Author

@Giuseppe5 Giuseppe5 Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm leaving it for now so that test run and I can see what other things I'm breaking in the process, but I'll remove before this PR is merged

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with doing it similarly as for lighteval/lm_eval

tensor_shape_list = list(tensor_shape)
x = padding_to_multiple(x, group_dim, group_size)

tensor_shape = x.shape
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to do simplify this logic? A function like torch.unflatten might be useful.

return ["brevitas_config.json"]

def get_quant_method(self, layer: torch.nn.Module,
prefix: str) -> Optional["QuantizeMethodBase"]:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The __init__ uses typing from Python 3.10+, e.g. ignored_layers: list[str] | None = None, while, in this method, the legacy typing is used Optional["QuantizeMethodBase"]. Can we use Python 3.10+ typing for consistency with vLLM.

@dataclass
class QuantConfigBrevitas(QuantizationConfig):

def __init__(self, ignored_layers: list[str] | None = None, config: str | None = None):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this config: str | None = None the correct typing?

self.config = config

@classmethod
def from_config(cls, config: dict[str, Any]) -> "QuantConfigTcast":
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def from_config(cls, config: dict[str, Any]) -> "QuantConfigTcast":
def from_config(cls, config: dict[str, Any]) -> "QuantConfigBrevitas":

prefix: str) -> Optional["QuantizeMethodBase"]:
if isinstance(layer, RowParallelLinear) or isinstance(
layer, MergedColumnParallelLinear) or isinstance(layer, QKVParallelLinear):
if self.ignored_layers and is_layer_skipped(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the check self.ignored_layers needed? Maybe

Suggested change
if self.ignored_layers and is_layer_skipped(
if is_layer_skipped(

would suffice, from what I see in other classes, e.g. Fp8Config.

@nickfraser nickfraser mentioned this pull request Feb 9, 2026
34 tasks
@nickfraser nickfraser added the next release PRs which should be merged for the next release label Feb 9, 2026
'IntInferencetHandler': IntInferencetHandler,}


class QuantLinear(LinearMethodBase):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adapting this class to better match the structure of examples such as vllm.model_executor.layers.quantization.fp_quant

raise Exception(f"{impl_type} not recognized.")


def solve_float_to_int_enum_from_impl(impl_type):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function introduces an extra maintainability burden, i.e. every time one adds a new FloatToIntImplType, two updates need to be done. However, this pattern matching could be done programatically by iterating over the possible values FloatToIntImplType, resolving them to classes and then selecting the value of the enumeration corresponding to the given class (which would amount to generating the dictionary FLOAT_TO_INT_IMPL_TO_ENUM programatically).

raise RuntimeError(f"{impl_type} not recognized.")


def solve_restrict_value_enum_from_impl(impl):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

'SolveDtypeDeviceFromTrackedParameterList',
'SolveRestrictScaleSign']

# FLOAT_TO_INT_ENUM_TO_IMPL = {FloatToIntImplType.ROUND: RoundSte,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove


return o

def state_dict(self, destination=None, prefix='', keep_vars=False):
Copy link
Collaborator

@pablomlago pablomlago Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change in how state_dict works is specifically required for vLLM, but I don't see a reason why it should be done always. Is it possible to do this override only in the vLLM export flow?

out = self.layer(*kwargs.values())
return out

def state_dict(self, destination=None, prefix='', keep_vars=False):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as below

x = x.reshape(shape)
return x

# def compute_scale(self, x, group_dim):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

next release PRs which should be merged for the next release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants