Skip to content

vllm.model_executor.models.transformers.fx_utils

fx tracing and forward-source rewriting for the Transformers backend fusers.

A small engine, independent of any particular pattern: trace a module's forward with torch.fx (tolerating a partial graph), inspect the resulting nodes, and rewrite the forward's source (AST) so only matched calls change while the rest stays live Python. fusion.py builds the concrete fusion patterns on top.

Functions:

  • compile_forward

    Compile funcdef in fn's module so tracebacks point at the source.

  • find_node

    The first node in graph matching predicate, or None.

  • forward_input_count

    The number of tensor inputs cls.forward declares, excluding self and

  • innermost_block

    The innermost statement list containing node, and the index within.

  • is_fn

    Is node <target>().

  • is_linear

    Is node nn.Linear.__call__().

  • is_method

    Is node .<name>().

  • is_op

    Is node torch.<name>(), F.<name>(), operator.<name>(), or Tensor.<name>().

  • peel

    Strip dtype-cast wrappers (.to(...), .float(), .type_as(...)).

  • recover_forward

    Parse the source of cls.forward, ready for rewriting.

  • replace_expr

    Replace the expression old (by identity) with new within module.

  • single_self_call

    The unique self.<name>(arg) call in funcdef.

  • trace

    Trace module.forward, returning the partial graph on failure.

_AllLeafTracer

Bases: Tracer

Tracer that treats every submodule as a leaf.

Each child stays one call_module node, so matching sees the module's own forward structure (activations aren't decomposed into e.g. sigmoid * x). iter traces through the leading shape unpacks (see _infer_len); anything else untraceable ends the trace early and the partial graph is matched.

Source code in vllm/model_executor/models/transformers/fx_utils.py
class _AllLeafTracer(fx.Tracer):
    """Tracer that treats every submodule as a leaf.

    Each child stays one `call_module` node, so matching sees the module's own
    forward structure (activations aren't decomposed into e.g. `sigmoid * x`).
    `iter` traces through the leading shape unpacks (see `_infer_len`); anything
    else untraceable ends the trace early and the partial graph is matched.
    """

    def is_leaf_module(self, m: nn.Module, module_qualified_name: str) -> bool:
        return True

    def proxy(self, node: fx.Node) -> fx.Proxy:
        return _SizedProxy(node, self)

    def iter(self, obj: fx.Proxy):
        length = _infer_len(obj.node)
        if length is None:
            return super().iter(obj)
        return iter([obj[i] for i in range(length)])

_SizedProxy

Bases: Proxy

Proxy whose len is inferred from the graph (see _infer_len).

Source code in vllm/model_executor/models/transformers/fx_utils.py
class _SizedProxy(fx.Proxy):
    """Proxy whose `len` is inferred from the graph (see `_infer_len`)."""

    def __len__(self) -> int:
        length = _infer_len(self.node)
        if length is None:
            return super().__len__()
        return length

_infer_len(node)

Concrete length of a proxy's value, inferred from its node chain.

Lets tracing pass through the shape unpacks and *-splats (e.g. (*input_shape, -1, head_dim)) that precede the patterns in HF attention.

Source code in vllm/model_executor/models/transformers/fx_utils.py
def _infer_len(node: fx.Node) -> int | None:
    """Concrete length of a proxy's value, inferred from its node chain.

    Lets tracing pass through the shape unpacks and `*`-splats (e.g.
    `(*input_shape, -1, head_dim)`) that precede the patterns in HF attention.
    """
    # `x.shape` has the rank of `x`, when known
    if (
        node.op == "call_function"
        and node.target is getattr
        and node.args[1] == "shape"
        and (rank := _rank(node.args[0])) is not None
    ):
        return rank
    # Slices of known-length values
    if node.op == "call_function" and node.target is operator.getitem:
        src_len = _infer_len(node.args[0])
        index = node.args[1]
        if src_len is not None and isinstance(index, slice):
            return len(range(*index.indices(src_len)))
    return None

_rank(node)

The tensor rank of node's value, if known.

Source code in vllm/model_executor/models/transformers/fx_utils.py
def _rank(node: fx.Node) -> int | None:
    """The tensor rank of `node`'s value, if known."""
    # vLLM always feeds the model [1, seq_len, hidden_size] hidden states
    if node.op == "placeholder" and node.target == "hidden_states":
        return 3
    return None

