LangChain大型语言模型(LLM)应用开发(一):Models, Prompts and Output Parsers

news2024/12/27 13:27:50

LangChain是一个基于大语言模型(如ChatGPT)用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,以便在不同的应用程序中使用。

今天我们来学习DeepLearning.AI的在线课程:LangChain for LLM Application Development的第一门课:Models, Prompts and Output Parsers,该门课程主要讲解如何在Langchain中定义模型,如何编写Prompt以及如何对输出结果进行解析。

设置访问LLM的API key

因为Langchain本身只是一个LLM的应用框架,所以它必须和LLM对接才能使用,这里和Langchain对接的LLM主要是openai的语言模型,所以我们需要设置访问Openai的api key:

#!pip install python-dotenv
#!pip install openai

import os
import openai

from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv()) # read local .env file
openai.api_key = os.environ["OPENAI_API_KEY"]

Chat API : OpenAI

首先让我们从直接从调用 OpenAI 的API 开始。下面是我们访问openai的“gpt-3.5-turbo”模型的主要代码:

def get_completion(prompt, model="gpt-3.5-turbo"):
    messages = [{"role": "user", "content": prompt}]
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        temperature=0, 
    )
    return response.choices[0].message["content"]

 下面我们我们用openai的api来实现一个简单的语调转换的简单例子,首先我们需要定义一个prompt:

customer_email="""
哎呀,我很生气,因为我的搅拌机盖子飞走了,冰沙溅到了我的厨房墙壁上! 
更糟糕的是,保修不包括清理厨房的费用。 我现在需要你的帮助,朋友!
"""

style ="""
委婉和耐心的语气表达
"""

prompt =f"""将由三个反引号分隔的文本
转换为{style}风格。
文本:```{customer_email}```
"""

print(prompt)

 这里我们定义了一个prompt,该prompt是由f-string定义的一个长字符串,其中嵌入了两个变量,style和customer_email,并且主要的文本内容customer_email用一对3个反引号隔离。这是创建openai的prompt的典型方法。

response = get_completion(prompt)
print(response)

Chat API : LangChain

让我们尝试一下如何使用 LangChain 来做同样的事情。

Model

首先我们需要通过langchain来创建一个chat model对象:

#!pip install --upgrade langchain

from langchain.chat_models import ChatOpenAI

#要减少LLM 生成文本的随机性,请设置温度参数= 0.0
chat = ChatOpenAI(temperature=0.0)
chat

 这里我们定义了一个Langchain的聊天模型,该模型的默认参数均为openai的API的参数,如“model_name”=“gpt-3.5-turbo”,“temperature”=0.0等,这里需要说明的时候temperature参数的默认值为0.7,只是这里我们人为设置为0.0,除此之外其他参数均为默认参数。

定义Langchain的Prompt 模板

style ="""
委婉和耐心的语气表达
"""
customer_email="""
哎呀,我很生气,因为我的搅拌机盖子飞走了,冰沙溅到了我的厨房墙壁上! 
更糟糕的是,保修不包括清理厨房的费用。 我现在需要你的帮助,朋友!
"""

template_string = """将由三个反引号分隔的文本
转换为 {style} 风格。
文本:```{text}```
"""

这里需要说明的是template_string并不是f-string,所以其中的{style}和{text}并不是变量,而是属于字符串本身的一部分。接下来我们需要定义一个prompt模板:ChatPromptTemplate

from langchain.prompts import ChatPromptTemplate

prompt_template = ChatPromptTemplate.from_template(template_string)
prompt_template

 这里我们可以看到虽然我们没有将template_string定义为f-string,但是当我们创建prompt_template 时,会自动将template_string的中{style}和{text}识别为变量,并且将模板的格式定义为f-string。

下面我们创建一个message,该message是由prompt 模板的format_messages方法生成的,该方法包含了两个参数:style和text, 这两个参数对应于template_string 中的两个变量{style}和{text}。

customer_messages = prompt_template.format_messages(
                    style=style,
                    text=customer_email)
customer_messages

下面我们调用LLM 来实现客户信息的语气风格转换:

#调用LLM来翻译客户信息的风格
customer_response = chat(customer_messages)
print(customer_response.content)

 

 这里我们可以看到输出结果与之前直接调用openai api的方法的结果是一样的。下面我们再看一个例子:

service_reply ="""
嘿,顾客,保修不包括厨房的清洁费用,\
因为您在启动搅拌机之前忘记盖上盖子而误用搅拌机,这是您的错。 \
倒霉! 再见!
"""

