写点什么

人工智能 | LangChain 核心模块 PromptsModelsParsers

  • 2023-12-13
    北京
  • 本文字数:4448 字

    阅读完需:约 15 分钟

简介

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



  • Prompts:负责请求数据的准备步骤。

  • Model:负责具体请求和参数。

  • Parser:负责请求结果返回后的处理步骤。

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

使用价值

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

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

OpenAI 官方库示例

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

# OpenAI提供的python公共库import openaikey = 'open_ai_key'# 设置OpenAI Tokenopenai.api_key = keyresponse = 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 ChatOpenAIfrom 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 ChatOpenAIfrom langchain.prompts import ChatPromptTemplatekey = '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, StructuredOutputParserfrom langchain.chat_models import ChatOpenAIfrom langchain.prompts import ChatPromptTemplatekey = '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格式定义,自动生成一个支持格式化输出的promptformat_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, StructuredOutputParserfrom langchain.chat_models import ChatOpenAIfrom langchain.prompts import ChatPromptTemplatekey = '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格式定义,自动生成一个支持格式化输出的promptformat_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基础语法趣味学习视频,请点击!

领取人工智能学习资料,请点击!!!

用户头像

社区:ceshiren.com 微信:ceshiren2023 2022-08-29 加入

微信公众号:霍格沃兹测试开发 提供性能测试、自动化测试、测试开发等资料、实事更新一线互联网大厂测试岗位内推需求,共享测试行业动态及资讯,更可零距离接触众多业内大佬

评论

发布
暂无评论
人工智能 | LangChain 核心模块PromptsModelsParsers_测试_测吧(北京)科技有限公司_InfoQ写作社区