【AI Agent系列】【LangGraph】2. 再进阶:给你的LangGraph加入循环逻辑(Cycles)

简介: 【AI Agent系列】【LangGraph】2. 再进阶:给你的LangGraph加入循环逻辑(Cycles)
  • 大家好,我是同学小张,日常分享AI知识和实战案例
  • 欢迎 点赞 + 关注 👏,持续学习持续干货输出
  • 一起交流💬,一起进步💪。
  • 微信公众号也可搜【同学小张】 🙏

本站文章一览:


今天我们继续学习 LangGraph 的基础内容。前面两篇文章我们学习了 LangGraph 的基本用法条件分支,本文继续学习如何利用 LangGraph 实现一个环(循环)结构。

0. 完整代码

0.1 完整代码

还是先上完整代码,Demo代码参考这里

from langchain_community.tools.tavily_search import TavilySearchResults
tools = [TavilySearchResults(max_results=1)]
from langgraph.prebuilt import ToolExecutor
tool_executor = ToolExecutor(tools)
from langchain_openai import ChatOpenAI
# We will set streaming=True so that we can stream tokens
# See the streaming section for more information on this.
model = ChatOpenAI(temperature=0)
from langchain.tools.render import format_tool_to_openai_function
functions = [format_tool_to_openai_function(t) for t in tools]
model = model.bind_functions(functions)
from typing import TypedDict, Annotated, Sequence
import operator
from langchain_core.messages import BaseMessage
class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], operator.add]
    
from langgraph.prebuilt import ToolInvocation
import json
from langchain_core.messages import FunctionMessage
# Define the function that determines whether to continue or not
def should_continue(state):
    messages = state['messages']
    last_message = messages[-1]
    # If there is no function call, then we finish
    if "function_call" not in last_message.additional_kwargs:
        return "end"
    # Otherwise if there is, we continue
    else:
        return "continue"
# Define the function that calls the model
def call_model(state):
    messages = state['messages']
    response = model.invoke(messages)
    # We return a list, because this will get added to the existing list
    return {"messages": [response]}
# Define the function to execute tools
def call_tool(state):
    messages = state['messages']
    # Based on the continue condition
    # we know the last message involves a function call
    last_message = messages[-1]
    # We construct an ToolInvocation from the function_call
    action = ToolInvocation(
        tool=last_message.additional_kwargs["function_call"]["name"],
        tool_input=json.loads(last_message.additional_kwargs["function_call"]["arguments"]),
    )
    # We call the tool_executor and get back a response
    response = tool_executor.invoke(action)
    # We use the response to create a FunctionMessage
    function_message = FunctionMessage(content=str(response), name=action.tool)
    # We return a list, because this will get added to the existing list
    return {"messages": [function_message]}
from langgraph.graph import StateGraph, END
# Define a new graph
workflow = StateGraph(AgentState)
# Define the two nodes we will cycle between
workflow.add_node("agent", call_model)
workflow.add_node("action", call_tool)
# Set the entrypoint as `agent`
# This means that this node is the first one called
workflow.set_entry_point("agent")
# We now add a conditional edge
workflow.add_conditional_edges(
    # First, we define the start node. We use `agent`.
    # This means these are the edges taken after the `agent` node is called.
    "agent",
    # Next, we pass in the function that will determine which node is called next.
    should_continue,
    # Finally we pass in a mapping.
    # The keys are strings, and the values are other nodes.
    # END is a special node marking that the graph should finish.
    # What will happen is we will call `should_continue`, and then the output of that
    # will be matched against the keys in this mapping.
    # Based on which one it matches, that node will then be called.
    {
        # If `tools`, then we call the tool node.
        "continue": "action",
        # Otherwise we finish.
        "end": END
    }
)
# We now add a normal edge from `tools` to `agent`.
# This means that after `tools` is called, `agent` node is called next.
workflow.add_edge('action', 'agent')
# Finally, we compile it!
# This compiles it into a LangChain Runnable,
# meaning you can use it as you would any other runnable
app = workflow.compile()
from langchain_core.messages import HumanMessage
inputs = {"messages": [HumanMessage(content="what is the weather in sf")]}
response = app.invoke(inputs)
print(response)

0.2 运行前准备

官方给出的这个Demo程序,需要用到 Tavily API 的key。

需要大家去 这个地方 去自行申请一个。

申请完后,记得将该 API key 添加到你的环境变量中。

TAVILY_API_KEY = "tvly-xxxxxxxxxxx"

1. 代码详解

1.1 创建图 - StateGraph

首先是实例化一个 Graph,与前面用的 Graph 不同,前面用的是 MessageGraph,现在这个例子中用的是 StateGraph

from langgraph.graph import StateGraph, END
# Define a new graph
workflow = StateGraph(AgentState)

