【大语言模型】LangChain ModelsIO与Prompts详解
- 一、LangChain ModelsIO
- 1、简介
- 2、Models I/O 的应用场景
- 3、Models I/O 主要模块
- 3.1、Prompts
- 3.2、Models
- a、MESSAGES 类型
- 3.3、Output Parsers
- 二、LangChain ModelsIO Prompts
- 1、简介
- 2、Prompts 的优点
- 3、实战示例
- 3.1、PromptTemplate 提示模板的用法
- 3.1.1、LCEL 表达式
- 3.2、ChatPromptTemplate 聊天提示模板的用法
- 3.2.1、二元组
- 3.2.2、MessagePromptTemplate 或 BaseMessage 的实例
- 3.3、LCEL 表达式
一、LangChain ModelsIO
1、简介
LangChain 实质上是对大语言模型(LLM)的一个扩展封装,其主要目的仍然是为了更好的使用大语言模型。
通过 LangChain,用户可以通过输入文本或补充模板信息来获取符合需求的文本输出。不难看出 LangChain 最终操作的结果都是字符串,因此在使用过程中不可避免地涉及到大量的文本处理工作,例如输入的格式化和输出结果的解析等。
2、Models I/O 的应用场景
文本处理工作既复杂又重复,对于开发者来说是一个必要但不重要的繁琐步骤。
LangChain 深知文本处理的痛点,因此提供了 Prompt Templates 和 Output Parser 抽象。用户可以根据自己的需求选择合适的实现类型,从而简化文本处理工作,提高开发效率。I/O 最主要的需要包含以下两个部分:
- Prompt Templates: 负责请求数据的准备步骤。
- Output Parser:则用于解析输出结果。
这样开发者就可以专注于业务逻辑的实现,而无需过多关注底层的文本处理细节。这种抽象的设计使得 LangChain 在大语言模型应用开发中具有更强的灵活性和可扩展性。
3、Models I/O 主要模块
3.1、Prompts
提示指的是将用户输入转换为语言模型的输入。这个提示由提示模板完成,它将用户的输入转换为一系列消息列表或最终的字符串对象。LangChain 提供了多种抽象,使得操作提示变得更加简单和灵活。
包含以下几种类型:
- PromptValue:包含一个要转换为字符串的方法,以及一个要转换为消息列表的方法。
- PromptTemplate:由模板字符串组成,格式化用户输入转为大语言模型的输入。
- MessagePromptTemplate:由模板消息和一个 PromptTemplate 组成,将用户输入进行格式化,以生成最终字符串,即为消息的 content。
- MessagesPlaceholder:消息的输入可以是消息列表。
- ChatPromptTemplate:由 MessagePromptTemplate 和 MessagesPlaceholder 的列表组成,根据用户输入对这些内容进行格式化以生成最后的消息列表。
3.2、Models
LangChain 集成的模型主要有两个类型:LLMs 和聊天模型。
LLMs:指的是纯文本补全模型,包装的 API 将字符串提示作为输入并输出字符串完成。
Chat Models:聊天模型在 LLMs 的基础上针对对话进行了调整。将包含聊天消息的列表作为输入,
不同模型适合不同的提示策略,这意味着为一种模型设计的优化提示可能无法直接应用于其他模型。虽然 LangChain 提供了许多默认提示,但无法保证这些默认提示在所有模型中都能发挥良好的效果。
a、MESSAGES 类型
ChatModels 将详细列表作为输入并返回消息。所有消息都有一个 role 和 content 属性。role 代表消息的发出者是谁,content 描述了消息的具体内容,可能是几种不同的内容形式
除了上述两种类型外,消息还有一个 additional_kwargs 的属性,可以传递消息的附加信息,例如 OpenAI 的 function_call 。
类型 | 作用 |
---|---|
HumanMessage | 代表用户的消息。 |
AIMessage | 代表模型输出的消息。 |
SystemMessage | 代表系统消息。 |
FunctionMessage | 表示函数调用的结果,该参数为被调用的函数的名称。 |
ToolMessage | 表示工具调用的结果,对应匹配 OpenAI 的 function 和 tool 消息类型。 |
3.3、Output Parsers
输出解析器是用来处理模型生成的文本输出的组件,它接收模型的输出并将其转换为更易于使用的形式。
通常,输出解析器会将模型输出中的信息提取出来,特别是针对输出信息中的内容部分,有时也会处理额外的参数,如 additional_kwargs 字段中的值。
常见的输出解析器类型有如下几种:
- StrOutputParser:把语言模型的输出转换为字符串。
- OpenAI Functions Parsers:用于处理 OpenAI 函数调用,获取并使用 function_call 和 arguments 参数。
- Agent Output Parsers:根据用户输入和应用场景,选择合适的方案来执行操作。
二、LangChain ModelsIO Prompts
1、简介
在 LangChain Models 中输入和输出同样重要,Promots 即为对输入信息的处理。这些提示是用户提供给模型的一组指令或输入,旨在触发模型生成响应并协助理解上,以生成相关且连贯的语言的输出。
但是涉及到提示的内容过于冗长,并且很多是重复且不需要每次关注的内容,为了简化这一过程并提高效率,Prompts 提供了许多模板类型,使得输入步骤变得更加简洁高效。
2、Prompts 的优点
LangChain 提供的常见模板能够帮助用户快速构建适当的输入,以获得相对准确的输出结果。Langchain 的目标是创建出与模型无关的模板,以便能够轻松地跨不同语言模板重用现有模板。
模板可以包括说明、少量示例以及适合给定任务的特定上下文和问题。
并且所有模板都实现了 Runnable 接口,在内部完成对于 Runnable 的实现,这样用户可以轻松的使用 LCEL 将 prompt 与其他的 Runnable 对象连接起来。
3、实战示例
3.1、PromptTemplate 提示模板的用法
使用 PromptTemplate 创建字符串提示模板,默认情况下 PromptTemplate 使用 Python 的 str.format 语法进行模板化。
用户只需要自定义的消息提示语,将不同部分用插值的方式表示来自定义提示模板。
PromptTemplate 支持多个变量,如下代码所示:
from langchain_core.prompts import PromptTemplate
# 定义一个包含两个变量的提示模板
prompt = PromptTemplate.from_template("给出一个{topic} 的广告, 它的价格是 {price} ¥,广告需要能够引起用户的兴趣")
# 格式化并传入参数
print(prompt.format(topic='冰淇淋', price=3))
# 给出一个冰淇淋的广告, 它的价格是 3 ¥,广告需要是能够引起用户兴趣的
除了支持多个变量之外,还支持无变量的形式,如下代码所示:
from langchain_core.prompts import PromptTemplate
# 定义一个包含两个变量的提示模板
prompt = PromptTemplate.from_template("告诉我一个广告")
# 格式化并传入参数
print(prompt.format())
# 告诉我一个广告
3.1.1、LCEL 表达式
PromptTemplate 接受字典并返回 StringPromptValue。
# 定义一个包含两个变量的提示模板
prompt = PromptTemplate.from_template("给出一个{topic} 的广告, 它的价格是 {price} ¥,广告需要能够引起用户的兴趣")
# invoke 调用
prompt_val = prompt.invoke({"topic": "冰淇淋", "price": "3"})
print(prompt_val)
# text='给出一个冰淇淋的广告, 它的价格是 3 ¥,广告需要是能够引起用户兴趣的'
通过 to_string() 方法能够将结果转换为字符串
# 定义一个包含两个变量的提示模板
prompt = PromptTemplate.from_template("给出一个{topic} 的广告, 它的价格是 {price} ¥,广告需要能够引起用户的兴趣")
# invoke 调用
prompt_val = prompt.invoke({"topic": "冰淇淋", "price": "3"})
print(prompt_val)
# text='给出一个冰淇淋的广告, 它的价格是 3 ¥,广告需要是能够引起用户兴趣的'
print(prompt_val.to_string())
#给出一个冰淇淋 的广告, 它的价格是 3 ¥,广告需要能够引起用户的兴趣
3.2、ChatPromptTemplate 聊天提示模板的用法
聊天模型的提示是聊天消息列表,传入时需要传入一个消息的列表,其中传入的消息都需要与 OpenAI 消息列表的 role 相关,每个 role 对应的有不同的文本描述用来串联上下文,Langchain 同样提供这样的形式来完成对 role 和 content 的定义,以实现更为方便的构建聊天提示。
聊天提示模板有两种书写方式:
- 二元组。
- MessagePromptTemplate 或 BaseMessage 的实例。
3.2.1、二元组
代码示例如下所示:
# 制定模板
chat_prompt = ChatPromptTemplate.from_messages([("system", "你是一个游戏的 npc,有三个任务让玩家完成,需要给出玩家三个任务,并且规定出完成的标准。"),("human", "你好,我是这个游戏的玩家"),("ai", "{user} 玩家你好,欢迎来到这个游戏"),("human", "{user_input}"),])
# 格式化消息列表,并且传入参数
messages = chat_prompt.format_messages(user="ling", user_input="你好,我需要做什么")
print(messages)
# [SystemMessage(content='你是一个游戏的 npc,有三个任务让玩家完成,需要给出玩家三个任务,并且规定出完成的标准。'), HumanMessage(content='你好,我是这个游戏的玩家'), AIMessage(content='ling 玩家你好,欢迎来到这个游戏'), HumanMessage(content='你好,我需要做什么')]
3.2.2、MessagePromptTemplate 或 BaseMessage 的实例
chat_template = ChatPromptTemplate.from_messages([SystemMessage(content=("你是一个擅长制定计划的助手""计划需要贴合用户需求,给出详细的时间节点和任务指标")),HumanMessagePromptTemplate.from_template("{user_req}")]
)
messages_o = chat_template.format_messages(user_req="我想要一个旅行计划")
print(messages_o)
# [SystemMessage(content='你是一个擅长制定计划的助手计划需要贴合用户需求,给出详细的时间节点和任务指标'), HumanMessage(content='我想要一个旅行计划')]
3.3、LCEL 表达式
ChatPromptValue 接受字典并返回转换后消息的值。可以转换为消息列表或者是转换为字符串。
# 使用 invoke 方式调用
chat_prompt = ChatPromptTemplate.from_messages([("system", "你是一个游戏的 npc,有三个任务让玩家完成,需要给出玩家三个任务,并且规定出完成的标准。"),("human", "你好,我是这个游戏的玩家"),("ai", "{user} 玩家你好,欢迎来到这个游戏"),("human", "{user_input}"),])
chat_val = chat_prompt.invoke({"user": "ling", "user_input": "你好,我需要做什么"})
print(chat_val)
# messages=[SystemMessage(content='你是一个游戏的 npc,有三个任务让玩家完成,需要给出玩家三个任务,并且规定出完成的标准。'), HumanMessage(content='你好,我是这个游戏的玩家'), AIMessage(content='ling 玩家你好,欢迎来到这个游戏'), HumanMessage(content='你好,我需要做什么')]
print(chat_val.to_string())
"""
System: 你是一个游戏的 npc,有三个任务让玩家完成,需要给出玩家三个任务,并且规定出完成的标准。
Human: 你好,我是这个游戏的玩家
AI: ling 玩家你好,欢迎来到这个游戏
Human: 你好,我需要做什么
"""