Skip to content

如何准备大语言模型学件?

大语言模型的学件包在基本遵循已有学件标准的基础上,针对大语言模型的特点进行了扩展。本文将详细介绍大语言模型学件的组成、实现方式及注意事项,帮助用户规范地创建大语言模型学件。

请先阅读 如何准备一个学件?,以便了解基础学件的构建流程和要求。

学件的基本组成

大语言模型的学件是一个 zip 包,其中至少需要包含以下内容:

  • learnware.yaml:学件配置文件,描述学件的元信息;
  • __init__.py:实现学件的核心功能,包括模型加载、推理等接口;
  • 统计规约文件:其文件名可自定义并记录在 learnware.yaml 中;
  • environment.yamlrequirements.txt:指明模型的运行环境。
  • weights_file_path/:存放模型权重和配置文件的目录。 对于基座模型和全量微调模型,该目录下存放的是模型的全部权重和配置文件;对于参数高效微调模型,该目录下存放的是微调参数的权重和配置文件。

weights_file_path/ 目录下通常包含以下文件。这些文件包括模型的权重(如 model.safetensors)和配置(如 config.json),它们决定了模型加载和运行的准确性。

对于基座模型和全量微调模型:

  • config.json
  • generation_config.json
  • model.safetensors
  • tokenizer_config.json
  • tokenizer.json

对于参数高效微调模型:

  • adapter_config.json
  • adapter_model.safetensors
  • tokenizer_config.json
  • tokenizer.json

接下来,我们将详细介绍上述文件的具体内容。

模型调用文件 __init__.py

学件的核心功能通过 __init__.py 文件实现。以下是基座模型学件和全量微调模型学件 __init__.py 文件的参考模板,默认存放模型权重和配置文件的目录为 weights。请注意,为了实现系统对于大语言模型通用能力的评测,需要在 __init__.py 文件中提供 get_model 接口,返回实例化好的模型。

py
import os
import numpy as np
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
from learnware.model import BaseModel


class MyModel(BaseModel):
    def __init__(self):
        super(MyModel, self).__init__(input_shape=None, output_shape=None)
        
        # 获取模型权重和配置文件的路径
        dir_path = os.path.dirname(os.path.abspath(__file__))
        model_path = os.path.join(dir_path, "weights")

        # 加载模型和 Tokenizer
        self.model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto", torch_dtype=torch.bfloat16)
        self.tokenizer = AutoTokenizer.from_pretrained(model_path)

        # 配置 Tokenizer
        self.tokenizer.pad_token = self.tokenizer.eos_token
        self.max_length=1024

    def fit(self, X: np.ndarray, y: np.ndarray):
        pass

    def predict(self, X):
        """
        基于输入文本生成预测输出。
        Args:
            X (list[str]): 输入文本列表。
        Returns:
            list[str]: 预测结果。
        """
        inputs = self.tokenizer(X, padding=True, truncation=True, return_tensors="pt").to(self.model.device)
        outputs = self.model.generate(
            inputs["input_ids"],
            max_length=self.max_length,
            num_return_sequences=1,
            do_sample=True,
            temperature=0.7
        )
        return [self.tokenizer.decode(output, skip_special_tokens=True) for output in outputs]

    def finetune(self, X: np.ndarray, y: np.ndarray):
        pass

    def get_model(self):
        """
        获取模型实例。
        Returns:
            torch.nn.Module: 模型实例。
        """
        return self.model
import os
import numpy as np
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
from learnware.model import BaseModel


