第六章:主流 Agent 开发框架实战 (一):LangChain 与 LlamaIndex

引言

经过前五章对 AI Agent 核心概念、架构、执行逻辑、高级工具以及智能策略的深入探讨,我们已经打下了坚实的理论基础。现在,是时候将理论付诸实践,进入激动人心的框架实战环节了!理论是灯塔,而框架则是我们航向目标的船只。本章,我们将聚焦于当前 Python 生态中最主流、应用最广泛的两大 Agent 开发框架:LangChainLlamaIndex。我们将学习如何利用这两个强大的框架,快速构建、配置和运行我们自己的 AI Agent,并通过具体的代码示例理解它们各自的设计哲学与核心优势。掌握它们,是你将 Agent 应用从想法变为现实的关键一步。
第六章:主流 Agent 开发框架实战 (一):LangChain 与 LlamaIndex_第1张图片

6.1 LangChain Agents:构建灵活的 Agent 应用

LangChain 以其灵活性、高度模块化和广泛的集成能力而闻名。它提供了一套丰富的组件和工具链,让开发者可以像搭积木一样自由地构建复杂的 LLM 应用,其中 Agent 是其核心功能之一。

  • 核心 API 与概念详解:
    在使用 LangChain 构建 Agent 时,你会经常遇到以下核心组件:

    • Tool: 这是对 Agent 可用功能的抽象封装(对应第四章的工具概念)。你需要为 Agent 定义一系列工具,每个工具包含名称、描述(供 LLM 理解何时使用)、以及具体的执行函数。
    • Memory: 用于让 Agent 维持状态和记忆(对应第二章的记忆模块)。LangChain 提供了多种 Memory 类型,如 ConversationBufferMemory 等。
    • PromptTemplate/ChatPromptTemplate: 用于精确控制发送给 LLM 的指令,指导 Agent 如何思考、使用工具和格式化输出。
    • LLM/ChatModel: Agent 的核心大脑,如 OpenAI GPT-4, Anthropic Claude 等。
    • AgentExecutor: LangChain Agent 的核心执行器,负责驱动 Agent 的运行逻辑(例如执行第三章讨论的 ReAct 循环)。
    • initialize_agent: 快速初始化 AgentExecutor 的便捷函数(较旧的 API,现在更推荐使用 LCEL 或 create_react_agent 等方式)。
  • Agent 类型概览:
    LangChain 提供了一些预置的 Agent 类型,如 zero-shot-react-description, conversational-react-description 等,方便快速启动。

  • 定制 Agent 实践:
    常见的定制包括修改 Prompt、添加自定义工具、自定义输出解析,以及集成图数据库工具(如将 Cypher 查询封装为 Tool)。

  • 实战代码演练:构建一个简单的 LangChain ReAct Agent

    • 目标/场景: 下面的代码将演示如何使用 LangChain 构建一个简单的 ReAct Agent。这个 Agent 会拥有一个计算数字平方的工具,并能调用它来回答问题。

    • 前提条件:

      • 你需要安装 LangChain 核心库以及与你选择的 LLM 相关的库(示例中使用 OpenAI):pip install langchain langchain-openai
      • 你需要拥有一个 OpenAI API Key,并将其设置为环境变量 OPENAI_API_KEY
      • 注意: LangChain 版本迭代较快,具体 API 可能略有变化,请参考你所使用版本的官方文档。
    • 关键代码示例:

      import os
      from langchain_openai import ChatOpenAI
      from langchain.agents import tool, AgentExecutor, create_react_agent
      from langchain_core.prompts import PromptTemplate # 或者 ChatPromptTemplate
      from langchain import hub # 用于获取预置的 ReAct prompt
      
      # --- 前提:设置 OpenAI API Key ---
      # 确保你的 OpenAI API Key 已经设置在环境变量中
      # os.environ["OPENAI_API_KEY"] = "sk-..." 
      # 如果没有设置,后续创建 LLM 时会报错
      
      # --- 1. 定义工具 ---
      @tool
      def get_square(number: float) -> float:
        """当需要计算一个数字的平方时,使用此工具。输入一个数字,返回它的平方值。"""
        print(f"\n*** 调用 get_square 工具,输入: {number} ***\n")
        return number ** 2
      
      tools = [get_square]
      
      # --- 2. 选择 LLM ---
      # 使用 OpenAI 的 GPT-3.5 Turbo 模型
      # temperature=0 表示我们希望得到更确定性的输出
      llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
      
      # --- 3. 获取 ReAct Prompt 模板 ---
      # 从 LangChain Hub 拉取一个预置的 ReAct prompt,它定义了 Agent 的思考和行动格式
      # 这是 LangChain 推荐的方式之一,简化了 Prompt 工程
      prompt = hub.pull("hwchase17/react")
      # 你可以通过 print(prompt.template) 查看模板内容
      
      # --- 4. 创建 Agent 核心逻辑 ---
      # create_react_agent 函数将 LLM、工具列表和 Prompt 模板组合起来
      # 它定义了 Agent 如何根据输入和工具描述来决定下一步行动
      agent = create_react_agent(llm, tools, prompt)
      
      # --- 5. 创建 Agent 执行器 ---
      # AgentExecutor 负责实际运行 ReAct 循环:
      # 调用 Agent 获取下一步行动 -> 执行行动(调用工具)-> 获取结果 -> 重复
      # verbose=True 会打印出 Agent 的完整思考过程(Thought, Action, Observation)
      agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True)
      # handle_parsing_errors=True 可以帮助处理 LLM 输出格式偶尔不规范的问题
      
      # --- 6. 运行 Agent ---
      print("\n--- 运行 Agent ---")
      try:
          response = agent_executor.invoke({
              "input": "计算 5 的平方是多少?"
          })
          print("\n--- Agent 执行完毕 ---")
          print("最终答案:")
          print(response['output'])
      except Exception as e:
          print(f"Agent 执行出错: {e}")
      
      # 思考:如果问 "法国的首都是哪里?" Agent 会怎么做?(它没有相关工具)
      # 尝试运行: agent_executor.invoke({"input": "法国的首都是哪里?"})
      
    • 代码解释:

      • 我们首先导入必要的库并定义了一个简单的 get_square 工具,注意其 docstring 对 Agent 理解工具功能至关重要。
      • 选择了 gpt-3.5-turbo 作为 LLM。
      • 从 LangChain Hub 获取了一个标准的 ReAct prompt 模板。
      • 使用 create_react_agent 创建了 Agent 的核心逻辑。
      • 创建了 AgentExecutor 来运行 Agent,并设置 verbose=True 以观察其内部思考过程。
      • 最后,通过 invoke 方法传入问题来运行 Agent。
    • 观察重点: 运行代码时,仔细观察 verbose=True 打印出的 Thought:, Action:, Observation: 序列。你会看到 Agent 如何分析问题,决定需要计算平方,选择 get_square 工具,指定输入参数,然后根据工具返回的 Observation(计算结果)得出最终答案。尝试问一个它没有工具能回答的问题,观察它的反应。

