LangChain初学者指南

LLM可以帮助我们将AI能力接入应用,LangChain作为开源工具,提供了接入各种主流LLM的接口,从而让我们以非常低的成本构建基于LLM的AI应用。原文: Getting Started with LangChain: A Beginner’s Guide to Building LLM-Powered Applications

LangChain初学者指南_第1张图片

自从ChatGPT发布以来,大语言模型(LLM)得到极大普及。虽然大多数人没有足够资金和计算资源从头开始训练LLM,但仍然可以基于预训练的LLM来构建一些很酷的东西,例如:

  • 可以根据个人数据与外界互动的 个人助理 [1]
  • 为特定目的定制的 聊天机器人 [2]
  • 对文档或 代码 [3]进行 分析 [4]总结 [5]

LLM正在改变构建人工智能产品的方式

凭借其奇怪的API和提示工程,LLM正在改变我们构建人工智能产品的方式。这就是为什么出现大量冠以"LLMOps[6]"名义的新开发工具的原因。

其中一个新工具就是LangChain。

什么是LangChain?

LangChain是一个帮助我们轻松构建LLM驱动的应用程序的框架,提供以下功能:

  • 各种不同基础模型的通用接口
  • 帮助管理提示的框架,以及
  • 连接长期内存、外部数据、其他LLM,以及LLM无法处理的任务(例如,计算或搜索)的其他代理的中心化接口。

LangChain是由Harrison Chase创建的开源项目。

因为LangChain有很多不同功能,所以从头开始理解其功能可能会很有挑战性。这就是为什么我们将在本文中介绍LangChain(目前)的六个关键模块,从而帮助读者更好理解它的功能。

前提条件

要继续学习本教程,需要安装langchain Python包并准备好使用所有相关API的密钥。

安装LangChain

在安装langchain包之前,请确保Python版本≥3.8.1且<4.0。

可以通过pip安装langchain包。

pip install langchain

本文使用0.0.147版本,由于LangChainb的GitHub非常活跃,因此请确保安装当前版本。

完成所有设置后,导入langchain Python包。

import langchain
API密钥

基于LLM构建应用需要使用某些服务的API密钥,有些API是收费的。

LLM服务商(必需的) - 首先需要LLM服务商的API密钥。我们目前正在经历"人工智能的Linux时刻[7]",开发人员必须在专有或开源基础模型之间做出选择,而这主要基于性能和成本的权衡。

LangChain初学者指南_第2张图片 LLM服务商: 专有和开源基础模型

专有模型是由拥有大型专家团队和大量AI预算的公司拥有的闭源基础模型,通常比开源模型大,因此具有更好的性能,但API开销也更昂贵。专有模型服务商有OpenAI、co:here、AI21 Labs或Anthropic。

大多数LangChain教程都使用OpenAI,但请注意,OpenAI API(用于实验目的并不太贵)不是免费的[8]。要获得OpenAI API Key,需要创建OpenAI帐户,然后在API keys[9]下单击"Create new secret Key"。

import os
os.environ["OPENAI_API_KEY"] = ... # 设置API_TOKEN

开源模型通常比专有模型更小,功能更少,但比专有模型更具成本效益。开源模型有:

  • BigScience的[BLOOM]https://huggingface.co/bigscience/bloom)
  • Meta AI的 LLaMA
  • Google的 Flan-T5
  • Eleuther AI的 GPT-J

许多开源模型被组织和托管在Hugging Face上,要获得Hugging Face API密钥,需要开通Hugging Face帐户并在Access Tokens[10]下创建"New token"。

import os

os.environ["HUGGINGFACEHUB_API_TOKEN"] = ... # 设置API_TOKEN

可以免费使用Hugging Face的开源LLM,但仅限于性能较差的小型LLM。


个人提示 —— 实话实话,我们当然可以尝试开源模型。我试图在本文里只使用托管在Hugging Face上的开源模型,并提供常规帐户(google/flan-t5-xl和sentence-transformers/all-MiniLM-L6-v2)。大多数示例都没问题,但某些示例实在无法工作。最后,我只能在OpenAI上设置了一个付费帐户,因为大多数LangChain示例似乎都针对OpenAI的API进行了优化。总的来说,为本教程运行几个实验花费了大约1美元。