class MyModel(BaseModel):
    def __init__(self):
        super(MyModel, self).__init__(input_shape=None, output_shape=None)
        
        # 获取模型权重和配置文件的路径
        dir_path = os.path.dirname(os.path.abspath(__file__))
        model_path = os.path.join(dir_path, "weights")

        # 加载模型和 Tokenizer
        self.model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto", torch_dtype=torch.bfloat16)
        self.tokenizer = AutoTokenizer.from_pretrained(model_path)

        # 配置 Tokenizer
        self.tokenizer.pad_token = self.tokenizer.eos_token
        self.max_length=1024

    def fit(self, X: np.ndarray, y: np.ndarray):
        pass

    def predict(self, X):
        """
        基于输入文本生成预测输出。
        Args:
            X (list[str]): 输入文本列表。
        Returns:
            list[str]: 预测结果。
        """
        inputs = self.tokenizer(X, padding=True, truncation=True, return_tensors="pt").to(self.model.device)
        outputs = self.model.generate(
            inputs["input_ids"],
            max_length=self.max_length,
            num_return_sequences=1,
            do_sample=True,
            temperature=0.7
        )
        return [self.tokenizer.decode(output, skip_special_tokens=True) for output in outputs]

    def finetune(self, X: np.ndarray, y: np.ndarray):
        pass

    def get_model(self):
        """
        获取模型实例。
        Returns:
            torch.nn.Module: 模型实例。
        """
        return self.model

以下是参数高效微调学件 __init__.py 文件的参考模板。其中 get_pretrained_path 函数根据传入的北冥坞学件 ID,返回下载到本地的基座模型权重和配置文件的目录的路径,可用于参数高效微调学件加载基座模型。

py
import os
import numpy as np
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
from peft import get_peft_model, LoraConfig, TaskType,AutoPeftModelForCausalLM
from learnware.model import BaseModel
from learnware.client import LearnwareClient

class MyModel(BaseModel):
    def __init__(self):
        super(MyModel, self).__init__(input_shape=None, output_shape=None)

        dir_path = os.path.dirname(os.path.abspath(__file__))
        adapter_path = os.path.join(dir_path, "adapter")

        # 获取基座模型权重路径
        client = LearnwareClient()
        base_model_path = client.get_pretrained_path("Base Model ID")   

        # 加载基座模型
        base_model = AutoModelForCausalLM.from_pretrained(base_model_path, device_map="auto", torch_dtype=torch.bfloat16)
        
        # 加载适配器模型
        peft_config = LoraConfig.from_pretrained(adapter_path)
        self.model = get_peft_model(base_model, peft_config)
        self.model.load_adapter(adapter_path, adapter_name = "lora")

        # 配置 Tokenizer
        self.tokenizer = AutoTokenizer.from_pretrained(base_model_path)
        self.tokenizer.pad_token = self.tokenizer.eos_token
        self.max_length=1024

    def fit(self, X: np.ndarray, y: np.ndarray):
        pass

    def predict(self, X):
        inputs = self.tokenizer(X, padding=True, truncation=True, return_tensors="pt").to(self.model.device)
        outputs = self.model.generate(
            inputs["input_ids"],
            max_length=self.max_length,
            num_return_sequences=1,
            do_sample=True,
            temperature=0.7
        )
        return [self.tokenizer.decode(output, skip_special_tokens=True) for output in outputs]

    def finetune(self, X: np.ndarray, y: np.ndarray):
        pass

    def get_model(self):
        return self.model
import os
import numpy as np
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
from peft import get_peft_model, LoraConfig, TaskType,AutoPeftModelForCausalLM
from learnware.model import BaseModel
from learnware.client import LearnwareClient

class MyModel(BaseModel):
    def __init__(self):
        super(MyModel, self).__init__(input_shape=None, output_shape=None)

        dir_path = os.path.dirname(os.path.abspath(__file__))
        adapter_path = os.path.join(dir_path, "adapter")

        # 获取基座模型权重路径
        client = LearnwareClient()
        base_model_path = client.get_pretrained_path("Base Model ID")   

        # 加载基座模型
        base_model = AutoModelForCausalLM.from_pretrained(base_model_path, device_map="auto", torch_dtype=torch.bfloat16)
        
        # 加载适配器模型
        peft_config = LoraConfig.from_pretrained(adapter_path)
        self.model = get_peft_model(base_model, peft_config)
        self.model.load_adapter(adapter_path, adapter_name = "lora")

        # 配置 Tokenizer
        self.tokenizer = AutoTokenizer.from_pretrained(base_model_path)
        self.tokenizer.pad_token = self.tokenizer.eos_token
        self.max_length=1024

    def fit(self, X: np.ndarray, y: np.ndarray):
        pass

    def predict(self, X):
        inputs = self.tokenizer(X, padding=True, truncation=True, return_tensors="pt").to(self.model.device)
        outputs = self.model.generate(
            inputs["input_ids"],
            max_length=self.max_length,
            num_return_sequences=1,
            do_sample=True,
            temperature=0.7
        )
        return [self.tokenizer.decode(output, skip_special_tokens=True) for output in outputs]

    def finetune(self, X: np.ndarray, y: np.ndarray):
        pass

    def get_model(self):
        return self.model

