LangChain 框架介绍及入门指南

LangChain 是一个用来开发大型语言模型(LLM)应用的框架,为了简化构建基于 LLM 的应用,它能够为开发 LLM 应用带来如下能力:

  • 根据给定的 Prompt 方便构建上下文,并连接到 LLM, 得到更加符合查询的回答结果
  • 在构建整个基于 LLM 的应用提供各种工具,如各种模块(Modules)、LCEL、LangGraph 等
  • 提供工具支持,使用户自己的 LLM 应用从原型版本到上线到生产环境过程中,一站式的调试、测试、评估等迭代功能

当前,已经发布了最新的 v0.10.0 稳定版本,可以参考这里 LangChain v0.1.0。本文我们通过介绍 LangChain 框架的方方面面(算是对官方文档的一个入门的内容浓缩)使我们对它有一个更全面的认识,以帮助我们使用 LangChain 构建基于 LLM 的应用,具体包括如下几个方面的内容:

  • LangChain 是什么
  • LangChain Modules 概览
  • LangChain 模块:Model I/O
  • LangChain 模块:Retrieval
  • LangChain 模块:Agents
  • LangChain 模块:Chains
  • LangChain 模块:Memory
  • LangChain 模块:Callbacks
  • LCEL(LangChain Expression Language)
  • LangServe 介绍
  • LangSmith 介绍
  • LangGraph 介绍

LangChain 是什么

LangChain 是一个开源框架,它提供了构建基于 LLM 的 AI 应用所需的各种模块(Modules)与工具,大大降低了开发这一类相关应用的门槛,使得任何人都可以轻松构建基于 OpenAI、Cohere、GPT4All、Huggingface 等提供的大模型的应用。
首先,我们看一下 LangChain 框架的组成,如下图所示:
langchain_stack
可见,LangChain 包含如下 4 个主要部分:

  • LangChain Libraries

LangChain Libraries 是一个 Python 和 JavaScript 库,是 LangChain 中最核心的部分,在图中对应于下方的深色块。LangChain Libraries 被分为 3 个核心的部分,也是代码组织方式的表现:LangChain、LangChain-Community、LangChain-Core,简要介绍如下:

  1. LangChain

包括组成应用认知架构(Application’s Cognitive Architecture)的各个部分,如 Chains、Agents 以及 检索策略(Retrieval Strategies)等。

  1. LangChain-Community

所有用来与第三方集成的功能,都会放到 LangChain-Community 中,方便构建 LLM 应用的人更集中关注集成的能力,比如提供 LLM 的各个 Provider。

  1. LangChain-Core

包含 LangChain 的基本抽象和 LCEL(LangChain Expression Language)。

  • LangChain Templates

提供了一组用于简化部署的参考架构,方便构建基于 LLM 应用的中的各种任务。

  • LangServe

提供了用来将 LangChain 部署为 REST API 服务的工具,以供应用的其他模块调用。LangChain 使用了 FastAPI 来实现这种服务能力。

  • LangSmith

LangSmith 是 LangChain 提供的开发平台,方便开发人员进行调试、测试、评估、监控等。

LangChain 模块(Modules)概览

LangChain 提供了一个标准的可扩展的接口,可以方便地与外部其他组件进行交互以满足面向特定领域 LLM 应用的需求,它也能够与外部其它组件/中间件连接和交互。这些模块根据功能及行为方式,分为 6 个类别,如下表所示:

模块名称 模块功能
Model I/O 用于与 LLM 语言模型交互
Retrieval 用于与应用特定的数据进行交互
Agents 用于确定 LLM 需要采用的 Action 及其顺序的决策,即智能体应用
Chains 用于构建顺序调用的多个构建块(Building Block),主要支持通过 LCEL 的方式构建
Memory 用于在多轮对话过程中保存应用状态
Callbacks 回调系统,用来支持 LLM 应用的日志记录、监控、Streaming 处理,等等

通过上面表格,我们基本了解了 LangChain 提供的一些方便构建 LLM 应用的模块及其对应的功能,下面,针对每个模块进行更详细的说明。

LangChain 模块:Model I/O

Model I/O 模块是基于 LangChain 框架构建 LLM 应用的最核心的模块,因为我们必须要与 LLM 进行交互,没有它其他什么都做不了。使用 Model I/O 模块的基本流程,如下图所示:
model_io
我们以使用开源 LLM 为例,基于 Llama 2 模型来说明如何快速使用 Model I/O 的方法,分为如下几个步骤:

  1. 选择并连接到 LLM