compile_forward(funcdef, fn)

Compile funcdef in fn's module so tracebacks point at the source.

Source code in vllm/model_executor/models/transformers/fx_utils.py
def compile_forward(funcdef: ast.FunctionDef, fn: Callable) -> Callable:
    """Compile `funcdef` in `fn`'s module so tracebacks point at the source."""
    module = ast.Module(body=[funcdef], type_ignores=[])
    ast.fix_missing_locations(module)
    ast.increment_lineno(module, fn.__code__.co_firstlineno - 1)
    code = compile(module, fn.__code__.co_filename, "exec")
    namespace: dict = {}
    exec(code, fn.__globals__, namespace)
    return namespace[funcdef.name]

find_node(graph, predicate)

The first node in graph matching predicate, or None.

Source code in vllm/model_executor/models/transformers/fx_utils.py
def find_node(graph: fx.Graph, predicate: Callable[[fx.Node], bool]) -> fx.Node | None:
    """The first node in `graph` matching `predicate`, or `None`."""
    return next((n for n in graph.nodes if predicate(n)), None)

forward_input_count(cls)

The number of tensor inputs cls.forward declares, excluding self and any *args/**kwargs. Read from the signature, so it is independent of whether the trace completes (unlike counting placeholders).

Source code in vllm/model_executor/models/transformers/fx_utils.py
def forward_input_count(cls: type[nn.Module]) -> int:
    """The number of tensor inputs `cls.forward` declares, excluding `self` and
    any `*args`/`**kwargs`. Read from the signature, so it is independent of
    whether the trace completes (unlike counting placeholders)."""
    try:
        params = list(inspect.signature(cls.forward).parameters.values())[1:]
    except (ValueError, TypeError):
        return 1  # uninspectable: assume a single input and let matching decide
    fixed = (
        inspect.Parameter.POSITIONAL_ONLY,
        inspect.Parameter.POSITIONAL_OR_KEYWORD,
        inspect.Parameter.KEYWORD_ONLY,
    )
    return sum(1 for p in params if p.kind in fixed)

innermost_block(block, node)

The innermost statement list containing node, and the index within.

Source code in vllm/model_executor/models/transformers/fx_utils.py
def innermost_block(
    block: list[ast.stmt], node: ast.AST
) -> tuple[list[ast.stmt], int] | None:
    """The innermost statement list containing `node`, and the index within."""
    for index, stmt in enumerate(block):
        if not any(child is node for child in ast.walk(stmt)):
            continue
        child_blocks = [
            getattr(stmt, fld, None) for fld in ("body", "orelse", "finalbody")
        ]
        child_blocks += [h.body for h in getattr(stmt, "handlers", [])]
        child_blocks += [c.body for c in getattr(stmt, "cases", [])]
        for child_block in child_blocks:
            if (
                isinstance(child_block, list)
                and child_block
                and (found := innermost_block(child_block, node)) is not None
            ):
                return found
        return block, index
    return None

is_fn(node, target)

Is node <target>().

Source code in vllm/model_executor/models/transformers/fx_utils.py
def is_fn(node: object, target: Callable) -> bool:
    """Is node `<target>()`."""
    return (
        isinstance(node, fx.Node)
        and node.op == "call_function"
        and node.target is target
    )

is_linear(node, module)

Is node nn.Linear.__call__().

Source code in vllm/model_executor/models/transformers/fx_utils.py
def is_linear(node: fx.Node, module: nn.Module) -> bool:
    """Is node `nn.Linear.__call__()`."""
    return node.op == "call_module" and isinstance(
        module.get_submodule(node.target), nn.Linear
    )

is_method(node, name)

Is node .<name>().

Source code in vllm/model_executor/models/transformers/fx_utils.py
def is_method(node: object, name: str) -> bool:
    """Is node `.<name>()`."""
    return (
        isinstance(node, fx.Node) and node.op == "call_method" and node.target == name
    )

is_op(node, name)

Is node torch.<name>(), F.<name>(), operator.<name>(), or Tensor.<name>().

Source code in vllm/model_executor/models/transformers/fx_utils.py
def is_op(node: object, name: str) -> bool:
    """
    Is node `torch.<name>()`, `F.<name>()`, `operator.<name>()`, or `Tensor.<name>()`.
    """
    return any(
        is_fn(node, getattr(module, name, None)) for module in (torch, F, operator)
    ) or (hasattr(torch.Tensor, name) and is_method(node, name))

peel(node)

Strip dtype-cast wrappers (.to(...), .float(), .type_as(...)).

Source code in vllm/model_executor/models/transformers/fx_utils.py
def peel(node: object) -> object:
    """Strip dtype-cast wrappers (`.to(...)`, `.float()`, `.type_as(...)`)."""
    while (
        isinstance(node, fx.Node)
        and node.op == "call_method"
        and node.target in _DTYPE_CASTS
    ):
        node = node.args[0]
    return node

recover_forward(cls)

Parse the source of cls.forward, ready for rewriting.

Source code in vllm/model_executor/models/transformers/fx_utils.py
def recover_forward(cls: type[nn.Module]) -> tuple[ast.FunctionDef, Callable]:
    """Parse the source of `cls.forward`, ready for rewriting."""
    fn = inspect.unwrap(cls.forward)
    if fn.__code__.co_freevars:
        raise ValueError("forward is a closure")
    tree = ast.parse(textwrap.dedent(inspect.getsource(fn)))
    funcdef = tree.body[0]
    if not isinstance(funcdef, ast.FunctionDef):
        raise ValueError("source is not a plain function definition")
    # `fn` is already unwrapped; don't re-apply its decorators
    funcdef.decorator_list.clear()
    # Annotations may not evaluate outside the defining module (e.g. with
    # postponed evaluation); they're not needed at runtime
    funcdef.returns = None
    args = funcdef.args
    for arg in (
        *args.posonlyargs,
        *args.args,
        *args.kwonlyargs,
        *filter(None, (args.vararg, args.kwarg)),
    ):
        arg.annotation = None
    # Recompiling outside the class body would break name mangling
    for node in ast.walk(funcdef):
        name = getattr(node, "attr", None) or getattr(node, "id", None)
        if name and name.startswith("__") and not name.endswith("__"):
            raise ValueError(f"{name} would be name mangled")
    return funcdef, fn

replace_expr(module, old, new)

Replace the expression old (by identity) with new within module.

Source code in vllm/model_executor/models/transformers/fx_utils.py
def replace_expr(module: ast.AST, old: ast.expr, new: ast.expr) -> None:
    """Replace the expression `old` (by identity) with `new` within `module`."""

    class _Replacer(ast.NodeTransformer):
        def visit(self, node: ast.AST) -> ast.AST:
            if node is old:
                return new
            return super().generic_visit(node)

    _Replacer().visit(module)

single_self_call(funcdef, name)

The unique self.<name>(arg) call in funcdef.

Raises unless name appears exactly once, as such a call, so the source rewrite agrees with the fx match.

Source code in vllm/model_executor/models/transformers/fx_utils.py
def single_self_call(funcdef: ast.FunctionDef, name: str) -> ast.Call:
    """The unique `self.<name>(arg)` call in `funcdef`.

    Raises unless `name` appears exactly once, as such a call, so the source
    rewrite agrees with the fx match.
    """
    uses = [
        node
        for node in ast.walk(funcdef)
        if isinstance(node, ast.Attribute) and node.attr == name
    ]
    if len(uses) != 1:
        raise ValueError(f"{name} is referenced {len(uses)} times")
    calls = [
        node
        for node in ast.walk(funcdef)
        if isinstance(node, ast.Call)
        and node.func is uses[0]
        and len(node.args) == 1
        and not isinstance(node.args[0], ast.Starred)
        and not node.keywords
    ]
    if (
        len(calls) != 1
        or not isinstance(uses[0].value, ast.Name)
        or uses[0].value.id != "self"
    ):
        raise ValueError(f"{name} is not a single-argument call on self")
    return calls[0]

trace(module)

Trace module.forward, returning the partial graph on failure.

The graph is only evidence for matching, and the patterns sit at the top of their forwards, so a trace that fails partway can still be matched.

Source code in vllm/model_executor/models/transformers/fx_utils.py
def trace(module: nn.Module) -> fx.Graph | None:
    """Trace `module.forward`, returning the partial graph on failure.

    The graph is only evidence for matching, and the patterns sit at the top of
    their forwards, so a trace that fails partway can still be matched."""
    tracer = _AllLeafTracer()
    try:
        return tracer.trace(module)
    except Exception as exc:
        logger.debug("Could not fully trace %s: %s", type(module), exc)
        return getattr(tracer, "graph", None)