Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 100 additions & 20 deletions tensorrt_llm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,34 +99,114 @@ def _setup_vendored_triton_kernels():

_setup_vendored_triton_kernels()

# The package's public surface is loaded lazily (PEP 562): importing
# tensorrt_llm no longer executes the whole product tree (previously ~99% of
# product modules ran at import time through the eager chain below). Accessing
# any public name (tensorrt_llm.LLM, tensorrt_llm.models, ...) imports just
# what that name needs. The TYPE_CHECKING block keeps the original imports
# visible to static tooling.
import importlib
from typing import TYPE_CHECKING

# Need to import torch before tensorrt_llm library, otherwise some shared binary files
# cannot be found for the public PyTorch, raising errors like:
# ImportError: libc10.so: cannot open shared object file: No such file or directory
import torch # noqa

import tensorrt_llm._torch.models as torch_models
import tensorrt_llm.math_utils as math_utils
import tensorrt_llm.models as models
import tensorrt_llm.quantization as quantization
import tensorrt_llm.runtime as runtime
import tensorrt_llm.tools as tools

from ._common import _init
from ._mnnvl_utils import MnnvlMemory, MnnvlMoe, MoEAlltoallInfo
from ._utils import (default_gpus_per_node, local_mpi_rank, local_mpi_size,
mpi_barrier, mpi_comm, mpi_rank, mpi_world_size,
set_mpi_comm, str_dtype_to_torch)
from .disaggregated_params import DisaggregatedParams
from .llmapi import LLM, AsyncLLM, MultimodalEncoder
from .llmapi.llm_args import LlmArgs, TorchLlmArgs
from .logger import logger
from .mapping import Mapping
from .models.automodel import AutoConfig, AutoModelForCausalLM
from .sampling_params import SamplingParams
from .version import __version__
from .visual_gen import (ExtraParamSchema, VisualGen, VisualGenArgs,
VisualGenMetrics, VisualGenOutput, VisualGenParams,
VisualGenResult)

if TYPE_CHECKING:
import tensorrt_llm._torch.models as torch_models
import tensorrt_llm.math_utils as math_utils
import tensorrt_llm.models as models
import tensorrt_llm.quantization as quantization
import tensorrt_llm.runtime as runtime
import tensorrt_llm.tools as tools

from ._mnnvl_utils import MnnvlMemory, MnnvlMoe, MoEAlltoallInfo
from ._utils import (default_gpus_per_node, local_mpi_rank, local_mpi_size,
mpi_barrier, mpi_comm, mpi_rank, mpi_world_size,
set_mpi_comm, str_dtype_to_torch)
from .disaggregated_params import DisaggregatedParams
from .llmapi import LLM, AsyncLLM, KvCacheConfig, MultimodalEncoder
from .llmapi.llm_args import LlmArgs, TorchLlmArgs
from .mapping import Mapping
from .models.automodel import AutoConfig, AutoModelForCausalLM
from .sampling_params import SamplingParams
from .visual_gen import (ExtraParamSchema, VisualGen, VisualGenArgs,
VisualGenMetrics, VisualGenOutput, VisualGenParams,
VisualGenResult)

# Public name -> (source module, attribute); attribute None = the module itself.
_LAZY_ATTRS = {
'torch_models': ('tensorrt_llm._torch.models', None),
'math_utils': ('tensorrt_llm.math_utils', None),
'models': ('tensorrt_llm.models', None),
'quantization': ('tensorrt_llm.quantization', None),
'runtime': ('tensorrt_llm.runtime', None),
'tools': ('tensorrt_llm.tools', None),
'MnnvlMemory': ('tensorrt_llm._mnnvl_utils', 'MnnvlMemory'),
'MnnvlMoe': ('tensorrt_llm._mnnvl_utils', 'MnnvlMoe'),
'MoEAlltoallInfo': ('tensorrt_llm._mnnvl_utils', 'MoEAlltoallInfo'),
'default_gpus_per_node': ('tensorrt_llm._utils', 'default_gpus_per_node'),
'local_mpi_rank': ('tensorrt_llm._utils', 'local_mpi_rank'),
'local_mpi_size': ('tensorrt_llm._utils', 'local_mpi_size'),
'mpi_barrier': ('tensorrt_llm._utils', 'mpi_barrier'),
'mpi_comm': ('tensorrt_llm._utils', 'mpi_comm'),
'mpi_rank': ('tensorrt_llm._utils', 'mpi_rank'),
'mpi_world_size': ('tensorrt_llm._utils', 'mpi_world_size'),
'set_mpi_comm': ('tensorrt_llm._utils', 'set_mpi_comm'),
'str_dtype_to_torch': ('tensorrt_llm._utils', 'str_dtype_to_torch'),
'DisaggregatedParams':
('tensorrt_llm.disaggregated_params', 'DisaggregatedParams'),
'LLM': ('tensorrt_llm.llmapi', 'LLM'),
'AsyncLLM': ('tensorrt_llm.llmapi', 'AsyncLLM'),
'MultimodalEncoder': ('tensorrt_llm.llmapi', 'MultimodalEncoder'),
'KvCacheConfig': ('tensorrt_llm.llmapi', 'KvCacheConfig'),
'LlmArgs': ('tensorrt_llm.llmapi.llm_args', 'LlmArgs'),
'TorchLlmArgs': ('tensorrt_llm.llmapi.llm_args', 'TorchLlmArgs'),
'Mapping': ('tensorrt_llm.mapping', 'Mapping'),
'AutoConfig': ('tensorrt_llm.models.automodel', 'AutoConfig'),
'AutoModelForCausalLM':
('tensorrt_llm.models.automodel', 'AutoModelForCausalLM'),
'SamplingParams': ('tensorrt_llm.sampling_params', 'SamplingParams'),
'ExtraParamSchema': ('tensorrt_llm.visual_gen', 'ExtraParamSchema'),
'VisualGen': ('tensorrt_llm.visual_gen', 'VisualGen'),
'VisualGenArgs': ('tensorrt_llm.visual_gen', 'VisualGenArgs'),
'VisualGenMetrics': ('tensorrt_llm.visual_gen', 'VisualGenMetrics'),
'VisualGenOutput': ('tensorrt_llm.visual_gen', 'VisualGenOutput'),
'VisualGenParams': ('tensorrt_llm.visual_gen', 'VisualGenParams'),
'VisualGenResult': ('tensorrt_llm.visual_gen', 'VisualGenResult'),
}