service_style = """
和蔼和礼貌的口吻
"""

service_messages = prompt_template.format_messages(
    style=service_style,
    text=service_reply)

print(service_messages[0].content)

service_response = chat(service_messages)
print(service_response.content)

 

 输出解析(Output Parsers)

 在之前的博客:使用大型语言模(LLM)构建系统(七):评估1中我们发现有时候LLM的输出结果数据中除了会包含我们需要的指定格式数据以外还会附带一些文本说明信息,而这些文本说明信息的存在不利于我们解析LLM的输出结果,在之前的博客中我们通过修改prompt,在其中加入禁止输出某些的内容的语句后,输出结果有了改善。下面我们看看Langchain是如果来解析LLM的输出结果的。

customer_review = """
这款吹风机非常神奇。 它有四个设置:\
吹蜡烛、微风、风城、龙卷风。 \
两天后就到了,正好赶上我妻子的周年纪念礼物。 \
我想我的妻子非常喜欢它,她说不出话来。 \
到目前为止,我是唯一一个使用它的人,\
而且我每隔一天早上都会使用它来清除草坪上的树叶。\
它比其他吹叶机稍微贵一点,但我认为它的额外功能是值得的。
"""

review_template ="""
对于下面的文本,提取以下信息:

gift:该商品是作为礼物送给别人的吗? \
如果是,则回答 True;如果否或未知,则回答 False。

delivery_days:产品需要多少天到达? 如果没有找到该信息,则输出-1。

price_value:提取有关价值或价格的任何句子,\
并将它们输出为逗号分隔的 Python 列表。

输出包含下面的三个key的JSON格式:
gift
delivery_days
price_value

文本:{text}
"""

 这里我们提供了一段用户对商品的评语customer_review 和评语模板review_template,在review_template中我们要求LLM提取用户评语中的gift、delivery_days和price_value三部分信息,并以JSON格式输出。

from langchain.prompts import ChatPromptTemplate

prompt_template = ChatPromptTemplate.from_template(review_template)

messages = prompt_template.format_messages(text=customer_review)
chat = ChatOpenAI(temperature=0.0)
response = chat(messages)
print(response.content)

 从上面的输出结果中我们可以看到LLM输出了一个符合要求的JSON格式,不过这里需要说明的是response.content返回的其实都是字符串,也就是说LLM只能返回字符串,无法直接返回特定类型的数据,下面我们用访问python字典的方式来访问返回结果中的数据,我们会看到它会报错:

# You will get an error by running this line of code 
# because'gift' is not a dictionary
# 'gift' is a string
response.content.get('gift')

 

 这里报错的原因是string对象没有get属性。

将LLM输出字符串解析为Python字典

要解析输出结果中的格式化数据,我们需要定义ResponseSchema变量,这里我们需要解析3个变量gift、delivery_days和price_value,所以需要定义3个ResponseSchema,最后把它们打包在一起放在list中:

from langchain.output_parsers import ResponseSchema
from langchain.output_parsers import StructuredOutputParser

gift_schema = ResponseSchema(name="gift",
                             description="该商品是作为礼物送给别人的吗?\
                             如果是,则回答 True,如果否或未知,则回答 False。")

delivery_days_schema = ResponseSchema(name="delivery_days",
                                      description="产品需要多少天才能送达? \
                                                   如果没有找到该信息,则输出-1。")

price_value_schema = ResponseSchema(name="price_value",
                                    description="提取有关价值或价格的任何句子,\
                                    并将它们输出为逗号分隔的 Python 列表。")

response_schemas = [gift_schema, 
                    delivery_days_schema,
                    price_value_schema]

 接下来我们要定义一个解析器StructuredOutputParser。

output_parser = StructuredOutputParser.from_response_schemas(response_schemas)

 然后让该解析器给我们生成一个prompt,该prompt是一个格式化指令,它用来指导LLM产生格式化的输出结果:

format_instructions = output_parser.get_format_instructions()
print(format_instructions)

 接下来我们要定义一个新的review_template_2模板,在之前的review_template模板中我们明确要求LLM生成一个包含3个key的JSON格式的结果,而在下面定义的review_template_2模板中我们不再要求LLM生成一个JSON格式的结果:

review_template_2 ="""
对于下面的文本,提取以下信息:

gift:该商品是作为礼物送给别人的吗? \
如果是,则回答 True;如果否或未知,则回答 False。

delivery_days:产品需要多少天送达? \
如果没有找到该信息,则输出-1。

price_value:提取有关价值或价格的任何句子,\
并将它们输出为逗号分隔的 Python 列表。

文本:{text}

{format_instructions}
"""

