LangChain学习记录

资料来自【极客时间出品】 LangChain实战课LangChain 实战课 - 掘金小册 - 掘金小册

什么是LangChain?

LangChain是一个基于大语言模型(LLMs)用于构建端到端语言模型应用的框架。

作用:通过API调用如 ChatGPT、GPT-4、Llama 2 等大型语言模型,还可以实现更高级的功能。

具备两个特性:1、数据感知2、具有代表性

LangChain组成:6 大组件

  • 模型(Models) ,包含各大语言模型的LangChain接口和调用细节,以及输出解析机制。
  • 提示模板(Prompts) ,使提示工程流线化,进一步激发大语言模型的潜力。
  • 数据检索(Indexes) ,构建并操作文档的方法,接受用户的查询并返回最相关的文档,轻松搭建本地知识库。
  • 记忆(Memory) ,通过短时记忆和长时记忆,在对话过程中存储和检索数据,让ChatBot记住你是谁。
  • 链(Chains) ,是LangChain中的核心机制,以特定方式封装各种功能,并通过一系列的组合,自动而灵活地完成常见用例。
  • 代理(Agents) ,是另一个LangChain中的核心机制,通过“代理”让大模型自主调用外部工具和内部工具,使强大的“智能化”自主Agent成为可能!你的 App 将产生自驱力!

案例:海报文案生成器

代码主要包含三个部分:

  1. 初始化图像字幕生成模型(HuggingFace中的image-caption模型)。
  2. 定义LangChain图像字幕生成工具。
  3. 初始化并运行LangChain Agent(代理),这个Agent是OpenAI的大语言模型,会自动进行分析,调用工具,完成任务。

思路

这里对图像的处理是通过HuggingFace中的image-caption模型实现的,那么LLM发挥的作用即为针对给出的文字描述再输出相应结果。

了解大模型api

要使用OpenAI API,需要先用科学的方法进行注册,得到一个API Key。

有了OpenAI的账号和Key,你就可以在面板中看到各种信息,比如模型的费用、使用情况等。下面的图片显示了各种模型的访问数量限制信息。其中,TPM和RPM分别代表tokens-per-minute、requests-per-minute。也就是说,对于GPT-4,你通过API最多每分钟调用200次、传输40000个字节。

这里,我们需要重点说明的两类模型,就是图中的Chat Model和Text Model。这两类Model,是大语言模型的代表。当然,OpenAI还提供Image、Audio和其它类型的模型,目前它们不是LangChain所支持的重点,模型数量也比较少。

Chat模型和Text模型

  • Chat Model,聊天模型,用于产生人类和AI之间的对话,代表模型当然是gpt-3.5-turbo(也就是ChatGPT)和GPT-4。当然,OpenAI还提供其它的版本,gpt-3.5-turbo-0613代表ChatGPT在2023年6月13号的一个快照,而gpt-3.5-turbo-16k则代表这个模型可以接收16K长度的Token,而不是通常的4K。(注意了,gpt-3.5-turbo-16k并未开放给我们使用,而且你传输的字节越多,花钱也越多)
  • Text Model,文本模型,在ChatGPT出来之前,大家都使用这种模型的API来调用GPT-3,文本模型的代表作是text-davinci-003(基于GPT3)。而在这个模型家族中,也有专门训练出来做文本嵌入的text-embedding-ada-002,也有专门做相似度比较的模型,如text-similarity-curie-001。

上面这两种模型,提供的功能类似,都是接收对话输入(input,也叫prompt),返回回答文本(output,也叫response)。但是,它们的调用方式和要求的输入格式是有区别的,这个我们等下还会进一步说明。

下面我们用简单的代码段说明上述两种模型的调用方式。先看比较原始的Text模型(GPT3.5之前的版本)。

调用 Text 模型

第1步,先注册好你的API Key。

第2步,用 pip install openai 命令来安装OpenAI库。

第3步,导入 OpenAI API Key。

导入API Key有多种方式,其中之一是通过下面的代码:

import os os.environ["OPENAI_API_KEY"] = '你的Open API Key'

OpenAI库就会查看名为OPENAI_API_KEY的环境变量,并使用它的值作为API密钥。

也可以像下面这样先导入OpenAI库,然后指定api_key的值。

import openai openai.api_key = '你的Open API Key'

当然,这种把Key直接放在代码里面的方法最不可取,因为你一不小心共享了代码,密钥就被别人看到了,他就可以使用你的GPT-4资源!所以,建议你给自己的OpenAI账户设个上限,比如每月10美元啥的。

所以更好的方法是在操作系统中定义环境变量,比如在Linux系统的命令行中使用:

export OPENAI_API_KEY='你的Open API Key'

