AI实战课程笔记-03

130 阅读8分钟

LangChain六大核心组件

  • Model
  • Prompts
  • Chains
  • Memory
  • Agents
  • Indexes

Model I/O

  • 输入提示(Format):使用模型的第一个环节是把提示信息输入到模型中。我们可以创建LangChain的提示模板,根据实际需求动态选择不同的输入。
  • 调用模型(Parse):LangChain允许我们通过通用接口来调用语言模型。
  • 输出解析(Input/Output):LangChain还提供了从模型输出中提取信息的功能。通过输出解析器,我们可以精确地从模型的输出中获取需要的信息,而不需要处理冗余或不相关的数据,更重要的是还可以把大模型给回的非结构化文本,转换成程序可以处理的结构化数据。

1 提示模板

1.1 提示模板的生成方式

导入langchain中的提示模板

import os
from langchain.prompts import PromptTemplate

PromptTemplate 是 LangChain 库中的一个类,用于创建和管理提示模板。通过使用 PromptTemplate,可以定义一个模板,其中包含固定的文本和可变的占位符,这些占位符可以在运行时被具体的值替换。

在导入 PromptTemplate 之后,通常会创建一个提示模板的实例,并使用它来格式化输入,然后将格式化后的提示传递给语言模型进行处理。

根据原始模板创建LangChain提示模板

template = """您是一位专业的鲜花店文案撰写员。\n 对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗? """ 
prompt = PromptTemplate.from_template(template) 
print(prompt)

from_templatePromptTemplate 类的一个方法,它允许我们直接从一个字符串模板中创建一个PromptTemplate对象,这个对象就是LangChain中的提示模板。

1.2 PromptTemplate对象的具体内容

input_variables=['flower_name', 'price'] 
output_parser=None partial_variables={} 
template='/\n您是一位专业的鲜花店文案撰写员。\n对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?\n'
template_format='f-string' 
validate_template=True
  • input_variables表示输入变量是flower_name 和 price
  • output_parser=None 表示没有指定输出解析器
  • partial_variables 参数表示一个字典,用于提供模板中占位符的部分变量值,格式为 {模板中的占位符内容:替换后的内容}partial_variables={} 表示没有提供任何部分变量值,因此模板中的所有占位符都将等待在实例化时被填充。
  • template_format='f-string'表示模版格式为‘f-string’格式。f-string 是 Python 3.6 及以后版本引入的一种字符串格式化方式,它允许在字符串字面量中插入表达式,并在运行时计算这些表达式的值。f-string 的格式通常是在字符串的前面加上字母 f 或 F,然后在字符串内部使用花括号 {} 来包含要插入的表达式。
  • validate_template参数表示是否验证模版有效性。当设置为 True 时,LangChain 会检查模板字符串是否符合特定的格式要求,例如是否包含正确的占位符和语法。如果模板字符串格式不正确,验证将失败,并可能抛出一个异常。如果验证通过,from_template 方法将继续创建建 PromptTemplate 对象。

2 语言模型

2.1 LangChain支持的语言模型

  • 大语言模型(LLM):也叫Text Model,这些模型将文本字符串作为输入,并返回文本字符串作为输出。Open AI的text-davinci-003、Facebook的LLaMA、ANTHROPIC的Claude,都是典型的LLM。
  • 聊天模型(Chat Model):主要代表Open AI的ChatGPT系列模型。这些模型通常由语言模型支持,但它们的 API 更加结构化。具体来说,这些模型将聊天消息列表作为输入,并返回聊天消息。
  • 文本嵌入模型(Embeding Model):这些模型将文本作为输入并返回浮点数列表,也就是Embedding。文本嵌入模型负责把文档存入向量数据库,典型的文本嵌入模型如我们之前见的OpenAI的text-embedding-ada-002。

2.2 调用语言模型

调用OpenAI类创建模型