在review_template_2中除了一个{text}变量以为,我们还增加了一个{format_instructions}变量,该变量为先前的输出解析器output_parser创建的prompt, 它的作用就是告诉LLM怎么提取text中的格式化数据:

prompt = ChatPromptTemplate.from_template(template=review_template_2)

messages = prompt.format_messages(text=customer_review, 
                                format_instructions=format_instructions)

print(messages[0].content)

 上面是我们将review_template_2、text,format_instructions三部分内容整合在一起的一个完整的prompt,下面我们让LLM读取这个完整的prompt,并查看返回结果:

response = chat(messages)
print(response.content)

 下面我们用输出解析器来解析这个结果,看看能否得到我们想要的字典格式:

output_dict = output_parser.parse(response.content)
output_dict

我们使用type命令来查看它的类型:

 总结

今天我们学习了如何使用langchain来创建prompt模板,并且langchain的prompt模板会自动识别prompt中的内嵌变量,在生成message时只需在prompt模板的format_messages方法中传递所需变量即可。另外我们还学习了如何通过Langchain来解析LLM的输出结果,通过创建ResponseSchema和StructuredOutputParser,可以产生用来指导LLM如何产生格式化数据的prompt即format_instructions ,LLM会根据format_instructions的要求自动生产格式化的输出结果,而无需我们告诉LLM该如何生成格式化的输出结果。

参考资料

DLAI - Learning Platform Beta

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/701983.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

iOS App的上架和版本更新流程

