Repository: PaddlePaddle/PaddleFormers Branch: develop Commit: 505415631247 Files: 1045 Total size: 23.2 MB Directory structure: gitextract__9f9_ucr/ ├── .copyright.hook ├── .flake8 ├── .github/ │ ├── CODE_OF_CONDUCT.md │ ├── CODE_OF_CONDUCT_en.md │ ├── CONTRIBUTING_en.md │ ├── ISSUE_TEMPLATE/ │ │ ├── ask-question.yml │ │ ├── bug-report.yml │ │ ├── docs-report.yml │ │ ├── feature-request.yml │ │ ├── new-model.yaml │ │ └── others.yml │ ├── PULL_REQUEST_TEMPLATE.md │ ├── actions/ │ │ └── rerun-workflow/ │ │ ├── action.yml │ │ └── rerun.sh │ ├── codecov.yml │ └── workflows/ │ ├── _clone_linux.yml │ ├── _xpu_ci_test.yml │ ├── ce-build-ci-workflow.yml │ ├── ce-build-images.yml │ ├── ce-build-whl.yml │ ├── ce-deadlink.yml │ ├── ce-unittest-gpu.yml │ ├── check-release-pr.yaml │ ├── cherry-pick.yml │ ├── ci_iluvatar.yml │ ├── ci_xpu.yml │ ├── debug-unittest-gpu.yml │ ├── fleet-model-test.yml │ ├── lint.yml │ ├── model-unittest-gpu.yml │ ├── requirements-review.yml │ ├── rerun.yml │ ├── stale.yml │ ├── unittest-gpu.yml │ └── update-precision.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yaml ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── docs/ │ ├── en/ │ │ ├── cli_usage.md │ │ ├── datasets.md │ │ ├── datasets_format.md │ │ ├── image_processors.md │ │ ├── processors.md │ │ └── video_processors.md │ └── zh/ │ ├── ILUVATAR-GPU_installation_guide.md │ ├── ILUVATAR-GPU_usage_guide.md │ ├── Metax-GPU_installation_guide.md │ ├── Metax-GPU_usage_guide.md │ ├── XPU_installation_guide.md │ ├── XPU_usage_guide.md │ ├── chat_template_guide.md │ ├── cli_usage.md │ ├── custom_datasets_format_zh.md │ ├── data_processing_guide.md │ ├── dataset_format.md │ ├── deployment_guide.md │ ├── dpo_and_lora_guide.md │ ├── ernie4.5_pretraining.md │ ├── how_to_download_model.md │ ├── image_processors_zh.md │ ├── model_capability.md │ ├── processors_zh.md │ ├── pt_and_cpt_guide.md │ ├── sft_and_lora_guide.md │ ├── template.md │ ├── template_zh.md │ ├── training_arguments.md │ └── video_processors_zh.md ├── examples/ │ ├── FAQ.md │ ├── README.md │ ├── best_practices/ │ │ ├── DeepSeek-V3/ │ │ │ ├── README.md │ │ │ ├── SFT-Practice.md │ │ │ ├── dsv3_128k_config.yaml │ │ │ ├── dsv3_32k_config.yaml │ │ │ ├── dsv3_4k_config.yaml │ │ │ ├── pretrain/ │ │ │ │ ├── config/ │ │ │ │ │ ├── config.json │ │ │ │ │ ├── pretrain_argument.yaml │ │ │ │ │ ├── tokenizer.json │ │ │ │ │ └── tokenizer_config.json │ │ │ │ ├── run.sh │ │ │ │ └── train_gpu.sh │ │ │ ├── run_dsv3_128k.sh │ │ │ ├── run_dsv3_32k.sh │ │ │ └── run_dsv3_4k.sh │ │ ├── ERNIE-4.5/ │ │ │ └── README.md │ │ ├── ERNIE-4.5-VL/ │ │ │ ├── README.md │ │ │ ├── ernie45vl_32k_config.yaml │ │ │ ├── ernie45vl_8k_config.yaml │ │ │ └── ernie45vl_8k_lora_config.yaml │ │ ├── PaddleOCR-VL/ │ │ │ ├── README.md │ │ │ ├── paddleocr-vl_full_16k_config.yaml │ │ │ ├── paddleocr-vl_lora_16k_config.yaml │ │ │ ├── paddleocr-vl_lora_export.yaml │ │ │ ├── run_paddleocr-vl_full_16k.sh │ │ │ ├── run_paddleocr-vl_full_16k_4090D.sh │ │ │ ├── run_paddleocr-vl_lora_16k.sh │ │ │ ├── run_paddleocr-vl_lora_16k_4090D.sh │ │ │ └── run_paddleocr-vl_lora_export.sh │ │ ├── PaddleOCR-VL-1.5/ │ │ │ ├── README.md │ │ │ ├── paddleocr-vl-v15_full_16k_region_config.yaml │ │ │ ├── paddleocr-vl-v15_full_16k_table_config.yaml │ │ │ ├── paddleocr-vl-v15_lora_16k_region_config.yaml │ │ │ ├── paddleocr-vl-v15_lora_16k_table_config.yaml │ │ │ ├── region_ocr.md │ │ │ └── table_ocr.md │ │ ├── function_call.md │ │ └── tutorials/ │ │ ├── how_to_train_a_function_call_model.md │ │ ├── how_to_train_a_reasoning_model.md │ │ ├── how_to_train_a_visual_grounding_model.md │ │ └── how_to_train_an_emoji_model.md │ ├── config/ │ │ ├── dpo/ │ │ │ ├── full.yaml │ │ │ ├── full_function_call.yaml │ │ │ ├── full_tp_pp.yaml │ │ │ ├── full_tp_pp_ep.yaml │ │ │ ├── lora.yaml │ │ │ ├── lora_tp_pp.yaml │ │ │ └── lora_tp_pp_ep.yaml │ │ ├── dpo-vl/ │ │ │ ├── full.yaml │ │ │ ├── full_fsdp.yaml │ │ │ ├── full_tp.yaml │ │ │ ├── lora.yaml │ │ │ ├── lora_fsdp.yaml │ │ │ └── lora_tp.yaml │ │ ├── iluvatar/ │ │ │ ├── ERNIE-4.5-0.3B-PT/ │ │ │ │ └── sft/ │ │ │ │ ├── full_8k.yaml │ │ │ │ ├── lora_8k.yaml │ │ │ │ ├── lora_export.yaml │ │ │ │ ├── run_full_8k.sh │ │ │ │ ├── run_lora_8k.sh │ │ │ │ └── run_lora_export.sh │ │ │ ├── ERNIE-4.5-21B-A3B-PT/ │ │ │ │ └── sft/ │ │ │ │ ├── full_8k.yaml │ │ │ │ ├── lora_8k.yaml │ │ │ │ ├── lora_export.yaml │ │ │ │ ├── run_full_8k.sh │ │ │ │ ├── run_lora_8k.sh │ │ │ │ └── run_lora_export.sh │ │ │ └── PaddleOCR-VL/ │ │ │ └── sft/ │ │ │ ├── paddleocr-vl_full_16k_config.yaml │ │ │ ├── paddleocr-vl_lora_16k_config.yaml │ │ │ ├── paddleocr-vl_lora_export.yaml │ │ │ ├── run_paddleocr-vl_full_16k.sh │ │ │ ├── run_paddleocr-vl_lora_16k.sh │ │ │ └── run_paddleocr-vl_lora_export.sh │ │ ├── metax/ │ │ │ ├── ERNIE-4.5-0.3B/ │ │ │ │ └── sft/ │ │ │ │ ├── lora.yaml │ │ │ │ ├── run_lora.sh │ │ │ │ ├── run_sft.sh │ │ │ │ └── sft.yaml │ │ │ └── ERNIE-4.5-21B-A3B/ │ │ │ └── sft/ │ │ │ ├── lora.yaml │ │ │ ├── run_lora.sh │ │ │ ├── run_sft.sh │ │ │ └── sft.yaml │ │ ├── pt/ │ │ │ ├── eb45_pretrain/ │ │ │ │ ├── 21b_8_gpus.yaml │ │ │ │ ├── 300b_2016_gpus.yaml │ │ │ │ ├── 300b_4_nodes_ce.yaml │ │ │ │ ├── 300b_8_gpus_ci.yaml │ │ │ │ ├── 300b_96gpus.yaml │ │ │ │ └── 300b_96gpus_small_acc.yaml │ │ │ ├── full.yaml │ │ │ ├── full_offline_data.yaml │ │ │ ├── full_tp_pp.yaml │ │ │ ├── full_tp_pp_ep.yaml │ │ │ ├── lora.yaml │ │ │ ├── lora_tp_pp.yaml │ │ │ └── lora_tp_pp_ep.yaml │ │ ├── run_export.yaml │ │ ├── sft/ │ │ │ ├── full.yaml │ │ │ ├── full_function_call.yaml │ │ │ ├── full_tp_pp.yaml │ │ │ ├── full_tp_pp_ep.yaml │ │ │ ├── lora.yaml │ │ │ ├── lora_tp_pp.yaml │ │ │ └── lora_tp_pp_ep.yaml │ │ ├── sft-vl/ │ │ │ ├── full.yaml │ │ │ ├── full_fsdp.yaml │ │ │ ├── full_tp.yaml │ │ │ ├── lora.yaml │ │ │ ├── lora_fsdp.yaml │ │ │ └── lora_tp.yaml │ │ └── xpu/ │ │ ├── DeepseekV3/ │ │ │ └── sft/ │ │ │ ├── full_32k_config.yaml │ │ │ ├── full_4k_config.yaml │ │ │ ├── run_full_32k.sh │ │ │ └── run_full_4k.sh │ │ ├── ERNIE-4.5-0.3B/ │ │ │ └── sft/ │ │ │ ├── full_8k.yaml │ │ │ ├── lora_8k.yaml │ │ │ └── lora_8k_export.yaml │ │ ├── ERNIE-4.5-21B-A3B/ │ │ │ └── sft/ │ │ │ ├── full_32k.yaml │ │ │ ├── lora_32k.yaml │ │ │ ├── lora_32k_export.yaml │ │ │ └── run_lora_32k.sh │ │ ├── ERNIE-4.5-21B-A3B-Thinking/ │ │ │ └── sft/ │ │ │ └── full_8k.yaml │ │ ├── ERNIE-4.5-VL-28B-A3B-Thinking/ │ │ │ └── sft/ │ │ │ └── full_32k.yaml │ │ └── PaddleOCR-VL/ │ │ └── sft/ │ │ ├── paddleocr-vl_full_16k_config.yaml │ │ ├── paddleocr-vl_lora_16k_config.yaml │ │ ├── paddleocr-vl_lora_export.yaml │ │ ├── run_paddleocr-vl_full_16k.sh │ │ ├── run_paddleocr-vl_lora_16k.sh │ │ └── run_paddleocr-vl_lora_export.sh │ ├── experiments/ │ │ ├── deepseek_v3_pretrain/ │ │ │ ├── README.md │ │ │ ├── config/ │ │ │ │ ├── __init__.py │ │ │ │ ├── config.json │ │ │ │ ├── configuration.py │ │ │ │ ├── pretrain_argument.json │ │ │ │ └── pretrain_argument.yaml │ │ │ ├── convert_ckpt_to_sft.py │ │ │ ├── fp8_linear.py │ │ │ ├── kernel.py │ │ │ ├── load_hf_ckpt.py │ │ │ ├── modeling.py │ │ │ ├── modeling_pp.py │ │ │ ├── moe_gate.py │ │ │ ├── moe_layer.py │ │ │ ├── moe_utils.py │ │ │ ├── run.sh │ │ │ ├── run_pretrain.py │ │ │ ├── script/ │ │ │ │ └── train_gpu.sh │ │ │ └── token_dispatcher.py │ │ ├── ernie_pretrain/ │ │ │ ├── README.md │ │ │ ├── README_zh.md │ │ │ ├── demo_data/ │ │ │ │ ├── data-1-part0.idx │ │ │ │ └── data-1-part1.idx │ │ │ ├── ernie/ │ │ │ │ ├── config.py │ │ │ │ ├── model_config.py │ │ │ │ ├── pretrain.py │ │ │ │ └── src/ │ │ │ │ ├── __init__.py │ │ │ │ ├── callbacks/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── fp8_quant_weight_callback.py │ │ │ │ │ ├── gc_callback.py │ │ │ │ │ ├── logging_callback.py │ │ │ │ │ ├── moe_correction_bias_adjust_callback.py │ │ │ │ │ ├── moe_logging_callback.py │ │ │ │ │ ├── ortho_loss_callback.py │ │ │ │ │ ├── sp_grad_sync_callback.py │ │ │ │ │ └── tensorboard_callback.py │ │ │ │ ├── clip/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── moe_clip.py │ │ │ │ ├── lr_schedulers/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── cosine_lr.py │ │ │ │ │ └── wsd_lr.py │ │ │ │ ├── tokenizers/ │ │ │ │ │ ├── tokenization_eb_v2.py │ │ │ │ │ └── tokenizer_model/ │ │ │ │ │ ├── added_tokens.json │ │ │ │ │ ├── special_tokens_map.json │ │ │ │ │ ├── tokenizer.model │ │ │ │ │ └── tokenizer_config.json │ │ │ │ ├── trainers/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── data_parallel.py │ │ │ │ │ ├── dygraph_optimizer/ │ │ │ │ │ │ └── hybrid_parallel_optimizer.py │ │ │ │ │ └── pretraining_trainer.py │ │ │ │ └── utils/ │ │ │ │ ├── __init__.py │ │ │ │ ├── logging.py │ │ │ │ ├── misc.py │ │ │ │ ├── seed_utils.py │ │ │ │ └── training_utils.py │ │ │ ├── model_configs/ │ │ │ │ ├── ERNIE-4p5-21B-A3B/ │ │ │ │ │ └── model_config.json │ │ │ │ └── ERNIE-4p5-300B-A47B/ │ │ │ │ └── model_config.json │ │ │ ├── models/ │ │ │ │ ├── comm_utils.py │ │ │ │ ├── ernie/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── configuration.py │ │ │ │ │ ├── modeling.py │ │ │ │ │ ├── modeling_moe.py │ │ │ │ │ └── modeling_pp.py │ │ │ │ ├── fp8_linear.py │ │ │ │ ├── moe/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── moe_layer.py │ │ │ │ │ ├── token_dispatcher/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── fp8_utils.py │ │ │ │ │ │ └── moe_utils.py │ │ │ │ │ └── top2_gate.py │ │ │ │ ├── sequence_parallel_utils.py │ │ │ │ └── utils.py │ │ │ ├── requirements.txt │ │ │ ├── scripts/ │ │ │ │ └── ERNIE-4p5-300B-A47B/ │ │ │ │ ├── ci_ce/ │ │ │ │ │ ├── train_4_nodes_ce.sh │ │ │ │ │ └── train_8_gpus_ci.sh │ │ │ │ ├── train_2016_gpus.sh │ │ │ │ └── train_96_gpus.sh │ │ │ ├── tools/ │ │ │ │ ├── sharded_to_uc/ │ │ │ │ │ ├── README_zh.md │ │ │ │ │ ├── convert_multi_nodes_sharded_to_single_uc.sh │ │ │ │ │ ├── convert_sharded_to_uc.py │ │ │ │ │ ├── gather_all_ckpt.py │ │ │ │ │ └── merge_sharding_ep.py │ │ │ │ └── uc_to_sharded/ │ │ │ │ ├── README.md │ │ │ │ ├── README_zh.md │ │ │ │ └── convert_uc_to_sharded.py │ │ │ └── yamls/ │ │ │ ├── ERNIE-4p5-21B-A3B/ │ │ │ │ └── pretrain_8_gpus.yaml │ │ │ └── ERNIE-4p5-300B-A47B/ │ │ │ ├── ci_ce/ │ │ │ │ ├── pretrain_4_nodes_ce.yaml │ │ │ │ └── pretrain_8_gpus_ci.yaml │ │ │ ├── pretrain_2016_gpus.yaml │ │ │ ├── pretrain_96_gpus.yaml │ │ │ └── pretrain_96_gpus_small_acc.yaml │ │ ├── glm_pretrain/ │ │ │ └── GLM4.5-Air.yaml │ │ └── paddlefleet/ │ │ ├── glm45.json │ │ ├── glm45_provider.py │ │ ├── glm45_single_card.json │ │ ├── qwen_provider.py │ │ ├── qwen_single_card.json │ │ ├── run_glm45.sh │ │ └── run_pretrain.py │ └── tools/ │ ├── create_pretraining_data.py │ ├── gpt-oss_weight_change/ │ │ ├── README.md │ │ └── change_weight_dtype.py │ ├── merge.py │ └── trans_paddlenlp2hf.py ├── paddleformers/ │ ├── __init__.py │ ├── cli/ │ │ ├── __init__.py │ │ ├── cli.py │ │ ├── export/ │ │ │ ├── __init__.py │ │ │ └── export.py │ │ ├── hparams/ │ │ │ ├── __init__.py │ │ │ ├── data_args.py │ │ │ ├── export_args.py │ │ │ ├── finetuning_args.py │ │ │ ├── generating_args.py │ │ │ ├── model_args.py │ │ │ ├── parser.py │ │ │ ├── preprocess_args.py │ │ │ └── server_args.py │ │ ├── launcher.py │ │ ├── train/ │ │ │ ├── __init__.py │ │ │ ├── auto_parallel/ │ │ │ │ ├── __init__.py │ │ │ │ └── workflow.py │ │ │ ├── deepseek_v3_pretrain/ │ │ │ │ ├── __init__.py │ │ │ │ ├── configuration.py │ │ │ │ ├── fp8_linear.py │ │ │ │ ├── kernel.py │ │ │ │ ├── modeling.py │ │ │ │ ├── modeling_pp.py │ │ │ │ ├── moe_gate.py │ │ │ │ ├── moe_layer.py │ │ │ │ ├── moe_utils.py │ │ │ │ ├── token_dispatcher.py │ │ │ │ ├── utils/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── convert_ckpt_to_sft.py │ │ │ │ │ └── load_hf_ckpt.py │ │ │ │ └── workflow.py │ │ │ ├── dpo/ │ │ │ │ ├── __init__.py │ │ │ │ ├── data_config.py │ │ │ │ ├── dpo_argument.py │ │ │ │ ├── dpo_estimate_training.py │ │ │ │ ├── dpo_trainer.py │ │ │ │ └── workflow.py │ │ │ ├── ernie_pretrain/ │ │ │ │ ├── __init__.py │ │ │ │ ├── model_config.py │ │ │ │ ├── models/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── comm_utils.py │ │ │ │ │ ├── ernie/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── configuration.py │ │ │ │ │ │ ├── modeling.py │ │ │ │ │ │ ├── modeling_moe.py │ │ │ │ │ │ └── modeling_pp.py │ │ │ │ │ ├── fp8_linear.py │ │ │ │ │ ├── moe/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── moe_layer.py │ │ │ │ │ │ ├── token_dispatcher/ │ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ │ ├── fp8_utils.py │ │ │ │ │ │ │ └── moe_utils.py │ │ │ │ │ │ └── top2_gate.py │ │ │ │ │ ├── sequence_parallel_utils.py │ │ │ │ │ └── utils.py │ │ │ │ ├── src/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── callbacks/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── fp8_quant_weight_callback.py │ │ │ │ │ │ ├── gc_callback.py │ │ │ │ │ │ ├── logging_callback.py │ │ │ │ │ │ ├── moe_correction_bias_adjust_callback.py │ │ │ │ │ │ ├── moe_logging_callback.py │ │ │ │ │ │ ├── ortho_loss_callback.py │ │ │ │ │ │ ├── sp_grad_sync_callback.py │ │ │ │ │ │ └── tensorboard_callback.py │ │ │ │ │ ├── clip/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ └── moe_clip.py │ │ │ │ │ ├── lr_schedulers/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── cosine_lr.py │ │ │ │ │ │ └── wsd_lr.py │ │ │ │ │ ├── tokenizers/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ └── tokenization_eb_v2.py │ │ │ │ │ ├── trainers/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── data_parallel.py │ │ │ │ │ │ ├── dygraph_optimizer/ │ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ │ └── hybrid_parallel_optimizer.py │ │ │ │ │ │ └── pretraining_trainer.py │ │ │ │ │ └── utils/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── logging.py │ │ │ │ │ ├── misc.py │ │ │ │ │ ├── seed_utils.py │ │ │ │ │ └── training_utils.py │ │ │ │ └── workflow.py │ │ │ ├── sft/ │ │ │ │ ├── __init__.py │ │ │ │ ├── dataset_formatting.py │ │ │ │ ├── make_data_utils.py │ │ │ │ ├── sft_config.py │ │ │ │ ├── sft_trainer.py │ │ │ │ └── workflow.py │ │ │ └── tuner.py │ │ └── utils/ │ │ ├── __init__.py │ │ ├── llm_utils.py │ │ ├── mllm_utils.py │ │ └── process.py │ ├── data/ │ │ ├── __init__.py │ │ ├── blendable_dataset.py │ │ ├── causal_dataset.py │ │ ├── collate.py │ │ ├── data_collator.py │ │ ├── dist_dataloader.py │ │ ├── indexed_dataset.py │ │ ├── iterator.py │ │ ├── sampler.py │ │ ├── tokenizer.py │ │ └── vocab.py │ ├── datasets/ │ │ ├── DPODataset.py │ │ ├── SFTDataset.py │ │ ├── __init__.py │ │ ├── collate.py │ │ ├── data_utils.py │ │ ├── dataset.py │ │ ├── loader.py │ │ ├── reader/ │ │ │ ├── __init__.py │ │ │ ├── convertor.py │ │ │ ├── data_info.json │ │ │ ├── download_manager.py │ │ │ ├── file_reader.py │ │ │ ├── io.py │ │ │ ├── mix_datasets.py │ │ │ └── multi_source_datasets.py │ │ ├── rlhf_datasets/ │ │ │ ├── __init__.py │ │ │ ├── protocol.py │ │ │ └── rl_dataset.py │ │ ├── sampler/ │ │ │ └── __init__.py │ │ └── template/ │ │ ├── __init__.py │ │ ├── augment_utils.py │ │ ├── formatter.py │ │ ├── grounding_plugin.py │ │ ├── mm_plugin.py │ │ ├── template.py │ │ └── tool_utils.py │ ├── generation/ │ │ ├── __init__.py │ │ ├── configuration_utils.py │ │ ├── logits_process.py │ │ ├── stopping_criteria.py │ │ ├── streamers.py │ │ └── utils.py │ ├── mergekit/ │ │ ├── __init__.py │ │ ├── merge_config.py │ │ ├── merge_method.py │ │ ├── merge_model.py │ │ ├── merge_utils.py │ │ └── sparsify_method.py │ ├── nn/ │ │ ├── __init__.py │ │ ├── activation.py │ │ ├── attention/ │ │ │ ├── __init__.py │ │ │ ├── eager_attention.py │ │ │ ├── flashmask_attention.py │ │ │ ├── interface.py │ │ │ ├── sdpa_attention.py │ │ │ ├── sink_impl.py │ │ │ └── utils.py │ │ ├── criterion/ │ │ │ ├── __init__.py │ │ │ ├── dpo_loss.py │ │ │ ├── interface.py │ │ │ ├── kto_loss.py │ │ │ ├── loss_utils.py │ │ │ └── sft_loss.py │ │ ├── embedding.py │ │ ├── general.py │ │ ├── linear.py │ │ ├── lm_head.py │ │ ├── mlp.py │ │ ├── moe/ │ │ │ ├── __init__.py │ │ │ ├── abstract.py │ │ │ ├── all_gather.py │ │ │ ├── all_to_all.py │ │ │ ├── moe_allgather_layer.py │ │ │ ├── moe_alltoall_layer.py │ │ │ ├── moe_block.py │ │ │ ├── topk_gate.py │ │ │ └── utils.py │ │ ├── moe_deepep/ │ │ │ ├── __init__.py │ │ │ ├── modular_moe_layer.py │ │ │ ├── moe_communication.py │ │ │ ├── moe_expert.py │ │ │ ├── moe_factory.py │ │ │ ├── moe_gate.py │ │ │ ├── moe_loss.py │ │ │ └── moe_loss_instance.py │ │ ├── norm.py │ │ └── pp_model.py │ ├── peft/ │ │ ├── __init__.py │ │ └── lora/ │ │ ├── __init__.py │ │ ├── auto_lora_model.py │ │ ├── lora_config.py │ │ ├── lora_layers.py │ │ ├── lora_model.py │ │ ├── lora_quant_layers.py │ │ ├── lora_quantization_layers.py │ │ ├── loraga_utils.py │ │ └── utils.py │ ├── quantization/ │ │ ├── __init__.py │ │ ├── checkpoint_quantization_utils.py │ │ ├── hadamard_utils.py │ │ ├── qat_utils.py │ │ ├── qlora.py │ │ ├── quantization_config.py │ │ ├── quantization_linear.py │ │ ├── quantization_utils.py │ │ └── unified_checkpoint_quantization.py │ ├── trainer/ │ │ ├── __init__.py │ │ ├── argparser.py │ │ ├── integrations.py │ │ ├── plugins/ │ │ │ ├── __init__.py │ │ │ ├── npu_plugin.py │ │ │ └── timer.py │ │ ├── trainer.py │ │ ├── trainer_callback.py │ │ ├── trainer_utils.py │ │ ├── training_args.py │ │ ├── unified_checkpoint/ │ │ │ ├── __init__.py │ │ │ ├── async_handler.py │ │ │ ├── check_completion.py │ │ │ ├── load_dynamic.py │ │ │ ├── load_local.py │ │ │ ├── load_save_single_card.py │ │ │ ├── sharding_split_param_utils.py │ │ │ ├── shared_memory_utils.py │ │ │ ├── unified_checkpoint.py │ │ │ └── utils.py │ │ └── utils/ │ │ ├── __init__.py │ │ ├── async_save.py │ │ ├── ckpt_converter.py │ │ ├── doc.py │ │ ├── helper.py │ │ ├── offload_optimizer.py │ │ ├── reshard/ │ │ │ ├── __init__.py │ │ │ ├── common.py │ │ │ ├── pp_reshard.py │ │ │ ├── sharding_v1.py │ │ │ └── sharding_v2.py │ │ ├── sharding_io.py │ │ └── zero_cost_checkpoint.py │ ├── transformers/ │ │ ├── __init__.py │ │ ├── activations.py │ │ ├── aistudio_utils.py │ │ ├── attention_utils.py │ │ ├── audio_processing_utils.py │ │ ├── audio_utils.py │ │ ├── auto/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── factory.py │ │ │ ├── feature_extraction.py │ │ │ ├── image_processing.py │ │ │ ├── modeling.py │ │ │ ├── processing.py │ │ │ ├── tokenizer.py │ │ │ └── video_processing.py │ │ ├── auto_utils.py │ │ ├── cache_utils.py │ │ ├── configuration_utils.py │ │ ├── context_parallel_utils.py │ │ ├── contrastive_loss.py │ │ ├── conversion_utils.py │ │ ├── deepseek_v3/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── mfu_utils.py │ │ │ └── modeling.py │ │ ├── download_utils.py │ │ ├── dpo_criterion.py │ │ ├── embedding_utils.py │ │ ├── ernie4_5/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── modeling.py │ │ │ └── tokenizer.py │ │ ├── ernie4_5_moe/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ └── modeling.py │ │ ├── ernie4_5_moe_vl/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── image_processor.py │ │ │ ├── model/ │ │ │ │ ├── __init__.py │ │ │ │ ├── comm_utils.py │ │ │ │ ├── configuration.py │ │ │ │ ├── dfnrope/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── activation.py │ │ │ │ │ ├── configuration.py │ │ │ │ │ ├── modeling.py │ │ │ │ │ └── modeling_pp.py │ │ │ │ ├── distributed/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── common_dist_utils.py │ │ │ │ │ └── xpu_dist_utils.py │ │ │ │ ├── fusion_ops/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── common_fusion_ops.py │ │ │ │ │ └── npu_fusion_ops.py │ │ │ │ ├── longcontext_ops.py │ │ │ │ ├── loss/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── dpo.py │ │ │ │ ├── modeling.py │ │ │ │ ├── modeling_moe.py │ │ │ │ ├── modeling_moe_pp.py │ │ │ │ ├── modeling_moe_vl.py │ │ │ │ ├── modeling_moe_vl_pp.py │ │ │ │ ├── moe/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── moe_all_gather_layer.py │ │ │ │ │ ├── moe_layer.py │ │ │ │ │ └── topk_gate.py │ │ │ │ ├── refined_recompute/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── utils.py │ │ │ │ ├── sequence_parallel_utils.py │ │ │ │ └── utils/ │ │ │ │ ├── __init__.py │ │ │ │ └── misc.py │ │ │ ├── modeling.py │ │ │ ├── processor.py │ │ │ ├── tokenizer.py │ │ │ └── vision_process.py │ │ ├── feature_extraction_utils.py │ │ ├── fp8_utils.py │ │ ├── fused_a2a.py │ │ ├── gemma3_text/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ └── modeling.py │ │ ├── glm4_moe/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ └── modeling.py │ │ ├── glm4v_moe/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── image_processor.py │ │ │ ├── image_processor_fast.py │ │ │ ├── modeling.py │ │ │ ├── processor.py │ │ │ └── video_processor.py │ │ ├── glm_ocr/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── image_processor.py │ │ │ ├── modeling.py │ │ │ └── processor.py │ │ ├── gpt_oss/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ └── modeling.py │ │ ├── gpt_provider.py │ │ ├── image_processing_utils.py │ │ ├── image_processing_utils_fast.py │ │ ├── image_transforms.py │ │ ├── image_utils.py │ │ ├── kimi_k2/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── modeling.py │ │ │ └── tokenizer.py │ │ ├── kimi_k25/ │ │ │ ├── __init__.py │ │ │ ├── media_utils.py │ │ │ ├── processor.py │ │ │ ├── tokenizer.py │ │ │ ├── tool_declaration_ts.py │ │ │ └── vision_processor.py │ │ ├── kto_criterion.py │ │ ├── legacy/ │ │ │ ├── __init__.py │ │ │ ├── tokenizer_utils.py │ │ │ └── tokenizer_utils_base.py │ │ ├── linear_utils.py │ │ ├── llama/ │ │ │ ├── __init__.py │ │ │ ├── auto_dist_config.py │ │ │ ├── configuration.py │ │ │ ├── modeling.py │ │ │ ├── tokenizer.py │ │ │ └── tokenizer_fast.py │ │ ├── masking_utils.py │ │ ├── mc2_parallel_linear.py │ │ ├── model_outputs.py │ │ ├── model_provider.py │ │ ├── model_utils.py │ │ ├── modeling_rope_utils.py │ │ ├── modelscope_utils.py │ │ ├── moe_gate.py │ │ ├── moe_gate_auto.py │ │ ├── moe_layer.py │ │ ├── moe_layer_auto.py │ │ ├── moe_utils.py │ │ ├── ofa_utils.py │ │ ├── optimization.py │ │ ├── paddle_vision_utils.py │ │ ├── paddleocr_vl/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── image_processor.py │ │ │ ├── modeling.py │ │ │ └── processor.py │ │ ├── phi3/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── modeling.py │ │ │ └── tokenizer.py │ │ ├── processing_utils.py │ │ ├── qwen2/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── modeling.py │ │ │ ├── tokenizer.py │ │ │ └── tokenizer_fast.py │ │ ├── qwen2_5_vl/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── modeling.py │ │ │ └── processor.py │ │ ├── qwen2_moe/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ └── modeling.py │ │ ├── qwen2_vl/ │ │ │ ├── __init__.py │ │ │ ├── image_processor.py │ │ │ ├── image_processor_fast.py │ │ │ ├── processor.py │ │ │ ├── video_processor.py │ │ │ └── vision_process.py │ │ ├── qwen3/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ └── modeling.py │ │ ├── qwen3_5/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ └── modeling.py │ │ ├── qwen3_moe/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ └── modeling.py │ │ ├── qwen3_next/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ └── modeling.py │ │ ├── qwen3_omni_moe/ │ │ │ ├── __init__.py │ │ │ └── processor.py │ │ ├── qwen3_vl/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ ├── modeling.py │ │ │ ├── modeling_fleet.py │ │ │ ├── processor.py │ │ │ └── video_processor.py │ │ ├── qwen3_vl_moe/ │ │ │ ├── __init__.py │ │ │ ├── configuration.py │ │ │ └── modeling.py │ │ ├── refined_recompute.py │ │ ├── ring_flash_attention.py │ │ ├── segment_parallel_utils.py │ │ ├── sequence_parallel_utils.py │ │ ├── tensor_parallel_utils.py │ │ ├── token_dispatcher.py │ │ ├── tokenizer_utils.py │ │ ├── tokenizer_utils_base.py │ │ ├── utils.py │ │ ├── video_processing_utils.py │ │ ├── video_utils.py │ │ ├── vocab_utils.py │ │ └── whisper/ │ │ ├── __init__.py │ │ └── processor.py │ ├── triton_kernels/ │ │ ├── __init__.py │ │ └── rope_triton.py │ ├── utils/ │ │ ├── __init__.py │ │ ├── adamw_triton.py │ │ ├── batch_sampler.py │ │ ├── converter.py │ │ ├── distributed.py │ │ ├── doc_parser.py │ │ ├── download/ │ │ │ ├── __init__.py │ │ │ ├── aistudio_hub_download.py │ │ │ ├── common.py │ │ │ └── download.py │ │ ├── downloader.py │ │ ├── env.py │ │ ├── fault_tolerance.py │ │ ├── ie_utils.py │ │ ├── image_utils.py │ │ ├── import_utils.py │ │ ├── infohub.py │ │ ├── initializer.py │ │ ├── lazy_import.py │ │ ├── log.py │ │ ├── masking_utils.py │ │ ├── memory_utils.py │ │ ├── moe_hybrid_parallel_optimizer.py │ │ ├── nested.py │ │ ├── optimizer.py │ │ ├── paddle_patch.py │ │ ├── pdc_sdk.py │ │ ├── perf_utils.py │ │ ├── profiler.py │ │ ├── safetensors.py │ │ ├── serialization.py │ │ ├── tools.py │ │ ├── type_validators.py │ │ └── upcast_downcast_triton.py │ └── version/ │ ├── __init__.py │ └── git.py ├── pyproject.toml ├── requirements.txt ├── scripts/ │ ├── ci_utils/ │ │ ├── __init__.py │ │ ├── log_analyzer.py │ │ └── training_utils.py │ ├── codestyle/ │ │ ├── check_dead_links.py │ │ ├── check_spaces.py │ │ └── get_modified_files.py │ ├── dependence/ │ │ └── build.sh │ ├── iluvatar_ci/ │ │ ├── base_value/ │ │ │ └── ERNIE-21B-SFT-LOSS.json │ │ ├── config/ │ │ │ └── ERNIE-21B-SFT.yaml │ │ ├── conftest.py │ │ └── test_ernie_21b_sft.py │ ├── regression/ │ │ ├── ci_model_unittest.sh │ │ ├── test_dpo_tiny-random-glm4moe.py │ │ ├── test_pt_tiny-random-glm4moe.py │ │ └── test_sft_tiny-random-glm4moe.py │ ├── unit_test/ │ │ ├── ci_unittest.sh │ │ └── gen_allure_report.py │ └── xpu_ci/ │ ├── README.md │ ├── base_value/ │ │ ├── ernie_21b_sft_loss.json │ │ └── ernie_28b_thinking_sft_loss.json │ ├── config/ │ │ ├── ernie_21b_sft.yaml │ │ └── ernie_vl_28b_sft.yaml │ ├── conftest.py │ ├── test_ernie_21b_sft.py │ ├── test_ernie_28b_thinking_sft.py │ └── test_example_template.py.template ├── setup.py └── tests/ ├── README.md ├── __init__.py ├── check_log_for_exitcode.py ├── common_test.py ├── config/ │ ├── benchmark/ │ │ └── config/ │ │ ├── pt/ │ │ │ ├── DeepSeek-V3.yaml │ │ │ ├── ERNIE45-21B.yaml │ │ │ ├── ERNIE45-300B.yaml │ │ │ ├── GLM4.5-Air.yaml │ │ │ ├── GLM4.5-Air_64k.yaml │ │ │ ├── GLM4.5-Air_FP8.yaml │ │ │ ├── Qwen3-30B-A3B-Base-64k.yaml │ │ │ └── Qwen3-30B-A3B-Base.yaml │ │ └── sft/ │ │ ├── GLM4.5-Air.yaml │ │ ├── GLM4.5-Air_128k.yaml │ │ ├── GLM4.5-Air_64k.yaml │ │ ├── Qwen3-30B-A3B-Base-64k.yaml │ │ ├── Qwen3-30B-A3B-Base.yaml │ │ ├── Qwen3-VL-30B-A3B-Instruct.yaml │ │ └── Qwen3-VL-8B-Instruct.yaml │ └── ci/ │ ├── glm45_dpo.yaml │ ├── glm45_dpo_lora.yaml │ ├── glm45_lora.yaml │ ├── glm45_pt.yaml │ ├── glm45_pt_fp8.yaml │ ├── glm45_pt_grouped_gemm.yaml │ ├── glm45_sft.yaml │ ├── glm45_single_pt-test.yaml │ ├── qwen3_multicard_lora.yaml │ ├── qwen3_multicard_pt.yaml │ ├── qwen3_multicard_sft.yaml │ ├── qwen3_pt.yaml │ ├── qwen3vl_lora.yaml │ ├── qwen3vl_sft.yaml │ ├── qwen3vl_sft_fsdp.yaml │ ├── qwen3vl_sft_moe.yaml │ ├── qwen3vl_sft_moe_a100.yaml │ └── qwen3vl_sft_single.yaml ├── conftest.py ├── data/ │ ├── __init__.py │ ├── test_blendable_dataset.py │ ├── test_collate.py │ ├── test_data_collator.py │ ├── test_sampler.py │ └── test_vocab.py ├── dataset/ │ ├── __init__.py │ ├── test_convertor.py │ ├── test_ernie_datasets.py │ ├── test_file_reader.py │ ├── test_io.py │ └── test_iter_datasets.py ├── fixtures/ │ ├── chat_template.json │ ├── chat_template_with_context.json │ ├── dummy/ │ │ ├── dpo/ │ │ │ ├── eval.jsonl │ │ │ ├── function-call-eval.jsonl │ │ │ ├── function-call-train.jsonl │ │ │ └── train.jsonl │ │ ├── dpo-vl/ │ │ │ ├── eval.jsonl │ │ │ └── train.jsonl │ │ ├── io/ │ │ │ ├── train.jsonl │ │ │ └── train.parquet │ │ ├── pt/ │ │ │ ├── eval.jsonl │ │ │ └── train.jsonl │ │ ├── sft/ │ │ │ ├── eval.jsonl │ │ │ ├── function-call-eval.jsonl │ │ │ ├── function-call-train.jsonl │ │ │ └── train.jsonl │ │ ├── sft-vl/ │ │ │ ├── thinking_safety_demo.jsonl │ │ │ └── train.jsonl │ │ └── tnews/ │ │ ├── dev.json │ │ └── train.json │ └── sample_text.txt ├── generation/ │ ├── __init__.py │ ├── test_logits_process.py │ ├── test_stopping_criteria.py │ ├── test_streamers.py │ └── test_synced_gpus.py ├── integration_test/ │ ├── check_loss.py │ ├── check_pr_approval.py │ ├── check_precision_approval.sh │ ├── glm45_a100.sh │ ├── glm45_dpo.sh │ ├── glm45_dpo_lora.sh │ ├── glm45_lora.sh │ ├── glm45_pt.sh │ ├── glm45_pt_ep4.sh │ ├── glm45_pt_fp8.sh │ ├── glm45_pt_grouped_gemm.sh │ ├── glm45_pt_single_card.sh │ ├── glm45_sft.sh │ ├── preprocess.sh │ ├── qwen.sh │ ├── qwen3_a100.sh │ ├── qwen3_single_card.sh │ ├── qwen3vl_lora.sh │ ├── qwen3vl_sft.sh │ ├── qwen3vl_sft_single_card.sh │ └── update_precision.sh ├── mergekit/ │ ├── __init__.py │ ├── test_merge_config.py │ ├── test_merge_method.py │ ├── test_merge_model.py │ └── test_sparsify_method.py ├── nn/ │ ├── __init__.py │ ├── test_activation.py │ ├── test_attention.py │ ├── test_criterion.py │ ├── test_embedding.py │ ├── test_linear.py │ ├── test_lm_head.py │ ├── test_mlp.py │ └── test_norm.py ├── parallel_launch.py ├── peft/ │ ├── __init__.py │ ├── test_lora.py │ └── test_quant_lora.py ├── quantization/ │ ├── __init__.py │ └── test_quant.py ├── requirements.txt ├── testing_utils.py ├── trainer/ │ ├── test_argparser.py │ ├── test_hf_format_saver_tp4_sharding2.py │ ├── test_lora_unified_checkpoint.py │ ├── test_moe_unified_checkpoint.py │ ├── test_trainer_callback.py │ ├── test_trainer_visualization.py │ ├── test_unified_checkpoint.py │ ├── trainer_utils.py │ └── unified-ckpt-llama-170m/ │ └── config.json ├── transformers/ │ ├── __init__.py │ ├── auto/ │ │ ├── __init__.py │ │ ├── test_configuration.py │ │ ├── test_feature_extraction.py │ │ ├── test_image_processor.py │ │ ├── test_modeling.py │ │ ├── test_processor.py │ │ ├── test_tokenizer.py │ │ ├── test_tokenizer_without_paddle.py │ │ └── test_video_processor.py │ ├── deepseek_v3/ │ │ ├── __init__.py │ │ └── test_modeling.py │ ├── ernie4_5/ │ │ ├── __init__.py │ │ └── test_modeling.py │ ├── ernie4_5_moe/ │ │ ├── __init__.py │ │ └── test_modeling.py │ ├── ernie4_5_moe_vl/ │ │ ├── __init__.py │ │ ├── test_modeling.py │ │ ├── test_processor.py │ │ ├── test_tokenizer.py │ │ └── test_vision_process.py │ ├── gemma3_text/ │ │ ├── __init__.py │ │ └── test_modeling.py │ ├── glm4_moe/ │ │ ├── __init__.py │ │ └── test_modeling.py │ ├── glm4v_moe/ │ │ ├── __init__.py │ │ ├── test_image_processor.py │ │ ├── test_modeling.py │ │ └── test_processor.py │ ├── glm_ocr/ │ │ ├── __init__.py │ │ ├── test_image_processor.py │ │ ├── test_modeling.py │ │ └── test_processor.py │ ├── gpt_oss/ │ │ ├── __init__.py │ │ ├── test_fp4_to_bf16.py │ │ └── test_modeling.py │ ├── kimi_k2/ │ │ └── test_modeling.py │ ├── kimi_k25/ │ │ ├── __init__.py │ │ └── test_processor.py │ ├── llama/ │ │ ├── __init__.py │ │ ├── test_modeling.py │ │ └── test_tokenizer.py │ ├── paddleocr_vl/ │ │ ├── __init__.py │ │ ├── test_modeling.py │ │ └── test_processor.py │ ├── phi3/ │ │ ├── __init__.py │ │ └── test_modeling.py │ ├── qwen2/ │ │ ├── __init__.py │ │ ├── test_modeling.py │ │ └── test_tokenizer.py │ ├── qwen2_5_vl/ │ │ ├── __init__.py │ │ ├── test_modeling.py │ │ └── test_processor.py │ ├── qwen2_vl/ │ │ ├── __init__.py │ │ ├── test_image_processor.py │ │ ├── test_processor.py │ │ ├── test_video_processor.py │ │ └── test_vision_process.py │ ├── qwen2moe/ │ │ ├── __init__.py │ │ └── test_modeling.py │ ├── qwen3/ │ │ ├── __init__.py │ │ └── test_modeling.py │ ├── qwen3_omni_moe/ │ │ ├── __init__.py │ │ └── test_processor.py │ ├── qwen3_vl/ │ │ ├── __init__.py │ │ ├── test_modeling.py │ │ ├── test_processor.py │ │ └── test_video_processor.py │ ├── qwen3_vl_moe/ │ │ ├── __init__.py │ │ └── test_modeling.py │ ├── qwen3moe/ │ │ ├── __init__.py │ │ └── test_modeling.py │ ├── qwen3next/ │ │ ├── __init__.py │ │ └── test_modeling.py │ ├── test_cache_utils.py │ ├── test_configuration_common.py │ ├── test_configuration_utils.py │ ├── test_conversion_common.py │ ├── test_conversion_tp_split_merge.py │ ├── test_generation_utils.py │ ├── test_hf_feature_extractor.py │ ├── test_hf_image_processor.py │ ├── test_hf_processor.py │ ├── test_hf_tokenizer.py │ ├── test_hf_video_processor.py │ ├── test_image_processing_common.py │ ├── test_masking_utils.py │ ├── test_modeling_common.py │ ├── test_modeling_rope_utils.py │ ├── test_modeling_utils.py │ ├── test_processing_common.py │ ├── test_ring_flash_attention.py │ ├── test_safetensors.py │ ├── test_segment_parallel_utils.py │ ├── test_tensor_parallel.py │ ├── test_utils.py │ └── test_video_processing_common.py ├── triton/ │ └── test_rope_triton.py └── utils/ ├── __init__.py ├── test_aistudio_download.py ├── test_downloader.py ├── test_import_utils.py ├── test_module/ │ ├── __init__.py │ ├── custom_configuration.py │ ├── custom_model.py │ ├── custom_tokenizer.py │ └── custom_tokenizer_fast.py ├── test_serialization.py └── test_set_nccl_config.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .copyright.hook ================================================ # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import absolute_import from __future__ import print_function from __future__ import unicode_literals import argparse import io import re import sys import os import datetime COPYRIGHT = '''Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.''' def _generate_copyright(comment_mark): copyright=COPYRIGHT.split(os.linesep) header = copyright[0].rstrip() p = re.search('(\d{4})', header).group(0) now = datetime.datetime.now() header = header.replace(p,str(now.year)) ans=[comment_mark + " " + header + os.linesep] for idx, line in enumerate(copyright[1:]): ans.append(comment_mark + " " + line.rstrip() + os.linesep) return ans def _get_comment_mark(path): lang_type=re.compile(r"\.(py|sh)$") if lang_type.search(path) is not None: return "#" lang_type=re.compile(r"\.(h|c|hpp|cc|cpp|cu|go|cuh|proto)$") if lang_type.search(path) is not None: return "//" return None RE_ENCODE = re.compile(r"^[ \t\v]*#.*?coding[:=]", re.IGNORECASE) RE_COPYRIGHT = re.compile(r".*Copyright( \(c\))* \d{4}", re.IGNORECASE) RE_SHEBANG = re.compile(r"^[ \t\v]*#[ \t]?\!") def _check_copyright(path): head=[] try: with open(path, encoding="utf-8") as f: head = [next(f) for x in range(4)] except StopIteration: pass for idx, line in enumerate(head): if RE_COPYRIGHT.search(line) is not None: return True return False def generate_copyright(path, comment_mark): original_contents = io.open(path, encoding="utf-8").readlines() head = original_contents[0:4] insert_line_no=0 for i, line in enumerate(head): if RE_ENCODE.search(line) or RE_SHEBANG.search(line): insert_line_no=i+1 copyright = _generate_copyright(comment_mark) if insert_line_no == 0: new_contents = copyright if len(original_contents) > 0 and len(original_contents[0].strip()) != 0: new_contents.append(os.linesep) new_contents.extend(original_contents) else: new_contents=original_contents[0:insert_line_no] new_contents.append(os.linesep) new_contents.extend(copyright) if len(original_contents) > insert_line_no and len(original_contents[insert_line_no].strip()) != 0: new_contents.append(os.linesep) new_contents.extend(original_contents[insert_line_no:]) new_contents="".join(new_contents) with io.open(path, 'w') as output_file: output_file.write(new_contents) def main(argv=None): parser = argparse.ArgumentParser( description='Checker for copyright declaration.') parser.add_argument('filenames', nargs='*', help='Filenames to check') args = parser.parse_args(argv) retv = 0 for path in args.filenames: comment_mark = _get_comment_mark(path) if comment_mark is None: print("warning:Unsupported file", path, file=sys.stderr) continue if _check_copyright(path): continue generate_copyright(path, comment_mark) if __name__ == '__main__': exit(main()) ================================================ FILE: .flake8 ================================================ [flake8] ignore = E203, E402, E501, E731, E741, W503, W605, E722 max-line-length = 119 # E402: module level import not at top of file per-file-ignores = __init__.py:F401,F403,E402 ================================================ FILE: .github/CODE_OF_CONDUCT.md ================================================ **简体中文**🀄 | [English🌎](./CODE_OF_CONDUCT_en.md) # 贡献者公约 ## 我们的承诺 身为社区成员、贡献者和领袖,我们承诺使社区参与者不受骚扰,无论其年龄、体型、可见或不可见的缺陷、族裔、性征、性别认同和表达、经验水平、教育程度、社会与经济地位、国籍、相貌、种族、种姓、肤色、宗教信仰、性倾向或性取向如何。 我们承诺以有助于建立开放、友善、多样化、包容、健康社区的方式行事和互动。 ## 我们的准则 有助于为我们的社区创造积极环境的行为例子包括但不限于: * 表现出对他人的同情和善意 * 尊重不同的主张、观点和感受 * 提出和大方接受建设性意见 * 承担责任并向受我们错误影响的人道歉 * 注重社区共同诉求,而非个人得失 不当行为例子包括: * 使用情色化的语言或图像,及性引诱或挑逗 * 嘲弄、侮辱或诋毁性评论,以及人身或政治攻击 * 公开或私下的骚扰行为 * 未经他人明确许可,公布他人的私人信息,如物理或电子邮件地址 * 其他有理由认定为违反职业操守的不当行为 ## 责任和权力 社区领袖有责任解释和落实我们所认可的行为准则,并妥善公正地对他们认为不当、威胁、冒犯或有害的任何行为采取纠正措施。 社区领导有权力和责任删除、编辑或拒绝或拒绝与本行为准则不相符的评论(comment)、提交(commits)、代码、维基(wiki)编辑、议题(issues)或其他贡献,并在适当时机知采取措施的理由。 ## 适用范围 本行为准则适用于所有社区场合,也适用于在公共场所代表社区时的个人。 代表社区的情形包括使用官方电子邮件地址、通过官方社交媒体帐户发帖或在线上或线下活动中担任指定代表。 ## 监督 辱骂、骚扰或其他不可接受的行为可通过 paddlenlp@baidu.com 向负责监督的社区领袖报告。 所有投诉都将得到及时和公平的审查和调查。 所有社区领袖都有义务尊重任何事件报告者的隐私和安全。 ## 处理方针 社区领袖将遵循下列社区处理方针来明确他们所认定违反本行为准则的行为的处理方式: ### 1. 纠正 **社区影响**:使用不恰当的语言或其他在社区中被认定为不符合职业道德或不受欢迎的行为。 **处理意见**:由社区领袖发出非公开的书面警告,明确说明违规行为的性质,并解释举止如何不妥。或将要求公开道歉。 ### 2. 警告 **社区影响**:单个或一系列违规行为。 **处理意见**:警告并对连续性行为进行处理。在指定时间内,不得与相关人员互动,包括主动与行为准则执行者互动。这包括避免在社区场所和外部渠道中的互动。违反这些条款可能会导致临时或永久封禁。 ### 3. 临时封禁 **社区影响**: 严重违反社区准则,包括持续的不当行为。 **处理意见**: 在指定时间内,暂时禁止与社区进行任何形式的互动或公开交流。在此期间,不得与相关人员进行公开或私下互动,包括主动与行为准则执行者互动。违反这些条款可能会导致永久封禁。 ### 4. 永久封禁 **社区影响**:行为模式表现出违反社区准则,包括持续的不当行为、骚扰个人或攻击或贬低某个类别的个体。 **处理意见**:永久禁止在社区内进行任何形式的公开互动。 ## 参见 本行为准则改编自 [Contributor Covenant][homepage] 2.1 版, 参见 [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]。 社区处理方针灵感来源于 [Mozilla's code of conduct enforcement ladder][Mozilla CoC]。 有关本行为准则的常见问题的答案,参见 [https://www.contributor-covenant.org/faq][FAQ]。 其他语言翻译参见 [https://www.contributor-covenant.org/translations][translations]。 [homepage]: https://www.contributor-covenant.org [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations ================================================ FILE: .github/CODE_OF_CONDUCT_en.md ================================================ [简体中文🀄](./CODE_OF_CONDUCT.md) | **English**🌎 # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at paddlenlp@baidu.com. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations]. [homepage]: https://www.contributor-covenant.org [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations ================================================ FILE: .github/CONTRIBUTING_en.md ================================================ [简体中文🀄](../CONTRIBUTING.md) | **English**🌎 # Contributing to PaddleFormers We highly welcome and value your contributions to `PaddleFormers`. The first step to start your contribution is to sign the [PaddlePaddle Contributor License Agreement](https://cla-assistant.io/PaddlePaddle/PaddleFormers). This document explains our workflow and work style: ## Finding out what to work on Workflow ## Development Workflow PaddleFormers uses the [Git branching model](http://nvie.com/posts/a-successful-git-branching-model/). The following steps guide usual contributions. #### 1. Fork Our development community has been growing fastly; it doesn't make sense for everyone to write into the official repo. So, please file Pull Requests from your fork. To make a fork, just head over to the GitHub page and click the ["Fork" button](https://help.github.com/articles/fork-a-repo/). #### 2. Clone To make a copy of your fork to your local computers, please run ```bash git clone https://github.com//PaddleFormers cd PaddleFormers ``` #### 3. Create the local feature branch For daily works like adding a new feature or fixing a bug, please open your feature branch before coding: ```bash git checkout -b my-cool-feature ``` #### 4. Set up the development environment Before you start coding, you need to setup the development environment. We highly recommend doing all your development in a virtual environment such as [venv](https://docs.python.org/3/library/venv.html) or [conda](https://docs.conda.io/en/latest/). After you setup and activated your virtual environment, run the following command: ```bash make install ``` This will setup all the dependencies of `PaddleFormers` as well as the [`pre-commit`](http://pre-commit.com/) tool. If you are working on the `examples` or `applications` module and require importing from `PaddleFormers`, make sure you install `PaddleFormers` in editable mode. If `PaddleFormers` is already installed in the virtual environment, remove it with `pip uninstall PaddleFormers` before reinstalling it in editable mode with `pip install -e .` #### 5. Develop As you develop your new exciting feature, keep in mind that it should be covered by unit tests. All of our unit tests can be found under the `tests` directory. You can either modify existing unit test to cover the new feature, or create a new test from scratch. As you finish up the your code, you should make sure the test suite passes. You can run the tests impacted by your changes like this: ```bash pytest tests/.py ``` #### 6. Commit We utilizes [`pre-commit`](http://pre-commit.com/) (with [black](https://black.readthedocs.io/en/stable/), [isort](https://pycqa.github.io/isort/) and [flake8](https://flake8.pycqa.org/en/latest/) under the hood) to check the style of code and documentation in every commit. When you run run `git commit`, you will see something like the following: ``` ➜ (my-virtual-env) git commit -m "commiting my cool feature" black....................................................................Passed isort....................................................................Passed flake8...................................................................Passed check for merge conflicts................................................Passed check for broken symlinks............................(no files to check)Skipped detect private key.......................................................Passed fix end of files.....................................(no files to check)Skipped trim trailing whitespace.............................(no files to check)Skipped CRLF end-lines checker...............................(no files to check)Skipped CRLF end-lines remover...............................(no files to check)Skipped No-tabs checker......................................(no files to check)Skipped Tabs remover.........................................(no files to check)Skipped copyright_checker........................................................Passed ``` But most of the time things don't go so smoothly. When your code or documentation doesn't meet the standard, the `pre-commit` check will fail. ``` ➜ (my-virtual-env) git commit -m "commiting my cool feature" black....................................................................Passed isort....................................................................Failed - hook id: isort - files were modified by this hook Fixing examples/information_extraction/waybill_ie/run_ernie_crf.py flake8...................................................................Passed check for merge conflicts................................................Passed check for broken symlinks............................(no files to check)Skipped detect private key.......................................................Passed fix end of files.....................................(no files to check)Skipped trim trailing whitespace.............................(no files to check)Skipped CRLF end-lines checker...............................(no files to check)Skipped CRLF end-lines remover...............................(no files to check)Skipped No-tabs checker......................................(no files to check)Skipped Tabs remover.........................................(no files to check)Skipped copyright_checker........................................................Passed ``` But **don't panic**! Our tooling will fix most of the style errors automatically. Some errors will need to be addressed manually. Fortunately, the error messages are straight forward and the errors are usually simple to fix. After addressing the errors, you can run `git add ` and `git commit` again, which will trigger `pre-commit` again. Once the `pre-commit` checks pass, you are ready to push the code. [Google][http://google.com/] or [StackOverflow](https://stackoverflow.com/) are great tools to help you understand the code style errors. Don't worry if you still can't figure it out. You can commit with `git commit -m "style error" --no-verify` and we are happy to help you once you create a Pull Request. #### 7. Keep pulling An experienced Git user pulls from the official repo often -- daily or even hourly, so they notice conflicts with others work early, and it's easier to resolve smaller conflicts. ```bash git remote add upstream https://github.com/PaddlePaddle/PaddleFormers git pull upstream develop ``` #### 8. Push and file a pull request You can "push" your local work into your forked repo: ```bash git push origin my-cool-stuff ``` The push allows you to create a pull request, requesting owners of this [official repo](https://github.com/PaddlePaddle/PaddleFormers) to pull your change into the official one. To create a pull request, please follow [these steps](https://help.github.com/articles/creating-a-pull-request/). #### 9. Delete local and remote branches To keep your local workspace and your fork clean, you might want to remove merged branches: ```bash git push origin my-cool-stuff git checkout develop git pull upstream develop git branch -d my-cool-stuff ``` ## Code Review - Please feel free to ping your reviewers by @-mentioning the in the Pull Request. Please do this after your pull request passes the CI. - Please answer reviewers' every comment. If you are to follow the comment, please write "Done"; Otherwise, please start a discussion under the comment. - If you don't want your reviewers to get overwhelmed by email notifications, you might reply their comments by [in a batch](https://help.github.com/articles/reviewing-proposed-changes-in-a-pull-request/). ================================================ FILE: .github/ISSUE_TEMPLATE/ask-question.yml ================================================ name: 🐛 Ask Question description: 请描述您使用PaddleFormers时遇到的问题 title: "[Question]: " labels: - question body: - type: markdown attributes: value: > #### 你可以在这里提出一个使用/咨询问题,提问之前请确保: - 1)已经百度/谷歌搜索过你的问题,但是没有找到解答; - 2)已经在官网查询过[API文档](https://www.paddlepaddle.org.cn/documentation/docs/zh/api/index_cn.html)与[FAQ](https://www.paddlepaddle.org.cn/documentation/docs/zh/faq/index_cn.html),但是没有找到解答; - 3)已经在[历史issue](https://github.com/PaddlePaddle/Paddle/issues)中搜索过,没有找到同类issue或issue未被解答。 - type: textarea id: question attributes: label: 请提出你的问题 validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/bug-report.yml ================================================ name: 🐛 Bug Report description: PaddleFormers问题反馈 title: "[Bug]: " labels: bug body: - type: textarea id: environment attributes: label: 软件环境 description: | 请使用以下命令给出您本地Paddle相关包信息 ```sh pip list | grep paddle ``` value: | - paddlepaddle: - paddlepaddle-gpu: - paddleformers: render: Markdown validations: required: true - type: checkboxes id: dumplicated-problem attributes: label: 重复问题 description: 是否已在issues中搜索相关问题 options: - label: I have searched the existing issues required: true - type: textarea id: descripton attributes: label: 错误描述 description: 给出错误详细描述,以便能够更好的追踪相关问题 render: Markdown validations: required: true - type: textarea id: mvp-code attributes: label: 稳定复现步骤 & 代码 description: 请给出稳定复现该问题的步骤 & 代码,以便相关人员能够快速定位到具体问题。 validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/docs-report.yml ================================================ name: 🐛 Docs Report description: PaddleFormers文档反馈 title: "[Docs]: " labels: - documentation body: - type: textarea id: environment attributes: label: 软件环境 description: | 请使用以下命令给出您本地Paddle相关包信息 ```sh pip list | grep paddle ``` value: | - paddlepaddle: - paddlepaddle-gpu: - paddleformers: render: Markdown validations: required: true - type: textarea id: description attributes: label: 详细描述 description: 请详细描述您想要反馈的具体问题 render: Markdown validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/feature-request.yml ================================================ name: "\U0001F680 Feature request" description: 请详细描述您所需功能 labels: [ "feature" ] body: - type: textarea id: feature-request validations: required: true attributes: label: Feature request description: | 对特性提案的清晰而简明的描述。如果论文和代码存在,请提供链接。 - type: textarea id: motivation validations: required: true attributes: label: Motivation description: | 请概述这项建议的动机。您的特性要求与问题有关吗? - type: textarea id: contribution validations: required: true attributes: label: Your contribution description: | Is there any way that you could help, e.g. by submitting a PR? Make sure to read the CONTRIBUTING.MD [readme](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md) ================================================ FILE: .github/ISSUE_TEMPLATE/new-model.yaml ================================================ name: "\U0001F31F 添加新模型" description: 请为新模型提交一份说明 labels: [ "New model" ] body: - type: textarea id: description-request validations: required: true attributes: label: 简要描述 description: | 请简要描述模型的类型、解决的问题等。 - type: checkboxes id: information-tasks attributes: label: 是否已开源 options: - label: 已开源 - label: 未开源 - type: textarea id: additional-info attributes: label: 模型详细信息 description: | 请给出新模型相关信息,如论文地址、现存代码地址等。 ================================================ FILE: .github/ISSUE_TEMPLATE/others.yml ================================================ name: 🧩 其他 Others description: 提出其他问题。 labels: [others] body: - type: markdown attributes: value: > #### 你可以在这里提出任何前面几类模板不适用的问题,包括但不限于:优化性建议、框架使用体验反馈、版本兼容性问题、报错信息不清楚等。 - type: textarea id: others attributes: label: 问题描述 validations: required: true - type: markdown attributes: value: > 感谢你的贡献 🎉! ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ #### Before submitting - [ ] Lint code. If there are lint issues, please format the code first. ```shell # Install and register `pre-commit` in the project folder pip install pre-commit && pre-commit install # Process previous code files separately pre-commit run --file XXXX.py ``` - [ ] Add test cases into `tests` folder. If there are codecov issues, please add tests cases first. ### PR types ### PR changes ### Description ================================================ FILE: .github/actions/rerun-workflow/action.yml ================================================ name: 'Rerun Workflow' description: 'Re-run GitHub Actions workflow for a given Pull Request' inputs: GITHUB_TOKEN: description: 'GitHub token with repo scope' required: true OWNER: description: 'Repository owner' required: true REPO: description: 'Repository name' required: true PR_ID: description: 'Pull Request ID' required: true JOB_NAME: description: 'Job name to rerun' required: true runs: using: 'composite' steps: - run: bash ./.github/actions/rerun-workflow/rerun.sh shell: bash env: GITHUB_TOKEN: ${{ inputs.GITHUB_TOKEN }} OWNER: ${{ inputs.OWNER }} REPO: ${{ inputs.REPO }} PR_ID: ${{ inputs.PR_ID }} JOB_NAME: ${{ inputs.JOB_NAME }} ================================================ FILE: .github/actions/rerun-workflow/rerun.sh ================================================ # Copyright (c) 2025 PaddleFormers Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. set -e COMMIT_SHA=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_ID" | jq -r '.head.sha') echo "Commit SHA: $COMMIT_SHA" response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/actions/runs?head_sha=$COMMIT_SHA&per_page=100") echo "Response: $response" run_ids=$(echo "$response" | jq -r '.workflow_runs[].id') if [ -n "$run_ids" ]; then echo "Found run_ids for commit $COMMIT_SHA: $run_ids" for run_id in $run_ids; do if [ "$JOB_NAME" = "all-failed" ]; then echo "Rerunning all failed jobs for run_id: $run_id" rerun_response=$(curl -X POST -s -w "%{http_code}" -o /dev/null \ -H "Accept: application/vnd.github.v3+json" \ -H "Authorization: Bearer $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/actions/runs/$run_id/rerun-failed-jobs") if [ "$rerun_response" -eq 201 ]; then echo "Successfully requested rerun for all blocked jobs in run_id: $run_id" else echo "Failed to request rerun for run_id: $run_id with status code $rerun_response" fi else jobs_response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/actions/runs/$run_id/jobs") echo "Jobs Response for run_id $run_id: $jobs_response" # if [[ "$JOB_NAME" == *"bypass"* ]]; then block_jobs=$(echo "$jobs_response" | jq -r --arg job_name "$JOB_NAME" \ '.jobs[] | select(.name == $job_name) | .id') # else # block_jobs=$(echo "$jobs_response" | jq -r --arg job_name "$JOB_NAME" \ # '.jobs[] | select(.name == $job_name and .conclusion != "success") | .id') # fi if [ -n "$block_jobs" ]; then echo "Found block jobs for run_id $run_id: $block_jobs" for job_id in $block_jobs; do echo "Rerunning job_id: $job_id" curl -X POST -H "Accept: application/vnd.github.v3+json" \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/actions/jobs/$job_id/rerun" done else echo "No block jobs found for run_id $run_id with name $JOB_NAME." fi fi done else echo "No matching workflow runs found for commit $COMMIT_SHA." exit 1 fi ================================================ FILE: .github/codecov.yml ================================================ codecov: notify: wait_for_ci: false coverage: status: project: default: target: 30% # overall project Coverage threshold: 1% # Allow the coverage to drop by 1%, and posting a success status. patch: default: target: 75% # lines adjusted Coverage < 60% CI will fail ================================================ FILE: .github/workflows/_clone_linux.yml ================================================ name: PaddleFormers Code Clone description: "PaddleFormers clone and upload" on: workflow_call: inputs: bos_dir: type: string required: false default: 'PaddleFormers' outputs: repo_archive_url: description: "Compressed source code archive." value: ${{ jobs.code-clone.outputs.repo_archive_url }} jobs: code-clone: runs-on: group: HK-Clone outputs: repo_archive_url: ${{ steps.set_output.outputs.repo_archive_url }} steps: - name: Clone PaddleFormers uses: actions/checkout@v4 with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.ref || github.ref_name }} submodules: 'recursive' fetch-depth: 1000 - name: Merge PR (if needed) if: ${{ github.event_name == 'pull_request' }} run: | git config --global user.name "PaddleFormersCI" git config --global user.email "paddleformers_ci@example.com" echo "Fetching and merging PR..." git fetch origin pull/${{ github.event.pull_request.number }}/head:pr/${{ github.event.pull_request.number }} git merge --no-ff pr/${{ github.event.pull_request.number }} echo "PR Branch log " git log --oneline -n 5 pr/${{ github.event.pull_request.number }} - uses: actions/setup-python@v5 with: python-version: '3.10' - name: Code Info Show and Upload id: set_output env: AK: paddle SK: paddle run: | git config --unset http.https://github.com/.extraheader git submodule foreach --recursive sh -c "git config --local --unset-all 'http.https://github.com/.extraheader'" git submodule foreach --recursive sh -c "git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'" echo "Current HEAD Log:" git log --oneline -n 5 ls cd .. tar -zcf PaddleFormers.tar.gz PaddleFormers if [[ "${{ github.event_name }}" == "pull_request" ]];then commit_id=${{ github.event.pull_request.head.sha }} pr_num=${{ github.event.pull_request.number }} target_path=paddle-github-action/PR/PaddleFormers/${pr_num}/${commit_id} elif [[ "${{ github.ref_type }}" == "tag" ]]; then commit_id=${{ github.sha }} tag_name=${{ github.ref_name }} target_path=paddle-github-action/TAG/PaddleFormers/${tag_name}/${commit_id} else commit_id=${{ github.sha }} branch_name=${{ github.ref_name }} target_path=paddle-github-action/BRANCH/PaddleFormers/${branch_name}/${commit_id} fi wget -O bos_tools.py -q --no-proxy --no-check-certificate https://paddle-qa.bj.bcebos.com/CodeSync/develop/PaddlePaddle/PaddleTest/tools/bos_tools.py push_file=$(realpath bos_tools.py) python -m pip install bce-python-sdk==0.9.29 ls python ${push_file} PaddleFormers.tar.gz ${target_path} target_path_stripped="${target_path#paddle-github-action/}" REPO_ARCHIVE_URL=https://paddle-github-action.bj.bcebos.com/${target_path_stripped}/PaddleFormers.tar.gz echo "repo_archive_url=${REPO_ARCHIVE_URL}" >> $GITHUB_OUTPUT ================================================ FILE: .github/workflows/_xpu_ci_test.yml ================================================ name: xpu_ci_test on: workflow_call: inputs: DOCKER_IMAGE: description: "Build Images" required: true type: string default: "ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddleqa:xpu-ubuntu2204-x86_64-gcc123-py310" PADDLEFORMERS_ARCHIVE_URL: description: "URL of the compressed PaddleFormers code archive." required: true type: string PADDLE_WHL_URL: description: "Paddle Wheel Package URL" required: false type: string default: "" MODEL_PATH: description: "MODEL Dir Use" required: true type: string default: "" jobs: run_xpu_cases: runs-on: [self-hosted, XPU-P800-8Cards] timeout-minutes: 60 steps: - name: Print current runner name run: | echo "Current runner name: ${{ runner.name }}" - name: Code Prepare shell: bash env: docker_image: ${{ inputs.DOCKER_IMAGE }} formers_archive_url: ${{ inputs.PADDLEFORMERS_ARCHIVE_URL }} model_path: ${{ inputs.MODEL_PATH }} run: | set -x REPO="https://github.com/${{ github.repository }}.git" FULL_REPO="${{ github.repository }}" REPO_NAME="${FULL_REPO##*/}" BASE_BRANCH="${{ github.base_ref }}" # 由于ci机器网络问题 暂时屏蔽pull命令 # docker pull ${docker_image} # Clean the repository directory before starting docker run --rm --net=host -v $(pwd):/workspace -w /workspace \ -e "REPO_NAME=${REPO_NAME}" \ ${docker_image} /bin/bash -c ' CLEAN_RETRIES=3 CLEAN_COUNT=0 while [ $CLEAN_COUNT -lt $CLEAN_RETRIES ]; do echo "Attempt $((CLEAN_COUNT+1)) to remove ${REPO_NAME}* ..." rm -rf "${REPO_NAME}"* || true sleep 2 # Check if anything matching ${REPO_NAME}* still exists if ! ls "${REPO_NAME}"* >/dev/null 2>&1; then echo "All ${REPO_NAME}* removed successfully" break fi CLEAN_COUNT=$((CLEAN_COUNT + 1)) done if ls "${REPO_NAME}"* >/dev/null 2>&1; then echo "ERROR: Failed to clean ${REPO_NAME}* after multiple attempts" ls -ld "${REPO_NAME}"* exit 1 fi ' wget -q --no-proxy ${formers_archive_url} tar -xf PaddleFormers.tar.gz rm -rf PaddleFormers.tar.gz cd PaddleFormers git config --global user.name "PaddleFormersCI" git config --global user.email "paddleformers_ci@example.com" git log -n 3 --oneline - name: Run CI unittest env: docker_image: ${{ inputs.DOCKER_IMAGE }} formers_archive_url: ${{ inputs.PADDLEFORMERS_ARCHIVE_URL }} model_path: ${{ inputs.MODEL_PATH }} run: | runner_name="${{ runner.name }}" last_char="${runner_name: -1}" PARENT_DIR=$(dirname "$WORKSPACE") echo "PARENT_DIR:$PARENT_DIR" docker run --rm --net=host --cap-add=SYS_PTRACE --privileged --shm-size=64G \ -v $(pwd):/workspace -w /workspace \ -v "/home/suijiaxin/model:/model" \ -v "/home/suijiaxin/images:/images" \ -e "MODEL_PATH=${model_path}" \ -e "PADDLEFORMERS_ARCHIVE_URL=${formers_archive_url}" \ -e "PADDLE_WHL_URL=${PADDLE_WHL_URL}" \ -e "http_proxy=$(git config --global --get http.proxy)" \ -e "https_proxy=$(git config --global --get https.proxy)" \ -e "no_proxy=bcebos.com,mirrors.tuna.tsinghua.edu.cn,127.0.0.1,localhost" \ ${docker_image} /bin/bash -c ' # 重启XPU卡 echo "重启XPU卡..." xpu-smi -r -i 0,1,2,3,4,5,6,7 xpu-smi set -e git config --global --add safe.directory /workspace/PaddleFormers cd PaddleFormers python -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple python -m pip install -r requirements.txt echo "安装PaddlePaddle..." # 针对不同分支和tag使用不同的PaddlePaddle安装包 python -m pip uninstall paddlepaddle-xpu paddleformers -y python -m pip uninstall librosa -y python -m pip install --pre paddlepaddle-xpu -i https://www.paddlepaddle.org.cn/packages/nightly/xpu-p800/ echo "安装PaddleFormers..." python -m pip install -e . echo "============================安装测试依赖============================" python -m pip install pytest python -m pip install pytest-timeout unset http_proxy unset https_proxy echo "============================开始运行pytest测试============================" ln -s /model baidu ln -s /images tests/fixtures/dummy/sft-vl/ export XPU_VISIBLE_DEVICES="0,1,2,3" python -m pytest -v -s --tb=short scripts/xpu_ci/ exit_code=$? if [ $exit_code -eq 0 ]; then echo "============================4卡cases测试通过!============================" else echo "============================4卡cases测试失败,请检查日志!============================" exit $exit_code fi ' ================================================ FILE: .github/workflows/ce-build-ci-workflow.yml ================================================ name: Build CI Images on: schedule: - cron: "0 22 * * *" # every day at 06:00 Beijing time (UTC+8) workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: image_base: "ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:cuda126-dev" jobs: build-ci-images-test: name: build-ci-images-test if: github.ref == 'refs/heads/develop' uses: ./.github/workflows/ce-build-images.yml with: flag_build: test runner: ernie-8gpu-2 image_base: ${{ env.image_base }} test-ci-images: name: test-ci-images needs: build-ci-images-test if: ${{ needs.build-ci-images-test.outputs.flag_downstream == 'true' }} uses: ./.github/workflows/unittest-gpu.yml with: runner: ernie-8gpu-2 image_name: ${{ needs.build-ci-images-test.outputs.image_name }} clean-ci-image: name: clean-ci-image needs: [build-ci-images-test, test-ci-images] if: always() runs-on: [self-hosted, ernie-8gpu-2] steps: - name: Remove Dangling Image run: docker images -f "dangling=true" -q | xargs -r docker rmi -f update-ci-images-1: name: update-ci-images-1 needs: [build-ci-images-test, test-ci-images] uses: ./.github/workflows/ce-build-images.yml with: flag_build: update runner: ernie-8gpu-1 image_base: ${{ env.image_base }} update-ci-images-2: name: update-ci-images-2 needs: [build-ci-images-test, test-ci-images] uses: ./.github/workflows/ce-build-images.yml with: flag_build: update runner: ernie-8gpu-2 image_base: ${{ env.image_base }} ================================================ FILE: .github/workflows/ce-build-images.yml ================================================ name: Build CI Images For Test on: workflow_call: inputs: flag_build: # test||update required: true type: string runner: required: true type: string image_base: required: true type: string env: TASK: PaddleFormers-build-CI-image jobs: build-images: name: build-images runs-on: ${{ inputs.runner }} outputs: flag_downstream: ${{ steps.build_image_flags.outputs.flag_downstream }} image_name: ${{ steps.build_image_flags.outputs.image_name }} steps: - name: Run Container env: work_dir: ${{ github.workspace }} IMAGE_BASE: ${{ inputs.image_base }} run: | container_name=${TASK}-$(date +%Y%m%d-%H%M%S) echo "container_name=${container_name}" >> ${{ github.env }} docker_image="${IMAGE_BASE}" echo "docker_image=${docker_image}" DOCKER_VER=$(docker version --format '{{.Server.Version}}' | cut -d. -f1,2) if (( $(echo "$DOCKER_VER < 19.03" | bc -l) )); then GPU_OPTION="--runtime=nvidia" else GPU_OPTION="--gpus all" fi echo "DOCKER_VER=${DOCKER_VER}" echo "GPU_OPTION=${GPU_OPTION}" docker run -d -t ${GPU_OPTION} --name ${container_name} --net=host -v /dev/shm:/dev/shm --shm-size=32G \ -v $work_dir/../../..:$work_dir/../../.. \ -v $work_dir:/workspace \ -v /home/.cache/pip:/home/.cache/pip \ -e work_dir \ -e no_proxy \ -w /workspace --privileged ${docker_image} - name: Download Code env: work_dir: ${{ github.workspace }} run: | docker exec -t ${container_name} /bin/bash -c ' rm -rf * .[^.]* echo "Downloading PaddleFormers.tar.gz" wget -q --no-proxy https://paddleformers.bj.bcebos.com/wheels/PaddleFormers.tar.gz --no-check-certificate echo "Extracting PaddleFormers.tar.gz" tar xf PaddleFormers.tar.gz && rm -rf PaddleFormers.tar.gz source $work_dir/../../../proxy cd PaddleFormers git config --global user.name "PaddleCI" git config --global user.email "paddle_ci@example.com" git pull git submodule update --init --recursive --force git log --pretty=oneline -10 unset http_proxy && unset https_proxy ' - name: Write Dockerfile Inline run: | cat < Dockerfile FROM ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:cuda126-dev # RUN apt-get update && \ # apt-get install -y openjdk-11-jdk && \ # rm -rf /var/lib/apt/lists/* # ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 # ENV PATH="$JAVA_HOME/bin:${PATH}" RUN python -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple RUN python -m pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn COPY PaddleFormers/ /tmp/paddleformers/ WORKDIR /tmp/paddleformers RUN python -m pip install -r requirements.txt --progress-bar off RUN python -m pip install -r tests/requirements.txt --progress-bar off RUN python setup.py bdist_wheel RUN python -m pip install "$(ls -t dist/*.whl | head -1)[paddlefleet]" --progress-bar off WORKDIR / RUN rm -rf /tmp/paddleformers RUN python -m pip install opt_einsum --progress-bar off # for paddle EOF - name: Build Docker Image id: build_image_flags env: work_dir: ${{ github.workspace }} flag_build: ${{ inputs.flag_build }} image_base: ${{ inputs.image_base }} run: | flag_downstream=false if [[ "${flag_build}" == "test" ]]; then flag_downstream=true image_name="${image_base}-test-$(date +%Y%m%d-%H%M%S)" docker build --network host -t ${image_name} . elif [[ "${flag_build}" == "update" ]]; then flag_downstream=false image_name="${image_base}-latest" # remove old bak docker images --format '{{.Repository}}:{{.Tag}}' | grep 'bak' || true | while read img; do echo "Removing image $img ..." docker rmi "$img" || true done # mv old latest to bak docker images --format '{{.Repository}}:{{.Tag}}' | grep 'latest' || true | while read img; do echo "Tagging $img as ${image_base}-bak ..." docker tag "$img" "${image_base}-bak" docker rmi "$img" || true done # mv test image to latest or new build latest if docker images --format '{{.Repository}}:{{.Tag}}' | grep 'test'; then echo "mv test image to latest, no need to build" docker tag "$img" "${image_name}" docker rmi "$img" || true else docker build --network host -t ${image_name} . fi else echo "Invalid flag_build: ${flag_build}" exit 1 fi echo "flag_downstream=${flag_downstream}" >> "$GITHUB_OUTPUT" echo "image_name=${image_name}" >> "$GITHUB_OUTPUT" - name: Terminate And Delete the Container if: always() run: | docker rm -f ${container_name} 2>/dev/null || true ================================================ FILE: .github/workflows/ce-build-whl.yml ================================================ name: Build Whl CE on: push: branches: - develop - release/* env: BRANCH: ${{ github.ref_name }} COMMIT_ID: ${{ github.sha }} TASK: PaddleFormers-CE-${{ github.sha }}-build CE_name: build-ce no_proxy: "localhost,bj.bcebos.com,su.bcebos.com,bcebos.com,apiin.im.baidu.com,gitee.com,aliyun.com,.baidu.com,.tuna.tsinghua.edu.cn" defaults: run: shell: bash jobs: build-ce: name: build-ce runs-on: [self-hosted, paddleformers] steps: - name: Determine Image Name run: | echo "IMAGE_NAME=ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:cuda126-dev-latest" >> "$GITHUB_ENV" - name: Run Container env: work_dir: ${{ github.workspace }} FLAGS_dynamic_static_unified_comm: "True" python_version: "3.10" paddle: https://paddle-qa.bj.bcebos.com/paddle-pipeline/Develop-GpuAll-LinuxCentos-Gcc11-Cuda126-Cudnn95-Trt105-Py310-Compile/latest/paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl run: | container_name=${TASK}-$(date +%Y%m%d-%H%M%S) echo "container_name=${container_name}" >> "$GITHUB_ENV" DOCKER_VER=$(docker version --format '{{.Server.Version}}' | cut -d. -f1,2) if (( $(echo "$DOCKER_VER < 19.03" | bc -l) )); then GPU_OPTION="--runtime=nvidia" else GPU_OPTION="--gpus all" fi echo "DOCKER_VER=${DOCKER_VER}" echo "GPU_OPTION=${GPU_OPTION}" docker run -d -t ${GPU_OPTION} --name ${container_name} --net=host -v /dev/shm:/dev/shm --shm-size=32G \ -v $work_dir/../../..:$work_dir/../../.. \ -v $work_dir:/workspace \ -v /home/.cache/pip:/home/.cache/pip \ -v /home/paddle-1/models/:/home/models/ \ -e "BRANCH=$BRANCH" \ -e "COMMIT_ID=$COMMIT_ID" \ -e work_dir \ -e ce_scripts \ -e no_proxy \ -e CE_name \ -e paddle \ -e FLAGS_dynamic_static_unified_comm \ -e python_version \ -w /workspace --privileged $IMAGE_NAME - name: Download Code run: | docker exec -t $container_name /bin/bash -c ' rm -rf * .[^.]* echo "Downloading PaddleFormers.tar" wget -q --no-proxy https://paddle-qa.bj.bcebos.com/CodeSync/develop/PaddleFormers.tar --no-check-certificate echo "Extracting PaddleFormers.tar" tar xf PaddleFormers.tar && rm -rf PaddleFormers.tar source $work_dir/../../../proxy cd PaddleFormers git config --global user.name "PaddleCE" git config --global user.email "paddle_ce@example.com" git pull git submodule update --init --recursive --force git remote add upstream https://github.com/PaddlePaddle/PaddleFormers.git echo "Checking out ${BRANCH}..." git fetch upstream ${BRANCH}:${BRANCH} git checkout ${BRANCH} git log --pretty=oneline -10 ' - name: Test run: | docker exec -t $container_name /bin/bash -c ' ldconfig pip config set global.cache-dir "/home/.cache/pip" set -e cd /workspace/PaddleFormers && git config --global --add safe.directory $PWD bash scripts/dependence/build.sh ' - name: Upload Products if: always() run: | docker exec -t $container_name /bin/bash -c ' cd /workspace/PaddleFormers/upload cp /home/models/bos/bos_tools.py ./ for FILE in /workspace/PaddleFormers/upload/*; do file=$(basename "$FILE") python bos_tools.py $file paddle-whl/nightly/cu126/paddleformers/ echo "$file: https://paddle-whl.bj.bcebos.com/nightly/cu126/paddleformers/$file" done ' - name: Terminate And Delete the Container if: always() run: | docker rm -f $container_name 2>/dev/null || true ================================================ FILE: .github/workflows/ce-deadlink.yml ================================================ name: Deadlink CE on: schedule: - cron: "0 8 * * 6" # every Saturday at 16:00 workflow_dispatch: # allow to manually trigger the workflow concurrency: group: deadlink-${{ github.workflow }} cancel-in-progress: true env: COMMIT_ID: ${{ github.event.pull_request.head.sha }} TASK: PaddleFormers-CE-${{ github.event.pull_request.number }}-deadlink BRANCH: ${{ github.event.pull_request.base.ref }} CE_name: deadlink-ce no_proxy: "localhost,bj.bcebos.com,su.bcebos.com,bcebos.com,apiin.im.baidu.com,gitee.com,aliyun.com,.baidu.com,.tuna.tsinghua.edu.cn" defaults: run: shell: bash jobs: deadlink-ce: name: deadlink-ce if: github.ref == 'refs/heads/develop' runs-on: [self-hosted, paddleformers] steps: - name: Determine Image Name run: | echo "IMAGE_NAME=ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:cuda126-dev-latest" >> "$GITHUB_ENV" - name: Run Container env: work_dir: ${{ github.workspace }} FLAGS_dynamic_static_unified_comm: "True" python_version: "3.10" paddle_whl: https://paddle-qa.bj.bcebos.com/paddle-pipeline/Develop-GpuAll-LinuxCentos-Gcc11-Cuda126-Cudnn95-Trt105-Py310-Compile/latest/paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl run: | container_name=${TASK}-$(date +%Y%m%d-%H%M%S) echo "container_name=${container_name}" >> "$GITHUB_ENV" DOCKER_VER=$(docker version --format '{{.Server.Version}}' | cut -d. -f1,2) if (( $(echo "$DOCKER_VER < 19.03" | bc -l) )); then GPU_OPTION="--runtime=nvidia" else GPU_OPTION="--gpus all" fi echo "DOCKER_VER=${DOCKER_VER}" echo "GPU_OPTION=${GPU_OPTION}" docker run -d -t ${GPU_OPTION} --name ${container_name} --net=host -v /dev/shm:/dev/shm --shm-size=32G \ -v $work_dir/../../..:$work_dir/../../.. \ -v $work_dir:/workspace \ -v /home/.cache/pip:/home/.cache/pip \ -e BRANCH \ -e COMMIT_ID \ -e work_dir \ -e ce_scripts \ -e no_proxy \ -e CE_name \ -e paddle_whl \ -e FLAGS_dynamic_static_unified_comm \ -e python_version \ -w /workspace --privileged $IMAGE_NAME - name: Download Code run: | docker exec -t $container_name /bin/bash -c ' rm -rf * .[^.]* echo "Downloading PaddleFormers.tar" wget -q --no-proxy https://paddle-qa.bj.bcebos.com/CodeSync/develop/PaddleFormers.tar --no-check-certificate echo "Extracting PaddleFormers.tar" tar xf PaddleFormers.tar && rm -rf PaddleFormers.tar source $work_dir/../../../proxy cd PaddleFormers git config --global user.name "PaddleCE" git config --global user.email "paddle_ce@example.com" git pull git submodule update --init --recursive --force git log --pretty=oneline -10 cd - echo "Downloading PaddleTest.tar" wget -q --no-proxy https://xly-devops.bj.bcebos.com/PaddleTest/PaddleTest.tar.gz --no-check-certificate tar xf PaddleTest.tar.gz cp -r PaddleTest/models/PaddleNLP/deadlink/* ./ ' - name: Test run: | docker exec -t $container_name /bin/bash -c ' ldconfig pip config set global.cache-dir "/home/.cache/pip" set -e python -m pip install beautifulsoup4 openpyxl source $work_dir/../../../proxy bash run.sh PaddleFormers develop liujie44@baidu.com "PaddleFormers Broken Link Check Summary Report" ' - name: Upload Logs if: always() env: home_path: ${{ github.workspace }}/../../.. bos_file: ${{ github.workspace }}/../../../bos/BosClient.py run: | docker exec -t $container_name /bin/bash -c ' if [ ! -f "${{ env.bos_file }}" ]; then wget -q --no-proxy -O ${{ env.home_path }}/bos_new.tar.gz https://xly-devops.bj.bcebos.com/home/bos_new.tar.gz --no-check-certificate mkdir ${{ env.home_path }}/bos tar xf ${{ env.home_path }}/bos_new.tar.gz -C ${{ env.home_path }}/bos fi bos_prefix="schedule/$(date +%Y%m%d)" cd /workspace/result for FILE in /workspace/result/*; do file=$(basename "$FILE") python ${{ env.bos_file }} $file paddle-github-action/PR/PaddleFormers/deadlink/${bos_prefix}/logs echo "$file: https://paddle-github-action.bj.bcebos.com/PR/PaddleFormers/deadlink/${bos_prefix}/logs/$file" done ' - name: Terminate And Delete the Container if: always() run: | docker rm -f $container_name 2>/dev/null || true ================================================ FILE: .github/workflows/ce-unittest-gpu.yml ================================================ name: Unittest GPU CE on: schedule: - cron: "0 1 * * *" # every day at 09:00 Beijing time (UTC+8) workflow_dispatch: # allow to manually trigger the workflow inputs: paddle_whl: description: "paddle_whl" required: false default: "https://paddle-qa.bj.bcebos.com/paddle-pipeline/Develop-GpuAll-LinuxCentos-Gcc11-Cuda126-Cudnn95-Trt105-Py310-Compile/latest/paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl" type: string repo_branch: description: "repo_branch" required: false type: string concurrency: group: unittest-ce-${{ github.workflow }} cancel-in-progress: true env: COMMIT_ID: ${{ github.event.pull_request.head.sha }} TASK: PaddleFormers-CE-unittest-gpu ce_scripts: workspace/PaddleFormers/scripts/unit_test BRANCH: ${{ github.event.pull_request.base.ref }} AGILE_COMPILE_BRANCH: ${{ github.event.pull_request.base.ref }} CE_name: unittest-gpu-ce no_proxy: "localhost,bj.bcebos.com,su.bcebos.com,bcebos.com,apiin.im.baidu.com,gitee.com,aliyun.com,.baidu.com,.tuna.tsinghua.edu.cn" defaults: run: shell: bash jobs: unittest-gpu-ce: name: unittest-gpu-ce runs-on: [self-hosted, ernie-8gpu, distribute] steps: - name: Determine Image Name run: | echo "IMAGE_NAME=ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:cuda126-dev-latest" >> "$GITHUB_ENV" - name: Run Container env: work_dir: ${{ github.workspace }} FLAGS_dynamic_static_unified_comm: "True" python_version: "3.10" paddle_whl: ${{ github.event.inputs.paddle_whl || 'https://paddle-qa.bj.bcebos.com/paddle-pipeline/Develop-GpuAll-LinuxCentos-Gcc11-Cuda126-Cudnn95-Trt105-Py310-Compile/latest/paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl' }} repo_branch: ${{ github.event.inputs.repo_branch || '' }} run: | container_name=${TASK}-$(date +%Y%m%d-%H%M%S) echo "container_name=${container_name}" >> "$GITHUB_ENV" echo "Workspace path: ${{ github.workspace }}" DOCKER_VER=$(docker version --format '{{.Server.Version}}' | cut -d. -f1,2) if (( $(echo "$DOCKER_VER < 19.03" | bc -l) )); then GPU_OPTION="--runtime=nvidia" else GPU_OPTION="--gpus all" fi echo "DOCKER_VER=${DOCKER_VER}" echo "GPU_OPTION=${GPU_OPTION}" docker run -d -t --name ${container_name} --net=host -v /dev/shm:/dev/shm --shm-size=32G \ -v $work_dir/../../..:$work_dir/../../.. \ -v $work_dir:workspace/ \ -v /home/.cache/pip:/home/.cache/pip \ -v /home/paddle-1/models/:/home/models/ \ -e PF_HOME=/home/models/ \ -e BRANCH \ -e AGILE_COMPILE_BRANCH \ -e COMMIT_ID \ -e work_dir \ -e ce_scripts \ -e no_proxy \ -e CE_name \ -e paddle_whl \ -e repo_branch \ -e FLAGS_dynamic_static_unified_comm \ -e python_version \ -e HF_PROXY_PATH=$work_dir/../../../proxy_huggingface \ -e AISTUDIO_PROXY_PATH=$work_dir/../../../proxy_aistudio \ -e "HF_DATASETS_CACHE=$work_dir/../../../paddlenlp/huggingface/datasets" \ -e "TRANSFORMERS_CACHE=$work_dir/../../../paddlenlp/huggingface" \ -w workspace/ ${GPU_OPTION} --privileged $IMAGE_NAME - name: Download Code run: | docker exec -t $container_name /bin/bash -c ' rm -rf * .[^.]* echo "Downloading PaddleFormers.tar" wget -q --no-proxy https://paddle-qa.bj.bcebos.com/CodeSync/develop/PaddleFormers.tar --no-check-certificate echo "Extracting PaddleFormers.tar" tar xf PaddleFormers.tar && rm -rf PaddleFormers.tar source $work_dir/../../../proxy cd PaddleFormers git config --global user.name "PaddleCE" git config --global user.email "paddle_ce@example.com" if [ -n "$repo_branch" ]; then echo "Switching to branch: $repo_branch" git fetch origin $repo_branch git checkout $repo_branch || git checkout -b $repo_branch origin/$repo_branch git pull else echo "No repo_branch provided, just pulling latest changes" git pull fi git submodule update --init --recursive --force git log --pretty=oneline -10 ' - name: Test run: | docker exec -t $container_name /bin/bash -c ' ldconfig pip config set global.cache-dir "/home/.cache/pip" set -e rm -rf /root/.cache/aistudio/ cd workspace/PaddleFormers && git config --global --add safe.directory $PWD source $work_dir/../../../proxy source $work_dir/../../../AISTUDIO_ACCESS_TOKEN echo "work_dir = ${work_dir}" cp -r ${work_dir}/../../../models ./models echo "Check whether the local model file exists:" ls -l ./models bash scripts/unit_test/ci_unittest.sh ${paddle_whl} true ' - name: Upload Allure-reports & Logs if: always() env: home_path: ${{ github.workspace }}/../../.. bos_file: ${{ github.workspace }}/../../../bos/BosClient.py allure_file: ${{ github.workspace }}/../../../allure-2.19.0/bin/allure run: | docker exec -t $container_name /bin/bash -c ' if [ ! -f "${{ env.bos_file }}" ]; then wget -q --no-proxy -O ${{ env.home_path }}/bos_new.tar.gz https://xly-devops.bj.bcebos.com/home/bos_new.tar.gz --no-check-certificate mkdir ${{ env.home_path }}/bos tar xf ${{ env.home_path }}/bos_new.tar.gz -C ${{ env.home_path }}/bos fi # if [ ! -f "${{ env.allure_file }}" ]; then # wget -q --no-proxy -O ${{ env.home_path }}/allure-2.19.0.zip https://xly-devops.bj.bcebos.com/tools/allure-2.19.0.zip --no-check-certificate # unzip -q ${{ env.home_path }}/allure-2.19.0.zip # fi bos_prefix="schedule/github-ce-$(date +%Y%m%d)" # # coverage.xml # cd /workspace/PaddleFormers # python ${{ env.bos_file }} coverage.xml paddle-github-action/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs # echo "cov-report: https://paddle-github-action.bj.bcebos.com/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs/coverage.xml" # logs cd /workspace/PaddleFormers/unittest_logs for FILE in /workspace/PaddleFormers/unittest_logs/*; do file=$(basename "$FILE") python ${{ env.bos_file }} $file paddle-github-action/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs echo "$file: https://paddle-github-action.bj.bcebos.com/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs/$file" done # cd /workspace/PaddleFormers/ # ${{ env.allure_file }} generate result -o report # tar -czf products.tar.gz report unittest_logs # python ${{ env.bos_file }} products.tar.gz paddle-github-action/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs # echo "report: https://paddle-github-action.bj.bcebos.com/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs/products.tar.gz" ' - name: Terminate And Delete the Container if: always() run: | docker rm -f $container_name 2>/dev/null || true ================================================ FILE: .github/workflows/check-release-pr.yaml ================================================ name: Check Release PR on: pull_request: branches: - 'release/*' types: - opened - edited - synchronize jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Check if PR description contains dev PR link env: PR_BODY: ${{ github.event.pull_request.body }} run: | echo "Checking PR body: $PR_BODY" if ! echo "$PR_BODY" | grep -Eqi "dev.*#([0-9]+)"; then echo "::error::PR must include a link to merged PR in dev branch (e.g., 'Merged in dev: #1234')" exit 1 fi echo "Dev PR link found" - name: Check the referenced PR is merged into dev env: GH_TOKEN: ${{ github.token }} run: | DEV_PR=$(echo "${{ github.event.pull_request.body }}" | grep -Eo "#[0-9]+" | head -1 | tr -d "#") echo "Found dev PR: $DEV_PR" if [ -z "$DEV_PR" ]; then echo "::error::No valid PR number found" exit 1 fi STATUS=$(gh pr view $DEV_PR --json state --jq .state) echo "Dev PR status: $STATUS" if [ "$STATUS" != "MERGED" ]; then echo "::error::The referenced dev PR (#$DEV_PR) is not merged yet" exit 1 fi echo "Dev PR merged. Validation completed." ================================================ FILE: .github/workflows/cherry-pick.yml ================================================ name: Cherry Pick on: pull_request_target: branches: [develop] types: [closed, labeled] permissions: contents: write pull-requests: write issues: write concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number }} cancel-in-progress: false jobs: cherry-pick: if: > github.event.pull_request.merged == true && ( github.event.action == 'labeled' || contains(join(github.event.pull_request.labels.*.name, ' '), 'cherry-pick') ) runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 persist-credentials: false - name: Cherry Pick env: GH_TOKEN: ${{ secrets.CHERRY_PICK_BOT_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} PR_TITLE: ${{ github.event.pull_request.title }} PR_BODY: ${{ github.event.pull_request.body }} PR_AUTHOR: ${{ github.event.pull_request.user.login }} MERGE_COMMIT_SHA: ${{ github.event.pull_request.merge_commit_sha }} BOT_USERNAME: ShigureNyako BOT_EMAIL: shigure_nyako@outlook.com REPO_NAME: ShigureNyako/PaddleFormers run: | # Function to post comment post_comment() { gh pr comment "$PR_NUMBER" --body "$1" } # Configure git for the original author echo "Fetching author info for $PR_AUTHOR..." AUTHOR_INFO=$(gh api "/users/$PR_AUTHOR" --jq '{email: .email, name: .name}') AUTHOR_EMAIL=$(echo "$AUTHOR_INFO" | jq -r '.email') AUTHOR_NAME=$(echo "$AUTHOR_INFO" | jq -r '.name') if [ "$AUTHOR_EMAIL" = "null" ] || [ -z "$AUTHOR_EMAIL" ]; then AUTHOR_EMAIL="${PR_AUTHOR}@users.noreply.github.com" echo "Author email not found, using default: $AUTHOR_EMAIL" fi if [ "$AUTHOR_NAME" = "null" ] || [ -z "$AUTHOR_NAME" ]; then AUTHOR_NAME="${PR_AUTHOR}" echo "Author name not found, using username: $AUTHOR_NAME" fi git config user.name "$AUTHOR_NAME" git config user.email "$AUTHOR_EMAIL" # Capture current SHA to return to later ORIGINAL_HEAD_SHA=$(git rev-parse HEAD) # Get labels LABELS=$(gh pr view "$PR_NUMBER" --json labels --jq '.labels[].name') if [ -z "$LABELS" ]; then echo "No labels found." exit 0 fi # Loop through labels while read -r label; do if [[ "$label" == cherry-pick:* ]]; then TARGET_BRANCH=$(echo "${label#cherry-pick:}" | xargs) if [ -z "$TARGET_BRANCH" ]; then echo "Empty target branch for label '$label', skipping." continue fi echo "Processing cherry-pick to $TARGET_BRANCH" # Check if target branch exists on remote if ! git ls-remote --exit-code --heads origin "$TARGET_BRANCH"; then echo "Target branch $TARGET_BRANCH does not exist." post_comment "❌ Cherry-pick failed: Target branch \`$TARGET_BRANCH\` does not exist." continue fi # Create a new branch for the cherry-pick NEW_BRANCH="cherry-pick/$PR_NUMBER/$TARGET_BRANCH" # Clean up local branch if it exists (from previous run) if git show-ref --verify --quiet "refs/heads/$NEW_BRANCH"; then git branch -D "$NEW_BRANCH" fi # Fetch the target branch and checkout a new branch from it git fetch origin "$TARGET_BRANCH" git checkout -b "$NEW_BRANCH" "origin/$TARGET_BRANCH" # Cherry pick # Try standard cherry-pick first (for squash merges or single commits) if git cherry-pick "$MERGE_COMMIT_SHA"; then echo "Cherry-pick successful." else echo "Standard cherry-pick failed, trying with -m 1 (for merge commits)..." git cherry-pick --abort if git cherry-pick -m 1 "$MERGE_COMMIT_SHA"; then echo "Cherry-pick with -m 1 successful." else echo "Cherry-pick failed." git cherry-pick --abort post_comment "❌ Cherry-pick failed: Conflicts detected when cherry-picking to \`$TARGET_BRANCH\`. Please resolve manually." # Cleanup git checkout "$ORIGINAL_HEAD_SHA" git branch -D "$NEW_BRANCH" continue fi fi # Push # Construct authenticated URL for the fork FORK_URL_AUTH="https://${BOT_USERNAME}:${GH_TOKEN}@github.com/${REPO_NAME}.git" echo "Pushing to fork..." git push "$FORK_URL_AUTH" "$NEW_BRANCH" --force # Create PR # If PR_TITLE starts with "[", don't insert an extra space. if [ "${PR_TITLE:0:1}" = "[" ]; then NEW_TITLE="[$TARGET_BRANCH]$PR_TITLE" else NEW_TITLE="[$TARGET_BRANCH] $PR_TITLE" fi NEW_BODY="$PR_BODY Cherry-pick of #$PR_NUMBER to \`$TARGET_BRANCH\`. Merged in dev: #$PR_NUMBER " # Prepare head ref for PR creation (owner:branch) HEAD_REF="${BOT_USERNAME}:${NEW_BRANCH}" # Check if PR already exists EXISTING_PR=$(gh pr list --base "$TARGET_BRANCH" --head "$NEW_BRANCH" --json url --jq '.[0].url') if [ -n "$EXISTING_PR" ]; then echo "PR already exists: $EXISTING_PR" post_comment "ℹ️ Cherry-pick PR already exists: $EXISTING_PR" else # Create PR using gh CLI, ignoring errors because of "Resource not accessible" false positives gh pr create --base "$TARGET_BRANCH" --head "$HEAD_REF" --title "$NEW_TITLE" --body "$NEW_BODY" || true # Wait a bit for eventual consistency sleep 2 # Search for the created PR CREATED_PR_URL=$(gh pr list --head "$NEW_BRANCH" --state all --json url --jq '.[0].url') if [ -n "$CREATED_PR_URL" ]; then echo "Created PR: $CREATED_PR_URL" post_comment "✅ Cherry-pick successful! Created PR: $CREATED_PR_URL" # Request review gh pr review-request "$CREATED_PR_URL" --reviewer "$PR_AUTHOR" || true else echo "Failed to create PR." post_comment "❌ Cherry-pick failed: Could not create PR to \`$TARGET_BRANCH\`." continue fi fi # Cleanup for next loop git checkout "$ORIGINAL_HEAD_SHA" git branch -D "$NEW_BRANCH" fi done <<< "$LABELS" - name: Remove Cherry Pick Labels env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} REPO_NAME: ${{ github.repository }} run: | LABELS=$(gh pr view "$PR_NUMBER" --repo "$REPO_NAME" --json labels --jq '.labels[].name') if [ -z "$LABELS" ]; then exit 0 fi while read -r label; do if [[ "$label" == cherry-pick:* ]]; then echo "Removing label: $label" gh pr edit "$PR_NUMBER" --repo "$REPO_NAME" --remove-label "$label" fi done <<< "$LABELS" ================================================ FILE: .github/workflows/ci_iluvatar.yml ================================================ name: CI_ILUVATAR on: pull_request: types: [opened, synchronize] branches: [develop, release/**] permissions: read-all concurrency: group: ${{ github.event.pull_request.number }}-${{ github.workflow }} cancel-in-progress: true jobs: iluvatar_test: name: iluvatar_test runs-on: iluvatar-gpu-2 timeout-minutes: 60 container: image: ccr-2vdh3abv-pub.cnc.bj.baidubce.com/device/paddle-ixuca:3.3.0 env: LD_LIBRARY_PATH: /usr/local/corex/lib LIBRARY_PATH: /usr/local/corex/lib http_proxy: http://oversea-website-proxy.aistudio.public:8888 https_proxy: http://oversea-website-proxy.aistudio.public:8888 steps: - name: Print current runner name run: | echo "Current runner name: ${{ runner.name }}" env curl -v --proxy http://oversea-website-proxy.aistudio.public:8888 https://www.github.com - name: Checkout code uses: actions/checkout@v4 with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.ref || github.ref_name }} submodules: 'recursive' fetch-depth: 1000 - name: Merge PR (if needed) if: ${{ github.event_name == 'pull_request' }} run: | git config --global --add safe.directory "$GITHUB_WORKSPACE" git config --global user.name "PaddleFormersCI" git config --global user.email "paddleformers_ci@example.com" echo "Fetching and merging PR..." git fetch origin pull/${{ github.event.pull_request.number }}/head:pr/${{ github.event.pull_request.number }} git merge --no-ff pr/${{ github.event.pull_request.number }} echo "PR Branch log " git log --oneline -n 5 pr/${{ github.event.pull_request.number }} - name: Run CI unittest env: MODEL_PATH: /aistudio/paddle_ci run: | set -e git config --global --add safe.directory "$GITHUB_WORKSPACE" unset http_proxy unset https_proxy python -m pip install -r requirements.txt echo "Uninstall PaddlePaddle and PaddleFormers beforehand..." python -m pip uninstall paddlepaddle paddle-iluvatar-gpu paddlepaddle-iluvatar paddleformers -y echo "Install PaddlePaddle..." retry_count=0 max_retries=3 while [ $retry_count -lt $max_retries ]; do if python -m pip install --pre paddlepaddle-iluvatar -i https://www.paddlepaddle.org.cn/packages/nightly/ixuca/; then echo "PaddlePaddle Iluvatar installation successful" break else retry_count=$((retry_count + 1)) if [ $retry_count -lt $max_retries ]; then echo "PaddlePaddle Iluvatar installation failed, retrying in 10 seconds... (Attempt $retry_count/$max_retries)" sleep 10 else echo "PaddlePaddle Iluvatar installation failed after $max_retries attempts, Please try rerun this job." exit 1 fi fi done echo "Install PaddleFormers..." retry_count=0 max_retries=3 while [ $retry_count -lt $max_retries ]; do if python -m pip install -e .; then echo "PaddleFormers installation successful" break else retry_count=$((retry_count + 1)) if [ $retry_count -lt $max_retries ]; then echo "PaddleFormers installation failed, retrying in 10 seconds... (Attempt $retry_count/$max_retries)" sleep 10 else echo "PaddleFormers installation failed after $max_retries attempts, Please try rerun this job." exit 1 fi fi done python -m pip install pytest python -m pip install pytest-timeout echo "============================Start running tests============================" mkdir -p baidu cp -r ${MODEL_PATH}/ERNIE-4.5-21B-A3B-PT baidu/ ixsmi python -m pytest -v -s --tb=short scripts/iluvatar_ci/ echo "============================All tests passed============================" rm -rf baidu/ ================================================ FILE: .github/workflows/ci_xpu.yml ================================================ name: CI_XPU on: pull_request: types: [opened, synchronize] branches: [develop, release/**] permissions: read-all concurrency: group: ${{ github.event.pull_request.number }}-${{ github.workflow }} cancel-in-progress: true jobs: clone: name: Clone-Linux uses: ./.github/workflows/_clone_linux.yml xpu_test: name: xpu_test needs: [clone] uses: ./.github/workflows/_xpu_ci_test.yml with: PADDLEFORMERS_ARCHIVE_URL: ${{ needs.clone.outputs.repo_archive_url }} DOCKER_IMAGE: ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddleqa:xpu-ubuntu2204-x86_64-gcc123-py310 MODEL_PATH: /ssd3/model # xpu_4cards_case_test: # name: xpu_4cards_case_test # needs: [clone, xpu_build_test] # uses: ./.github/workflows/_xpu_4cards_case_test.yml # with: # FASTDEPLOY_ARCHIVE_URL: ${{ needs.clone.outputs.repo_archive_url }} # DOCKER_IMAGE: ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/fastdeploy-xpu:ci # FASTDEPLOY_WHEEL_URL: ${{ needs.xpu_build_test.outputs.wheel_path }} # MODEL_PATH: /ssd3/model # xpu_8cards_case_test: # name: xpu_8cards_case_test # needs: [clone, xpu_build_test] # uses: ./.github/workflows/_xpu_8cards_case_test.yml # with: # FASTDEPLOY_ARCHIVE_URL: ${{ needs.clone.outputs.repo_archive_url }} # DOCKER_IMAGE: ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/fastdeploy-xpu:ci # FASTDEPLOY_WHEEL_URL: ${{ needs.xpu_build_test.outputs.wheel_path }} # MODEL_PATH: /ssd3/model ================================================ FILE: .github/workflows/debug-unittest-gpu.yml ================================================ name: Debug Unittest GPU with SSH on: workflow_dispatch: env: PR_ID: ${{ github.event.pull_request.number }} COMMIT_ID: ${{ github.event.pull_request.head.sha }} BRANCH: ${{ github.event.pull_request.base.ref }} AGILE_COMPILE_BRANCH: ${{ github.event.pull_request.base.ref }} TASK: PaddleFormers-CI-${{ github.event.pull_request.number }}-unittest-gpu-debug ci_scripts: /workspace/PaddleFormers/scripts/unit_test CI_name: unittest-gpu-debug no_proxy: "localhost,bj.bcebos.com,su.bcebos.com,bcebos.com,apiin.im.baidu.com,gitee.com,aliyun.com,.baidu.com,.tuna.tsinghua.edu.cn" defaults: run: shell: bash jobs: debug-container: name: unittest-gpu-debug runs-on: [self-hosted, 4gpu] timeout-minutes: 30 steps: - name: Run Container env: work_dir: ${{ github.workspace }} FLAGS_dynamic_static_unified_comm: "True" python_version: "3.10" paddle_whl: https://paddle-qa.bj.bcebos.com/paddle-pipeline/Develop-GpuAll-LinuxCentos-Gcc11-Cuda126-Cudnn95-Trt105-Py310-Compile/latest/paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl run: | container_name=${TASK}-$(date +%Y%m%d-%H%M%S) echo "container_name=${container_name}" >> "$GITHUB_ENV" image_name=ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:cuda126-dev-latest echo "image_name=${image_name}" >> "$GITHUB_ENV" DOCKER_VER=$(docker version --format '{{.Server.Version}}' | cut -d. -f1,2) if (( $(echo "$DOCKER_VER < 19.03" | bc -l) )); then GPU_OPTION="--runtime=nvidia" else GPU_OPTION="--gpus all" fi echo "DOCKER_VER=${DOCKER_VER}" echo "GPU_OPTION=${GPU_OPTION}" docker run -d -t ${GPU_OPTION} --name ${container_name} --net=host -v /dev/shm:/dev/shm --shm-size=32G \ -v $work_dir/../../..:$work_dir/../../.. \ -v $work_dir:/workspace \ -v /home/.cache/pip:/home/.cache/pip \ -e BRANCH \ -e PR_ID \ -e COMMIT_ID \ -e work_dir \ -e ci_scripts \ -e no_proxy \ -e CI_name \ -e paddle_whl \ -e FLAGS_dynamic_static_unified_comm \ -e python_version \ -w /workspace --privileged $image_name - name: Download Code run: | docker exec -t $container_name /bin/bash -c ' rm -rf * .[^.]* echo "Downloading PaddleFormers.tar" wget -q --no-proxy https://paddle-qa.bj.bcebos.com/CodeSync/develop/PaddleFormers.tar --no-check-certificate echo "Extracting PaddleFormers.tar" tar xf PaddleFormers.tar && rm -rf PaddleFormers.tar source $work_dir/../../../proxy cd PaddleFormers git config --global user.name "PaddleCI" git config --global user.email "paddle_ci@example.com" git pull git submodule update --init --recursive --force if [ -n "${PR_ID}" ]; then git fetch origin pull/${PR_ID}/head git checkout -b PR_${PR_ID} FETCH_HEAD git remote add upstream https://github.com/PaddlePaddle/PaddleFormers.git git fetch upstream ${BRANCH} git merge ${BRANCH} --no-edit git diff --numstat ${BRANCH} -- | awk "{print \$NF}" else echo "Not in a pull_request event. Skipping PR-specific operations." fi git log --pretty=oneline -10 unset http_proxy && unset https_proxy ' - name: Prepare Environment run: | docker exec -t $container_name /bin/bash -c ' ldconfig set -e python -c "import sys; print(sys.version_info[:])" pip config set global.cache-dir "/home/.cache/pip" cd /workspace/PaddleFormers && git config --global --add safe.directory $PWD ' - name: Print Info env: work_dir: ${{ github.workspace }} run: | echo "docker exec -it $container_name bash" echo "work_path: $work_dir/PaddleFormers" echo "work_path in docker: /workspace/PaddleFormers" echo "cmd: " echo "bash scripts/unit_test/ci_unittest.sh ${paddle_whl}" echo "or python -m pytest fail_case_name" echo "docker rm -f $container_name" ================================================ FILE: .github/workflows/fleet-model-test.yml ================================================ name: Fleet Model Test on: pull_request: branches: - develop - release/** permissions: read-all concurrency: group: ${{ github.event.pull_request.number }}-${{ github.workflow }} cancel-in-progress: true env: PR_ID: ${{ github.event.pull_request.number || '0' }} COMMIT_ID: ${{ github.event.pull_request.head.sha || github.sha }} work_dir: /paddle PADDLE_ROOT: /paddle ci_scripts: /paddle/ci BRANCH: ${{ github.event.pull_request.base.ref || github.ref_name }} CI_name: fleet-model-test no_proxy: "bcebos.com,.bcebos.com,apiin.im.baidu.com,gitee.com,aliyun.com,.baidu.com,.tuna.tsinghua.edu.cn" docker_image: "ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:cuda129-coverage-test" defaults: run: shell: bash jobs: check_skip: name: Check skip-fleet-models-ci label runs-on: ubuntu-latest outputs: skip: ${{ steps.check_skip.outputs.skip }} steps: - name: Check skip-fleet-models-ci label id: check_skip shell: bash run: | if [[ "${{ github.event_name }}" == "pull_request" ]]; then labels='${{ toJson(github.event.pull_request.labels.*.name) }}' echo "PR labels: $labels" if echo "$labels" | grep -q "skip-fleet-models-ci"; then echo "skip=true" >> "$GITHUB_OUTPUT" else echo "skip=false" >> "$GITHUB_OUTPUT" fi else echo "skip=false" >> "$GITHUB_OUTPUT" fi - name: Skip CI but mark success if: steps.check_skip.outputs.skip == 'true' run: | echo "skip-fleet-models-ci label found" echo "Downstream GPU jobs will be skipped" check_documents_type: needs: check_skip if: ${{ needs.check_skip.outputs.skip == 'false' }} name: check documents type for pull request runs-on: ubuntu-latest env: GITHUB_REPO_NAME: ${{ github.repository }} outputs: is_md_only: ${{ steps.check_files.outputs.is_md_only }} steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-python@v5 with: python-version: '3.10' - name: git diff and check id: check_files if: | github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'fleet-models-ci') run: | changed_files=$(git diff origin/${{ github.event.pull_request.base.ref }}...HEAD --name-only) echo "Changed files: $changed_files" all_count=0 md_count=0 for file in $changed_files; do all_count=$((all_count+1)) echo $file if [[ $file == *.md ]]; then echo "Markdown document: $file has been changed." md_count=$((md_count+1)) fi done echo "总计: all_count=$all_count, md_count=$md_count" if [ "$md_count" -eq "$all_count" ]; then echo "is_md_only=true" >> $GITHUB_OUTPUT echo "is_md_only=true" else echo "is_md_only=false" >> $GITHUB_OUTPUT echo "is_md_only=false" fi echo "is_md_only: $(cat $GITHUB_OUTPUT | grep is_md_only || echo '未找到')" integration-test-H20-single-card: needs: [check_documents_type, check_skip] if: ${{ needs.check_documents_type.outputs.is_md_only == 'false' && needs.check_skip.outputs.skip == 'false' }} name: Integration test (H20, single card) runs-on: group: Fleet-H-single-card env: PIP_CACHE_DIR: /home/.cache/pip CACHE_DIR: /home/.cache TASK: formers-fleet-CI-${{ github.event.pull_request.number }}-integration-test-single-card steps: - name: Determine the runner run: | gpu_id=$(( $(echo $PWD | awk -F'/' '{print $3}' | awk -F'-' '{print $2}') + 3 )) echo GPU_DEVICES="$gpu_id" >> $GITHUB_ENV - name: Check docker image and run container env: GPU_DEVICES: ${{ env.GPU_DEVICES }} run: | container_name=${TASK}-$(date +%Y%m%d-%H%M%S) echo "container_name=${container_name}" >> ${{ github.env }} docker pull $docker_image set -x docker run -d -t --name ${container_name} --gpus "\"device=${GPU_DEVICES}\"" --shm-size=32G \ -v "/dev/shm:/dev/shm" \ -v ${{ github.workspace }}/../../..:${{ github.workspace }}/../../.. \ -v ${{ github.workspace }}/../../..:/root \ -v /ssd1/paddle-1/action_cache:/home/.cache \ -v ${{ github.workspace }}:/workspace \ -e BRANCH \ -e PR_ID \ -e COMMIT_ID \ -e PADDLE_ROOT \ -e ci_scripts \ -e CACHE_DIR \ -e no_proxy \ -e CI_name \ -e PIP_CACHE_DIR \ -e GITHUB_SHA="${{ github.event.pull_request.head.sha }}" \ -e GITHUB_HEAD_REF="${{ github.head_ref }}" \ -e GITHUB_BASE_SHA="${{ github.event.pull_request.base.sha }}" \ -e GITHUB_REPO_NAME="${{ github.repository }}" \ -e GITHUB_EVENT_NAME="${{ github.event_name }}" \ -e GITHUB_EVENT_PULL_REQUEST_NUMBER="${{ github.event.pull_request.number }}" \ -e GITHUB_TOKEN="${{ secrets.GITHUB_TOKEN }}" \ -e GITHUB_RUN_ID="${{ github.run_id }}" \ -e PR_USER="${{ github.event.pull_request.user.login }}" \ -w /workspace --network host ${docker_image} - name: Install PaddleFormers id: formers_install run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' rm -rf * .[^.]* echo $PR_USER source /root/proxy mkdir -p /home/.cache/pip pip cache dir pip install --upgrade pip git clone https://github.com/PaddlePaddle/PaddleFormers.git -b ${BRANCH} cd PaddleFormers git status git config --global --add safe.directory /workspace/PaddleFormers git config user.name "PaddleCI" git config user.email "paddle_ci@example.com" git config pull.rebase false git pull --no-edit origin pull/${PR_ID}/head export UV_SKIP_WHEEL_FILENAME_CHECK=1 sed -i "s/from gpt_provider import GPTModelProvider/from paddleformers.transformers.gpt_provider import GPTModelProvider/g" examples/experiments/paddlefleet/glm45_provider.py sed -i "s/from gpt_provider import GPTModelProvider/from paddleformers.transformers.gpt_provider import GPTModelProvider/g" examples/experiments/paddlefleet/qwen_provider.py pip install -e ".[paddlefleet]" --extra-index-url=https://www.paddlepaddle.org.cn/packages/stable/cu129/ --extra-index-url=https://www.paddlepaddle.org.cn/packages/nightly/cu129/ # wget -q --no-proxy --no-check-certificate https://paddle-github-action.cdn.bcebos.com/PaddleFleet/release/0.2/latest/cu129/paddlefleet-0.0.0-cp310-cp310-linux_x86_64.whl # pip uninstall paddlefleet -y # pip install paddlefleet-0.0.0-cp310-cp310-linux_x86_64.whl --extra-index-url=https://www.paddlepaddle.org.cn/packages/stable/cu129/ # wget -q --no-proxy --no-check-certificate https://paddle-qa.bj.bcebos.com/paddle-pipeline/Release-TagBuild-Training-Linux-Gpu-Cuda12.9-Cudnn9.9-Trt10.5-Mkl-Avx-Gcc11-SelfBuiltPypiUse/latest/paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl # pip uninstall paddlepaddle-gpu -y # pip install paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl --index-url=https://www.paddlepaddle.org.cn/packages/nightly/cu129/ echo "paddle commit:" python -c "import paddle; print(paddle.version.commit)" echo "paddlefleet commit:" python -c "import paddlefleet; print(paddlefleet.version.commit)" cd /workspace wget -q --no-proxy -O bos_new.tar.gz https://xly-devops.bj.bcebos.com/home/bos_new.tar.gz --no-check-certificate mkdir bos tar xf bos_new.tar.gz -C bos pip install bce-python-sdk==0.8.74 pip install coverage==7.6.1 pip install librosa==0.11.0 ' - name: Proprocess for integration test if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/preprocess.sh preprocess_exit_code=$? if [[ "$preprocess_exit_code" != "0" ]]; then echo -e "::error:: \033[31mPreprocess failed.\033[0m" exit 1 else echo -e "\033[32mPreprocess succeeded.\033[0m" fi ' - name: Integration test (GLM4.5 single-card) if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_pt_single_card.sh glm45_single_card_exit_code=$? if [[ "$glm45_single_card_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5 single-card.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 single-card.\033[0m" fi ' - name: Integration test (Qwen3-30B-A3B single-card) if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen3_single_card.sh qwen3_single_card_exit_code=$? if [[ "$qwen3_single_card_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: Qwen3-30B-A3B single-card.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: Qwen3-30B-A3B single-card.\033[0m" fi ' - name: Qwen3-vl-8k-single-card if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen3vl_sft_single_card.sh single exit_code=$? if [[ "$exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: Qwen3-vl-8k-single-card.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: Qwen3-vl-8k-single-card.\033[0m" fi ' - name: Terminate and delete the container if: ${{ always() }} run: | set +e docker exec -t ${{ env.container_name }} /bin/bash -c 'rm -rf * .[^.]*' docker rm -f ${{ env.container_name }} integration-test-H20-multi-card: needs: [check_documents_type, check_skip] if: ${{ needs.check_documents_type.outputs.is_md_only == 'false' && needs.check_skip.outputs.skip == 'false' }} name: Integration test (H20, multi-card) runs-on: group: Fleet-H-multi-card env: PIP_CACHE_DIR: /home/.cache/pip CACHE_DIR: /home/.cache TASK: formers-fleet-CI-${{ github.event.pull_request.number }}-integration-test-multi-card steps: - name: Check docker image and run container run: | container_name=${TASK}-$(date +%Y%m%d-%H%M%S) echo "container_name=${container_name}" >> ${{ github.env }} docker pull $docker_image docker run -d -t --name ${container_name} --gpus all --shm-size=32G \ -v "/dev/shm:/dev/shm" \ -v ${{ github.workspace }}/../../..:${{ github.workspace }}/../../.. \ -v ${{ github.workspace }}/../../..:/root \ -v /ssd1/paddle-1/action_cache:/home/.cache \ -v ${{ github.workspace }}:/workspace \ -e BRANCH \ -e PR_ID \ -e COMMIT_ID \ -e PADDLE_ROOT \ -e ci_scripts \ -e CACHE_DIR \ -e no_proxy \ -e CI_name \ -e PIP_CACHE_DIR \ -e GITHUB_SHA="${{ github.event.pull_request.head.sha }}" \ -e GITHUB_HEAD_REF="${{ github.head_ref }}" \ -e GITHUB_BASE_SHA="${{ github.event.pull_request.base.sha }}" \ -e GITHUB_REPO_NAME="${{ github.repository }}" \ -e GITHUB_EVENT_NAME="${{ github.event_name }}" \ -e GITHUB_EVENT_PULL_REQUEST_NUMBER="${{ github.event.pull_request.number }}" \ -e GITHUB_TOKEN="${{ secrets.GITHUB_TOKEN }}" \ -e GITHUB_RUN_ID="${{ github.run_id }}" \ -e PR_USER="${{ github.event.pull_request.user.login }}" \ -w /workspace --network host ${docker_image} - name: Install PaddleFormers id: formers_install run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' rm -rf * .[^.]* source /root/proxy mkdir -p /home/.cache/pip pip cache dir pip install --upgrade pip git clone https://github.com/PaddlePaddle/PaddleFormers.git -b ${BRANCH} cd PaddleFormers git status git config --global --add safe.directory /workspace/PaddleFormers git config user.name "PaddleCI" git config user.email "paddle_ci@example.com" git config pull.rebase false git pull --no-edit origin pull/${PR_ID}/head export UV_SKIP_WHEEL_FILENAME_CHECK=1 pip install -e ".[paddlefleet]" --extra-index-url=https://www.paddlepaddle.org.cn/packages/stable/cu129/ --extra-index-url=https://www.paddlepaddle.org.cn/packages/nightly/cu129/ # wget -q --no-proxy --no-check-certificate https://paddle-github-action.cdn.bcebos.com/PaddleFleet/release/0.2/latest/cu129/paddlefleet-0.0.0-cp310-cp310-linux_x86_64.whl # pip uninstall paddlefleet -y # pip install paddlefleet-0.0.0-cp310-cp310-linux_x86_64.whl --extra-index-url=https://www.paddlepaddle.org.cn/packages/stable/cu129/ # wget -q --no-proxy --no-check-certificate https://paddle-qa.bj.bcebos.com/paddle-pipeline/Release-TagBuild-Training-Linux-Gpu-Cuda12.9-Cudnn9.9-Trt10.5-Mkl-Avx-Gcc11-SelfBuiltPypiUse/latest/paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl # pip uninstall paddlepaddle-gpu -y # pip install paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl --index-url=https://www.paddlepaddle.org.cn/packages/nightly/cu129/ echo "paddle commit:" python -c "import paddle; print(paddle.version.commit)" echo "paddlefleet commit:" python -c "import paddlefleet; print(paddlefleet.version.commit)" cd /workspace wget -q --no-proxy -O bos_new.tar.gz https://xly-devops.bj.bcebos.com/home/bos_new.tar.gz --no-check-certificate mkdir bos tar xf bos_new.tar.gz -C bos pip install bce-python-sdk==0.8.74 pip install coverage==7.6.1 pip install librosa==0.11.0 ' - name: GLM4.5 pre-train if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_pt.sh glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5.\033[0m" fi ' - name: GLM4.5 sft if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_sft.sh glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5 sft.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 sft.\033[0m" fi ' - name: GLM4.5 lora if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_lora.sh glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5 lora.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 lora.\033[0m" fi ' - name: GLM4.5 dpo if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_dpo.sh glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5 dpo.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 dpo.\033[0m" fi ' - name: GLM4.5 dpo_lora if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_dpo_lora.sh glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5 dpo lora.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 dpo lora.\033[0m" fi ' - name: GLM4.5 pre-train (EP4) if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_pt_ep4.sh glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5 EP4.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 EP4.\033[0m" fi ' - name: GLM4.5 pre-train (FP8) if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_pt_fp8.sh glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 FP8.\033[0m" fi ' - name: GLM4.5 pre-train (Grouped GEMM) if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_pt_grouped_gemm.sh glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5 Grouped GEMM.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 Grouped GEMM.\033[0m" fi ' - name: Qwen pre-train if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen.sh pt ' - name: Qwen sft if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen.sh sft ' - name: Qwen lora if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen.sh lora ' - name: Qwen vl sft if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen3vl_sft.sh tp8 h20 ' - name: Qwen vl lora if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen3vl_lora.sh h20 ' - name: Qwen vl moe if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 10m bash -x PaddleFormers/tests/integration_test/qwen3vl_sft.sh moe h20 ' - name: Qwen3-vl-8k-fsdp if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 10m bash -x PaddleFormers/tests/integration_test/qwen3vl_sft.sh fsdp h20 ' - name: Terminate and delete the container if: ${{ always() }} run: | set +e docker exec -t ${{ env.container_name }} /bin/bash -c 'rm -rf * .[^.]*' docker rm -f ${{ env.container_name }} integration-test-a100: needs: [check_documents_type, check_skip] if: ${{ needs.check_documents_type.outputs.is_md_only == 'false' && needs.check_skip.outputs.skip == 'false' }} name: Integration test (A100) runs-on: group: Distribute env: PIP_CACHE_DIR: /home/.cache/pip CACHE_DIR: /home/.cache TASK: formers-fleet-CI-${{ github.event.pull_request.number }}-integration-test-A100 steps: - name: Check docker image and run container run: | container_name=${TASK}-$(date +%Y%m%d-%H%M%S) echo "container_name=${container_name}" >> ${{ github.env }} docker pull $docker_image docker run -d -t --name ${container_name} --gpus all --shm-size=32G \ -v "/dev/shm:/dev/shm" \ -v ${{ github.workspace }}/../../..:${{ github.workspace }}/../../.. \ -v ${{ github.workspace }}/../../..:/root \ -v /ssd1/paddle-1/action_cache:/home/.cache \ -v ${{ github.workspace }}:/workspace \ -e BRANCH \ -e PR_ID \ -e COMMIT_ID \ -e PADDLE_ROOT \ -e ci_scripts \ -e CACHE_DIR \ -e no_proxy \ -e CI_name \ -e PIP_CACHE_DIR \ -e GITHUB_SHA="${{ github.event.pull_request.head.sha }}" \ -e GITHUB_HEAD_REF="${{ github.head_ref }}" \ -e GITHUB_BASE_SHA="${{ github.event.pull_request.base.sha }}" \ -e GITHUB_REPO_NAME="${{ github.repository }}" \ -e GITHUB_EVENT_NAME="${{ github.event_name }}" \ -e GITHUB_EVENT_PULL_REQUEST_NUMBER="${{ github.event.pull_request.number }}" \ -e GITHUB_TOKEN="${{ secrets.GITHUB_TOKEN }}" \ -e GITHUB_RUN_ID="${{ github.run_id }}" \ -e PR_USER="${{ github.event.pull_request.user.login }}" \ -w /workspace --network host ${docker_image} - name: Install PaddleFormers id: formers_install run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' rm -rf * .[^.]* source /root/proxy mkdir -p /home/.cache/pip pip cache dir pip install --upgrade pip git clone https://github.com/PaddlePaddle/PaddleFormers.git -b ${BRANCH} cd PaddleFormers git status git config --global --add safe.directory /workspace/PaddleFormers git config user.name "PaddleCI" git config user.email "paddle_ci@example.com" git config pull.rebase false git pull --no-edit origin pull/${PR_ID}/head export UV_SKIP_WHEEL_FILENAME_CHECK=1 sed -i "s/from gpt_provider import GPTModelProvider/from paddleformers.transformers.gpt_provider import GPTModelProvider/g" examples/experiments/paddlefleet/glm45_provider.py sed -i "s/from gpt_provider import GPTModelProvider/from paddleformers.transformers.gpt_provider import GPTModelProvider/g" examples/experiments/paddlefleet/qwen_provider.py pip install -e ".[paddlefleet]" --extra-index-url=https://www.paddlepaddle.org.cn/packages/stable/cu129/ --extra-index-url=https://www.paddlepaddle.org.cn/packages/nightly/cu129/ # wget -q --no-proxy --no-check-certificate https://paddle-github-action.cdn.bcebos.com/PaddleFleet/release/0.2/latest/cu129/paddlefleet-0.0.0-cp310-cp310-linux_x86_64.whl # pip uninstall paddlefleet -y # pip install paddlefleet-0.0.0-cp310-cp310-linux_x86_64.whl --extra-index-url=https://www.paddlepaddle.org.cn/packages/stable/cu129/ # wget -q --no-proxy --no-check-certificate https://paddle-qa.bj.bcebos.com/paddle-pipeline/Release-TagBuild-Training-Linux-Gpu-Cuda12.9-Cudnn9.9-Trt10.5-Mkl-Avx-Gcc11-SelfBuiltPypiUse/latest/paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl # pip uninstall paddlepaddle-gpu -y # pip install paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl --index-url=https://www.paddlepaddle.org.cn/packages/nightly/cu129/ echo "paddle commit:" python -c "import paddle; print(paddle.version.commit)" echo "paddlefleet commit:" python -c "import paddlefleet; print(paddlefleet.version.commit)" cd /workspace wget -q --no-proxy -O bos_new.tar.gz https://xly-devops.bj.bcebos.com/home/bos_new.tar.gz --no-check-certificate mkdir bos tar xf bos_new.tar.gz -C bos pip install bce-python-sdk==0.8.74 pip install coverage==7.6.1 pip install librosa==0.11.0 ' - name: GLM4.5 pre-train run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_a100.sh pt glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5.\033[0m" fi ' - name: GLM4.5 sft if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_a100.sh sft glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5 sft.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 sft.\033[0m" fi ' - name: GLM4.5 lora if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_a100.sh lora glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5 lora.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 lora.\033[0m" fi ' - name: GLM4.5 dpo if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_a100.sh dpo glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5 dpo.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 dpo.\033[0m" fi ' - name: GLM4.5 dpo_lora if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/glm45_a100.sh dpo_lora glm45_exit_code=$? if [[ "$glm45_exit_code" != "0" ]]; then echo -e "::error:: \033[31mIntegration test failed: GLM4.5 dpo lora.\033[0m" exit 1 else echo -e "\033[32mIntegration test succeeded: GLM4.5 dpo lora.\033[0m" fi ' - name: Qwen pre-train if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen3_a100.sh pt ' - name: Qwen sft if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen3_a100.sh sft ' - name: Qwen lora if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen3_a100.sh lora ' - name: Qwen vl sft if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen3vl_sft.sh tp8 a100 ' - name: Qwen vl lora if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 5m bash -x PaddleFormers/tests/integration_test/qwen3vl_lora.sh a100 ' - name: Qwen vl moe if: (success() || failure()) && steps.formers_install.conclusion == 'success' run: | docker exec -t ${{ env.container_name }} /bin/bash -ce ' source /root/proxy timeout 10m bash -x PaddleFormers/tests/integration_test/qwen3vl_sft.sh moe a100 ' # - name: Qwen3-vl-8k-fsdp # if: (success() || failure()) && steps.formers_install.conclusion == 'success' # run: | # docker exec -t ${{ env.container_name }} /bin/bash -ce ' # source /root/proxy # timeout 10m bash -x PaddleFormers/tests/integration_test/qwen3vl_sft.sh fsdp h20 # ' - name: Terminate and delete the container if: ${{ always() }} run: | set +e docker exec -t ${{ env.container_name }} /bin/bash -c 'rm -rf * .[^.]*' docker rm -f ${{ env.container_name }} ================================================ FILE: .github/workflows/lint.yml ================================================ name: Codestyle Check on: [push, pull_request] concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number }} cancel-in-progress: true env: PR_ID: ${{ github.event.pull_request.number }} COMMIT_ID: ${{ github.event.pull_request.head.sha }} BRANCH: ${{ github.event.pull_request.base.ref }} TASK: PaddleFormers-CI-Lint-${{ github.event.pull_request.number }} jobs: Lint: name: Lint runs-on: [self-hosted, ernie-cpu-01] steps: - name: Run Container env: work_dir: ${{ github.workspace }} python_version: "3.10" run: | container_name=${TASK}-$(date +%Y%m%d-%H%M%S) echo "container_name=${container_name}" >> "$GITHUB_ENV" docker_image="iregistry.baidu-int.com/paddlecloud/base-images:paddlecloud-ubuntu20.04-gcc12.2-cuda12.3-cudnn9.0-nccl2.20.3.1-openmpi4.1.5-latest" docker run -d -t --name ${container_name} --net=host -v /dev/shm:/dev/shm --shm-size=32G \ -v $work_dir/../../..:$work_dir/../../.. \ -v $work_dir:/workspace \ -v /home/.cache/pip:/home/.cache/pip \ -e BRANCH \ -e PR_ID \ -e COMMIT_ID \ -e work_dir \ -e no_proxy \ -e python_version \ -w /workspace ${docker_image} - name: Download Code env: work_dir: ${{ github.workspace }} run: | docker exec -t ${container_name} /bin/bash -c ' rm -rf * .[^.]* echo "Downloading PaddleFormers.tar" wget -q --no-proxy https://paddle-qa.bj.bcebos.com/CodeSync/develop/PaddleFormers.tar --no-check-certificate echo "Extracting PaddleFormers.tar" tar xf PaddleFormers.tar && rm -rf PaddleFormers.tar source $work_dir/../../../proxy cd PaddleFormers git config --global user.name "PaddleCI" git config --global user.email "paddle_ci@example.com" git pull git submodule update --init --recursive --force if [ -n "${PR_ID}" ]; then git fetch origin pull/${PR_ID}/head git checkout -b PR_${PR_ID} FETCH_HEAD git remote add upstream https://github.com/PaddlePaddle/PaddleFormers.git git fetch upstream ${BRANCH} git merge ${BRANCH} --no-edit git diff --numstat ${BRANCH} -- | awk "{print \$NF}" else echo "Not in a pull_request event. Skipping PR-specific operations." fi git log --pretty=oneline -10 if ! git show-ref --quiet refs/heads/develop; then \ echo "local develop branch is missing, creating local develop branch that tracks remote develop branch" git fetch origin develop git branch develop --track origin/develop else echo "local develop branch exist, skipping" fi unset http_proxy && unset https_proxy ' - name: Setup Environment run: | docker exec -t $container_name /bin/bash -c ' unlink /usr/local/bin/python ln -sf $(which python${python_version}) /usr/local/bin/python set -e python -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple python -m pip config set global.cache-dir "/home/.cache/pip" python -m pip install --upgrade pip cd /workspace/PaddleFormers && git config --global --add safe.directory $PWD make install ' - name: Test run: | docker exec -t $container_name /bin/bash -c ' set -e cd /workspace/PaddleFormers source $work_dir/../../../proxy make lint ' - name: Terminate And Delete the Container if: always() run: | docker rm -f $container_name 2>/dev/null || true ================================================ FILE: .github/workflows/model-unittest-gpu.yml ================================================ name: Model Unittest GPU CI on: pull_request: schedule: - cron: "0 18 * * *" workflow_call: inputs: runner: required: false type: string image_name: required: false type: string concurrency: group: model-unittest-${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} cancel-in-progress: true env: PR_ID: ${{ github.event.pull_request.number || '0' }} COMMIT_ID: ${{ github.event.pull_request.head.sha || github.sha }} TASK: PaddleFormers-CI-${{ github.event.pull_request.number }}-model-unittest-gpu CI_SCRIPTS_PATH: /workspace/PaddleFormers/scripts/ci_model_unittest.sh BRANCH: ${{ github.event.pull_request.base.ref || github.ref_name }} AGILE_COMPILE_BRANCH: ${{ github.event.pull_request.base.ref }} CI_JOB_NAME: model-unittest-gpu-ci no_proxy: "localhost,bj.bcebos.com,su.bcebos.com,bcebos.com,apiin.im.baidu.com,gitee.com,aliyun.com,.baidu.com,.tuna.tsinghua.edu.cn" defaults: run: shell: bash jobs: check_skip: name: Check skip-models-ci label runs-on: ubuntu-latest outputs: skip: ${{ steps.check_skip.outputs.skip }} steps: - name: Check skip-models-ci label id: check_skip shell: bash run: | if [[ "${{ github.event_name }}" == "pull_request" ]]; then labels='${{ toJson(github.event.pull_request.labels.*.name) }}' echo "PR labels: $labels" if echo "$labels" | grep -q "skip-models-ci"; then echo "skip=true" >> "$GITHUB_OUTPUT" else echo "skip=false" >> "$GITHUB_OUTPUT" fi else echo "skip=false" >> "$GITHUB_OUTPUT" fi - name: Skip CI but mark success if: steps.check_skip.outputs.skip == 'true' run: | echo "skip-models-ci label found" echo "Downstream GPU jobs will be skipped" model-unittest-gpu-ci: needs: check_skip if: needs.check_skip.outputs.skip == 'false' name: model-unittest-gpu-ci runs-on: ${{ inputs.runner || 'ernie-8gpu' || 'distrbute' }} steps: - name: Determine Image Name env: IMAGE_NAME: ${{ inputs.image_name }} run: | if [[ -n "${IMAGE_NAME}" ]]; then echo "IMAGE_NAME=${IMAGE_NAME}" >> "$GITHUB_ENV" else echo "IMAGE_NAME=ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:cuda126-dev-latest" >> "$GITHUB_ENV" fi - name: Run Container env: work_dir: ${{ github.workspace }} FLAGS_dynamic_static_unified_comm: "True" python_version: "3.10" PIP_CACHE_DIR: /root/.cache/pip paddle_whl: https://paddle-qa.bj.bcebos.com/paddle-pipeline/Develop-TagBuild-Training-Linux-Gpu-Cuda12.6-Cudnn9.5-Trt10.5-Mkl-Avx-Gcc11-SelfBuiltPypiUse/latest/paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl run: | container_name=${TASK}-$(date +%Y%m%d-%H%M%S) echo "container_name=${container_name}" >> "$GITHUB_ENV" echo "Workspace path: ${{ github.workspace }}" DOCKER_VER=$(docker version --format '{{.Server.Version}}' | cut -d. -f1,2) if (( $(echo "$DOCKER_VER < 19.03" | bc -l) )); then GPU_OPTION="--runtime=nvidia" else GPU_OPTION="--gpus all" fi echo "DOCKER_VER=${DOCKER_VER}" echo "GPU_OPTION=${GPU_OPTION}" docker run -d -t ${GPU_OPTION} --name ${container_name} --net=host -v /dev/shm:/dev/shm --shm-size=32G \ -v ${work_dir}/../../..:${work_dir}/../../.. \ -v ${work_dir}:/workspace \ -v /home/.cache/:/root/.cache/ \ -v /home/paddle-1/models/:/home/models/ \ -e "BRANCH=$BRANCH" \ -e "AGILE_COMPILE_BRANCH=$AGILE_COMPILE_BRANCH" \ -e "PR_ID=$PR_ID" \ -e "COMMIT_ID=$COMMIT_ID" \ -e "work_dir=$work_dir" \ -e "CI_SCRIPTS_PATH=$CI_SCRIPTS_PATH" \ -e "no_proxy=$no_proxy" \ -e "CI_JOB_NAME=$CI_JOB_NAME" \ -e "paddle_whl=$paddle_whl" \ -e "FLAGS_dynamic_static_unified_comm=$FLAGS_dynamic_static_unified_comm" \ -e "python_version=$python_version" \ -e HF_PROXY_PATH=${work_dir}/../../../proxy_huggingface \ -e AISTUDIO_PROXY_PATH=${work_dir}/../../../proxy_aistudio \ -e PF_HOME=/home/models/ \ -e PIP_CACHE_DIR \ -w /workspace --privileged ${IMAGE_NAME} - name: Download Code run: | docker exec -t $container_name /bin/bash -c ' rm -rf * .[^.]* echo "Downloading PaddleFormers.tar" wget -q --no-proxy https://paddle-qa.bj.bcebos.com/CodeSync/develop/PaddleFormers.tar --no-check-certificate echo "Extracting PaddleFormers.tar" rm -rf PaddleFormers tar xf PaddleFormers.tar && rm -rf PaddleFormers.tar echo "work_dir = ${work_dir}" source ${work_dir}/../../../proxy cd PaddleFormers git config --global user.name "PaddleCI" git config --global user.email "paddle_ci@example.com" git pull git submodule update --init --recursive --force if [ -n "$PR_ID" ] && [ "$PR_ID" != "0" ]; then git fetch origin pull/${PR_ID}/head git checkout -b PR_${PR_ID} FETCH_HEAD git remote add upstream https://github.com/PaddlePaddle/PaddleFormers.git echo "Checking out ${BRANCH}..." git fetch upstream ${BRANCH}:${BRANCH} git merge ${BRANCH} --no-edit git diff --numstat ${BRANCH} -- | awk "{print \$NF}" else echo "Not in a pull_request event. Skipping PR-specific operations." fi git log --pretty=oneline -10 ' - name: Test run: | docker exec -t $container_name /bin/bash -c ' ldconfig mkdir -p /root/.cache/pip pip cache dir set -e rm -rf /root/.cache/aistudio/ cd /workspace/PaddleFormers && git config --global --add safe.directory $PWD echo "work_dir = ${work_dir}" cp -r ${work_dir}/../../../models ./models echo "Check whether the local model file exists:" ls -l ./models bash -x scripts/regression/ci_model_unittest.sh ${paddle_whl} false ${AGILE_COMPILE_BRANCH} ' - name: Upload Products if: always() env: home_path: ${{ github.workspace }}/../../.. bos_file: ${{ github.workspace }}/../../../bos/BosClient.py run: | docker exec -t $container_name /bin/bash -c ' if [ ! -f "${{ env.bos_file }}" ]; then wget -q --no-proxy -O ${{ env.home_path }}/bos_new.tar.gz https://xly-devops.bj.bcebos.com/home/bos_new.tar.gz --no-check-certificate mkdir ${{ env.home_path }}/bos tar xf ${{ env.home_path }}/bos_new.tar.gz -C ${{ env.home_path }}/bos fi if [ -n "$PR_ID" ] && [ "$PR_ID" != "0" ]; then bos_prefix="${PR_ID}/${COMMIT_ID}" else bos_prefix="schedule/$(date +%Y%m%d)" fi # logs cd /workspace/PaddleFormers/model_unittest_logs for FILE in /workspace/PaddleFormers/model_unittest_logs/*; do file=$(basename "$FILE") python ${{ env.bos_file }} $file paddle-github-action/PR/PaddleFormers/model-unittest-gpu/${bos_prefix}/logs echo "$file: https://paddle-github-action.bj.bcebos.com/PR/PaddleFormers/model-unittest-gpu/${bos_prefix}/logs/$file" done ' - name: Terminate And Delete the Container if: always() run: | docker rm -f $container_name 2>/dev/null || true ================================================ FILE: .github/workflows/requirements-review.yml ================================================ name: Check Requirements Need Approval on: pull_request: types: [opened, synchronize, reopened, ready_for_review] paths: - 'requirements.txt' pull_request_review: types: [submitted] jobs: check-review: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Check if requirements.txt changed id: check_diff run: | git fetch origin ${{ github.base_ref }} if git diff origin/${{ github.base_ref }} --name-only | grep -q '^requirements.txt$'; then echo "changed=true" >> $GITHUB_OUTPUT else echo "changed=false" >> $GITHUB_OUTPUT fi - name: Skip if requirements.txt not changed if: steps.check_diff.outputs.changed == 'false' run: | echo "requirements.txt not changed, skip approval check" - name: Check required reviewer approval if: steps.check_diff.outputs.changed == 'true' uses: actions/github-script@v7 with: script: | const required = [ "nepeplwu", "lugimzzz", "zjjlivein" ]; const { data: reviews } = await github.rest.pulls.listReviews({ owner: context.repo.owner, repo: context.repo.repo, pull_number: context.payload.pull_request.number, }); const approved = new Set(); for (const r of reviews) { if ( required.includes(r.user.login) && r.state === "APPROVED" ) { approved.add(r.user.login); } } if (approved.size === 0) { core.setFailed( `requirements.txt changed: need approval from one of ${required.join(", ")}` ); } else { core.info(`Approved by: ${Array.from(approved).join(", ")}`); } ================================================ FILE: .github/workflows/rerun.yml ================================================ name: Re-run on: issue_comment: types: [created] jobs: re-run: if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/re-run') && github.event.comment.user.login == github.event.issue.user.login }} runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v3 - name: Rerun All Failed Jobs if: ${{ contains(github.event.comment.body, 'all-failed') }} uses: ./.github/actions/rerun-workflow with: PR_ID: ${{ github.event.issue.number }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} OWNER: ${{ github.repository_owner }} REPO: ${{ github.event.repository.name }} JOB_NAME: 'all-failed' - name: Rerun Unittest GPU if: ${{ contains(github.event.comment.body, 'Unittest GPU') }} uses: ./.github/actions/rerun-workflow with: PR_ID: ${{ github.event.issue.number }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} OWNER: ${{ github.repository_owner }} REPO: ${{ github.event.repository.name }} JOB_NAME: 'Unittest GPU CI / unittest-gpu-ci' - name: Rerun Unittest CPU if: ${{ contains(github.event.comment.body, 'Unittest CPU') }} uses: ./.github/actions/rerun-workflow with: PR_ID: ${{ github.event.issue.number }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} OWNER: ${{ github.repository_owner }} REPO: ${{ github.event.repository.name }} JOB_NAME: 'Unittest CPU CI / unittest-cpu-ci' - name: Rerun Codestyle Check if: ${{ contains(github.event.comment.body, 'Codestyle Check') }} uses: ./.github/actions/rerun-workflow with: PR_ID: ${{ github.event.issue.number }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} OWNER: ${{ github.repository_owner }} REPO: ${{ github.event.repository.name }} JOB_NAME: 'Codestyle Check / Lint' ================================================ FILE: .github/workflows/stale.yml ================================================ name: Stale on: # Allow manual run via GitHub web or CLI workflow_dispatch: schedule: # Run daily at midnight UTC - cron: 0 0 * * * permissions: issues: write pull-requests: write jobs: stale: runs-on: ubuntu-24.04 permissions: issues: write pull-requests: write steps: - uses: actions/stale@v6.0.1 with: days-before-issue-stale: 60 days-before-issue-close: 14 stale-issue-label: "stale" stale-issue-message: "This issue is stale because it has been open for 60 days with no activity. 当前issue 60天内无活动,被标记为stale。" close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale. 当前issue 被标记为stale已有14天,即将关闭。" exempt-issue-labels: 'triage,keep' days-before-pr-stale: 60 days-before-pr-close: -1 stale-pr-label: "stale" stale-pr-message: "This Pull Request is stale because it has been open for 60 days with no activity. 当前Pull Request 60天内无活动,被标记为stale。" operations-per-run: 400 ================================================ FILE: .github/workflows/unittest-gpu.yml ================================================ name: Unittest GPU CI on: pull_request: schedule: - cron: "0 18 * * *" workflow_call: inputs: runner: required: false type: string image_name: required: false type: string concurrency: group: unittest-${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} cancel-in-progress: true env: PR_ID: ${{ github.event.pull_request.number || '0' }} COMMIT_ID: ${{ github.event.pull_request.head.sha || github.sha }} TASK: PaddleFormers-CI-${{ github.event.pull_request.number }}-unittest-gpu ci_scripts: /workspace/PaddleFormers/scripts/unit_test BRANCH: ${{ github.event.pull_request.base.ref || github.ref_name }} AGILE_COMPILE_BRANCH: ${{ github.event.pull_request.base.ref }} CI_name: unittest-gpu-ci no_proxy: "localhost,bj.bcebos.com,su.bcebos.com,bcebos.com,apiin.im.baidu.com,gitee.com,aliyun.com,.baidu.com,.tuna.tsinghua.edu.cn" PYTEST_EXECUTE_FLAG_FILE: ${{ github.workspace }}/../../../PYTEST_EXECUTE_FLAG_FILE/${{ github.event.pull_request.number || '0' }}/${{ github.event.pull_request.head.sha || github.sha }}/pytest_execute.flag PYTEST_EXECUTE_FLAG: false defaults: run: shell: bash jobs: check_skip: name: Check skip-unittest-ci label runs-on: ubuntu-latest outputs: skip: ${{ steps.check_skip.outputs.skip }} steps: - name: Check skip-unittest-ci label id: check_skip shell: bash run: | if [[ "${{ github.event_name }}" == "pull_request" ]]; then labels='${{ toJson(github.event.pull_request.labels.*.name) }}' echo "PR labels: $labels" if echo "$labels" | grep -q "skip-unittest-ci"; then echo "skip=true" >> "$GITHUB_OUTPUT" else echo "skip=false" >> "$GITHUB_OUTPUT" fi else echo "skip=false" >> "$GITHUB_OUTPUT" fi - name: Skip CI but mark success if: steps.check_skip.outputs.skip == 'true' run: | echo "skip-unittest-ci label found" echo "Downstream GPU jobs will be skipped" unittest-gpu-ci: needs: check_skip if: needs.check_skip.outputs.skip == 'false' name: unittest-gpu-ci runs-on: ${{ inputs.runner || 'ernie-8gpu' || 'distrbute' }} outputs: pytest_execute_flag: ${{ steps.set_pytest_flag.outputs.pytest_execute_flag }} steps: - name: Determine Image Name env: IMAGE_NAME: ${{ inputs.image_name }} run: | if [[ -n "${IMAGE_NAME}" ]]; then echo "IMAGE_NAME=${IMAGE_NAME}" >> "$GITHUB_ENV" else echo "IMAGE_NAME=ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:cuda126-dev-latest" >> "$GITHUB_ENV" fi - name: Run Container env: work_dir: ${{ github.workspace }} FLAGS_dynamic_static_unified_comm: "True" python_version: "3.10" PIP_CACHE_DIR: /root/.cache/pip paddle_whl: https://paddle-qa.bj.bcebos.com/paddle-pipeline/Develop-TagBuild-Training-Linux-Gpu-Cuda12.6-Cudnn9.5-Trt10.5-Mkl-Avx-Gcc11-SelfBuiltPypiUse/latest/paddlepaddle_gpu-0.0.0-cp310-cp310-linux_x86_64.whl run: | container_name=${TASK}-$(date +%Y%m%d-%H%M%S) echo "container_name=${container_name}" >> "$GITHUB_ENV" echo "Workspace path: ${{ github.workspace }}" DOCKER_VER=$(docker version --format '{{.Server.Version}}' | cut -d. -f1,2) if (( $(echo "$DOCKER_VER < 19.03" | bc -l) )); then GPU_OPTION="--runtime=nvidia" else GPU_OPTION="--gpus all" fi echo "DOCKER_VER=${DOCKER_VER}" echo "GPU_OPTION=${GPU_OPTION}" docker run -d -t ${GPU_OPTION} --name ${container_name} --net=host -v /dev/shm:/dev/shm --shm-size=32G \ -v $work_dir/../../..:$work_dir/../../.. \ -v $work_dir:/workspace \ -v /home/.cache/:/root/.cache/ \ -v /home/paddle-1/models/:/home/models/ \ -e PF_HOME=/home/models/ \ -e "BRANCH=$BRANCH" \ -e "AGILE_COMPILE_BRANCH=$AGILE_COMPILE_BRANCH" \ -e "PR_ID=$PR_ID" \ -e "COMMIT_ID=$COMMIT_ID" \ -e "work_dir=$work_dir" \ -e "ci_scripts=$ci_scripts" \ -e "PYTEST_EXECUTE_FLAG_FILE=$PYTEST_EXECUTE_FLAG_FILE" \ -e "no_proxy=$no_proxy" \ -e "CI_JOB_NAME=$CI_JOB_NAME" \ -e "paddle_whl=$paddle_whl" \ -e "FLAGS_dynamic_static_unified_comm=$FLAGS_dynamic_static_unified_comm" \ -e "python_version=$python_version" \ -e "HF_PROXY_PATH=$work_dir/../../../proxy_huggingface" \ -e "AISTUDIO_PROXY_PATH=$work_dir/../../../proxy_aistudio" \ -e "HF_DATASETS_CACHE=$work_dir/../../../paddlenlp/huggingface/datasets" \ -e "TRANSFORMERS_CACHE=$work_dir/../../../paddlenlp/huggingface" \ -e PIP_CACHE_DIR \ -w /workspace --privileged $IMAGE_NAME - name: Download Code run: | docker exec -t $container_name /bin/bash -c ' rm -rf * .[^.]* echo "Downloading PaddleFormers.tar" wget -q --no-proxy https://paddle-qa.bj.bcebos.com/CodeSync/develop/PaddleFormers.tar --no-check-certificate echo "Extracting PaddleFormers.tar" rm -rf PaddleFormers tar xf PaddleFormers.tar && rm -rf PaddleFormers.tar source $work_dir/../../../proxy cd PaddleFormers git config --global user.name "PaddleCI" git config --global user.email "paddle_ci@example.com" git pull git submodule update --init --recursive --force if [ -n "$PR_ID" ] && [ "$PR_ID" != "0" ]; then git fetch origin pull/${PR_ID}/head git checkout -b PR_${PR_ID} FETCH_HEAD git remote add upstream https://github.com/PaddlePaddle/PaddleFormers.git git fetch upstream ${BRANCH}:${BRANCH} git merge ${BRANCH} --no-edit git diff --numstat ${BRANCH} -- | awk "{print \$NF}" else echo "Not in a pull_request event. Skipping PR-specific operations." fi git log --pretty=oneline -10 ' - name: Test run: | docker exec -t $container_name /bin/bash -c ' ldconfig mkdir -p /root/.cache/pip pip cache dir set -e rm -rf /root/.cache/aistudio/ cd /home/models/my_packages && dpkg -i *.deb cd /workspace/PaddleFormers && git config --global --add safe.directory $PWD source $work_dir/../../../proxy source $work_dir/../../../AISTUDIO_ACCESS_TOKEN echo "work_dir = ${work_dir}" cp -r ${work_dir}/../../../models ./models echo "Check whether the local model file exists:" ls -l ./models bash -x scripts/unit_test/ci_unittest.sh ${paddle_whl} false ${PYTEST_EXECUTE_FLAG_FILE} ${AGILE_COMPILE_BRANCH} ' - name: Upload Products env: home_path: ${{ github.workspace }}/../../.. bos_file: ${{ github.workspace }}/../../../bos/BosClient.py allure_file: ${{ github.workspace }}/../../../allure-2.19.0/bin/allure run: | docker exec -t $container_name /bin/bash -c ' if [ ! -f "${{ env.bos_file }}" ]; then wget -q --no-proxy -O ${{ env.home_path }}/bos_new.tar.gz https://xly-devops.bj.bcebos.com/home/bos_new.tar.gz --no-check-certificate mkdir ${{ env.home_path }}/bos tar xf ${{ env.home_path }}/bos_new.tar.gz -C ${{ env.home_path }}/bos fi # if [ ! -f "${{ env.allure_file }}" ]; then # wget -q --no-proxy -O ${{ env.home_path }}/allure-2.19.0.zip https://xly-devops.bj.bcebos.com/tools/allure-2.19.0.zip --no-check-certificate # unzip -q ${{ env.home_path }}/allure-2.19.0.zip # fi if [ -n "$PR_ID" ] && [ "$PR_ID" != "0" ]; then bos_prefix="${PR_ID}/${COMMIT_ID}" else bos_prefix="schedule/github-ci-$(date +%Y%m%d)" fi # coverage.xml if [ -f "${PYTEST_EXECUTE_FLAG_FILE}" ]; then echo "PYTEST_EXECUTE_FLAG_FILE found, uploading coverage.xml." cd /workspace/PaddleFormers python ${{ env.bos_file }} coverage.xml paddle-github-action/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs echo "cov-report: https://paddle-github-action.bj.bcebos.com/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs/coverage.xml" else echo "PYTEST_EXECUTE_FLAG_FILE not found, skipping coverage.xml upload." fi # logs cd /workspace/PaddleFormers/unittest_logs for FILE in /workspace/PaddleFormers/unittest_logs/*; do file=$(basename "$FILE") python ${{ env.bos_file }} $file paddle-github-action/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs echo "$file: https://paddle-github-action.bj.bcebos.com/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs/$file" done # allure # cd /workspace/PaddleFormers/ # ${{ env.allure_file }} generate result -o report # tar -czf report.tar.gz report # python ${{ env.bos_file }} report.tar.gz paddle-github-action/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs # echo "report: https://paddle-github-action.bj.bcebos.com/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs/report.tar.gz" ' - name: Set pytest execute flag output id: set_pytest_flag # 专门设置输出的步骤 run: | # 检查标志文件是否存在,并设置作业输出 if [ -f "${{ env.PYTEST_EXECUTE_FLAG_FILE }}" ]; then echo "pytest_execute_flag=true" >> $GITHUB_OUTPUT echo "PYTEST_EXECUTE_FLAG_FILE exists, setting flag to true" else echo "pytest_execute_flag=false" >> $GITHUB_OUTPUT echo "PYTEST_EXECUTE_FLAG_FILE does not exist, setting flag to false" fi - name: Terminate And Delete the Container if: always() run: | docker rm -f $container_name 2>/dev/null || true upload-coverage: name: upload-coverage needs: [unittest-gpu-ci] if: always() runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Check if should upload coverage id: flag_check run: | echo "needs.unittest-gpu-ci.outputs.pytest_execute_flag = ${{ needs.unittest-gpu-ci.outputs.pytest_execute_flag }}" if [ "${{ needs.unittest-gpu-ci.outputs.pytest_execute_flag }}" = "true" ]; then echo "pytest_execute_flag is true, proceeding to upload coverage." echo "should_upload=true" >> $GITHUB_OUTPUT else echo "pytest_execute_flag is false, skipping coverage upload." echo "should_upload=false" >> $GITHUB_OUTPUT fi - name: Download coverage.xml if: steps.flag_check.outputs.should_upload == 'true' env: PR_ID: ${{ github.event.pull_request.number || '0' }} COMMIT_ID: ${{ github.event.pull_request.head.sha || github.sha }} run: | if [ -n "$PR_ID" ] && [ "$PR_ID" != "0" ]; then bos_prefix="${PR_ID}/${COMMIT_ID}" else bos_prefix="schedule/$(date +%Y%m%d)" fi echo "bos_prefix=${bos_prefix}" wget -q --no-proxy \ https://paddle-github-action.bj.bcebos.com/PR/PaddleFormers/unittest-gpu/${bos_prefix}/logs/coverage.xml \ --no-check-certificate -O coverage.xml - name: Fix coverage.xml paths if: steps.flag_check.outputs.should_upload == 'true' run: | echo "Before fix:" head -n 10 coverage.xml || true old_source=$(grep -oPm1 '(?<=).*?(?=)' coverage.xml || true) if [ -n "$old_source" ]; then echo "Replacing source '$old_source' with 'paddleformers'" sed -i "s|$old_source|paddleformers|g" coverage.xml else echo "No found, injecting paddleformers" sed -i 's||\n paddleformers|' coverage.xml fi echo "After fix:" head -n 10 coverage.xml || true - name: Upload coverage to Codecov if: steps.flag_check.outputs.should_upload == 'true' uses: codecov/codecov-action@v4 with: files: coverage.xml env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} ================================================ FILE: .github/workflows/update-precision.yml ================================================ name: update precision on: push: branches: - develop jobs: determine-whether-update: name: Determine whether to update if: github.repository == 'PaddlePaddle/PaddleFormers' runs-on: ubuntu-latest outputs: need_change: ${{ steps.determine.outputs.need_change }} steps: - name: Determine whether to update id: determine run: | sleep 30 response=$(curl -L \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer ${{ github.token }}" \ -H "X-GitHub-Api-Version: 2022-11-28" \ https://api.github.com/repos/PaddlePaddle/PaddleFormers/commits/${{ github.sha }}/pulls) pr_number=$(echo "$response" | jq -r '.[] | select(.url | contains("PaddlePaddle/PaddleFormers")) | .number') set +e wget --no-proxy --no-check-certificate https://paddle-github-action.cdn.bcebos.com/PaddleFleet/precision/PaddleFormers/${pr_number}/precision_list.txt if [ $? -eq 0 ]; then echo "need_change=true" >> "$GITHUB_OUTPUT" else echo "need_change=false" >> "$GITHUB_OUTPUT" fi update-precision: name: Update precision needs: determine-whether-update if: needs.determine-whether-update.outputs.need_change == 'true' runs-on: ubuntu-latest steps: - name: Clone PaddleFormers uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.base.ref }} fetch-depth: 100 - name: Setup python3.10 uses: actions/setup-python@v5 with: python-version: "3.10" - name: Update precision env: AK: ${{ secrets.AK }} SK: ${{ secrets.SK }} GITHUB_TOKEN: ${{ github.token }} COMMIT_ID: ${{ github.sha }} GITHUB_REPO_NAME: ${{ github.repository }} run: | python -m pip install bce-python-sdk==0.8.74 wget -q -O bos_new.tar.gz https://xly-devops.bj.bcebos.com/home/bos_new.tar.gz --no-check-certificate mkdir bos tar xf bos_new.tar.gz -C bos bash -x tests/integration_test/update_precision.sh ================================================ FILE: .gitignore ================================================ # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ build* !scripts/dependence/build.sh develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover .hypothesis/ .pytest_cache/ # Translations *.doctree *.mo *.pot *.doctree # Django stuff: *.log local_settings.py db.sqlite3 # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv .python-version # celery beat schedule file celerybeat-schedule # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pycharm # vscode .vscode ./ppdiffusers/ppdiffusers/version.py # third party csrc/third_party/ dataset/ output/ !tests/dataset/ # gen codes autogen/ # cutlass kernel !csrc/gpu/cutlass_kernels/gemm/collective/builders #fp8 ops/csrc/fp8/deep_gemm/include/cutlass ops/csrc/fp8/deep_gemm/include/cute .ccls-cache .DS_Store .idea/ FETCH_HEAD # vscode .vscode ./ppdiffusers/ppdiffusers/version.py # third party csrc/third_party/ dataset/ output/ !tests/dataset/ # gen codes autogen/ # cutlass kernel !csrc/gpu/cutlass_kernels/gemm/collective/builders #fp8 ops/csrc/fp8/deep_gemm/include/cutlass ops/csrc/fp8/deep_gemm/include/cute .ccls-cache # logs and running results paddleformers_dist_log checkpoints ================================================ FILE: .pre-commit-config.yaml ================================================ repos: # For Python files - repo: https://github.com/psf/black.git rev: 22.8.0 hooks: - id: black files: \.(py|pyi)$ additional_dependencies: [toml] - repo: https://github.com/PyCQA/isort rev: 5.11.5 hooks: - id: isort - repo: https://github.com/PyCQA/flake8 rev: 4.0.1 hooks: - id: flake8 - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.1.0 hooks: - id: check-merge-conflict - id: check-symlinks - id: detect-private-key files: (?!.*paddle)^.*$ - id: end-of-file-fixer files: \.md$ - id: trailing-whitespace files: \.md$ - repo: https://github.com/Lucas-C/pre-commit-hooks rev: v1.1.14 hooks: - id: forbid-crlf files: \.md$ - id: remove-crlf files: \.md$ - id: forbid-tabs files: \.md$ - id: remove-tabs files: \.md$ - repo: local hooks: - id: copyright_checker name: copyright_checker entry: python .copyright.hook language: system files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto|xpu|kps|py|sh)$ # For Markdown files - repo: local hooks: - id: add-spaces-between-chinese-and-english name: Add spaces between Chinese and English characters entry: python scripts/codestyle/check_spaces.py language: python files: \.(md|markdown)$ pass_filenames: true # For dead links - repo: local hooks: - id: check-dead-links name: Check dead links entry: python scripts/codestyle/check_dead_links.py language: python files: \.(md|markdown|rst)$ pass_filenames: true ================================================ FILE: .readthedocs.yaml ================================================ # .readthedocs.yaml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 build: os: "ubuntu-20.04" tools: python: "3.10" submodules: include: all recursive: true # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/zh/conf.py # Optionally build your docs in additional formats such as PDF #formats: # - pdf # Optionally set the version of Python and requirements required to build your docs python: install: - requirements: docs/requirements.txt ================================================ FILE: CONTRIBUTING.md ================================================ **简体中文**🀄 | [English🌎](.github/CONTRIBUTING_en.md) # Contributing to PaddleFormers 我们非常欢迎并希望您对`PaddleFormers`做出开源贡献。在您开始提交您的贡献之前,请先行签署[PaddlePaddle 贡献者许可协议](https://cla-assistant.io/PaddlePaddle/PaddleFormers)。 本文接下来将介绍我们的开发与贡献流程: ## 贡献方式 我们欢迎不同的向`PaddleFormers`做出贡献的方式,例如: - 修复已知的 Issue - 提交新的 Issue,例如提出功能需求或者 bug 报告 - 实现新的模型结构 如果您不知道从哪里开始,请查看 Issues 板块中的`Good First Issue`标签。它为您提供一个对初学者友好的已知 Issue 列表,可以降低贡献的门槛,帮助您开始为开源做出贡献。您只需在您想处理的 Issue 中告知我们您想负责此 Issue 即可。 ## 开发流程 PaddleFormers 使用 [Git 分支模型](http://nvie.com/posts/a-successful-git-branching-model/)。对于常见的开源贡献,我们有以下的贡献流程: ### 1. Fork 因为 PaddleFormers 的开发社区一直在发展,如果每位贡献者都直接向官方 Repo 提交 commit 将会难以管理。因此,请从您的分支中提交 Pull Requests。建议您通过 GitHub 的[“Fork”按钮](https://help.github.com/articles/fork-a-repo/)来创建您的 Fork 分支。 ### 2. Clone 请运行一下命令将您的分支 clone 到本地 ```bash git clone https://github.com//PaddleFormers cd PaddleFormers ``` ### 3. 创建本地开发分支 对于添加新功能或修复错误等日常工作,请在开发前创建您的本地开发分支: ```bash git checkout -b my-cool-feature ``` ### 4. 配置开发环境 在开始编码之前,您需要设置开发环境。我们强烈建议您在虚拟环境中进行所有开发,例如[venv](https://docs.python.org/3/library/venv.html)或[conda](https://docs.conda.io/en/latest/)。 请您设置并激活虚拟环境后,运行以下命令: ```bash make install ``` 这将设置 `PaddleFormers` 的所有依赖以及 [`pre-commit`](http://pre-commit.com/) 工具。 如果您需要开发 `examples` 或 `applications` 模块并加载 `PaddleFormers`,请确保以可编辑模式(`-e`)安装 `PaddleFormers`。 如果在虚拟环境中已经安装 `PaddleFormers` ,请使用 `pip uninstall paddleformers` 将其删除,然后以可编辑模式重新安装它 `pip install -e .` ### 5. 开发 当您开发时,请确保您新增的代码会被单元测试所覆盖。我们所有的单元测试都可以在 `tests` 目录下找到。 您可以修改现有单元测试以覆盖新功能,也可以从头开始创建新测试。 当您完成代码时,您应该确保相关的单元测试可以通过。您可以像这样运行受更改影响的测试: ```bash pytest tests/.py ``` ### 6. Commit 我们使用 [`pre-commit`](http://pre-commit.com/)工具(包括[black](https://black.readthedocs.io/en/stable/)、[isort](https:/ /pycqa.github.io/isort/) 和 [flake8](https://flake8.pycqa.org/en/latest/))来检查每次提交中的代码和文档的风格。当你运行 `git commit` 时,你会看到 类似于以下内容: ```text ➜ (my-virtual-env) git commit -m "committing my cool feature" black....................................................................Passed isort....................................................................Passed flake8...................................................................Passed check for merge conflicts................................................Passed check for broken symlinks............................(no files to check)Skipped detect private key.......................................................Passed fix end of files.....................................(no files to check)Skipped trim trailing whitespace.............................(no files to check)Skipped CRLF end-lines checker...............................(no files to check)Skipped CRLF end-lines remover...............................(no files to check)Skipped No-tabs checker......................................(no files to check)Skipped Tabs remover.........................................(no files to check)Skipped copyright_checker........................................................Passed ``` 但大多数时候事情并没有那么顺利。当您的代码或文档不符合标准时,`pre-commit` 检查将失败。 ```text ➜ (my-virtual-env) git commit -m "committing my cool feature" black....................................................................Passed isort....................................................................Failed - hook id: isort - files were modified by this hook Fixing examples/information_extraction/waybill_ie/run_ernie_crf.py flake8...................................................................Passed check for merge conflicts................................................Passed check for broken symlinks............................(no files to check)Skipped detect private key.......................................................Passed fix end of files.....................................(no files to check)Skipped trim trailing whitespace.............................(no files to check)Skipped CRLF end-lines checker...............................(no files to check)Skipped CRLF end-lines remover...............................(no files to check)Skipped No-tabs checker......................................(no files to check)Skipped Tabs remover.........................................(no files to check)Skipped copyright_checker........................................................Passed ``` 我们的工具将自动修复大部分样式错误,但是有些错误需要手动解决。幸运的是,错误信息一般通俗易懂,很容易修复。 解决错误后,您可以再次运行 `git add ` 和 `git commit`,这将再次触发 pre-commit 。 一旦 pre-commit 检查通过,您就可以推送代码了。 [Google](https://google.com/) 或 [StackOverflow](https://stackoverflow.com/) 是帮助您了解代码风格错误的好工具。 如果您仍然无法弄清楚,请不要担心。您可以使用 `git commit -m "style error" --no-verify` 提交,我们很乐意在您创建 Pull Request 后帮助您。 ### 7. git pull 与代码冲突 有经验的 Git 用户经常从官方 Repo 中 git pull。因为这样子他们会及早注意到与其他人的代码冲突,并且让代码冲突更容易解决 ```bash git remote add upstream https://github.com/PaddlePaddle/PaddleFormers git pull upstream develop ``` ### 8. git push 与提交 Pull Request 您可以将您的本地开发分支中的工作 push 到您的 fork 的分支中: ```bash git push origin my-cool-stuff ``` git push 之后,您可以提交 Pull Request,请求[官方 repo](https://github.com/PaddlePaddle/PaddleFormers) 采纳您的开发工作。请您依照[这些步骤](https://help.github.com/articles/creating-a-pull-request/)创建 Pull Request。 ### 9. 删除已经合入的本地和远程分支 为了保持您本地的工作区和 fork 分支的干净整洁,建议您在 Pull Request 合入之后删除本地的残余分支: ```bash git push origin my-cool-stuff git checkout develop git pull upstream develop git branch -d my-cool-stuff ``` ## 代码 Review - 在您的 Pull Request 能够顺利通过本地测试以及 CI 的情况下,您可以在 Pull Request 中 @ 相关的 Reviewer,提醒他们尽快对您的 Pull Request 进行 Review。 - 请处理 Reviewer 的每一条评论。如果您已按照评论修改,请回复“完成”;否则,可以在评论下展开讨论。 - 如果您不希望您的 Reviewer 被电子邮件通知淹没,您可以[批量回复](https://help.github.com/articles/reviewing-proposed-changes-in-a-pull-request/)。 ================================================ FILE: LICENSE ================================================ Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: Makefile ================================================ # Makefile for PaddleFormers # # GitHb: https://github.com/PaddlePaddle/PaddleFormers # Author: Paddle Team https://github.com/PaddlePaddle # .PHONY: all all : lint test check_dirs := paddleformers scripts tests # # # # # # # # # # # # # # # Format Block # # # # # # # # # # # # # # # format: pre-commit run isort pre-commit run black # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Lint Block # # # # # # # # # # # # # # # .PHONY: lint lint: $(eval modified_py_files := $(shell python scripts/codestyle/get_modified_files.py $(check_dirs))) @if test -n "$(modified_py_files)"; then \ echo ${modified_py_files}; \ pre-commit run --files ${modified_py_files}; \ else \ echo "No library .py files were modified"; \ fi # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Test Block # # # # # # # # # # # # # # # .PHONY: test test: unit-test unit-test: DOWNLOAD_SOURCE=aistudio \ PYTHONPATH=$(shell pwd) pytest -v \ --retries 1 --retry-delay 1 \ --durations 20 \ --cov=./paddleformers \ --cov-report=xml:coverage.xml # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # .PHONY: install install: @echo "Checking CUDA version and selecting pip source..." @if ! command -v nvcc >/dev/null 2>&1; then \ echo "ERROR: nvcc (CUDA) not found. Please install CUDA before proceeding."; \ exit 1; \ fi; \ cuda_version=$$(nvcc --version | grep release | awk '{print $$5}' | sed 's/,//'); \ echo "Detected CUDA version: $$cuda_version"; \ if [ "$$cuda_version" = "12.6" ]; then \ PADDLE_SOURCE="https://www.paddlepaddle.org.cn/packages/nightly/cu126/"; \ elif [ "$$cuda_version" = "12.9" ]; then \ PADDLE_SOURCE="https://www.paddlepaddle.org.cn/packages/nightly/cu129/"; \ elif [ "$$cuda_version" = "13.0" ]; then \ PADDLE_SOURCE="https://www.paddlepaddle.org.cn/packages/nightly/cu130/"; \ else \ PADDLE_SOURCE=""; \ echo "Unknown CUDA version."; \ fi; \ echo "Using pip source: $$PADDLE_SOURCE"; \ pip install -r tests/requirements.txt \ pip install -r requirements.txt --extra-index-url "$$PADDLE_SOURCE"; \ pre-commit install .PHONY: deploy-ppdiffusers deploy-ppdiffusers: cd ppdiffusers && make install && make .PHONY: deploy-paddle-pipelines deploy-paddle-pipelines: cd pipelines && make install && make .PHONY: deploy-paddleformers deploy-paddleformers: # install related package make install # build python3 setup.py sdist bdist_wheel # upload twine upload --skip-existing dist/* ================================================ FILE: README.md ================================================

