[TOC]
LangChain 在与语言模型交互时的三个主要环节:
- 输入提示(Format)
- 调用模型(Predict)
- 输出解析(Parse)
这三个环节被统称为 Model I/O,可以理解为与语言模型交互的整个过程。
-
输入提示(Format) :
- 在调用语言模型之前,我们需要向模型提供一定的输入。LangChain提供了模板(Prompt Templates)功能,允许你根据不同的任务动态构建提示信息。这样,你可以灵活地调整输入,以便模型能够更好地理解并生成所需的结果。
-
调用模型(Predict) :
- 这一部分是实际调用语言模型的过程。LangChain提供了一个统一的接口,可以通过该接口调用不同的语言模型,无论是 OpenAI、GPT 或其他模型,都能以相同的方式进行调用。这种统一接口提高了代码的灵活性和可移植性。
-
输出解析(Parse) :
- 模型生成的输出通常是非结构化的文本,这可能包含冗余或不相关的信息。LangChain提供了输出解析功能,帮助你从模型的文本输出中提取出需要的关键信息,并将这些信息转化为结构化数据(如 JSON 格式),方便后续处理和使用。
提示工程(Prompt Engineering)
提示工程(Prompt Engineering),是指通过设计合理的提示,引导模型生成更加符合你需求的答案或内容。Langchain提供了强大的工具,帮助用户更便捷地构建和管理提示模板。
提示模板
提示模板的核心是通过占位符来定义提示的格式,并根据实际输入填充这些占位符,从而生成最终的提示内容。LangChain中的提示模板 允许我们使用占位符来定义模板格式。
from langchain.prompts import PromptTemplate
# 创建原始模板
template = """您是一位专业的鲜花店文案撰写员。\n
对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?
"""
# 根据原始模板创建LangChain提示模板
prompt = PromptTemplate.from_template(template)
# 打印LangChain提示模板的内容
print(prompt)
得到的回复如下:
input_variables=['flower_name', 'price'] template='您是一位专业的鲜花店文案撰写员。\n\n对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?\n' content='50 元的玫瑰,绽放着爱的芬芳,传递着深情的祝福。每一朵都如爱情的使者,用娇艳的姿态诉说着浪漫的故事。它是表达爱意的最佳选择,让你的心意在这束玫瑰中完美呈现。'
另外我们还可以将模版实例化,使用特定的变量值来替换模版中的占位符,生成最终的提示字符串。这种方式的好处是,你可以复用相同的模板,通过不同的输入数据生成不同的提示,从而得到与之对应的模型输出。
在之前的例子中,模板格式如下:
template = """您是一位专业的鲜花店文案撰写员。\n
对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?
"""
这个模板定义了两个占位符:{price} 和 {flower_name},当我们提供具体的花名和价格时,就可以将模板实例化,生成具体的提示内容。
输出解析
输出解析 是将模型返回的非结构化文本数据(如一段自由文本)转化为程序可以直接处理的结构化数据的过程。
例如:
在大多数开发应用中,模型返回的结果通常是非结构化的文本。例如,在生成鲜花文案时,模型返回的内容可能是像下面这样的一段文本:
让你心动!50元就可以拥有这支充满浪漫气息的玫瑰花束,让TA感受你的真心爱意。为什么这样说呢?因为爱情是无价的,50元对应热恋中的情侣也会觉得值得。
而我们可能想要将这段文本分解为更有意义的数据结构,如 Python 字典,方便后续处理,例如:
{
'description': '让你心动!50元就可以拥有这支充满浪漫气息的玫瑰花束,让TA感受你的真心爱意。',
'reason': '因为爱情是无价的,50元对应热恋中的情侣也会觉得值得。'
}
为了让模型的输出更容易被程序处理和分析,我们可以利用 LangChain 提供的 输出解析器 来自动提取有用的信息,并将其转化为结构化的数据。
输出解析的实现
在 LangChain 中,输出解析的关键组件是 StructuredOutputParser 和 ResponseSchema。我们可以使用它们来定义期望的输出结构,之后模型的输出就会遵循这个结构进行格式化,从而方便后续解析和处理。
定义输出结构
首先,我们定义一个 ResponseSchema 列表,描述我们期望从模型中得到的输出字段。
# 定义输出的结构
response_schemas = [
ResponseSchema(name="description", description="鲜花的描述文案"),
ResponseSchema(name="reason", description="撰写文案的原因")
]
创建输出解析器
模型输出包括 description(鲜花的文案描述)和 reason(为何这样写文案的原因)。
再根据定义的 ResponseSchema,我们创建一个 StructuredOutputParser 对象,这个对象将帮助我们解析模型输出并将其转化为结构化数据。
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
获取格式说明并创建提示模板
输出解析器有一个方法 get_format_instructions() ,可以生成模型应遵循的格式说明。这些说明会被包含到我们的提示模板中,确保模型生成的输出遵循预定的格式。
# 获取格式说明
format_instructions = output_parser.get_format_instructions()
# 创建提示模板,将格式指示嵌入其中
prompt_template = """您是一位专业的鲜花店文案撰写员。
对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?
{format_instructions}"""
# 创建LangChain提示模板实例
from langchain.prompts import PromptTemplate
prompt = PromptTemplate.from_template(prompt_template, partial_variables={"format_instructions": format_instructions})
调用模型并解析输出
通过 model.invoke(input) 调用模型,获取模型的响应,并通过输出解析器进行解析,将非结构化的文本转化为结构化数据(例如,Python 字典)。
from langchain_openai import OpenAI
# 创建模型实例
model = OpenAI(model_name='gpt-3.5-turbo-instruct')
# 假设我们有一些鲜花和价格列表
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_text = prompt.format(flower_name=flower, price=price)
# 获取模型输出
output = model.invoke(input_text)
# 解析输出
parsed_output = output_parser.parse(output)
# 将“flower”和“price”添加到解析后的输出中
parsed_output['flower'] = flower
parsed_output['price'] = price
# 将解析后的数据添加到DataFrame中
df.loc[len(df)] = parsed_output
# 打印DataFrame内容
print(df.to_dict(orient='records'))
# 保存到CSV文件
df.to_csv("flowers_with_descriptions.csv", index=False)
输出CSV文件内容为:
flower,price,description,reason 玫瑰,50,50 元的玫瑰,是爱情的象征,是浪漫的表达,是心意的传递。,这个文案突出了玫瑰的象征意义,强调了它在爱情、浪漫和心意传递方面的重要性,同时也提到了价格,让顾客对产品有更清晰的了解。 百合,30,纯洁高雅的百合,仅需 30 元,为你的生活增添一抹清新与浪漫。,突出百合纯洁高雅的特点,同时强调价格实惠,能够吸引消费者的注意。 康乃馨,20,仅需 20 元,即可拥有一束温馨的康乃馨,为生活增添一抹亮丽的色彩。,突出价格实惠,同时强调康乃馨能为生活带来温馨和亮丽色彩,吸引消费者购买。