人工智能 | LangChain 核心模块PromptsModelsParsers

简介

在学习 LangChain 的过程中,第一个核心概念就是 PromptsModelsParsers,也有人叫做 ModelsIO,他们代表了对一次大模型请求的完整周期。如下图所示

  • Prompts:负责请求数据的准备步骤。
  • Model:负责具体请求和参数。
  • Parser:负责请求结果返回后的处理步骤。

三者共同作用,完整的覆盖了整个大模型请求。

使用价值

很多人疑惑的一点可能在于明明基于官方的 API 也可以实现请求响应的一系列过程,为何还要多此一举使用这三个模块呢?

首先先来看一个官方的示例:

OpenAI 官方库示例

先来看一个直接使用官方 API 发起的请求,示例代码如下:

# OpenAI提供的python公共库
import openai
key = 'open_ai_key'
# 设置OpenAI Token
openai.api_key = key
response = openai.ChatCompletion.create(
    # 声明调用的模型名称
    model='gpt-3.5-turbo',
    # temperature用来设置大模型返回数据的随机性和创造性,较低的数值返回的数据就更贴近现实。
    temperature=0.0,
    # 消息内容,可以包含上下文信息,列表数据中的顺序就是对话发生的顺序
    messages=[{'role': 'user', 'content': '1+1等于几?'}]
)
# 从返回数据中拿到具体的答案信息
answer = response['choices'][0]['message']['content']
# 打印调试信息
print(answer)

从以上代码中可以看出以下几个问题:

  1. 官方提供的主要功能为请求的发送,具体发送的数据 messages 部分需要用户自己组织和维护。
  2. 返回的数据 response 部分也只是简单的组装了一个结构。有过开发经验的同学都深有感触,如果每次给到的返回信息从结构到内容都是不一样的,作为调用方,则需要编写无数行代码去处理这些异常。

而 LangChain 的 Prompts、Models、Parsers 则通过了很强的抽象设计解决了这个问题。

实践演练

接下来将分为 2 个模块讲解这三个部分分别起到的作用,最后在展示一下它们合并到一起的效果。

Prompts 与 Models

在学习写作文的过程中,我们的老师常常会教各种句式和结构,目的就是为了让我们的作文更加的清晰明了。

包括在工作之后,我们也会通过学习 STAR 法则,5W1H 等各种方法论让我们的表达更加清晰。

而 Prompt 也是这个作用,让输入提示词的人可以根据一个清晰的结构明确自己要表述的内容。

所以为了实现这个目的,通常会使用 ChatPromptTemplate,可以自行定义让用户输入提示词的结构。

# LangChain相关模块的导入
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate

key = "OpenAIToken"
# 创建OpenAI调用实例
# temperature用来设置大模型返回数据的随机性和创造性,较低的数值返回的数据就更贴近现实。
chat = ChatOpenAI(temperature=0.0, openai_api_key=key)

# 可复用的模板字符串,注意不要使用 f字符串 ,LangChain会在运行时自动替换
template_str = """将三个反引号内的文本内容转换成{style}风格的文本```{text}```"""
# 创建一个针对模板字符串的prompt模板实例
prompt_template = ChatPromptTemplate.from_template(template_str)
# 用prompt模板实例+参数,生成具体的请求消息列表
custom_message = prompt_template.format_messages(
    style="标准文言文",
    text="2023年8月23日下午18:19分,我在盘锦坐在沙发上忽悠两下,感觉到了地震震,房子在晃动两下,窗帘在动,厨房灯在抖动,我连忙打开手机发现大连在地震,而我们是余震,可吓死我了"
    )
# 调用chat发送消息,从ChatGPT中获取相应信息
customer_res = chat(custom_message)
# 相应信息中的content是具体的返回消息体
print(customer_res.content)

Parsers

在前文中已经提到过,ChatGPT 直接返回的文本信息是无格式的,会让调用方在后续编码过程中非常痛苦。

根据业务需求,开发者通常需要大模型返回一个结构化的数据,方便后续的逻辑可以根据这个数据进行进一步的处理。

而这一个问题,可以通过在 Prompt 中给出相应的要求,让返回值达到预期的格式来解决,代码如下所示:

# LangChain相关模块的导入
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
key = 'open_ai_key'
# 创建OpenAI调用实例
# temperature用来设置大模型返回数据的随机性和创造性,较低的数值返回的数据就更贴近现实。
chat = ChatOpenAI(temperature=0.0, openai_api_key=key)
# 可复用的模板字符串,注意不要使用 f字符串 ,LangChain会在运行时自动替换
template_str = """\
对于给出的text数据,从中提取出下列数据
时间: 事件发生的准确时间
地点: 事情发生时,讲述人所处的城市名称
事件: 文中主要讲述的具体事件是发生了什么事件
现象: 列举出事件发生时,出现的每个现象,每个现象作为单独的句子记录
将提取出的数据,按照json的格式显示出来,json的key分别为以下几个字段
时间
地点
事件
现象
text: {text}
"""
# 创建一个针对模板字符串的prompt模板实例
prompt_template = ChatPromptTemplate.from_template(template_str)
# 用prompt模板实例+参数,生成具体的请求消息列表
custom_message = prompt_template.format_messages(
    text="2023年8月23日下午18:19分,我在盘锦坐在沙发上忽悠两下,感觉到了地震,房子在晃动两下,窗帘在动,厨房灯在抖动,我连忙打开手机发现大连在地震,而我们是余震,可吓死我了"
)
# 调用chat发送消息,从ChatGPT中获取相应信息
customer_res = chat(custom_message)
# 相应信息中的content是具体的返回消息体
print(customer_res.content)
print(type(customer_res.content))

