模型I/O | 第七届青训营笔记

94 阅读7分钟

[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 中,输出解析的关键组件是 StructuredOutputParserResponseSchema。我们可以使用它们来定义期望的输出结构,之后模型的输出就会遵循这个结构进行格式化,从而方便后续解析和处理。

定义输出结构

首先,我们定义一个 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 元,即可拥有一束温馨的康乃馨,为生活增添一抹亮丽的色彩。,突出价格实惠,同时强调康乃馨能为生活带来温馨和亮丽色彩,吸引消费者购买。