一、前言: 作为一名iOSDeveloper,把开发出来的App上传到App Store是必要的。下面就来详细讲解一下具体流程步骤。 二、准备: 一个已付费的开发者账号(账号类型分为个人(Individual)、公司(Com…

2023上半年软考系统分析师科目一整理-17

2023上半年软考系统分析师科目一整理-17 计算机系统的性能一般包括两个大的方面。一个方面是它的(),也就是计算机系统能正常工作的时间,其指标可以是能够持续工作的时间长度,也可以是在一段时间内,能正常工…

【域名详解】网络杂谈(13)之深入简出了解什么是域名

涉及知识点 什么是域名,域名的概念,域名的结构,域名地址的寻址过程,深入了解域名的寻址机制。 原创于:CSDN博主-《拄杖盲学轻声码》,更多内容可去其主页关注下哈,不胜感激 文章目录 涉及知识点…

【工作记录】基于CSS+JS可拖拽改变大小、可吸附到边界的DIV

记录一段实现可拖拽、可自动吸附到边界的代码。 <!DOCTYPE html> <html lang"en"> <head><style>body {overflow: hidden;}#pane {position: absolute;width: 45%;height: 45%;top: 20%;left: 20%;margin: 0;padding: 0;z-index: 99;border…

青岛大学_王卓老师【数据结构与算法】Week03_07_线性表的链式表示和实现7_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c;另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础–…

【Java项目】拉取公司GitLab项目的教程

文章目录 创建Git账号登录Git 创建Git账号 进入公司后&#xff0c;会拿到公司给你注册的邮箱以及密码&#xff0c;你得到用户名和密码之后&#xff0c;需要先创建一个拉取这个仓库对应的git账号。 我们先登录GitLab 当你登录GitLab之后&#xff0c;会显示你还没有ssh key&…

基于matlab使用基本形态运算符和 blob分析的组合从视频流中提取信息(附源码)

一、前言 此示例演示如何使用基本形态运算符和 blob 分析的组合从视频流中提取信息。在本例中&#xff0c;该示例计算每个视频帧中大肠杆菌的数量。请注意&#xff0c;细胞的亮度各不相同&#xff0c;这使得分割任务更具挑战性。 形态运算符是一种图像处理中常用的操作&#…

Linux系统部署BBR服务器加速软件

1. BBR加速软件介绍 BBR简介&#xff1a;   BBR是谷歌的黑科技&#xff0c;也可以理解为用来加速网络的软件&#xff0c;如果服务器在海外&#xff0c;会发现丢包率很高&#xff0c;线路还会时断时续。所以&#xff0c;不用点黑科技&#xff0c;肯定是没办法使用。而BBR加速能…

团体程序设计天梯赛-练习集L2篇⑨

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的普通人。 &#x1f3c0;个人主页&#xff1a;陈童学哦CSDN &#x1f4a1;所属专栏&#xff1a;PTA &#x1f381;希望各…

Redis 安装配置 常用命令

---------------------- 关系数据库与非关系型数据库 ---------------------------------------- ●关系型数据库&#xff1a; 关系型数据库是一个结构化的数据库&#xff0c;创建在关系模型&#xff08;二维表格模型&#xff09;基础上&#xff0c;一般面向于记录。 SQL 语句&…

Tomcat的安装部署

tomcat安装部署 tomcat安装部署 一、概述&#xff1a;1.tomcat介绍&#xff1a;2.tomcat核心组件&#xff1a;3.tomcat处理内部请求&#xff08;数据流向图&#xff09;4.tomcat服务部署&#xff1a; 二、虚拟主机配置&#xff1a;1.创建 chan 和 baek 项目目录和文件&#xf…

【C语言初阶(5)】循环练习题

文章目录 1. 计算 n 的阶乘2. 计算 1!2!3!……10!3. 使用二分查找法查找某数二分查找算法介绍代码实现 4. 演示字符移动5. 模拟用户登录场景 1. 计算 n 的阶乘 阶乘 某个数从 1 开始一直乘到这个数本身为止&#xff1b; 例如&#xff1a;3 的阶乘就是 1 * 2 * 3 6&#xff1b…

利用SpringBoot整合mybatis

代码地址&#xff1a;https://gitee.com/jkangle/springboot-exercise.git 1.构建SpringBoot项目 注意版本不能太高版本太高会出现问题整体的项目结构如图 2.导入Mybatis依赖 <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --><dependency>&l…

vim 对js文件和txt的操作不同

vim 对js文件和txt的操作不同 https://www.runoob.com/w3cnote/ascii.html 同样一段话&#xff0c;vim 123.txt 和 vim 123.js &#xff0c;将下面这些内容复制&#xff0c;然后粘贴&#xff0c; 显示的效果不一样 .js文件 会把 0D 0A 变换为 0A 09 import { request } from…

图像去模糊:RSBlur 数据集以及模糊图像合成方法

本内容主要介绍图像去模糊数据集 RSBlur&#xff0c;以及逼真模糊图像合成方法。 论文&#xff1a;Realistic Blur Synthesis for Learning Image Deblurring 代码&#xff08;官方&#xff09;&#xff1a;https://github.com/rimchang/RSBlur 1.1 背景 运动模糊是由曝光…

89C52RC普中单片机-4

20230629 Thusday lcd1602代码 lcd1602.c #include <REGX52.H>//引脚配置&#xff1a; sbit LCD_RSP2^6; sbit LCD_RWP2^5; sbit LCD_ENP2^7; #define LCD_DataPort P0//函数定义&#xff1a; /*** brief LCD1602延时函数&#xff0c;12MHz调用可延时1ms* param 无*…

UNet Pytorch实现

用于图像分割的不同种类的Unet模型的实现 UNet - U-Net&#xff1a; 用于生物医学图像分割的卷积网络 https://arxiv.org/abs/1505.04597RCNN-UNet - 基于U-Net的递归残差卷积神经网络&#xff08;R2U-Net&#xff09;用于医学图像分割 https://arxiv.org/abs/1802.06955Atten…

ROS学习总结(一)

渐渐开始接触项目了&#xff0c;准备把以前学习的ros做一些总结&#xff0c;以致孰能生巧。 ros分布框架学习 vscode使用ros节点和包 vscode使用 下载&#xff1a;https://code.visualstudio.com/ 安装&#xff1a;sudo dpkg -i code(tap补全) code 能快捷启动。 插件安装&am…

django.db.utils.OperationalError: no such table: onlyoffice_customuser

我写了个类 Curstomuser 重新运行命令&#xff1a; >python manage.py makemigrations就报错了&#xff1a; 我以为是自己设计的类有问题&#xff0c;结果发现是因为我在其它 py 文件中进行了数据库查询。 而 Django 架构让我忽略了代码运行的前后关系。。。 先注释掉其它…

【STM32】keil MDK-Arm 5.38 功能详解

一、基本概念二、软件安装三、软件介绍3.1 Intro3.2 keil菜单栏3.21 file选项3.22 Edit 选项3.23 View选项3.24 Project选项3.25 Flash选项3.26 Debug选项3.27 Peripherals选项3.28 Tools选项3.29 SVCS选项3.2.10 Window选项3.2.11 Help选项 3.3 keil工具栏 四、设置与项目设置…