
文章目录基础介绍简单案例基础介绍单一的LLM的只能通过提示词来生成答复内容自身不能执行任何行为相当于人的大脑仅限于思考与回答问题能力有限单一Agent将LLM Tools 组合不仅可以思考还可以通过工具调用完成某种行为相当于给大脑加上了手臂可以完成稍微复杂一点的任务ReAct agent 即 Reason and Act 推理一步执行一步再推理再执行流程来完成一个目标任务pip install -U langgraph 安装最新的版本简单案例importosfromlanggraph.graphimportStateGraph,MessagesState,START,ENDfromlanggraph.graph.messageimportadd_messagesfromtypingimportAnnotated,TypedDict,Listfromlangchain_core.messagesimportBaseMessage,AIMessage,HumanMessage,ToolMessagefromlangchain_openaiimportChatOpenAI# tool 装饰器fromlangchain_core.toolsimporttool,Toolfromlangchain_core.promptsimportChatPromptTemplate# 定义工具tool(description这是一个加法运算工具用于完成两个数值的相加)defadd(p1,p2): :param p1: :param p2: :return: p1p2 returnp1p2## prompt ChatPromptTemplate.from_messages([# (system, 你是一个数学科学家可以帮助用户进行数学计算),# (user, {question}) # 占位符字符串# ])# 创建LLM访问并关联工具llmChatOpenAI(# 环境变量中需要配置调用LLM的密钥base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1,modelqwen-plus,api_keyos.environ.get(OPENAI_API_KEY),temperature0.3,# 越大越具有创造性)tools[add]llm_with_toolsllm.bind_tools(toolstools)# llm_chain prompt | llm_with_tools# agent中的状态数据classMyState(TypedDict):# 同 MessageState# 各种消息的列表# Annotated 类型注解[类型 metadata, ...]messages:Annotated[List[BaseMessage],add_messages]# 在每个节点返回字典后langgraph底层通过metadata 更新字典# 若没有add_messages 元数据则会直接覆盖原始数据# LLM调用并返回数据defreason_llm(state:MyState):# state 表示状态数据messagesstate[messages]# 获取到所有的Message对象# 得到AIMessageresponsellm_with_tools.invoke(messages)# 返回一个MyState同结构的字典或者 key子集字典return{messages:[response]}deftool_call(state:MyState):# LLM 推理返回的文本中只是包含了需要调用的工具名称及参数# 并不会真正的自己去调用工具 只是将调用工具的逻辑封装了messagestate[messages][-1]ifhasattr(message,tool_calls)andmessage.tool_calls:# 说明需要调用工具# 这里实现调用工具的逻辑# [{name: add, args: {p1: 3, p2: 5}, id: call_c1daa4d2e4d74c4f85da5e, type: tool_call}]print(工具调用,message.tool_calls)cur_toolmessage.tool_calls[0]cur_tool_namecur_tool.get(name)cur_tool_argscur_tool.get(args)cur_tool_idcur_tool.get(id)else:...# 将工具调用的结果封装为ToolMessagemessageToolMessage(contenttool result,tool_call_idcur_tool_id)return{messages:[message]}defshould_exit(state:MyState):messagestate[messages][-1]ifhasattr(message,tool_calls)andmessage.tool_calls:returntoolreturnend# 创建状态图graphStateGraph(MyState)# 添加推理节点 (名称 函数)graph.add_node(reason_llm,reason_llm)# 添加工具节点graph.add_node(tool_call,tool_call)# 添加有向边graph.add_edge(START,reason_llm)graph.add_conditional_edges(reason_llm,should_exit,{tool:tool_call,end:END})graph.add_edge(tool_call,reason_llm)# 编译图graphgraph.compile()# 调用图并传入MyState 实例result_stategraph.invoke({messages:[(user,帮我计算35等于多少)]})# 从 end 节点中输出state对象 messages属性中包含了所有的Message对象print(result:,result_state)# ipynb中可以通过Ipython查看图# from IPython.display import Image, display# display(Image(graph.get_graph().draw_mermaid()))img_bytesgraph.get_graph().draw_png()# pip install pygraphviz 绘制图片返回字节数据withopen(ReAct-agent.png,wb)asf:f.write(img_bytes)