news 2026/9/6 18:54:41

ai-engineering-hub:用 CrewAI + LinkUp + DeepSeek-R1 搭建 MCP 驱动的多智能体深度研究系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ai-engineering-hub:用 CrewAI + LinkUp + DeepSeek-R1 搭建 MCP 驱动的多智能体深度研究系统

ai-engineering-hub:用 CrewAI + LinkUp + DeepSeek-R1 搭建 MCP 驱动的多智能体深度研究系统

【免费下载链接】ai-engineering-hubIn-depth tutorials on LLMs, RAGs and real-world AI agent applications.项目地址: https://gitcode.com/GitHub_Trending/ai/ai-engineering-hub

本文基于仓库中的Multi-Agent-deep-researcher-mcp-windows-linux项目,讲解如何从零搭建一个支持深度网络搜索的 Agentic Deep Researcher:以 CrewAI 编排"搜索—分析—写作"三名智能体,以 LinkUp 作为搜索工具,以本地 Ollama 部署的 DeepSeek-R1 作为推理 LLM,并支持 Streamlit 交互界面与 MCP Server 两种使用方式。读完后,你可以完整理解多智能体研究流水线的 CrewAI 实现细节,并学会把整个研究系统以 MCP 工具的形式暴露给任意支持 MCP 的客户端。

系统概览:一条"搜索 → 分析 → 写作"的智能体流水线

该项目的目标(见 README)是构建一个由 MCP 驱动的多智能体深度研究员(Agentic Deep Researcher),能够执行深度网络搜索。整体技术栈由四部分组成:

  • LinkUp:提供网络搜索能力的搜索工具(SDK 依赖linkup-sdk);
  • CrewAI:负责智能体的角色定义、任务编排与委派机制(依赖crewai);
  • DeepSeek R1:驱动各智能体的推理 LLM(实际通过本地 Ollama 调用);
  • Streamlit:把研究逻辑包装成交互式聊天界面。

从源码结构看,整个项目只有 4 个核心 Python 文件,职责划分非常清晰:

文件职责
agents.py定义 LinkUp 搜索工具、LLM 客户端、三个智能体与任务编排,对外暴露run_research(query)
server.py基于 FastMCP 的 stdio MCP 服务,把研究流水线封装为名为crew_research的工具
app.pyStreamlit 聊天界面,负责 API Key 配置与结果展示
pyproject.toml依赖声明,要求 Python >= 3.11

两种使用入口最终都汇聚到同一个函数run_research(query):Streamlit 应用在聊天流程中直接调用它,MCP Server 则在工具回调中调用它,保证了"界面版"和"工具版"行为一致。

环境准备:依赖、本地模型与 API Key

依赖安装

在项目根目录执行 README 给出的安装命令:

uv sync

pyproject.toml 中声明的运行时依赖为:

依赖版本约束用途
crewai>=0.114.0多智能体编排框架
linkup-sdk>=0.2.4LinkUp 搜索客户端
mcp>=1.6.0MCP 协议服务端(FastMCP)
openai>=1.75.0LLM 调用底层客户端(CrewAI 经由 OpenAI 协议对接 Ollama)
python-dotenv>=1.1.0.env文件加载环境变量
streamlit>=1.44.1交互式 UI
streamlit-crewai-process-output>=0.1.1CrewAI 过程输出在 Streamlit 中的展示组件

项目要求Python >= 3.11(见 pyproject.toml 第 6 行),uv sync会依据uv.lock在隔离环境中安装全部依赖。

两个运行前提:本地 DeepSeek-R1 与 LinkUp API Key

源码中有两个 README 未展开、但运行前必须满足的前提:

  1. 本地 Ollama 模型。agents.py 第 13–18 行 中的 LLM 客户端配置如下:
def get_llm_client(): """Initialize and return the LLM client""" return LLM( model="ollama/deepseek-r1:7b", base_url="http://localhost:11434" )
也就是说,虽然技术栈写的是"DeepSeek R1 (LLM)",但实际推理发生在**本地 Ollama**(`localhost:11434`)上,模型为 `deepseek-r1:7b`。运行前需要先用 Ollama 拉取并启动该模型。
  1. LinkUp API Key。搜索工具在运行时通过os.getenv("LINKUP_API_KEY")读取密钥(见 agents.py 第 44 行),文件头部还调用了load_dotenv()(第 10 行),因此可以把LINKUP_API_KEY写入项目根目录的.env文件,也可以在 Streamlit 界面侧边栏中直接填入(见下文)。