MessageGraphStateGraph 好像也没什么太大的区别:

1.2 添加节点 - node

# Define the two nodes we will cycle between
workflow.add_node("agent", call_model)
workflow.add_node("action", call_tool)

添加了两个节点:

  • 初始节点 agent,用来调用大模型
  • 节点 action,用来执行工具

1.3 添加边

# We now add a conditional edge
workflow.add_conditional_edges(
    "agent",
    should_continue,
    {
        # If `tools`, then we call the tool node.
        "continue": "action",
        "end": END
    }
)
workflow.add_edge('action', 'agent')

添加了一个条件边,一个普通边。

现在这个图结构应该是这样的:

看一下条件边的条件:should_continue

def should_continue(state):
    messages = state['messages']
    last_message = messages[-1]
    # If there is no function call, then we finish
    if "function_call" not in last_message.additional_kwargs:
        return "end"
    # Otherwise if there is, we continue
    else:
        return "continue"

就是判断是否有工具需要执行,如果有,则走 agent —> action 方向,如果没有,则走 agent —> END 方向。

1.4 总结

所以到这里,结构的实现已经比较清晰了,对比上一篇文章条件分支的代码,其实最主要变化的是这一句:

workflow.add_edge('action', 'agent')

由原来的 action —> END,变成了 action —> agent。

另外,还有一个要注意的点:

def call_model(state):
    messages = state['messages']
    response = model.invoke(messages)
    # We return a list, because this will get added to the existing list
    return {"messages": [response]}

在 model.invoke 时,注意 invoke 参数类型,messages = state['messages'],不是传state类型,而是里面的 messages 类型,也就是HumanMessageAIMessage等类型。

如果觉得本文对你有帮助,麻烦点个赞和关注呗 ~~~


  • 大家好,我是 同学小张,日常分享AI知识和实战案例
  • 欢迎 点赞 + 关注 👏,持续学习持续干货输出
  • 一起交流💬,一起进步💪。
  • 微信公众号也可搜【同学小张】 🙏

本站文章一览:

相关文章
|
6月前
|
机器学习/深度学习 人工智能 自动驾驶
跳出循环:当AI不再是“模仿”,而是“思考”
跳出循环:当AI不再是“模仿”,而是“思考”
229 94
|
6月前
|
机器学习/深度学习 数据采集 人工智能
从ChatGPT到文心一言:AI为什么能“懂人话”?——大语言模型的底层逻辑揭秘
从ChatGPT到文心一言:AI为什么能“懂人话”?——大语言模型的底层逻辑揭秘
833 9
|
6月前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
6883 94
|
7月前
|
存储 人工智能 测试技术
手把手带你入门AI智能体:从核心概念到第一个能跑的Agent
AI智能体是一种能感知环境、自主决策并执行任务的人工智能系统。它不仅能生成回应,还可通过工具使用、计划制定和记忆管理完成复杂工作,如自动化测试、脚本编写、缺陷分析等。核心包括大语言模型(LLM)、任务规划、工具调用和记忆系统。通过实践可逐步构建高效智能体,提升软件测试效率与质量。
|
6月前
|
人工智能 搜索推荐 数据可视化
当AI学会“使用工具”:智能体(Agent)如何重塑人机交互
当AI学会“使用工具”:智能体(Agent)如何重塑人机交互
667 115
|
6月前
|
人工智能 自然语言处理 安全
从工具到伙伴:AI代理(Agent)是下一场革命
从工具到伙伴:AI代理(Agent)是下一场革命
743 117
|
6月前
|
人工智能 定位技术 API
智能体(Agent):AI不再只是聊天,而是能替你干活
智能体(Agent):AI不再只是聊天,而是能替你干活
1193 99
|
6月前
|
人工智能 缓存 运维
【智造】AI应用实战:6个agent搞定复杂指令和工具膨胀
本文介绍联调造数场景下的AI应用演进:从单Agent模式到多Agent协同的架构升级。针对复杂指令执行不准、响应慢等问题,通过意图识别、工具引擎、推理执行等多Agent分工协作,结合工程化手段提升准确性与效率,并分享了关键设计思路与实践心得。
982 20
【智造】AI应用实战:6个agent搞定复杂指令和工具膨胀
|
人工智能 Cloud Native 搜索推荐
【2025云栖大会】阿里云AI搜索年度发布:开启Agent时代,重构搜索新范式
2025云栖大会阿里云AI搜索专场上,发布了年度AI搜索技术与产品升级成果,推出Agentic Search架构创新与云原生引擎技术突破,实现从“信息匹配”到“智能问题解决”的跨越,支持多模态检索、百亿向量处理,助力企业降本增效,推动搜索迈向主动服务新时代。
697 0

热门文章

最新文章