6.2 LlamaIndex Agents:以数据为中心的 Agent 构建

LlamaIndex 最初以其在数据索引和检索增强生成 (RAG) 方面的强大能力而闻名。它的 Agent 构建思路也深受其数据处理核心的影响,呈现出以数据为中心的特色。

  • 核心概念与设计哲学:

    • Query Engines as Tools: 这是 LlamaIndex Agent 最具特色的地方。它允许你将 LlamaIndex 强大的数据索引(Index)和查询引擎(Query Engine)——无论是基于向量、关键词,还是我们特别关注的知识图谱——直接封装成 Agent 可以调用的工具这正是第四章工具概念的一种强大实现)。
    • AgentRunner / ReActAgent 等: LlamaIndex 提供了类似 LangChain AgentExecutor 的执行器类。
    • 与 LangChain 对比: LlamaIndex 更侧重于围绕数据索引进行构建,其 Agent 的核心优势在于能够智能地利用其强大的数据查询能力作为工具。
  • 知识图谱集成(重点):
    LlamaIndex 对知识图谱提供了优秀的原生支持:

    • 可以使用 KnowledgeGraphIndex 从文档中自动构建知识图谱(提取实体和关系)。
    • 可以将构建好的 KG 索引转换成一个查询引擎,并直接作为工具提供给 Agent 使用。
  • 实战代码演练:构建一个使用 KG 索引工具的 LlamaIndex Agent

    • 目标/场景: 下面的代码将演示如何使用 LlamaIndex 构建一个简单的知识图谱索引,并将其作为工具提供给一个 ReAct Agent,用于回答基于图谱知识的问题。

    • 前提条件:

      • 你需要安装 LlamaIndex 核心库及相关依赖(示例中使用 OpenAI):pip install llama-index llama-index-llms-openai
      • 你需要拥有一个 OpenAI API Key,并将其设置为环境变量 OPENAI_API_KEY
      • 注意: LlamaIndex 同样版本迭代较快,API 可能有变化,请参考官方文档。
    • 关键代码示例:

      import os
      from llama_index.core import SimpleDirectoryReader, KnowledgeGraphIndex, Settings
      from llama_index.core.graph_stores import SimpleGraphStore # 使用内存中的简单图存储
      from llama_index.core.storage.storage_context import StorageContext
      from llama_index.llms.openai import OpenAI # 使用 OpenAI LLM
      from llama_index.embeddings.openai import OpenAIEmbedding # 使用 OpenAI Embedding
      from llama_index.core.agent import ReActAgent
      from llama_index.core.tools import QueryEngineTool, ToolMetadata
      
      # --- 前提:设置 OpenAI API Key ---
      # os.environ["OPENAI_API_KEY"] = "sk-..."
      
      # --- 1. 配置 LLM 和 Embedding ---
      # LlamaIndex 使用 Settings 来全局配置 LLM 和 Embedding
      Settings.llm = OpenAI(model="gpt-3.5-turbo")
      Settings.embed_model = OpenAIEmbedding(model="text-embedding-ada-002")
      
      # --- 2. 准备简单数据 ---
      # 为了演示,我们创建一些简单的文本数据,LlamaIndex 将从中提取实体关系
      # 实际应用中可以使用 SimpleDirectoryReader 读取文件
      from llama_index.core import Document
      documents = [
          Document(text="张三是北京智科公司的软件工程师。"),
          Document(text="李四是北京智科公司的项目经理,他认识张三。"),
          Document(text="北京智科公司位于中关村软件园。")
      ]
      print("\n--- 准备演示数据 ---")
      for doc in documents:
          print(doc.text)
      
      # --- 3. 构建知识图谱索引 ---
      # 使用内存存储 (SimpleGraphStore)
      graph_store = SimpleGraphStore()
      storage_context = StorageContext.from_defaults(graph_store=graph_store)
      
      print("\n--- 开始构建知识图谱索引 (可能需要一点时间) ---")
      # 从文档中构建 KG 索引,max_triplets_per_chunk 控制提取三元组的数量
      # include_embeddings=True 允许后续进行混合查询(如果需要)
      index = KnowledgeGraphIndex.from_documents(
          documents,
          max_triplets_per_chunk=5,
          storage_context=storage_context,
          include_embeddings=True,
      )
      print("--- 知识图谱索引构建完成 ---")
      
      # --- 4. 创建 KG 查询引擎并封装为工具 ---
      # 将 KG 索引转换为查询引擎
      kg_query_engine = index.as_query_engine(
          include_text=False, # 通常 KG 查询我们更关心结构化结果
          response_mode="tree_summarize" # 可以尝试不同的响应模式
      )
      
      # 创建 QueryEngineTool,让 Agent 可以使用这个 KG 查询引擎
      kg_tool = QueryEngineTool(
          query_engine=kg_query_engine,
          metadata=ToolMetadata(
              name="knowledge_graph_query",
              description=(
                  "当需要查询人物、组织、地点之间的关系或属性时使用。"
                  "例如,查询某人的职位、某公司位于何处、某人认识谁等。"
                  "输入应该是针对这些实体和关系的自然语言问题。"
              )
          )
      )
      tools = [kg_tool]
      print("\n--- KG 查询工具已创建 ---")
      print(f"工具名称: {kg_tool.metadata.name}")
      print(f"工具描述: {kg_tool.metadata.description}")
      
      # --- 5. 创建 LlamaIndex ReAct Agent ---
      # 使用配置好的 LLM 和 KG 工具创建 Agent
      agent = ReActAgent.from_tools(tools=tools, llm=Settings.llm, verbose=True)
      print("\n--- LlamaIndex ReAct Agent 已创建 ---")
      
      # --- 6. 运行 Agent ---
      print("\n--- 运行 Agent 查询 KG ---")
      try:
          # 提问需要利用图谱关系的问题
          response = agent.chat("李四在北京智科公司的职位是什么?他在公司认识谁?")
          # 也可以尝试: agent.chat("北京智科公司在哪里?")
          print("\n--- Agent 执行完毕 ---")
          print("最终答案:")
          print(str(response)) # Agent 的响应通常是 Response 对象,转为字符串打印
      
          # 对比直接查询 KG 索引 (如果需要)
          # direct_response = kg_query_engine.query("李四在北京智科公司的职位是什么?他在公司认识谁?")
          # print("\n直接查询 KG 引擎结果:")
          # print(str(direct_response))
      except Exception as e:
          print(f"Agent 执行出错: {e}")
      
    • 代码解释:

      • 我们首先配置了全局的 LLM 和 Embedding 模型(LlamaIndex 推荐方式)。
      • 创建了简单的文本 Document 对象作为数据源。
      • 使用 KnowledgeGraphIndex.from_documents 从这些文档中自动提取三元组,构建了一个内存中的知识图谱索引。
      • 将这个 KG 索引转换为 QueryEngine,它封装了查询图谱的能力。
      • 使用 QueryEngineTool 将这个查询引擎包装成 Agent 可用的工具,并提供了清晰的描述。
      • 创建了一个 LlamaIndex 的 ReActAgent,并将 KG 工具传递给它。
      • 最后,通过 agent.chat() 方法向 Agent 提问,问题需要利用我们构建的 KG 中的关系才能回答。
    • 观察重点: 运行代码时,注意观察 verbose=True 输出的 ReAct 过程。看看 Agent 是如何理解问题,判断需要使用 knowledge_graph_query 工具,构造内部查询(可能是自然语言,由 Query Engine 转译),获取 KG 返回的信息,并最终整合出答案的。可以尝试不同的问题,测试 Agent 利用 KG 工具的能力。思考 Agent 查询与直接查询 KG 引擎结果的异同。

