提示词工程的意义
在大型语言模型(Large Language Models, LLMs)中,提示词工程(Prompt Engineering)是至关重要的,它涉及设计和构建输入提示,以便有效地引导模型生成期望的输出。以下是提示词工程重要性的几个关键点:
-
精确性:良好的提示词可以帮助模型更准确地理解用户的意图,从而生成更精确的回答或执行特定的任务。
-
上下文提供:提示词可以为模型提供必要的上下文信息,这对于生成相关和连贯的输出至关重要。
-
引导行为:通过精心设计的提示词,可以引导模型的行为,使其按照特定的方式响应,这对于特定的应用场景非常有用。
-
避免歧义:提示词可以减少模型理解问题的歧义,确保它按照用户的预期方向进行处理。
-
提高效率:有效的提示词可以减少模型生成无关回答或进行无效搜索的次数,从而提高整体的处理效率。
-
增强交互性:在对话系统中,提示词工程可以提升用户与模型之间的交互质量,使对话更加自然和人性化。
-
创造性激发:在创意写作或内容生成任务中,提示词可以激发模型的创造性,生成更有创意和价值的内容。
-
控制生成内容:在需要控制生成内容的场合,如避免生成不当或敏感内容时,精心设计的提示词可以作为重要的控制手段。
-
适应性:提示词可以根据不同的任务和需求进行定制,使模型能够适应多变的应用场景。
-
提高用户满意度:通过提供清晰、准确的提示词,可以提高用户对模型输出的满意度,增强用户对系统的信任和依赖。
-
节省资源:有效的提示词可以减少模型的试错过程,节省计算资源,尤其是在需要大量交互的场景中。
-
教育和引导:在教育或培训应用中,提示词可以用来引导学习者思考和探索,促进知识的理解和掌握。
-
实验和研究:在研究和实验中,提示词工程可以帮助研究者探索模型的能力和局限性,推动语言模型技术的发展。
-
商业应用:在商业环境中,精心设计的提示词可以提升用户体验,增强产品的市场竞争力。
提示词工程是大型语言模型应用开发中的一个关键环节,它需要结合领域知识、用户体验和模型特性进行综合考量。
提示词工程的代码实现
依赖加载
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, AutoConfig
定义模型路径和量化配置
MODEL_PATH = r'G:\hugging_fase_model\Llama-2-7b-chat-hf'
quantization_config = BitsAndBytesConfig(
load_in_4bit = True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
)
加载分词器和模型
#加载token
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
#AutoModelForCausalLM类,用于因果语言建模的模型的自动配置版本。
model = AutoModelForCausalLM.from_pretrained(
MODEL_PATH,
device_map = "auto",
trust_remote_code = True,#这个参数允许模型加载远程代码或配置。
quantization_config=quantization_config,#量化配置对象
)
数据加载
import pandas as pd
from tqdm import tqdm
DEBUG = False
TEST_DF_FILE = './nbroad-v1.csv'
SUB_DF_FILE = './sample_submission.csv'
NROWS = 10 if DEBUG else None
tdf = pd.read_csv(TEST_DF_FILE, nrows=NROWS, usecols=['id', 'original_text', 'rewritten_text'])
sub = pd.read_csv(SUB_DF_FILE, nrows=NROWS, usecols=['id', 'rewrite_prompt'])
tdf = tdf.head(50)#这里数据很多做了几个截取
print(tdf.head())
文本截断函数
定义了一个文本截断函数,如果文本长度超过指定的length,则截断到前length个单词。
def truncate_txt(text, length):
text_list = text.split()
if len(text_list) <= length:
return text
return " ".join(text_list[:length])
生成提示词函数
def gen_prompt(og_text, rewritten_text):
# 暂时将文本截断为前200个单词
# 可能存在内存问题
og_text = truncate_txt(og_text, 200)
rewritten_text = truncate_txt(rewritten_text, 200)
return f"""
Original Essay:
\"""{
og_text}\"""
Rewritten Essay:
\"""{
rewritten_text}\"""
Given are 2 essays, the Rewritten essay was created from the Original essay using the google Gemma model.
You are trying to understand how the original essay was transformed into a new version.
Analyzing the changes in style, theme, etc., please come up with a prompt that must have been used to guide the transformation from the original to the rewritten essay.
Start directly with the prompt, that's all I need. Output should be only line ONLY.
"""
提示翻译:
给定两篇文章,重写的文章是使用谷歌Gemma模型从原始文章创建的。 你试图理解原来的文章是如何转变成一个新版本的。
分析风格、主题等方面的变化,请提出一个提示,一定是用来指导从原文到重写文章的转变。
直接从提示符开始,这就是我所需要的。输出应该只有行only。
初始化设备和进度条 & 迭代生成提示词
import gc
device = 'cuda'
tdf['rewrite_prompt'] = sub['rewrite_prompt'].copy()
pbar = tqdm(total=tdf.shape[0])
it = iter(tdf.iterrows())
idx, row = next(it, (None, None))
error_encountered = 0
while idx is not None and error_encountered < 10:
torch.cuda.empty_cache()
gc.collect()
# 只是跳到下一排,因为有些东西不起作用。
if error_encountered == 10:
idx, row = next(it, (None, None))
continue
try:
messages = [
{
"role": "user",
"content": gen_prompt(row["original_text"], row["rewritten_text"])
}
]
encoded_input = tokenizer.apply_chat_template(messages, return_tensors="pt", add_generation_prompt=True).to(device)
#这里使用了分词器(tokenizer)的apply_chat_template方法。这个方法是专门为处理对话场景设计的,它接受一个消息(messages)列表,其中每个消息都是一个包含角色(role)和内容(content)的字典。
#return_tensors="pt": 此参数指示分词器返回PyTorch张量(torch.Tensor),这是模型可以接受的格式。
#add_generation_prompt=True: 此参数指示分词器在生成的文本之前添加特定的生成前缀(prompt),这对于某些模型来说是必要的,以表明接下来的文本是生成的输出。
# # 代码块中的所有操作都不会追踪梯度
with torch.no_grad():
#model.generate是模型生成文本的方法,它在不计算梯度的情况下运行,因为这个阶段是推理过程,不需要更新模型的权重
encoded_output = model.generate(encoded_input, max_new_tokens=50, do_sample=True, pad_token_id=tokenizer.eos_token_id)
#tokenizer.decode: 这个方法是tokenizer对象的一个方法,它接受一系列token ID,并将其转换回原始文本。它使用模型的词汇表来将token ID映射回对应的tokens或words。
#encoded_output: 这通常是模型生成的一系列token ID的张量(tensor),它们代表了生成的文本的编码形式。在文本生成任务中,模型会输出一个序列的token ID,这些ID对应于词汇表中的tokens。
#encoded_output[0]: 这里,我们选择了encoded_output张量中的第一个元素
#skip_special_tokens=True: 这是一个参数,指定在解码过程中是否跳过特殊tokens。
decoded_output = tokenizer.decode(encoded_output[0], skip_special_tokens=True)
#替换部分字符
decoded_output = decoded_output.replace(messages[0]["content"], '').replace("[INST]", "").replace("[/INST]", "").strip()
#连接而不是替换
tdf.loc[idx, "rewrite_prompt"] = decoded_output
idx, row = next(it, (None, None))
pbar.update(1)
del encoded_input, decoded_output, encoded_output
except Exception as e:
print(f"ERROR: {
e}")
#重写提示词的备份
sub["rewrite_prompt"] = tdf['rewrite_prompt'].copy()
sub.to_csv("submission.csv", index=False)
error_encountered += 1
pbar.close()
#查看详细数据
for i in range(tdf.shape[0]):
print(f'New Generated Prompt: ----> {
tdf.iloc[i]["rewrite_prompt"]}', end="\n \n")
print(f'Original Prompt: ---> {
sub.iloc[i]["rewrite_prompt"]}', end="\n \n ---------------------------- \n \n")
更新的提示
以上只是部分提示。感谢阅读。