使用 Ollama 在本地就可以启动一个模型服务,然后我们就可以使用 LangChain 创建对应的 LLM 和 ChatModel,示例代码如下:

from langchain_community.llms import Ollama
from langchain_community.chat_models import ChatOllama

llm = Ollama(model="llama2")
chat_model = ChatOllama()

通过 llm 和 chat_model 我们就可以与 LLM 进行交互。我们需要知道,llm 和 chat_model 是不同的(具体区别查看这里:LLM vs Chat Models),但是都能通过它们与大模型对话,其中 chat_model 是基于 llm 的,而且进一步进行了调优,使整个持续对话过程更加丰富和完善。

  1. 调用与 LLM 对话

使用 LangChain 与 LLM 进行对话,示例代码如下:

from langchain.schema import HumanMessage

text = "What would be a good company name for a company that makes colorful socks?"
messages = [HumanMessage(content=text)]
llm.invoke(text) # >> Feetful of Fun
chat_model.invoke(messages) # >> AIMessage(content="Socks O'Color")
  1. 创建 Prompt Template

Prompt Template 包含了我们要查询 LLM 的请求内容,以及我们所基于的上下文,这样就限制了预训练的 LLM 能够基于我们提供的上下文来给出更准确的回答。示例代码如下:

from langchain.prompts.chat import ChatPromptTemplate

template = "You are a helpful assistant that translates {input_language} to {output_language}."
human_template = "{text}"
chat_prompt = ChatPromptTemplate.from_messages([
    ("system", template),
    ("human", human_template),
])
chat_prompt.format_messages(input_language="English", output_language="French", text="I love programming.")

这样就能够把当前要查询的请求内容,以及相关的上线文消息信息整合到一起,然后调用 LLM 进行对话。

  1. 创建并配置 OutputParser,指定 LLM 返回消息格式

LangChain 提供了不同类型的 OutputParser,能够将 LLM 输出的消息进行格式化,方便下游应用任务使用。比如,下面示例中使用 CommaSeparatedListOutputParser,将消息按照逗号分割,并返回一个列表:

from langchain.output_parsers import CommaSeparatedListOutputParser

output_parser = CommaSeparatedListOutputParser()
output_parser.parse("hi, bye") # >> ['hi', 'bye']
  1. 使用 LCEL 组装上面的各种配置

使用 LCEL 将上面的 Prompt Template、ChatModel、OutputParser 组合到一起,并实现了与 LLM 的交互,示例代码如下:

template = "Generate a list of 5 {text}.\n\n{format_instructions}"

chat_prompt = ChatPromptTemplate.from_template(template)
chat_prompt = chat_prompt.partial(format_instructions=output_parser.get_format_instructions())
chain = chat_prompt | chat_model | output_parser
chain.invoke({"text": "colors"}) # >> ['red', 'blue', 'green', 'yellow', 'orange']

LangChain 模块:Retrieval

我们在使用 LLM 构建应用时,往往会根据自己的应用场景使用自己的数据,而不是直接使用预训练的 LLM 提供的内容,所以我们就会从自己的系统中输入数据来影响与 LLM 对话返回的结果内容。LangChain 通过 Retrieval 模块来处理有关数据连接的功能,比如常用的 RAG(Retrieval Augmented Generation)架构能够增强 LLM 的表达。LangChain 提供了 RAG 架构所需要的各种 Building Block,简化我们开发 LLM 应用的难度。
LangChain 基于 RAG 实现的 Retrieval 模块的基本流程,如下图所示:
retrieval_data_connection
下面简要说明流程中涉及到的各个部分,有关 RAG 更详细内容可以参考其它资料。

  • Document Loaders

从指定的数据源加载数据,通过 LangChain 的 Document Loader 实现,并转换成对应的 Document 对象(一个文本块及其相关信息),示例如下:

from langchain_community.document_loaders import TextLoader

loader = TextLoader("./index.md")
loader.load()
  • Text Splitting

将一个 Document 分割成多个文本块(Text Chunk),根据输入 LLM 的 Prompt 得到与对话查询最相关的文本块,以此作为对话上下文,提高对话返回结果的相关性和精确度。

  • Text Embedding Model

