虚行 發表於 2025-12-8 14:16:00

405-LangGraph Reflexion 智能体案例分析 - 详解

<style>pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; line-height: 1.6 !important; padding: 16px !important; margin: 16px 0 !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; tab-size: 4 !important; -moz-tab-size: 4 !important; max-width: 100% !important; box-sizing: border-box !important }
code { font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; overflow-wrap: normal !important; display: inline !important; background: rgba(0, 0, 0, 0) !important; border: none !important; padding: 0 !important; margin: 0 !important; line-height: inherit !important }
pre code { background: rgba(0, 0, 0, 0) !important; border: 0 !important; border-radius: 0 !important; display: block !important; line-height: 1.6 !important; margin: 0 !important; max-width: none !important; overflow: visible !important; padding: 0 !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; color: inherit !important }
.token.comment, .token.prolog, .token.doctype, .token.cdata { color: rgba(112, 128, 144, 1) !important; font-style: italic !important }
.token.punctuation { color: rgba(153, 153, 153, 1) !important }
.token.atrule, .token.attr-value, .token.keyword { color: rgba(0, 119, 170, 1) !important; font-weight: bold !important }
.token.function, .token.class-name { color: rgba(221, 74, 104, 1) !important; font-weight: bold !important }
.token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.inserted { color: rgba(102, 153, 0, 1) !important }
.token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted { color: rgba(153, 0, 85, 1) !important }
.cnblogs-markdown pre, .cnblogs-post-body pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; padding: 16px !important; margin: 16px 0 !important }
pre, pre, pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important }</style>
      <div class="htmledit_views atom-one-dark" id="content_views"><p><img alt="" height="648" src="https://i-blog.csdnimg.cn/direct/3b8462eea704442a9dad10fc0ce05c6e.png" width="1123"></p><p>本案例分析了使用LangGraph实现的Reflexion(反思)AI智能体,该智能体能够通过自我反思和修订来提高回答质量,展示了LangGraph在构建复杂AI工作流方面的强大能力。</p><h3>1. 案例目标</h3><p>本案例的主要目标是构建一个能够自我反思和改进的AI智能体,具体包括:</p><ol><li><strong>实现Reflexion机制</strong>:构建一个能够生成初始回答、反思回答质量、并基于反思修订回答的智能体。</li><li><strong>集成外部工具</strong>:将Tavily搜索工具集成到智能体中,使其能够获取最新信息来支持回答。</li><li><strong>构建状态图工作流</strong>:使用LangGraph的StateGraph构建包含多个节点的复杂工作流,实现智能体的自主决策和执行。</li><li><strong>演示迭代改进过程</strong>:通过气候危机问题的回答示例,展示智能体如何通过多次迭代逐步提高回答质量。</li></ol><h3>2. 技术栈与核心依赖</h3><ul><li><strong>LangGraph</strong>:用于构建智能体的状态图和工作流,是本案例的核心框架。</li><li><strong>LangChain</strong>:提供大模型交互、工具调用等基础功能。</li><li><strong>LangChain Anthropic</strong>:提供与Anthropic的Claude模型集成的功能。</li><li><strong>Tavily Python</strong>:提供网络搜索功能,作为智能体的外部工具。</li><li><strong>Pydantic</strong>:用于定义数据模型和验证。</li></ul><p>在代码中,通过以下方式引入核心依赖:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code># 安装依赖
%pip install -U langgraph langchain_anthropic tavily-python
# 导入核心模块
from langgraph.graph import END, StateGraph, START
from langchain_anthropic import ChatAnthropic
from langchain_core.tools import tool
from langchain_core.messages import HumanMessage
from tavily import TavilyClient
from typing import Annotated, List
from langchain_core.pydantic_v1 import BaseModel, Field</code></pre>
<h3>3. 环境配置</h3><p>在运行本案例前,需要配置以下环境变量:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code># 设置Anthropic API密钥
import os
os.environ["ANTHROPIC_API_KEY"] = "your-api-key-here"
# 设置Tavily API密钥
os.environ["TAVILY_API_KEY"] = "your-tavily-api-key-here"</code></pre>
<p><strong>重要提示</strong>:请将上述API密钥替换为您从Anthropic和Tavily获取的有效密钥。这些密钥用于访问大模型和搜索服务。</p><h3>4. 案例实现</h3><h4>4.1 数据模型定义</h4><p>首先定义了两个Pydantic模型,用于结构化智能体的状态和输出:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code>class Reflection(BaseModel):
    missing: str = Field(description="回答中缺失的关键信息")
    superfluous: str = Field(description="回答中的冗余信息")
