LangGraph入门

2,094 阅读4分钟

构建LangGraph

一般来说使用LangGraph构建workflow 的步骤如下

  1. 初始化模型和工具。
  2. 使用状态初始化图。
  3. 定义图节点。
  4. 定义入口点和图边。
  5. 编译该图。
  6. 执行该图。

下面我们来一步一步实现

1. 初始化模型和工具

首先,设置 Azure OpenAI 的相关环境变量并初始化模型:

import os
from langchain.chat_models import AzureChatOpenAI

os.environ['AZURE_OPENAI_ENDPOINT'] = 'xxx'
os.environ['OPENAI_API_KEY'] = 'xxx'
os.environ['OPENAI_API_VERSION'] = '2024-08-01-preview'
os.environ['DEPLOYMENT_NAME'] = 'gpt-4o-mini'

# 初始化 LLM 模型
llm = AzureChatOpenAI()

2. 使用状态初始化图

定义 State 类,用于存储和更新状态:

from typing import TypedDict, Annotated

class State(TypedDict):
    messages: Annotated[list, add_messages]

3. 定义图节点

识别图片节点

处理图片并发送给 LLM 进行描述:

import json
from langchain.schema import HumanMessage

def process_pic(state: State):
    params = state['messages'][-1].content
    params = json.loads(params)
    base64_image = params['content']

    message = HumanMessage(
        content=[
            {"type": "text", "text": "describe the weather in this image"},
            {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}},
        ],
    )
    res = llm.invoke([message])
    return {"messages": res}

普通文字聊天节点

处理普通文字内容并发送给 LLM 进行回答:

def process_text(state: State):
    params = state['messages'][-1].content
    params = json.loads(params)
    text = params['content']
    res = llm.invoke(input=text)
    return {"messages": res}

4. 定义入口点和图边

路由规则

根据 param_type 来选择对应的节点,图片走 process_pic,文字走 process_text,否则结束:

def route_tools(state: State):
    params = state['messages'][-1].content
    params = json.loads(params)
    param_type = params['param_type']
    
    if param_type == 'image':
        return 'process_pic'
    elif param_type == 'text':
        return "process_text"
    
    return END

添加节点到图中

将处理图片和文字的节点添加到 graph_builder 中:

graph_builder = StateGraph(State)
graph_builder.add_node('process_pic', process_pic)
graph_builder.add_node('process_text', process_text)

添加边到图中

通过 add_conditional_edges 定义边,并根据路由规则决定下一步执行哪个节点:

graph_builder.add_conditional_edges(
    START, 
    route_tools, 
    {"process_pic": "process_pic", "process_text": "process_text", END: END}
)

graph_builder.set_finish_point("process_pic")
graph_builder.set_finish_point("process_text")

添加检查点功能

添加 MemorySaver 作为检查点,用于保存状态和记忆:

checkpointer = MemorySaver()

5. 编译图

编译图并将其绘制为 mermaid.png

graph = graph_builder.compile(checkpointer=checkpointer)
img = graph.get_graph().draw_mermaid_png()

# 保存为图片
with open("mermaid.png", "wb") as f:
    f.write(img)

6. 使用图

处理图片

将图片转换为 Base64 格式并传递给图进行处理:

import base64
import json

# 图片转 Base64 格式
def image_to_base64(image_path):
    with open(image_path, "rb") as image_file:
        encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
    return encoded_string

# 配置
base64_pic = image_to_base64('202191013236_6182.jpg')
s = json.dumps({"param_type": "image", "content": base64_pic})

config = {"configurable": {"thread_id": "1"}}

# 使用图处理图片
for event in graph.stream({"messages": [("user", s)]}, config=config):
    for value in event.values():
        print(value)

处理文字

发送普通文字给图进行处理:

s = json.dumps({"param_type": "text", "content": 'hello'})

config = {"configurable": {"thread_id": "1"}}

# 使用图处理文字
for event in graph.stream({"messages": [("user", s)]}, config=config):
    for value in event.values():
        print(value)

配置 Langsmith (可选)

如果你想启用 Langsmith 作为控制台进行调试,可以去官网申请,然后如下配置到代码里: 官网地址:www.langchain.com/langsmith

import os

# 配置 Langsmith API 密钥
os.environ['LANGCHAIN_TRACING_V2'] = 'true'
os.environ['LANGCHAIN_ENDPOINT'] = "https://api.smith.langchain.com"
os.environ['LANGCHAIN_API_KEY'] = "xxx"
os.environ['LANGCHAIN_PROJECT'] = "test1"

全部代码

import os
import json
from typing import Annotated
from langchain_core.messages import HumanMessage
from langchain_openai import AzureChatOpenAI, ChatOpenAI

from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph

from typing_extensions import TypedDict

from langgraph.graph.message import add_messages

from langgraph.constants import (
    END,
    START
)


class State(TypedDict):
    messages: Annotated[list, add_messages]


os.environ[
    'AZURE_OPENAI_ENDPOINT'] = 'xxx'
os.environ['OPENAI_API_KEY'] = 'xxx'
os.environ['OPENAI_API_VERSION'] = '2024-08-01-preview'
os.environ['DEPLOYMENT_NAME'] = 'gpt-4o-mini'
llm = AzureChatOpenAI()

os.environ['LANGCHAIN_TRACING_V2'] = 'true'
os.environ['LANGCHAIN_ENDPOINT'] = "https://api.smith.langchain.com"
os.environ['LANGCHAIN_API_KEY'] = "xxx"
os.environ['LANGCHAIN_PROJECT'] = "test1"


def process_pic(state: State):
    params = state['messages'][-1].content
    params = json.loads(params)
    base64_image = params['content']

    message = HumanMessage(
        content=[
            {"type": "text", "text": "describe the weather in this image"},
            {
                "type": "image_url",
                "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"},
            },
        ],
    )
    res = llm.invoke(input=[message])
    return {"messages": res}



def process_text(state: State):
    params = state['messages'][-1].content
    params = json.loads(params)
    text = params['content']
    res = llm.invoke(input=text)
    return {"messages":  res}


def route_tools(
        state: State,
):
    params = state['messages'][-1].content
    params = json.loads(params)
    param_type = params['param_type']
    if param_type == 'image':
        return 'process_pic'
    elif param_type == 'text':
        return "process_text"

    return END


graph_builder = StateGraph(State)
graph_builder.add_node('process_pic', process_pic)

graph_builder.add_node('process_text', process_text)

graph_builder.add_conditional_edges(START, route_tools,
                                    {"process_pic": "process_pic", "process_text": "process_text", END: END})

graph_builder.set_finish_point("process_pic")
graph_builder.set_finish_point("process_text")

checkpointer = MemorySaver()

graph = graph_builder.compile(checkpointer=checkpointer)
img = graph.get_graph().draw_mermaid_png()
with open("mermaid.png", "wb") as f:
    f.write(img)

运行部分

import json

from fengshui.graph.sha import graph
import base64


def image_to_base64(image_path):
    with open(image_path, "rb") as image_file:
        encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
    return encoded_string


base64_pic = image_to_base64('202191013236_6182.jpg')
s = json.dumps({"param_type": "image", "content": base64_pic})


config = {"configurable": {"thread_id": "1"}}
for event in graph.stream({"messages": [("user", s)]}, config=config):
    for value in event.values():
        print(value)

总结

  • LangGraph 核心组件: Graphs, State, Nodes, Edges, Send, checkpointer。
  • LangGraph 实现特点: 可控性、持久化、Human-in-the-loop、Streaming、React agent。