对输入 LLM 的 Prompt,以及我们上面得到的文本块,需要通过调用选定的 Text Embedding Model 模型来得到对应的 Embedding,以此获取丰富的语义表达,这样就能够得到与 Prompt 最相关的文本块作为与 LLM 此次对话的上下文。

  • Vector Store

Vector Store 也叫 Vector DB,用来存储我们自己数据的向量表示内容(Embedding),以支持 Retrieval 模块的检索匹配。

  • Retriever

Retriever 称为检索器,从我们构建好的 Vector Store 中进行检索。LangChain 提供了各种支持检索的算法,比如:ParentDocumentRetriever、SelfQueryRetriever、EnsembleRetriever、MultiVectorRetriever,等等。
下面以 SelfQueryRetriever 为例说明使用方法,示例代码如下所示:

from langchain.schema import Document
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
docs = [
    Document(
        page_content="A bunch of scientists bring back dinosaurs and mayhem breaks loose",
        metadata={"year": 1993, "rating": 7.7, "genre": "science fiction"},
    ),
    Document(
        page_content="Leo DiCaprio gets lost in a dream within a dream within a dream within a ...",
        metadata={"year": 2010, "director": "Christopher Nolan", "rating": 8.2},
    ),
]
vectorstore = Chroma.from_documents(docs, OpenAIEmbeddings())

from langchain.chains.query_constructor.base import AttributeInfo
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain_openai import ChatOpenAI

metadata_field_info = [
    AttributeInfo(
        name="genre",
        description="The genre of the movie. One of ['science fiction', 'comedy', 'drama', 'thriller', 'romance', 'action', 'animated']",
        type="string",
    ),
    AttributeInfo(
        name="year",
        description="The year the movie was released",
        type="integer",
    ),
]
document_content_description = "Brief summary of a movie"
llm = ChatOpenAI(temperature=0)
retriever = SelfQueryRetriever.from_llm(
    llm, vectorstore, document_content_description, metadata_field_info,
)

# This example only specifies a filter
retriever.invoke("I want to watch a movie rated higher than 8.5")

上面代码,首先,构建 Document,生成对应的 Embedding 保存到 Vector Store 中;然后,创建 SelfQueryRetriever,需要指定 LLM、Vector Store、Document 相关的元数据信息(如果对搜索引擎索引数据比较熟悉,就会理解这么做的原因:是为了构建倒排索引);最后,就可以通过 retriever 来进行查询得到与输入 Prompt 最相关的 Document,并基于这些 Document 作为对话上下文,输入给 LLM 得到最终的对话输出结果。

LangChain 模块:Agents

Agent 通过 LLM 来推理,能够自然地、持续多轮地与 LLM 交互,这也是智能体所具备与支持的基本能力。
为了说明 Agent 框架的使用方法,使用 Tavily 和 Retriever 两个工具来构建 Agent,其中 Tavily 是一个支持 Online 搜索的工具。

  1. 准备 Tavily 和 Retriever
from langchain_community.tools.tavily_search import TavilySearchResults
search = TavilySearchResults()

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
loader = WebBaseLoader("https://docs.smith.langchain.com/overview")
docs = loader.load()
documents = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200).split_documents(docs)
vector = FAISS.from_documents(documents, OpenAIEmbeddings())
retriever = vector.as_retriever()

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!",
)
  1. 创建 Agent
from langchain_openai import ChatOpenAI
tools = [search, retriever_tool]
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

from langchain import hub
prompt = hub.pull("hwchase17/openai-functions-agent") # Get the prompt to use

from langchain.agents import create_openai_functions_agent
agent = create_openai_functions_agent(llm, tools, prompt)

from langchain.agents import AgentExecutor
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
  1. 运行 Agent

运行 Agent,示例代码如下:

agent_executor.invoke({"input": "hi!"})

这样的交互不会记忆上下文,是无状态的。所以,如果考虑上下文,需要把以往的记录加入到 Memory,示例代码如下:

from langchain_core.messages import AIMessage, HumanMessage
agent_executor.invoke(
    {
        "chat_history": [
            HumanMessage(content="hi! my name is bob"),
            AIMessage(content="Hello Bob! How can I assist you today?"),
        ],
        "input": "what's my name?",
    }
)

也可以直接使用 LangChain 提供的 ChatMessageHistory、RunnableWithMessageHistory 来实现自动跟踪历史消息的功能,可以参考 LangChain 文档。

LangChain 模块:Chains

