PaddlePaddle / PaddleNLP

👑 Easy-to-use and powerful NLP and LLM library with 🤗 Awesome model zoo, supporting wide-range of NLP tasks from research to industrial applications, including 🗂Text Classification, 🔍 Neural Search, ❓ Question Answering, ℹ️ Information Extraction, 📄 Document Intelligence, 💌 Sentiment Analysis etc.
https://paddlenlp.readthedocs.io
Apache License 2.0
12.01k stars 2.92k forks source link

[Improvement Request] 简化数据集加载逻辑并改进文档支持 #9007

Open natureLanguageQing opened 1 month ago

natureLanguageQing commented 1 month ago

Feature request

标题:

描述:

在使用 paddlenlp 进行训练和微调时,我发现 pretrain 和 sft 部分的代码实现存在一些问题,尤其是在数据集加载逻辑方面。当前实现包含了大量复杂的代码来处理数据集路径的检测和加载,这不仅影响了代码的可读性,也使得用户难以理解和维护。

当前实现问题:

    if data_args.dataset_name_or_path is None:
        raise ValueError(f"Please specific dataset name or path (got {data_args.dataset_name_or_path})")
    elif (
        os.path.exists(os.path.join(data_args.dataset_name_or_path, "train.json"))
        or os.path.exists(os.path.join(data_args.dataset_name_or_path, "dev.json"))
        or os.path.exists(os.path.join(data_args.dataset_name_or_path, "quant.json"))
    ):
        if training_args.do_train or quant_args.do_qat:
            train_ds = load_dataset(
                "json",
                data_files=os.path.join(data_args.dataset_name_or_path, "train.json"),
                lazy=data_args.lazy,
            )[0]
        else:
            train_ds = None
        if training_args.do_eval:
            dev_ds = load_dataset(
                "json",
                data_files=os.path.join(data_args.dataset_name_or_path, "dev.json"),
                lazy=data_args.lazy,
            )[0]
        else:
            dev_ds = None
        if quant_args.do_ptq or quant_args.do_gptq:
            if os.path.exists(os.path.join(data_args.dataset_name_or_path, "quant.json")):
                ptq_ds = load_dataset(
                    "json",
                    data_files=os.path.join(data_args.dataset_name_or_path, "quant.json"),
                    lazy=data_args.lazy,
                )[0]
            elif os.path.exists(os.path.join(data_args.dataset_name_or_path, "train.json")):
                ptq_ds = load_dataset(
                    "json",
                    data_files=os.path.join(data_args.dataset_name_or_path, "train.json"),
                    lazy=data_args.lazy,
                )[0]
                logger.info(
                    f"Not found quant.json in {data_args.dataset_name_or_path}. Set train dataset as PTQ calibration dataset."
                )
            else:
                raise ValueError(
                    f"Quant strategy requires quant.json or train.json in {data_args.dataset_name_or_path}"
                )
        else:
            ptq_ds = None
    elif (
        os.path.exists(os.path.join(data_args.dataset_name_or_path, "train"))
        or os.path.exists(os.path.join(data_args.dataset_name_or_path, "dev"))
        or os.path.exists(os.path.join(data_args.dataset_name_or_path, "quant"))
    ):
        import glob

        if training_args.do_train or quant_args.do_qat:
            train_ds = load_dataset(
                "json",
                data_files=glob.glob(os.path.join(data_args.dataset_name_or_path, "train", "*.json")),
                lazy=data_args.lazy,
            )[0]
        else:
            train_ds = None
        if training_args.do_eval:
            dev_ds = load_dataset(
                "json",
                data_files=glob.glob(os.path.join(data_args.dataset_name_or_path, "dev", "*.json")),
                lazy=data_args.lazy,
            )[0]
        else:
            dev_ds = None
        if quant_args.do_ptq or quant_args.do_gptq:
            if os.path.exists(os.path.join(data_args.dataset_name_or_path, "quant")):
                ptq_ds = load_dataset(
                    "json",
                    data_files=glob.glob(os.path.join(data_args.dataset_name_or_path, "quant", "*.json")),
                    lazy=data_args.lazy,
                )[0]
            elif os.path.exists(os.path.join(data_args.dataset_name_or_path, "train")):
                ptq_ds = load_dataset(
                    "json",
                    data_files=glob.glob(os.path.join(data_args.dataset_name_or_path, "train", "*.json")),
                    lazy=data_args.lazy,
                )[0]
                logger.info(
                    f"Not found quant.json in {data_args.dataset_name_or_path}. Set train dataset as PTQ calibration dataset."
                )
            else:
                raise ValueError(f"Quant strategy requires quant or train folder in {data_args.dataset_name_or_path}")
        else:
            ptq_ds = None
    else:
        if training_args.do_train or quant_args.do_qat:
            train_ds = load_dataset(data_args.dataset_name_or_path, splits=["train"])[0]
        else:
            train_ds = None
        if training_args.do_eval:
            dev_ds = load_dataset(data_args.dataset_name_or_path, splits=["dev"])[0]
        else:
            dev_ds = None
        if quant_args.do_ptq or quant_args.do_gptq:
            ptq_ds = load_dataset(data_args.dataset_name_or_path, splits=["train"])[0]
            logger.info("Set train dataset as PTQ calibration dataset.")
        else:
            ptq_ds = None

