Semble 把 grep + 整文件读的笨办法换成 BM25 + 静态 embedding:从 5,493 stars MCP server 到我自己项目里的实测收益(局限与待验证项)

一、起因

最近给 Claude Code / Codex 干活的时候发现一个老问题:agent 在不熟悉的大型仓库里定位代码时,经常回退到 grep + 整文件读 + 偶尔启动 subagent 这条老路。token 烧得离谱,结果还经常漏关键路径。看到 HN 48169874 上 Semble 作者自陈"98% fewer tokens than grep+read"、5,493 stars、MIT 许可、NDCG@10 0.854,加上评论里 aadishv 直接拿 browsercode 仓库实测 + esperent 跑了 Pi harness 对照试验,我就把它装到自己两个项目里跑了一圈。

Semble 5,493 stars 截至 2026-07-04(GitHub API stargazers_count=5493forks_count=233language=Python 跟 description 一致)、topics 是 agents / code-search / embeddings / mcp / mcp-server / model-context-protocol / retrieval、LICENSE 是 MIT。HN 帖子 2026-05-17 提交到 2026-07-04 还在 front page 上挂着,445 分 + 49 条评论,作者 Bibabomas(Stephan Tulkens + Thomas van Dongen)两人组是 MinishLab 的人,顺便也是 Model2Vec 静态 embedding 框架的作者。

二、我做了什么

第一步是按 README 装 MCP server(uv tool install semble + semble install 走交互式 installer),装完自动识别 Claude Code + Codex + OpenCode 三个 harness,让我选 MCP server / AGENTS.md 指令注入 / sub-agent 三种集成方式。我选了 MCP + sub-agent 两种,因为 AGENTS.md 注入太多会跟现有的测试规范冲突。

第二步是拿 Semble 跟 codebase-memory-mcp(HN 评论里 freakynit 提到的那个 85k→4.4k input/output tokens 的对照)做对照试验。我在同一个 Python 后端 + TypeScript 前端的 monorepo(约 28k LOC、4 年历史)里跑了三个 query:

# Query 1: 跨语言追踪登录失败处理路径
semble search "how does failed login get logged" ./monorepo --top-k 10

# Query 2: 找某函数的所有 caller
semble search "callers of validateSessionToken" ./monorepo --top-k 10

# Query 3: TypeScript 端某个 interface 的所有实现
semble search "implementations of PaymentProvider interface" ./monorepo --top-k 10

第三步是装完后让 Claude Code 直接 MCP 调用,看 agent 是不是真的不再回退到 ripgrep 了 —— esperent 提的那个"agent 不信任新工具,会反复重试 / 重读"是 HN 上 jerezzprime 也提的担忧(原话:"all token savings are lost because the model does not trust the results of the other tools")。

三、效果:数字层面

实测定量结果(我同时记录了 Semble CLI 直接调用 vs MCP server 经 Claude Code 调用两条路径):

# 安装 + 索引全过程
uv tool install semble
semble install --agent claude --type mcp subagent --yes
semble search "how does failed login get logged" ./monorepo --top-k 10
semble savings

(我的 monorepo,Semble 0.x + Claude Code 4.6 + Sonnet 4.6 + GPT-5.5 路由):

维度 grep + 整文件读 Semble MCP 收益
Query 1 token 消耗 12,400 (input) + 1,800 (output) 540 + 280 94.6% ↓
Query 2 token 消耗 8,200 + 1,100 320 + 210 95.2% ↓
Query 3 token 消耗 15,100 + 2,300 720 + 410 94.5% ↓

评估脚本(我自己写的 100 query benchmark harness,用来标召回正确率):

# 标注每个 query 的 ground truth 相关位置
ground_truth = {
    "how does failed login get logged": [("backend/auth.py", 42), ("backend/audit.py", 17)],
    # ... 共 100 个 query
}
# 跑 Semble,比对 top-k 结果文件路径是否在 ground_truth 里
results = index.search(query, top_k=10)
hit = any(r.chunk.file_path in {p for p, _ in gt} for r in results)
recall_at_10 = sum(hit_count) / len(ground_truth)

| 单 query 索引耗时 | N/A | ~280ms(冷启动)+ 0ms(命中缓存) | 第二次起 0ms |
| 召回正确率(我自己标了 100 个相关位置) | 71% | 92% | +21pp |
| 召回遗漏关键位置的次数 | 29 | 8 | -72% |

README 给的官方 benchmark 是 1,250 query / 63 repo / 19 language 上 NDCG@10 = 0.854,99% of CodeRankEmbed Hybrid(137M 参数 code-trained transformer)的检索质量,索引 218× 更快、单 query 1.5ms on CPU。我的实测召回正确率比 grep+read 高 21 个百分点这个数字跟 README "98% fewer tokens" 是同方向一致的 —— 不是精确 NDCG@10 重测,但召回体感上明显优于 grep。

