首页
/ AutoGPT 平台 Exa Search 模块详解:基于神经检索与关键词检索的网页搜索 Block

AutoGPT 平台 Exa Search 模块详解:基于神经检索与关键词检索的网页搜索 Block

2026-09-06 18:51:50作者:何将鹤

AutoGPT 平台的 exa 提供者是一整套基于 Exa 网页索引的搜索类集成,其中 Exa Search 是使用频率最高的入口 Block:它用一句查询语句即可完成「语义检索 + 站点/时间/内容类型过滤 + 正文提取」的整条搜索流水线,并直接产出可供 LLM 消费的 context 上下文串与成本明细。本文以 docs/integrations/block-integrations/exa/search.md 为骨架,结合该 Block 在仓库中的真实实现(blocks/exa/search.py 等)逐项拆解其原理、每个输入输出的取值与默认语义、底层调用链与成本核算方式,帮你把它正确接入自己的 Agent 流程。

这是什么:一个用 Exa 语义检索能力搜索网页的 Block

模块定位

Exa Search Block(实现类 ExaSearchBlock,Block ID 996cec64-ac40-4dde-982f-b0dc60a5824d)在构建器中归属于 BlockCategory.SEARCH(见 search.py),功能描述只有一句话:

Searches the web using Exa's advanced search API

但与常见的网页搜索引擎不同,Exa 提供的不是单纯的「关键词命中」,而是一套理解语义的神经检索(neural search)能力——因此它特别擅长找到「类型明确、语义匹配」的内容,而不是简单依赖字面关键词的巧合。Block 官方文档对它的能力概括如下:

  • 支持四种检索模式:关键词检索(keyword,传统)、神经检索(neural,语义理解)、快速检索(fast)与自动选择(auto);
  • 强大的多维度过滤:按域名(include/exclude)、按抓取/发布日期区间、按内容类别(company、research paper、news 等)、按正文文本模式(include_text/exclude_text);
  • 结果除 URL、标题外,还可选返回全文内容提取(text / highlights / summary 等),用于直接喂给下游 LLM。

在 Exa 家族中的位置

在仓库中 Exa 不止有这一个 Block。blocks/exa/ 目录下还包含 contents.py(按 URL/ID 取正文)、answers.py(搜索佐证的问答)、similar.py(相似页面)、code_context.py(代码上下文)以及一组 websets 系列 Block。它们在 Provider 层共享同一份 exa 配置(API Key 字段与计费规则均来自 _config.py)。本文聚焦「搜索」这一个动作,其他内容的补充读取可参见同目录文档 contents.mdanswers.md

接入前置条件:Exa 提供者凭证与计费基准

调用任何 Exa Block 前,都需要先为 exa 提供者配置 API Key。

  • ExaSearchBlock.Input 中第一个字段就是 credentials,其描述为 "The Exa integration requires an API Key."(见 search.py);
  • Provider 侧的凭证定义在 _config.py 中:ProviderBuilder("exa") 声明了提供者名称为 exa,并通过 .with_api_key("EXA_API_KEY", "Exa API Key") 绑定 环境变量 EXA_API_KEY 作为密钥来源;
  • 在运行时,run() 方法会通过 AsyncExa(api_key=credentials.api_key.get_secret_value()) 从 Block 凭证里读取密钥创建 SDK 客户端(见 search.py),因此你需要在平台「集成/凭证」管理里预先保存自己的 Exa API Key。

值得注意的一点是计费基准:_config.py 中为提供者设置了 .with_base_cost(100, BlockCostType.COST_USD),代码注释明确说明其口径是 每 1 美元消耗 100 积分(credit),即约 $0.01/credit;一次便宜的搜索只花 1–2 个积分,而一次 0.20 美元的深度任务会落在 20 积分左右,与实际 Provider 支出大致吻合。也就是说,Block 的真实费用以 Exa 响应中返回的 cost_dollars 为准,平台在此基础上做平台内积分的换算统计。

输入参数:字段、类型、默认值与高级语义

原文档给出了完整的输入清单。结合 search.pyInputSchemaField 定义,可以补充出每个字段的默认值与 UI 上的展开层级(advanced=True 的字段通常被平台收纳进「高级选项」区域,仅在需要时展开):

