整体入门demo
教程概览
欢迎来到LangGraph教程! 这些笔记本通过构建各种语言代理和应用程序,介绍了如何使用LangGraph。
快速入门(Quick Start)
快速入门部分通过一个全面的入门教程,帮助您从零开始构建一个代理,学习LangGraph的基础知识。
-
- 内容简介: 在本教程中,您将使用LangGraph构建一个支持型聊天机器人(support chatbot)。
- 目标: 学习LangGraph的基本概念和操作,通过实际构建一个聊天机器人,掌握创建和管理语言代理的基本技能。
-
- 内容简介: 在本教程中,您将构建并部署一个代理到LangGraph Cloud。
- 目标: 学习如何在云端环境中部署和管理LangGraph代理,了解云部署的优势和操作步骤。
用例(Use cases)
用例部分通过具体的示例实现,展示了为特定场景设计的图结构和常见的设计模式。
聊天机器人(Chatbots)
-
- 内容简介: 构建一个客户支持聊天机器人,用于管理航班、酒店预订、租车等任务。
- 目标: 学习如何设计和实现一个多功能的客户支持系统,提高用户满意度和自动化水平。
-
根据用户需求生成提示(Prompt Generation from User Requirements):
- 内容简介: 构建一个信息收集型聊天机器人。
- 目标: 学习如何设计一个能够根据用户需求生成相关提示和问题的聊天机器人,提升信息收集效率。
-
- 内容简介: 构建一个代码分析和生成助手。
- 目标: 学习如何设计一个能够分析、调试和生成代码的智能助手,辅助开发者提高工作效率。
RAG(Retrieval-Augmented Generation)
-
- 内容简介: 使用代理在回答用户问题之前,检索最相关的信息。
- 目标: 学习如何结合信息检索和生成模型,提高回答的准确性和相关性。
-
- 内容简介: 自适应RAG是一种将查询分析与主动/自我纠正RAG相结合的策略。
- 实现链接: 论文链接
- 本地LLM版本: 使用本地LLM实现的自适应RAG。
-
- 内容简介: 使用LLM评估检索信息的质量,如果质量低,则尝试从其他来源检索信息。
- 实现链接: 论文链接
- 本地LLM版本: 使用本地LLM实现的纠正性RAG。
-
- 内容简介: 自我RAG是一种结合自我反思/自我评估对检索文档和生成内容进行优化的策略。
- 实现链接: 论文链接
- 本地LLM版本: 使用本地LLM实现的自我RAG。
-
- 内容简介: 构建一个能够回答关于SQL数据库问题的SQL代理。
- 目标: 学习如何设计一个能够与SQL数据库交互,执行查询并返回结果的智能代理。
代理架构(Agent Architectures)
-
多代理系统(Multi-Agent Systems):
- 网络(Network):
- 内容简介: 使两个或更多代理协作完成任务。
- 目标: 学习如何设计和实现多个代理之间的协作机制,提高任务执行的效率和复杂性处理能力。
- 监督者(Supervisor):
- 内容简介: 使用LLM来协调和委派任务给各个独立的代理。
- 目标: 学习如何设计一个监督者代理,负责管理和分配任务,提高系统的整体协调性。
- 层级团队(Hierarchical Teams):
- 内容简介: 协调嵌套团队的代理以解决问题。
- 目标: 学习如何设计层级化的代理团队,处理复杂问题,提升系统的组织和管理能力。
- 网络(Network):
-
规划代理(Planning Agents):
- 计划与执行(Plan-and-Execute):
- 内容简介: 实现一个基本的规划与执行代理。
- 目标: 学习如何设计一个能够制定计划并执行任务的代理,提高任务管理的系统性和效率。
- 无需观察的推理(Reasoning without Observation):
- 内容简介: 通过将观察结果保存为变量,减少重新规划的需求。
- 目标: 学习如何优化代理的推理过程,减少不必要的重新规划,提高系统的响应速度。
- LLMCompiler:
- 内容简介: 从计划器流式传输并提前执行DAG任务。
- 目标: 学习如何使用LLMCompiler,通过流式和提前执行任务来优化任务执行流程。
- 计划与执行(Plan-and-Execute):
反思与批评(Reflection & Critique)
-
- 内容简介: 提示代理对其输出进行反思和修正。
- 目标: 学习如何设计一个能够自我反思并改进输出的代理,提升系统的智能化水平。
-
- 内容简介: 批评缺失和多余的细节,以指导下一步行动。
- 目标: 学习如何通过自我评估,优化代理的决策过程和输出质量。
-
- 内容简介: 使用评分树搜索候选解决方案。
- 目标: 学习如何设计一个通过评分和搜索优化思维过程的代理,提高问题解决的准确性和效率。
-
语言代理树搜索(Language Agent Tree Search):
- 内容简介: 使用反思和奖励驱动蒙特卡洛树搜索。
- 目标: 学习如何结合反思机制和奖励系统,优化代理的决策路径,提高问题解决能力。
-
- 内容简介: 分析一个能够学习自身能力的代理。
- 目标: 学习如何设计一个具备自我学习和能力提升的智能代理,提高系统的自适应性和智能化水平。
评估(Evaluation)
-
基于代理的评估(Agent-based Evaluation):
- 内容简介: 通过模拟用户交互来评估聊天机器人。
- 目标: 学习如何设计和实施代理系统的评估方法,确保系统的有效性和用户满意度。
-
在LangSmith中的评估(In LangSmith Evaluation):
- 内容简介: 在LangSmith中使用对话数据集评估聊天机器人。
- 目标: 学习如何利用LangSmith平台进行系统化的评估和监控,提高系统的性能和稳定性。
实验性(Experimental)
-
- 内容简介: 通过研究和多视角问答生成类似维基百科的文章。
- 目标: 学习如何设计一个能够进行深入研究和多角度问答的代理系统,提升信息生成的多样性和准确性。
-
- 内容简介: 构建丰富、可解释的用户意图分类系统,使用微软为其Bing Copilot应用开发的分类系统。
- 目标: 学习如何设计一个能够精确分类和解释用户意图的代理系统,提高用户交互的智能化水平。
-
- 内容简介: 构建一个能够导航和交互网站的代理。
- 目标: 学习如何设计一个具备网页浏览和互动能力的代理系统,提高系统的实用性和用户体验。
-
竞赛编程(Competitive Programming):
- 内容简介: 构建一个具备少量“情景记忆”和人类参与协作的代理,解决美国计算机奥林匹克竞赛的问题;改编自Shi, Tang, Narasimhan和Yao的“语言模型能否解决奥林匹克编程问题?”论文。
- 目标: 学习如何设计一个具备记忆和协作能力的高级编程代理,提高系统在复杂问题解决中的表现。
-
复杂数据提取(Complex Data Extraction):
- 内容简介: 构建一个能够使用函数调用执行复杂提取任务的代理。
- 目标: 学习如何设计一个能够处理复杂数据提取需求的代理系统,提升系统的数据处理能力和灵活性。
plan_and_execute
当然!我很乐意为您详细讲解这个“Plan-and-Execute”示例代码。这个案例展示了如何使用LangGraph构建一个“计划和执行”风格的代理(Agent),该代理首先生成一个多步骤计划,然后逐步执行计划中的每个步骤。在执行过程中,如果有必要,可以重新规划。
这个示例受到了“Plan-and-Solve”论文和“Baby-AGI”项目的启发,其主要优势包括:
- 显式的长期规划:即使是强大的大型语言模型(LLMs)在长远规划上也可能遇到困难,通过显式的规划可以弥补这一不足。
- 模型效率:可以使用较小或较弱的模型来执行步骤,只在规划阶段使用更大或更好的模型。

