LangGraph

LangGraph#

官网:https://langchain-ai.github.io/langgraph/

LangGraph 是什么: LangGraph 是一个用于构建具有状态、多角色应用程序的库,适用于创建代理和多代理工作流。

能干什么:

  • 实现应用中的循环和分支。

  • 自动在图的每一步之后保存状态,支持暂停和恢复图的执行,以支持错误恢复、人工控制agent

  • 支持agent中人为可控制,可中断图的执行以批准或编辑代理计划的下一个动作。

  • 支持流输出,包括每个节点产生的令牌流。

  • 与 LangChain 和 LangSmith 无缝集成。

快速开始#

!pip install -U langgraph
!pip install langchain-anthropic
Requirement already satisfied: langgraph in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (0.2.19)
Requirement already satisfied: langchain-core<0.4,>=0.2.38 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langgraph) (0.2.38)
Requirement already satisfied: langgraph-checkpoint<2.0.0,>=1.0.2 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langgraph) (1.0.8)
Requirement already satisfied: PyYAML>=5.3 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.4,>=0.2.38->langgraph) (6.0.1)
Requirement already satisfied: jsonpatch<2.0,>=1.33 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.4,>=0.2.38->langgraph) (1.33)
Requirement already satisfied: langsmith<0.2.0,>=0.1.75 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.4,>=0.2.38->langgraph) (0.1.83)
Requirement already satisfied: packaging<25,>=23.2 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.4,>=0.2.38->langgraph) (24.1)
Requirement already satisfied: pydantic<3,>=1 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.4,>=0.2.38->langgraph) (2.8.0)
Requirement already satisfied: tenacity!=8.4.0,<9.0.0,>=8.1.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.4,>=0.2.38->langgraph) (8.4.2)
Requirement already satisfied: typing-extensions>=4.7 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.4,>=0.2.38->langgraph) (4.12.2)
Requirement already satisfied: jsonpointer>=1.9 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from jsonpatch<2.0,>=1.33->langchain-core<0.4,>=0.2.38->langgraph) (3.0.0)
Requirement already satisfied: orjson<4.0.0,>=3.9.14 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.75->langchain-core<0.4,>=0.2.38->langgraph) (3.10.5)
Requirement already satisfied: requests<3,>=2 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.75->langchain-core<0.4,>=0.2.38->langgraph) (2.32.3)
Requirement already satisfied: annotated-types>=0.4.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from pydantic<3,>=1->langchain-core<0.4,>=0.2.38->langgraph) (0.7.0)
Requirement already satisfied: pydantic-core==2.20.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from pydantic<3,>=1->langchain-core<0.4,>=0.2.38->langgraph) (2.20.0)
Requirement already satisfied: charset-normalizer<4,>=2 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from requests<3,>=2->langsmith<0.2.0,>=0.1.75->langchain-core<0.4,>=0.2.38->langgraph) (3.3.2)
Requirement already satisfied: idna<4,>=2.5 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from requests<3,>=2->langsmith<0.2.0,>=0.1.75->langchain-core<0.4,>=0.2.38->langgraph) (3.7)
Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from requests<3,>=2->langsmith<0.2.0,>=0.1.75->langchain-core<0.4,>=0.2.38->langgraph) (2.2.2)
Requirement already satisfied: certifi>=2017.4.17 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from requests<3,>=2->langsmith<0.2.0,>=0.1.75->langchain-core<0.4,>=0.2.38->langgraph) (2024.6.2)

[notice] A new release of pip is available: 24.0 -> 24.2
[notice] To update, run: pip install --upgrade pip
Collecting langchain-anthropic
  Downloading langchain_anthropic-0.1.23-py3-none-any.whl.metadata (2.2 kB)
Collecting anthropic<1,>=0.30.0 (from langchain-anthropic)
  Downloading anthropic-0.34.2-py3-none-any.whl.metadata (18 kB)
Requirement already satisfied: defusedxml<0.8.0,>=0.7.1 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-anthropic) (0.7.1)
Requirement already satisfied: langchain-core<0.3.0,>=0.2.26 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-anthropic) (0.2.38)
Requirement already satisfied: anyio<5,>=3.5.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from anthropic<1,>=0.30.0->langchain-anthropic) (4.4.0)
Requirement already satisfied: distro<2,>=1.7.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from anthropic<1,>=0.30.0->langchain-anthropic) (1.9.0)
Requirement already satisfied: httpx<1,>=0.23.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from anthropic<1,>=0.30.0->langchain-anthropic) (0.27.0)
Collecting jiter<1,>=0.4.0 (from anthropic<1,>=0.30.0->langchain-anthropic)
  Downloading jiter-0.5.0-cp311-cp311-macosx_11_0_arm64.whl.metadata (3.6 kB)