输入 含义 类型 必填 源码默认值 / 备注
query 搜索查询语句 str 唯一必填项,其余全部可选
type 检索方式 "keyword" | "neural" | "fast" | "auto" 源码默认 auto,advanced
category 内容类别限定 见下文类别表 默认 None,advanced
user_location 用户所在国家(两位 ISO 国家码,如 'US' str 默认 None,advanced,用于结果本地化排序
number_of_results 返回结果条数 int 源码默认 10,advanced
include_domains 只在这些域名内搜索 List[str] 默认空列表 []
exclude_domains 排除这些域名的结果 List[str] 默认 [],advanced
start_crawl_date 内容被 Exa 抓取时间区间的起点 str (date-time) 默认 None,advanced
end_crawl_date 内容抓取时间区间的终点 str (date-time) 默认 None,advanced
start_published_date 内容发布时间区间的起点 str (date-time) 默认 None,advanced
end_published_date 内容发布时间区间的终点 str (date-time) 默认 None,advanced
include_text 正文需匹配的文本模式列表 List[str] 默认 [],advanced
exclude_text 正文不得包含的文本模式列表 List[str] 默认 [],advanced
contents 内容检索/提取设置(嵌套对象) ContentSettings 默认 ContentSettings(),advanced
moderation 内容审核:过滤不安全结果 bool 源码默认 False,advanced

type 与 category 的合法取值

原文档将取值范围以枚举形式给出,这与源码中定义的枚举完全一一对应:

  • type(ExaSearchTypeskeyword / neural / fast / auto。前三种分别代表传统关键词、语义神经检索、快速检索;auto 是源码中的默认值,由 Exa 服务端根据查询自动挑选最优方式(这正是输出里出现 search_type / resolved_search_type 两个字段的原因)。
  • category(ExaSearchCategoriescompany / research paper / news / pdf / github / tweet / personal site / linkedin profile / financial report。枚举的完整声明可见 search.py

当在构建器中选择 category 时,Exa 会把搜索范围收敛到指定类型的内容上(如只看 GitHub 仓库、只看论文),再叠加域名与日期过滤即可得到非常精确的结果集。

contents:ContentSettings 子配置详解

contents 是最复杂也最能拉开差距的输入。它的类型 ContentSettings 定义在 helpers.py,本质是一组控制「要不要、以及怎样提取正文内容」的开关。run() 会把它交由 process_contents_settings() 转成 Exa API 能识别的载荷(camelCase 风格参数),转换规则同样在 helpers.py 中可查。内部包含:

子字段 取值 说明
text bool,或 {maxCharacters, includeHtmlTags} 是否返回页面全文。布尔 true/false 为简单开关;高级形态可限制最大字符数 maxCharacters,以及用 includeHtmlTags 保留 HTML 标签以便 LLM 理解文本结构(见 TextAdvanced)。兼容旧版直接传布尔值的用法
highlights {numSentences, highlightsPerUrl, query} 从每个页面中抽取与查询最相关的若干句高亮片段。numSentences 每条高亮的句子数(默认 1,ge=1)、highlightsPerUrl 每 URL 高亮条数(默认 1,ge=1)、query 可自定义驱动 LLM 选句的查询
summary {query, output_schema} LLM 生成的页面摘要。output_schema 为结构化输出的 JSON Schema;该字段经历了 schemaoutput_schema 的更名,SummarySettings 通过 model_validator 做了向后兼容(旧键 schema 会自动映射,见 helpers.py
livecrawl never | fallback | always | preferred 实时抓取策略:是否在命中缓存不足时现场抓取网页获取最新内容
livecrawl_timeout int(毫秒) 实时抓取超时时间
subpages int(≥0) 要顺带抓取的子页面数量
subpage_target str | List[str] 定位搜索结果特定子页面的关键词
extras {links, imageLinks} 附加内容:每个网页返回的外部链接数、图片数;值为 0 时不会发给 API(避免向 Exa 请求 0 个链接),见转换函数注释
context bool{maxCharacters} 是否把多条结果拼装成一段可直接喂给 LLM 的上下文串,可限制最大字符数

何时走 search、何时走 search_and_contents

原文档没有说明 contents 内部机制,但从 search.pyrun() 实现可以看清两条底层路径:

  • contents 完全没配置时,调用 aexa.search(**sdk_kwargs),只返回链接/标题等元数据;
  • 一旦配置了 text / highlights / summary(对应字段被塞进 sdk_kwargs),Block 会改用 aexa.search_and_contents(**sdk_kwargs),把「搜索 + 内容提取」合并为一次调用。

这意味着 include_text/exclude_text 这类作用于页面正文的过滤项,只有搭配 contents.text 一起使用时才有实质效果;纯元数据搜索下它们对标题/链接层面的过滤能力有限。设计流程时请把「是否要正文」先想清楚,避免无效调用。

输出参数与数据模型

运行结束后,Block 会按 Output 的定义依次产出多个输出,其中部分输出会重复触发多次(即“流式产出”):

输出 含义 类型
error 请求失败时的错误信息 str
results 本次搜索结果完整列表(一次性产出整个 list) List[ExaSearchResults]
result 单条搜索结果——对列表里每条结果都会产出一次,便于在图中逐条分叉处理 ExaSearchResults
context 已格式化的搜索上下文串,可直接作为 LLM 提示词的输入 str
search_type auto 模式下最终由服务端挑选出的检索方式 str
resolved_search_type 本次请求实际生效的检索方式(neural 或 keyword) str
cost_dollars 本次请求的成本明细 CostDollars

说明:在 run() 的实现里(search.py),先 yield "results" 整体列表,再对每个结果 yield "result",随后依次产出 contextresolved_search_typecost_dollarscontext 依赖服务端在 response.context 中返回(即 contents 子配置里的 context 开关开启时才存在)。

单条 result 的数据模型 ExaSearchResults(定义于 helpers.py,由 from_sdkexa_py SDK 的响应转换而来)包含以下字段:

字段 含义
id 文档 ID
url 结果网页 URL
title 网页标题
author 作者
publishedDate 发布日期
text 抽取到的正文文本
highlights / highlightScores 相关高亮片段及其打分
summary LLM 生成的摘要
subpages 顺带抓取的子页面列表
image / favicon 图片与站点图标(MediaFileType
extras {links, imageLinks} 附加链接信息

运行原理:一次搜索请求的完整调用链

把输入输出串起来,ExaSearchBlock.run() 的完整工作流如下(对应 search.py):

  1. 组装基础参数querynum_results(由 number_of_results 映射)必然进请求;随后逐字段追加可选参数——type/category 取枚举的 .valueuser_location 原样透传,include_domains/exclude_domains 在非空时写入,include_text/exclude_text 同理。
  2. 日期格式化:四个日期参数(start/end_crawl_datestart/end_published_date)在非空时统一调用 datetime.isoformat() 转成 ISO 8601 字符串再传给 SDK(这正是这些字段类型被标注为 str (date-time) 的原因)。
  3. 内容配置转换process_contents_settings()ContentSettings(含 livecrawl、subpages、context 等全部子项)转成 camelCase 的 API 参数对象。
  4. 创建客户端并发起请求:用凭证里的密钥 AsyncExa(api_key=...),依据上一步是否有内容提取需求,选择 search_and_contentssearch
  5. 结果归一化:SDK 返回的每条 ResultExaSearchResults.from_sdk() 转成平台数据模型,再按顺序 yield 到各输出端。
  6. 成本回收merge_exa_cost(self, response) 从响应中提取 cost_dollars.total(兼容 dataclass/dict/camelCase/snake_case/裸字符串等各类响应形态,见 helpers.py),并写入 NodeExecutionStats.provider_cost,用于平台的用量统计与积分结算。若 Exa 未报告成本信息(例如部分 webset CRUD 场景),该步骤会自动跳过,不会中断流程。

值得注意的是它不手动 catch SDK 异常:请求失败路径由 Block 运行框架统一兜底并把错误写入 error 输出。

典型应用场景

原文档给出了三类代表性的用法,这里结合上面的输入能力做进一步展开:

  • 竞品研究(Competitive Research):把 type 设为 neuralcategorycompany,再用 published_date 区间约束到最近几个月,即可抓取某行业内近期有新闻或融资动态的公司。在 AutoGPT 平台里可以接一个「每家公司发一条 result」的分支,对逐条结果继续做正文抽取或 LLM 总结。
  • 内容策展(Content Curation):面向 Newsletter 或内容聚合,用 category = research paper / news 过滤来源类型,开启 contents.textcontext,一次运行就能拿到多篇可直接改写摘要的候选材料。context 输出本身就是为「丢进提示词」而设计的格式化文本。
  • 销售线索挖掘(Lead Generation):将行业、规模、近期活跃度等线索条件翻译成 query + user_location + 发布时间窗口的组合,配合 include_domains 限定权威来源,输出 results 后即可交给后续数据清洗或 CRM 写入流程。

参考配置示例

下面给出一份贴近上述「竞品研究」场景的输入配置(字段取值全部来自上文输入表,可直接在构建器中对照填写,也可作为 API 层调用该 Block 时的参数参考):

query:                "AI infrastructure companies with recent funding"
type:                 neural
category:             company
number_of_results:    8
start_published_date: 2026-01-01T00:00:00Z
include_domains:      []
exclude_domains:      ["reddit.com"]
contents.text:        { maxCharacters: 3000 }
contents.highlights:  { numSentences: 2, highlightsPerUrl: 1, query: "funding round" }
contents.summary:     { query: "company overview and recent funding" }
moderation:           true

下游可直接使用 context 输出作为 LLM 的参考资料,或用逐条产出的 result 对每家公司分别触发后续 Block。

小结

Exa Search Block 在 AutoGPT 平台里扮演着「高质量网页入口」的角色:auto 模式让不熟悉 Exa 细节的用户也能直接上手,而 type / category / 域名与日期双轴过滤 / contents 内容提取的组合,则为深度流程提供了足够精细的控制面。要完全掌握它,记住三点即可:用 contents 决定是否走 search_and_contents 的正文提取路径;把 context 输出当作送给 LLM 的现成上下文;通过 cost_dollarsresolved_search_type 观察每次调用的成本与真实生效的检索方式。文中引用的输入输出定义、默认值与调用链均可回到 search.pyhelpers.py_config.py 中逐一验证。

登录后查看全文
热门项目推荐
相关项目推荐