基于 llama2 的提示词工程案例

提示词工程的意义

在大型语言模型(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")

更新的提示
在这里插入图片描述
在这里插入图片描述
以上只是部分提示。感谢阅读。

猜你喜欢

转载自blog.csdn.net/weixin_41870426/article/details/138427804