1. LangGraph进阶:构建ReACT架构的智能Agent 1.1 引言 在人工智能和大语言模型(LLM)快速发展的今天,如何构建高效、灵活的智能Agent成为了一个热门话题。LangGraph作为一个强大的工具,为我们提供了一种新的方式来实现复杂的AI工作流,特别是在构建ReACT(Reasoning and Acting)架构的智能Agent方面表现出色。本文将深入探讨如何使用LangGraph来实现ReACT架构,并提供详细的代码示例和解释。
1.2 LangGraph的基本概念 LangGraph是一个用于构建基于LLM的应用程序的Python框架。它的核心理念是将复杂的AI工作流程表示为一个状态图,其中包含节点、边和数据状态。这种方法使得我们可以更直观地设计和实现智能Agent的行为逻辑。
在LangGraph中,我们可以使用基础组件(节点、边、数据状态)来构建Agent,这也是LangGraph自由度高的一个重要优点。同时,LangGraph还提供了一些预构建的代理,如ReACT智能体和工具调用智能体,使得我们可以更快速地创建智能Agent。
1.3 ReACT架构简介 ReACT(Reasoning and Acting)是一种智能Agent架构,它结合了推理和行动的能力。在ReACT架构中,Agent通过不断地思考(Reasoning)、采取行动(Acting)和观察结果(Observing)来解决问题。这种方法使得Agent能够更灵活地应对复杂的任务,并且可以利用外部工具来增强其能力。
使用LangGraph实现ReACT架构 现在,让我们通过一个具体的例子来看看如何使用LangGraph实现ReACT架构的智能Agent。
1.3.1 环境设置 首先,我们需要导入必要的库和模块:
1 2 3 4 5 6 7 8 9 10 11 12 import dotenvfrom langchain_community.tools import GoogleSerperRunfrom langchain_community.tools.openai_dalle_image_generation import OpenAIDALLEImageGenerationToolfrom langchain_community.utilities import GoogleSerperAPIWrapperfrom langchain_community.utilities.dalle_image_generator import DallEAPIWrapperfrom langchain_core.pydantic_v1 import BaseModel, Fieldfrom langchain_openai import ChatOpenAIfrom langgraph.prebuilt.chat_agent_executor import create_react_agentdotenv.load_dotenv()
1.3.2 定义工具和参数模式 接下来,我们定义了两个工具:Google搜索和DALL-E图像生成。同时,我们也为这些工具定义了参数模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class GoogleSerperArgsSchema (BaseModel ): query: str = Field(description="执行谷歌搜索的查询语句" ) class DallEArgsSchema (BaseModel ): query: str = Field(description="输入应该是生成图像的文本提示(prompt)" ) google_serper = GoogleSerperRun( name="google_serper" , description=( "一个低成本的谷歌搜索API。" "当你需要回答有关时事的问题时,可以调用该工具。" "该工具的输入是搜索查询语句。" ), args_schema=GoogleSerperArgsSchema, api_wrapper=GoogleSerperAPIWrapper(), ) dalle = OpenAIDALLEImageGenerationTool( name="openai_dalle" , api_wrapper=DallEAPIWrapper(model="dall-e-3" ), args_schema=DallEArgsSchema, ) tools = [google_serper, dalle]
1.3.3 创建语言模型 我们使用OpenAI的GPT-4模型作为我们的大语言模型:
1 model = ChatOpenAI(model="gpt-4o-mini" , temperature=0 )
1.3.4 使用预构建函数创建ReACT智能体 LangGraph提供了预构建的函数来创建ReACT智能体,使用起来非常简单:
1 2 3 4 agent = create_react_agent( model=model, tools=tools )
1.3.5 调用智能体并输出内容 最后,我们可以调用我们创建的智能体,并打印输出结果:
1 print (agent.invoke({"messages" : [("human" , "帮我绘制一幅鲨鱼在天上飞的图片" )]}))
1.3.6 运行结果分析 当我们运行这段代码时,智能体会首先理解任务需求,然后决定使用DALL-E工具来生成图像。它会生成一个详细的图像描述,然后调用DALL-E API来创建图像。最后,它会返回生成的图像URL,并提供一个简短的描述。
输出内容可能如下所示:
1 2 3 4 5 {'messages' : [HumanMessage(content='帮我绘制一幅鲨鱼在天上飞的图片' ), AIMessage(content='' , additional_kwargs={'tool_calls' : [...]}), ToolMessage(content='https://dalleproduse.blob.core.windows.net/...' ), AIMessage(content='这是您请求的画面:一只鲨鱼在天上飞翔的图片。您可以点击下面的链接查看这幅图。\n\n' )] }
1.4 总结 通过这个例子,我们可以看到LangGraph如何简化了ReACT架构智能Agent的构建过程。它提供了高级抽象和预构建组件,使得我们可以快速实现复杂的AI工作流。同时,LangGraph的灵活性也允许我们根据需要自定义和扩展Agent的功能。
需要注意的是,LangGraph仍在快速发展中。例如,当前版本(截至文章撰写时)的预构建ReACT智能体是基于函数调用实现的,并且在0.3.0版本中可能会被移除。因此,在使用LangGraph时,建议关注其最新的文档和更新。
尽管如此,LangGraph的核心设计理念和封装思路仍然非常值得学习和借鉴。随着AI技术的不断进步,我们可以期待LangGraph在未来会提供更多强大和易用的功能,进一步简化智能Agent的开发过程。
2. LangGraph高级技巧:图结构应用程序删除消息的使用技巧 2.1 消息删除的重要性 在图结构应用中,消息的累积可能会导致性能问题和不必要的复杂性。因此,适时删除不再需要的消息是很有必要的。LangGraph提供了几种方法来实现这一目标。
2.2 使用delete_messages函数 LangGraph提供了delete_messages函数,它可以根据指定的条件删除消息。这个函数可以在图的节点中使用,特别是在处理完某些消息后。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from langgraph.prebuilt import ToolMessagedef process_and_delete (state ): state = delete_messages(state, lambda x: isinstance (x, ToolMessage)) return state graph = Graph() graph.add_node("process_and_delete" , process_and_delete)
2.3 消息过滤技巧 除了直接删除消息,我们还可以使用过滤技巧来控制消息的流动:
2.3.1 使用条件边 1 2 3 4 5 graph.add_conditional_edge( "node_a" , "node_b" , condition=lambda x: not isinstance (x, ToolMessage) )
2.3.2 在节点函数中进行过滤 1 2 3 4 5 def filter_messages (state ): filtered_messages = [msg for msg in state['messages' ] if not isinstance (msg, ToolMessage)] return {"messages" : filtered_messages} graph.add_node("filter" , filter_messages)
2.4 消息修剪策略 在长时间运行的应用中,可能需要定期修剪消息以保持性能:
2.4.1 基于时间的修剪 1 2 3 4 5 6 7 8 9 10 11 from datetime import datetime, timedeltadef prune_old_messages (state ): current_time = datetime.now() recent_messages = [ msg for msg in state['messages' ] if current_time - msg.timestamp < timedelta(hours=1 ) ] return {"messages" : recent_messages} graph.add_node("prune" , prune_old_messages)
2.4.2 基于数量的修剪 1 2 3 4 def keep_latest_messages (state, max_messages=50 ): return {"messages" : state['messages' ][-max_messages:]} graph.add_node("prune" , lambda s: keep_latest_messages(s, max_messages=100 ))
2.5 实际应用案例:智能客服系统 考虑一个智能客服系统,它需要处理用户查询,但同时要保持对话的简洁性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from langgraph.prebuilt import ToolMessage, HumanMessagedef process_query (state ): return state def summarize_and_prune (state ): summary = summarize_conversation(state['messages' ]) new_messages = [msg for msg in state['messages' ] if isinstance (msg, HumanMessage)][-3 :] new_messages.append(ToolMessage(content=summary)) return {"messages" : new_messages} graph = Graph() graph.add_node("process_query" , process_query) graph.add_node("summarize_and_prune" , summarize_and_prune) graph.add_edge("process_query" , "summarize_and_prune" ) graph.add_edge("summarize_and_prune" , "process_query" )
2.6 总结 通过合理使用LangGraph提供的消息删除和过滤功能,我们可以有效地管理图结构应用中的消息流。这不仅可以提高应用的性能,还能使对话更加清晰和有针对性。在实际应用中,根据具体需求选择适当的消息管理策略至关重要。
3. LangGraph中的检查点与人机交互 3.1 LangGraph的检查点机制 检查点机制是LangGraph中一个强大的功能,它允许我们在图执行的特定点暂停处理,保存状态,并在需要时恢复。
3.1.1 检查点的基本概念 检查点本质上是图执行过程中的一个快照,包含了当前的状态信息。这对于长时间运行的任务、需要人工干预的流程,或者需要断点续传的应用特别有用。
3.1.2 创建检查点 在LangGraph中,我们可以使用create_checkpoint函数来创建检查点:
1 2 3 4 5 6 7 8 9 10 11 from langgraph.checkpoint import create_checkpointdef process_with_checkpoint (state ): checkpoint = create_checkpoint(state) return {"checkpoint" : checkpoint, "state" : state} graph.add_node("process" , process_with_checkpoint)
3.1.3 恢复检查点 使用load_checkpoint函数可以恢复之前保存的检查点:
1 2 3 4 5 6 7 8 9 from langgraph.checkpoint import load_checkpointdef resume_from_checkpoint (checkpoint ): state = load_checkpoint(checkpoint) return state graph.add_node("resume" , resume_from_checkpoint)
3.2 实现人在环路(Human-in-the-loop)交互 人在环路交互是指在AI系统的执行过程中,允许人类参与并提供输入或做出决策。LangGraph提供了灵活的机制来实现这种交互。
3.2.1 使用回调函数实现人机交互 我们可以在图的节点中定义回调函数,用于获取人类输入:
1 2 3 4 5 6 7 8 9 10 11 12 def human_input_node (state ): print ("Current state:" , state) user_input = input ("Please provide your input: " ) state['user_input' ] = user_input return state graph.add_node("human_input" , human_input_node)
3.2.2 条件分支实现人机交互 我们可以使用条件分支来决定是否需要人类干预:
1 2 3 4 5 6 7 8 9 10 11 12 13 def check_confidence (state ): if state['confidence' ] < 0.8 : return "human_input" else : return "auto_process" graph.add_conditional_edges( "check_confidence" , { "human_input" : lambda s: s['confidence' ] < 0.8 , "auto_process" : lambda s: s['confidence' ] >= 0.8 } )
3.3 实际应用案例:智能客服系统升级版 让我们将检查点机制和人机交互结合到之前的智能客服系统中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 from langgraph.prebuilt import ToolMessage, HumanMessagefrom langgraph.checkpoint import create_checkpoint, load_checkpointdef process_query (state ): state['confidence' ] = calculate_confidence(state) return state def human_intervention (state ): print ("Current conversation:" , state['messages' ]) human_response = input ("Please provide assistance: " ) state['messages' ].append(HumanMessage(content=human_response)) return state def summarize_and_prune (state ): summary = summarize_conversation(state['messages' ]) new_messages = state['messages' ][-5 :] new_messages.append(ToolMessage(content=summary)) state['messages' ] = new_messages checkpoint = create_checkpoint(state) state['checkpoint' ] = checkpoint return state graph = Graph() graph.add_node("process_query" , process_query) graph.add_node("human_intervention" , human_intervention) graph.add_node("summarize_and_prune" , summarize_and_prune) graph.add_conditional_edges( "process_query" , { "human_intervention" : lambda s: s['confidence' ] < 0.8 , "summarize_and_prune" : lambda s: s['confidence' ] >= 0.8 } ) graph.add_edge("human_intervention" , "summarize_and_prune" ) graph.add_edge("summarize_and_prune" , "process_query" )
在这个升级版的智能客服系统中,我们引入了以下改进:
根据置信度决定是否需要人工干预。
在每次总结和修剪后创建检查点,以便在需要时恢复状态。
人工干预节点允许人类直接参与对话。
3.4 总结 LangGraph的检查点机制和人机交互功能为构建复杂、可靠的AI系统提供了强大的工具。通过合理使用这些功能,我们可以创建更加智能、灵活且可控的应用程序。检查点允许我们在长时间运行的任务中保存和恢复状态,而人机交互则为AI决策过程引入了人类的判断和专业知识。在实际应用中,这些功能的结合可以显著提高系统的性能和可靠性。
4. 使用LangGraph构建复杂AI工作流:子图架构详解 4.1 子图架构概述 子图(Subgraph)是LangGraph中一个强大的特性,它允许我们将复杂的工作流程分解成更小、更易管理的组件。通过子图,我们可以实现模块化设计,提高代码的可重用性和可维护性。
4.1.1 子图的基本概念 子图本质上是一个完整的图结构,可以作为更大图结构中的一个节点使用。它具有以下特点:
1 2 3 4 5 6 7 8 9 10 11 from langgraph.graph import SubGraph, Graphclass MarketingSubGraph (SubGraph ): def __init__ (self ): super ().__init__() def build (self ) -> Graph: graph = Graph() return graph
4.1.2 子图的优势
模块化:将复杂逻辑封装在独立的子图中
可重用性:子图可以在不同的主图中重复使用
可维护性:更容易进行测试和调试
扩展性:便于添加新功能和修改现有功能
4.2 子图的实现方法 4.2.1 创建基本子图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class ContentGenerationSubGraph (SubGraph ): def build (self ) -> Graph: graph = Graph() graph.add_node("generate_content" , self.generate_content) graph.add_node("review_content" , self.review_content) graph.add_edge("generate_content" , "review_content" ) return graph def generate_content (self, state ): return state def review_content (self, state ): return state
4.2.2 子图的状态管理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class AnalyticsSubGraph (SubGraph ): def build (self ) -> Graph: graph = Graph() def process_analytics (state ): if 'metrics' not in state: state['metrics' ] = {} state['metrics' ]['engagement' ] = calculate_engagement(state) return state graph.add_node("analytics" , process_analytics) return graph
4.3 子图的组合与交互 4.3.1 在主图中使用子图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def create_marketing_workflow (): main_graph = Graph() content_graph = ContentGenerationSubGraph() analytics_graph = AnalyticsSubGraph() main_graph.add_node("content" , content_graph) main_graph.add_node("analytics" , analytics_graph) main_graph.add_edge("content" , "analytics" ) return main_graph
4.3.2 子图间的数据传递 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class DataProcessingSubGraph (SubGraph ): def build (self ) -> Graph: graph = Graph() def prepare_data (state ): state['processed_data' ] = { 'content_type' : state['raw_data' ]['type' ], 'metrics' : state['raw_data' ]['metrics' ], 'timestamp' : datetime.now() } return state graph.add_node("prepare" , prepare_data) return graph
4.4 实际案例:营销智能体实现 让我们通过一个完整的营销智能体案例来展示子图的实际应用:
4.4.1 内容生成子图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class ContentCreationSubGraph (SubGraph ): def build (self ) -> Graph: graph = Graph() def generate_content (state ): prompt = f""" Target Audience: {state['audience' ]} Platform: {state['platform' ]} Campaign Goal: {state['goal' ]} """ content = generate_with_llm(prompt) state['generated_content' ] = content return state def optimize_content (state ): optimized = optimize_for_platform( state['generated_content' ], state['platform' ] ) state['final_content' ] = optimized return state graph.add_node("generate" , generate_content) graph.add_node("optimize" , optimize_content) graph.add_edge("generate" , "optimize" ) return graph
4.4.2 分析子图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class AnalyticsSubGraph (SubGraph ): def build (self ) -> Graph: graph = Graph() def analyze_performance (state ): metrics = calculate_metrics(state['final_content' ]) state['analytics' ] = { 'engagement_score' : metrics['engagement' ], 'reach_prediction' : metrics['reach' ], 'conversion_estimate' : metrics['conversion' ] } return state def generate_recommendations (state ): recommendations = generate_improvements( state['analytics' ], state['goal' ] ) state['recommendations' ] = recommendations return state graph.add_node("analyze" , analyze_performance) graph.add_node("recommend" , generate_recommendations) graph.add_edge("analyze" , "recommend" ) return graph
4.4.3 主工作流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 def create_marketing_agent (): main_graph = Graph() content_graph = ContentCreationSubGraph() analytics_graph = AnalyticsSubGraph() def setup_campaign (state ): if 'config' not in state: state['config' ] = { 'audience' : state.get('audience' , 'general' ), 'platform' : state.get('platform' , 'twitter' ), 'goal' : state.get('goal' , 'engagement' ) } return state main_graph.add_node("setup" , setup_campaign) main_graph.add_node("content" , content_graph) main_graph.add_node("analytics" , analytics_graph) main_graph.add_edge("setup" , "content" ) main_graph.add_edge("content" , "analytics" ) return main_graph
4.5 最佳实践与注意事项 4.5.1 子图设计原则:
保持子图功能单一
确保清晰的输入输出接口
适当处理状态传递
4.5.2 性能考虑:
避免子图间频繁的大数据传输
合理设计状态存储结构
考虑异步处理需求
4.5.3 错误处理:
在子图内部实现错误处理
提供清晰的错误信息
确保状态一致性
4.6 总结 LangGraph的子图架构为构建复杂AI工作流提供了强大而灵活的解决方案。通过合理使用子图,我们可以将复杂的任务分解为可管理的模块,提高代码的可维护性和可重用性。在实际应用中,子图不仅简化了开发过程,还为扩展和优化系统提供了便利。营销智能体的案例展示了如何在实践中运用这些概念,构建出功能强大、结构清晰的AI应用。