快速入门
在本快速入门中,我们将向您展示如何:
- 用LangChain, LangSmith 和 LangServe设置
- 用LangChain最基本、最常用的组件:提示模板、模型和输出解析器
- 用 LangChain 表达式语言,是 LangChain 构建的协议,有助于组件链接
- 用LangChain构建一个简单的应用
- 用 LangSmith 追踪应用程序
- 用 LangServe 为您的应用程序提供服务
这需要涵盖相当多的内容!让我们开始吧
设置
Jupyter 笔记本
本指南(以及文档中的大多数其他指南)使用 Jupyter 笔记本,并假设读者也是如此。 Jupyter 笔记本非常适合学习如何使用 LLM 系统,因为很多时候事情可能会出错(意外输出、API 关闭等),而在交互式环境中阅读指南是更好地理解它们的好方法。
您不需要在 Jupyter Notebook 中阅读该指南,但建议您这样做。有关如何安装的说明,请参阅此处。
安装
运行LangChain安装
- Pip
- Conda
pip install langchain
conda install langchain -c conda-forge
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 模型创建代理,因为本地模型还不够可靠。 :::
构建代理时要做的第一件事就是决定它应该有权访问哪些工具。在此示例中,我们将授予代理访问两个工具的权限:
- 我们刚刚创建的检索器。这将让它轻松回答有关 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]
现在我们有了工具,我们可以创建一个代理来使用它们。我们将很快讨论这一点 - 要更深入地了解到底发生了什么,请查看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 文件。这将包含我们为应用程序提供服务的逻辑。它由三部分组成:
- 我们刚刚在上面构建的链的定义
- 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_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 为您的应用程序提供服务的更多信息