Exa Canon — 搜索引擎 DAG 编排系统

> 一句话版本:Exa 搜索引擎内部系统。把搜索流程从一堆 if/else 函数调用改造成 DAG(有向无环图),自动并行、自动取消、自动追踪、自动缓存。为 AI Agent 写代码的时代设计的搜索架构。

项目信息
来源[exa.ai/blog/composing-a-search-engine](https://exa.ai/blog/composing-a-search-engine)
公司Exa(AI 搜索 API)
系统Canon(内部搜索编排器)
日期2026 年

背景

Exa 每天处理数十亿搜索请求,服务数千个不同的 AI Agent。搜索不再是简单的"查索引 → 排序 → 返回":

简单请求变成了 20+ 节点类型的 DAG,带很多分支。

核心设计:搜索即 DAG

Canon 把搜索管道定义为 DAG:


{
  "nodes": {
    "dense": {
      "type": "retrieve",
      "index": "web",
      "numResults": 50
    },
    "fetch": {
      "type": "fetch_content",
      "source": "dense"
    }
  },
  "root": {
    "node": "fetch",
    "output": "docs",
    "query": "effect-ts fiber runtime evaluation signal",
    "numResults": 10
  }
}

DAG 提供的能力

能力说明
自动并行运行时知道依赖关系,无依赖的节点自动并行
持久执行节点失败可以从该节点重试,不用从头执行
可内省DAG 是数据,可以可视化、验证、分析
定义与执行分离同一 DAG 可以同步测试、分布式生产、dry-run 预览

DAG 不适用的场景

运行时设计

Pull-based 系统:节点只在下游消费者请求时才运行(惰性求值)。

关键特性:

示例流程


查询进入
  ├ 并行:web index 检索 / news index 检索 / knowledge graph 检索
  │   ↓
  │   web index 先返回(赢得竞态)
  │   → 取消 news index 和 knowledge graph
  │
  ├ fetch content(拉取 web index 结果)
  ├ rerank(拉取 fetch 结果,运行一次,缓存)
  ├ 并行:post-processing
  └ 返回结果 + 完整 trace

可观测性

之前的问题

Canon 的方案

为 AI Agent 写代码的时代设计

核心洞察:2026 年几乎所有代码由 Agent 编写。Agent 需要结构引导它们一次性写对。

旧世界的问题

Canon 的解法

DAG 通俗解释

用搜索 "best restaurants near me" 举例:

旧方式(if/else 串行)


results = search_index("best restaurants near me")  # 100ms
localized = localize(results, lang="zh")             # 50ms
ranked = rerank(localized)                           # 80ms
cleaned = moderate(ranked)                           # 30ms
return cleaned[:10]                                  # 总计 260ms,串行

问题:如果用户用英文搜,localize 白跑 50ms。想加"新鲜度过滤"?要在中间插代码。

DAG 方式


用户查询: "best restaurants near me"
         │
    ┌────▼────┐
    │ classify │  ← 什么类型的查询?→ "local_search"
    └────┬────┘
         │
    ┌────┼────────────┐        ← 并行执行
    ▼    ▼            ▼
  web   maps    knowledge_graph
  index index   search
  60ms  40ms      90ms
    │    │            │
    │    │      ┌─────┘
    │    │      │ maps 先返回 → 取消 knowledge_graph
    │    └──────┤ web 也返回
    └─────┬─────┘
          ▼
      merge → rerank → moderate → return top 10
                                      总计 ≈ 150ms
旧方式DAG
并行手写,容易忘自动,运行时算
加新步骤改代码,怕改坏加个节点,不影响其他
某步失败手动 try/catch运行时自动重试/降级
调试"为什么没返回X"翻日志图上有完整路径
某个索引慢了全卡住其他先返回的先用

菱形依赖缓存:两个节点共享同一个上游祖先时,祖先只计算一次,结果缓存共享。

一句话:DAG 就是一张"任务依赖图"。能并行的全并行,没人需要的任务立刻取消。

分析

优势

局限性

与 Jay 的关联

评分

维度评分 (1-10)说明
架构设计9DAG + pull-based + 全函数,教科书级
实用性8解决真实的十亿级搜索编排问题
创新性7DAG 编排不新,但搜索场景应用深入
开放性3不开源,只有博客文章
与 Jay 的关联6架构思路有参考价值
**总分****6.6**搜索引擎编排的优秀架构案例