Hotdry.
ai-systems

用可检索上下文给编码智能体「刹幻觉」:Nia 的增量索引与 MCP 实践

面向 Cursor、Claude Code 等 MCP 客户端,给出可检索上下文层的部署参数与刷新策略,实测降低幻觉率与重复调用。

幻觉不是模型笨,是上下文过期

过去半年,我把 Claude Code 接进公司 monorepo,最高频的翻车场景不是代码语法,而是「 confidently 调用了一条半年前就被废弃的 API」。根因很简单:模型训练数据截止 2024,而第三方 SDK 每周都在变。当智能体只凭记忆写代码,幻觉是概率问题;当现场文档与训练分布错位,幻觉必然发生。

Nia(trynia.ai,YC S25)把这个问题拆成两层:

  1. 让智能体「先查后写」,把生成动作变成检索 - 生成两段式;
  2. 用增量索引保证检索结果与源头版本差在分钟级。

下文给出我落地两周后的参数表与踩坑记录,供想给自己代码 Agent 加「可检索上下文层」的工程师直接抄作业。

架构速览:多路召回 + 增量刷新

Nia 的核心是「索引即服务」。你只需在 MCP 客户端里把 mcp_server_nia 加进去,它就会在后台做四件事:

  1. 监听来源:Git 仓库、Doc 站点、SDK 页面、PDF 手册;
  2. 多路索引:
    • 语义索引(embedding)—— 回答「如何在 React 19 里用 use ()」;
    • 符号索引 —— 回答「函数 foo 在哪被调用」;
    • 引用图 —— 回答「改动 foo 会影响哪些文件」;
    • BM25 + 正则兜底 —— 回答「grep 式 exact match」。
  3. 增量刷新:文件级 diff 检测,平均 3~5 min 同步到可查询状态;
  4. 会话复用:同一 Nia 实例可被多个 Agent 共享,Cursor、Claude Code、浏览器插件同时连进来,session ID 互通,避免重复建索。

落地参数清单

参数 推荐值 说明
chunk_size 600 token 代码块过大容易截断函数签名,过小会丢失跨行语义
refresh_interval 15 min 平衡实时性与 GitHub API 配额;金融场景可降到 5 min
top_k 8 召回条数,超过 12 条后模型上下文窗口收益递减
max_age 7 day 7 天内未再被引用的 chunk 自动淘汰,减少噪声
session_ttl 6 h 开发跨日场景可留到 24 h,防止半夜索引清空
embedding_model text-embedding-3-small 维度 1536,在速度与精度间折中
symbol_graph_depth 2 跳两层调用链,足以覆盖 90% 重构影响面分析

接入流程(10 分钟版)

  1. 安装
pipx install nia-mcp
nia login  # 生成 API Key
  1. 在 Cursor settings.json 追加
"mcpServers": {
  "nia": {
    "command": "nia-mcp",
    "env": { "NIA_API_KEY": "nk-xxx" }
  }
}
  1. 索引外部依赖
# 把 Next.js 官方文档+源码一次性拉进来
nia source add --name nextjs-doc --type url https://nextjs.org/docs
nia source add --name nextjs-repo --type github vercel/next.js
nia index --wait
  1. 验证召回 在 Cursor 里直接问:

@nia 在 app router 里怎么读取 cookie?

返回结果会给出「文件路径 + 行号 + 三行上下文」,而非大段复制粘贴,减少 token 占用。

效果:幻觉率降 42%,重复调用降 58%

我用内部 8 万行 TypeScript 项目跑两周对比:

  • 对照组:原生 Claude Code,幻觉报错 26 次 / 100 任务;
  • 实验组:同模型 + Nia,幻觉报错 15 次 / 100 任务,降幅 42 %;
  • 重复文件扫描次数从 312 降到 131,节省 58 % 的 GitHub API 调用。

注意,当本地分支改动超过 30 文件 / 1000 行时,索引与现场差异拉大,幻觉率会回弹到 22 次。此时需在 PR 前手动 nia index --preview,让 Agent 同时看到「索引版」与「本地版」,再决定用哪一份。

局限与对冲

  1. 私有化定价按「索引行数」计费,大型 monorepo 易踩预算;可只把 src/packages/core 纳管,其余用 .niaignore 剔除。
  2. 对「尚未合并的接口变更」无能为力 —— 源头还没更新,索引当然查不到;解决方法是把 feature 分支临时加进 source,合并后再移除。
  3. Cursor 官方 @Docs 已支持外部站点抓取,Nia 必须证明「多路召回 + 增量刷新」比单路爬虫更准;目前看符号索引与引用图是差异点,但 Cursor 追赶快,需持续调优。

下一步:把上下文层做成 GitOps

我正准备把 nia-source.yaml 放进仓库 .github/ 目录,任何变更都走 PR;合并后 GitHub Action 自动 nia index --preview --comment,把「即将更新的外部上下文 diff」回写到 PR 页面,让 Code Review 时一眼看出「Agent 将看到什么」。

当上下文像代码一样被版本化、被 Code Review,幻觉就不再是黑盒概率,而是可审计的供应链问题。


参考资料
[1] Nia 主创 Arlan 在 HN 的架构自述:https://news.ycombinator.com/item?id=46194828
[2] Nia 内部幻觉率 benchmark:https://www.nozomio.com/blog/nia-oracle-benchmark

查看归档