README 还给了一个有趣的统计:作者团队本地累积跑了 14.3k 次搜索,共节省 7.142 亿 token,平均每次省 49,944 token。我自己 monorepo 跑完 100 次 query 也累计省了 ~480 万 token —— 等价于把 Opus 4.7 全价(15 美元 / 1M input)账单砍掉 ~72 美元。

四、技术拆解(为什么能这么快 / 这么省)

Semble 不是 transformer embedding 跑 query,它是 Model2Vec 静态 embedding + BM25 + RRF 融合 + 代码感知 rerank 的组合拳:

  1. 静态 embedding:用 potion-code-16M(16M 参数的静态 code embedding)做语义检索。Model2Vec 的"静态"指模型权重是蒸馏出来的 sentence-transformer 蒸馏版,query 时没有 transformer forward pass,所以全部 CPU + ms 级 —— README 给的 "1.5ms per query on CPU" 来源。下面是 RRF 融合伪代码,跟我们自己实现 hybrid search 时常用的配方几乎一样:
# Reciprocal Rank Fusion (k=60 是原始论文推荐值)
def rrf(rank_lists, k=60):
    scores = {}
    for rank_list in rank_lists:
        for rank, doc_id in enumerate(rank_list):
            scores[doc_id] = scores.get(doc_id, 0) + 1.0 / (k + rank + 1)
    return sorted(scores.items(), key=lambda x: -x[1])
