快速入门
在这个快速入门中,我们将向您展示如何:
- 设置 LangChain、LangSmith 和 LangServe
- 使用 LangChain 的最基本和常见的组件:提示模板、模型和输出解析器
- 使用 LangChain 表达语言,这是 LangChain 构建的协议,也是组件链接的基础
- 使用 LangChain 构建一个简单的应用程序
- 使用 LangSmith 跟踪您的应用程序
- 使用 LangServe 为您的应用程序提供服务
要涵盖的内容很多!让我们开始吧。
设置
Jupyter Notebook
本指南(以及文档中的大多数其他指南)使用 Jupyter 笔记本 (opens in a new tab),并假定读者也在使用。Jupyter 笔记本非常适合学习如何使用 LLM 系统,因为往往会出现一些问题(意外输出、API 宕机等),通过在交互环境中进行指南可以更好地理解它们。
您不需要在 Jupyter 笔记本中进行指南,但建议这样做。有关如何安装的说明,请参阅 这里 (opens in a new tab)。
安装
要安装 LangChain,请运行:
pip install langchain详细信息请参阅我们的 安装指南。
LangSmith
您使用 LangChain 构建的许多应用程序将包含多个步骤,其中使用 LLM 调用的多个调用。 随着这些应用程序变得越来越复杂,能够检查链或代理内部发生的情况变得至关重要。 最好的方法是使用 LangSmith (opens in a new tab)。
请注意,LangSmith 并非必需,但非常有用。 如果您确实想使用 LangSmith,请在上面的链接上注册后,确保设置环境变量以开始记录跟踪:
export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="..."使用 LangChain 构建
LangChain 使其能够将外部数据源和计算与 LLM 连接起来。 在这个快速入门中,我们将介绍一些不同的方法来实现这一点。 我们将从一个简单的 LLM 链开始,它只依赖于提示模板中的信息来回复。 接下来,我们将构建一个检索链,该链从单独的数据库获取数据并将其传递到提示模板中。 然后,我们将添加聊天记录,以创建一个对话检索链。这使您可以以聊天方式与此 LLM 进行交互,因此它会记住以前的问题。 最后,我们将构建一个代理,该代理利用 LLM 来确定是否需要获取数据来回答问题。 我们将简要介绍这些内容,但是所有这些都有很多细节!我们会链接到相关的文档。
LLM Chain
我们将展示如何使用 API 提供的模型,如 OpenAI,以及使用 Ollama 等集成的本地开源模型。
首先,我们需要导入 LangChain x OpenAI 集成包。
pip install langchain-openai访问 API 需要一个 API 密钥,您可以通过创建帐户并前往 这里 (opens in a new tab) 获取。一旦我们有了密钥,我们将通过运行以下命令将其设置为环境变量:
export OPENAI_API_KEY="..."然后可以初始化模型:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI()如果您不想设置环境变量,可以在初始化 OpenAI LLM 类时直接通过 api_key 命名参数传入密钥:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(api_key="...")一旦您安装并初始化了所选的 LLM,我们就可以尝试使用它! 让我们问它 LangSmith 是什么——这是训练数据中不存在的内容,所以它不应该给出很好的回答。
llm.invoke("how can langsmith help with testing?")我们还可以用提示模板引导其响应。 提示模板将原始用户输入转换为对 LLM 更好的输入。
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "You are a world class technical documentation writer."),
("user", "{input}")
])现在我们可以将这些组合成一个简单的 LLM 链:
chain = prompt | llm 我们现在可以调用它并提出同样的问题。它仍然不知道答案,但它应该以更适合技术文档写作者的语调来回答!
chain.invoke({"input": "how can langsmith help with testing?"})ChatModel(因此也包括这个链)的输出是一条消息。然而,使用字符串通常要方便得多。让我们添加一个简单的输出解析器,将聊天消息转换为字符串。
from langchain_core.output_parsers import StrOutputParser
output_parser = StrOutputParser()现在我们可以将其添加到之前的链中:
chain = prompt | llm | output_parser我们现在可以调用它并提出同样的问题。答案现在将是一个字符串(而不是 ChatMessage)。
chain.invoke({"input": "how can langsmith help with testing?"})深入了解
我们现在已经成功设置了一个基本的 LLM 链。我们只涉及了提示、模型和输出解析器的基础知识——要深入了解这里提到的所有内容,请查看 文档的这一部分。
检索链
为了正确回答最初的问题("how can langsmith help with testing?"),我们需要向 LLM 提供额外的上下文。 我们可以通过 检索 来做到这一点。 当您有 太多数据 无法直接传递给 LLM 时,检索非常有用。 然后,您可以使用检索器仅获取最相关的部分并将其传入。
在这个过程中,我们将从 检索器 查找相关文档,然后将它们传入提示。 检索器可以基于任何东西——SQL 表、互联网等——但在本实例中,我们将填充一个向量存储并将其用作检索器。有关向量存储的更多信息,请参阅 此文档。
首先,我们需要加载要索引的数据。为此,我们将使用 WebBaseLoader。这需要安装 BeautifulSoup (opens in a new tab):
pip install beautifulsoup4之后,我们可以导入并使用 WebBaseLoader。
from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader("https://docs.smith.langchain.com/user_guide")
docs = loader.load()接下来,我们需要将其索引到一个向量存储中。这需要几个组件,即一个 嵌入模型 和一个 向量存储。
对于嵌入模型,我们再次为通过 API 访问或运行本地模型提供示例。
确保您已安装 langchain_openai 包并设置了适当的环境变量(这些与 LLM 所需的相同)。
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()现在,我们可以使用这个嵌入模型将文档摄取到向量存储中。 为简单起见,我们将使用一个简单的本地向量存储 FAISS。
首先,我们需要为此安装所需的包:
pip install faiss-cpu然后我们可以构建我们的索引:
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter()
documents = text_splitter.split_documents(docs)
vector = FAISS.from_documents(documents, embeddings)现在我们已经将这些数据索引到向量存储中,我们将创建一个检索链。 这个链将接收传入的问题,查找相关文档,然后将这些文档连同原始问题一起传入 LLM,并要求它回答原始问题。
首先,让我们设置接受问题和检索到的文档并生成答案的链。
from langchain.chains.combine_documents import create_stuff_documents_chain
prompt = ChatPromptTemplate.from_template("""Answer the following question based only on the provided context:
<context>
{context}
</context>
Question: {input}""")
document_chain = create_stuff_documents_chain(llm, prompt)如果我们愿意,我们可以通过直接传入文档来自己运行它:
from langchain_core.documents import Document
document_chain.invoke({
"input": "how can langsmith help with testing?",
"context": [Document(page_content="langsmith can let you visualize test results")]
})然而,我们希望文档首先来自我们刚刚设置的检索器。 这样,我们可以使用检索器动态选择最相关的文档,并为给定问题传入这些文档。
from langchain.chains import create_retrieval_chain
retriever = vector.as_retriever()
retrieval_chain = create_retrieval_chain(retriever, document_chain)我们现在可以调用这个链。它返回一个字典——LLM 的响应在 answer 键中
response = retrieval_chain.invoke({"input": "how can langsmith help with testing?"})
print(response["answer"])
# LangSmith offers several features that can help with testing:...这个答案应该更加准确!
深入了解
我们现在已经成功设置了一个基本的检索链。我们只涉及了检索的基础知识——要深入了解这里提到的所有内容,请查看 文档的这一部分。
对话检索链
到目前为止我们创建的链只能回答单个问题。人们正在构建的主要类型的 LLM 应用之一是聊天机器人。那么我们如何将这个链变成一个可以回答后续问题的链呢?
我们仍然可以使用 create_retrieval_chain 函数,但我们需要改变两件事:
- 检索方法现在不应只处理最近的输入,而应考虑整个历史记录。
- 最终的 LLM 链同样应考虑整个历史记录
更新检索
为了更新检索,我们将创建一个新链。这个链将接收最近的输入(input)和对话历史记录(chat_history),并使用 LLM 生成搜索查询。
from langchain.chains import create_history_aware_retriever
from langchain_core.prompts import MessagesPlaceholder
# First we need a prompt that we can pass into an LLM to generate this search query
prompt = ChatPromptTemplate.from_messages([
MessagesPlaceholder(variable_name="chat_history"),
("user", "{input}"),
("user", "Given the above conversation, generate a search query to look up to get information relevant to the conversation")
])
retriever_chain = create_history_aware_retriever(llm, retriever, prompt)我们可以通过传入一个用户提出后续问题的实例来测试这个。
from langchain_core.messages import HumanMessage, AIMessage
chat_history = [HumanMessage(content="Can LangSmith help test my LLM applications?"), AIMessage(content="Yes!")]
retriever_chain.invoke({
"chat_history": chat_history,
"input": "Tell me how"
})您应该看到这会返回关于在 LangSmith 中测试的文档。这是因为 LLM 生成了一个新查询,将聊天历史记录与后续问题结合起来。
现在我们有了这个新的检索器,我们可以创建一个新链,在考虑这些检索到的文档的情况下继续对话。
prompt = ChatPromptTemplate.from_messages([
("system", "Answer the user's questions based on the below context:\n\n{context}"),
MessagesPlaceholder(variable_name="chat_history"),
("user", "{input}"),
])
document_chain = create_stuff_documents_chain(llm, prompt)
retrieval_chain = create_retrieval_chain(retriever_chain, document_chain)我们现在可以端到端地测试这个:
chat_history = [HumanMessage(content="Can LangSmith help test my LLM applications?"), AIMessage(content="Yes!")]
retrieval_chain.invoke({
"chat_history": chat_history,
"input": "Tell me how"
})我们可以看到这给出了一个连贯的答案——我们已经成功地将检索链转变为聊天机器人!
代理
到目前为止,我们已经创建了链的示例——其中每个步骤都是预先知道的。 我们将创建的最后一件事是代理——由 LLM 决定采取什么步骤。
注意:对于这个例子,我们将只展示如何使用 OpenAI 模型创建代理,因为本地模型还不够可靠。
构建代理时要做的第一件事是决定它应该访问哪些工具。 对于这个例子,我们将让代理访问两个工具:
- 我们刚刚创建的检索器。这将使它能够轻松回答关于 LangSmith 的问题
- 一个搜索工具。这将使它能够轻松回答需要最新信息的问题。
首先,让我们为我们刚刚创建的检索器设置一个工具:
from langchain.tools.retriever import create_retriever_tool
retriever_tool = create_retriever_tool(
retriever,
"langsmith_search",
"Search for information about LangSmith. For any questions about LangSmith, you must use this tool!",
)我们将使用的搜索工具是 Tavily。这需要一个 API 密钥(他们有慷慨的免费层)。在他们的平台上创建后,您需要将其设置为环境变量:
export TAVILY_API_KEY=...如果您不想设置 API 密钥,可以跳过创建此工具。
from langchain_community.tools.tavily_search import TavilySearchResults
search = TavilySearchResults()现在我们可以创建我们想要使用的工具列表:
tools = [retriever_tool, search]现在我们有了这些工具,我们可以创建一个代理来使用它们。我们将很快地介绍这一点——要深入了解到底发生了什么,请查看 代理的入门文档
首先安装 langchain hub
pip install langchainhub安装 langchain-openai 包 要与 OpenAI 交互,我们需要使用 langchain-openai,它连接 OpenAI SDK [https://github.com/langchain-ai/langchain/tree/master/libs/partners/openai]。 (opens in a new tab)
pip install langchain-openai现在我们可以使用它来获取一个预定义的提示
from langchain_openai import ChatOpenAI
from langchain import hub
from langchain.agents import create_openai_functions_agent
from langchain.agents import AgentExecutor
# Get the prompt to use - you can modify this!
prompt = hub.pull("hwchase17/openai-functions-agent")
# You need to set OPENAI_API_KEY environment variable or pass it as argument `api_key`.
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)我们现在可以调用代理并看看它如何回应!我们可以问它关于 LangSmith 的问题:
agent_executor.invoke({"input": "how can langsmith help with testing?"})我们可以问它关于天气的问题:
agent_executor.invoke({"input": "what is the weather in SF?"})我们可以与它进行对话:
chat_history = [HumanMessage(content="Can LangSmith help test my LLM applications?"), AIMessage(content="Yes!")]
agent_executor.invoke({
"chat_history": chat_history,
"input": "Tell me how"
})深入了解
我们现在已经成功设置了一个基本代理。我们只涉及了代理的基础知识——要深入了解这里提到的所有内容,请查看 文档的这一部分。
使用 LangServe 进行服务
现在我们已经构建了一个应用程序,我们需要为它提供服务。这就是 LangServe 的用武之地。 LangServe 帮助开发人员将 LangChain 链部署为 REST API。您不需要使用 LangServe 来使用 LangChain,但在本指南中,我们将展示如何使用 LangServe 部署您的应用。
虽然本指南的第一部分是在 Jupyter Notebook 中运行的,但我们现在将离开那里。我们将创建一个 Python 文件,然后从命令行与它交互。
使用以下命令安装:
pip install "langserve[all]"服务器
为了为我们的应用程序创建一个服务器,我们将创建一个 serve.py 文件。这将包含我们为应用程序提供服务的逻辑。它由三部分组成:
- 我们上面刚刚构建的链的定义
- 我们的 FastAPI 应用
- 用于为链提供服务的路由的定义,这是通过
langserve.add_routes完成的
#!/usr/bin/env python
from typing import List
from fastapi import FastAPI
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_community.document_loaders import WebBaseLoader
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.tools.retriever import create_retriever_tool
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain import hub
from langchain.agents import create_openai_functions_agent
from langchain.agents import AgentExecutor
from langchain.pydantic_v1 import BaseModel, Field
from langchain_core.messages import BaseMessage
from langserve import add_routes
# 1. Load Retriever
loader = WebBaseLoader("https://docs.smith.langchain.com/user_guide")
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter()
documents = text_splitter.split_documents(docs)
embeddings = OpenAIEmbeddings()
vector = FAISS.from_documents(documents, embeddings)
retriever = vector.as_retriever()
# 2. Create Tools
retriever_tool = create_retriever_tool(
retriever,
"langsmith_search",
"Search for information about LangSmith. For any questions about LangSmith, you must use this tool!",
)
search = TavilySearchResults()
tools = [retriever_tool, search]
# 3. Create Agent
prompt = hub.pull("hwchase17/openai-functions-agent")
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# 4. App definition
app = FastAPI(
title="LangChain Server",
version="1.0",
description="A simple API server using LangChain's Runnable interfaces",
)
# 5. Adding chain route
# We need to add these input/output schemas because the current AgentExecutor
# is lacking in schemas.
class Input(BaseModel):
input: str
chat_history: List[BaseMessage] = Field(
...,
extra={"widget": {"type": "chat", "input": "location"}},
)
class Output(BaseModel):
output: str
add_routes(
app,
agent_executor.with_types(input_type=Input, output_type=Output),
path="/agent",
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="localhost", port=8000)就是这样!如果我们执行这个文件:
python serve.py我们应该看到我们的链在 localhost: 8000 上提供服务。
游乐场
每个 LangServe 服务都附带一个简单的内置 UI,用于使用流式输出和中转步骤可见性来配置和调用应用程序。 前往 http://localhost (opens in a new tab): 8000/agent/playground/ 试一试!传入与之前相同的问题——"how can langsmith help with testing?"——它的响应应该与之前相同。
客户端
现在让我们设置一个客户端,以编程方式与我们的服务交互。我们可以使用 [langserve.RemoteRunnable](/langserve#client) 轻松地做到这一点。
使用它,我们可以与服务化的链交互,就像它在客户端运行一样。
from langserve import RemoteRunnable
remote_chain = RemoteRunnable("http://localhost:8000/agent/")
remote_chain.invoke({
"input": "how can langsmith help with testing?",
"chat_history": [] # Providing an empty list as this is the first call
})要了解 LangServe 的许多其他功能,请 前往此处。
下一步
我们已经介绍了如何使用 LangChain 构建应用程序、如何使用 LangSmith 跟踪它以及如何使用 LangServe 为它提供服务。 这三个方面的功能都比我们在这里介绍的要多得多。 要继续您的旅程,我们建议您按顺序阅读以下内容:
- 所有这些功能都由 LangChain 表达语言(LCEL) 支持——这是一种将这些组件链接在一起的方式。查看该文档以更好地了解如何创建自定义链。
- Model IO 涵盖了提示、LLM 和输出解析器的更多细节。
- 检索 涵盖了与检索相关的一切的更多细节
- 代理 涵盖了与代理相关的一切的细节
- 探索常见的 端到端用例 和 模板应用
- 阅读 LangSmith 相关资料,这是一个用于调试、测试、监控等的平台
- 了解有关使用 LangServe 为应用程序提供服务的更多信息