class AnswerQuestion(BaseModel):
    """回答用户问题的工具"""
    answer: str = Field(description="用户的回答")
    reflection: Reflection = Field(description="对回答的反思")
    search_queries: List = Field(
      default_factory=list,
      description="可能需要搜索的查询,以获取更多信息"
    )</code></pre>
<h4>4.2 响应生成器</h4><p>实现了一个带重试机制的响应生成器,用于生成和验证回答:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code>class ResponderWithRetries:
    def __init__(self, runnable, validator):
      self.runnable = runnable
      self.validator = validator
    def respond(self, state: list):
      response = []
      for attempt in range(3):
            response = self.runnable.invoke(
                {"messages": state}, {"tags": }
            )
            try:
                self.validator.invoke(response)
                return response
            except Exception as e:
                print(f"尝试 {attempt + 1} 失败: {e}")
      return response</code></pre>
<h4>4.3 初始响应器</h4><p>创建初始响应器,用于生成对用户问题的初步回答:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code>actor_prompt_template = ChatPromptTemplate.from_messages([
    ("system",
   "你是一个专家级的AI助手,擅长提供深思熟虑的回答。"
   "你将根据以下步骤回答用户问题:\n"
   "1. 首先,提供对问题的初步回答。\n"
   "2. 然后,反思你的回答,仔细考虑是否有任何遗漏或冗余信息。\n"
   "3. 最后,返回最终答案。\n\n"
   "请使用以下格式返回答案:\n"
   "```json\n"
   "{{\n"
   "\"answer\": \"你的回答\",\n"
   "\"reflection\": {{\n"
   "    \"missing\": \"回答中缺失的关键信息\",\n"
   "    \"superfluous\": \"回答中的冗余信息\"\n"
   "}},\n"
   "\"search_queries\": [\"可能需要搜索的查询\"]\n"
   "}}\n"
   "```"
    ),
    ("placeholder", "{messages}"),
])
initial_answer_chain = actor_prompt_template | bound.with_structured_output(
    AnswerQuestion
)
actor = ResponderWithRetries(
    runnable=initial_answer_chain,
    validator=AnswerQuestion,
)</code></pre>
<h4>4.4 修订响应器</h4><p>创建修订响应器,用于基于反思和搜索结果修订回答:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code>revision_prompt_template = ChatPromptTemplate.from_messages([
    ("system",
   "你是一个专家级的AI修订助手,擅长改进回答。\n"
   "你将根据以下步骤修订用户的回答:\n"
   "1. 首先,分析原始回答和反思。\n"
   "2. 然后,考虑搜索结果提供的新信息。\n"
   "3. 最后,返回修订后的回答。\n\n"
   "请使用以下格式返回修订后的答案:\n"
   "```json\n"
   "{{\n"
   "\"answer\": \"修订后的回答\",\n"
   "\"reflection\": {{\n"
   "    \"missing\": \"修订后回答中仍然缺失的关键信息\",\n"
   "    \"superfluous\": \"修订后回答中的冗余信息\"\n"
   "}},\n"
   "\"search_queries\": [\"可能需要进一步搜索的查询\"]\n"
   "}}\n"
   "```"
    ),
    ("placeholder", "{messages}"),
])
revision_chain = revision_prompt_template | bound.with_structured_output(
    AnswerQuestion
)
revisor = ResponderWithRetries(
    runnable=revision_chain,
    validator=AnswerQuestion,
)</code></pre>
<h4>4.5 工具节点</h4><p>创建工具节点,用于执行搜索查询:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code>@tool
def tavily_search(query: str) -&gt; str:
    """使用Tavily进行网络搜索"""
    tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])
    results = tavily_client.search(query=query, max_results=5)
    return str(results)
