跳到主要内容

快速入门

在本快速入门中,我们将向您展示如何:

  • 用LangChain, LangSmith 和 LangServe设置
  • 用LangChain最基本、最常用的组件:提示模板、模型和输出解析器
  • 用 LangChain 表达式语言,是 LangChain 构建的协议,有助于组件链接
  • 用LangChain构建一个简单的应用
  • 用 LangSmith 追踪应用程序
  • 用 LangServe 为您的应用程序提供服务

这需要涵盖相当多的内容!让我们开始吧

设置

Jupyter 笔记本

本指南(以及文档中的大多数其他指南)使用 Jupyter 笔记本,并假设读者也是如此。 Jupyter 笔记本非常适合学习如何使用 LLM 系统,因为很多时候事情可能会出错(意外输出、API 关闭等),而在交互式环境中阅读指南是更好地理解它们的好方法。

您不需要在 Jupyter Notebook 中阅读该指南,但建议您这样做。有关如何安装的说明,请参阅此处。

安装

运行LangChain安装

pip install langchain

LangSmith

使用 LangChain 构建的许多应用程序将包含多个步骤,并多次调用 LLM,随着这些应用程序变得越来越复杂,能够检查链或代理内部到底发生了什么变得至关重要。做到这一点的最佳方法是使用LangSmith。

请注意,LangSmith 不是必需的,但它很有帮助。如果您确实想使用 LangSmith,请在上面的链接注册后,确保设置环境变量以开始记录跟踪:

export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="..."

使用LangChain构建

LangChain 能够构建将外部数据源和计算连接到法学硕士的应用程序。在本快速入门中,我们将介绍几种不同的方法。我们将从一个简单的LLM链开始,它仅依赖于提示模板中的信息来响应。接下来,我们将构建一个检索链,它从单独的数据库中获取数据并将其传递到提示模板中。然后,我们将添加聊天历史记录,以创建对话检索链。这允许您以聊天方式与该法学硕士进行交互,因此它会记住以前的问题。最后,我们将构建一个代理 - 它利用 LLM 来确定是否需要获取数据来回答问题。我们将在高层次上介绍这些内容,但所有这些都有很多细节!我们将链接到相关文档。

LLM Chain

integration

我们将展示如何使用通过 API 提供的模型(例如 OpenAI)和本地开源模型,以及使用 Ollama 等集成。

OpenAI

首先我们要导入 LangChain x OpenAI 整合包

pip install langchain-openai

访问 API 需要 API 密钥,您可以通过创建帐户并前往此处获取该密钥。一旦我们有了密钥,我们就需要通过运行以下命令将其设置为环境变量:

export OPENAI_API_KEY="..."

然后我们初始化模型:

from langchain_openai import ChatOpenAI

llm = ChatOpenAI()

如果您不想设置环境变量,可以在启动 OpenAI LLM 类时直接通过 openai_api_key 命名参数传递密钥:

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(openai_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 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)。 Python

chain.invoke({"input": "how can langsmith help with testing?"})

Local (using Ollama)

Ollama 允许您在本地运行开源大型语言模型,例如 Llama 2。

首先,按照以下说明设置并运行本地 Ollama 实例:

  • 下载
  • 通过 ollama pull llama2 获取模型

然后,确保 Ollama 服务器正在运行。之后,您可以执行以下操作:

from langchain_community.llms import Ollama
llm = Ollama(model="llama2")

一旦您安装并初始化了您选择的 LLM,我们就可以开始试用!让我们问它 LangSmith 是什么 - 这是训练数据中不存在的东西,因此它不应该有很好的响应

llm.invoke("how can langsmith help with testing?")

我们还可以通过提示模板来指导它的响应。提示模板用于将原始用户输入转换为更好的 LLM 输入。

from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "You are 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)。 Python

chain.invoke({"input": "how can langsmith help with testing?"})

Anthropic

首先我们需要安装LangChain x Anthropic 整合包.

pip install langchain-anthropic

访问 API 需要 API 密钥,您可以通过在此处创建帐户来获取该密钥。当我们有了密钥,我们就需要通过运行以下命令将其设置为环境变量:

export ANTHROPIC_API_KEY="..."

然后我们初始化模型:

from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(model="claude-3-sonnet-20240229", temperature=0.2, max_tokens=1024)

如果您不想设置环境变量,则可以在启动 Anthropic 聊天模型类时直接通过 anthropic_api_key 命名参数传递密钥:

llm = ChatAnthropic(anthropic_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 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)。 Python

chain.invoke({"input": "how can langsmith help with testing?"})

Cohere

首先我们安装 Cohere SDK 包.

pip install cohere

访问 API 需要 API 密钥,您可以通过创建帐户并前往此处获取该密钥。当我们有了密钥,我们就需要通过运行以下命令将其设置为环境变量:

export COHERE_API_KEY="..."

然后我们初始化模型:

from langchain_community.chat_models import ChatCohere

llm = ChatCohere()

如果您不想设置环境变量,可以在启动 Cohere LLM 类时直接通过 cohere_api_key 命名参数传递密钥:

from langchain_community.chat_models import ChatCohere

llm = ChatCohere(cohere_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 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)。 Python

chain.invoke({"input": "how can langsmith help with testing?"})

进一步深入

我们现在已经成功建立了一个基本的LLM链。我们只涉及了提示、模型和输出解析器的基础知识 - 要更深入地了解这里提到的所有内容,请参阅本部分文档

对话检索链

到目前为止,我们创建的链只能回答单个问题。人们构建的 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 in order 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 中测试的文档。这是因为法学硕士生成了一个新查询,将聊天历史记录与后续问题相结合。

现在我们有了这个新的检索器,我们可以创建一个新的链来继续与这些检索到的文档进行对话。

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"
})

我们可以看到,这给出了一个连贯的答案 - 我们已经成功地将检索链变成了聊天机器人!

Agent

我们已经创建了链的示例 - 其中每个步骤都是提前知道的。我们要创建的最后一个东西是一个Agent——LLM决定采取什么步骤。

::: tip 注意 在本示例中,我们将仅展示如何使用 OpenAI 模型创建代理,因为本地模型还不够可靠。 :::

构建代理时要做的第一件事就是决定它应该有权访问哪些工具。在此示例中,我们将授予代理访问两个工具的权限:

  1. 我们刚刚创建的检索器。这将让它轻松回答有关 LangSmith 的问题
  2. 一个搜索工具。这将使它能够轻松回答需要最新信息的问题。

首先,让我们为刚刚创建的检索器设置一个工具:

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]

现在我们有了工具,我们可以创建一个代理来使用它们。我们将很快讨论这一点 - 要更深入地了解到底发生了什么,请查看Agent的入门文档

首先安装langchain hub

pip install langchainhub

现在我们可以使用它来获取预定义的prompt

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")
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)

我们现在可以调用Agent并查看它如何响应!我们可以向它询问有关 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"
})

进一步深入

现在我们已经成功建立了一个基本agent。我们只涉及了agent的基础知识 - 要深入了解此处提到的所有内容,请参阅本部分(文档)[https://python.langchain.com/docs/modules/agents]。

用LangServe创建服务

现在我们已经构建了一个应用程序,我们需要为它提供服务。这就是 LangServe 的用武之地。LangServe 帮助开发人员将 LangChain 链部署为 REST API。您不需要使用 LangServe 来使用 LangChain,但在本指南中,我们将向您展示如何使用 LangServe 部署您的应用程序。

虽然本指南的第一部分旨在在 Jupyter Notebook 中运行,但我们现在将不再使用它。我们将创建一个 Python 文件,然后从命令行与其交互。

安装:

pip install "langserve[all]"

服务

要为我们的应用程序创建服务器,我们将创建一个serve.py 文件。这将包含我们为应用程序提供服务的逻辑。它由三部分组成:

  1. 我们刚刚在上面构建的链的定义
  2. FastAPI 应用程序
  3. 为链提供服务的路由的定义,通过 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_openai import ChatOpenAI
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 上提供服务。

Playground

每个 LangServe 服务都带有一个简单的内置 UI,用于配置和调用具有流输出和中间步骤可见性的应用程序。前往 http://localhost:8000/agent/playground/ 尝试一下!传递与之前相同的问题 - “langsmith 如何帮助测试?” - 它的响应应该和以前一样。

Client

现在让我们设置一个客户端,以便以编程方式与我们的服务进行交互。我们可以使用 langserve.RemoteRunnable 轻松地做到这一点。使用它,我们可以与服务链进行交互,就像它在客户端运行一样。

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 的许多其他功能的更多信息,请前往(此处)[https://python.langchain.com/docs/langserve]。

下一步

我们已经介绍了如何使用 LangChain 构建应用程序、如何使用 LangSmith 跟踪它以及如何使用 LangServe 提供服务。这三个方面的功能比我们在此介绍的要多得多。要继续您的旅程,我们建议您阅读以下内容(按顺序):

  • 所有这些功能均由 LangChain 表达式语言(LCEL)支持 - 一种将这些组件链接在一起的方法。查看该文档以更好地了解如何创建自定义链。
  • 模型 IO 涵盖了提示、LLM 和输出解析器的更多细节。
  • 检索涵盖与检索相关的所有内容的更多细节
  • Agent涵盖与Agent相关的所有详细信息
  • 探索常见的端到端用例和模板应用程序
  • 了解 LangSmith,这是一个用于调试、测试、监控等的平台
  • 了解有关使用 LangServe 为您的应用程序提供服务的更多信息