核心实现解析:LinkUp 搜索工具与三名智能体

本节全部对应 agents.py 的源码,是整个系统的主干。

LinkUp 搜索工具:一个带参数 Schema 的 CrewAI Tool

智能体能否"会搜索",取决于工具定义。项目把 LinkUp 封装为标准的 CrewAIBaseTool,其输入参数由 Pydantic 模型LinkUpSearchInput描述(agents.py 第 23–29 行):

class LinkUpSearchInput(BaseModel): """Input schema for LinkUp Search Tool.""" query: str = Field(description="The search query to perform") depth: str = Field(default="standard", description="Depth of search: 'standard' or 'deep'") output_type: str = Field( default="searchResults", description="Output type: 'searchResults', 'sourcedAnswer', or 'structured'")

三个参数的含义与默认值:

  • query(必填):要执行的搜索查询词,由 Web Searcher 智能体在运行时自行改写;
  • depth(默认"standard"):搜索深度,可选"standard"(常规搜索)或"deep"(深度搜索),这是"Deep Researcher"名称中"deep"的能力来源——智能体可以为复杂问题自主选择更深度的搜索;
  • output_type(默认"searchResults"):返回形态,可选"searchResults"(原始搜索结果列表)、"sourcedAnswer"(带来源引用的答案)、"structured"(结构化输出)。

工具主体LinkUpSearchTool_run方法(agents.py 第 40–55 行)逻辑为:

  1. 用环境变量中的密钥初始化LinkupClient
  2. 调用linkup_client.search(query=..., depth=..., output_type=...)发起搜索;
  3. 将响应str(search_response)后返回给智能体;
  4. 任何异常都不会抛出,而是返回形如Error occurred while searching: ...的错误字符串,让智能体能"看到"失败并自行调整策略,而不是中断整个流水线。

这个"错误也作为观察结果返回"的写法,是 Agentic 工具封装中值得借鉴的健壮性设计。

三名智能体:角色、目标与委派边界

create_research_crew(query)函数(agents.py 第 58–126 行)定义了三个角色,全部挂载同一个本地 DeepSeek-R1 客户端:

1. Web Searcher(网络搜索员)—— 唯一持有搜索工具的智能体:

web_searcher = Agent( role="Web Searcher", goal="Find the most relevant information on the web, along with source links (urls).", backstory="An expert at formulating search queries and retrieving relevant information. Passes the results to the 'Research Analyst' only.", verbose=True, allow_delegation=True, tools=[linkup_search_tool], llm=client, )

其 goal 明确要求连同来源链接(URL)一起找到信息——这是整条流水线"引用可追溯"要求的第一环。

2. Research Analyst(研究分析师)—— 负责把原始搜索结果合成结构化洞察:

research_analyst = Agent( role="Research Analyst", goal="Analyze and synthesize raw information into structured insights, along with source links (urls) as citations.", backstory="... If required, can delagate the task of fact checking/verification to 'Web Searcher' only. Passes the final results to the 'Technical Writer' only.", verbose=True, allow_delegation=True, llm=client, )

注意它的 backstory 设定了一个委派边界:仅在需要事实验证时,才可以把任务委派回 "Web Searcher",且最终结果只能交给 "Technical Writer"。这种用自然语言 backstory 显式约束委派对象与输出流向的写法,是 CrewAI 多智能体系统中控制"信息流向"的常见手段。

3. Technical Writer(技术写作者)—— 只写不搜:

technical_writer = Agent( role="Technical Writer", goal="Create well-structured, clear, and comprehensive responses in markdown format, with citations/source links (urls).", backstory="An expert at communicating complex information in an accessible way.", verbose=True, allow_delegation=False, llm=client, )

它的allow_delegation=False,即不允许委派任何任务,职责是把分析结果组织成带引用链接的 Markdown 长文。

任务链与顺序执行流程

三个智能体被三条Task串联(agents.py 第 97–116 行):

search_task = Task( description=f"Search for comprehensive information about: {query}.", agent=web_searcher, expected_output="Detailed raw search results including sources (urls).", tools=[linkup_search_tool] ) analysis_task = Task( description="Analyze the raw search results, identify key information, verify facts and prepare a structured analysis.", agent=research_analyst, expected_output="A structured analysis of the information with verified facts and key insights, along with source links", context=[search_task] ) writing_task = Task( description="Create a comprehensive, well-organized response based on the research analysis.", agent=technical_writer, expected_output="A clear, comprehensive response that directly answers the query with proper citations/source links (urls).", context=[analysis_task] ) crew = Crew( agents=[web_searcher, research_analyst, technical_writer], tasks=[search_task, analysis_task, writing_task], verbose=True, process=Process.sequential )