def __getattr__(name):
entry = _LAZY_ATTRS.get(name)
if entry is not None:
module_name, attr = entry
module = importlib.import_module(module_name)
value = module if attr is None else getattr(module, attr)
globals()[name] = value # cache: subsequent access skips __getattr__
return value
# Fall back to plain submodules (tensorrt_llm.functional, .profiler, ...)
# that used to be reachable as attributes via the eager import chain.
try:
return importlib.import_module(f'.{name}', __name__)
except ModuleNotFoundError as e:
# Only translate "no such submodule" into AttributeError. A
# ModuleNotFoundError raised *inside* an existing submodule (missing
# dependency) is a real error and must propagate unchanged.
if e.name != f'{__name__}.{name}':
raise
raise AttributeError(
f"module {__name__!r} has no attribute {name!r}") from None


def __dir__():
return sorted(set(__all__) | set(globals()) | set(_LAZY_ATTRS))


__all__ = [
'AutoConfig',
Expand Down
152 changes: 64 additions & 88 deletions tensorrt_llm/_torch/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,40 @@
import transformers
# SPDX-FileCopyrightText: Copyright (c) 2022-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
"""PyTorch-backend model zoo, loaded lazily.

Importing this package no longer imports every ``modeling_*`` module (which
executes all model class bodies and their ``@register_auto_model`` decorators
at interpreter startup). Instead:

- attribute access (``models.LlamaForCausalLM`` or
``from tensorrt_llm._torch.models import LlamaForCausalLM``) imports just the
providing module, via PEP 562 ``__getattr__`` and ``MODEL_CLASS_TO_MODULE``;
- architecture-based resolution (``AutoModelForCausalLM``) imports on demand
via ``modeling_utils.get_registered_model_class`` and
``MODEL_ARCH_TO_MODULE``.
"""
import importlib

# Importing _torch.configs triggers AutoConfig registration for TRT-LLM-only
# model_types (deepseek_v32, kimi_k2, gemma4_unified) so AutoConfig /
# AutoTokenizer.from_pretrained work under transformers >= 5.5; see
# _torch/configs/__init__.py.
# AutoTokenizer.from_pretrained work under transformers >= 5.5; this must stay
# eager — see _torch/configs/__init__.py.
import tensorrt_llm._torch.configs # noqa: F401

from .modeling_afmoe import AfmoeForCausalLM
from ._arch_index import MODEL_CLASS_TO_MODULE
from .modeling_auto import AutoModelForCausalLM
from .modeling_bart import (BartForConditionalGeneration,
MBartForConditionalGeneration)
from .modeling_bert import BertForSequenceClassification
from .modeling_clip import CLIPVisionModel
from .modeling_cohere2 import Cohere2ForCausalLM
from .modeling_cosmos3 import Cosmos3Model
from .modeling_deepseekv3 import DeepseekV3ForCausalLM
from .modeling_deepseekv4 import DeepseekV4ForCausalLM
from .modeling_exaone4 import Exaone4ForCausalLM
from .modeling_exaone4_5 import Exaone4_5_ForConditionalGeneration
from .modeling_exaone_moe import ExaoneMoeForCausalLM
from .modeling_gemma3 import Gemma3ForCausalLM
from .modeling_gemma3vl import Gemma3VLM
from .modeling_gemma4 import Gemma4ForCausalLM
from .modeling_gemma4_unified import Gemma4UnifiedForConditionalGeneration
from .modeling_gemma4mm import Gemma4ForConditionalGeneration
from .modeling_glm import Glm4MoeForCausalLM
from .modeling_gpt_oss import GptOssForCausalLM
from .modeling_hunyuan_dense import HunYuanDenseV1ForCausalLM
from .modeling_hunyuan_moe import HunYuanMoEV1ForCausalLM
from .modeling_hyperclovax import HCXVisionForCausalLM
from .modeling_kimi_k25 import KimiK25ForConditionalGeneration
from .modeling_laguna import LagunaForCausalLM
from .modeling_llama import LlamaForCausalLM
from .modeling_llava_next import LlavaNextModel
from .modeling_minicpmv4_6 import MiniCPMV4_6Model
from .modeling_minimaxm2 import MiniMaxM2ForCausalLM
from .modeling_minimaxm3 import (MiniMaxM3ForCausalLM,
MiniMaxM3VLForConditionalGeneration)
from .modeling_mistral import Mistral3VLM, MistralForCausalLM
from .modeling_mixtral import MixtralForCausalLM
from .modeling_nemotron import NemotronForCausalLM
from .modeling_nemotron_h import NemotronHForCausalLM
from .modeling_nemotron_nano import NemotronH_Nano_VL_V2
from .modeling_nemotron_nas import NemotronNASForCausalLM
from .modeling_phi3 import Phi3ForCausalLM
from .modeling_phi4mm import Phi4MMForCausalLM
from .modeling_qwen import (Qwen2ForCausalLM, Qwen2ForProcessRewardModel,
Qwen2ForRewardModel)
from .modeling_qwen2vl import Qwen2_5_VLModel, Qwen2VLModel
from .modeling_qwen3 import Qwen3ForCausalLM
from .modeling_qwen3_5 import (Qwen3_5ForCausalLM, Qwen3_5MoeForCausalLM,
Qwen3_5MoeVLModel, Qwen3_5VLModel)
from .modeling_qwen3_moe import Qwen3MoeForCausalLM
from .modeling_qwen3_next import Qwen3NextForCausalLM
from .modeling_qwen3vl import Qwen3VLModel
from .modeling_qwen3vl_moe import Qwen3MoeVLModel
from .modeling_qwen_image_bench import QwenImageBenchModel
from .modeling_qwen_moe import Qwen2MoeForCausalLM
from .modeling_seedoss import SeedOssForCausalLM
from .modeling_siglip import SiglipVisionModel
from .modeling_starcoder2 import Starcoder2ForCausalLM
from .modeling_step3p7 import Step3p7ForCausalLM
from .modeling_step3p7vl import Step3p7VLForConditionalGeneration
from .modeling_t5 import T5ForConditionalGeneration
from .modeling_utils import get_model_architecture
from .modeling_vila import VilaModel
from .modeling_whisper import WhisperForConditionalGeneration

# Note: for better readiblity, this should have same order as imports above
__all__ = [
"AfmoeForCausalLM",
"AutoModelForCausalLM",
"BartForConditionalGeneration",
"BertForSequenceClassification",
"CLIPVisionModel",
"Cohere2ForCausalLM",
"Cosmos3Model",
"DeepseekV3ForCausalLM",
"DeepseekV4ForCausalLM",
"Exaone4ForCausalLM",
"Exaone4_5_ForConditionalGeneration",
"ExaoneMoeForCausalLM",
Expand All @@ -84,63 +43,80 @@
"Gemma4ForCausalLM",
"Gemma4ForConditionalGeneration",
"Gemma4UnifiedForConditionalGeneration",
"Glm4MoeForCausalLM",
"GptOssForCausalLM",
"HCXVisionForCausalLM",
"LagunaForCausalLM",
"HunYuanDenseV1ForCausalLM",
"HunYuanMoEV1ForCausalLM",
"KimiK25ForConditionalGeneration",
"LagunaForCausalLM",
"LlamaForCausalLM",
"LlavaNextModel",
"MBartForConditionalGeneration",
"MiniCPMV4_6Model",
"MiniMaxM2ForCausalLM",
"MiniMaxM3ForCausalLM",
"MiniMaxM3VLForConditionalGeneration",
"Mistral3VLM",
"MistralForCausalLM",
"MixtralForCausalLM",
"DeepseekV4ForCausalLM",
"NemotronH_Nano_VL_V2",
"MllamaForConditionalGeneration",
"NemotronForCausalLM",
"NemotronHForCausalLM",
"NemotronH_Nano_VL_V2",
"NemotronNASForCausalLM",
"Phi3ForCausalLM",
"Phi4MMForCausalLM",
"Qwen2ForCausalLM",
"Qwen2ForProcessRewardModel",
"Qwen2ForRewardModel",
"Qwen2MoeForCausalLM",
"SiglipVisionModel",
"Starcoder2ForCausalLM",
"T5ForConditionalGeneration",
"MBartForConditionalGeneration",
"get_model_architecture",
"VilaModel",
"Qwen2VLModel",
"Qwen2_5_VLModel",
"Qwen3ForCausalLM",
"Qwen3MoeForCausalLM",
"Qwen3MoeVLModel",
"Qwen3NextForCausalLM",
"Qwen3VLModel",
"Qwen3_5ForCausalLM",
"Qwen3_5MoeForCausalLM",
"QwenImageBenchModel",
"Qwen3_5MoeVLModel",
"Qwen3_5VLModel",
"Qwen3NextForCausalLM",
"Qwen3MoeVLModel",
"GptOssForCausalLM",
"QwenImageBenchModel",
"SeedOssForCausalLM",
"Glm4MoeForCausalLM",
"Qwen3VLModel",
"MiniMaxM2ForCausalLM",
"MiniMaxM3ForCausalLM",
"MiniMaxM3VLForConditionalGeneration",
"Cohere2ForCausalLM",
"SiglipVisionModel",
"Starcoder2ForCausalLM",
"Step3p7ForCausalLM",
"Step3p7VLForConditionalGeneration",
"T5ForConditionalGeneration",
"VilaModel",
"WhisperForConditionalGeneration",
"get_model_architecture",
]

if transformers.__version__ >= "4.45.1":
from .modeling_mllama import MllamaForConditionalGeneration # noqa

__all__.append("MllamaForConditionalGeneration")
else:
print(
f"Failed to import MllamaForConditionalGeneration as transformers.__version__ {transformers.__version__} < 4.45.1"
)
def __getattr__(name: str):
module_name = MODEL_CLASS_TO_MODULE.get(name)
if module_name is None:
# Also resolve bare submodule access (models.modeling_llama) so callers
# that relied on the previously-eager submodule attributes keep working.
if name.startswith("modeling_"):
try:
return importlib.import_module(f".{name}", __name__)
except ModuleNotFoundError as e:
# Only translate "no such submodule" into AttributeError; a
# ModuleNotFoundError raised *inside* an existing submodule
# (missing dependency) must propagate unchanged.
if e.name != f"{__name__}.{name}":
raise
raise AttributeError(
f"module {__name__!r} has no attribute {name!r}") from None
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
module = importlib.import_module(f".{module_name}", __name__)
attr = getattr(module, name)
globals()[name] = attr # cache: subsequent access skips __getattr__
return attr
Comment on lines +98 to +118

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Find attribute access on tensorrt_llm._torch.models submodules that are not modeling_*.
set -uo pipefail

# Direct attribute access via an imported package alias.
rg -nP -C3 --type=py '\bmodels\.(?!modeling_)[a-z_]+\b' -g '!**/models/**'

# Submodules that exist under the package.
fd -t d -d 1 . tensorrt_llm/_torch/models
fd -t f -d 1 -e py . tensorrt_llm/_torch/models

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

#!/bin/bash
set -u

printf '%s\n' '--- package file list ---'
git ls-files tensorrt_llm/_torch/models | sed -n '1,160p'

printf '%s\n' '--- __init__.py structure ---'
ast-grep outline tensorrt_llm/_torch/models/__init__.py --view expanded 2>/dev/null || true

printf '%s\n' '--- __init__.py relevant sections ---'
sed -n '1,135p' tensorrt_llm/_torch/models/__init__.py

printf '%s\n' '--- non-modeling attribute references outside the package ---'
rg -nP -C3 --type=py '\bmodels\.(?!modeling_)[a-z_]+\b' -g '!tensorrt_llm/_torch/models/**' . || true

printf '%s\n' '--- package submodule candidates ---'
python3 - <<'PY'
from pathlib import Path

root = Path("tensorrt_llm/_torch/models")
for path in sorted(root.iterdir()):
    if path.name == "__pycache__":
        continue
    print(path)
PY

Repository: NVIDIA/TensorRT-LLM

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -u

printf '%s\n' '--- package file list ---'
git ls-files tensorrt_llm/_torch/models | sed -n '1,160p'

printf '%s\n' '--- __init__.py structure ---'
ast-grep outline tensorrt_llm/_torch/models/__init__.py --view expanded 2>/dev/null || true

printf '%s\n' '--- __init__.py relevant sections ---'
sed -n '1,135p' tensorrt_llm/_torch/models/__init__.py

printf '%s\n' '--- non-modeling attribute references outside the package ---'
rg -nP -C3 --type=py '\bmodels\.(?!modeling_)[a-z_]+\b' -g '!tensorrt_llm/_torch/models/**' . || true

printf '%s\n' '--- package submodule candidates ---'
python3 - <<'PY'
from pathlib import Path

root = Path("tensorrt_llm/_torch/models")
for path in sorted(root.iterdir()):
    if path.name != "__pycache__":
        print(path)
PY

Repository: NVIDIA/TensorRT-LLM

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -u

printf '%s\n' '--- focused initial log ---'
sed -n '1,220p' /tmp/coderabbit-shell-logs/shell-output-EFTFt9

printf '%s\n' '--- current package initializer ---'
cat -n tensorrt_llm/_torch/models/__init__.py

printf '%s\n' '--- parent initializer, if available ---'
git show HEAD^:tensorrt_llm/_torch/models/__init__.py 2>/dev/null | cat -n | sed -n '1,180p' || true

printf '%s\n' '--- focused diff for initializer ---'
git diff HEAD^ -- tensorrt_llm/_torch/models/__init__.py | sed -n '1,240p'

printf '%s\n' '--- immediate package children ---'
python3 - <<'PY'
from pathlib import Path

root = Path("tensorrt_llm/_torch/models")
for path in sorted(root.iterdir()):
    if path.name == "__pycache__":
        continue
    if path.is_dir() and (path / "__init__.py").exists():
        print(f"package:{path.name}")
    elif path.is_file() and path.suffix == ".py":
        print(f"module:{path.stem}")
PY

Repository: NVIDIA/TensorRT-LLM

Length of output: 20943


🏁 Script executed:

#!/bin/bash
set -u

python3 - <<'PY'
from __future__ import annotations

import ast
from pathlib import Path

ROOT = Path("tensorrt_llm/_torch/models")
PACKAGE = "tensorrt_llm._torch.models"


def relative_import_name(node: ast.ImportFrom, current: str) -> str | None:
    if node.level == 0:
        return node.module
    parts = current.split(".")
    base = parts[: len(parts) - node.level]
    if node.module:
        base.append(node.module)
    return ".".join(base)


def imported_local_modules(path: Path, module_name: str) -> set[str]:
    tree = ast.parse(path.read_text(), filename=str(path))
    result: set[str] = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                if alias.name == PACKAGE or alias.name.startswith(PACKAGE + "."):
                    result.add(alias.name)
        elif isinstance(node, ast.ImportFrom):
            name = relative_import_name(node, module_name)
            if name and (name == PACKAGE or name.startswith(PACKAGE + ".")):
                result.add(name)
            elif name == PACKAGE:
                for alias in node.names:
                    if alias.name != "*":
                        result.add(f"{PACKAGE}.{alias.name}")
    return result


print("--- current initializer imports ---")
for name in sorted(imported_local_modules(ROOT / "__init__.py", PACKAGE)):
    print(name)

print("--- transitive local imports from initializer dependencies ---")
module_paths: dict[str, Path] = {PACKAGE: ROOT / "__init__.py"}
for path in ROOT.rglob("*.py"):
    relative = path.relative_to(ROOT).with_suffix("")
    suffix = ".".join(relative.parts)
    module_paths[f"{PACKAGE}.{suffix}"] = path

seen = {PACKAGE}
queue = [PACKAGE]
edges: dict[str, set[str]] = {}
while queue:
    current = queue.pop()
    path = module_paths.get(current)
    if path is None:
        continue
    deps = imported_local_modules(path, current)
    edges[current] = deps
    for dep in deps:
        if dep in module_paths and dep not in seen:
            seen.add(dep)
            queue.append(dep)

for current in sorted(edges):
    for dep in sorted(edges[current]):
        print(f"{current} -> {dep}")

print("--- direct child modules and __getattr__ coverage ---")
children: list[str] = []
for path in ROOT.iterdir():
    if path.name == "__pycache__":
        continue
    if path.is_file() and path.suffix == ".py":
        children.append(path.stem)
    elif path.is_dir() and (path / "__init__.py").exists():
        children.append(path.name)

init_text = (ROOT / "__init__.py").read_text()
for child in sorted(children):
    if child.startswith("modeling_"):
        coverage = "prefix fallback"
    else:
        coverage = "not covered by prefix fallback"
    print(f"{child}: {coverage}")

print("--- package-alias attribute access outside the package ---")
hits: list[tuple[str, int, str]] = []
for path in Path(".").rglob("*.py"):
    if ROOT in path.parents or path == ROOT / "__init__.py":
        continue
    try:
        tree = ast.parse(path.read_text(), filename=str(path))
    except (OSError, SyntaxError):
        continue

    aliases: set[str] = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                if alias.name == PACKAGE:
                    aliases.add(alias.asname or alias.name.rsplit(".", 1)[-1])
        elif isinstance(node, ast.ImportFrom):
            if node.module == "tensorrt_llm._torch" and any(
                alias.name == "models" for alias in node.names
            ):
                for alias in node.names:
                    if alias.name == "models":
                        aliases.add(alias.asname or alias.name)

    for node in ast.walk(tree):
        if isinstance(node, ast.Attribute) and node.value.__class__ is ast.Name:
            if node.value.id in aliases:
                hits.append((str(path), node.lineno, node.attr))

for path, line, attr in sorted(hits):
    print(f"{path}:{line}: models.{attr}")

print("--- git state and initializer history ---")
PY

git status --short
git log --oneline -8 -- tensorrt_llm/_torch/models/__init__.py

Repository: NVIDIA/TensorRT-LLM

Length of output: 3803


🏁 Script executed:

#!/bin/bash
set -u

python3 - <<'PY'
from __future__ import annotations

import ast
from pathlib import Path

ROOT = Path("tensorrt_llm/_torch/models")
PACKAGE = "tensorrt_llm._torch.models"


def relative_import_name(node: ast.ImportFrom, current: str) -> str | None:
    if node.level == 0:
        return node.module
    parts = current.split(".")
    base = parts[: len(parts) - node.level]
    if node.module:
        base.append(node.module)
    return ".".join(base)


def imported_local_modules(path: Path, module_name: str) -> set[str]:
    tree = ast.parse(path.read_text(), filename=str(path))
    result: set[str] = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                if alias.name == PACKAGE or alias.name.startswith(PACKAGE + "."):
                    result.add(alias.name)
        elif isinstance(node, ast.ImportFrom):
            name = relative_import_name(node, module_name)
            if name and (name == PACKAGE or name.startswith(PACKAGE + ".")):
                result.add(name)
            elif name == PACKAGE:
                for alias in node.names:
                    if alias.name != "*":
                        result.add(f"{PACKAGE}.{alias.name}")
    return result


print("--- current initializer imports ---")
for name in sorted(imported_local_modules(ROOT / "__init__.py", PACKAGE)):
    print(name)

print("--- transitive local imports from initializer dependencies ---")
module_paths: dict[str, Path] = {PACKAGE: ROOT / "__init__.py"}
for path in ROOT.rglob("*.py"):
    relative = path.relative_to(ROOT).with_suffix("")
    suffix = ".".join(relative.parts)
    module_paths[f"{PACKAGE}.{suffix}"] = path

seen = {PACKAGE}
queue = [PACKAGE]
edges: dict[str, set[str]] = {}
while queue:
    current = queue.pop()
    path = module_paths.get(current)
    if path is None:
        continue
    deps = imported_local_modules(path, current)
    edges[current] = deps
    for dep in deps:
        if dep in module_paths and dep not in seen:
            seen.add(dep)
            queue.append(dep)

for current in sorted(edges):
    for dep in sorted(edges[current]):
        print(f"{current} -> {dep}")

print("--- direct child modules and __getattr__ coverage ---")
children: list[str] = []
for path in ROOT.iterdir():
    if path.name == "__pycache__":
        continue
    if path.is_file() and path.suffix == ".py":
        children.append(path.stem)
    elif path.is_dir() and (path / "__init__.py").exists():
        children.append(path.name)

for child in sorted(children):
    coverage = (
        "prefix fallback"
        if child.startswith("modeling_")
        else "not covered by prefix fallback"
    )
    print(f"{child}: {coverage}")

print("--- package-alias attribute access outside the package ---")
hits: list[tuple[str, int, str]] = []
for path in Path(".").rglob("*.py"):
    if ROOT in path.parents or path == ROOT / "__init__.py":
        continue
    try:
        tree = ast.parse(path.read_text(), filename=str(path))
    except (OSError, SyntaxError):
        continue

    aliases: set[str] = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                if alias.name == PACKAGE:
                    aliases.add(alias.asname or alias.name.rsplit(".", 1)[-1])
        elif isinstance(node, ast.ImportFrom):
            if node.module == "tensorrt_llm._torch" and any(
                alias.name == "models" for alias in node.names
            ):
                for alias in node.names:
                    if alias.name == "models":
                        aliases.add(alias.asname or alias.name)

    for node in ast.walk(tree):
        if isinstance(node, ast.Attribute) and isinstance(node.value, ast.Name):
            if node.value.id in aliases:
                hits.append((str(path), node.lineno, node.attr))

for path, line, attr in sorted(hits):
    print(f"{path}:{line}: models.{attr}")

print("--- git state and initializer history ---")
PY

git status --short
git log --oneline -8 -- tensorrt_llm/_torch/models/__init__.py

Repository: NVIDIA/TensorRT-LLM

Length of output: 3803


🏁 Script executed:

#!/bin/bash
set -u

printf '%s\n' '--- old eager initializer ---'
git show 22833f245^:tensorrt_llm/_torch/models/__init__.py | cat -n | sed -n '1,220p'

printf '%s\n' '--- lazy initializer commit diff ---'
git diff 22833f245^ 22833f245 -- tensorrt_llm/_torch/models/__init__.py | sed -n '1,280p'

printf '%s\n' '--- corrected static import and compatibility verifier ---'
python3 - <<'PY'
from __future__ import annotations

import ast
from pathlib import Path

ROOT = Path("tensorrt_llm/_torch/models")
PACKAGE = "tensorrt_llm._torch.models"


def relative_import_name(node: ast.ImportFrom, current: str) -> str | None:
    if node.level == 0:
        return node.module
    parts = current.split(".")
    # level=1 means the current package; level=2 means its parent.
    base = parts[: len(parts) - node.level + 1]
    if node.module:
        base.append(node.module)
    return ".".join(base)


def imports_from(path: Path, module_name: str) -> set[str]:
    tree = ast.parse(path.read_text(), filename=str(path))
    result: set[str] = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                if alias.name == PACKAGE or alias.name.startswith(PACKAGE + "."):
                    result.add(alias.name)
        elif isinstance(node, ast.ImportFrom):
            name = relative_import_name(node, module_name)
            if name and (name == PACKAGE or name.startswith(PACKAGE + ".")):
                if node.module is None:
                    for alias in node.names:
                        if alias.name != "*":
                            result.add(f"{name}.{alias.name}")
                else:
                    result.add(name)
    return result


module_paths: dict[str, Path] = {PACKAGE: ROOT / "__init__.py"}
for path in ROOT.rglob("*.py"):
    relative = path.relative_to(ROOT).with_suffix("")
    module_paths[f"{PACKAGE}.{".".join(relative.parts)}"] = path

print("--- direct imports from current initializer ---")
for name in sorted(imports_from(ROOT / "__init__.py", PACKAGE)):
    print(name)

print("--- transitive imports reachable from current initializer ---")
seen = {PACKAGE}
queue = [PACKAGE]
edges: dict[str, set[str]] = {}
while queue:
    current = queue.pop()
    path = module_paths.get(current)
    if path is None:
        continue
    deps = imports_from(path, current)
    edges[current] = deps
    for dep in deps:
        if dep in module_paths and dep not in seen:
            seen.add(dep)
            queue.append(dep)

for current in sorted(edges):
    for dep in sorted(edges[current]):
        print(f"{current} -> {dep}")

print("--- old eager direct imports that are now absent ---")
old_text = Path("/tmp/old_models_init.py")
PY

Repository: NVIDIA/TensorRT-LLM

Length of output: 15615


🏁 Script executed:

#!/bin/bash
set -u

printf '%s\n' '--- old eager initializer ---'
git show 22833f245^:tensorrt_llm/_torch/models/__init__.py | cat -n | sed -n '1,220p'

printf '%s\n' '--- lazy initializer commit diff ---'
git diff 22833f245^ 22833f245 -- tensorrt_llm/_torch/models/__init__.py | sed -n '1,280p'

printf '%s\n' '--- corrected static import and compatibility verifier ---'
python3 - <<'PY'
from __future__ import annotations

import ast
from pathlib import Path

ROOT = Path("tensorrt_llm/_torch/models")
PACKAGE = "tensorrt_llm._torch.models"


def relative_import_name(node: ast.ImportFrom, current: str) -> str | None:
    if node.level == 0:
        return node.module
    parts = current.split(".")
    base = parts[: len(parts) - node.level + 1]
    if node.module:
        base.append(node.module)
    return ".".join(base)


def imports_from(path: Path, module_name: str) -> set[str]:
    tree = ast.parse(path.read_text(), filename=str(path))
    result: set[str] = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                if alias.name == PACKAGE or alias.name.startswith(PACKAGE + "."):
                    result.add(alias.name)
        elif isinstance(node, ast.ImportFrom):
            name = relative_import_name(node, module_name)
            if name and (name == PACKAGE or name.startswith(PACKAGE + ".")):
                if node.module is None:
                    for alias in node.names:
                        if alias.name != "*":
                            result.add(f"{name}.{alias.name}")
                else:
                    result.add(name)
    return result


module_paths: dict[str, Path] = {PACKAGE: ROOT / "__init__.py"}
for path in ROOT.rglob("*.py"):
    relative = path.relative_to(ROOT).with_suffix("")
    suffix = ".".join(relative.parts)
    module_paths[f"{PACKAGE}.{suffix}"] = path

print("--- direct imports from current initializer ---")
for name in sorted(imports_from(ROOT / "__init__.py", PACKAGE)):
    print(name)

print("--- transitive imports reachable from current initializer ---")
seen = {PACKAGE}
queue = [PACKAGE]
edges: dict[str, set[str]] = {}
while queue:
    current = queue.pop()
    path = module_paths.get(current)
    if path is None:
        continue
    deps = imports_from(path, current)
    edges[current] = deps
    for dep in deps:
        if dep in module_paths and dep not in seen:
            seen.add(dep)
            queue.append(dep)

for current in sorted(edges):
    for dep in sorted(edges[current]):
        print(f"{current} -> {dep}")

print("--- direct child modules not covered by the current fallback ---")
for path in sorted(ROOT.iterdir()):
    if path.name == "__pycache__":
        continue
    if path.is_file() and path.suffix == ".py":
        child = path.stem
    elif path.is_dir() and (path / "__init__.py").exists():
        child = path.name
    else:
        continue
    if not child.startswith("modeling_"):
        print(child)
PY

Repository: NVIDIA/TensorRT-LLM

Length of output: 17586


🏁 Script executed:

#!/bin/bash
set -u

python3 - <<'PY'
from __future__ import annotations

import ast
import subprocess
from pathlib import Path

ROOT = Path("tensorrt_llm/_torch/models")
PACKAGE = "tensorrt_llm._torch.models"


def module_name_for(path: Path) -> str:
    relative = path.relative_to(ROOT)
    if relative.name == "__init__.py":
        parts = relative.parent.parts
    else:
        parts = relative.with_suffix("").parts
    return PACKAGE + (("." + ".".join(parts)) if parts else "")


module_paths = {
    module_name_for(path): path
    for path in ROOT.rglob("*.py")
}


def package_of(module_name: str) -> str:
    if module_name in module_paths and module_paths[module_name].name == "__init__.py":
        return module_name
    return module_name.rsplit(".", 1)[0]


def relative_base(node: ast.ImportFrom, current: str) -> str | None:
    if node.level == 0:
        return node.module
    base = package_of(current)
    for _ in range(node.level - 1):
        base = base.rsplit(".", 1)[0]
    if node.module:
        return f"{base}.{node.module}"
    return base


def imports_from(path: Path, current: str) -> set[str]:
    tree = ast.parse(path.read_text(), filename=str(path))
    result: set[str] = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                if alias.name == PACKAGE or alias.name.startswith(PACKAGE + "."):
                    result.add(alias.name)
        elif isinstance(node, ast.ImportFrom):
            base = relative_base(node, current)
            if not base or not (
                base == PACKAGE or base.startswith(PACKAGE + ".")
            ):
                continue
            if node.module is not None:
                result.add(base)
            else:
                for alias in node.names:
                    if alias.name != "*":
                        result.add(f"{base}.{alias.name}")
    return result


def reachable(root_text: str, root_name: str) -> set[str]:
    root_path = Path("/tmp/initializer_for_scan.py")
    root_path.write_text(root_text)
    # The temporary root is parsed only; repository files are not modified.
    seen = {root_name}
    queue = [root_name]
    while queue:
        current = queue.pop()
        path = root_path if current == root_name else module_paths.get(current)
        if path is None:
            continue
        deps = imports_from(path, current)
        for dep in deps:
            if dep in module_paths and dep not in seen:
                seen.add(dep)
                queue.append(dep)
    root_path.unlink()
    return seen


current_text = Path(ROOT / "__init__.py").read_text()
old_text = subprocess.check_output(
    [
        "git",
        "show",
        "22833f245^:tensorrt_llm/_torch/models/__init__.py",
    ],
    text=True,
)

old_loaded = reachable(old_text, PACKAGE)
current_loaded = reachable(current_text, PACKAGE)


def direct_children(loaded: set[str]) -> set[str]:
    children = set()
    prefix = PACKAGE + "."
    for name in loaded:
        if name.startswith(prefix):
            children.add(name[len(prefix):].split(".", 1)[0])
    return children


old_children = direct_children(old_loaded)
current_children = direct_children(current_loaded)

print("--- direct child attributes loaded by old eager initializer ---")
for name in sorted(old_children):
    print(name)

print("--- direct child attributes loaded by current initializer ---")
for name in sorted(current_children):
    print(name)

print("--- old direct child attributes absent after current initialization ---")
for name in sorted(old_children - current_children):
    print(name)

print("--- absent old attributes not covered by current modeling_* fallback ---")
for name in sorted(old_children - current_children):
    if not name.startswith("modeling_"):
        print(name)
PY

printf '%s\n' '--- modeling_utils checkpoint import ---'
rg -n -C3 'checkpoints|hf_parameter_utils|multimodal_encoder_graph|dspark' \
  tensorrt_llm/_torch/models/modeling_utils.py \
  tensorrt_llm/_torch/models/modeling_*.py \
  tensorrt_llm/_torch/models/_arch_index.py | sed -n '1,220p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 20403


🏁 Script executed:

#!/bin/bash
set -u

python3 - <<'PY'
from __future__ import annotations

import ast
import subprocess
from pathlib import Path

ROOT = Path("tensorrt_llm/_torch/models")
PACKAGE = "tensorrt_llm._torch.models"


def module_name_for(path: Path) -> str:
    relative = path.relative_to(ROOT)
    if relative.name == "__init__.py":
        parts = relative.parent.parts
    else:
        parts = relative.with_suffix("").parts
    return PACKAGE + (("." + ".".join(parts)) if parts else "")


module_paths = {
    module_name_for(path): path
    for path in ROOT.rglob("*.py")
}


def package_of(module_name: str) -> str:
    if module_name in module_paths and module_paths[module_name].name == "__init__.py":
        return module_name
    return module_name.rsplit(".", 1)[0]


def relative_base(node: ast.ImportFrom, current: str) -> str | None:
    if node.level == 0:
        return node.module
    base = package_of(current)
    for _ in range(node.level - 1):
        base = base.rsplit(".", 1)[0]
    if node.module:
        return f"{base}.{node.module}"
    return base


def imports_from_tree(tree: ast.AST, current: str) -> set[str]:
    result: set[str] = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                if alias.name == PACKAGE or alias.name.startswith(PACKAGE + "."):
                    result.add(alias.name)
        elif isinstance(node, ast.ImportFrom):
            base = relative_base(node, current)
            if not base or not (
                base == PACKAGE or base.startswith(PACKAGE + ".")
            ):
                continue
            if node.module is not None:
                result.add(base)
            else:
                for alias in node.names:
                    if alias.name != "*":
                        result.add(f"{base}.{alias.name}")
    return result


def reachable(root_tree: ast.AST, root_name: str) -> set[str]:
    seen = {root_name}
    queue = [(root_name, root_tree)]
    while queue:
        current, tree = queue.pop()
        deps = imports_from_tree(tree, current)
        for dep in deps:
            if dep in module_paths and dep not in seen:
                seen.add(dep)
                queue.append((dep, ast.parse(module_paths[dep].read_text())))
    return seen


current_tree = ast.parse((ROOT / "__init__.py").read_text())
old_text = subprocess.check_output(
    [
        "git",
        "show",
        "22833f245^:tensorrt_llm/_torch/models/__init__.py",
    ],
    text=True,
)
old_tree = ast.parse(old_text)

old_loaded = reachable(old_tree, PACKAGE)
current_loaded = reachable(current_tree, PACKAGE)


def direct_children(loaded: set[str]) -> set[str]:
    prefix = PACKAGE + "."
    return {
        name[len(prefix):].split(".", 1)[0]
        for name in loaded
        if name.startswith(prefix)
    }


old_children = direct_children(old_loaded)
current_children = direct_children(current_loaded)

print("--- old direct child attributes ---")
for name in sorted(old_children):
    print(name)

print("--- current direct child attributes ---")
for name in sorted(current_children):
    print(name)

print("--- old attributes absent after current initialization ---")
for name in sorted(old_children - current_children):
    print(name)

print("--- absent old attributes not covered by modeling_* fallback ---")
for name in sorted(old_children - current_children):
    if not name.startswith("modeling_"):
        print(name)
PY

printf '%s\n' '--- relevant local imports ---'
rg -n -C3 'checkpoints|hf_parameter_utils|multimodal_encoder_graph|dspark' \
  tensorrt_llm/_torch/models/modeling_utils.py \
  tensorrt_llm/_torch/models/modeling_*.py \
  tensorrt_llm/_torch/models/_arch_index.py | sed -n '1,220p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 20814


🏁 Script executed:

#!/bin/bash
set -u

python3 - <<'PY'
from pathlib import Path
import re

root = Path("tensorrt_llm/_torch/models")
old_model_names = re.findall(
    r"from \.((?:modeling_[A-Za-z0-9_]+)) import",
    __import__("subprocess").check_output(
        ["git", "show", "22833f245^:tensorrt_llm/_torch/models/__init__.py"],
        text=True,
    ),
)

patterns = [
    re.compile(r"from\s+tensorrt_llm\._torch\.models\.([A-Za-z0-9_\.]+)\s+import"),
    re.compile(r"import\s+tensorrt_llm\._torch\.models\.([A-Za-z0-9_\.]+)"),
    re.compile(r"from\s+\.([A-Za-z0-9_]+)\s+import"),
]

print("--- non-modeling imports from old eager model modules ---")
seen = set()
for name in old_model_names:
    path = root / f"{name}.py"
    if not path.exists():
        continue
    for line_number, line in enumerate(path.read_text().splitlines(), 1):
        for pattern in patterns:
            match = pattern.search(line)
            if not match:
                continue
            imported = match.group(1).split(".", 1)[0]
            if not imported.startswith("modeling_") and imported not in seen:
                seen.add(imported)
                print(f"{path}:{line_number}: {imported}: {line.strip()}")
            break

print("--- non-modeling imports from current initializer dependencies ---")
for name in ("modeling_auto", "modeling_utils"):
    path = root / f"{name}.py"
    for line_number, line in enumerate(path.read_text().splitlines(), 1):
        for pattern in patterns:
            match = pattern.search(line)
            if not match:
                continue
            imported = match.group(1).split(".", 1)[0]
            if not imported.startswith("modeling_"):
                print(f"{path}:{line_number}: {imported}: {line.strip()}")
            break

print("--- package children and fallback result ---")
for path in sorted(root.iterdir()):
    if path.name == "__pycache__":
        continue
    if path.is_file() and path.suffix == ".py":
        child = path.stem
    elif path.is_dir() and (path / "__init__.py").exists():
        child = path.name
    else:
        continue
    print(f"{child}: {'handled' if child.startswith('modeling_') else 'not handled'}")
PY

Repository: NVIDIA/TensorRT-LLM

Length of output: 3047


🏁 Script executed:

#!/bin/bash
set -u

python3 - <<'PY'
from pathlib import Path
import re
import subprocess

root = Path("tensorrt_llm/_torch/models")
old_init = subprocess.check_output(
    [
        "git",
        "show",
        "22833f245^:tensorrt_llm/_torch/models/__init__.py",
    ],
    text=True,
)
old_model_names = re.findall(
    r"from \.((?:modeling_[A-Za-z0-9_]+)) import",
    old_init,
)

patterns = [
    re.compile(r"from\s+tensorrt_llm\._torch\.models\.([A-Za-z0-9_\.]+)\s+import"),
    re.compile(r"import\s+tensorrt_llm\._torch\.models\.([A-Za-z0-9_\.]+)"),
    re.compile(r"from\s+\.([A-Za-z0-9_]+)\s+import"),
]

print("--- non-modeling imports from old eager model modules ---")
seen = set()
for name in old_model_names:
    path = root / f"{name}.py"
    if not path.exists():
        continue
    for line_number, line in enumerate(path.read_text().splitlines(), 1):
        for pattern in patterns:
            match = pattern.search(line)
            if not match:
                continue
            imported = match.group(1).split(".", 1)[0]
            if not imported.startswith("modeling_") and imported not in seen:
                seen.add(imported)
                print(f"{path}:{line_number}: {imported}: {line.strip()}")
            break

print("--- non-modeling imports from current initializer dependencies ---")
for name in ("modeling_auto", "modeling_utils"):
    path = root / f"{name}.py"
    for line_number, line in enumerate(path.read_text().splitlines(), 1):
        for pattern in patterns:
            match = pattern.search(line)
            if not match:
                continue
            imported = match.group(1).split(".", 1)[0]
            if not imported.startswith("modeling_"):
                print(f"{path}:{line_number}: {imported}: {line.strip()}")
            break

print("--- package children and fallback result ---")
for path in sorted(root.iterdir()):
    if path.name == "__pycache__":
        continue
    if path.is_file() and path.suffix == ".py":
        child = path.stem
    elif path.is_dir() and (path / "__init__.py").exists():
        child = path.name
    else:
        continue
    print(f"{child}: {'handled' if child.startswith('modeling_') else 'not handled'}")
PY

Repository: NVIDIA/TensorRT-LLM

Length of output: 3047


🏁 Script executed:

#!/bin/bash
set -u

printf '%s\n' '--- modeling_utils checkpoint import context ---'
cat -n tensorrt_llm/_torch/models/modeling_utils.py | sed -n '1008,1035p'

printf '%s\n' '--- current initializer dependency imports ---'
rg -n '^from |^import ' \
  tensorrt_llm/_torch/models/modeling_auto.py \
  tensorrt_llm/_torch/models/modeling_utils.py |
  rg 'models|^\s*(from \.|import )' | sed -n '1,180p'

printf '%s\n' '--- all references to direct helper submodule names ---'
rg -n \
  'multimodal_encoder_graph|hf_parameter_utils|models\.checkpoints|models\.hf_parameter_utils|models\.multimodal_encoder_graph' \
  tensorrt_llm/_torch tests scripts examples 2>/dev/null | sed -n '1,220p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 26201


Preserve non-modeling_ submodule attributes.

The previous eager initializer exposed models.checkpoints and models.hf_parameter_utils. The current initializer raises AttributeError until a model module that imports them is loaded. Extend the fallback to direct submodules and convert only genuine import misses to AttributeError. models.modeling_multimodal_utils is already covered.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_torch/models/__init__.py` around lines 97 - 108, The
__getattr__ fallback in __init__ must also resolve direct submodule attributes
such as checkpoints and hf_parameter_utils, not only names beginning with
modeling_. Attempt importing the requested submodule for other names as well,
convert only genuine module-not-found misses to AttributeError, and preserve the
existing modeling_multimodal_utils coverage and model-class resolution behavior.



def __dir__():
return sorted(set(__all__) | set(globals()))
Loading
Loading