矢量数据库(可选) —— 如果你想使用某个特定的矢量数据库,如Pinecone, Weaviate,或Milvus,需要注册相应系统以获得API密钥并查看其定价。在本教程中,我们使用Faiss,不需要注册。

工具(可选) —— 取决于你希望LLM与之交互的工具[11],如OpenWeatherMap或SerpAPI,可能需要注册以获得API密钥并查看其定价。在本教程中,我们只使用不需要API密钥的工具。

能用LangChain做什么?

该包为许多基础模型提供了通用接口,支持提示管理,并充当其他组件(如提示模板、其他LLM、外部数据和通过代理的其他工具)的中心化接口。

在撰写本文时,LangChain(版本0.0.147)涵盖了六个模块:

  • 模型(Models): 从不同LLM和嵌入模型中选择
  • 提示(Prompts): 管理LLM输入
  • 链接(Chains): 将LLM与其他组件相结合
  • 索引(Indexes): 访问外部数据
  • 存储(Memory): 记住以前的对话
  • 代理(Agents): 访问其他工具

下面几节中的代码示例是从LangChain文档[12]中复制和修改的。

模型(Models): 从不同LLM和嵌入模型中选择

目前,许多不同的LLM正在兴起。LangChain提供了对各种模型的集成和简化界面。

LangChain区分了三种输入和输出不同的模型:

  • LLM接受字符串作为输入(提示)并输出字符串(补全)。
# 专有LLM,例如OpenAI
# pip install openai
from langchain.llms import OpenAI
llm = OpenAI(model_name="text-davinci-003")

# 或者使用托管在Hugging Face上的开源LLM
# pip install huggingface_hub
from langchain import HuggingFaceHub
llm = HuggingFaceHub(repo_id = "google/flan-t5-xl")

# LLM以提示词作为输入并输出补全
prompt = "Alice has a parrot. What animal is Alice's pet?"
completion = llm(prompt)
LangChain初学者指南_第3张图片 LLM模型
  • 聊天模型类似于LLM,将聊天消息列表作为输入并返回聊天消息。
  • 文本嵌入模型接受文本输入并返回浮点数(嵌入)列表,浮点数是输入文本的数字表示形式。嵌入有助于从文本中提取信息,这些信息可以稍后使用,例如,用于计算文本之间的相似性(例如,电影摘要)。
# 专有文本嵌入模型,例如OpenAI
# pip install tiktoken
from langchain.embeddings import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()

# 或者使用托管在Hugging Face上的开源文本嵌入模型
# pip install sentence_transformers
from langchain.embeddings import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(model_name = "sentence-transformers/all-MiniLM-L6-v2")

# 文本嵌入模型以文本作为输入,输出浮点数列表
text = "Alice has a parrot. What animal is Alice's pet?"
text_embedding = embeddings.embed_query(text)
LangChain初学者指南_第4张图片 文本嵌入模型
提示(Prompts): 管理LLM输入

LLM的API很奇怪,虽然用自然语言向LLM输入提示感觉很直观,但需要对提示进行相当多的调整,直到从LLM获得所需输出。这个过程被称为提示工程

有了好的提示后,可能希望将其用作其他用途的模板。因此,LangChain提供了所谓的PromptTemplates,帮助我们从多个组件构造提示。

from langchain import PromptTemplate

template = "What is a good name for a company that makes {product}?"

prompt = PromptTemplate(
    input_variables=["product"],
    template=template,
)

prompt.format(product="colorful socks")

上面的提示可以看作是一个零样本问题设置(zero-shot problem setting) ,我们希望LLM在足够的相关数据上进行了训练,以提供令人满意的响应。

改进LLM输出的另一个技巧是在提示中添加一些示例,使其成为多样本问题设置(few-shot problem setting)

from langchain import PromptTemplate, FewShotPromptTemplate

examples = [
    {"word""happy""antonym""sad"},
    {"word""tall""antonym""short"},
]

example_template = """
Word: {word}
Antonym: {antonym}\n
"""


example_prompt = PromptTemplate(
    input_variables=["word""antonym"],
    template=example_template,
)

few_shot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    prefix="Give the antonym of every input",
    suffix="Word: {input}\nAntonym:",
    input_variables=["input"],
    example_separator="\n",
)

few_shot_prompt.format(input="big")

以上代码将生成一个提示模板,并根据提供的示例和输入组成以下提示:

Give the antonym of every input

Word: happy
Antonym: sad

Word: tall
Antonym: short

Word: big
Antonym:
链接(Chains): 将LLM与其他组件相结合

LangChain中的链接简单描述了将LLM与其他组件组合在一起创建应用的过程。例如:

  • 结合LLM和提示模板(参见本节)
  • 通过将第一个LLM的输出作为第二个LLM的输入,顺序组合多个LLM(参见本节)
  • 将LLM与外部数据相结合,例如用于问答(参见索引章节)
  • 将LLM与长期存储相结合,例如用于聊天记录(参见存储章节)

前一节创建了一个提示模板,当我们想在LLM中使用时,可以使用LLMChain,如下所示:

from langchain.chains import LLMChain

chain = LLMChain(llm = llm, 
                  prompt = prompt)

# 通过输入特定参数执行该链
chain.run("colorful socks")

如果我们想使用第一个LLM的输出作为第二个LLM的输入,可以使用SimpleSequentialChain:

from langchain.chains import LLMChain, SimpleSequentialChain

# 像前面的代码示例一样定义第一个链
# ...

# 基于提示词模板和LLM创建第二个链
second_prompt = PromptTemplate(
    input_variables=["company_name"],
    template="Write a catchphrase for the following company: {company_name}",
)

chain_two = LLMChain(llm=llm, prompt=second_prompt)

# 结合第一和第二链
overall_chain = SimpleSequentialChain(chains=[chain, chain_two], verbose=True)

# 只指定第一个链的输入并运行该链。
catchphrase = overall_chain.run("colorful socks")
LangChain初学者指南_第5张图片 在LangChain中使用PromptTemplates和LLM的SimpleSequentialChain输出
索引(Indexes): 访问外部数据

LLM的一个限制是缺乏上下文信息(例如访问特定文档或电子邮件),可以通过允许LLM访问特定外部数据来解决这个问题。

为此,首先需要使用文档加载器加载外部数据。LangChain为不同类型文档提供了各种加载器,从pdf和电子邮件到网站和YouTube视频不等。

我们从YouTube视频中加载一些外部数据。如果你想加载大型文本文档并使用Text Splitter来拆分,可以参考官方文档[13]

# pip install youtube-transcript-api
# pip install pytube

from langchain.document_loaders import YoutubeLoader