6.3 框架选择权衡:我该用哪个?

LangChain 和 LlamaIndex 都是非常优秀的框架,各有千秋。选择哪个(或者如何结合使用)取决于你的具体需求:

  • 对比维度:

    • 学习曲线: LangChain 组件多,初期可能稍陡峭。LlamaIndex 在 RAG 核心上易上手。
    • 核心优势: LangChain 强在通用性、灵活性、广泛集成LlamaIndex数据索引、RAG 优化(含结构化数据) 上有深厚积累。
    • 社区与生态: 两者都活跃,LangChain 可能因通用性感觉生态更大。
    • 知识图谱集成: LlamaIndex 提供更原生、与数据体系结合更紧密的方案(自动构建索引并作工具)。LangChain 提供灵活接口供自行集成
    • 互操作性: 两者可结合使用。常见模式是在 LangChain Agent 中使用 LlamaIndex 的 Query Engine 作为 Tool。
  • 选型建议:

    • 复杂流程、广泛集成选 LangChain
    • 强 RAG 需求、利用内部知识库选 LlamaIndex
    • 深度利用 KG,优先考虑 LlamaIndex 的原生方案,或在 LangChain 中自行集成。
    • 结合使用往往能发挥最大优势。

总结

在本章中,我们通过具体的代码示例,动手实践了如何使用两大主流框架——LangChain 和 LlamaIndex 来构建 AI Agent。我们学习了它们的核心 API 与概念,体验了如何定义工具、配置 Agent 并观察其运行逻辑,特别是在 LlamaIndex 中实践了将知识图谱索引作为工具的强大功能。我们还比较了它们的设计哲学和选型考量。

掌握 LangChain 和 LlamaIndex 是 Agent 开发者的基本功。然而,Agent 的世界远不止于此。在下一章,我们将目光投向另外两个备受关注、各具特色的主流 Agent 框架:Microsoft 的 AutoGenCrewAI,它们分别在多 Agent 协作结构化流程定义方面展现出独特的魅力。让我们继续探索!

你可能感兴趣的:(AI,Agents,构建实战,langchain,人工智能,Agent,Llmaindex)