Chains 是一个调用/处理/计算任务序列的抽象,可以根据我们自己的需求来构建不同的调用链、处理链,等等。Chains 是通过 LangChain 提供的 LCEL 来构建的。下面是 LainChain 提供的一些 LCEL Constructor,可以方便构建一个 Chain,如下所示:

  • create_stuff_documents_chain
  • create_openai_fn_runnable
  • create_structured_output_runnable
  • load_query_constructor_runnable
  • create_sql_query_chain
  • create_history_aware_retriever
  • create_retrieval_chain

通过名称,就可以大致了解每个 LCEL Constructor 实现的 Chain 的功能。

LangChain 模块:Memory

Memory 模块主要用来支持读(READ)和写(WRITE)两个基本的操作。在与 LLM 交互过程中需要能够即时地获取、保存对话信息,具体交互流程如下图所示:
langchain_memory
下面以一个与 LLM 交互的过程为例,说明如何使用 LangChain 提供的 ConversationBufferMemory,示例代码如下:

from langchain_openai import OpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory

llm = OpenAI(temperature=0)
prompt = PromptTemplate.from_template(template)
memory = ConversationBufferMemory(memory_key="chat_history") # need to align the `memory_key`
conversation = LLMChain(llm=llm, prompt=prompt, verbose=True, memory=memory)

当然也可以直接使用 ChatModel 来实现整个对话过程,具体例子可以参考 LangChain 官网文档。
Memory 模块提供了多个不同的实现,具体也可以根据自己实际应用需求来实现,如下所示是 LangChain 提供的一些实现:

具体功能和使用方法,可以点击对应链接查看官网文档的详细说明。

LangChain 模块:Callbacks

LangChain 支持使用 Callbacks,通过 Hook 到基于 LLM 的应用的任何位置,来实现类似日志记录、监控、Streaming 处理以及其它任务等等。要想实现自定义的 Callback 能力,可以直接实现 CallbackHandler 接口,开发满足自己应用需求的 CallbackHandler。
LangChain 实现的 StdOutCallbackHandler 是一个非常基础的 Callback,使用示例如下:

from langchain.callbacks import StdOutCallbackHandler
from langchain.chains import LLMChain
from langchain_openai import OpenAI
from langchain.prompts import PromptTemplate

handler = StdOutCallbackHandler()
llm = OpenAI()
prompt = PromptTemplate.from_template("1 + {number} = ")

chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler]) # Constructor callback
chain.invoke({"number":2})

chain = LLMChain(llm=llm, prompt=prompt, verbose=True) # Use verbose flag to achieve callbacks
chain.invoke({"number":2})

chain = LLMChain(llm=llm, prompt=prompt) # Request callbacks
chain.invoke({"number":2}, {"callbacks":[handler]})

LCEL(LangChain Expression Language)

LCEL(LangChain Expression Language),是一种声明式表达式语言,可以非常容易地构建松耦合的执行链(Chain),主要优点如下所示:

  • 支持流式处理:可以通过 Streaming 的方式与 LLM 交互,比如根据自己构建的 LLM 应用的负载情况和处理能力,从 LLM 以 Streaming 的方式处理 LLM 输出的消息结果。
  • 支持异步:通过 LCEL 实现异步处理,也能方便地将同步方式改成异步方式,使 LLM 应用能够获得更好的性能。
  • 支持优化的并行执行:可以在 LangChain 底层对 LCEL chain 的每一步进行并行化,提高处理性能。
  • 支持重试与容错处理:可以对 LCEL chain 的每一步进行失败重试、容错处理,提高 LLM 应用的可靠性和健壮性。
  • 支持访问中间结果:通过访问 LCEL chain 中每一步的中间结果,能够对整个应用的处理过程进行透明化,并根据实际情况评估从而制定优化应用的方案。
  • 支持配置输入/输出 Schema:可以方便地用于验证输入/输出,同时更好地方便 LangServe 实现。
  • 支持无缝集成 LangSmith 跟踪监控:所有步骤执行的细节都可以记录到 LangSmith,从而最大限度地实现可观察性和可调试性。
  • 支持无缝集成 LangServe 部署:基于 LCEL 实现的 chain 可以非常方便地使用 LangServe 来完成部署。

下面通过一个实现 prompt + model + output parser 的例子,用来说明使用 LCEL 带来的直观性和便利性,示例代码如下:

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

prompt = ChatPromptTemplate.from_template("tell me a short joke about {topic}")
model = ChatOpenAI(model="gpt-4")
output_parser = StrOutputParser()

