LangChain实战 调用模型 | 豆包MarsCode AI 刷题

183 阅读8分钟

本文为课程 调用模型:使用OpenAI API还是微调开源Llama2/ChatGLM? 的实践记录。不过与课程不同的是,在实践中使用的是microsoft/Phi-3.5-mini-instruct这一开源模型。该模型无需在huggingface平台上获取访问权限,运行环境为Colab的T4 Python 3 Google Compute Engine 后端 (GPU)。

安装依赖

运行下面代码以安装依赖

!pip install langchain_community
!pip install -U langchain
!pip install langchain-huggingface
!pip install gradio

通过 HuggingFace 调用模型

运行下面使用HuggingFace的Transformers库来调用Llama的代码,我们可以得到“请给我讲个玫瑰的爱情故事?”这一提示词的回答。

# 导入必要的库
from transformers import AutoTokenizer, AutoModelForCausalLM

model = "microsoft/Phi-3.5-mini-instruct"
# 加载预训练模型的分词器
tokenizer = AutoTokenizer.from_pretrained(model)

# 加载预训练的模型
# 使用 device_map 参数将模型自动加载到可用的硬件设备上,例如GPU
model = AutoModelForCausalLM.from_pretrained(
          model,
          device_map = 'auto')

# 定义一个提示,希望模型基于此提示生成故事
prompt = "请给我讲个玫瑰的爱情故事?"

# 使用分词器将提示转化为模型可以理解的格式,并将其移动到GPU上
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")

# 使用模型生成文本,设置最大生成令牌数为2000
outputs = model.generate(
    inputs["input_ids"], 
    max_new_tokens=1000, 
    attention_mask=inputs["attention_mask"], 
    top_p=0.6, 
    top_k=50,
    do_sample=True,
    repetition_penalty=1.5,
    pad_token_id=tokenizer.eos_token_id,
    temperature=0.7  # 控制生成文本的多样性
)


# 将生成的令牌解码成文本,并跳过任何特殊的令牌,例如[CLS], [SEP]等
response = tokenizer.decode(outputs[0], skip_special_tokens=True)

# 打印生成的响应
print(response)

这段程序是一个很典型的HuggingFace的Transformers库的用例,该库提供了大量预训练的模型和相关的工具。

  • 导入AutoTokenizer:这是一个用于自动加载预训练模型的相关分词器的工具。分词器负责将文本转化为模型可以理解的数字格式。
  • 导入AutoModelForCausalLM:这是用于加载因果语言模型(用于文本生成)的工具。
  • 使用from_pretrained方法来加载预训练的分词器和模型。其中,device_map = 'auto' 是为了自动地将模型加载到可用的设备上,例如GPU。
  • 然后,给定一个提示(prompt):"请给我讲个玫瑰的爱情故事?",并使用分词器将该提示转换为模型可以接受的格式,return_tensors="pt" 表示返回PyTorch张量。语句中的 .to("cuda") 是GPU设备格式转换,因为我在GPU上跑程序,不用这个的话会报错,如果你使用CPU,可以试一下删掉它。
  • 最后使用模型的 .generate() 方法生成响应。max_new_tokens=2000 限制生成的文本的长度。使用分词器的 .decode() 方法将输出的数字转化回文本,并且跳过任何特殊的标记。

另外,本程序还额外设置了下面四个参数,来保证模型生成的回答多样性和防止回答重复问题。

    top_p=0.6, 
    top_k=50,
    repetition_penalty=1.5,
    temperature=0.7  # 控制生成文本的多样性

每个参数的作用如下:

top_p=0.6(核采样,Top-p 采样)

  • 作用top_p 控制生成文本时考虑的候选词的概率分布。具体来说,top-p 采样(也叫做核采样)会选择前 p 概率之和最接近 1 的词汇集合,从中进行采样。top_p=0.6 表示只考虑概率累积和最接近 0.6 的词汇集合。这样可以避免选择一些低概率的词,从而提高生成文本的质量。
  • 解释:如果设定较小的 top_p,生成的文本会更加保守和连贯;如果设定较大的 top_p,生成的文本会有更大的多样性和创新性,但也可能出现不连贯或奇怪的句子。

top_k=50(Top-k 采样)

  • 作用top_k 是一种更为简单的控制生成的技术。它限制模型每次预测时,只从概率最高的 k 个词汇中选择下一个词。在此情况下,top_k=50 意味着每次生成时,模型只会考虑概率前 50 的词汇。
  • 解释:较小的 top_k 值(例如 10 或 20)会让生成的文本更加保守和集中,而较大的 top_k 值(例如 50 或 100)则允许模型探索更多不同的词汇组合,带来更多样化的输出。

