尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

LangChain+Playwright搭建调研Agent:开发与测试全流程复盘

LangChain+Playwright搭建调研Agent:开发与测试全流程复盘 手动收集资料太痛苦我用 LangChain Playwright 搭了个调研 Agent开发测试全流程复盘不知道大家有没有遇到过这种场景老板丢下一句“帮我整理一下最近竞品的动态”然后你就要打开浏览器翻搜索页、点链接、复制内容、粘贴到文档里反复循环。如果是临时一次还好怕的是这种需求每个月都要来一次甚至每个星期都来一次。我之前就是这么熬过来的直到有一天决定彻底“偷懒”用 LangChain 做 Agent 编排用 Playwright 做浏览器自动化搭了一个“自动调研 Agent”。用户在命令行里输入一个主题Agent 自己会判断要不要开浏览器、搜索什么关键词、打开哪些页面、提取什么信息最后给出调研结论。这篇文章就来完整复盘这个小项目的设计、开发、测试全过程。文章不仅讲概念也会给出可直接复制的完整代码包括浏览器工具封装、LangChain Agent 组装、单元测试和集成测试。适合以下读者想入门 LLM Agent 开发但不知道从哪个项目练手的同学。已经会用 LangChain 基础功能想接浏览器自动化能力的开发者。做测试开发想了解如何对 Agent 这类异步、不确定输出的系统做可稳定验证的测试。工作中需要定时收集网页信息、竞品动态、新闻资讯的同学。读完这篇文章你会掌握LangChain Agent 的基本运行机制以及它和 LangGraph 的区别。如何把 Playwright 封装成一个能被大模型调用的 Tool。一个“需求调研 Agent”从 0 到 1 的完整实现过程。Agent 项目的测试思路Mock 外部依赖、控制不确定性、稳定断言。1. 背景与核心概念1.1 为什么需要“能操作浏览器的 Agent”先看传统做法。用普通爬虫去抓网页信息比如 requests BeautifulSoup问题很明显现在很多网站是前端渲染出来的直接请求 HTML 根本拿不到实际内容。另外如果调研目标是“打开百度搜索关键词点进前几个链接把页面正文摘录下来”这种流程用 requests 写起来非常繁琐每一步都要手动处理。Playwright 解决的是“浏览器自动化”的问题。它能启动一个真实的 Chromium 浏览器模拟真实用户点击、滚动、输入也能直接抓取渲染后的页面内容。本质上Playwright 就是给 Agent 一双“眼睛”和一双“手”。但 Playwright 本身不知道“用户想问什么”。比如用户输入“帮我调研一下 2025 年大模型 Agent 框架的对比”Playwright 只能逐条执行指令无法自己规划步骤。要让程序自己判断“我应该先搜索哪些关键词再打开哪些页面最后提炼哪些要点”就需要引入大模型推理能力也就是 LangChain 做的事情。所以说LangChain Playwright 的组合本质上是一个“大脑 手脚”的组合LangChain负责理解用户意图、规划步骤、调用工具、组织输出。Playwright负责执行真正的浏览器操作拿到网页数据。1.2 LangChain 在这个项目里的角色LangChain 是一个用于构建大模型应用的开发框架。它本身不生产模型而是把大模型、提示词、工具调用、记忆、文档加载等能力组织成一套标准化的开发接口。在本文的项目里LangChain 主要承担以下工作连接大模型通过 ChatOpenAI 统一调用模型接口。定义 Tool把 Playwright 的搜索和内容提取能力封装成大模型可以调用的工具函数。管理 Agent 循环Agent 根据用户的输入以及每一步工具返回的结果决定“下一步做什么”直到得到最终答案。这种“大模型 工具调用”的循环在 LangChain 官方的术语中叫 Agent。比较常用的类型是ZERO_SHOT_REACT_DESCRIPTION即零样本模式大模型通过 ReActReason Act思路先思考再行动观察结果再思考直到任务完成。1.3 LangChain 和 LangGraph 的区别这里顺便回答一个高频问题LangChain 和 LangGraph 到底有什么关系简单粗暴地理解LangChain 是“上层开发框架”提供 Agent、Tool、Chain、Memory 等高级抽象。适合快速开发对初学者友好。LangGraph 是“底层编排引擎”它把 Agent 流程建模为一张图节点是操作边是流转条件。适合需要精细控制流程、复杂分支、人工确认、循环限制的项目。本文项目用 LangChain 的 Agent 就完全够用。如果你以后发现流程复杂到难以用现成的 Agent 类型表达再去学习 LangGraph 也不迟。先跑通再谈优化。1.4 Playwright 在这个项目里的角色Playwright 是微软开源的一个自动化测试工具支持 Chromium、Firefox、WebKit 三种浏览器引擎。它最早是为了做 UI 自动化测试但用来开发“网页操作型工具”同样非常好用。在本项目里我们用一个典型场景搜索引擎结果提取。page.goto(https://www.baidu.com/s?wdLangChainAgent)这一行代码打开真实浏览器访问百度搜索结果页。然后通过选择器定位搜索结果元素提取标题和链接。整个过程跟真实用户操作几乎一致因此能绕过一些简单的静态反爬限制。不过要注意Playwright 加载页面是异步渲染的页面元素可能需要等待。所以代码里要使用wait_for_selector或page.locator().first.wait_for()来确保元素出现后再操作。2. 环境准备与版本说明2.1 运行环境本文示例的代码在以下环境中验证过读者可根据自己的环境微调操作系统Windows 11 / macOS 均可Linux 服务器同样支持。Python 版本3.10 及以上推荐 3.11。包管理工具pip。浏览器Chromium由 Playwright 自动安装。2.2 安装依赖建议在虚拟环境中操作。创建项目目录后先建一个虚拟环境mkdir agent-browser-demo cd agent-browser-demo python -m venv .venv # Windows .venv\Scripts\activate # macOS / Linux source .venv/bin/activate然后安装核心依赖pip install langchain langchain-openai playwright pydantic安装完成后需要安装 Playwright 对应的浏览器内核playwright install chromium这个命令会下载 Chromium 内核到本地缓存。注意国内网络环境下可能需要一点时间如果下载失败可以多试几次或者配置镜像源。2.3 大模型 API 准备本文使用 OpenAI 兼容接口。你可以在环境变量中配置 API Key# macOS / Linux export OPENAI_API_KEYsk-xxxx # Windows PowerShell $env:OPENAI_API_KEYsk-xxxx如果你使用的是国内大模型服务只要它提供 OpenAI 兼容接口也可以把 base_url 指向对应服务地址。LangChain 的ChatOpenAI支持自定义base_url参数这个在后面代码中会体现。3. 核心概念拆解Agent、Tool、Playwright3.1 LangChain Agent 的工作流程理解 Agent 的最简单方式是把它看成一个“会使用工具的大模型”。常规的大模型对话流程是用户输入 - 大模型 - 文本输出Agent 的流程多了一个“工具调用”环节用户输入 - 大模型推理 - 决定调用某个工具 - 执行工具 - 拿到结果 - 把结果交给大模型 - 大模型继续推理 - 得到最终答案这里最关键的一步是大模型“决定调用哪个工具”。LangChain 通过提示词和工具描述来实现这一点。每个 Tool 都有name和description大模型根据这两个字段判断“当前任务是否适合使用这个工具”。因此工具的描述写得越清楚Agent 的调用准确率就越高。这就像给一个实习生写工作手册描述越具体实习生就越知道什么时候该用哪种方法。3.2 什么是 Tool在 LangChain 中Tool 是一个封装了实际执行能力的对象。它有两个核心属性name工具名称必须是唯一的英文标识。description工具作用描述大模型会读取这段文字来判断调用时机。args_schema参数结构定义通常用 Pydantic 做参数校验。_run 方法真正的执行逻辑。我们接下来会把 Playwright 搜索和网页内容提取封装成一个 Tool让 Agent 能直接使用。3.3 Playwright 的同步 API 和异步 APIPlaywright 同时提供同步和异步两套 API。简单选择标准在脚本、命令行工具中使用同步 API代码更直观。在 FastAPI、AioHTTP、Jupyter Notebook 等已有事件循环的环境中使用异步 API。本文为了保持代码简洁统一使用同步 API。但要注意如果以后把项目改造成 Web 服务最好切换到异步 API否则容易导致线程阻塞。4. 完整实战从需求到开发测试全流程4.1 需求分析我们要做的“自动调研 Agent”核心需求如下用户输入一个主题比如“LangChain Agent 的最新实践”。Agent 调用浏览器工具去搜索引擎搜索相关关键词。Agent 读取搜索结果摘要打开有信息量的页面提取正文内容。Agent 综合搜索结果输出一份结构化的调研结论。为了减少开发复杂度第一个版本只做“搜索引擎结果摘要提取 页面标题收集”。第二个版本再增强“页面正文内容提取”。4.2 项目结构项目完整目录如下agent-browser-demo/ ├── requirements.txt ├── .env.example ├── agent/ │ ├── __init__.py │ ├── browser_tool.py │ ├── agent_runner.py │ └── config.py ├── tests/ │ ├── __init__.py │ ├── test_browser_tool.py │ └── test_agent_runner.py └── main.py为了避免把大段代码堆在一个文件里我们把配置、浏览器工具、Agent 主体拆开。这样后续维护和测试都更方便。4.3 配置文件config.py# agent/config.py import os from dotenv import load_dotenv load_dotenv() OPENAI_API_KEY os.getenv(OPENAI_API_KEY, ) OPENAI_BASE_URL os.getenv(OPENAI_BASE_URL, https://api.openai.com/v1) OPENAI_MODEL os.getenv(OPENAI_MODEL, gpt-4o-mini) SEARCH_ENGINE_URL os.getenv(SEARCH_ENGINE_URL, https://www.baidu.com/s?wd) BROWSER_HEADLESS os.getenv(BROWSER_HEADLESS, true).lower() true BROWSER_TIMEOUT int(os.getenv(BROWSER_TIMEOUT, 15000))这里强调两点不要把 API Key 硬编码在代码中要放在.env文件并通过环境变量加载。SEARCH_ENGINE_URL可以随时替换比如换成 Bing 或 Google方便适配不同网络环境。4.4 熟悉 Playwright 基础操作在封装 Tool 之前先用一段最简单的代码感受 Playwright 的用法# 文件路径demo/playwright_demo.py from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(headlessTrue) page browser.new_page() page.goto(https://www.baidu.com/s?wdLangChainAgent) page.wait_for_selector(div.result) results page.query_selector_all(div.result) for i, result in enumerate(results[:5]): title_ele result.query_selector(h3) link_ele result.query_selector(a) if title_ele: print(i 1, title_ele.inner_text()) if link_ele: print( , link_ele.get_attribute(href)) browser.close()这段代码做了几件事启动 ChromiumheadlessTrue表示无头模式不显示浏览器窗口。打开百度搜索结果页。等待div.result元素出现。这是一个重要的稳定性手段因为搜索结果页面是异步渲染的不能直接抓。提取前 5 条结果的标题和链接。4.5 封装浏览器搜索 Tool现在把上面的 Playwright 逻辑封装成 LangChain Tool。这部分是本文的核心代码建议重点阅读。# agent/browser_tool.py from typing import Type, Optional from urllib.parse import quote from langchain.tools import BaseTool from pydantic import BaseModel, Field from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeoutError from agent.config import SEARCH_ENGINE_URL, BROWSER_HEADLESS, BROWSER_TIMEOUT class BrowserSearchInput(BaseModel): 浏览器搜索的参数定义 query: str Field(description需要在搜索引擎中查询的关键词尽量简短精准) max_results: int Field( default5, description返回前几条搜索结果取值 1 到 10, ge1, le10, ) class BrowserSearchTool(BaseTool): 通过浏览器访问搜索引擎获取实时搜索结果。 当用户提出的问题需要最新网络信息、实时数据或者大模型知识库中 没有明确答案时使用这个工具。 name: str browser_search description: str ( 当需要获取实时网页信息、最新新闻、热门话题或大模型知识不够时 使用 browser_search 在搜索引擎中查询关键词并返回搜索结果的标题和链接。 输入参数是一个 query 字符串表示要搜索的关键词。 ) args_schema: Type[BaseModel] BrowserSearchInput def _run(self, query: str, max_results: int 5) - str: 执行浏览器搜索返回格式化后的文本结果。 try: with sync_playwright() as p: browser p.chromium.launch(headlessBROWSER_HEADLESS) page browser.new_page() search_url f{SEARCH_ENGINE_URL}{quote(query)} page.goto(search_url, timeoutBROWSER_TIMEOUT) # 等待结果容器出现 page.wait_for_selector(div.result, timeoutBROWSER_TIMEOUT) results page.query_selector_all(div.result)[:max_results] lines [] for idx, result in enumerate(results, start1): title_ele result.query_selector(h3) link_ele result.query_selector(a) snippet_ele result.query_selector(div.c-abstract, span.content-right_8Zs40) title title_ele.inner_text().strip() if title_ele else 无标题 link link_ele.get_attribute(href) if link_ele else snippet snippet_ele.inner_text().strip() if snippet_ele else 无摘要 lines.append(f{idx}. {title}\n 链接: {link}\n 摘要: {snippet}) browser.close() if not lines: return 未在搜索结果页面提取到有效内容可能是页面结构变化或搜索无结果。 return \n\n.join(lines) except PlaywrightTimeoutError: return 浏览器加载超时可能是网络问题或页面结构有变。建议稍后重试。 except Exception as e: return f浏览器搜索执行失败: {str(e)} async def _arun(self, query: str, max_results: int 5) - str: 异步版本暂不实现先保持同步逻辑。 return self._run(query, max_results)这段代码有几个关键点需要说明_run方法返回的是字符串而不是结构化对象。原因是大模型读取工具结果时最方便解析的就是文本。用try-except包裹浏览器操作避免因为页面加载失败导致整个 Agent 崩溃。这是 Agent 工具设计的重要原则工具应该尽力返回可读的错误信息而不是抛异常。百度搜索结果的 DOM 结构并非官方稳定接口选择器可能随时变化。如果你的页面结构对不上可以先用 Playwright 的调试工具查看页面元素调整选择器。quote(query)对中文关键词做 URL 编码确保链接可以正确打开。4.6 组装 Agentagent_runner.py有了 Tool 之后组装 Agent 就非常简单。# agent/agent_runner.py from langchain.agents import AgentExecutor, create_react_agent from langchain_openai import ChatOpenAI from langchain.prompts import PromptTemplate from agent.config import ( OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MODEL, ) from agent.browser_tool import BrowserSearchTool SYSTEM_PROMPT 你是一个专业的网络调研助手。 你的任务是根据用户的问题使用浏览器搜索工具获取最新信息然后整理成结构化结论。 请遵循以下要求 1. 如果问题需要实时信息先调用 browser_search 获取搜索结果。 2. 根据搜索结果中的标题和摘要判断哪些链接有进一步访问价值。 3. 如果结果信息不足可以更换关键词再次搜索。 4. 最终回答使用 Markdown 格式包含调研结论、信息来源列表、时间敏感性说明。 注意不要编造搜索结果中不存在的链接和信息。 def create_agent() - AgentExecutor: llm ChatOpenAI( modelOPENAI_MODEL, api_keyOPENAI_API_KEY, base_urlOPENAI_BASE_URL, temperature0, ) tools [BrowserSearchTool()] prompt PromptTemplate.from_template( {system_prompt} 用户问题: {input} 请开始。你的可用工具: {tools} 工具名称: {tool_names} {agent_scratchpad} ) agent create_react_agent( llmllm, toolstools, promptprompt, ) executor AgentExecutor( agentagent, toolstools, verboseTrue, max_iterations5, handle_parsing_errorsTrue, ) return executor这里解释几个重要参数temperature0温度设为 0让大模型的输出更确定减少随机性。Agent 任务中稳定执行比“有创意”重要得多。max_iterations5限制 Agent 最多执行 5 轮思考-行动循环。避免模型陷入死循环也控制 API 费用。verboseTrue在控制台输出 Agent 的思考过程方便调试。生产环境可以关闭。handle_parsing_errorsTrue容错处理即使大模型的输出格式不符合预期也不会直接崩溃。4.7 主入口main.py# main.py from agent.agent_runner import create_agent def main(): print( Agent 启动成功输入问题开始调研输入 exit 退出。) executor create_agent() while True: question input(\n请输入调研主题: ).strip() if question.lower() in (exit, quit): print( 再见) break if not question: continue result executor.invoke({input: question}) print(\n 调研结果 \n) print(result[output]) print(\n\n) if __name__ __main__: main()4.8 运行与验证在项目根目录下运行python main.py输入一个测试问题请输入调研主题: 2025年主流 AI Agent 开发框架有哪些Agent 会先调用browser_search工具搜索关键词获取搜索结果后再生成结构化结论。由于本文重点讲的是流程和代码实际运行时API 调用会产生少量费用建议先用免费额度或者便宜的模型测试。5. 测试开发Agent 项目怎么测才靠谱5.1 Agent 测试的最大困难传统函数的测试相对简单“给定输入断言输出”。但 Agent 项目有两个不确定性来源大模型输出不确定同样的问题可能给出不同回答。浏览器页面结构不稳定依赖真实网络环境。因此测试 Agent 项目的核心思路是“分层测试”对纯函数逻辑比如结果解析、文本格式化做普通单元测试。对工具函数Mock 掉浏览器和网络只测试工具逻辑本身。对 Agent 整体用小范围集成测试同时使用断言的关键词而不是全文本匹配。5.2 Mock 掉浏览器依赖测试 BrowserSearchTool 时我们不希望真实打开浏览器因为这样既慢又依赖网络。正确做法是使用 Python 的 unittest.mock 来模拟 Playwright 的调用。# tests/test_browser_tool.py from unittest.mock import MagicMock, patch from agent.browser_tool import BrowserSearchTool class MockPage: 模拟 Playwright 的 Page 对象 def __init__(self): self._results [] def goto(self, url, timeoutNone): pass def wait_for_selector(self, selector, timeoutNone): pass def query_selector_all(self, selector): return self._results class MockElement: 模拟 Playwright 的 ElementHandle 对象 def __init__(self, title测试标题, linkhttps://example.com, snippet测试摘要): self.title title self.link link self.snippet snippet def query_selector(self, selector): if selector h3: return MagicMock(inner_textlambda: self.title) if selector.startswith(a): return MagicMock(get_attributelambda name: self.link if name href else ) if c-abstract in selector or abstract in selector: return MagicMock(inner_textlambda: self.snippet) return None def test_browser_search_tool_mocked(): tool BrowserSearchTool() mock_elements [ MockElement(titleLangChain Agent 教程, linkhttps://example.com/1, snippet这是一段关于 LangChain Agent 的教程), MockElement(titlePlaywright 自动化, linkhttps://example.com/2, snippet这是一段关于 Playwright 的自动化教程), ] with patch(agent.browser_tool.sync_playwright) as mock_sync: # 模拟 Playwright 的上下文管理器和调用链 mock_context mock_sync.return_value.__enter__.return_value mock_browser mock_context.chromium.launch.return_value mock_page MockPage() mock_page._results mock_elements mock_browser.new_page.return_value mock_page result tool._run(测试, max_results2) assert LangChain Agent 教程 in result assert https://example.com/1 in result assert 测试摘要 in result这里用到了两个技巧patch(agent.browser_tool.sync_playwright)只 Mock 浏览器相关对象工具本身的逻辑仍然会被真实执行。自定义 MockElement 类模拟元素的选择器查询方法。这样测试不依赖真实 DOM。5.3 Agent 集成测试用关键词断言对 Agent 做整体测试时不要断言“输出等于某个字符串”因为大模型几乎不可能输出完全一致的文本。更好的策略是断言输出中包含关键主题词。断言输出长度超过某个阈值。断言输出使用 Markdown 结构。# tests/test_agent_runner.py from unittest.mock import patch from agent.agent_runner import create_agent def test_agent_output_contains_keyword(): # 使用一个很小的模型或者直接 Mock 掉 LLM 调用 executor create_agent() # 这里为了演示直接 mock 掉 AgentExecutor重点演示断言思路 with patch(agent.agent_runner.AgentExecutor) as MockExecutor: mock_instance MockExecutor.return_value mock_instance.invoke.return_value { output: ## 调研结论\n\n主流 AI Agent 框架包括 LangChain、LangGraph、AutoGen 等。 } result mock_instance.invoke({input: AI Agent 框架}) output result[output] assert 调研结论 in output assert LangChain in output assert len(output) 105.4 测试覆盖率的取舍对 Agent 项目测试覆盖率不必追求 100%。建议优先覆盖工具层能否正确执行、能否在异常时返回可读错误。解析层结果格式化、错误信息提取。集成层Agent 是否能成功调用工具、返回结果是否为字符串。大模型本身的输出准确性属于“模型能力验证”更适合用评测集单独跑而不是作为单元测试的断言目标。这一点对刚开始做 Agent 测试的同学尤其重要。6. 常见问题与排查思路6.1playwright命令无法识别在 Windows PowerShell 中运行playwright install时可能提示playwright : 无法将“playwright”项识别为 cmdlet、函数、脚本文件或可运行程序的名称原因通常是 Python Scripts 目录没有加入 PATH。解决思路# 先找到 playwright 命令所在目录 python -m playwright install chromium用python -m playwright的方式调用可以避开 PATH 配置问题。这也是我推荐的安装方式pip install playwright python -m playwright install chromium6.2 浏览器启动失败如果执行时报错Executable doesnt exist at .../chromium-xxx/chrome-win/chrome.exe说明 Chromium 内核没有安装成功。重新执行安装命令即可python -m playwright install chromium如果下载速度慢或失败可以配置镜像# Linux / macOS export PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright/ python -m playwright install chromium6.3 Agent 调用工具后一直返回同一个结果这可能有两个原因max_iterations设置太小模型还没来得及深化调研就被中断。尝试调大。工具描述不够清晰模型无法准确传入参数。检查 Tool 的description字段是否明确说明“什么时候用、参数怎么填”。6.4 搜索结果选择器失效百度、必应等搜索引擎改版后页面元素的 class 经常变化。如果div.result选择不到元素可以先用 Playwright 的调试模式查看页面结构from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(headlessFalse) page browser.new_page() page.goto(https://www.baidu.com/s?wdAIAgent) page.wait_for_timeout(10000) # 给手动画页面结构的时间 browser.close()在非无头模式下打开浏览器开发者工具手动查看搜索结果区块的 DOM 结构再用真实的选择器替换代码中的div.result。6.5 Agent 输出内容格式混乱大模型偶尔会输出不符合要求的格式。在 Agent 的 system_prompt 中可以加入“如果信息不足也要给出结论但说明时间和信息限制”之类的兜底指令。同时在业务层对输出做一次二次清洗比如强制截断超长内容、补全缺失的 Markdown 结构。7. 工程化实践建议7.1 工具设计三原则从这次实战中我总结了 Agent 工具设计的三个原则第一工具永远返回字符串。不要返回对象、字节流、字典。字符串既能被大模型直接读取也方便日志记录。第二工具对异常负责。工具内部捕获所有异常并把错误信息转换成可读文本返回。不要让异常抛到 Agent 引擎层否则不可控。第三描述就是文档。工具的description是给大模型看的用“当……时候使用这个工具”的句式比单纯写一句话准确率高得多。7.2 成本控制Agent 项目的成本主要来自 API 调用。几个控制思路设置max_iterations限制最大工具调用轮数。选用便宜的模型做“第一版尝鲜”跑通之后再切换更强模型。记录每次调用的 token 用量统计平均成本预估月度开销。from langchain.callbacks import get_openai_callback with get_openai_callback() as cb: result executor.invoke({input: AI Agent 框架}) print(fTotal tokens: {cb.total_tokens}) print(fPrompt tokens: {cb.prompt_tokens}) print(fCompletion tokens: {cb.completion_tokens})7.3 生产环境的 Playwright 服务化如果要把这个 Agent 部署成 Web API需要注意几点使用 Playwright 异步 API避免阻塞 FastAPI 事件循环。控制并发浏览器实例数量防止内存爆炸。建议复用浏览器实例而非每次新建。设置页面加载超时和内容大小限制防止异常页面拖垮服务。不要把浏览器操作和 Agent 逻辑混在一个进程推荐拆成独立 Worker。7.4 Agent 从 LangChain 迁移到 LangGraph 的时机当你发现如下信号时可以考虑从 LangChain Agent 迁移到 LangGraph需要人工确认后再继续执行。需要严格的循环次数和条件判断比如最多搜 3 次、每次换不同关键词。需要在某一步插入审计日志或数据校验。需要并行调用多个工具再合并结果。如果只是“搜索 - 总结 - 输出”这种简单线性流程LangChain 完全够用。不要为了“先进”而引入额外复杂度。8. 收尾下一步可以做什么文章的代码虽然只是“搜索工具 Agent 主流程”但这个框架可以轻松扩展出很多实用的场景。你可以把搜索工具换成“网页内容提取工具”增加一个open_urlTool让 Agent 在拿到搜索结果后继续打开具体页面读取正文。这样调研结果会更有深度。你还可以加入一个“记忆”功能让 Agent 记住用户之前的偏好。比如用户说“我喜欢中文资料”下一次 Agent 搜索时就会自动加上中文关键词。如果你继续深入可以关注 LangGraph 的状态管理、多 Agent 协作、Agent 与数据库和向量库的配合。但这些都不是必须一步到位先把最基础的跑通比什么都重要。本文的完整代码可以直接复制到本地运行。如果你在配置或运行过程中遇到问题欢迎在评论区留言一起交流。也建议把项目仓库保留好后续扩展新能力时会非常方便。
返回列表