或者,你也可以考虑把环境变量保存在.env文件中,使用python-dotenv库从文件中读取它,这样也可以降低API密钥暴露在代码中的风险。

第4步,导入OpenAI库,并创建一个Client。

from openai import OpenAI client = OpenAI()

第5步,指定 gpt-3.5-turbo-instruct(也就是 Text 模型)并调用 completions 方法,返回结果。

response = client.completions.create( model="gpt-3.5-turbo-instruct", temperature=0.5, max_tokens=100, prompt="请给我的花店起个名")

在使用OpenAI的文本生成模型时,你可以通过一些参数来控制输出的内容和样式。这里以下是一些常见的参数。

第6步,打印输出大模型返回的文字。

print(response.choices[0].text.strip())

当你调用OpenAI的Completion.create方法时,它会返回一个响应对象,该对象包含了模型生成的输出和其他一些信息。这个响应对象是一个字典结构,包含了多个字段。

在使用Text模型(如text-davinci-003)的情况下,响应对象的主要字段包括:

choices字段是一个列表,因为在某些情况下,你可以要求模型生成多个可能的输出。每个选择都是一个字典,其中包含以下字段:

  • text:模型生成的文本。
  • finish_reason:模型停止生成的原因,可能的值包括 stop(遇到了停止标记)、length(达到了最大长度)或 temperature(根据设定的温度参数决定停止)。

所以,response.choices[0].text.strip() 这行代码的含义是:从响应中获取第一个(如果在调用大模型时,没有指定n参数,那么就只有唯一的一个响应)选择,然后获取该选择的文本,并移除其前后的空白字符。这通常是你想要的模型的输出。

至此,任务完成,模型的输出如下:

心动花庄、芳华花楼、轩辕花舍、簇烂花街、满园春

调用 Chat 模型

整体流程上,Chat模型和Text模型的调用是类似的,只是前面加了一个chat,然后输入(prompt)和输出(response)的数据格式有所不同。

示例代码如下:

response = client.chat.completions.create( model="gpt-4", messages=[ {"role": "system", "content": "You are a creative AI."}, {"role": "user", "content": "请给我的花店起个名"}, ], temperature=0.8, max_tokens=60 )

这段代码中,除去刚才已经介绍过的temperature、max_tokens等参数之外,有两个专属于Chat模型的概念,一个是消息,一个是角色!

先说消息,消息就是传入模型的提示。此处的messages参数是一个列表,包含了多个消息。每个消息都有一个role(可以是system、user或assistant)和content(消息的内容)。系统消息设定了对话的背景(你是一个很棒的智能助手),然后用户消息提出了具体请求(请给我的花店起个名)。模型的任务是基于这些消息来生成回复。

再说角色,在OpenAI的Chat模型中,system、user和assistant都是消息的角色。每一种角色都有不同的含义和作用。

  • system:系统消息主要用于设定对话的背景或上下文。这可以帮助模型理解它在对话中的角色和任务。例如,你可以通过系统消息来设定一个场景,让模型知道它是在扮演一个医生、律师或者一个知识丰富的AI助手。系统消息通常在对话开始时给出。
  • user:用户消息是从用户或人类角色发出的。它们通常包含了用户想要模型回答或完成的请求。用户消息可以是一个问题、一段话,或者任何其他用户希望模型响应的内容。
  • assistant:助手消息是模型的回复。例如,在你使用API发送多轮对话中新的对话请求时,可以通过助手消息提供先前对话的上下文。然而,请注意在对话的最后一条消息应始终为用户消息,因为模型总是要回应最后这条用户消息。

在使用Chat模型生成内容后,返回的响应,也就是response会包含一个或多个choices,每个choices都包含一个message。每个message也都包含一个role和content。role可以是system、user或assistant,表示该消息的发送者,content则包含了消息的实际内容。

一个典型的response对象可能如下所示:

 {  'id': 'chatcmpl-2nZI6v1cW9E3Jg4w2Xtoql0M3XHfH',  'object': 'chat.completion',  'created': 1677649420,  'model': 'gpt-4',  'usage': {'prompt_tokens': 56, 'completion_tokens': 31, 'total_tokens': 87},  'choices': [    {     'message': {       'role': 'assistant',       'content': '你的花店可以叫做"花香四溢"。'      },     'finish_reason': 'stop',     'index': 0    }   ] }

以下是各个字段的含义:

这就是response的基本结构,其实它和Text模型返回的响应结构也是很相似,只是choices字段中的Text换成了Message。你可以通过解析这个对象来获取你需要的信息。例如,要获取模型的回复,可使用 response['choices'][0]['message']['content']。

Chat模型 vs Text模型

Chat模型和Text模型都有各自的优点,其适用性取决于具体的应用场景。