目录
1. 环境设置
首先,需要安装所需的Python包:
%pip install --quiet -U langgraph langchain-community langchain-openai tavily-python
langgraph:用于构建可组合的代理系统。langchain-community:LangChain的社区扩展包,包含一些社区贡献的工具和功能。langchain-openai:用于与OpenAI的API交互。tavily-python:Tavily的Python客户端,用于搜索功能。
2. 设置API密钥
为了使用OpenAI的语言模型和Tavily的搜索工具,需要设置相应的API密钥。
import getpass
import os
def _set_env(var: str):
if not os.environ.get(var):
os.environ[var] = getpass.getpass(f"{
var}: ")
_set_env("OPENAI_API_KEY")
_set_env("TAVILY_API_KEY")
getpass.getpass:用于安全地输入密钥,防止在终端中显示。os.environ:将API密钥设置为环境变量,供后续代码使用。
3. 定义工具
在这个示例中,我们使用了一个内置的搜索工具 TavilySearchResults。您也可以根据需要创建自己的工具。
from langchain_community.tools.tavily_search import TavilySearchResults
tools = [TavilySearchResults(max_results=3)]
TavilySearchResults:一个搜索工具,用于获取搜索结果。max_results=3:指定返回的最大搜索结果数量。
4. 定义执行代理
现在,我们创建一个执行代理(Execution Agent),用于执行规划好的任务。在这个示例中,我们为每个任务使用相同的执行代理,但实际上您可以根据需要为不同的任务使用不同的代理。
from langchain import hub
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
# 获取要使用的提示模板 - 您可以根据需要修改它!
prompt = hub.pull("ih/ih-react-agent-executor")
prompt.pretty_print()
# 选择驱动代理的LLM
llm = ChatOpenAI(model="gpt-4-turbo-preview")
agent_executor = create_react_agent(llm, tools, state_modifier=prompt)
hub.pull("ih/ih-react-agent-executor"):从LangChain Hub中获取预定义的提示模板。prompt.pretty_print():打印提示模板的内容,便于查看和修改。ChatOpenAI:初始化OpenAI的聊天模型。model="gpt-4-turbo-preview":指定使用的模型版本。
create_react_agent:创建一个基于ReAct框架的代理。llm:语言模型,用于驱动代理的决策和生成。tools:代理可用的工具列表。state_modifier=prompt:使用自定义的提示模板。
5. 定义状态
接下来,我们定义代理需要跟踪的状态。这包括:
input:用户的初始输入。plan:当前的计划,表示为字符串列表。past_steps:之前执行的步骤,表示为元组列表,每个元组包含步骤和结果。response:最终的响应。
import operator
from typing import Annotated, List, Tuple
from typing_extensions import TypedDict
class PlanExecute(TypedDict):
input: str
plan: List[str]
past_steps: Annotated[List[Tuple], operator.add]
response: str
PlanExecute:定义了代理的状态结构,继承自TypedDict,用于类型提示。past_steps:使用Annotated和operator.add,表示在状态更新时,新的步骤会被添加到过去的步骤中。
6. 规划步骤
现在,我们创建规划步骤,用于生成一个多步骤的计划。这里,我们使用了函数调用(Function Calling)和 pydantic 的模型来定义结构化的输出。
from pydantic import BaseModel, Field
class Plan(BaseModel):
"""Plan to follow in future"""
steps: List[str] = Field(
description="different steps to follow, should be in sorted order"
)
from langchain_core.prompts import ChatPromptTemplate
planner_prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"""For the given objective, come up with a simple step by step plan. \
This plan should involve individual tasks, that if executed correctly will yield the correct answer. Do not add any superfluous steps. \
The result of the final step should be the final answer. Make sure that each step has all the information needed - do not skip steps.""",
),
("placeholder", "{messages}"),
]
)
planner = planner_prompt | ChatOpenAI(
model="gpt-4o", temperature=0
).with_structured_output(Plan)
Plan:一个pydantic模型,定义了计划的结构,包含一个字符串列表steps。planner_prompt:定义了规划的提示模板,包含系统消息和占位符。ChatPromptTemplate.from_messages:创建一个聊天提示模板,基于消息列表。planner:将提示模板与LLM组合,并指定输出的结构为Plan。- with_structured_output(Plan):将llm的输出结构化为Plan类定义的格式
示例调用:
planner.invoke(
{
"messages": [
("user", "what is the hometown of the current Australia open winner?")
]
}
)
输出:
Plan(steps=['Identify the current winner of the Australia Open.', 'Find the hometown of the identified winner.'])
7. 重新规划步骤
在执行过程中,我们可能需要根据之前的执行结果重新规划。为此,我们定义了重新规划的步骤。
from typing import Union# 用于定义一个类型可以是多种类型中的任意一种
# 定义agent对于用户的最终响应
class Response(BaseModel):
"""Response to user."""
# 存储agent最终要返回给用户的回答
response: str
# 用于定义agent在重新规划步骤中可能采取的行动
class Act(BaseModel):
"""Action to perform."""
# Union[Response, Plan] 表示 action 字段可以是 Response 或 Plan 类型之一
action: Union[Response, Plan] = Field(
# 提供字段的描述信息,解释何时使用 Response,何时使用 Plan
description="Action to perform. If you want to respond to user, use Response. "
"If you need to further use tools to get the answer, use Plan."
)
# Act 类用于在重新规划时决定智能体的下一步行动,既可以是直接回应用户,也可以是生成新的计划以继续执行任务
replanner_prompt = ChatPromptTemplate.from_template(
"""For the given objective, come up with a simple step by step plan. \
This plan should involve individual tasks, that if executed correctly will yield the correct answer. Do not add any superfluous steps. \
The result of the final step should be the final answer. Make sure that each step has all the information needed - do not skip steps.
Your objective was this:
{input}
Your original plan was this:
{plan}
You have currently done the follow steps:
{past_steps}
Update your plan accordingly. If no more steps are needed and you can return to the user, then respond with that. Otherwise, fill out the plan. Only add steps to the plan that still NEED to be done. Do not return previously done steps as part of the plan."""
)
replanner = replanner_prompt | ChatOpenAI(
model="gpt-4o", temperature=0
).with_structured_output(Act)
Response:定义了向用户响应的模型,包含一个字符串response。Act:定义了行动模型,包含一个action,可以是Response或Plan。replanner_prompt:定义了重新规划的提示模板,包含了当前的目标、原始计划和已执行的步骤。replanner:将重新规划的提示模板与LLM组合,并指定输出的结构为Act。
8. 创建计算图
现在,我们创建代理的计算图,定义了代理的执行流程。
from typing import Literal
from langgraph.graph import END
async def execute_step(state: PlanExecute):
plan = state["plan"]
plan_str = "\n".join(f"{
i+1}. {
step}" for i, step in enumerate(plan))
task = plan[0]
task_formatted = f"""For the following plan:
{
plan_str}\n\nYou are tasked with executing step {
1}, {
task}."""
agent_response = await agent_executor.ainvoke(
{
"messages": [("user", task_formatted)]}
)
return {
"past_steps": [(task, agent_response["messages"][-1].content)],
}
async def plan_step(state: PlanExecute):
plan = await planner.ainvoke({
"messages": [("user", state["input"])]})
return {
"plan": plan.steps}
async def replan_step(state: PlanExecute):
output = await replanner.ainvoke(state)
if isinstance(output.action, Response):
return {
"response": output.action.response}
else:
return {
"plan": output.action.steps}
def should_end(state: PlanExecute):
if "response" in state and state["response"]:
return END
else:
return "agent"
execute_step:执行计划中的一个步骤。- 从
state中获取当前的计划,执行第一个步骤,并将结果添加到past_steps。
- 从
plan_step:初始规划步骤。- 使用
planner根据用户输入生成计划。
- 使用
replan_step:重新规划步骤。- 使用
replanner根据当前状态(包括已执行的步骤)更新计划或生成最终响应。
- 使用
should_end:判断是否结束执行。- 如果
response存在且非空,则返回END,否则继续执行。
- 如果
创建计算图:
from langgraph.graph import StateGraph, START
workflow = StateGraph(PlanExecute)
# 添加节点
workflow.add_node("planner", plan_step)
workflow.add_node("agent", execute_step)
workflow.add_node("replan", replan_step)
# 定义边
workflow.add_edge(START, "planner")
workflow.add_edge("planner", "agent")
workflow.add_edge("agent", "replan")
workflow.add_conditional_edges(
"replan",
should_end,
["agent", END],
)
# 编译计算图
app = workflow.compile()
StateGraph:定义状态图,描述代理的执行流程。add_node:添加节点,关联到对应的函数。add_edge:添加边,定义节点之间的顺序。add_conditional_edges:添加条件边,根据状态决定下一个节点。compile:编译状态图,生成可执行的应用程序。
9. 运行代理
现在,我们可以运行代理,并观察其执行过程。
config = {
"recursion_limit": 50}
inputs = {
"input": "what is the hometown of the mens 2024 Australia open winner?"}
async for event in app.astream(inputs, config=config):
for k, v in event.items():
if k != "__end__":
print(v)
输出示例:
{'plan': ["Identify the winner of the men's 2024 Australian Open.", 'Research the hometown of the identified winner.']}
{'past_steps': [("Identify the winner of the men's 2024 Australian Open.", "The winner of the men's singles tennis title at the 2024 Australian Open was Jannik Sinner. He defeated Daniil Medvedev in the final with scores of 3-6, 3-6, 6-4, 6-4, 6-3 to win his first major singles title.")]}
{'plan': ['Research the hometown of Jannik Sinner.']}
{'past_steps': [('Research the hometown of Jannik Sinner.', "Jannik Sinner's hometown is Sexten, which is located in northern Italy.")]}
{'response': "The hometown of the men's 2024 Australian Open winner, Jannik Sinner, is Sexten, located in northern Italy."}
- 第一步:生成计划,包含两个步骤:
- 确定2024年澳大利亚网球公开赛男子冠军。
- 调查该冠军的家乡。
- 第二步:执行第一个步骤,获取冠军的信息。
- 第三步:重新规划,因为第一个步骤已完成,更新计划,只剩下第二个步骤。
- 第四步:执行第二个步骤,获取冠军的家乡信息。
- 第五步:完成所有步骤,生成最终的响应。
10. 总结
通过这个示例,我们创建了一个“计划和执行”风格的代理,能够:
- 生成多步骤的计划:利用强大的语言模型来规划任务。
- 逐步执行计划:按顺序执行每个步骤,并跟踪执行结果。
- 动态重新规划:根据执行结果,动态更新计划,确保任务能够顺利完成。
- 结构化的状态管理:利用
TypedDict和pydantic模型,清晰地定义和管理代理的状态。
优点
- 显式的长期规划:能够有效处理需要多步骤解决的问题。
- 模型效率:在执行阶段,可以使用较小的模型,只在规划阶段使用更强大的模型。
可能的改进
- 并行执行:当前的设计是顺序执行,如果任务之间没有依赖关系,可以考虑并行执行以提高效率。
- 更复杂的规划:可以将计划表示为有向无环图(DAG),以处理更复杂的任务依赖关系。
附加说明
- LangGraph:一个用于构建可组合代理系统的框架,允许您定义代理的执行流程和状态管理。
- LangChain:一个用于构建语言模型应用的库,提供了工具、链和代理等组件。
汇总
当然!以下是将上述LangGraph“计划并执行”智能体入门案例汇总到一个完整的Python脚本中的示例。所有的提示词(prompts)都已翻译成中文,以便您更好地理解和学习。
请按照以下步骤操作:
-
安装必要的包:确保您已经安装了所需的Python包。您可以在命令行中运行以下命令来安装:
pip install -U langgraph langchain-community langchain-openai tavily-python pydantic typing_extensions -
设置API密钥:在运行脚本之前,请确保您已经拥有OpenAI和Tavily的API密钥。
-
运行脚本:将以下代码保存为
plan_and_execute_agent.py,然后在终端中运行:python plan_and_execute_agent.py
以下是完整的Python脚本内容:
# plan_and_execute_agent.py
import os
import getpass
import operator
import asyncio
from typing import Annotated, List, Tuple, Union
from typing_extensions import TypedDict
from pydantic import BaseModel, Field
from langchain import hub
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.prompts import ChatPromptTemplate
from langgraph.prebuilt import create_react_agent
from langgraph.graph import StateGraph, START, END
from dotenv import load_dotenv
# 导入 ChatTongyi 模型
from langchain_community.chat_models.tongyi import ChatTongyi
# 加载 .env 文件
load_dotenv()
# 读取环境变量
api_key = os.getenv("DASHSCOPE_API_KEY")
if not api_key:
raise ValueError("API Key not found in .env file.")
# 初始化 LLM(ChatTongyi)
llm = ChatTongyi(model='qwen-plus')
# ----------------------------------
# 定义工具
# ----------------------------------
# 使用Tavily的内置搜索工具,最多返回3个结果
tools = [TavilySearchResults(max_results=3)]
# ----------------------------------
# 定义执行智能体
# ----------------------------------
# 获取执行智能体的提示模板
prompt = hub.pull("ih/ih-react-agent-executor")
print("预定义prompt:\n"+str(prompt))
prompt.pretty_print()
# 创建ReAct风格的智能体执行器
agent_executor = create_react_agent(llm, tools, state_modifier=prompt)
# ----------------------------------
# 定义状态
# ----------------------------------
class PlanExecute(TypedDict):
input: str # 用户输入的原始请求
plan: List[str] # 一个列表,包含生成的计划步骤
past_steps: Annotated[List

最低0.47元/天 解锁文章
738

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



