提示模板
提示模板是结构化的文本模板,用于格式化用户提示,以优化模型在特定任务上的性能。它们可以服务于多种目的
特定于模型的模板,在提示模型时都需要这些模板,例如指令微调的 Llama2 和 Mistral 模型中的 [INST] 标签。这些模型是在预训练时使用这些标签进行训练的,在推理时使用这些标签可以帮助确保最佳性能。
特定于任务的模板,用于为模型装备特定任务,模型将在训练后预期执行该任务。例如,语法纠正 (
GrammarErrorCorrectionTemplate
)、摘要 (SummarizeTemplate
)、问答 (QuestionAnswerTemplate
) 等等。社区标准化模板,例如
ChatMLTemplate
例如,如果我想微调一个模型来执行语法纠正任务,我可以使用 GrammarErrorCorrectionTemplate
将文本 “将此内容纠正为标准英语:{prompt} — 纠正后:{response}” 添加到我的所有数据样本中。
from torchtune.data import GrammarErrorCorrectionTemplate, Message
sample = {
"incorrect": "This are a cat",
"correct": "This is a cat.",
}
msgs = [
Message(role="user", content=sample["incorrect"]),
Message(role="assistant", content=sample["correct"]),
]
gec_template = GrammarErrorCorrectionTemplate()
templated_msgs = gec_template(msgs)
for msg in templated_msgs:
print(msg.text_content)
# Correct this to standard English: This are a cat
# ---
# Corrected:
# This is a cat.
添加的文本不同于模型分词器添加的特殊标记。有关提示模板和特殊标记之间的区别的详细讨论,请参阅 分词提示模板和特殊标记。
使用提示模板
提示模板传递到分词器中,并将自动应用于您要对其进行微调的数据集。您可以通过两种方式传递它
指向提示模板类的字符串点路径,例如 “torchtune.models.mistral.MistralChatTemplate” 或 “path.to.my.CustomPromptTemplate”
一个字典,将角色映射到一个字符串元组,表示在消息内容之前和之后添加的文本
通过点路径字符串定义
# In code
from torchtune.models.mistral import mistral_tokenizer
m_tokenizer = mistral_tokenizer(
path="/tmp/Mistral-7B-v0.1/tokenizer.model"
prompt_template="torchtune.models.mistral.MistralChatTemplate"
)
# In config
tokenizer:
_component_: torchtune.models.mistral.mistral_tokenizer
path: /tmp/Mistral-7B-v0.1/tokenizer.model
prompt_template: torchtune.models.mistral.MistralChatTemplate
通过字典定义
例如,要实现以下提示模板
System: {content}\\n
User: {content}\\n
Assistant: {content}\\n
Tool: {content}\\n
您需要为每个角色传递一个元组,其中 PREPEND_TAG
是在文本内容之前添加的字符串,APPEND_TAG
是在文本内容之后添加的字符串。
template = {role: (PREPEND_TAG, APPEND_TAG)}
因此,该模板将定义如下
template = {
"system": ("System: ", "\\n"),
"user": ("User: ", "\\n"),
"assistant": ("Assistant: ", "\\n"),
"ipython": ("Tool: ", "\\n"),
}
现在,我们可以将其作为字典传递到分词器中
# In code
from torchtune.models.mistral import mistral_tokenizer
template = {
"system": ("System: ", "\\n"),
"user": ("User: ", "\\n"),
"assistant": ("Assistant: ", "\\n"),
"ipython": ("Tool: ", "\\n"),
}
m_tokenizer = mistral_tokenizer(
path="/tmp/Mistral-7B-v0.1/tokenizer.model"
prompt_template=template,
)
# In config
tokenizer:
_component_: torchtune.models.mistral.mistral_tokenizer
path: /tmp/Mistral-7B-v0.1/tokenizer.model
prompt_template:
system:
- "System: "
- "\\n"
user:
- "User: "
- "\\n"
assistant:
- "Assistant: "
- "\\n"
ipython:
- "Tool: "
- "\\n"
如果您不想为角色添加前缀/后缀标签,则可以根据需要传递空字符串 “”。
使用 PromptTemplate
类
模板字典也可以传递到 PromptTemplate
中,这样您就可以将其用作独立的自定义提示模板类。
from torchtune.data import PromptTemplate
def my_custom_template() -> PromptTemplate:
return PromptTemplate(
template={
"user": ("User: ", "\\n"),
"assistant": ("Assistant: ", "\\n"),
},
)
template = my_custom_template()
msgs = [
Message(role="user", content="Hello world!"),
Message(role="assistant", content="Is AI overhyped?"),
]
templated_msgs = template(msgs)
for msg in templated_msgs:
print(msg.role, msg.text_content)
# user, User: Hello world!
#
# assistant, Assistant: Is AI overhyped?
#
自定义提示模板
对于无法直接包含在 PREPEND_TAG content APPEND_TAG
模式中的更高级配置,您可以创建一个新的类,该类继承自 PromptTemplateInterface
并实现 __call__
方法。
from torchtune.data import Message
class PromptTemplateInterface(Protocol):
def __call__(
self,
messages: List[Message],
inference: bool = False,
) -> List[Message]:
"""
Format each role's message(s) according to the prompt template
Args:
messages (List[Message]): a single conversation, structured as a list
of :class:`~torchtune.data.Message` objects
inference (bool): Whether the template is being used for inference or not.
Returns:
The formatted list of messages
"""
pass
# Contrived example - make all assistant prompts say "Eureka!"
class EurekaTemplate(PromptTemplateInterface):
def __call__(
self,
messages: List[Message],
inference: bool = False,
) -> List[Message]:
formatted_dialogue = []
for message in messages:
if message.role == "assistant":
content = "Eureka!"
else:
content = message.content
formatted_dialogue.append(
Message(
role=message.role,
content=content,
masked=message.masked,
ipython=message.ipython,
eot=message.eot,
),
)
return formatted_dialogue
template = EurekaTemplate()
msgs = [
Message(role="user", content="Hello world!"),
Message(role="assistant", content="Is AI overhyped?"),
]
templated_msgs = template(msgs)
for msg in templated_msgs:
print(msg.role, msg.text_content)
# user, Hello world!
# assistant, Eureka!
有关更多示例,您可以查看 MistralChatTemplate
或 Llama2ChatTemplate
。
要将此自定义模板用于分词器,您可以通过点路径字符串传递它
# In code
from torchtune.models.mistral import mistral_tokenizer
m_tokenizer = mistral_tokenizer(
path="/tmp/Mistral-7B-v0.1/tokenizer.model",
prompt_template="path.to.template.EurekaTemplate",
)
# In config
tokenizer:
_component_: torchtune.models.mistral.mistral_tokenizer
path: /tmp/Mistral-7B-v0.1/tokenizer.model
prompt_template: path.to.template.EurekaTemplate