Python——学习LangGraph智能体(一)
Python——学习LangGraph智能体(一)
引言——LangGraph
Langgraph,官网网址:https://langgraph.com.cn/index.html
核心优势
LangGraph 为任何长时间运行、有状态的工作流或智能体提供底层支持基础设施。LangGraph 不抽象提示或架构,并提供以下核心优势:
持久执行:构建能够抵御故障并长时间运行的智能体,可从上次中断的地方自动恢复。
人机协作:在执行的任何时间点检查和修改智能体状态,无缝地融入人工监督。
全面记忆:创建真正有状态的智能体,既具备用于持续推理的短期工作记忆,也具备跨会话的长期持久记忆。
使用 LangSmith 进行调试:利用可视化工具深入了解复杂的智能体行为,这些工具可以追踪执行路径、捕获状态转换并提供详细的运行时指标。
生产就绪部署:利用可扩展的基础设施,自信地部署复杂的智能体系统,该基础设施旨在处理有状态、长时间运行工作流的独特挑战。
LangGraph 的生态系统
虽然 LangGraph 可以独立使用,但它也能与任何 LangChain 产品无缝集成,为开发人员提供构建智能体所需的全套工具。为了改进您的 LLM 应用程序开发,请将 LangGraph 与以下产品搭配使用:
LangSmith — 有助于智能体评估和可观察性。调试性能不佳的 LLM 应用程序运行、评估智能体轨迹、在生产环境中获得可见性,并随着时间的推移提高性能。
LangGraph 平台 — 使用专为长时间运行、有状态工作流设计的部署平台,轻松部署和扩展智能体。在团队之间发现、重用、配置和共享智能体 — 并在LangGraph Studio中通过可视化原型快速迭代。
LangChain – 提供集成和可组合组件,以简化 LLM 应用程序开发。
环境——前期准备
Python环境:3.12 (推荐3.9+)
pip install langgraph langchain langchain-openai langchain-community python-dotenv
python-dotenv依赖主要是为了读取根目录.env中配置(也可在项目中直接赋值)
.env文件配置
在根目录创建.env文件(本人使用的是智谱的APIkey,阿里云百炼的亦可用,后面只需要对应修改base-url即可
# 智谱 API Key
ZHIPUAI_API_KEY=这里填写apikey
搭建简单智能体
创建py文件:langgraph-base.py文件,附上全部代码,如下:(工作流程大概就是,如果提示词中存在“上海”或者“Shanghai”,则调用工具,workflow.add_edge(“tools”, “agent”)这一句代码即是如果调用了工具,那么就要再次回答agent节点。
附上流图(虚线为条件边,实现为普通边,如图在tools被调用之后,那么必定会调用agent
import os
from typing import Literal
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
load_dotenv() #使用此方法是为了刷新.env环境配置中的apikey,以防止下方初始化模型失败
from langgraph.checkpoint.memory import MemorySaver #类似于上下文存储,存放的记忆节点
from langgraph.graph import StateGraph, START, END, MessagesState # 对应的langgraph的边,图思想
from langgraph.prebuilt import ToolNode
@tool
def search(query: str):
"""模拟一个搜索工具"""
if "上海" in query.lower() or "Shanghai" in query.lower():
return "现在30度,有雾"
return "现在是35度,阳光明媚"
# 将工具函数放入工具列表
tools = [search]
# 创建工具节点
tool_node = ToolNode(tools)
# 1.初始化模型和工具,定义并绑定工具到模型
# 初始化智谱模型
model = ChatOpenAI(
model="glm-4.7", #如果使用的火山方舟或者阿里云百炼,则对应修改,注意填写的是对应的模型编码
openai_api_key=os.getenv("ZHIPUAI_API_KEY"),
openai_api_base="https://open.bigmodel.cn/api/paas/v4/", #如果使用的火山方舟或者阿里云百炼,则对应修改
temperature=0,
).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
# 定义调用模型的函数
def call_model(state: MessagesState):
messages = state['messages']
response = model.invoke(messages)
return {"messages": [response]}
# 2.初始化图,定义一个新的状态图
workflow = StateGraph(MessagesState)
# 3.定义图节点,定义我们将循环的两个节点
workflow.add_node("agent", call_model)
workflow.add_node("tools", tool_node)
# 4.定义入口点和图边
# 设置入口点为agent
# 这意味着是第一个被调用的节点
workflow.set_entry_point("agent")
# 添加条件边
workflow.add_conditional_edges(
# 首先,定义起始节点,我们使用 “agent”
# 这意味着这些边是在调用 "agent "节点后采取的
"agent",
#接下来,传递决定下一个调用节点的函数
should_continue,
)
# 添加从"tools" 到"agent"的普通边
# 这意味着每次调用 "tools "节点后,都会调用 "agent "节点
workflow.add_edge("tools", "agent")
# 初始化内存以在图运行之前持久化状态
checkpointer = MemorySaver() #可以存redis或者是MongoDB
# 5.编译图
# 这将其编译成一个LangChain可运行对象
# 这意味着你可以像使用其他可运行对象一样使用它
# 注意,我们(可选的)在编译图时传递内存
app = workflow.compile(checkpointer=checkpointer) #做一个预检查
# 6.执行图,使用可运行对象
final_state = app.invoke(
{"messages":[HumanMessage(content="上海的天气怎么样?")]},
config={"configurable":{"thread_id":42}} #相同的线程id可以记录记忆
)
# 从final_state 中获取最后一条消息的内存
result = final_state["messages"][-1].content
print(result)
print("-----第二轮对话-----")
# 继续对话
final_state = app.invoke(
{"messages":[HumanMessage(content="我问的哪个城市")]},
config={"configurable":{"thread_id":42}}
)
result = final_state["messages"][-1].content
print(result)
#将生成的图片保存到文件(为了看到智能体的工作流图)后续附上
graph_png = app.get_graph().draw_mermaid_png()
with open("langgraph_base.png", "wb") as f:
f.write(graph_png)
程序输出
使用了两次对话,去测试记忆节点。(thread_id去控制,如果thread_id不相同,则没有记忆),针对小型项目,可以结合redis中去,存放数据库专门去存储这些数据,后续学习或有更好的处理方式
根据最新的天气信息,上海现在的天气情况是:
- **温度**:30度
- **天气状况**:有雾
天气比较温暖,不过有雾,出行时请注意交通安全,能见度可能较低。建议您根据这个天气情况合理安排出行和着装。
-----第二轮对话-----
您问的是上海这个城市。
注意事项
即使代码都一模一样,但是第二次回答却没有记忆的话,原因:
1)查看一下两次对话通过invoke发出时,设置的config的thread_id是否一致,不一致的话,会话不相同,则无记忆。
2)仅有可能是模型能力的问题,导致上下文丢失(作者出现过的问题:使用glm-4-flash这个模型,那么始终都无法得到正确的上下文对话,随后使用了glm-4.7或者是glm-4.6,最后得以解决。
更多推荐
所有评论(0)