# pip install -U langgraph langsmith langchain_anthropic
from typing import Literal
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool
# from langchain_openai import BaseChatOpenAI
from langchain_openai.chat_models.base import BaseChatOpenAI
# 持久化状态
from langgraph.checkpoint.memory import MemorySaver
# 状态图和状态
from langgraph.graph import END, StateGraph, MessagesState
# 工具节点
from langgraph.prebuilt import ToolNode
@tool
def searchTool(query: str):
"""模拟一个搜索工具"""
if "上海" in query.lower() or "shanghai" in query.lower():
return "30度"
return "35度"
tools = [searchTool]
tool_node = ToolNode(tools)
model = BaseChatOpenAI(
model='qwen-plus',
openai_api_base='https://dashscope.aliyuncs.com/compatible-mode/v1',
max_tokens=1024,
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”
# 这意味着i一个别调用的第一个节点
workflow.set_entry_point("agent")
# 添加条件边
workflow.add_conditional_edges(
# 定义起始节点, 这意味着这些边是在调用 ‘agent’节点后采取的
"agent",
# 接下来 传递决定下一个调用节点的函数
should_continue
)
# 添加从 tools 到 agent的普通边 意味着在调用 tools 后接下来调用 agent节点
workflow.add_edge( "tools", "agent")
# 初始化内存以图运行之间的持久化状态
# 可以扩展 存redis MongoDB
checkpointer = MemorySaver()
# 5. 编译图
# 编译成一个langchain可运行的对象
# 这意味着你可以像运行其他对象一样使用它
# ps:我们在编译图时传递内存
app = workflow.compile(checkpointer=checkpointer)
# 6. 执行图
final_state = app.invoke({"messages":[HumanMessage(content="上海天气怎么样?")]}, config={"configurable": {"thread_id":42}})
# 从final_state 中获取最后一条消息内容
result = final_state["messages"][-1].content
print(result)
final_state = app.invoke({"messages":[HumanMessage(content="我问的哪个城市?")]}, config={"configurable": {"thread_id":42}})
# 从final_state 中获取最后一条消息内容
result = final_state["messages"][-1].content
print(result)
final_state = app.invoke({"messages":[HumanMessage(content="我问的哪个城市?")]}, config={"configurable": {"thread_id":41}})
# 从final_state 中获取最后一条消息内容
result = final_state["messages"][-1].content
print(result)
graph_png = app.get_graph().draw_mermaid_png()
with open("langraph_base.png", "wb") as f:
f.write(graph_png)
输出
上海的天气今天是30度。请注意,这只是一个示例回答,实际温度请以上海气象部门发布的实时天气信息为准。
您询问的是上海的天气情况。
您还没有提供相关信息,您可以告诉我一些关于这个城市的提示或者信息,例如它的名胜古迹、特色美食、地理位置等,这样我就可以帮助您确认是哪个城市了。