tools =
tool_node = ToolNode(tools)</code></pre>
<h4>4.6 构建状态图</h4><p>使用LangGraph的StateGraph构建智能体的工作流:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code>builder = StateGraph(list)
# 添加节点
builder.add_node("draft", actor.respond)# 生成初始回答
builder.add_node("execute_tools", tool_node)# 执行搜索
builder.add_node("revise", revisor.respond)# 修订回答
# 添加边
builder.add_edge(START, "draft")
builder.add_edge("draft", "execute_tools")
builder.add_edge("execute_tools", "revise")
# 添加条件边
def should_continue(state):
    messages = state[-1]
    if hasattr(messages, 'tool_calls') and messages.tool_calls:
      return "execute_tools"
    else:
      return END
builder.add_conditional_edges("revise", should_continue)
# 构建图
graph = builder.compile()</code></pre>
<h3>5. 案例效果</h3><p>通过向智能体提问"我们应该如何处理气候危机?",我们可以观察到以下效果:</p><h4>5.1 初始回答(Step 0-1)</h4><p>智能体首先生成一个关于气候危机的初步回答,包括政策措施、技术创新、行为改变和自然解决方案等方面,并指出回答中可能缺失的信息和冗余内容。</p><h4>5.2 搜索执行(Step 2)</h4><p>基于反思中识别的缺失信息,智能体生成搜索查询并执行搜索,获取关于气候政策、清洁能源技术、自然解决方案和适应策略的最新信息。</p><h4>5.3 回答修订(Step 3-7)</h4><p>智能体基于搜索结果多次修订回答,逐步完善内容,增加具体细节,提高回答的全面性和准确性。最终回答涵盖了:</p><ul><li>政策措施:碳定价、排放法规、清洁能源激励和国际协议</li><li>技术突破:能源存储、碳捕获、可持续燃料、氢能和工业脱碳</li><li>挑战分析:化石燃料利益、政治僵局、经济转型困难、全球治理问题和融资需求</li><li>自然解决方案:森林保护、重新造林和沿海恢复,可提供高达30%的减排量</li><li>适应措施:弹性基础设施、预警系统和气候智能农业</li></ul><h4>5.4 最终效果</h4><p>通过多次迭代和反思,智能体的回答从一般性的概述发展为全面、深入、有据可依的分析,展示了Reflexion机制在提高AI回答质量方面的有效性。</p><h3>6. 案例实现思路</h3><h4>6.1 Reflexion机制</h4><p>本案例的核心是Reflexion(反思)机制,其实现思路如下:</p><ol><li><strong>生成-反思-修订循环</strong>:智能体首先生成初步回答,然后反思回答的质量和完整性,最后基于反思修订回答。</li><li><strong>结构化反思</strong>:使用Pydantic模型定义反思的结构,包括缺失信息和冗余信息,使反思过程更加系统化。</li><li><strong>外部信息获取</strong>:当反思发现信息不足时,智能体主动搜索相关信息,为修订提供依据。</li><li><strong>迭代改进</strong>:通过多次生成-反思-修订循环,逐步提高回答质量。</li></ol><h4>6.2 状态图工作流</h4><p>使用LangGraph的StateGraph构建工作流的实现思路:</p><ol><li><strong>节点定义</strong>:将工作流分解为不同的功能节点,如draft(生成草稿)、execute_tools(执行工具)和revise(修订)。</li><li><strong>状态管理</strong>:通过共享状态(消息列表)在节点间传递信息,实现数据的流动和共享。</li><li><strong>条件路由</strong>:根据当前状态决定下一步的流向,实现动态的工作流控制。</li><li><strong>工具集成</strong>:将外部工具(如搜索)作为节点集成到工作流中,扩展智能体的能力。</li></ol><h4>6.3 错误处理与重试</h4><p>实现健壮性的思路:</p><ol><li><strong>重试机制</strong>:在响应生成器中实现重试机制,当生成的内容不符合要求时自动重试。</li><li><strong>验证机制</strong>:使用Pydantic模型验证生成的内容,确保符合预期格式。</li><li><strong>错误处理</strong>:捕获和处理可能的异常,避免智能体因错误而中断。</li></ol><h3>7. 扩展建议</h3><h4>7.1 功能扩展</h4><ul><li><strong>多轮对话支持</strong>:扩展智能体以支持多轮对话,记住之前的交互历史,提供连贯的对话体验。</li><li><strong>更多工具集成</strong>:集成更多外部工具,如计算器、代码解释器、数据库查询等,扩展智能体的能力范围。</li><li><strong>个性化调整</strong>:根据用户偏好和历史交互,调整回答的风格和深度,提供个性化的服务。</li><li><strong>多语言支持</strong>:扩展智能体以支持多种语言,满足不同语言用户的需求。</li></ul><h4>7.2 性能优化</h4><ul><li><strong>并行搜索</strong>:实现并行搜索多个查询,减少等待时间,提高效率。</li><li><strong>缓存机制</strong>:添加缓存层,存储常见问题的回答和搜索结果,减少重复计算和API调用。</li><li><strong>智能终止条件</strong>:优化终止条件,当回答质量达到一定阈值或改进幅度小于某个值时提前终止迭代,避免不必要的计算。</li><li><strong>异步处理</strong>:使用异步处理提高并发性能,特别是在处理多个用户请求时。</li></ul><h4>7.3 应用场景扩展</h4><ul><li><strong>内容创作助手</strong>:将Reflexion机制应用于内容创作,如文章写作、代码生成等,通过迭代改进提高内容质量。</li><li><strong>教育辅导系统</strong>:构建智能教育辅导系统,通过反思和改进提供个性化的学习指导。</li><li><strong>决策支持系统</strong>:应用于复杂决策场景,如商业决策、医疗诊断等,通过多轮反思提供更全面的决策支持。</li><li><strong>研究助手</strong>:构建科研助手,帮助研究人员收集和分析信息,生成研究报告。</li></ul><h4>7.4 技术架构扩展</h4><ul><li><strong>分布式架构</strong>:将智能体扩展为分布式架构,支持水平扩展和高可用性。</li><li><strong>微服务化</strong>:将不同功能模块拆分为微服务,提高系统的灵活性和可维护性。</li><li><strong>向量数据库集成</strong>:集成向量数据库,实现语义搜索和知识检索,增强智能体的知识能力。</li><li><strong>监控与分析</strong>:添加监控和分析功能,跟踪智能体的性能和用户反馈,持续优化系统。</li></ul><h3>8. 总结</h3><p>本案例展示了如何使用LangGraph构建一个具有Reflexion(反思)机制的AI智能体。通过生成-反思-修订的循环工作流,智能体能够逐步提高回答质量,提供更全面、准确和有据可依的回答。</p><p>案例的核心价值在于:</p><ul><li><strong>提高回答质量</strong>:通过反思和修订机制,智能体能够识别并弥补回答中的不足,显著提高回答质量。</li><li><strong>增强信息获取能力</strong>:集成外部搜索工具,使智能体能够获取最新信息,保持回答的时效性和准确性。</li><li><strong>展示LangGraph的强大能力</strong>:通过状态图工作流,展示了LangGraph在构建复杂AI系统方面的强大能力。</li><li><strong>提供可扩展的架构</strong>:模块化设计使系统易于扩展,可以集成更多工具和功能,适应不同应用场景。</li></ul><p>尽管本案例在提高回答质量方面取得了显著成效,但仍有一些可以改进的地方,如优化迭代效率、增强多轮对话能力、扩展应用场景等。通过持续优化和扩展,这种基于Reflexion机制的智能体有望在更多领域发挥重要作用,为用户提供更高质量的AI服务。</p></div><br><br>
来源:https://www.cnblogs.com/clnchanpin/p/19321569
頁: [1]
查看完整版本: 405-LangGraph Reflexion 智能体案例分析 - 详解