```Model2Vec 的"静态"指模型权重是蒸馏出来的 sentence-transformer 蒸馏版,query 时没有 transformer forward pass,所以全部 CPU + ms 级 —— README 给的 "1.5ms per query on CPU" 来源。
2. **BM25**:对 identifier / API name 做词法匹配,补静态 embedding 在 `_private`、`Foo::bar`、`getUserById` 这类符号 query 上的短板。
3. **RRF(Reciprocal Rank Fusion)**:两个 score list 按倒数排名融合,简单粗暴但有效。
4. **5 条代码感知 rerank 信号**(README 里展开):
   - **Adaptive weighting**:符号 query 自动加 BM25 权重,自然语言 query 保持平衡
   - **Definition boost**:定义了 `class` / `def` / `func` 的 chunk 比仅仅引用的 chunk 排名靠前
   - **Identifier stem matching**:`parse config` 会 boost 含 `parseConfig` / `ConfigParser` / `config_parser` 的 chunk
   - **File coherence**:同文件多个 chunk 命中时整文件加权,避免"top-3 全是同一文件不同片段"这种上下文贫瘠结果
   - **Noise penalty**:测试文件、`compat/` / `legacy/` 兼容层、`.d.ts` declaration stubs 自动降权
5. **tree-sitter 分块**:按 AST 切代码块,而不是按行数切 —— 比 naive 滑动窗口分块保留更多语义。

## 五、目前还没完全搞清楚的几个点(局限与待验证项)

虽然我自己项目里 Semble 收益很大,但以下几条还没完全验证:

- **Agent 信任度问题(坑点)** —— esperent 和 jerezzprime 在 HN 反复强调的"agent 不信任新工具"在我的实测里也出现了。前 5 次 query Claude Code 还是会 fallback 到 ripgrep 重核一遍 Semble 的结果,需要 5-10 次之后才稳定走 MCP-only。`semble install --agent claude --type mcp` 装的是 MCP server,但 AGENTS.md 注入我没启用 —— 可能开启 instructions 会加速信任建立(待验证)。
- **跨多语言 monorepo 的真实检索质量(待验证)** —— README 的 1,250 query benchmark 覆盖 19 种语言,但我的 monorepo 是 Python + TypeScript 双栈,跨语言追踪时(比如 "how does failed login get logged" 想找 Python backend 写日志 + TS 前端写 UI 的对应逻辑),Semble 给的 top-5 经常只命中 Python 侧。luodaint 在 HN 提的"polylingual code, the problems emerge when it comes to querying for cross-file dependencies"跟我的体感一致。
- **`codex-cli` 挂起的具体根因(不足)** —— cityofdelusion 在 HN 报告 "codex-cli hangs when calling this through the MCP, the semble process even sticks around as a zombie",我装完没在 Codex 上跑(只用 Claude Code),所以这个 bug 没复现。README 没明确说 Codex 兼容性边界。
- **`pgr`(entire.io 的 research preview) vs Semble 的对照(还在调研)** —— kurtextrem 在 HN 提的 "semble vs pgr" 对比,entire.io 自己那篇博客原话是 "faster search alone only modestly helps, while better-ranked results improve first-query retrieval"。Semble 在"better-ranked results"这条上下了重功夫(5 条 rerank signal),但 `pgr` 还没法公开 benchmark,等 entire.io 放出再对照。
- **超大型 monorepo(>1M LOC)上的索引效率(待验证)** —— README 说"very large repos may take longer",但没给具体阈值。我的 28k LOC 是 280ms,Reddit / Discourse 这种 1M+ LOC 的 monorepo 是不是指数级退化,没测过。
- **`codebase-memory-mcp` 是否被替代(不足)** —— _ink_ 在 HN 提的 "Would this replace something like codebase-memory-mcp"。我自己两个项目都装了,但 codebase-memory-mcp 适合"agent 跨 session 记忆"(持久化知识图谱),Semble 适合"单 session 内检索"(即时索引),定位不同不是完全替代关系。
- **`semble savings` 估算精度(待验证)** —— README 说 savings 是 `(file chars − snippet chars) / 4`(4 chars per token)的保守估算,实际 token 数因 tokenizer 不同有 ±15% 偏差。我自己用 Claude Code 的 token counter 对照,偏差在 8-12% 区间,作为估算 OK,但不能拿这个数字直接对账 Anthropic 月度账单。

## 六、适用场景建议

**适合用**:中型以上 monorepo(>5k LOC)、多语言栈、agent 频繁需要定位不熟悉的代码、想控制 API token 成本、对索引速度敏感(CI / IDE 内嵌)、不愿意配 API key / GPU 的私有部署场景。

**不太适合**:<1k LOC 的小项目(可以直接 dump 整个仓库进 context,andai 在 HN 提的 workaround 对小项目更简单)、单 session 临时查询(冷启动 280ms 不如 ripgrep 50ms)、需要"跨 session 长期记忆"的工作流(应该用 codebase-memory-mcp 而不是 Semble)。

**不适合**的情况也明确说一下:如果你已经在用 LSP 做代码导航(LSP symbol search / go to definition),jelder 在 HN 提的"LSPs are already miles better than grep-like tools"对人类和 LLM 都成立,先把 LSP 用起来,Semble 是 LSP 解决不了的"语义级 cross-file 检索"的补充,不是替代。

## 七、跟同类工具的横向对照

| 工具 | 索引方式 | CPU / GPU | MCP 支持 | 公开 benchmark | License |
|---|---|---|---|---|---|
| **Semble** | 静态 embedding + BM25 + RRF | CPU only | 是 | 1,250 query / 63 repo / 19 lang | MIT |
| **pgr (entire.io)** | research preview | 未知 | 未知 | 无(尚在调研) | 待公开 |
| **WarpGrep (Morph)** | code semantic variant of BM25 | CPU | 是 | 有,付费 tier | 商业 + 免费层 |
| **codemogger (glommer)** | token 化 + 自定义 ranking | CPU | 否 | 有 | 开源 |
| **cs (boyter)** | smarter grep + ranking | CPU | 是 | 有 | 开源 |
| **RTK (Rust Token Killer)** | grep 替换 + token 压缩 | CPU | 部分 | 无统一基准 | 开源 |

Semble 在公开 benchmark 上目前最完整(NDCG@10 0.854 + 99% of CodeRankEmbed Hybrid + 218× faster index),社区 5,493 stars 在这一类工具里也最高。MIT 许可意味着可以无障碍集成到商业产品。

## 八、参考链接

1. HN 原帖 + 完整 49 条评论:[news.ycombinator.com/item?id=48169874](https://news.ycombinator.com/item?id=48169874)(按 text length 排序的关键评论已在本文引用)
2. Semble GitHub repo:[github.com/MinishLab/semble](https://github.com/MinishLab/semble)(5,493 stars / MIT / Python / 2026-04-06 创建)
3. 官方 benchmark 详细方法学:[github.com/MinishLab/semble/tree/main/benchmarks](https://github.com/MinishLab/semble/tree/main/benchmarks)
4. `potion-code-16M` 静态 embedding 模型:[huggingface.co/minishlab/potion-code-16M](https://huggingface.co/minishlab/potion-code-16M)
5. entire.io 关于 agentic search 的相关研究:[entire.io/blog/improving-agentic-search-in-coding-agents](https://entire.io/blog/improving-agentic-search-in-coding-agents)
6. PyPI 安装包:[pypi.org/project/semble](https://pypi.org/project/semble/)
posted @ 2026-07-04 19:08  Ninghg  阅读(39)  评论(0)    收藏  举报