os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key'
from langchain_openai import OpenAI
model = OpenAI(model_name='gpt-3.5-turbo-instruct')
  • 首先在系统的环境变量处设置OpenAI API Key
  • 从 langchain_openai 模块中导入 OpenAI类,该类通常用于与 OpenAI 的文本模型(如 text-davinci-003)进行交互,它提供了一种简单的方法来调用 OpenAI 的 API 并获取文本生成的结果。
  • 利用OpenAI 类的构造函数创建了一个OpenAI 模型的实例model,使用的模型名称是 gpt-3.5-turbo-instructOpenAI 类的构造函数接受一个或多个参数,用于指定要使用的模型名称、API 密钥、temperature(控制输出的随机性)等。在本次示例中我们只指定了模型名称。 调用ChatOpenAI类创建模型
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model=os.environ.get("LLM_MODELEND"))
  • 从 langchain_openai 模块中导入 ChatOpenAI类,该类用于与 OpenAI 的聊天模型(如 gpt-3.5-turbo 或 gpt-4)进行交互,它允许我们构建一个对话历史,并以对话的形式与模型进行交流。
  • 首先使用 os.environ.get() 方法从环境变量中获取名为 LLM_MODELEND 的值,并将其赋值给变量 model_name。这个环境变量通常包含了要使用的 OpenAI 模型的名称,例如 gpt-3.5-turbo 或 gpt-4。然后使用获取到的模型名称 model_name 来初始化 ChatOpenAI 类的实例 model

输入提示

input = prompt.format(flower_name=["玫瑰"], price="50")

调用了 PromptTemplate类的 format 方法,传入了两个参数:flower_name 和 price。这两个参数将替换模板字符串中的占位符 {flower_name} 和 {price},生成一个具体的输入字符串。 得到模型的输出

output = model.invoke(input)
print(output)

调用了 model 实例的 invoke 方法,并将之前格式化好的输入字符串 input 作为参数传递给该方法。invoke 方法会将这个输入字符串发送给 OpenAI 的聊天模型,并返回模型生成的响应。

使用LangChain相较于直接使用Open AI API的优势:我们只需要定义一次模板,就可以用它来生成各种不同的提示。对比单纯使用 f-string 来格式化文本,这种方法更加简洁,也更容易维护。而LangChain在提示模板中,还整合了output_parsertemplate_format 以及是否需要validate_template等功能。

3 输出解析

创建输出解析器

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}
)
  • langchain.output_parsers 模块导入StructuredOutputParser 和 ResponseSchema 两个类。
    • StructuredOutputParser 是一个用于解析结构化输出的类。它可以帮助我们从模型的输出中提取特定的信息,并将其转换为结构化的数据格式,例如字典或列表。
    • ResponseSchema 是一个用于定义输出结构的类。可以用它来指定我们期望从模型输出中获取哪些信息,以及这些信息应该如何被组织。
  • 接下来定义了一个名为 response_schemas 的列表,该列表包含两个 ResponseSchema 对象。每个 ResponseSchema 对象都有一个名称和一个描述。
  • 根据我们之前定义的 response_schemas 列表创建一个 StructuredOutputParser 对象。调用了 StructuredOutputParser 类的 from_response_schemas 方法,传入了 response_schemas 列表作为参数。这个方法会根据列表中的 ResponseSchema 对象自动生成解析规则,以便后续能够将模型的输出解析成指定的结构化格式。
  • 然后调用 StructuredOutputParser 类的 get_format_instructions 方法获取格式指示。这个方法返回一个字符串,该字符串包含了如何格式化模型输出的说明。这些说明通常是一个 JSON 结构的模板,模型的输出应该遵循这个模板,以便 output_parser 能够正确地解析它。
  • 最后我们在提示模板中加入输出解析器的说明。

将解析好的数据存入csv文档

# 数据准备
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.content)
    # 在解析后的输出中添加“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)
  • parse 方法会根据 output_parser 中定义的解析规则,从模型输出的文本中提取出相应的信息,并将其转换为字典格式。
  • df.loc[len(df)]:使用 loc 索引器来选择 DataFrame 的下一行。len(df) 返回 DataFrame 的当前长度,因此 df.loc[len(df)] 指向的是 DataFrame 的最后一行之后的新行。 df.loc[len(df)] = parsed_output 这行代码的作用是将解析后的输出数据作为新的一行添加到 DataFrame 中。
  • orient="records" 参数在 pandas.DataFrame.to_dict() 方法中指定了将 DataFrame 转换为字典的格式。具体来说,它指定了将 DataFrame 的每一行转换为一个字典,其中字典的键是 DataFrame 的列名,值是对应行的数据。