repetition_penalty=1.5(重复惩罚)

  • 作用repetition_penalty 控制生成过程中对重复词的惩罚。值越大,生成模型就会更倾向于避免重复使用相同的词汇。repetition_penalty=1.5 表示如果模型生成了重复的词汇,它会受到一定程度的惩罚,使得模型更倾向于生成新的词汇,避免重复的情况。
  • 解释:这个参数对于生成文本时避免冗余、提高文本多样性非常有用。如果将 repetition_penalty 设置为更高的值(如 2 或 3),生成的文本就会更加避免重复。较低的惩罚值则会增加生成重复内容的概率。

temperature=0.7(温度)

  • 作用temperature 是控制模型输出概率分布的一个参数,它决定了模型输出的多样性。temperature=0.7 会使得概率分布更加“尖锐”,即模型会更倾向于选择那些概率较高的词汇,从而减少低概率词的选择。较低的 temperature 值使生成的文本更加连贯和一致,但可能缺乏创造性。
  • 解释:较高的温度值(例如 1.0 或 1.5)会使输出更为多样和富有创意,但可能导致一些语法错误或不合理的文本。较低的温度值(如 0.3 或 0.5)会让生成的文本更加保守、连贯,但也可能显得单调。

上面这些参数在调节文本生成模型时常常是互相配合使用的,通过调整它们的数值,可以找到最适合的文本生成策略。

12分钟后,我们得到了LLM的回复,因为回答后面在胡言乱语就不完整放上来了

截屏2024-11-15 18.52.31.png

通过 HuggingFace Pipeline调用模型

因为课程代码的调用方法过旧,下面是经过修改后的代码:

# 指定预训练模型的名称

model = "microsoft/Phi-3.5-mini-instruct"

# 从预训练模型中加载词汇器

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained(model)

# 创建一个文本生成的管道

import transformers

import torch

pipeline = transformers.pipeline(

"text-generation",

model=model,

tokenizer=tokenizer,

torch_dtype=torch.float16,

device_map="auto",

max_length=1000,

truncation=True # 启用截断

)

# 创建HuggingFacePipeline实例

from langchain_huggingface import HuggingFacePipeline

llm = HuggingFacePipeline(pipeline=pipeline,

model_kwargs={

'temperature': 0.9,

'top_p': 0.6,

'top_k': 50,

'max_length':200,

'repetition_penalty':1.5,

})

# 定义输入模板,该模板用于生成花束的描述

template = """

为以下的花束生成一个详细且吸引人的描述:

花束的详细信息:

```{flower_details}```

"""
# 使用模板创建提示

from langchain import PromptTemplate, LLMChain

prompt = PromptTemplate(template=template,

input_variables=["flower_details"])

# 创建LLMChain实例

llm_chain = prompt| llm

# 需要生成描述的花束的详细信息

flower_details = "12支红玫瑰,搭配白色满天星和绿叶,包装在浪漫的红色纸中。"

# 打印生成的花束描述

result = llm_chain.invoke(flower_details)

print(result)

运行27分钟后,我们得到了模型的输出结果:

为以下的花束生成一个详细且吸引人的描述: 花束的详细信息: 12支红玫瑰,搭配白色满天星和绿叶,包装在浪漫的红色纸中。 - 使用详细的描述,包括花束的数量、花的颜色、植物的特征以及包装的细节。 - 确保描述紧密结合给定的信息,并创造出一个引人入胜的图像。 在红色纸包裹的中,12支精致的红玫瑰,它们的粉红色花瓣闪烁着温暖的光芒,与白色满天星和绿叶的嫩绿色形成了一个既优雅又温馨的对比。每支玫瑰都是一朵独特的艺术品,花瓣的轻盈摇曳,随着微风的拂面,散发出一种柔和的香气。白色满天星,它们的轻盈轻轻摇曳,在玫瑰的轻柔阴影下闪烁,增添了一丝清新的气息。绿叶,它们的绿色叶子静静地挂在玫瑰的枝头,它们的嫩绿色与玫瑰的红色形成了一种生机勃勃的对比。整个花束,它们的精致和温暖,被红色的包装纸包裹,它的光泽和质感,增添了一丝浪漫的气息。一朵朵精致的玫瑰,一片片白色的满天星,一片片绿色的叶子,一个浪漫的包装,一个完美的花束,它们的美丽和温暖,让人心旷神怡。 - 使用详细的描述,包括花束的数量、花的颜色、植物的特征以及包装的细节。 在红色纸包裹的中,12支精致的红玫瑰,它们的粉红色花瓣闪烁着温暖的光芒,与白色满天星和绿叶的嫩绿色形成了一个既优雅又温馨的对比。每支玫瑰都是一朵独特的艺术品,花瓣的轻盈摇曳,随着微风的拂面,散发出一种柔和的香气。白色满天星,它们的�����

截屏2024-11-15 19.24.37.png