-
auo4 AI 观察 用户
开源Leviathan:Rust单文件全文检索索引,让AI智能体查百万条记录只花436个token
给 AI 智能体配"长期记忆",现在主流有两条路。一条是把历史记录一股脑塞进上下文,1M token 的窗口看着很大,遇到百万条工单照样撑爆;另一条是让智能体用 grep 自己翻,问题是它不知道该翻多少才够——翻少了漏答案,翻多了 token 账单直接失控。
10 月 5 日开源的 Leviathan 给了第三条路:本地建一份全文索引,智能体每次提问只拿回几张排好序的"记录卡片",token 消耗跟数据集大小基本脱钩。
核心数字
作者 Joshua Gunn(@joshuagunnn,此前做高频交易基础设施,现在做智能制造)在自己的合成维护日志数据集上跑了一组对比,规模 100 万条记录、678 MB,1200 个问题:
| 指标 | Leviathan | 最优 grep 策略 |
|---|---|---|
| 单次问题中位 token | 436 | 107,122(差 245 倍) |
| 最差情况(1200 问) | 602 tokens | 9,700,000 tokens |
| top-5 相关记录召回率 | 99.0% | 96.0%(30K 字符输出内) |
| rank 1 准确率 | 98.5% | — |
| 中位延迟 | 33 ms | 92 ms |
索引构建这边:100 万条记录耗时 52 秒,索引占 1.2 GB(源数据 678 MB)。
有个细节很关键:每张结果卡片大约 450 token,不管数据集是 1K 条还是 1M 条。也就是说数据从一千涨到一百万,单次查询的成本几乎不动。
它怎么工作
底层是 SQLite + FTS5 全文索引 + BM25 排序。一次查询的流程:
- 解析 group 参数(精确匹配 → 名称 → 包含 → 模糊)
- FTS5 匹配:group 值和 filter 值是作为 token 被索引进去的,不是查完再过滤,匹配更精确
- BM25 × boost 排序
- 只解码 top N 条,输出带
shown N of M的卡片
智能体拿到的结果长这样:
leviathan search · customer C-ACME "Acme Corp" (7 tickets)
· 查询 "sso 登录密码重置后跳回登录页"
T-1001 · 2024-01-08 · rel 16.9
密码重置后登录页无限循环
状态: 已关闭 · 优先级: 高
解决方案: 密码重置时清除了旧 session cookie,已发布在 4.2.1。
临时方案: 清除站点数据。
数据源与接入
Leviathan 本身不持有数据库凭据,靠各数据库自己的 CLI 接进去:
# CSV / JSONL 直接索引
leviathan index tickets.csv --id "Ticket ID" --group customer_id --date created_at
# PostgreSQL
psql "$DATABASE_URL" -At -c "SELECT row_to_json(t) FROM tickets t" | leviathan index - -c tickets.toml
# SQLite
leviathan index app.db --sql "SELECT * FROM tickets" -c tickets.toml
# DuckDB / Parquet
duckdb -json -c "SELECT * FROM 'events/*.parquet'" | leviathan index - -c events.toml
支持 JSONL、JSON、CSV/TSV、SQLite,以及任意数据库 CLI 的 JSON 输出。字段映射写在 leviathan.toml 里:id 必填(用于 get/upsert/delete 和引用),title/text 是被搜索的文本(title 权重 2×),group 用于范围搜索,date 支持 --since/--until 过滤,filters 做 facet 过滤。
接进智能体
CLI + Skill(作者推荐):把 skills/leviathan/SKILL.md 复制到 ~/.claude/skills/ 或贴进 AGENTS.md、.cursor/rules。不用的时候 0 token,用到才加载。
MCP Server(可选):leviathan mcp 提供 4 个只读 stdio 工具 —— search(排序全文检索)、resolve_group(模糊名解析到精确 ID)、get(按 ID 取完整记录)、describe(返回数据集摘要,约 640 token/会话)。注意作者认为注册 MCP 工具在每个会话都有 token 成本,所以更推荐 CLI + Skill。
一条命令生成配置,覆盖 24 个智能体:
leviathan mcp
leviathan wrap claude # 生成 Claude Code 配置
leviathan wrap codex
leviathan wrap cursor
工程细节
- 单个静态二进制,2.5 MB:
cargo install leviathan-index或下载预编译包,无运行时依赖 - 索引是单个 SQLite 文件:可 git 追踪,也能随数据集分发
- 增量更新:
upsert/delete保持索引新鲜,内容没变就跳过重建 - 原子构建:不会出现中间状态
- 退出码规范:0 正常(零结果也是 0)、1 错误、2 请求有误、3 group 不明确——智能体能据此做可靠判断
- 安全:只读、离线、无
unsafe代码
一个实际场景
客服工单记忆是最典型的用法。智能体要回答"某个客户之前报过什么 bug",传统做法是 grep 关键词再把命中的几百条原始记录全塞进上下文,平均 10 万+ token;Leviathan 的做法是建索引、每次返回 3–5 张排好序的卡片,不超过 600 token,99% 的情况下 rank 1 就是答案。
边界要看清
这是 v0.1.0,10 月 5 日才发,Apache-2.0 开源。
- Benchmark 基于单一合成数据集(维护日志,1500 台虚构机器、6 个规模档位),作者在文档里明确说明这不是标准 benchmark,方法见
docs/BENCHMARKS.md,改动 ranking 必须附带前后对比数字才能被 merge - 对比用的 grep 策略由作者自己挑选,且测试时给了精确的机器 key(真人可能只会用机器名),所以这个 245 倍是"有利条件下的对比"
- 测试只衡量"检索是否返回相关记录",没有验证模型能不能用这条记录得出正确最终答案
- FTS5 是词项匹配,语义相似(embedding 检索)不在覆盖范围内
换句话说,Leviathan 证明的是"紧凑的排序检索"这一层有效,不是"普通文本搜索在所有大数据集上都不行"。真实数据上语言更乱、结构更杂,泛化能力得自己跑一遍才知道。
项目地址:github.com/elstongun/leviathan(Apache-2.0,Rust)
来源:GitHub 项目 README 与 docs/BENCHMARKS.md、作者发布说明、RuntimeWire、Reveneau