关键编排细节:

  • 每个任务都声明了expected_output,用来锚定该环节的产物形态(带 URL 的原始结果 → 结构化分析 → 带引用的完整回答);
  • 后一个任务通过context=[前一个任务]声明数据依赖,搜索任务的结果流入分析任务,分析结果再流入写作任务;
  • process=Process.sequential指定顺序流程:任务按定义顺序逐个执行,而非由智能体自由协商并行。

最终执行入口是run_research(agents.py 第 129–136 行):构建 Crew、调用crew.kickoff(),并返回result.raw(纯文本结果);异常时同样以Error: ...字符串返回,保持了对上层调用方(Streamlit / MCP)一致的返回契约。

使用方式一:Streamlit 交互应用

按 README 的说明启动应用:

streamlit run app.py

app.py 实现了单页聊天界面,要点如下:

  • 侧边栏 API Key 配置(app.py 第 31–37 行):用户在侧边栏输入 LinkUp API Key 后,会被写入会话状态并同步设置到环境变量:
if linkup_api_key: st.session_state.linkup_api_key = linkup_api_key # Update the environment variable os.environ["LINKUP_API_KEY"] = linkup_api_key

由于LinkUpSearchTool._run是在每次搜索时才读取os.getenv("LINKUP_API_KEY"),所以界面中输入的 Key 能即时生效,无需重启进程。未填 Key 时提问会得到 "Please enter your Linkup API Key in the sidebar." 的提示(app.py 第 70–71 行)。

  • 聊天主流程(app.py 第 65–83 行):用户提问后,界面在 "Researching..." 的 spinner 下调用run_research(prompt),把返回的 Markdown 结果以 assistant 消息追加进st.session_state.messages历史,支持连续多轮提问与一键清空(Clear 按钮触发reset_chat)。

  • 页面通过st.set_page_config(page_title="🔍 Agentic Deep Researcher", layout="wide")使用宽布局展示长文结果。

由于 DeepSeek-R1 在本地推理、搜索走 LinkUp 云端,该界面适合在联网开发机上直接体验完整的"提问 → 多智能体研究 → 带引用长文"流程。

使用方式二:暴露为 MCP Server 供其他客户端调用

这是本项目标题中"MCP"二字的落点:整个多智能体研究系统被封装为一个标准的stdio 传输 MCP Server,任意支持 MCP 的客户端(如 Cursor)都可以把crew_research当作一个工具来调用。

服务端实现

server.py 只有约 20 行核心代码:

from mcp.server.fastmcp import FastMCP from agents import run_research # Create FastMCP instance mcp = FastMCP("crew_research") @mcp.tool() async def crew_research(query: str) -> str: """Run CrewAI-based research system for given user query. Can do both standard and deep web search. Args: query (str): The research query or question. Returns: str: The research response from the CrewAI pipeline. """ return run_research(query)

要点:

  • FastMCP("crew_research")创建了名为crew_research的 MCP 服务实例;
  • @mcp.tool()装饰器把crew_research(query)注册为工具,其 docstring 会成为工具描述的一部分——其中明确告知调用方"Can do both standard and deep web search"(对应 LinkUp 工具的depth参数);
  • 工具是async的,内部同步调用run_research,完整复用 Streamlit 应用同一套智能体流水线;
  • 服务以mcp.run(transport="stdio")启动(server.py 第 22–23 行),即通过标准输入/输出与宿主客户端通信,这是本地 MCP Server 最常见的传输方式。

客户端配置

README 给出的 MCP 客户端配置(以mcpServers片段为例)如下:

{ "mcpServers": { "crew_research": { "command": "uv", "args": [ "--directory", "./Multi-Agent-deep-researcher-mcp-windows-linux", "run", "server.py" ], "env": { "LINKUP_API_KEY": "your_linkup_api_key_here" } } } }

配置解读与实操注意:

  • command+args:客户端用uv --directory <项目目录> run server.py拉起服务。uv --directory保证在项目自己的虚拟环境(uv.lock锁定的依赖)里运行server.py,无需手动激活环境;
  • 路径必须改成你自己机器上的位置--directory参数指向的是本仓库的Multi-Agent-deep-researcher-mcp-windows-linux目录(README 中写的是相对仓库根的路径;server.py 第 26–42 行 的注释示例则展示了配置绝对路径的写法)。实际使用时请替换为本机克隆仓库后对应目录的绝对路径;
  • env:通过 MCP 客户端直接注入LINKUP_API_KEY,服务端在启动进程中即可通过环境变量拿到密钥,与.env文件方式二选一即可;
  • 该目录同时支持 Windows 与 Linux(目录名mcp-windows-linux即为此意),配置片段可放入对应客户端的 MCP 配置文件(例如 Cursor 的./.cursor/mcp.json)。

