构建LangGraph
一般来说使用LangGraph构建workflow 的步骤如下
- 初始化模型和工具。
- 使用状态初始化图。
- 定义图节点。
- 定义入口点和图边。
- 编译该图。
- 执行该图。
下面我们来一步一步实现
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。