相较于Text模型,Chat模型的设计更适合处理对话或者多轮次交互的情况。这是因为它可以接受一个消息列表作为输入,而不仅仅是一个字符串。这个消息列表可以包含system、user和assistant的历史信息,从而在处理交互式对话时提供更多的上下文信息。

这种设计的主要优点包括:

  1. 对话历史的管理:通过使用Chat模型,你可以更方便地管理对话的历史,并在需要时向模型提供这些历史信息。例如,你可以将过去的用户输入和模型的回复都包含在消息列表中,这样模型在生成新的回复时就可以考虑到这些历史信息。
  2. 角色模拟:通过system角色,你可以设定对话的背景,给模型提供额外的指导信息,从而更好地控制输出的结果。当然在Text模型中,你在提示中也可以为AI设定角色,作为输入的一部分。

然而,对于简单的单轮文本生成任务,使用Text模型可能会更简单、更直接。例如,如果你只需要模型根据一个简单的提示生成一段文本,那么Text模型可能更适合。从上面的结果看,Chat模型给我们输出的文本更完善,是一句完整的话,而Text模型输出的是几个名字。这是因为ChatGPT经过了对齐(基于人类反馈的强化学习),输出的答案更像是真实聊天场景。

好了,我们对OpenAI的API调用,理解到这个程度就可以了。毕竟我们主要是通过LangChain这个高级封装的框架来访问Open AI。

通过 LangChain 调用 Text 和 Chat 模型

调用 Text 模型代码如下:

import os os.environ["OPENAI_API_KEY"] = '你的Open API Key' from langchain.llms import OpenAI llm = OpenAI(       model="gpt-3.5-turbo-instruct",     temperature=0.8,     max_tokens=60,) response = llm.predict("请给我的花店起个名") print(response)

输出:

花之缘、芳华花店、花语心意、花风旖旎、芳草世界、芳色年华

这只是一个对OpenAI API的简单封装:先导入LangChain的OpenAI类,创建一个LLM(大语言模型)对象,指定使用的模型和一些生成参数。使用创建的LLM对象和消息列表调用OpenAI类的__call__方法,进行文本生成。生成的结果被存储在response变量中。没有什么需要特别解释之处。

调用 Chat 模型代码如下:
 import os os.environ["OPENAI_API_KEY"] = '你的Open API Key' from langchain.chat_models import ChatOpenAI chat = ChatOpenAI(model="gpt-4",                     temperature=0.8,                     max_tokens=60) from langchain.schema import (     HumanMessage,     SystemMessage ) messages = [     SystemMessage(content="你是一个很棒的智能助手"),     HumanMessage(content="请给我的花店起个名") ] response = chat(messages) print(response) 

这段代码也不难理解,主要是通过导入LangChain的ChatOpenAI类,创建一个Chat模型对象,指定使用的模型和一些生成参数。然后从LangChain的schema模块中导入LangChain的SystemMessage和HumanMessage类,创建一个消息列表。消息列表中包含了一个系统消息和一个人类消息。你已经知道系统消息通常用来设置一些上下文或者指导AI的行为,人类消息则是要求AI回应的内容。之后,使用创建的chat对象和消息列表调用ChatOpenAI类的__call__方法,进行文本生成。生成的结果被存储在response变量中。

输出:

 content='当然可以,叫做"花语秘境"怎么样?' additional_kwargs={} example=False 

从响应内容“当然可以,叫做‘花语秘境’怎么样? ”不难看出,GPT-4的创造力真的是胜过GPT-3,她给了我们这么有意境的一个店名,比我自己起的“易速鲜花”好多了。

另外,无论是langchain.llms中的OpenAI(Text模型),还是langchain.chat_models中的ChatOpenAI中的ChatOpenAI(Chat模型),其返回的结果response变量的结构,都比直接调用OpenAI API来得简单一些。这是因为,LangChain已经对大语言模型的output进行了解析,只保留了响应中最重要的文字部分。

总结时刻

课程的内容有OpenAI从Text模型到Chat模型的进化,以及什么时候会选用Chat模型,什么时候会选用Text模型,另外就是这两种模型的最基本调用流程。

另外,大语言模型可不是OpenAI一家独大,知名的大模型开源社群HugginFace网站上面提供了很多开源模型供尝试使用。现在,Meta的Llama-2最受热捧,而且通义千问(Qwen)则刚刚开源。

两点提醒,一是这个领域进展太快,当你学这门课程的时候,流行的开源模型肯定变成别的了;二是这些新的开源模型,LangChain还不一定提供很好的接口,因此通过LangChain来使用最新的开源模型可能不容易。

不过LangChain作为最流行的LLM框架,新的开源模型被封装进来是迟早的事情。而且,LangChain的框架也已经定型,各个组件的设计都基本固定了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值