loader = YoutubeLoader.from_youtube_url("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
    
documents = loader.load()

现在已经准备好了外部数据作为documents,可以使用矢量数据库(VectorStore) 中的文本嵌入模型对其进行索引。流行的矢量数据库包括Pinecone、Weaviate和Milvus。本文使用Faiss,因为它不需要API密钥。

# pip install faiss-cpu
from langchain.vectorstores import FAISS

# 创建矢量数据库作为索引
db = FAISS.from_documents(documents, embeddings)

文档(在本例中是视频)现在作为嵌入存储在矢量存储中。

现在可以用这些外部数据做很多事情,我们来做一个带有信息检索器的问答任务:

from langchain.chains import RetrievalQA

retriever = db.as_retriever()

qa = RetrievalQA.from_chain_type(
    llm=llm, 
    chain_type="stuff"
    retriever=retriever, 
    return_source_documents=True)

query = "What am I never going to do?"
result = qa({"query": query})

print(result['result'])
RetrievalQA的输出 RetrievalQA的输出

等等,你是不是被忽悠了?是的,确实是。

存储(Memory): 记住以前的对话

对于像聊天机器人这样的应用来说,能够记住以前的对话至关重要。但默认情况下LLM没有任何长期记忆,除非显式输入聊天记录。

LangChain初学者指南_第6张图片 聊天有没有会话记忆的比较

LangChain通过提供几个不同的选项来处理聊天记录,从而解决了这个问题:

  • 保留所有对话,
  • 保留最新的k次对话,
  • 总结对话内容。

本例将使用ConversationChain为应用提供会话存储。

from langchain import ConversationChain

conversation = ConversationChain(llm=llm, verbose=True)

conversation.predict(input="Alice has a parrot.")

conversation.predict(input="Bob has two cats.")

conversation.predict(input="How many pets do Alice and Bob have?")

这会输出上图中右边的对话。如果没有ConversationChain来保存会话记录,那么会话将看起来像上图中左侧的对话。

代理(Agents): 访问其他工具

LLM有强大的能力,但也有很多限制:缺乏上下文信息(例如训练数据没有覆盖的特定领域知识),信息会快速过时(例如GPT-4是基于2021年9月份之前的数据训练的),以及不擅长数学。

LangChain初学者指南_第7张图片

因为LLM可能会对自己无法完成的任务产生幻觉,所以需要使用辅助工具,例如搜索(例如,Google搜索[14])、计算器(例如,Python REPL[15]Wolfram Alpha[16])和查找(例如,Wikipedia[17])。

此外,需要代理根据LLM的输出决定使用哪些工具来完成任务。

请注意,某些LLM(如google/flan-t5-xl)不适合以下示例,因为它们不遵循对话-反应-描述模板,这就是我在OpenAI上建立付费账户并切换到OpenAI API的原因。

在下面的示例中,代理首先在维基百科上查找巴拉克·奥巴马的出生日期,然后用计算器计算出他在2022年的年龄。

# pip install wikipedia
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType

tools = load_tools(["wikipedia""llm-math"], llm=llm)
agent = initialize_agent(tools, 
                         llm, 
                         agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, 
                         verbose=True)


agent.run("When was Barack Obama born? How old was he in 2022?")
LangChain初学者指南_第8张图片 LLM代理输出
总结

就在几个月前,我们所有人(或者至少大多数人)都对ChatGPT的功能印象深刻。现在,像LangChain这样的新开发工具使我们能够在几个小时内在笔记本电脑上构建类似的令人印象深刻的原型,这是真正令人兴奋的时刻!

LangChain是一个开源Python库,可以让任何会写代码的人构建LLM驱动的应用程序。该包为许多基础模型提供了通用接口,支持提示管理,并充当其他组件(如提示模板、其他LLM、外部数据以及支持代理的其他工具)的中心化接口。

该库提供了比本文提到的更多特性。以目前的发展速度,这篇文章也可能会很快过时。

在撰写本文时,我注意到库和文档都围绕OpenAI的API。虽然许多例子都使用开源模型google/flan-t5-xl,但我还是切换到了OpenAI API。尽管不是免费的,但本文中的OpenAI API实验只花了大约1美元。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

参考资料

[1]

LangChain Use Case: Personal Assistants: https://python.langchain.com/en/latest/use_cases/personal_assistants.html

[2]

LangChain Use Case: Chatbots: https://python.langchain.com/en/latest/use_cases/chatbots.html

[3]

LangChain Use Case: Code: https://python.langchain.com/en/latest/use_cases/code.html

[4]

LangChain Use Case: Question Answering: https://python.langchain.com/en/latest/use_cases/question_answering.html

[5]

LangChain Use Case: Summarization: https://python.langchain.com/en/latest/use_cases/summarization.html

[6]

Understanding LLMOps: Large Language Model Operations: https://wandb.ai/iamleonie/Articles/reports/Understanding-LLMOps-Large-Language-Model-Operations--Vmlldzo0MDgyMDc2

[7]

AI's Linux moment: https://hazyresearch.stanford.edu/blog/2023-01-30-ai-linux

[8]

OpenAI Pricing: https://openai.com/pricing

[9]

OpenAI API Keys: https://platform.openai.com/account/api-keys

[10]

Hugging Face Tokens: https://huggingface.co/settings/tokens

[11]

LangChain Agents Tools: https://python.langchain.com/en/latest/modules/agents/tools.html

[12]

LangChain Documentation: https://python.langchain.com/en/latest/index.html

[13]

LangChain Documentation: Indexes: https://python.langchain.com/en/latest/modules/indexes/getting_started.html

[14]

LangChang Agents: Google Search: https://python.langchain.com/en/latest/modules/agents/tools/examples/google_search.html

[15]

LangChain Agents: Python REPL: https://python.langchain.com/en/latest/modules/agents/tools/examples/python.html

[16]

LangChain Agents: Wolfram Alpha: https://python.langchain.com/en/latest/modules/agents/tools/examples/wolfram_alpha.html

[17]

LangChain Agents: Wikipedia: https://python.langchain.com/en/latest/modules/agents/tools/examples/wikipedia.html

- END -

本文由 mdnice 多平台发布

你可能感兴趣的:(程序人生)