配置完成后,宿主客户端中的模型即可像调用普通工具一样发起crew_research(query),背后自动完成"Web Searcher 深度搜索 → Research Analyst 综合分析 → Technical Writer 成文"的全过程,并把带引用链接的 Markdown 研究报告作为工具返回值交还。

设计要点小结

从这套实现中可以提炼出几个可复用的模式:

  1. 职责分段 + 数据依赖显式化:用Task.context把上游任务产物显式传给下游,配合Process.sequential保证执行顺序确定,避免了自由协商式流程在简单场景下的不可控;
  2. 引用贯穿全链:从 goal 到expected_output,每个环节都强制要求携带 source URLs,使最终报告"句句可溯源";
  3. 工具错误不抛异常:搜索失败时返回错误描述字符串,让智能体有机会改写查询重试;
  4. 同一核心、两种门面run_research()作为唯一入口,被 Streamlit 与 MCP 两个壳层复用,既提供人类交互界面,又向 AI 客户端开放为工具;
  5. 本地小模型驱动:通过ollama/deepseek-r1:7b在本地完成推理,搜索知识则外包给 LinkUp 云端,"本地推理 + 云端检索"的组合降低了 API 成本与数据出境面。

相关文件索引

  • README.md:安装、启动与 MCP 配置说明
  • agents.py:工具、智能体、任务与 Crew 定义
  • server.py:FastMCP stdio 服务端
  • app.py:Streamlit 聊天界面
  • pyproject.toml:依赖与 Python 版本约束

需要说明的是,运行本系统依赖外部服务(LinkUp API)与本地 Ollama 上的deepseek-r1:7b模型,且依赖版本以当前仓库 pyproject.toml 声明的下限(crewai>=0.114.0、mcp>=1.6.0 等)为准;CrewAI 与 MCP SDK 迭代较快,升级依赖后需回归验证Task.contextProcess.sequential等 API 的兼容性。

【免费下载链接】ai-engineering-hubIn-depth tutorials on LLMs, RAGs and real-world AI agent applications.项目地址: https://gitcode.com/GitHub_Trending/ai/ai-engineering-hub

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 18:53:51

SPWM变频调速系统的MATLAB仿真:原理、建模与调试全攻略

简介&#xff1a;电机调速是工业自动化的基础技术&#xff0c;变频调速通过对电机供电电源的频率与电压进行协调控制&#xff0c;实现宽范围平滑调速。SPWM&#xff08;正弦脉宽调制&#xff09;作为实现变频的核心调制方式&#xff0c;利用脉冲宽度按正弦规律变化来逼近正弦输…

作者头像 李华
网站建设 2026/9/6 18:49:23

ISO/IEC 25012数据质量模型:从维度定义到评估落地

简介&#xff1a;ISO/IEC 25012:2008 是国际标准化组织&#xff08;ISO&#xff09;与国际电工委员会&#xff08;IEC&#xff09;联合发布的数据质量模型标准&#xff0c;属于SQuaRE系列&#xff0c;为软件工程中的数据质量管理提供系统化框架&#xff0c;填补了数据质量评估缺…

作者头像 李华
网站建设 2026/9/6 18:48:53

CP控制计划实战指南:从APQP定位到现场落地的完整解析

简介&#xff1a;CP控制计划&#xff08;Control Plan&#xff09;培训宣讲PPT系统讲解控制计划这一质量核心工具&#xff0c;从C代表Control控制、P代表Plan计划的命名释义切入&#xff0c;明确其在产品质量先期策划&#xff08;APQP&#xff09;中的重要输出地位。内容覆盖IS…

作者头像 李华
网站建设 2026/9/6 18:48:21

超螺旋高阶滑模+双观测器:Buck变换器负载突变抑制方案

简介&#xff1a;面向电力电子工程师、自动化控制研究人员及高校相关专业师生&#xff0c;提供Buck型变换器高阶滑模控制方法的完整研究资料。内容涵盖Buck变换器工作原理与数学模型建立、传统一阶滑模/积分滑模/终端滑模控制性能对比、二阶滑模抖振抑制设计&#xff0c;以及负…

作者头像 李华