您可以根据模型的具体需求来实现 MyModel 类中的接口。此外,我们建议您在完成 __init__.py 文件后,实例化 MyModel 类,并测试各个接口的行为,确保它们符合预期的功能和表现。

学件统计规约 stat.json

对于基座模型学件,您无需提供统计规约,系统会为其自动生成通用能力规约并存储在学件包中;对于全量微调模型和参数高效微调模型学件,您需要提供两种规约:文本 RKME 规约文本生成模型规约

以下是相应的代码示例:

  1. 文本 RKME 规约
py
from learnware.specification import generate_stat_spec

spec1 = generate_stat_spec(type="text", X=train_x)
spec1.save("rkme.json")
from learnware.specification import generate_stat_spec

spec1 = generate_stat_spec(type="text", X=train_x)
spec1.save("rkme.json")
  1. 文本生成模型规约
py
from learnware.specification import generate_generative_model_spec

# 您可以提供 `List[str]` 类型的 `X`:
spec = generate_generative_model_spec(X=X)
# 或者您也可以提供 `datasets.Dataset` 类型的 `X`,其中 `dataset_text_field` 是数据集文本字段的名称:
spec = generate_generative_model_spec(dataset=train_dataset, dataset_text_field="text")
spec.save("generative.pth")
from learnware.specification import generate_generative_model_spec

# 您可以提供 `List[str]` 类型的 `X`:
spec = generate_generative_model_spec(X=X)
# 或者您也可以提供 `datasets.Dataset` 类型的 `X`,其中 `dataset_text_field` 是数据集文本字段的名称:
spec = generate_generative_model_spec(dataset=train_dataset, dataset_text_field="text")
spec.save("generative.pth")

学件配置文件 learnware.yaml

相比一般的的学件配置文件,大语言模型还需要额外指明:

  • weights_file_path: 模型权重和配置文件的相对路径,帮助 get_pretrained_path 函数返回正确的基座模型权重和配置文件路径。

  • required_learnware_ids: 该模型依赖的北冥坞其他学件的 ID,用于在下载和加载参数高效微调学件时为其指明或自动下载北冥坞上的基座模型和全量微调模型学件。

以下是 learnware.yaml 的示例。

yaml
model:
  class_name: MyModel
  weights_file_path: weights  # 新增字段:模型权重文件的相对路径
  required_learnware_ids:  # 新增字段:该模型依赖的其他模型的 ID
    - base_model_id
  kwargs: {}
stat_specifications:
  - module_path: learnware.specification
    class_name: RKMETextSpecification
    file_name: rkme.json
    kwargs: {}
  - module_path: learnware.specification
    class_name: GenerativeModelSpecification
    file_name: generative.pth
    kwargs: {}
model:
  class_name: MyModel
  weights_file_path: weights  # 新增字段:模型权重文件的相对路径
  required_learnware_ids:  # 新增字段:该模型依赖的其他模型的 ID
    - base_model_id
  kwargs: {}
stat_specifications:
  - module_path: learnware.specification
    class_name: RKMETextSpecification
    file_name: rkme.json
    kwargs: {}
  - module_path: learnware.specification
    class_name: GenerativeModelSpecification
    file_name: generative.pth
    kwargs: {}

模型运行依赖

为了使上传的学件可以被后续其它用户使用,您需要在上传的学件 zip 包中明确指定模型的运行依赖。此部分的要求与 如何准备一个学件? 中的要求相同。