LangGraph的诞生

LangGraph由LangChain团队开发。而LangChain 诞生于 2022 年 10 月,最初只是一个帮助开发者调用大语言模型(LLM)的工具包。它的定位是“链式调用”,用 Chain(链)把 Prompt、模型、工具(Tool)、数据源等连接在一起。凭借这个简单而强大的抽象,LangChain 很快成为当时最受欢迎的 LLM 应用框架。

早期的LangChain有很多自定义的Chain,很方便做demo。但是由于其过度封装,工程化的时候遇到了很多的麻烦,一旦想自定义就得继承原有Chian,然后再在from_llm中编写逻辑,写了很多不必要的代码。(曾经为了修改Chain,想debug学习一下代码,但是一路下去,不知道跳转到哪里去了,当时还有LangChain和LlamaIndex之争。)

from langchain import hub
from langchain.chains import RetrievalQA

# See full prompt at https://smith.langchain.com/hub/rlm/rag-prompt
prompt = hub.pull("rlm/rag-prompt")

qa_chain = RetrievalQA.from_llm(
    llm, retriever=vectorstore.as_retriever(), prompt=prompt
)

qa_chain("What are autonomous agents?")

后来在2023年8月推出了LCEL,Chain的调用才变得直观起来。

from langchain import hub
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

prompt = hub.pull("rlm/rag-prompt")

defformat_docs(docs):
    return"nn".join(doc.page_content for doc in docs)

qa_chain = (
    {
        "context": vectorstore.as_retriever() | format_docs,
        "question": RunnablePassthrough(),
    }
    | prompt
    | llm
    | StrOutputParser()
)

qa_chain.invoke("What are autonomous agents?")
  • 但随着应用越来越复杂,线性链式结构逐渐暴露很多局限,在实际开发时很痛苦:
    • 一旦有逻辑分支就会变得冗长。
    • 难以表示循环、状态保持。
    • 多智能体之间的消息传递无法自然表达。

于是,LangChain 团队推出了新的尝试 —— LangGraph,于2024年1月推出0.0.1版本。

LangGraph的特点

  • LangChain 用“链”描述逻辑,适合 简单的、一次性的 LLM 调用。

  • LangGraph 用“图”描述逻辑,适合 复杂的、有状态的、多轮或多智能体协作。

LangGraph 更像“流程编排系统”。利用了图的思想:节点、边与状态其核心抽象是 图(Graph):

  • 节点(Node):执行单元,可以是调用一个模型、运行一个工具、访问一个数据库,或者一个人工审批环节,自由的编写代码。
  • 边(Edge):控制数据流,决定从一个节点走向另一个节点,可以是顺序执行、条件分支、循环。
  • 状态(State):全局上下文,贯穿整个图的执行过程。它可以被节点读写,从而支持有状态的对话、多轮任务执行,甚至长时任务恢复(其实就是一个字典)。

于是LangGraph 相较于传 LangChain有了以下优势:

  • 有状态执行: 支持跨节点共享上下文,能够保存和恢复任务,使Agent的上下文管理变得简单。
  • 灵活的流程表达: 分支、循环、人机协同都可以通过图结构自然表达。
  • 直观的运行逻辑: 使用LangSmith或者graph.get_graph(xray=True).draw_mermaid_png()可以轻松的查看图的整体结构和运行逻辑关系,方便追踪执行路径、调试 agent、持久存储执行状态。
  • 更低层的可控性: LangGraph 真正做到了框架,让开发者完全掌控 agent 的运行逻辑,专心编写业务代码。

与Dify等低代码有何不同

LangGraph 与 Dify这类平台比较,定位有明显不同:

  • LangGraph:
    • 开源框架,更偏向 开发者。
    • 提供底层抽象,让你可以搭建高度自定义的 agent 工作流。
    • 更适合需要灵活控制、多智能体协作的复杂应用。
  • Dify:
    • 属于 AI 应用开发中台。
    • 提供的是“低代码”环境,开发者通过界面化配置快速构建应用。
    • 优点是上手快、集成好,但灵活性受限。

LangGraph的唯一缺点就是不能直接给非技术人员使用。因此实际开发中,很多时候用Dify,Coze等快速验证想法,再使用LangGraph重新开发,优化各部分算法,提高运行效率。

基于LangGraph开发一个聊天bot

bot Agent 代码

from typing import Annotated
from typing_extensions import TypedDict
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from pydantic import SecretStr

# 此处定义你自己的模型
llm = ChatOpenAI(base_url="http://127.0.0.1:8000/v1", api_key=SecretStr("123123"), model="qwen3_32")

# 定义图状态
classState(TypedDict):
    messages: Annotated[list, add_messages]  # 此处维护完整的消息历史

graph = StateGraph(State)


defchatbot(state: State):
    return {"messages": [llm.invoke(state["messages"])]}

graph.add_node("chatbot", chatbot)
graph.add_edge(START, "chatbot")
graph.add_edge("chatbot", END)

app = graph.compile()

if __name__ == "__main__":
    messages = []
    whileTrue:
        user_input = input("‍: ")
        if user_input.lower() in ["quit""exit""q"]:
            print("Exiting...")
            break
        messages.append({"role""user""content": user_input})
        response = app.invoke({"messages": messages})
        messages = response["messages"]
        print(f': {response["messages"][-1].content}')

查看图结构

使用下面的代码,保存图结构

from PIL import Image
import io
png_data = app.get_graph(xray=True).draw_mermaid_png()
img_io = io.BytesIO(png_data)

# 使用PIL的Image打开BytesIO对象
image = Image.open(img_io)

# 指定保存的本地文件路径
save_path'local_image.png'

# 保存图像到本地
image.save(save_path)

Image

运行示例

Image

学习资源推荐

如果你想更深入地学习大模型,以下是一些非常有价值的学习资源,这些资源将帮助你从不同角度学习大模型,提升你的实践能力。

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]