第三节课之模型
Model I/O:三块
输入提示(Format)、调用模型(Predict)、输出解析(Parse)。
这三块形成了一个整体,因此在LangChain中这个过程被统称为 Model I/O(Input/Output)。
LangChain为Model I/O的每个环节提供了模板和工具,快捷形成调用各种语言模型的接口。
- 提示模板:使用模型的第一个环节是把提示信息输入到模型中创建模版根据需求调整输入。
- 语言模型:LangChain允许通过通用接口来调用语言模型。
- 输出解析:LangChain提供了从模型输出中提取信息的功能。
提示模板
“提示工程”:Prompt Engineering,是专门研究对大语言模型的提示构建。
吴恩达老师的提示工程课程中:
- 给予模型清晰明确的指示
- 让模型慢慢地思考
提示模板的具体内容如下:
input_variables=['flower_name', 'price']
output_parser=None partial_variables={}
template='/\n您是一位专业的鲜花店文案撰写员。
\n对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?\n'
template_format='f-string'
validate_template=True
在此代码中“模板”就是一段描述某种鲜花的文本格式,它是一个 f-string,其中有两个变量 {flower_name} 和 {price} 表示花的名称和价格,这两个值是模板里面的占位符,在实际使用模板生成提示时会被具体的值替换。
代码中的from_template是一个类方法,它允许直接从一个字符串模板中创建一个PromptTemplate对象。打印出这个PromptTemplate对象,这个对象中的信息包括输入的变量(flower_name 和 price)、模板的格式('f-string')、输出解析器、是否验证模板( True)。因此PromptTemplate的from_template方法就是将一个原始的模板字符串转化为一个更丰富、更方便操作的PromptTemplate对象,这个对象就是LangChain中的提示模板。
LangChain 提供了多个类和函数,为各种应用场景设计了很多内置模板,使构建和使用提示变得容易。
语言模型
LangChain中支持的模型有三大类。
- 大语言模型(LLM) ,也叫Text Model,这些模型将文本字符串作为输入,并返回文本字符串作为输出。
- 聊天模型(Chat Model),主要代表Open AI的ChatGPT系列模型。这些模型通常由语言模型支持,但它们的 API 更加结构化。这些模型将聊天消息列表作为输入,并返回聊天消息。
- 文本嵌入模型(Embedding Model),这些模型将文本作为输入并返回浮点数列表,就是Embedding。文本嵌入模型负责把文档存入向量数据库。
# 设置OpenAI API Key
import os
os.environ["OPENAI_API_KEY"] = '你的Open AI API Key'
# 导入LangChain中的OpenAI模型接口
from langchain_openai import OpenAI
# 创建模型实例
model = OpenAI(model_name='gpt-3.5-turbo-instruct')
# 输入提示
input = prompt.format(flower_name=["玫瑰"], price='50')
# 得到模型的输出
output = model.invoke(input)
# 打印输出内容
print(output)
input = prompt.format(flower_name=["玫瑰"], price='50') 这行代码的作用是将模板实例化,此时将 {flower_name} 替换为 "玫瑰",{price} 替换为 '50',形成了具体的提示:“您是一位专业的鲜花店文案撰写员。对于售价为 50 元的玫瑰,您能提供一个吸引人的简短描述吗?”
对比Openai,LangChain的优点在于只需要定义一次模板,就可以用它来生成各种不同的提示。对比单纯使用 f-string 来格式化文本,这种方法更加简洁,也更容易维护。而LangChain在提示模板中,还整合了output_parser、template_format 以及是否需要validate_template等功能。
使用LangChain和提示模板的好处是:
- 代码的可读性:使用模板,提示文本更易于阅读和理解,特别是对于复杂的提示或多变量的情况。
- 可复用性:模板可以在多个地方被复用,代码更简洁,不需要在每个需要生成提示的地方重新构造提示字符串。
- 维护:如果后续需要修改提示,使用模板的话,只需要修改模板就可以了,而不需要在代码中查找所有使用到该提示的地方进行修改。
- 变量处理:如果提示中涉及到多个变量,模板可以自动处理变量的插入,不需要手动拼接字符串。
- 参数化:模板能根据不同的参数生成不同的提示,有利于个性化文本的生成。
输出解析
通过LangChain的输出解析器来重构程序,让模型有能力生成结构化的回应,同时对其进行解析,直接将解析好的数据存入CSV文档。
# 导入OpenAI Key
import os
os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key'
# 导入LangChain中的提示模板
from langchain.prompts import PromptTemplate
# 创建原始提示模板
prompt_template = """您是一位专业的鲜花店文案撰写员。
对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?
{format_instructions}"""
# 通过LangChain调用模型
from langchain_openai import OpenAI
# 创建模型实例
model = OpenAI(model_name='gpt-3.5-turbo-instruct')
# 导入结构化输出解析器和ResponseSchema
from langchain.output_parsers import StructuredOutputParser, ResponseSchema
# 定义我们想要接收的响应模式
response_schemas = [
ResponseSchema(name="description", description="鲜花的描述文案"),
ResponseSchema(name="reason", description="问什么要这样写这个文案")
]
# 创建输出解析器
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
# 获取格式指示
format_instructions = output_parser.get_format_instructions()
# 根据原始模板创建提示,同时在提示中加入输出解析器的说明
prompt = PromptTemplate.from_template(prompt_template,
partial_variables={"format_instructions": format_instructions})
# 数据准备
flowers = ["玫瑰", "百合", "康乃馨"]
prices = ["50", "30", "20"]
# 创建一个空的DataFrame用于存储结果
import pandas as pd
df = pd.DataFrame(columns=["flower", "price", "description", "reason"]) # 先声明列名
for flower, price in zip(flowers, prices):
# 根据提示准备模型的输入
input = prompt.format(flower_name=flower, price=price)
# 获取模型的输出
output = model.invoke(input)
# 解析模型的输出(这是一个字典结构)
parsed_output = output_parser.parse(output)
# 在解析后的输出中添加“flower”和“price”
parsed_output['flower'] = flower
parsed_output['price'] = price
# 将解析后的输出添加到DataFrame中
df.loc[len(df)] = parsed_output
# 打印字典
print(df.to_dict(orient='records'))
# 保存DataFrame到CSV文件
df.to_csv("flowers_with_descriptions.csv", index=False)
解析代码:
第一步:定义输出结构,模型生成的答案包含两部分:鲜花的描述文案(description)和撰写这个文案的原因(reason)。定义了一个名为response_schemas的列表,其中包含两个ResponseSchema对象,分别对应这两部分的输出。通过StructuredOutputParser.from_response_schemas方法创建了一个输出解析器。
第二步:通过输出解析器对象的get_format_instructions()方法获取输出的格式说明(format_instructions),再根据原始的字符串模板和输出解析器格式说明创建新的提示模板(整合了输出解析结构信息)。再通过新的模板生成模型的输入,得到模型的输出。
对于每一个鲜花和价格组合,用 output_parser.parse(output) 把模型输出的文案解析成之前定义好的数据格式,也就是一个Python字典,这个字典中包含了description 和 reason 这两个字段的值。
第三步:把所有信息整合到一个pandas DataFrame对象中(安装Pandas库)。DataFrame对象中包含了flower、price、description 和 reason 这四个字段的值。其中,description 和 reason 是由 output_parser 从模型的输出中解析出来的,flower 和price是自己添加的。
第四步:打印出DataFrame的内容,方便地在程序中处理它,保存为下面的CSV文件。因为此时数据不再是模糊的、无结构的文本,而是结构清晰的有格式的数据。
总结
使用LangChain框架的好处如下:
- 模板管理:在大型项目中,可能会有许多不同的提示模板,使用 LangChain 可以帮助你更好地管理这些模板,保持代码的清晰和整洁。
- 变量提取和检查:LangChain 可以自动提取模板中的变量并进行检查,确保没有忘记填充任何变量。
- 模型切换:如果想要尝试使用不同的模型,只需要更改模型的名称就可以了,无需修改代码。
- 输出解析:LangChain的提示模板可以嵌入对输出格式的定义,以便在后续处理过程中比较方便地处理已经被格式化了的输出。