chain = prompt | model | output_parser

chain.invoke({"topic": "ice cream"})

首先定义每一步中的逻辑,然后使用 UNIX 管道符 “|” 顺序连接,就可以构建好一个 LCEL chain,并启动执行该 LCEL chain。
上面例子,是最简单的使用串行方式构建 LCEL chain,LangChain 也支持更加复杂的 LCEL chain,可以根据自己的应用需求来进行编排。下面是官网文档中相对复杂的一个例子,如图所示:
langchain_rag_example_graph
具体代码实现,参考官网这里 RAG Search Example

LangServe 工具介绍

LangServe 提供了将 LangChain 的 runnables 和 chains 部署为 REST API 的能力,它是使用 FastAPI 来实现的。使用 LangServe 部署基于 LLM 的应用,会包含两个部分:Server(提供 LLM ChatModel 服务)、Client(调用模型服务)。
下面通过一个例子来说明如何构建。

  • 实现 Server 端

Server 包括 OpenAI ChatModel 和 Anthropic ChatModel,它们可以提供对话服务能力,示例代码如下:

#!/usr/bin/env python
from fastapi import FastAPI
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatAnthropic, ChatOpenAI
from langserve import add_routes
import uvicorn

app = FastAPI(
    title="LangChain Server",
    version="1.0",
    description="A simple api server using Langchain's Runnable interfaces",
)

add_routes(
    app, ChatOpenAI(), path="/openai",
)

add_routes(
    app, ChatAnthropic(), path="/anthropic",
)

model = ChatAnthropic()
prompt = ChatPromptTemplate.from_template("tell me a joke about {topic}")
add_routes(
    app, prompt | model, path="/joke",
)

if __name__ == "__main__":
    uvicorn.run(app, host="localhost", port=8000)

如果没有报错,打开浏览器浏览 localhost:8080/docs 可以看到对应的页面,说明 Server 端部署成功。

  • 实现 Client 端

Client 端用来与 Server 端进行交互:调用 Server 端提供的 REST API 就可以实现。Client 端示例的 Python 代码如下:

from langchain.schema import SystemMessage, HumanMessage
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnableMap
from langserve import RemoteRunnable

openai = RemoteRunnable("http://localhost:8000/openai/")
anthropic = RemoteRunnable("http://localhost:8000/anthropic/")
joke_chain = RemoteRunnable("http://localhost:8000/joke/")

joke_chain.invoke({"topic": "parrots"})

# or async
await joke_chain.ainvoke({"topic": "parrots"})

prompt = [
    SystemMessage(content='Act like either a cat or a parrot.'),
    HumanMessage(content='Hello!')
]

# Supports astream
async for msg in anthropic.astream(prompt):
    print(msg, end="", flush=True)

prompt = ChatPromptTemplate.from_messages(
    [("system", "Tell me a long story about {topic}")]
)

# Can define custom chains
chain = prompt | RunnableMap({
    "openai": openai,
    "anthropic": anthropic,
})

chain.batch([{"topic": "parrots"}, {"topic": "cats"}])

上面代码给出了不同的调用方式:同步调用、异步调用、流式调用,甚至可以根据 Server 端提供的服务接口实现自定义的 Chain 调用。

LangSmith 工具介绍

使用 LangChain 可以方便、快速构建我们的 LLM 应用或 Agent 的原型,但是并不能方便地实现从原型到生产环境的部署。所以就有了 LangSmith,LangSmith 可以非常方便地对原型进行调试、测试,持续地迭代直至满足生产环境要求。
使用 LangSmith 平台,需要通过 https://smith.langchain.com/ 创建一个 LangSmith 账号并注册一个 API Key 才能使用。具体如何使用,可以参考官方文档 https://docs.smith.langchain.com/user_guide,这里不再过多说明。

LangGraph 介绍

LangGraph 是一个用来构建有状态的、多 Actor 的 LLM 应用的库,它是在 LangChain 框架的基础之上构建实现的。LangGraph 的灵感来自 Pregel 和 Apache Beam,支持基于 LCEL 的能力构建一个带有循环的(Cyclic)的应用模式,从而实现协调多个 Chain 跨多个计算步骤(Computation Steps)的能力。可见,LangGraph 是支持带环的计算图模式的,并不是简单的 DAG(有向无环图)。
下面以官网的入门例子为例,说明如何使用 LangGraph,如下所示:

  1. 构建一个 Online 搜索工具 Tavily