数据集加载逻辑复杂:

当前代码处理数据集路径和加载的逻辑非常繁琐。这种复杂性不仅使代码难以理解,而且增加了维护的难度。 文档支持不足:

当前文档中未包括对数据集加载逻辑的详细解读,使得用户很难理解如何正确配置和使用数据集。 建议的改进:

简化数据集加载逻辑:

目标: 减少代码的复杂性,通过更简洁的逻辑处理数据集加载,提升代码的可读性和维护性。 实现建议: 统一数据集格式和路径规范,减少路径检查和数据集加载的复杂度。 改进文档支持:

目标: 提供清晰的文档解释数据集加载逻辑和要求。 实现建议: 在文档中详细说明数据集文件的格式、路径要求,以及如何正确配置数据集。 添加使用示例和说明,帮助用户理解如何设置数据集并解决常见问题。 期望的改进:

简化数据集加载: 通过精简代码逻辑,提升代码可读性和维护性。 文档改进: 提供详细的文档说明,帮助用户理解数据集要求和配置。 感谢团队对项目的持续投入和改进。希望这些建议能对 paddlenlp 的发展有所帮助。

Motivation

当前代码处理数据集路径和加载的逻辑非常繁琐。这种复杂性不仅使代码难以理解,而且增加了维护的难度。 文档支持不足:

当前文档中未包括对数据集加载逻辑的详细解读,使得用户很难理解如何正确配置和使用数据集。

Your contribution

目标: 提供清晰的文档解释数据集加载逻辑和要求。 实现建议: 在文档中详细说明数据集文件的格式、路径要求,以及如何正确配置数据集。 添加使用示例和说明,帮助用户理解如何设置数据集并解决常见问题。 期望的改进:

简化数据集加载: 通过精简代码逻辑,提升代码可读性和维护性。 文档改进: 提供详细的文档说明,帮助用户理解数据集要求和配置。

natureLanguageQing commented 1 month ago

在代码编程规范中,“高内聚,低耦合”是两个非常重要的概念,尤其在设计模块和系统时,它们有助于提高代码的可维护性、可重用性和可扩展性。以下是对这两个概念的详细解释:

高内聚(High Cohesion)

定义:

优点:

示例:

低耦合(Low Coupling)

定义:

优点:

示例:

实际应用中的策略

  1. 模块化设计:

    • 将系统分解成小的、职责明确的模块或组件,每个模块完成特定的功能。
  2. 接口和抽象:

    • 使用接口或抽象类来定义模块之间的交互,减少模块间的直接依赖。
  3. 信息隐藏:

    • 将模块的内部实现细节隐藏在模块内部,仅暴露必要的接口。
  4. 依赖注入:

    • 使用依赖注入的方式将模块的依赖项注入到模块中,而不是在模块内部直接创建依赖项。

总结

高内聚低耦合是设计高质量软件系统的重要原则。高内聚确保了模块功能的集中和明确,使得代码更易于理解和维护;低耦合则减少了模块间的依赖,使得系统更加灵活、可扩展和可测试。应用这两个原则可以帮助开发者构建更健壮、易于维护的软件系统。