但是!现有的这个输出无法满足我们的需求,因为它实际的返回是 string,但是需求要求为 dict 格式数据。

可以通过 ResponseSchema 将返回值信息彻底转换为我们需要的结构信息。

1.针对prompt中的每个想要提取的属性,创建ResponseSchema记录字段名称和描述,用于后续解析返回数据:

# LangChain相关模块的导入
from langchain.output_parsers import ResponseSchema, StructuredOutputParser
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
key = 'open_ai_key'
# 创建OpenAI调用实例
# temperature用来设置大模型返回数据的随机性和创造性,较低的数值返回的数据就更贴近现实。
chat = ChatOpenAI(temperature=0.0, openai_api_key=key)
# 可复用的模板字符串,注意不要使用 f字符串 ,LangChain会在运行时自动替换
template_str = """\
text: {text}
{format_instructions}
"""
# 针对prompt中的每个想要提取的属性,创建ResponseSchema记录字段名称和描述,用于后续解析返回数据
time_schema = ResponseSchema(name="时间", description="事件发生的准确时间")
location_schema = ResponseSchema(name="地点", description="事情发生时,讲述人所处的城市名称")
event_schema = ResponseSchema(name="事件", description="文中主要讲述的具体事件是发生了什么事件")
situation_schema = ResponseSchema(
    name="现象",
    description="列举出事件发生时,出现的每个现象,每个现象作为列表中的单独一项"
)

2.将所有schema组装成列表,生成响应值结构化解析器,并根据schema格式定义,自动生成一个支持格式化输出的Prompt:

response_schemas = [time_schema, location_schema, event_schema, situation_schema]
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
# 根据schema格式定义,自动生成一个支持格式化输出的prompt
format_instructions = output_parser.get_format_instructions()
# 输出生成的prompt查看格式
print(format_instructions)

3.根据模板和数据,生成完整成Prompt请求数据:

prompt_template = ChatPromptTemplate.from_template(template_str)
custom_message = prompt_template.format_messages(
    text="2023年8月23日下午18:19分,我在盘锦坐在沙发上忽悠两下,感觉到了地震,房子在晃动两下,窗帘在动,厨房灯在抖动,我连忙打开手机发现大连在地震,而我们是余震,可吓死我了",
    format_instructions=format_instructions
)
# 根据结构化解析器,解析返回数据,获取类型正确的数据结果
result = output_parser.parse(resp.content)
print(result)
print(type(result))

完整代码为:

# LangChain相关模块的导入
from langchain.output_parsers import ResponseSchema, StructuredOutputParser
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
key = 'open_ai_key'
# 创建OpenAI调用实例
# temperature用来设置大模型返回数据的随机性和创造性,较低的数值返回的数据就更贴近现实。
chat = ChatOpenAI(temperature=0.0, openai_api_key=key)
# 可复用的模板字符串,注意不要使用 f字符串 ,LangChain会在运行时自动替换
template_str = """\
  text: {text}
  {format_instructions}
"""
# 针对prompt中的每个想要提取的属性,创建ResponseSchema记录字段名称和描述,用于后续解析返回数据
time_schema = ResponseSchema(name="时间", description="事件发生的准确时间")
location_schema = ResponseSchema(name="地点", description="事情发生时,讲述人所处的城市名称")
event_schema = ResponseSchema(name="事件", description="文中主要讲述的具体事件是发生了什么事件")
situation_schema = ResponseSchema(
    name="现象",
    description="列举出事件发生时,出现的每个现象,每个现象作为列表中的单独一项"
)
# 将全部的属性描述schema组装成列表,生成相应值结构化解析器
response_schemas = [time_schema, location_schema, event_schema, situation_schema]
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
# 根据schema格式定义,自动生成一个支持格式化输出的prompt
format_instructions = output_parser.get_format_instructions()
# 输出生成的prompt查看格式
print(format_instructions)
# 根据模板和数据,生成完整成prompt请求数据
prompt_template = ChatPromptTemplate.from_template(template_str)
custom_message = prompt_template.format_messages(
    text="2023年8月23日下午18:19分,我在盘锦坐在沙发上忽悠两下,感觉到了地震,房子在晃动两下,窗帘在动,厨房灯在抖动,我连忙打开手机发现大连在地震,而我们是余震,可吓死我了",
    format_instructions=format_instructions
)
# 调用大模型发起请求
customer_res = chat(custom_message)
# 根据结构化解析器,解析返回数据,获取类型正确的数据结果
result = output_parser.parse(customer_res.content)
print(result)
print(type(result))

返回结果示例如图:

如此一来,通过解析器解析之后的数据,格式已经转为了 Python 中支持的 dict 格式,可以直接给后续的逻辑中使用。

更多Python基础语法趣味学习视频,请点击!

  • 25
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值