Requirement already satisfied: pydantic<3,>=1.9.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from anthropic<1,>=0.30.0->langchain-anthropic) (2.8.0)
Requirement already satisfied: sniffio in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from anthropic<1,>=0.30.0->langchain-anthropic) (1.3.1)
Requirement already satisfied: tokenizers>=0.13.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from anthropic<1,>=0.30.0->langchain-anthropic) (0.19.1)
Requirement already satisfied: typing-extensions<5,>=4.7 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from anthropic<1,>=0.30.0->langchain-anthropic) (4.12.2)
Requirement already satisfied: PyYAML>=5.3 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.3.0,>=0.2.26->langchain-anthropic) (6.0.1)
Requirement already satisfied: jsonpatch<2.0,>=1.33 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.3.0,>=0.2.26->langchain-anthropic) (1.33)
Requirement already satisfied: langsmith<0.2.0,>=0.1.75 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.3.0,>=0.2.26->langchain-anthropic) (0.1.83)
Requirement already satisfied: packaging<25,>=23.2 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.3.0,>=0.2.26->langchain-anthropic) (24.1)
Requirement already satisfied: tenacity!=8.4.0,<9.0.0,>=8.1.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langchain-core<0.3.0,>=0.2.26->langchain-anthropic) (8.4.2)
Requirement already satisfied: idna>=2.8 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from anyio<5,>=3.5.0->anthropic<1,>=0.30.0->langchain-anthropic) (3.7)
Requirement already satisfied: certifi in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from httpx<1,>=0.23.0->anthropic<1,>=0.30.0->langchain-anthropic) (2024.6.2)
Requirement already satisfied: httpcore==1.* in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from httpx<1,>=0.23.0->anthropic<1,>=0.30.0->langchain-anthropic) (1.0.5)
Requirement already satisfied: h11<0.15,>=0.13 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->anthropic<1,>=0.30.0->langchain-anthropic) (0.14.0)
Requirement already satisfied: jsonpointer>=1.9 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from jsonpatch<2.0,>=1.33->langchain-core<0.3.0,>=0.2.26->langchain-anthropic) (3.0.0)
Requirement already satisfied: orjson<4.0.0,>=3.9.14 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.75->langchain-core<0.3.0,>=0.2.26->langchain-anthropic) (3.10.5)
Requirement already satisfied: requests<3,>=2 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.75->langchain-core<0.3.0,>=0.2.26->langchain-anthropic) (2.32.3)
Requirement already satisfied: annotated-types>=0.4.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->anthropic<1,>=0.30.0->langchain-anthropic) (0.7.0)
Requirement already satisfied: pydantic-core==2.20.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->anthropic<1,>=0.30.0->langchain-anthropic) (2.20.0)
Requirement already satisfied: huggingface-hub<1.0,>=0.16.4 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from tokenizers>=0.13.0->anthropic<1,>=0.30.0->langchain-anthropic) (0.23.4)
Requirement already satisfied: filelock in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic<1,>=0.30.0->langchain-anthropic) (3.15.4)
Requirement already satisfied: fsspec>=2023.5.0 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic<1,>=0.30.0->langchain-anthropic) (2024.6.1)
Requirement already satisfied: tqdm>=4.42.1 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.0->anthropic<1,>=0.30.0->langchain-anthropic) (4.66.4)
Requirement already satisfied: charset-normalizer<4,>=2 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from requests<3,>=2->langsmith<0.2.0,>=0.1.75->langchain-core<0.3.0,>=0.2.26->langchain-anthropic) (3.3.2)
Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/cliu/.virtualenvs/langchain-guide/lib/python3.11/site-packages (from requests<3,>=2->langsmith<0.2.0,>=0.1.75->langchain-core<0.3.0,>=0.2.26->langchain-anthropic) (2.2.2)
Downloading langchain_anthropic-0.1.23-py3-none-any.whl (21 kB)
Downloading anthropic-0.34.2-py3-none-any.whl (891 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 891.9/891.9 kB 3.0 MB/s eta 0:00:00a 0:00:01m
?25hDownloading jiter-0.5.0-cp311-cp311-macosx_11_0_arm64.whl (299 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 299.3/299.3 kB 17.1 MB/s eta 0:00:00
?25hInstalling collected packages: jiter, anthropic, langchain-anthropic
Successfully installed anthropic-0.34.2 jiter-0.5.0 langchain-anthropic-0.1.23

[notice] A new release of pip is available: 24.0 -> 24.2
[notice] To update, run: pip install --upgrade pip
from typing import Annotated, Literal, TypedDict
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import END, START, StateGraph, MessagesState
from langgraph.prebuilt import ToolNode
from langchain_openai import ChatOpenAI
from langchain.globals import set_verbose

set_verbose(True)

# 给agent定义工具
@tool
def search(query: str):
    """搜索提亲"""
    # This is a placeholder, but don't tell the LLM that...
    if "sf" in query.lower() or "san francisco" in query.lower():
        return "It's 60 degrees and foggy."
    return "It's 90 degrees and sunny."


# 绑定工具给模型,
tools = [search]
# 定义工具节点
tool_node = ToolNode(tools)
model = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
model = model.bind_tools(tools)

# 定义函数来判断是否要继续执行
def should_continue(state: MessagesState) -> Literal["tools", END]:
    messages = state['messages']
    last_message = messages[-1]
    # 如果模型需要调用工具,则继续执行
    if last_message.tool_calls:
        return "tools"
    # 否则,我们停止(回复用户)
    return END


# 定义函数来调用模型,需要注意,这里的方法的入参的类型`MessagesState`
def call_model(state: MessagesState):
    messages = state['messages']
    response = model.invoke(messages)
    # We return a list, because this will get added to the existing list
    return {"messages": [response]}


# 定义工作流
workflow = StateGraph(MessagesState)
# 添加节点,一个是模型节点,一个是工具节点
workflow.add_node("agent", call_model)
workflow.add_node("tools", tool_node)

# 添加边,从开始节点到agent节点
workflow.add_edge(START, "agent")

# 添加了边,从agent节点到should_continue对应的节点
workflow.add_conditional_edges(
    # First, we define the start node. We use `agent`.
    # This means these are the edges taken after the `agent` node is called.
    "agent",
    # Next, we pass in the function that will determine which node is called next.
    should_continue,
)

# 添加边,从tools节点到agent节点
workflow.add_edge("tools", 'agent')

# 初始化一个内存保存器,用来保存中间状态
checkpointer = MemorySaver()

# Finally, we compile it!
# This compiles it into a LangChain Runnable,
# meaning you can use it as you would any other runnable.
# Note that we're (optionally) passing the memory when compiling the graph
app = workflow.compile(checkpointer=checkpointer)

# Use the Runnable
final_state = app.invoke(
    {"messages": [HumanMessage(content="what is the weather in sf")]},
    config={"configurable": {"thread_id": 42}}
)
final_state["messages"][-1].content
'The weather in San Francisco is 60 degrees Fahrenheit and foggy.'

final_state中保存了所有的消息,我们可以查看每一步的消息,如下:

for index,item in enumerate(final_state['messages']):
    print(f'{index}:     {item}\n')
0:     content='what is the weather in sf' id='c9f135bf-a5f1-4ed7-8dd7-d11ca22dec1c'

1:     content='' additional_kwargs={'tool_calls': [{'id': 'call_9xEBQ03d0EM8Z7GnR602Tz7Z', 'function': {'arguments': '{"query":"weather in San Francisco"}', 'name': 'search'}, 'type': 'function'}]} response_metadata={'token_usage': {'completion_tokens': 16, 'prompt_tokens': 49, 'total_tokens': 65}, 'model_name': 'gpt-35-turbo', 'system_fingerprint': 'fp_e49e4201a9', 'finish_reason': 'tool_calls', 'logprobs': None} id='run-f81b46ec-423e-43d1-af2a-db6821faa87d-0' tool_calls=[{'name': 'search', 'args': {'query': 'weather in San Francisco'}, 'id': 'call_9xEBQ03d0EM8Z7GnR602Tz7Z', 'type': 'tool_call'}] usage_metadata={'input_tokens': 49, 'output_tokens': 16, 'total_tokens': 65}

2:     content="It's 60 degrees and foggy." name='search' id='1b4a8e65-f185-4861-b763-b137f6d35749' tool_call_id='call_9xEBQ03d0EM8Z7GnR602Tz7Z'

3:     content='The weather in San Francisco is currently 60 degrees and foggy.' response_metadata={'token_usage': {'completion_tokens': 15, 'prompt_tokens': 81, 'total_tokens': 96}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-a48dd699-a6b5-44fe-811b-773658a9223e-0' usage_metadata={'input_tokens': 81, 'output_tokens': 15, 'total_tokens': 96}

Langsmith中的观察如下: 图片的替代文本 链接: https://smith.langchain.com/public/b811deb0-0464-47d2-8380-d85c377b0992/r

下面我们对上面的代码做具体的解释

  1. LangGraph本身是一个图,图有节点和边,上面的agent,tool都是在定义节点,节点需要通过边来连接起来

  2. 图需要有开始和结束节点。上面的代码中有start和end

  3. 这里不同的是,当前节点执行完毕,下一个节点是可以动态选择的。

  4. 具体的在代码里面已详细的注释了,代入到图的概念里面比较好理解

按照执行过程解释如下

  1. start节点开始, star节点加了一个朝向agent的边。一开始就会执行agent节点。

  2. agent 节点, 会和模型做交互

  3. agent 节点有一个should_continue的边,在边里面决定走tools节点还是end节点。

  4. 模型的返回是要调用工具的,所以should_continue返回了tools

  5. tools执行结束后,tools节点有一个朝向agent的边, 所以,他会继续执行agent

  6. agent结束之后,会继续should_continue,此时返回了end节点,agent flow结束

总结: 对比LangChain之前提供了Agent和agent_executor,这种方式可操作性更强,可控制性更强。 之前LangChain的agent_executor,想要做人为控制是很不方便的,没有这样的入口,是否继续执行是模型决定的,并且他的实现本质上是迭代器。agent_executor将工具的输出一直输入到模型,直到没有工具可调用,agent才结束。此外,它还可以保存整个agent的过程数据,比如对话历史,但是agent_executor就不行,它没有提供这样的功能,本质上对话历史LangChain自己处理。