from langchain_community.tools.tavily_search import TavilySearchResults
tools = [TavilySearchResults(max_results=1)]

from langgraph.prebuilt import ToolExecutor
tool_executor = ToolExecutor(tools) # wrap Tavily tool using LangGraph ToolExecutor
  1. 构建 LLM 对象
from langchain_openai import ChatOpenAI
# We will set streaming=True so that we can stream tokens
model = ChatOpenAI(temperature=0, streaming=True)

from langchain.tools.render import format_tool_to_openai_function
functions = [format_tool_to_openai_function(t) for t in tools]
model = model.bind_functions(functions) # Bind tools to the model
  1. 定义 Agent 状态

langgraph 提供的图主要是指 StatefulGraph,它可以被一个状态对象参数化(Parameterized)。状态对象在图中的每个节点之间传递,每一个节点会返回更新状态对象的操作,从而实现状态的更新。
这里的状态会跟踪对话过程中产生的消息的列表,构建的图中的每个节点需要把消息添加到列表中,所以使用 TypedDict 来实现 Agent 状态,如下所示:

from typing import TypedDict, Annotated, Sequence
import operator
from langchain_core.messages import BaseMessage

class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], operator.add]
  1. 定义图节点(Node)和边(Edge)

在 langgraph 中,图节点是一个 function 对象或 runnable 对象;然后通过边来连接各个节点,在 langgraph 中有两种类型的边:Conditional Edge 和 Normal Edge,可以通过定义函数来实现,确定从一个节点到另一个节点的路径。示例代码如下:

from langgraph.prebuilt import ToolInvocation
import json
from langchain_core.messages import FunctionMessage

# Define the function that determines whether to continue or not
def should_continue(state):
    messages = state['messages']
    last_message = messages[-1]
    if "function_call" not in last_message.additional_kwargs:
        return "end"
    else:
        return "continue"

# Define the function that calls the model
def call_model(state):
    messages = state['messages']
    response = model.invoke(messages)
    return {"messages": [response]} # Return a list to add to the existing list

# Define the function to execute tools
def call_tool(state):
    messages = state['messages']
    # Based on the continue condition, we know the last message involves a function call
    last_message = messages[-1]
    # We construct an ToolInvocation from the function_call
    action = ToolInvocation(
        tool=last_message.additional_kwargs["function_call"]["name"],
        tool_input=json.loads(last_message.additional_kwargs["function_call"]["arguments"]),
    )
    response = tool_executor.invoke(action) # Call the tool_executor and get back a response
    function_message = FunctionMessage(content=str(response), name=action.tool) # use the response to create a FunctionMessage
    return {"messages": [function_message]}

上面代码定义了一个 LangGraph 中需要个节点(call_model 和 call_tool 代表图中的两个计算节点)和边(通过 should_continue 函数决定计算下一个节点),节点和边的连接构建组合成图的逻辑,会在下一步进行。

  1. 定义 StateGraph
from langgraph.graph import StateGraph, END

workflow = StateGraph(AgentState)

# Define the two nodes we will cycle between
workflow.add_node("agent", call_model)
workflow.add_node("action", call_tool)

workflow.set_entry_point("agent") # Set the entrypoint as `agent`

# Add a conditional edge
workflow.add_conditional_edges(
    "agent", # First, we define the start node. We use `agent`.
    should_continue, # Next, the function will determine which node is called next.
    # Finally we pass in a mapping, and based on which one it matches, that node will then be called.
    {
        "continue": "action", # If `tools`, then we call the tool node.
        "end": END # Otherwise we finish.
    }
)

# Add a normal edge from `tools` to `agent`: after `tools` is called, `agent` node is called next.
workflow.add_edge('action', 'agent')

app = workflow.compile() # # Compiles it into a LangChain Runnable,
  1. 执行定义好的 LangGraph
from langchain_core.messages import HumanMessage

inputs = {"messages": [HumanMessage(content="what is the weather in sf")]}
app.invoke(inputs)

通过上面 1~6 步骤,就可以构建并执行一个基于 LangGraph 的简单 LLM 应用。

参考资源

Creative Commons License

本文基于署名-非商业性使用-相同方式共享 4.0许可协议发布,欢迎转载、使用、重新发布,但务必保留文章署名时延军(包含链接:http://shiyanjun.cn),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>