使用langgraph创建工作流系列2:增加工具

        本文基于使用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获取搜索结果。

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值