------------------------------------------------------------------------------------------

最新更新 | 特性 | 安装 | 快速体验 | 社区交流

# PaddleFormers ## 📝简介 PaddleFormers 是基于百度深度学习框架 PaddlePaddle 搭建的 Transformers 库,旨在为 PaddlePaddle 生态提供与 Hugging Face Transformers 项目对等的模型接口与功能体验,支持大语言模型(LLM)与视觉语言模型(VLM)的训练能力。PaddleFormers 充分发挥 PaddlePaddle 在高性能训练方面的内置优势,全面支持包括张量并行、流水线并行和专家并行在内的主流大模型分布式训练策略,以及自动混合精度等加速技术,在 DeepSeek-V3、GLM-4.5-Air 等重点模型上,训练性能明显超越 Megatron-LM ,实现了高效的预训练与后训练性能。 结合业界主流优化方法与飞桨在业务实践中积累的高效特性,PaddleFormers 致力于打造**高性能、低资源占用**的训练体验,帮助用户高效便捷地完成大模型训练,而无需关注底层复杂的优化细节。 ## 🆕最新更新 * 2026.01.21 - PaddleFomers v1.0版本发布啦!我们提供了针对 LLM 和 VLM 等模型的训练能力,针对 DeepSeek-V3模型和 GLM-4.5-Air 等重点模型,我们实现了极致性能优化(训练性能明显超越 Megatron-LM )。针对 PaddleOCR-VL,我们在昆仑芯 P800、天数天垓150等国产计算芯片上进行了适配,更好的满足国内用户需求。 ## ✨特性 * **丰富的模型支持:** PaddleFormers 实现了对于 100+ 主流的大语言模型和视觉语言模型的训练能力支持,涵盖了 DeepSeek-V3、GLM-4.5系列、Qwen2和 Qwen3系列、Qwen3-VL 等前沿模型。同时提供了对 ERNIE-4.5、ERNIE-4.5-VL、PaddleOCR-VL 等文心系列模型完备的训练能力。 * **高性能组网实现:** 实现了 FP8低精度训练与高性能算子优化、通信计算重叠优化、精细化存算均衡等策略,大幅提升大模型训练的计算、通信和存储效率。在 DeepSeek-V3、GLM-4.5-Air 等模型上,训练性能明显超越 Megatron-LM。 * **全流程能力支持:** PaddleFormers 实现了从预训练到后训练的全流程训练能力支持,其中后训练支持 CPT / SFT / SFT-LoRA / DPO / DPO-LoRA 等主流能力,帮助用户高效、便捷地完成大模型的迭代与优化。PaddleFormers 还实现了对 Safetensors 格式的 **全面支持** ,训练完成的模型,其存储格式与 Hugging Face 上托管的权重格式一致,可以在任意支持该格式的框架或工具中使用(如 FastDeploy / vLLM / SGLang 等)。 * **完备的训练能力支持:** PaddleFormers 实现了对于 **Function Call** 、 **Thinking**​ 等大模型前沿能力的训练支持,并通过 **Data Packing** 、 **Padding Free**​ 等数据流技术显著优化训练性能。 * **国产芯片深度适配:** 支持昆仑芯 P800、天数天垓150、沐曦 C550等国产计算平台,基于128卡昆仑芯 P800支持 DeepSeek V3的 SFT,成为最少国产算力资源后训练方案。 ## 📋模型列表
模型类型 模型系列 模型名称 Chat Template
LLM DeepSeekv3 deepseek-ai/DeepSeek-V3-Base、deepseek-ai/DeepSeek-V3、deepseek-ai/DeepSeek-V3-0324 deepseek3
🏛️ERNIE-4.5 baidu/ERNIE-4.5-0.3B-Base-PT、baidu/ERNIE-4.5-0.3B-PT、baidu/ERNIE-4.5-21B-A3B-Base-PT、baidu/ERNIE-4.5-21B-A3B-PT、baidu/ERNIE-4.5-300B-A47B-Base-PT、baidu/ERNIE-4.5-300B-A47B-PT、baidu/ERNIE-4.5-21B-A3B-Thinking ernie、ernie_nothink
gemma3 google/gemma-3-270m、google/gemma-3-270m-it、google/gemma-3-1b-pt、google/gemma-3-1b-it、google/gemma-3-4b-pt、google/gemma-3-4b-it、google/gemma-3-12b-pt、google/gemma-3-12b-it、google/gemma-3-27b-pt、google/gemma-3-27b-it gemma
GLM-4.5 zai-org/GLM-4.5-Air-Base、zai-org/GLM-4.5-Air、zai-org/GLM-4.5-Base、zai-org/GLM-4.5 glm4_moe
gpt-oss openai/gpt-oss-20b、openai/gpt-oss-120b gpt
Llama-3 meta-llama/Meta-Llama-3-8B、meta-llama/Meta-Llama-3-8B-Instruct、meta-llama/Meta-Llama-3-70B、meta-llama/Meta-Llama-3-70B-Instruct、meta-llama/Llama-3.1-8B、meta-llama/Llama-3.1-8B-Instruct、meta-llama/Llama-3.1-70B、meta-llama/Llama-3.1-70B-Instruct、meta-llama/Llama-3.1-405B、meta-llama/Llama-3.1-405B-Instruct、meta-llama/Llama-3.2-1B、meta-llama/Llama-3.2-1B-Instruct、meta-llama/Llama-3.2-3B、meta-llama/Llama-3.2-3B-Instruct、meta-llama/Llama-3.3-70B-Instruct llama3
phi-4 microsoft/phi-4 phi4
Qwen2 Qwen/Qwen2-0.5B、Qwen/Qwen2-0.5B-Instruct、Qwen/Qwen2-1.5B、Qwen/Qwen2-1.5B-Instruct、Qwen/Qwen2-7B、Qwen/Qwen2-7B-Instruct、Qwen/Qwen2-57B-A14B、Qwen/Qwen2-57B-A14B-Instruct、Qwen/Qwen2-72B、Qwen/Qwen2-0.5B-Instruct qwen
Qwen3 Qwen/Qwen3-0.6B-Base、Qwen/Qwen3-0.6B、Qwen/Qwen3-1.7B-Base、Qwen/Qwen3-1.7B、Qwen/Qwen3-4B-Base、Qwen/Qwen3-4B、Qwen/Qwen3-4B-Instruct-2507、Qwen/Qwen3-4B-Thinking-2507、Qwen/Qwen3-8B-Base、Qwen/Qwen3-8B、Qwen/Qwen3-14B-Base、Qwen/Qwen3-14B、Qwen/Qwen3-32B、Qwen/Qwen3-30B-A3B-Base、Qwen/Qwen3-30B-A3B、Qwen/Qwen3-30B-A3B-Instruct-2507、Qwen/Qwen3-30B-A3B-Thinking-2507、Qwen/Qwen3-235B-A22B、Qwen/Qwen3-235B-A22B-Instruct-2507、Qwen/Qwen3-235B-A22B-Thinking-2507 qwen3、qwen3_nothink
Qwen3-Next Qwen/Qwen3-Next-80B-A3B-Instruct、Qwen/Qwen3-Next-80B-A3B-Thinking qwen3、qwen3_nothink
VLM 🏛️ERNIE-4.5-VL baidu/ERNIE-4.5-VL-28B-A3B-Base-PT、baidu/ERNIE-4.5-VL-28B-A3B-PT、baidu/ERNIE-4.5-VL-424B-A47B-Base-PT、baidu/ERNIE-4.5-VL-424B-A47B-PT、baidu/ERNIE-4.5-VL-28B-A3B-Thinking ernie_vl、ernie_vl_nothink
🏛️PaddleOCR-VL PaddlePaddle/PaddleOCR-VL paddleocr_vl
Qwen2.5-VL Qwen/Qwen2.5-VL-3B-Instruct、Qwen/Qwen2.5-VL-7B-Instruct、Qwen/Qwen2.5-VL-32B-Instruct、Qwen/Qwen2.5-VL-72B-Instruct qwen2_vl
Qwen3-VL Qwen/Qwen3-VL-2B-Instruct、Qwen/Qwen3-VL-2B-Thinking、Qwen/Qwen3-VL-4B-Instruct、Qwen/Qwen3-VL-4B-Thinking、Qwen/Qwen3-VL-8B-Instruct、Qwen/Qwen3-VL-8B-Thinking、Qwen/Qwen3-VL-32B-Instruct、Qwen/Qwen3-VL-32B-Thinking、Qwen/Qwen3-VL-30B-A3B-Instruct、Qwen/Qwen3-VL-30B-A3B-Thinking、Qwen/Qwen3-VL-235B-A22B-Instruct、Qwen/Qwen3-VL-235B-A22B-Thinking qwen3_vl、qwen3_vl_nothink
* 更多关于模型训练能力的支持细节,请参考:[PaddleFormers 模型能力矩阵](./docs/zh/model_capability.md) * 带有🏛️标签的模型是 PaddleFormers 官方维护的模型 ## 💾安装 **环境依赖** * python ≥ 3.10 * CUDA ≥ 12.0 * PaddleFleet ≥ 0.2(仅为 GPU 训练功能依赖) **安装依赖(GPU)**
基于 Docker 容器的方式(推荐 ------ > 为了避免本地环境存在较多冲突,我们建议使用 PaddleFormers 的预置镜像来准备环境,容器中已经拉取了 PaddleFormers 仓库并完成了安装: > > ```shell > # 以cuda12.6为例 > docker run --gpus all --name paddleformers-work -v $(pwd):/work \ > -w=/work --shm-size=512G --network=host -it \ > ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:3.3.0-gpu-cuda12.6-cudnn9.5 /bin/bash > > # cuda12.9镜像:ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:3.3.0-gpu-cuda12.9-cudnn9.9 > # cuda13.0镜像:ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddle:3.3.0-gpu-cuda13.0-cudnn9.13 > ``` ------
基于 pip/源码的安装方式 ------ > 我们推荐使用 `conda` / `venv` / `uv` 等虚拟环境工具管理 python 环境。 > > ```shell > # conda > conda create -n paddleformers-work python=3.10 #支持python3.10~3.13 > conda activate paddleformers-work > # venv > python -m venv .paddleformers-work > source .paddleformers-work/bin/activate > # uv > uv venv .paddleformers-work > source .paddleformers-work/bin/activate > ``` ------ > **安装方案一:** 拉取源码安装 > > ```shell > # Install development version > git clone https://github.com/PaddlePaddle/PaddleFormers.git > cd PaddleFormers > # cuda12.6 > python -m pip install -e '.[paddlefleet]' --extra-index-url https://www.paddlepaddle.org.cn/packages/nightly/cu126/ > # cuda12.9 > # python -m pip install -e '.[paddlefleet]' --extra-index-url https://www.paddlepaddle.org.cn/packages/nightly/cu129/ > # cuda13.0 > # python -m pip install -e '.[paddlefleet]' --extra-index-url https://www.paddlepaddle.org.cn/packages/nightly/cu130/ > ``` ------ > **安装方案二:** 如果您不想拉取源码,可以基于下面的命令安装 PaddleFormers 和 PaddleFleet。 > > ```shell > # Install via pip > # cuda12.6 > python -m pip install "paddleformers[paddlefleet]" --extra-index-url https://www.paddlepaddle.org.cn/packages/stable/cu126/ > # cuda12.9 > # python -m pip install "paddleformers[paddlefleet]" --extra-index-url https://www.paddlepaddle.org.cn/packages/stable/cu129/ > # cuda13.0 > # python -m pip install "paddleformers[paddlefleet]" --extra-index-url https://www.paddlepaddle.org.cn/packages/stable/cu130/ > ``` ------ > **安装方案三:** 如果您只需使用 tokenizer 或者 processor,可以通过以下命令安装,这种情况下不会安装训练相关的依赖,安装速度更加快。 > > ```shell > python -m pip install paddleformers > ``` ------
**安装依赖(XPU & ILUVATAR-GPU & Metax GPU)** * [昆仑芯安装说明文档](./docs/zh/XPU_installation_guide.md) * [天数智芯安装说明文档](./docs/zh/ILUVATAR-GPU_installation_guide.md) * [沐曦安装说明文档](./docs/zh/Metax-GPU_installation_guide.md) # ⚡快速体验 PaddleFormers 在 API 设计上与 Hugging Face Transformers 保持了高度一致,使用示例如下: **使用 tokenizer** ```python from paddleformers.transformers import AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-0.6B-Base") print(tokenizer.encode("中华人民共和国")) # 中华人民共和国将会被编码为两个token: # [105492, 104773] ``` **文本生成** ```python from paddleformers.transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-0.6B-Base") model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-0.6B-Base", dtype="bfloat16").eval() input_features = tokenizer("请给我一段大模型的简短介绍:", return_tensors="pd") outputs = model.generate(**input_features, max_new_tokens=256) output_ids = outputs[0].tolist()[0] print(tokenizer.decode(output_ids, skip_special_tokens=True)) ``` **模型训练** ```shell paddleformers-cli train ./examples/config/sft/full.yaml ``` ## 📊数据处理 * [数据集格式说明](./docs/zh/dataset_format.md) * [Chat Template 说明](./docs/zh/chat_template_guide.md) * [数据流参数说明](./docs/zh/data_processing_guide.md) ## 🚀模型训练 & 部署 * [PaddleFormers 命令行工具](./docs/zh/cli_usage.md) * [训练参数配置说明](./docs/zh/training_arguments.md) * [基于 PaddleFormers 进行模型预训练/后预训练](./docs/zh/pt_and_cpt_guide.md) * [基于 PaddleFormers 进行指令微调(SFT & LoRA)](./docs/zh/sft_and_lora_guide.md) * [基于 PaddleFormers 进行偏好对齐(DPO & LoRA)](./docs/zh/dpo_and_lora_guide.md) * [基于 FastDeploy / vLLM 部署模型](./docs/zh/deployment_guide.md) ## 💻多硬件使用 * [昆仑芯使用说明文档](./docs/zh/XPU_usage_guide.md) * [天数智芯使用说明文档](./docs/zh/ILUVATAR-GPU_usage_guide.md) * [沐曦使用说明文档](./docs/zh/Metax-GPU_usage_guide.md) ## 🔍最佳实践 * [基于 DeepSeekv3的高效预训练](./examples/best_practices/DeepSeek-V3/) * [基于 ERNIE-4.5的高效预训练](./examples/best_practices/ERNIE-4.5/) * [训练一个偏好 Emoji 输出的对齐模型](./examples/best_practices/tutorials/how_to_train_an_emoji_model.md) * [训练一个支持思考能力的模型](./examples/best_practices/tutorials/how_to_train_a_reasoning_model.md) * [训练一个支持 Function Call 能力的模型](./examples/best_practices/tutorials/how_to_train_a_function_call_model.md) * [基于 PaddleOCR-VL 微调实现孟加拉语识别能力](./examples/best_practices/PaddleOCR-VL/) * [训练一个支持 Grounding 的模型](./examples/best_practices/tutorials/how_to_train_a_visual_grounding_model.md) ## ➕其他 * [如何下载模型](./docs/zh/how_to_download_model.md) * [常见问题处理](https://github.com/PaddlePaddle/PaddleFormers/issues/3699) ## 💬社区相关 **贡献代码** * 欢迎社区用户为 PaddleFormers 贡献代码,详情请参考 [贡献指南](CONTRIBUTING.md)。 **和我们交流** * 微信扫描二维码并填写问卷,即可加入交流群与众多社区开发者以及官方团队深度交流.
qrcode
## 🙏致谢 我们借鉴了 Hugging Face 的[Transformers](https://github.com/huggingface/transformers)🤗关于预训练模型使用的优秀设计,在此对 Hugging Face 作者及其开源社区表示感谢。 ## 📜许可证 PaddleFormers 遵循[Apache-2.0开源协议](LICENSE)。 ================================================ FILE: docs/en/cli_usage.md ================================================ # CLI ## Overview CLI (Command Line Interface) provides terminal-based interaction with the program, enabling efficient and flexible execution of model training, inference, and evaluation tasks through parameterized configurations. ## Quick Start **Installation** Run in the PaddleFormers root directory: ```bash python -m pip install -e . ``` Verify installation: ```bash paddleformers-cli help ``` Expected output: ``` ------------------------------------------------------------ | Usage: | | paddleformers-cli train : model finetuning | | paddleformers-cli export : model export | | paddleformers-cli help: show helping info | ------------------------------------------------------------ ``` **GPU Configuration** By default, all available gpus are used in CLI. If you wan to specify certain gpus, please set CUDA_VISIBLE_DEVICES before running CLI: ```bash # Single GPU export CUDA_VISIBLE_DEVICES=0 # Multi GPUs export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 # Single XPU export XPU_VISIBLE_DEVICES=0 # Multi XPUs export XPU_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 # Single NPU export ASCEND_RT_VISIBLE_DEVICES=0 # Multi NPUs export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 ``` * Note: In `Chat` module, the number of gpus configured by CUDA_VISIBLE_DEVICES should be equal to `tensor_model_parallel_size` in the config. Alternatively, you can also unset CUDA_VISIBLE_DEVICES. **Proxy Configuration** ```bash export HTTPS_PROXY={your_proxy} export HTTP_PROXY={your_proxy} ``` ## CLI Specific Usage Example using the **Qwen/Qwen3-0.6B-Base** model: ### 1. Chat To be supplemented ### 2. Model Pre-training ```bash # Example 1: PT-Full using online dataset paddleformers-cli train examples/config/pt/full.yaml # Example 2: PT-Full using offline dataset paddleformers-cli train examples/config/pt/full_offline_data.yaml ``` ### 3. Model Fine-tuning #### 3.1. SFT and LoRA Fine-tuning ```bash # Example 1: SFT paddleformers-cli train examples/config/sft/lora.yaml # Example 2: SFT-Full paddleformers-cli train examples/config/sft/full.yaml ``` #### 3.2. DPO and LoRA Fine-tuning ```bash # Example 1: 8K seq length, DPO paddleformers-cli train examples/config/dpo/full.yaml # Example 2: 8K seq length, DPO-LoRA paddleformers-cli train examples/config/dpo/lora.yaml ``` ### 4. Model Evaluation To be supplemented ### 5. Model Export ```bash paddleformers-cli export examples/config/run_export.yaml ``` ### 6. Multi-node Training #### 6.1. Method 1 ```bash NNODES={num_nodes} MASTER_ADDR={your_master_addr} MASTER_PORT={your_master_port} RANK={rank} CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 paddleformers-cli train examples/config/sft_full.yaml ``` #### 6.2. Method 2 (mpirun) First, write a script, such as `scripts/train_96_gpus.sh`, with the following content: ```bash NNODES={num_nodes} MASTER_ADDR={your_master_addr} MASTER_PORT={your_master_port} RANK={rank} CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 paddleformers-cli train examples/config/sft_full.yaml ``` Then: ```bash mpirun bash scripts/train_96_gpus.sh ``` ================================================ FILE: docs/en/datasets.md ================================================ # Data Format Specification ## Pre-training offline dataset - **CLI**: Modify the following fields in the YAML configuration file: - `input_dir` specify the prefix of the dataset, for example: dataset `data-1-part0.bin` need to be set to `input_dir: "1.0 ./data-1-part0"`,`1.0` is the dataset prob - `split` specify `train/eval` distribution ratio, such as: `split: "998,2"`, `train` is the training set, `eval` for the evaluation set - `dataset_type` specify as`pretrain`, such as: `dataset_type: "pretrain"` - Example: ```yaml dataset_type: "pretrain" input_dir: "1.0 ./data/pre-training/demo_data/data-1-part0" split: "998,2" ``` ## Pre-training online dataset + others - **CLI**: Modify the following fields in the YAML config file: - Set `train_dataset_path` / `eval_dataset_path` to the absolute or relative path of your local dataset file - Set `train_dataset_type` / `eval_dataset_type` to the dataset format (erniekit/chatml) - Set `train_dataset_prob` / `eval_dataset_prob` for multi-source dataset mixing probabilities ```yaml # single-source train_dataset_type: "erniekit" train_dataset_path: "./examples/data/sft-train.jsonl" train_dataset_prob: "1.0" # multi-source train_dataset_type: "erniekit,erniekit" train_dataset_path: "./examples/data/sft-train1.jsonl,./examples/data/sft-train2.jsonl" train_dataset_prob: "0.8,0.2" ``` - Supplement: The `truncate_packing` strategy is also supported in the online pre-training data stream, which supports truncating the data to effectively reduce padding tokens. You can use `truncate_packing` by setting it to `True`, as shown in the figure below:
# Data Packing Strategy `Packing` is a technique used to optimize batch processing by combining multiple short input sequences into a single longer sequence before feeding them into the LLM. This reduces padding overhead and improves hardware utilization (e.g., GPU/TPU efficiency). `The greedy intokens strategy` is a token-level optimization that prioritizes filling the available token budget (e.g., max sequence length) in a greedy manner during batch processing. It ensures that the model generates as many tokens as possible within the constraints, minimizing wasted capacity. | packing | greedy_intokens | Packing Strategy | |--------------|-----------------|------------------| | false | any | No packing | | true | false | packing is enabled without greedy intokens strategy | | true | true | greedy intokens packing is enabled | # Data Sampling Strategy Currently, four data sampling strategies are supported: `random`, `concat`, `interleave_under`, `interleave_over` | Data Sampling Strategy | Applicable Scenarios | Limitations | Description | |------------------|-----------------|------------------|------------------| | `random` | The dataset is extremely large and strict data proportioning is required | max_steps > 0 | In `random` mode, based on the input dataset probs, a fixed-size sample pool of `num_samples_each_epoch` is constructed, and the data loader randomly acquires data from this sample pool. | | `concat` | Need to train all data in the datasets | None | In `concat` mode, the input dataset probs are not used. Instead, multiple datasets are directly concatenated. The size of the dataset is equal to the total size of the input multi-source datasets. When max_steps = -1, setting `num_train_epochs` allows for a complete traversal of the input datasets for `num_train_epochs` rounds. | | `interleave_under` | When small datasets are important but have limited samples | None | The `interleave` strategy involves cross-concatenating multiple datasets according to data proportioning. `interleave_under` indicates undersampling, meaning that sampling stops as soon as one of the datasets is exhausted. | | `interleave_over` | When small datasets are important but have limited samples | None | The `interleave` strategy involves cross-concatenating multiple datasets according to data proportioning. `interleave_over` indicates oversampling, meaning that sampling stops only after all datasets have been exhausted. | - Note: `num_samples_each_epoch` only works in `random` data sampling strategy. # Attention Mask The data stream defaults to passing in a causal Attention Mask. In the packing case, when `use_global_causal_attn` is true, it corresponds to the `Causal Attention` shown in the figure below. Different samples within a `Sequence` are visible. When `use_global_causal_attn` is false, it corresponds to the `Causal Document Attention` shown in the figure below. Different samples within a `Sequence` are not visible.
Causal Attention
Causal Attention
Causal Document Attention
Causal Document Attention
================================================ FILE: docs/en/datasets_format.md ================================================ # Data Stream Format Documentation ## Data Stream File Format Support Currently, pre-training and post-training data streams only support the `jsonl` format. ## 1. Pre-training Data Stream ### 1.1. Online Data Stream In the pre-training data stream, each data entry is a dictionary containing the following fields: - `text` : `str, List(str)`, pre-training text. Sample data: ```text {"text": ["An example of a classification problem that requires continuous input values is house price prediction. The price of a house is usually based on factors such as square footage, location, number of bedrooms and bathrooms, and features like a backyard or garage. To accurately predict house prices, these criteria must be entered into the classification model as continuous input values."]} ... ``` For ease of testing, we also provide a [demo dataset](https://paddleformers.bj.bcebos.com/datasets/pt_data.tar.gz) that can be used directly: ```shell wget https://paddleformers.bj.bcebos.com/datasets/pt_data.tar.gz mkdir -p data/pt && tar -xf pt_data.tar.gz -C data/pt/ ``` ### 1.2. Offline Data Stream We can also choose to use offline bit pre-training data streams, which saves more memory. For ease of testing, we also provide an [offline pre-training demo dataset](https://paddleformers.bj.bcebos.com/datasets/pretrain_offline_data.tar.gz) that can be used directly: ```shell wget https://paddleformers.bj.bcebos.com/datasets/pretrain_offline_data.tar.gz tar -xf pretrain_offline_data.tar.gz -C data/pre-training/ ``` You can also create your own offline data stream. The method for creating an offline data stream is as follows: Download a text dataset, such as https://modelscope.cn/datasets/BazingaLyn/mini_pretrain_dataset The format must be jsonl, and the format of each line is like BazingaLyn/mini_pretrain_dataset/pretrain_hq_v7.jsonl: ```text {"text": "Scrambled eggs with tomatoes\nIngredients:\n3 eggs, 1 tomato, oil, salt, sugar, cornstarch\nInstructions:..."} {"text": "Please describe how to properly plan personal finance. Properly planning personal finance requires the following steps..."} {"text": "Please enter a scene dialogue about marine conservation. Person A: Wow, this beach is really..."} {"text": "Identify two different types of wine. The method of identifying wine varies depending on its type and variety, below..."} ``` Run `examples/tools/create_pretraining_data.py`, and the generated data will be saved in `./pretrain_data.bin` and `./pretrain_data.idx` in the current directory. ```text python -u examples/tools/create_pretraining_data.py \ --model_name_or_path "/path/to/your/Qwen3-0.6B-base" \ --data_format "JSON" \ --input_path "/path/to/your/BazingaLyn/mini_pretrain_dataset/pretrain_hq_v7.jsonl" \ --append_eos \ --output_prefix "./pretrain_data" \ --workers 1 \ --log_interval 10000 \ --data_impl "mmap" ``` - Parameter Description | Parameter Name | Type | Description | |--------------------|----------- |-----------------| | `--model_name_or_path` | string | Model path | | `--data_format` | string | Supported file format, currently only supports JSON | | `--input_path` | string | Path to the input json file | | `--append_eos` | store_true | Whether to add an eos token at the end of the document | | `--output_prefix` | str | Prefix of the output file | | `--workers` | int | Number of processes to run | | `--log_interval` | int | Log printing interval | | `--data_impl` | str | Type of dataset to create, default is mmap, can also choose lazy | ## 2. SFT Data Stream ### erniekit format To use the `erniekit` format, specify `erniekit` at `train(/eval)_dataset_type`. In the SFT data stream, each data entry is a dictionary containing the following fields: - `src` : `str, List(str)`, the model's input instructions, prompts, and the task the model should perform. - `tgt` : `str, List(str)`, the model's output. - `system(optional)` : System configuration - `label(optional)`: Training flag (1=participate in training, 0=do not participate in training) - `is_system(optional)` : Indicates whether the first piece of data in src is system Notes: * `src` and `tgt` are list objects that support multi-turn conversations. * Each training sample is in JSON format, with multiple samples separated by line breaks. Sample data: ```json { "system": "You are a life assistant", "src": [ "How can we reduce water consumption in our daily lives?", "Any other suggestions?" ], "tgt": [ "1. Use water-saving devices, such as water-saving shower heads and faucets.", "2. Use tanks or buckets to collect household wastewater, such as dishwashing and bathing. \n3. Raise awareness of water conservation in the community. \n4. Check water pipes and irrigation systems for leaks and repair them promptly. \n5. Shorten shower time and use low-flow shower heads to save water. \n6. Collect rainwater for gardening or other non-drinking purposes. \n7. Turn off the faucet when brushing your teeth or wiping your hands. \n8. Reduce the time spent watering lawns. \n9. Reuse gray water (water from washing machines, bathroom sinks, and showers) as much as possible. \n10. Only buy energy-efficient dishwashers and washing machines." ], "label": [0, 1], } ``` For ease of testing, we also provide the [tatsu-lab/alpaca](https://huggingface.co/datasets/tatsu-lab/alpaca) demo dataset that can be used directly: ```shell wget https://bj.bcebos.com/paddlenlp/datasets/examples/alpaca_demo.gz mkdir -p data/sft && tar -xf alpaca_demo.gz -C data/sft/ --strip-components=1 ``` ### chatml format To use the `chatml` format, specify `chatml` at `train(/eval)_dataset_type`. In the SFT data stream, each data entry is a dictionary containing the following fields: - `messages` : `List(Dict)`, each dictionary contains three keys: `role`, `content`, and `tool_calls(optional)`. - The value of `role` can be `system`, `user`, `assistant` or `tool(optional)`. - `content` is the specific dialogue content. - `tool_calls(optional)` is for requesting tool calls. - `tools(optional)` : `List(Dict)`, represents tool information. - `label(optional)`: Training flag (1=participate in training, 0=do not participate in training) Notes: * Each training sample is in JSON format, with multiple samples separated by line breaks. Sample data: ```json [ { "messages": [ {"role": "system", "content": "You are a good coder."}, {"role": "user", "content": "Given an integer array nums and an integer target value target, find two integers in the array whose sum equals the target value target, and return their array indices. You may assume that each input will have exactly one solution, and you may not use the same element twice. You can return the answer in any order. Example 1: Input: nums = [2,7,11,15], target = 9\nOutput: [0,1]\nExplanation: Because nums[0] + nums[1] == 9, return [0, 1]."}, {"role": "assistant", "content": "We are going to use a hash map (dictionary) to store the numbers we have seen so far along with their indices.\n For each number in the array, we calculate the complement (target - current number).\n If the complement exists in the hash map, that means we have found the two numbers that add up to the target.\n We then return the current index and the index of the complement from the hash map.\n Since we are guaranteed exactly one solution, we can return immediately when we find it.\n\nTo solve this problem efficiently, we can use a hash map to store each number's index as we iterate through the array. For each number, we calculate its complement (target minus the current number). If the complement exists in the hash map, we immediately return the current index and the complement's index. This approach ensures we find the solution in linear time.\n\n### Approach\n1. **Initialization**: Create an empty dictionary to store numbers and their indices.\n2. **Iterate through the array**: For each number in the array:\n - Calculate the complement (target - current number).\n - Check if the complement exists in the dictionary.\n - If found, return the current index and the complement's index.\n - Otherwise, add the current number and its index to the dictionary.\n3. **Result**: Since the problem guarantees exactly one solution, we will always find it during iteration.\n\n### Solution Code\n```python\ndef twoSum(nums, target):\n num_map = {}\n for i, num in enumerate(nums):\n complement = target - num\n if complement in num_map:\n return [num_map[complement], i]\n num_map[num] = i\n```\n\n### Explanation\n- **Initialization**: The dictionary `num_map` will track each number encountered and its index.\n- **Iteration**: For each number `num` at index `i`:\n - Compute `complement = target - num`.\n - If `complement` is in `num_map`, return `[num_map[complement], i]` since these two numbers sum to the target.\n - Otherwise, store `num` with its index in `num_map` for future checks.\n- **Efficiency**: This approach runs in O(n) time, where n is the number of elements, as each dictionary operation (insertion and lookup) is O(1) on average. The space complexity is O(n) to store the dictionary.\n"} ] } ] ``` - Note: The demo datasets provided in `examples/data/sft_think-train.jsonl` and `examples/data/sft_think-eval.jsonl` come from the [OpenCodeReasoning dataset](https://huggingface.co/datasets/nvidia/OpenCodeReasoning) released by nvidia. This dataset needs to follow the Creative Commons Attribution 4.0 International License (CC BY 4.0) agreement. Demo data for function call training: ```json [ { "messages": [ {"role": "user", "content": "I'm feeling a bit down. Can you tell me a joke to cheer me up?"}, {"role": "assistant", "content": "Okay, let me try to figure out how to approach this. The user is feeling down and asks for a joke to cheer up. I need to connect this request to the appropriate function call. Looking at the available tools, there's a function called get_random_joke which is designed exactly for this purpose. Since the user's main need is to feel better, providing a joke makes sense. The function doesn't require any parameters, so it's straightforward to call it without any additional arguments.\n", "tool_calls": [{"type": "function", "function": {"name": "get_random_joke", "arguments": {}}}]}, {"role": "tool", "content": [{"joke": "Why don't scientists trust atoms? Because they make up everything!"}]}, {"role": "assistant", "content": "Sure, here's a joke for you: \"Why don't scientists trust atoms? Because they make up everything!\" I hope that brings a smile to your face."} ], "tools": [ {"type": "function", "function": {"name": "get_random_joke", "description": "Get a random joke", "parameters": {"type": "object", "properties": {}, "required": []}}}, {"type": "function", "function": {"name": "generate_random_number", "description": "Generate a random number within a specified range", "parameters": {"type": "object", "properties": {"min": {"type": "number", "description": "The minimum value of the range"}, "max": {"type": "number", "description": "The maximum value of the range"}}, "required": ["min", "max"]}}} ] } ] ``` For ease of testing, we also provide a `chatml` function call SFT dataset that can be used directly: ```bash wget https://paddleformers.bj.bcebos.com/datasets/sft_function_call_demo.tar.gz mkdir -p data/sft && tar -zxf sft_function_call_demo.tar.gz -C data/sft/ ``` ## 3. DPO Data Stream ### erniekit format To use the `erniekit` format, specify `erniekit` at `train(/eval)_dataset_type`. In the DPO data stream, each data entry is a dictionary containing the following fields: - `system(optional)`: System configuration - `src` : `str, List(str)`, User dialogue content - `tgt` : `str, List(str)`, System reply content (one less than src) - `response` : `str, List(str)`, Contains chosen and rejected replies. - `sort` : `List(int)`, The sort value is used to distinguish between chosen and rejected in the response (the smaller sort value is rejected, and the larger sort value is chosen). - `is_system(optional)` : Indicates whether the first piece of data in src is system Notes: * Each training sample is in JSON format, with multiple samples separated by line breaks. Sample data: ```json { "system": "You are a life assistant", "src": [ "Hello.", "Which is richer in protein, a bed or a wall?" ], "tgt": ["Hello, I am your life assistant."], "response": [ [ "Neither beds nor walls are sources of protein, as they are both inanimate objects. Protein is usually found in foods such as meat, dairy products, beans, and nuts." ], [ "Sorry, I can't answer that question. Please provide more specific information so I know what help you need." ] ], "sort": [ 1, 0 ] } ... ``` For ease of testing, we also provide a preference dataset that can be used directly: ```bash wget https://bj.bcebos.com/paddlenlp/datasets/examples/ultrafeedback_binarized.tar.gz mkdir -p data/dpo && tar -zxf ultrafeedback_binarized.tar.gz -C data/dpo/ --strip-components=1 ``` ### chatml format To use the `chatml` format, specify `chatml` at `train(/eval)_dataset_type`. In the DPO data stream, each data entry is a dictionary containing the following fields: - `messages` : `List(dict)`, a list of dialogue history. - Normal rounds: Contains `role` (`"user"` or `"assistant"`) and `content` (`str`) fields. - Preference/Non-preference rounds (for preference learning): Contains the following two key fields to represent the preference ranking of different system responses to the same user query. - `preferred_output` : `dict`, the preferred (chosen) system response, including fields such as `role` (`"assistant"`) and `content` (`str`), and may include tool call information (`tool_calls`) depending on whether the tool is called. - `non_preferred_output` : `dict`, the non-preferred (rejected) system response, including fields such as `role` (`"assistant"`) and `content` (`str`). - `tools` : `List(dict)`, a list of definitions of tools (functions) that may be used in the dialogue. - `label` : `List(int)`, a sorting label used to distinguish between `preferred_output` and `non_preferred_output`. Where 0 corresponds to `non_preferred_output` (rejected) and 1 corresponds to `preferred_output` (chosen). Detailed data format can be found in [function call instructions](https://github.com/PaddlePaddle/PaddleFormers/blob/develop/examples/best_practices/function_call.md) Sample data ```json { "messages": [ { "role": "system", "content": "You are a function calling AI model. You are provided with function signatures within XML tags. You may call one or more functions to assist with the user query. Don't make assumptions about what values to plug into functions.\n\n[{'type': 'function', 'function': {'name': 'play_music', 'description': 'Play music from a specified playlist or genre', 'parameters': {'type': 'object', 'properties': {'playlist': {'type': 'string', 'description': 'The playlist to play'}, 'genre': {'type': 'string', 'description': 'The genre of music to play'}}, 'required': []}}}, {'type': 'function', 'function': {'name': 'analyze_sentiment', 'description': 'Analyze the sentiment of a text', 'parameters': {'type': 'object', 'properties': {'text': {'type': 'string', 'description': 'The text to analyze'}, 'language': {'type': 'string', 'description': 'The language of the text (optional)'}}, 'required': ['text']}}}]\n\nFor each function call return a json object with function name and arguments within XML tags with the following schema:\n\n{'arguments': , 'name': }\n\n" }, { "role": "user", "content": "I want to listen to some music. Can you play something for me?" }, { "preferred_output": { "role": "assistant", "content": "Of course! Do you have a specific playlist or genre in mind?" }, "non_preferred_output": { "role": "assistant", "content": "", "tool_calls": [ { "type": "function", "function": { "name": "play_music", "arguments": "{\n\t\"playlist\": \"Top hits\"\n}" } } ] } } ], "tools": [ { "type": "function", "function": { "name": "play_music", "description": "Play music from a specified playlist or genre", "parameters": { "type": "object", "properties": { "playlist": { "type": "string", "description": "The playlist to play" }, "genre": { "type": "string", "description": "The genre of music to play" } }, "required": [] } } }, ], "label": [ 1, 0 ] } ``` For ease of testing, we also provide a `chatml` function call DPO dataset that can be used directly: ```bash wget https://paddleformers.bj.bcebos.com/datasets/dpo_function_call_1k.tar.gz mkdir -p data/dpo_fc && tar -zxf dpo_function_call_1k.tar.gz -C data/dpo_fc/ ``` ================================================ FILE: docs/en/image_processors.md ================================================ ### 🏞️ Image Processor `Image Processor` is an image preprocessing tool responsible for preparing input features for vision or multimodal models. It provides various transformations, such as resizing and normalization, and supports returning outpus in Paddle Tensor. It acts as a bridge between raw image data and the model, ensuring that input features are optimized for VLMs (Vision-Language Models. Using the `[~BaseImageProcessor.from_pretrained]` method, you can easily load the processor configuration associated with a pretrained model (e.g., target image size, normalization settings). When loading, the Image Processor automatically reads the `preprocessor_config.json` file from the model directory to ensure the preprocessing steps are identical to those used during model trainging or inference. The method supports loading from a **local directory** or **multiple download sources**: - [huggingface](https://huggingface.co) (**Default**) - [modelscope](https://modelscope.cn/home) - [aistudio](https://aistudio.baidu.com/overview) ### 💻 Usage Example Here’s how to load an `Image Processor` and process image data with [Qwen2.5-VL-3B-Instruct](https://huggingface.co/Qwen/Qwen2.5-VL-3B-Instruct). ```python from paddleformers.transformers import AutoImageProcessor from PIL import Image import requests image_processor = AutoImageProcessor.from_pretrained("Qwen/Qwen2.5-VL-3B-Instruct") url = "https://paddlenlp.bj.bcebos.com/datasets/paddlemix/demo_images/example1.jpg" image = Image.open(requests.get(url, stream=True).raw).convert("RGB") processed_image = image_processor(image, return_tensors="pd") # return Paddle Tensor ``` > **How to change the download source?** > > You can specify the model download source in two ways: > > - Via the `download_hub` parameter, passed directly in the `from_pretrained` method. > > ```python > image_processor = AutoImageProcessor.from_pretrained( > "Qwen/Qwen2.5-VL-3B-Instruct", > download_hub="modelscope" > ) > ``` > > - Via the `DOWNLOAD_SOURCE` environment variable, to change the default download source. > ```bash > export DOWNLOAD_SOURCE=aistudio > ``` ================================================ FILE: docs/en/processors.md ================================================ ### ⚙️ Processors `Processor` is a multimodal preprocessing tool responsible for preparing inputs that combine more than one modality (like text, images). It provides a unified interface for different transformations, such as tokenizing text and resizing/normalizing images, and supports returning outpus in Paddle Tensor. For example, [Qwen2.5-VL](https://github.com/PaddlePaddle/PaddleFormers/blob/develop/paddleformers/transformers/qwen2_5_vl/processor.py) is a vision-language model that uses the [Qwen2-VL](https://github.com/PaddlePaddle/PaddleFormers/blob/develop/paddleformers/transformers/qwen2_vl/image_processor.py) image processor and the [Qwen2](https://github.com/PaddlePaddle/PaddleFormers/blob/develop/paddleformers/transformers/qwen2/tokenizer.py) tokenizer. A `ProcessorMixin` class wraps both of these, providing a single class for the model. Using the `[~ProcessorMixin.from_pretrained]` method, you can easily load the processor configuration associated with a pretrained model (e.g., target image size, tokenization vocabulary). The Processor automatically loads all necessary configuration files (like `processor_config.json`, `preprocessor_config.json`, `tokenizer_config.json`, etc.) from the model directory to ensure the preprocessing steps are identical to those used during model training or inference. The method supports loading from a **local directory** or **multiple download sources**: - [huggingface](https://huggingface.co) (**Default**) - [modelscope](https://modelscope.cn/home) - [aistudio](https://aistudio.baidu.com/overview) ### 💻 Usage Example Here’s how to load an `Processor` and process image/video data with [Qwen2.5-VL-3B-Instruct](https://huggingface.co/Qwen/Qwen2.5-VL-3B-Instruct). - Case 1: Processing image and text directly: ```python from paddleformers.transformers import AutoProcessor from PIL import Image import requests processor = AutoProcessor.from_pretrained("Qwen/Qwen2.5-VL-3B-Instruct") text = "Describe this image." url = "https://paddlenlp.bj.bcebos.com/datasets/paddlemix/demo_images/example1.jpg" image = Image.open(requests.get(url, stream=True).raw).convert("RGB") inputs = processor(text=text, images=image, return_tensors="pd") # return Paddle Tensor ``` - Case 2: Handling conversational inputs (chat-formatted messages[image]): ```python from paddleformers.transformers import AutoProcessor from paddleformers.transformers import process_vision_info # Processing functions for QwenVL models processor = AutoProcessor.from_pretrained("Qwen/Qwen2.5-VL-3B-Instruct") messages = [ { "role": "user", "content": [ { "type": "image", "image": "https://paddlenlp.bj.bcebos.com/datasets/paddlemix/demo_images/example1.jpg", }, {"type": "text", "text": "Describe this image."}, ], } ] text = processor.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) image_inputs, video_inputs = process_vision_info(messages) inputs = processor( text=[text], images=image_inputs, videos=video_inputs, padding=True, return_tensors="pd", ) ``` - Case 3: Handling conversational inputs (chat-formatted messages[video]): ```python from paddleformers.transformers import AutoProcessor from paddleformers.transformers import process_vision_info # Processing functions for QwenVL models processor = AutoProcessor.from_pretrained("Qwen/Qwen2.5-VL-3B-Instruct") messages = [ { "role": "user", "content": [ { "type": "video", "video": "http://paddlenlp.bj.bcebos.com/datasets/paddlemix/demo_video/example_video.mp4", }, {"type": "text", "text": "Describe this video."}, ], } ] text = processor.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) image_inputs, video_inputs = process_vision_info(messages, video_backend="paddlecodec") # load_video backend support: ["paddlecodec", "decord"], default: "paddlecodec" inputs = processor( text=[text], images=image_inputs, videos=video_inputs, padding=True, return_tensors="pd", ) ``` - Case 3: Handling conversational inputs (chat-formatted messages[video]): ```python processor = AutoProcessor.from_pretrained("Qwen/Qwen3-Omni-30B-A3B-Instruct", download_hub="modelscope") text = "What can you see and hear? Answer in one short sentence." image_url = "https://paddlenlp.bj.bcebos.com/datasets/paddlemix/demo_images/example1.jpg" audio_url = "https://paddlenlp.bj.bcebos.com/models/community/paddlemix/audio-files/wave.wav" image_response = requests.get(image_url) audio_response = requests.get(audio_url) with open("./example1.jpg", "wb") as f: f.write(image_response.content) with open("./wave.wav", "wb") as f: f.write(audio_response.content) conversation = [ { "role": "user", "content": [ {"type": "image", "image": "./example1.jpg"}, {"type": "audio", "audio": "./wave.wav"}, {"type": "text", "text": "What can you see and hear? Answer in one short sentence."}, ], }, ] USE_AUDIO_IN_VIDEO = True text = processor.apply_chat_template(conversation, add_generation_prompt=True, tokenize=False) audios, images, videos = process_mm_info(conversation, use_audio_in_video=USE_AUDIO_IN_VIDEO) inputs = processor( text=text, audio=audios, images=images, videos=videos, return_tensors="pd", padding=True, use_audio_in_video=USE_AUDIO_IN_VIDEO, ) ``` > **How to change the download source?** > > You can specify the model download source in two ways: > > - Via the `download_hub` parameter, passed directly in the `from_pretrained` method. > > ```python > processor = AutoProcessor.from_pretrained( > "Qwen/Qwen2.5-VL-3B-Instruct", > download_hub="modelscope" > ) > ``` > > - Via the `DOWNLOAD_SOURCE` environment variable, to change the default download source. > ```bash > export DOWNLOAD_SOURCE=aistudio > ``` ================================================ FILE: docs/en/video_processors.md ================================================ ### 🎬 Video Processor `Video Processor` is a video preprocessing tool responsible for preparing input features for multimodal models and processing their outputs. It provides various transformations, such as resizing and normalization, and supports returning outpus in Paddle Tensor. The Video Processor extends the functionality of an image processor to handle video inputs, allowing models to process videos using a different set of parameters than images. It acts as a bridge between raw video data and the model, ensuring that input features are optimized for VLM (Vision-Language Model). Using the `[~BaseVideoProcessor.from_pretrained]` method, you can easily load the processor configuration associated with a pretrained model (e.g., target image size, normalization settings). When loading, the Video Processor automatically reads the `video_preprocessor_config.json` or `preprocessor_config.json` file from the model directory to ensure the preprocessing steps are identical to those used during model inference. The method supports loading from a **local directory** or **multiple download sources**: - [huggingface](https://huggingface.co) (**Default**) - [modelscope](https://modelscope.cn/home) - [aistudio](https://aistudio.baidu.com/overview) ### 💻 Usage Example Here’s how to load a`Video Processor` and process video data with [Qwen2.5-VL-3B-Instruct](https://huggingface.co/Qwen/Qwen2.5-VL-3B-Instruct). ```python from paddleformers.transformers import AutoVideoProcessor from paddleformers.transformers.video_utils import load_video video_processor = AutoVideoProcessor.from_pretrained("Qwen/Qwen2.5-VL-3B-Instruct") video = load_video("your_video.mp4", video_backend="paddlecodec") # or video URL. load_video backend support: ["paddlecodec", "decord"], default: "paddlecodec" processed_video = video_processor(video[0], return_tensors="pd") # return Paddle Tensor ``` > **How to change the download source?** > > You can specify the model download source in two ways: > > - Via the `download_hub` parameter, passed directly in the `from_pretrained` method. > > ```python > video_processor = AutoVideoProcessor.from_pretrained( > "Qwen/Qwen2.5-VL-3B-Instruct", > download_hub="modelscope" > ) > ``` > > - Via the `DOWNLOAD_SOURCE` environment variable, to change the default download source. > ```bash > export DOWNLOAD_SOURCE=aistudio > ``` ================================================ FILE: docs/zh/ILUVATAR-GPU_installation_guide.md ================================================ # 1. 安装 **环境依赖** |Chip type|Driver version| |-|-| |BI150|4.3.8| * **机器:** BI150/BI150s 64GB 8-card machine * **镜像:** ccr-2vdh3abv-pub.cnc.bj.baidubce.com/device/paddle-ixuca:3.3.0 * **GCC path:** /usr/bin/gcc (9.4) * **python version:** 3.10 要验证 Iluvatar GPU 是否正常,可以使用`ixsmi`命令 ```shell ixsmi #example:$ ixsmi Timestamp Thu Jul 10 16:59:37 2025 +-----------------------------------------------------------------------------+ | IX-ML: 4.3.0 Driver Version: 4.3.0 CUDA Version: 10.2 | |-------------------------------+----------------------+----------------------| | GPU Name | Bus-Id | Clock-SM Clock-Mem | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 Iluvatar BI-V150 | 00000000:13:00.0 | 1500MHz 1600MHz | | N/A 35C P0 N/A / N/A | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 1 Iluvatar BI-V150 | 00000000:16:00.0 | 1500MHz 1600MHz | | N/A 34C P0 103W / 350W | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 2 Iluvatar BI-V150 | 00000000:1C:00.0 | 1500MHz 1600MHz | | N/A 35C P0 N/A / N/A | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 3 Iluvatar BI-V150 | 00000000:1F:00.0 | 1500MHz 1600MHz | | N/A 34C P0 106W / 350W | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 4 Iluvatar BI-V150 | 00000000:27:00.0 | 1500MHz 1600MHz | | N/A 35C P0 N/A / N/A | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 5 Iluvatar BI-V150 | 00000000:2A:00.0 | 1500MHz 1600MHz | | N/A 35C P0 105W / 350W | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 6 Iluvatar BI-V150 | 00000000:34:00.0 | 1500MHz 1600MHz | | N/A 34C P0 N/A / N/A | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 7 Iluvatar BI-V150 | 00000000:37:00.0 | 1500MHz 1600MHz | | N/A 34C P0 106W / 350W | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 8 Iluvatar BI-V150 | 00000000:3D:00.0 | 1500MHz 1600MHz | | N/A 34C P0 N/A / N/A | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 9 Iluvatar BI-V150 | 00000000:40:00.0 | 1500MHz 1600MHz | | N/A 35C P0 107W / 350W | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 10 Iluvatar BI-V150 | 00000000:48:00.0 | 1500MHz 1600MHz | | N/A 34C P0 N/A / N/A | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 11 Iluvatar BI-V150 | 00000000:4B:00.0 | 1500MHz 1600MHz | | N/A 33C P0 103W / 350W | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 12 Iluvatar BI-V150 | 00000000:54:00.0 | 1500MHz 1600MHz | | N/A 34C P0 N/A / N/A | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 13 Iluvatar BI-V150 | 00000000:57:00.0 | 1500MHz 1600MHz | | N/A 35C P0 104W / 350W | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 14 Iluvatar BI-V150 | 00000000:64:00.0 | 1500MHz 1600MHz | | N/A 35C P0 N/A / N/A | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 15 Iluvatar BI-V150 | 00000000:67:00.0 | 1500MHz 1600MHz | | N/A 36C P0 107W / 350W | 64MiB / 32768MiB | 0% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Process name Usage(MiB) | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+ ``` **安装依赖** 1. 拉取镜像 ```shell docker pull ccr-2vdh3abv-pub.cnc.bj.baidubce.com/device/paddle-ixuca:3.3.0 ``` 2. 启动 docker ```shell docker run -itd --name paddleformers-ixuca --network host -v /usr/src:/usr/src -v /lib/modules:/lib/modules -v /dev:/dev -v /home:/home -v /data:/data --privileged --cap-add=ALL --pid=host ccr-2vdh3abv-pub.cnc.bj.baidubce.com/device/paddle-ixuca:3.3.0 docker exec -it paddleformers-ixuca bash ``` 3. 安装 PaddlePaddle ```shell # 推荐使用 Paddle 3.3.0 版本 python -m pip install paddlepaddle==3.3.0 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/ python -m pip install paddle-iluvatar-gpu==3.3.0 -i https://www.paddlepaddle.org.cn/packages/stable/ixuca/ # 如果想用 nightly 的 PaddlePaddle: python -m pip install --pre paddlepaddle -i https://www.paddlepaddle.org.cn/packages/nightly/cpu/ python -m pip install --pre paddle-iluvatar-gpu -i https://www.paddlepaddle.org.cn/packages/nightly/ixuca/ ``` 4. 安装 PaddleFormers ```shell git clone https://github.com/PaddlePaddle/PaddleFormers.git cd PaddleFormers python -m pip install -e . ``` # 2. 开始训练 所有示例脚本都位于 examples/config/iluvatar 下。下面以 ERNIE-4.5-21B-A3B-PT 的 SFT 为例。首先需要通过 Huggingface 下载模型: ```shell hf download baidu/ERNIE-4.5-21B-A3B-PT --local-dir baidu/ERNIE-4.5-21B-A3B-PT ``` 如果需要对 ERNIE-4.5-21B-A3B-PT 进行全参数 SFT: ```shell bash examples/config/iluvatar/ERNIE-4.5-21B-A3B-PT/sft/run_full_8k.sh ``` 如果需要对 ERNIE-4.5-21B-A3B-PT 进行基于 LoRA 的 SFT: ```shell bash examples/config/iluvatar/ERNIE-4.5-21B-A3B-PT/sft/run_lora_8k.sh ``` 训练产物位于 checkpoints 下,如果要使用 FastDeploy 进行推理,请先参考[https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/zh/get_started/installation/iluvatar_gpu.md](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/zh/get_started/installation/iluvatar_gpu.md) 安装 FastDeploy。 加载 ERNIE-4.5-21B-A3B-PT 全参数 SFT 后的权重进行推理: ```shell python3 -m fastdeploy.entrypoints.openai.api_server --model checkpoints/ernie-21B-sft-full-tp-pp/ --port 8180 --tensor-parallel-size 1 --quantization wint8 --max-model-len 32768 --max-num-seqs 8 --block-size 16 ``` 加载 ERNIE-4.5-21B-A3B-PT SFT-LoRA 后的权重进行推理: ```shell # 导出权重 bash examples/config/iluvatar/ERNIE-4.5-21B-A3B-PT/sft/run_full_export.sh # 进行推理 python3 -m fastdeploy.entrypoints.openai.api_server --model checkpoints/ernie-sft-lora-tp-pp/export/ --port 8180 --tensor-parallel-size 1 --quantization wint8 --max-model-len 32768 --max-num-seqs 8 --block-size 16 ``` ================================================ FILE: docs/zh/ILUVATAR-GPU_usage_guide.md ================================================ # 模型列表和使用说明 |Model Name|Training Method|Context Length|Quantization|ILUVATAR-GPUs Required|Deployment Commands|Applicable Version| |-|-|-|-|-|-|-| |ERNIE-4.5-21B-A3B-PT|SFT-Full|8K|BF16|8卡16芯|bash examples/config/iluvatar/ERNIE-4.5-21B-A3B-PT/sft/run_full_8k.sh|1.0| |ERNIE-4.5-21B-A3B-PT|SFT-LoRA|8K|BF16|4卡8芯|bash examples/config/iluvatar/ERNIE-4.5-21B-A3B-PT/sft/run_lora_8k.sh|1.0| |ERNIE-4.5-0.3B-PT|SFT-Full|8K|BF16|单卡单芯|bash examples/config/iluvatar/ERNIE-4.5-0.3B-PT/sft/run_full_8k.sh|1.0| |ERNIE-4.5-0.3B-PT|SFT-LoRA|8K|BF16|单卡单芯|bash examples/config/iluvatar/ERNIE-4.5-0.3B-PT/sft/run_lora_8k.sh|1.0| |PaddleOCR-VL-0.9B|SFT-Full|16K|BF16|单卡单芯|bash bash examples/config/iluvatar/PaddleOCR-VL/sft/run_paddleocr-vl_full_16k.sh|1.0| |PaddleOCR-VL-0.9B|SFT-LoRA|16K|BF16|单卡单芯|bash bash examples/config/iluvatar/PaddleOCR-VL/sft/run_paddleocr-vl_lora_16k.sh|1.0| ================================================ FILE: docs/zh/Metax-GPU_installation_guide.md ================================================ # 1. 安装 **环境依赖** |Chip type|Driver version| |-|-| |MetaX C550|2.15.9| * **机器:** MetaX C550 64GB 8-card machine * **镜像:** cr.metax-tech.com/public-ai-release/maca/paddle-metax:3.3.0-maca.ai3.3.0.10-py310-ubuntu22.04-amd64 * **GCC path:** /usr/bin/gcc (9.4) * **python version:** 3.10 要验证 Metax GPU 是否正常,可以使用`mx-smi`命令 ```shell mx-smi #example:$ mx-smi mx-smi version: 2.2.4 =================== MetaX System Management Interface Log =================== Timestamp : Tue Jul 29 12:16:08 2025 Attached GPUs : 8 +---------------------------------------------------------------------------------+ | MX-SMI 2.2.4 Kernel Mode Driver Version: 2.15.9 | | MACA Version: 2.32.0.6 BIOS Version: 1.25.1.0 | |------------------------------------+---------------------+----------------------+ | GPU NAME | Bus-id | GPU-Util | | Temp Pwr:Usage/Cap | Memory-Usage | GPU-State | |====================================+=====================+======================| | 0 MetaX C550 | 0000:0f:00.0 | 0% | | 29C 53W / 450W | 858/65536 MiB | Available | +------------------------------------+---------------------+----------------------+ | 1 MetaX C550 | 0000:34:00.0 | 0% | | 29C 53W / 450W | 858/65536 MiB | Available | +------------------------------------+---------------------+----------------------+ | 2 MetaX C550 | 0000:48:00.0 | 0% | | 30C 54W / 450W | 858/65536 MiB | Available | +------------------------------------+---------------------+----------------------+ | 3 MetaX C550 | 0000:5a:00.0 | 0% | | 29C 54W / 450W | 858/65536 MiB | Available | +------------------------------------+---------------------+----------------------+ | 4 MetaX C550 | 0000:87:00.0 | 0% | | 30C 53W / 450W | 858/65536 MiB | Available | +------------------------------------+---------------------+----------------------+ | 5 MetaX C550 | 0000:ae:00.0 | 0% | | 32C 55W / 450W | 858/65536 MiB | Available | +------------------------------------+---------------------+----------------------+ | 6 MetaX C550 | 0000:c2:00.0 | 0% | | 32C 56W / 450W | 858/65536 MiB | Available | +------------------------------------+---------------------+----------------------+ | 7 MetaX C550 | 0000:d7:00.0 | 0% | | 31C 56W / 450W | 858/65536 MiB | Available | +------------------------------------+---------------------+----------------------+ +---------------------------------------------------------------------------------+ | Process: | | GPU PID Process Name GPU Memory | | Usage(MiB) | |=================================================================================| | no process found | +---------------------------------------------------------------------------------+ ``` **安装依赖** 1. 拉取镜像(以 release3.3为例) ```shell docker pull cr.metax-tech.com/public-ai-release/maca/paddle-metax:3.3.0-maca.ai3.3.0.10-py310-ubuntu22.04-amd64 ``` 2. 启动 docker ```shell docker run \ -it \ --device=/dev/dri \ --device=/dev/mxcd \ --device=/dev/infiniband \ --group-add video \ --name \ --network=host \ --uts=host \ --ipc=host \ --privileged=true \ --security-opt seccomp=unconfined \ --security-opt apparmor=unconfined \ --shm-size '500gb' \ --ulimit memlock=-1 \ -v /sw_home/:/sw_home/ \ -v /pde_ai/:/pde_ai/ \ -v /mxstorage/:/mxstorage/ \ mxcr.io/ai-release/maca/paddle-metax:3.3.0-maca.ai3.3.0.0-py310-ubuntu22.04-amd64 \ /bin/bash ``` 3. 进入容器运行环境 ```shell docker exec -it ``` 4. 初始化容器 ```shell apt update apt install -y libglib2.0-dev apt install -y unzip apt install -y vim git #unzip libgl1-mesa-glx libsm6 libxext6 ffmpeg apt-get install -y libssl-dev ``` 5. 拉取代码分支 ```shell git clone https://github.com/PaddlePaddle/PaddleFormers.git cd PaddleFormers python -m pip install -e . ``` # 2. 开始训练 所有示例脚本都位于 examples/config/metax 下。下面以 ERNIE-4.5-21B-A3B-PT 的 SFT 为例。首先需要通过 Huggingface 下载模型: ```shell hf download baidu/ERNIE-4.5-21B-A3B-PT --local-dir baidu/ERNIE-4.5-21B-A3B-PT ``` 如果需要对 ERNIE-4.5-21B-A3B-PT 进行全参数 SFT: ```shell bash ./examples/config/metax/ERNIE-4.5-21B-A3B/sft/run_sft.sh ``` 如果需要对 ERNIE-4.5-21B-A3B-PT 进行基于 LoRA 的 SFT: ```shell bash ./examples/config/metax/ERNIE-4.5-21B-A3B/sft/run_lora.sh ``` 训练产物位于 checkpoints 下,如果要使用 FastDeploy 进行推理,请参考[https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/zh/get_started/installation/metax_gpu.md](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/zh/get_started/installation/metax_gpu.md) ================================================ FILE: docs/zh/Metax-GPU_usage_guide.md ================================================ # 模型列表和使用说明 |Model Name|Training Method|Context Length|Quantization|Metax-GPUs Required|Deployment Commands|Applicable Version| |-|-|-|-|-|-|-| |ERNIE-4.5-21B-A3B|SFT-Full|8K|BF16|8|bash ./examples/config/metax/ERNIE-4.5-21B-A3B/sft/run_sft.sh|1.0| |ERNIE-4.5-21B-A3B|SFT-Lora|8K|BF16|8|bash ./examples/config/metax/ERNIE-4.5-21B-A3B/sft/run_lora.sh|1.0| |ERNIE-4.5-0.3B|SFT-Full|8K|BF16|1|bash ./examples/config/metax/ERNIE-4.5-0.3B/sft/run_sft.sh|1.0| |ERNIE-4.5-0.3B|SFT-Lora|8K|BF16|1|bash ./examples/config/metax/ERNIE-4.5-0.3B/sft/run_lora.sh|1.0| ================================================ FILE: docs/zh/XPU_installation_guide.md ================================================ # 1. 安装 **环境依赖** |Chip type|Driver version| |-|-| |KunlunxinP800|5.0.21.26| * **机器:** KunlunxinP800 96GB 8-card machine * **镜像:** ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddleqa:xpu-ubuntu2204-x86_64-gcc123-py310 * **GCC path:** /usr/bin/gcc (12.3) * **python version:** 3.10 要验证 XPU 是否正常,可以使用`xpu_smi`命令 ```shell xpu_smi #example:$ xpu_smi Thu Feb 5 13:00:00 2026 +-----------------------------------------------------------------------------+ | XPU-SMI Driver Version: 5.0.21.26 XPU-RT Version: 5.0.21 | |-------------------------------+----------------------+----------------------+ | XPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | XPU-Util Compute M. | | | L3-Usage | SR-IOV M. | |===============================+======================+======================| | 0 P800 OAM N/A | 00000000:03:00.0 N/A | 0 | | N/A 37C N/A 85W / 400W | 0MiB / 98304MiB | 0% Default | | | 0MiB / 96MiB | Disabled | +-------------------------------+----------------------+----------------------+ | 1 P800 OAM N/A | 00000000:05:00.0 N/A | 0 | | N/A 41C N/A 86W / 400W | 0MiB / 98304MiB | 0% Default | | | 0MiB / 96MiB | Disabled | +-------------------------------+----------------------+----------------------+ | 2 P800 OAM N/A | 00000000:63:00.0 N/A | 0 | | N/A 34C N/A 85W / 400W | 0MiB / 98304MiB | 0% Default | | | 0MiB / 96MiB | Disabled | +-------------------------------+----------------------+----------------------+ | 3 P800 OAM N/A | 00000000:65:00.0 N/A | 0 | | N/A 39C N/A 88W / 400W | 0MiB / 98304MiB | 0% Default | | | 0MiB / 96MiB | Disabled | +-------------------------------+----------------------+----------------------+ | 4 P800 OAM N/A | 00000000:83:00.0 N/A | 0 | | N/A 37C N/A 86W / 400W | 0MiB / 98304MiB | 0% Default | | | 0MiB / 96MiB | Disabled | +-------------------------------+----------------------+----------------------+ | 5 P800 OAM N/A | 00000000:85:00.0 N/A | 0 | | N/A 42C N/A 86W / 400W | 0MiB / 98304MiB | 0% Default | | | 0MiB / 96MiB | Disabled | +-------------------------------+----------------------+----------------------+ | 6 P800 OAM N/A | 00000000:A3:00.0 N/A | 0 | | N/A 35C N/A 86W / 400W | 0MiB / 98304MiB | 0% Default | | | 0MiB / 96MiB | Disabled | +-------------------------------+----------------------+----------------------+ | 7 P800 OAM N/A | 00000000:A5:00.0 N/A | 0 | | N/A 42C N/A 88W / 400W | 0MiB / 98304MiB | 0% Default | | | 0MiB / 96MiB | Disabled | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | XPU XI CI PID Type Process name XPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+ ``` **安装依赖** 1. 拉取镜像 ```shell docker pull ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddleqa:xpu-ubuntu2204-x86_64-gcc123-py310 ``` 2. 启动 docker ```shell # Recommended: Map your project directory and a dataset directory # Replace pwd with the actual path on your host machine docker run -it --privileged=true --net host --shm-size '256gb' --device=/dev/xpu0:/dev/xpu0 --device=/dev/xpu1:/dev/xpu1 --device=/dev/xpu2:/dev/xpu2 --device=/dev/xpu3:/dev/xpu3 --device=/dev/xpu4:/dev/xpu4 --device=/dev/xpu5:/dev/xpu5 --device=/dev/xpu6:/dev/xpu6 --device=/dev/xpu7:/dev/xpu7 --device=/dev/xpuctrl:/dev/xpuctrl --name paddle-xpu-dev -v $(pwd):/work -w=/work -v xxx ccr-2vdh3abv-pub.cnc.bj.baidubce.com/paddlepaddle/paddleqa:xpu-ubuntu2204-x86_64-gcc123-py310 /bin/bash ``` 3. 安装 PaddlePaddle ```shell # 推荐使用 Paddle 3.3.0 版本 python -m pip install https://paddle-qa.bj.bcebos.com/PaddleFormers/xpu_whl/paddlepaddle_xpu-3.3.0.dev20260122-cp310-cp310-linux_x86_64.whl # 如果想用 nightly 的 PaddlePaddle: python -m pip install --pre paddlepaddle-xpu -i https://www.paddlepaddle.org.cn/packages/nightly/xpu-p800/ ``` 4. 安装 PaddleFormers ```shell git clone https://github.com/PaddlePaddle/PaddleFormers.git cd PaddleFormers python -m pip install -e . ``` # 2. 开始训练 所有示例脚本都位于 examples/config/xpu 下。下面以 ERNIE-4.5-21B-A3B-PT 的 SFT 为例。首先需要通过 Huggingface 下载模型: ```shell hf download baidu/ERNIE-4.5-21B-A3B-PT --local-dir baidu/ERNIE-4.5-21B-A3B-PT ``` 如果需要对 ERNIE-4.5-21B-A3B-PT 进行全参数 SFT: ```shell paddleformers-cli train examples/config/xpu/ERNIE-4.5-21B-A3B/sft/full_32k.yaml ``` 如果需要对 ERNIE-4.5-21B-A3B-PT 进行基于 LoRA 的 SFT: ```shell bash train examples/config/xpu/ERNIE-4.5-21B-A3B/sft/run_lora_32k.sh ``` 训练产物位于 checkpoints 下,如果要使用 FastDeploy 进行推理,请先参考[https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/zh/get_started/installation/kunlunxin_xpu.md](https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/zh/get_started/installation/kunlunxin_xpu.md) ================================================ FILE: docs/zh/XPU_usage_guide.md ================================================ # 模型列表和使用说明 |Model Name|Training Method|Context Length|Quantization|XPUs Required|Deployment Commands|Applicable Version| |-|-|-|-|-|-|-| |ERNIE-4.5-21B-A3B|SFT|32K|BF16|8|paddleformers-cli train examples/config/xpu/ERNIE-4.5-21B-A3B/sft/full_32k.yaml|1.0| ||SFT-LoRA|32K|BF16|4|bash train examples/config/xpu/ERNIE-4.5-21B-A3B/sft/run_lora_32k.sh|1.0| |ERNIE-4.5-0.3B|SFT|8k|BF16|1|paddleformers-cli train examples/config/xpu/ERNIE-4.5-0.3B/sft/full_8k.yaml|1.0| ||SFT-LoRA|8k|BF16|1|paddleformers-cli train examples/config/xpu/ERNIE-4.5-0.3B/sft/lora_8k.yaml|1.0| |PaddleOCR-VL-0.9B|SFT-Full|16K|BF16|1|bash examples/config/xpu/PaddleOCR-VL/sft/run_paddleocr-vl_full_16k.sh|1.0| ||SFT-LoRA|16K|BF16|1|bash examples/config/xpu/PaddleOCR-VL/sft/run_paddleocr-vl_lora_16k.sh|1.0| |DeepSeek-V3|SFT-Full|32K|BF16|128|mpirun bash ./examples/config/xpu/DeepseekV3/sft/run_full_32k.sh|1.0| ================================================ FILE: docs/zh/chat_template_guide.md ================================================ # 1. 背景说明 大语言模型依托对话交互能力,能够输出符合人类语境的智能回复。而这一能力需依托 **Chat Template **结构化标注角色与上下文,定义多轮对话数据如何被转换为模型可训练的 token 序列,从而确保交互逻辑精准。 **Chat Template ** 规定了: * 不同角色(如 `system / user / assistant`)的拼接方式 * 特殊 token(如 BOS / EOS / role token)的插入规则 * 哪些 token 参与 loss 计算(label / mask 规则) # 2. 使用说明 PaddleFormers 内置了常用模型的默认 Chat Template,普通用户无需额外开发,在训练配置中指定使用即可,如 qwen3: ```yaml template_backend: custom template: qwen3 ``` 值得注意的是,哪怕是同一系列的模型,在不同训练任务(如 思考模型和非思考模型)对 label 和 mask 的策略也存在差异,务必确保为对应的模型设置正确的 Chat Template,使用不匹配的 Chat Template 可能导致: * 训练不收敛或效果明显下降 * 对话边界学习错误 * 推理阶段输出异常 在模型列表中,我们给出了不同模型训练时所需使用的 Template,在训练时请按照表格所建议的 Template 进行设置。 # 3. 自定义新的 Template 在以下情况中,您可能想要使用自己定义的 Chat Template: * 希望自定义对话格式或特殊 token 规则 * 新增或接入框架尚未内置的新模型 * 需要调整 label / mask 行为(如特殊 EOS、packing 场景) 在这些情况下,您需要显式注册 Chat Template,以确保模型输入格式与训练目标一致。 对于未注册的情况,框架将使用对应模型的默认模板。 ## 3.1. 注册方法 在 `paddleformers/datasets/template/template.py` 文件中实现模型 chat template 的注册,如: ```python register_template( name="glm4_moe", format_user=StringFormatter(slots=["<|user|>\n{{content}}<|assistant|>\n"]), format_assistant=StringFormatter(slots=["\n{{content}}"]), format_system=StringFormatter(slots=["[gMASK]<|system|>\n{{content}}"]), format_function=FunctionFormatter(slots=["{{content}}"], tool_format="glm4_moe"), format_observation=StringFormatter(slots=["<|observation|>\n{{content}}<|assistant|>"]), format_tools=ToolFormatter(tool_format="glm4_moe"), format_prefix=EmptyFormatter(slots=["[gMASK]"]), suffix=["<|user|>"], thought_words=("", ""), template_class=ReasoningTemplate, ) ``` ## 3.2. 参数说明 |参数名|解释| |-|-| |`name`|template 的名字,也就是训练的时候需要指定的 template 参数| |`format_user`|对 role 为 user 的 content 进行 format,{{content}}表示塞入实际的 content,其他为拼接的 token| |`format_assistant`|对 role 为 assistant 的 content 进行 format| |`format_system`|对 role 为 system 的 content 进行 format| |`format_function`|对 role 为 function(申请工具调用)的 content 进行 format| |`format_observation`|对 role 为 observation(工具返回信息)的 content 进行 format| |`format_tools`|对 tools 信息进行 format| |`format_prefix`|在 system 前面加的内容| |`default_system`|默认的 system 信息,如果数据里面没有 role 为 system 的,就用这个| |`chat_sep`|历史轮对话末尾加的字符串| |`suffix`|默认为 eos token,在多轮对话的最后面添加| |`efficient_eos`|suffix 是否有效,即是否在最后拼接 suffix token| |`auto_add_bos`|设置为 true 的时候,如果 bos 没添加,会自动添加上| |`thought_words`|数据里面的思考标志是什么,比如| |`enable_thinking`|否的话,会把思考信息删掉(当 template_class 选 ReasoningTemplate 时候生效)| |`mm_plugin`|使用什么插件来处理多模信息| |`grounding_plugin`|使用什么插件来处理 grounding 任务的 target 信息| |`template_class`|template 类,可以选 Template 或 ReasoningTemplate,ReasoningTemplate 一般是思考模型会用的,会根据 enable_thinking 决定是否删除思考信息| ## 3.3. 多模态处理(注册 mm_plugin) 多模模型需要实现自己的多模数据处理方法,包括图片处理、视频处理、音频处理、获取处理后的 tokens 数量来填充占位符 具体实现方式可以参考 Qwen2VLPlugin 类 ### 3.3.1. 多模数据下载(选做) 在基类 `MMPluginMixin` 中,PaddleFormers 已经为大家实现了最基本的数据下载函数: * `_regularize_images`:负责图片数据下载 * `_regularize_videos`:负责视频数据下载和抽帧 * `_regularize_videos`:负责音频数据下载(暂未实现) 若大家有定制化的数据下载需求,只需重写对应的处理函数即可 ### 3.3.2. 多模数据预处理(选做) 在基类 `MMPluginMixin` 中,PaddleFormers 已经为大家实现了最基本的多模数据预处理函数:`_get_mm_inputs` 在 `_get_mm_inputs` 中,PaddleFormers 会调用多模 `processor` 来处理对应模态的数据,并返回处理结果 若大家有定制化的数据预处理需求,只需重写 `_get_mm_inputs` 函数即可 ### 3.3.3. 多模 token 拼接(必做) PaddleFormers 需要重写 `process_messages` 函数来实现 template 中多模 token 的拼接逻辑。 在模型的 template 中,各个模态的数据会有各自的占位符,图片数据通常使用占位符 `` ,视频数据通常使用占位符 `