{"record":{"id":"e423e5f59b9dc1cf","repo":"hiyouga/LlamaFactory","slug":"the-model-does-not-have-a-submodule-named-submod","errorCode":null,"errorMessage":"The model does not have a submodule named '{submodule_name}'.","messagePattern":"The model does not have a submodule named '(.+?)'\\.","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"scripts/qwen_omni_merge.py","lineNumber":60,"sourceCode":"):\n    \"\"\"Load the original model, merge the LoRA weights.\n\n    For a specified submodule, and save the final merged model along with its configurations.\n\n    Args:\n        model_path (str): Path to the original model directory.\n        lora_path (str): Path to the directory containing LoRA weights.\n        save_path (str): Directory where the merged model and configurations will be saved.\n        extra_file (str): Name of the extra file to be copied (default: \"spk_dict.pt\").\n        submodule_name (str): Name of the submodule to merge (default: \"thinker\").\n    \"\"\"\n    # 1. Load the original model\n    model = AutoModelForTextToWaveform.from_pretrained(model_path, torch_dtype=\"auto\", device_map=\"cpu\")\n    print(\"Successfully loaded the original model.\")\n\n    # 2. Extract the submodule to be merged (e.g., model.thinker)\n    if not hasattr(model, submodule_name):\n        raise AttributeError(f\"The model does not have a submodule named '{submodule_name}'.\")\n\n    base_submodule = getattr(model, submodule_name)\n    print(f\"Successfully extracted submodule: {submodule_name}.\")\n\n    # 3. Load the LoRA weights onto the extracted submodule\n    lora_model = PeftModel.from_pretrained(base_submodule, lora_path)\n    processor = AutoProcessor.from_pretrained(lora_path)\n    print(\"Successfully loaded LoRA weights and processor.\")\n\n    # 4. Merge the LoRA weights into the submodule and unload the LoRA modules\n    merged_submodule = lora_model.merge_and_unload()\n    print(\"Successfully merged LoRA weights.\")\n\n    # 5. Replace the original submodule with the merged submodule in the model\n    setattr(model, submodule_name, merged_submodule)\n\n    # 6. Save the final merged model along with the tokenizer and processor configuration\n    model.save_pretrained(save_path)","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/hiyouga/LlamaFactory/blob/f28afaf6355af515454dfb16c97d728307c93897/scripts/qwen_omni_merge.py#L42-L78","documentation":"HyperParallel context parallelism repeats each logical batch across CP ranks via _CPBatchRepeatedBatchSampler, which requires integer indexing into the dataset (trainer.py:257). Iterable datasets (streaming datasets) can only be consumed sequentially, so _get_cp_dataloader raises NotImplementedError for torch.utils.data.IterableDataset before training starts.","triggerScenarios":"hyper_parallel_cp_size > 1 combined with a streaming dataset (dataset_info entry with streaming: true, or an IterableDataset handed to the trainer); get_train_dataloader routes into _get_cp_dataloader which refuses IterableDataset.","commonSituations":"Training on huge streamed corpora to avoid disk usage while enabling CP; switching a working streaming SFT config to the HyperParallel path.","solutions":["Use a map-style dataset: download/materialize the data and set streaming: false in dataset_info.json so a datasets.Dataset (map-style) is passed","Or set hyper_parallel_cp_size: 1 to disable CP, after which IterableDataset works through the normal trainer path"],"exampleFix":"# before (dataset_info.json)\n\"my_data\": {\"file_name\": \"...\", \"streaming\": true}\n# with hyper_parallel_cp_size: 2 -> NotImplementedError\n\n# after\n\"my_data\": {\"file_name\": \"...\", \"streaming\": false}","handlingStrategy":"validation","validationCode":"import torch.utils.data as tud\nassert not isinstance(train_dataset, tud.IterableDataset) or hp_args.cp_size <= 1, (\n    'HyperParallel CP (cp_size>1) needs a map-style dataset; disable streaming or set cp_size=1'\n)","typeGuard":"def dataset_is_map_style(dataset) -> bool:\n    import torch.utils.data as tud\n    return not isinstance(dataset, tud.IterableDataset)","tryCatchPattern":"try:\n    trainer.train()\nexcept NotImplementedError as e:\n    if 'map-style dataset' in str(e):\n        raise SystemExit('Set streaming:false in dataset_info.json or set hyper_parallel_cp_size:1') from e\n    raise","preventionTips":["Never combine streaming datasets with CP-parallel configs","Materialize large corpora once and train from the map-style cache"],"tags":["hyper-parallel","context-parallel","dataset","streaming"],"backgroundTag":null,"analyzedSha":"f28afaf6355af515454dfb16c97d728307c93897","analyzedAt":"2026-08-14T21:57:28.298Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}