本文基于使用langgraph创建工作流系列1:一个简单的chatbot中创建的chatbot增加一个搜索工具。仍使用免费的 taily搜索API。
1.安装tavily的包
#pip install -U langchain-tavily
2.设置tavily秘钥
import os os.environ["TAVILY_API_KEY"] = "tvly-..."
3.增加工具定义
from langchain_tavily import TavilySearch
tool = TavilySearch(max_results=2)#保留前两个搜索结果
tool.invoke("大模型混合专家详解")
搜索结果如下:
{'query': '大模型混合专家详解',
'follow_up_questions': None,
'answer': None,
'images': [],
'results': [{'url': 'https://www.wehelpwin.com/m_article/4858',
'title': '大模型的研究新方向:混合专家模型(MoE) - AI魔法学院',
'content': '混合专家模型(MoE)是一种稀疏门控制的深度学习模型,它主要由一组专家模型和一个门控模型组成。MoE的基本理念是将输入数据根据任务类型分割成多个区域,并将',
'score': 0.8091708,
'raw_content': None},
{'url': 'https://blog.youkuaiyun.com/u012856866/article/details/145967289',
'title': '【大模型】图解混合专家模型(Mixed Expert Models, MoEs) 转载',
'content': '混合专家(Mixture of Experts,简称MoE)模型,是一种利用多个不同的子模型(或“专家”)来提升大语言模型(LLM)质量的技术。 ... MoE模型的主要组成部分包括:.',
'score': 0.80698997,
'raw_content': None}],
'response_time': 0.92,
'request_id': '241bc091-4734-4c03-ab7f-3e785e9318aa'}
4.大模型绑定工具
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model = 'qwen-plus',
api_key = "sk-……",
base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1")tools = [tool]
llm_with_tools = llm.bind_tools(tools)
5.定义工作流图
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
class State(TypedDict):
messages: Annotated[list, add_messages]
graph_builder = StateGraph(State)
6.定义chatbot节点并增加到工作流图中
def chatbot(state: State):
return {"messages": [llm_with_tools.invoke(state["messages"])]}
graph_builder.add_node("chatbot", chatbot)
7.定义工具调用节点并增加到工作流图中
该节点根据大模型的function calling结果进行函数调用
import json
from langchain_core.messages import ToolMessage
class BasicToolNode:
def __init__(self, tools: list) -> None:
#tools_by_name属性是 k=工具名,v=工具的字典
self.tools_by_name = {tool.name: tool for tool in tools}
def __call__(self, inputs: dict):
if messages := inputs.get("messages", []):
message = messages[-1]#获取大模型应答
else: raise ValueError("No message found in input")
outputs = []
for tool_call in message.tool_calls:#遍历大模型应答中的tool_calls
#调用tool_calls中的工具
tool_result = self.tools_by_name[tool_call["name"]].invoke( tool_call["args"] )
#用工具名、工具id和调用工具的结果组成ToolMessage并增加到ouputs列表中
outputs.append( ToolMessage( content=json.dumps(tool_result),
name=tool_call["name"], tool_call_id=tool_call["id"], ) )
return {"messages": outputs}
tool_node = BasicToolNode(tools=[tool])
graph_builder.add_node("tools", tool_node)#把该节点增加到工作流图中
8.定义“条件边”
在langgraph中,“边”是有向的,用来说明控制流程的流转,也就控制流从一个节点流到另一个节点。
一般情况下一条“边”连接两个节点,“边”的起点是控制流当前所在节点,“边”的终点控制流流向节点。
“条件边”连接三个及以上的节点,只有一个起点,多个终点。根据处理状态确定控制流流向哪个节点。
下面的方法tool_route就是一个“条件边”,具体如下:
def route_tools(
state: State,
):
"""
作为条件边,如果大模型应答中有function calling信息,则流向ToolNode节点,否则流向END节点。
"""
if isinstance(state, list):
ai_message = state[-1]
elif messages := state.get("messages", []):
ai_message = messages[-1]
else:
raise ValueError(f"No messages found in input state to tool_edge: {state}")
if hasattr(ai_message, "tool_calls") and len(ai_message.tool_calls) > 0:
return "tools"
return END
9.用“边”连接节点
'''
在工作流图中增加“条件边”。第一个参数是控制流当前所在节点,第二参数前面定义的“条件边”对应的函数,第三个参数是所有可能的目的节点
'''
graph_builder.add_conditional_edges( "chatbot", route_tools, {"tools": "tools", END: END},)
#设置从'tools'——>‘chatbot’的边
graph_builder.add_edge("tools", "chatbot")
#设置从START——>'chatbot'的边
graph_builder.add_edge(START, "chatbot")
graph = graph_builder.compile()
10.可视化状态图
from IPython.display import Image, display
try:
display(Image(graph.get_graph().draw_mermaid_png()))
except Exception:
pass
状态图如下图:

解读上图:
1.图中共有四个节点__start__对应START,__end__对应END
2.程序启动后控制流从START进入chatbot节点
3.离开chatbot节点,有两个可能的目的节点,一个节点为tools,另一个节点为END。这就是条件边的作用
4.在tools节点完成处理后要回到chatbot节点
5.进入END节点后,处理结束
11.运行带工具的chatbot
以下代码与使用langgraph创建工作流系列1:一个简单的chatbot-优快云博客中的代码完全相同。
def stream_graph_updates(user_input: str):
for event in graph.stream({"messages": [{"role": "user", "content": user_input}]}):
for value in event.values():
#从state的messages列表中取最后一项
print("Assistant:", value["messages"][-1].content)
while True:
try: user_input = input("User: ")
if user_input.lower() in ["quit", "exit", "q"]:
print("Goodbye!")
break
stream_graph_updates(user_input)
except:
user_input = "What do you know about LangGraph?"
print("User: " + user_input)
stream_graph_updates(user_input)
break
12.与chatbot对话
问以下美国现任总统是谁:),显然chatbot调用了搜索工具tavily获取搜索结果。

3909

被折叠的 条评论
为什么被折叠?



