关闭

Tryaivo™技术

LangGraph 文档 4 种喂法实测,优化过的 llms.txt 打赢向量库

2026-11-14 02:06:30 浏览:

一句话结论:把 26 万 token 的 LangGraph 文档用 4 种不同方式喂给编码代理,错误最少的不是向量库,而是"用 LLM 重写过每条链接描述"的 llms.txt;配 Claude Code 时,5 道题生成的脚本全部拿到了部署分。

背景:代理不是不会写代码,是它读的文档不对

LangGraph 这类框架有两个特点,直接把问题放大了:

一是文档体量。整套 LangGraph 文档约 26 万 token,塞得进 200k 上下文,但也快撑满了;二是 API 变动快,模型预训练里的写法经常是旧版,StateGraph 的参数、langgraph.json 的字段名一次小版本就会变。

结果就是我们做内容站时最熟悉的那种场景:代理写出来的代码,import 一个根本不存在的模块,函数签名长得像真的但参数是编的。LangChain 的 Lance Martin(现 Anthropic 技术团队成员)在 2025-04-03 的公开基准里专门统计了这一点——11 个报错里有 6 个属于"导入了不存在的模块或函数",也就是典型的 API 幻觉。

他做的实验很朴素,但结论对每一个做文档站、API 站的人都直接可用:同一套 5 道代码题,同一套 LangGraph 文档,只改"文档怎么递给代理"这一个变量。

落地清单:4 种喂法是怎么搭的

1. 四种变量,其余全不动

编号 喂法 具体做法
A Context Stuffing 把 LangGraph 全部文档(约 266k token)一次性塞进上下文
B 标准 llms.txt 给代理一个能读 llms.txt 的 MCP 服务器 + 一个 URL 加载工具
C 优化版 llms.txt 用 LLM 把 llms.txt 里每一条链接的描述重写一遍,其余同上
D 向量库 文档切 8k token 块、k=3、text-embedding-3-large,通过 MCP 服务器语义检索

实验条件写清楚:Claude Code 用 claude-3-7-sonnet-20250219,Cursor 用 0.47.8(thinking 模式下的 claude-3-7-sonnet);每道题的脚本按 4 项打分——能否 import(0-1)、能否跑通(0-1)、LLM 质量分(0-1)、能否部署(0-0.5),单个脚本满分 3.5,5 道题合计上限 17.5。每种喂法跑在独立分支上,防止互相污染。

2. llms.txt 的问题出在"描述"两栏,不在格式

B 和 C 的差别只有一处,但正是大多数站点的通病。看 LangGraph 现在的 llms.txt 真实片段(官方地址 langchain-ai.github.io/langgraph/llms.txt,抓取于 2026-11-14):

# Docs by LangChain: LangGraph (Python)

> Markdown index of the LangGraph (Python) documentation.

## LangGraph (Python)

- [Memory](https://docs.langchain.com/oss/python/langgraph/add-memory.md)
- [Application structure](https://docs.langchain.com/oss/python/langgraph/application-structure.md)
- [Backward compatibility](https://docs.langchain.com/oss/python/langgraph/backward-compatibility.md)
- [Checkpointers](https://docs.langchain.com/oss/python/langgraph/checkpointers.md)
- [Choosing between Graph and Functional APIs](https://docs.langchain.com/oss/python/langgraph/choosing-apis.md)
- [Deployment](https://docs.langchain.com/oss/python/langgraph/deploy.md)
- [Quickstart](https://docs.langchain.com/oss/python/langgraph/quickstart.md)

格式完全合规:一个 H1、一行 blockquote、H2 分节、绝对 URL、链接指向 .md 页面。但每一行都没有"这页能回答什么问题"的说明。人类读者靠标题能猜,代理只能靠标题猜——而代理猜错的代价,是去抓一堆不相关的页面,再把两三篇的内容混在一起编。

优化版就补这一栏。对照写法:

## LangGraph (Python)

- [Application structure](https://docs.langchain.com/oss/python/langgraph/application-structure.md): 讲解 LangGraph 应用的目录结构,langgraph.json 的必填字段(dependencies/graphs/env),以及本地 server 启动时读取哪个入口文件。当问题涉及 langgraph.json 写法或部署失败时优先读这篇。
- [Choosing between Graph and Functional APIs](https://docs.langchain.com/oss/python/langgraph/choosing-apis.md): 给出 StateGraph 与 @entrypoint 两种 API 的适用边界与互相迁移方式,含同一逻辑的两种实现对照。当问题提到"该用哪个 API"时读这篇。
- [Backward compatibility](https://docs.langchain.com/oss/python/langgraph/backward-compatibility.md): 列出各版本间的破坏性变更与仍需保留的旧写法。当生成的代码被提示弃用或参数不匹配时读这篇。

差别不在长度,在"这页解决什么问题、什么时候读它"。这正是 C 胜过 B 的全部原因,也是 llms.txt 能被代理真正用起来的前提。

3. 用 LLM 批量重写描述:不要靠人肉

Lance Martin 为此单独做了一个包 llmstxt_architect:抓取 llms.txt 里每一条 URL 的正文,让 LLM 产出一句"内容摘要 + 适用场景",再回填到描述位。流程可以照抄成三步:

  1. 解析 llms.txt,抽出所有 - [标题](URL) 行;
  2. 逐条抓取对应 .md 页面正文,交给模型生成"这页讲什么 / 什么时候该读"的两段式描述;
  3. 回填,校验没有丢链接、没有改 URL、没有多出链接。

关键是第 3 步:重写描述时只动冒号后面的部分,URL 和标题一个字都不改,否则代理拿到的就是一份指向空气的索引。

4. 让代理"能读到":MCP 侧的两件套

光有文件不够,得有通路。实验里 B/C 两种喂法都通过 MCP 服务器把 llms.txt 暴露给代理,配一个 URL 加载工具(对应 LangChain 开源的 mcpdoc,该仓库目前已归档,逻辑仍可参考)。Cursor 侧配置大致是:

{
  "mcpServers": {
    "langgraph-docs": {
      "command": "uvx",
      "args": [
        "--from", "mcpdoc",
        "mcpdoc",
        "--urls", "LangGraph:https://docs.langchain.com/oss/python/langgraph/llms.txt",
        "--transport", "stdio"
      ]
    }
  }
}

代理侧拿到的是一个 fetch_docs 类工具:先读索引、按描述挑页面、再取正文。注意这是把"检索"这一步交给模型推理,而不是交给向量相似度——这也是 C 能赢 D 的原因。

5. robots 与爬虫放行:这件事和 llms.txt 无关

需要说清一点,避免踩错方向:llms.txt 只对"已经在读你文档的代理"有用,对"让 AI 搜索发现你"基本无效。Ahrefs 2026 年 5 月读的 137,210 个域名日志里,97% 的 llms.txt 从未被任何东西请求过(经 lukeocodes.dev 2026 年转述,非第三方复现)。

所以 robots 这边不要做无谓操作:不要为了 llms.txt 去额外放行一堆爬虫,也不要把 llms.txt 写成 robots.txt 的克隆(出现 User-agent、Allow、Disallow 字段是很多自动生成器的通病,对 LLM 完全无效)。

结果:四种喂法的错误分布

实验的错误分类统计(来源:Lance Martin 2025-04-03 基准,eval 日志 eval_run_20250402 公开):

喂法 导入错误 图配置错误 类型错误 API/服务错误 合计
llms-full(全文塞入) 3 1 1 0 5
标准 llms.txt 2 1 0 0 3
优化版 llms.txt 0 0 1 0 1
向量库 1 0 0 1 2

口径:错误数为 5 道题 × 2 个代理跑完后人工/脚本核对的累计条数,不是通过率。整体排序稳定为:优化版 llms.txt > 向量库 > 标准 llms.txt > 全文塞入。

三个可直接对照的观察:

  1. 全文塞入错误最多,且 5 个错误里 3 个是"导入不存在的模块"——26 万 token 全在上下文里,反而更容易把不同章节的概念搅在一起。
  2. 优化版 llms.txt 把导入错误压到 0,唯一剩下的 1 个是类型错误。配 Claude Code 时,5 个脚本的部署分全部拿到(关键是 langgraph.json 格式正确,这需要代理同时理解应用结构和本地 server 两篇文档)。
  3. 向量库不算差,但对切块大小、k 值、embedding 模型敏感,实验者本人也承认"可能没调到最优"。换句话说,RAG 调参的功夫,用重写 llms.txt 描述这一件事就能省掉大半。

外部旁证(均为服务商自述、非第三方复现,谨慎看待):Mintlify 2026-07-17 的基准用 20 个文档站 × 5 个问题 × 4 种格式共 2,400 次运行,结论是 HTML 直供时代理每任务平均撞 2.23 个死链、页面底部加一行 llms.txt 链接后降到 0.11(约 −90%),同时准确性在各格式下都保持在 90% 区间——"赢的是效率,不是正确性"。其 2026-09-01 的层级拆分复盘(10 站 200 个任务)称代理完成任务快 52.1%、token 少 44.8%。

复盘:3 条可直接抄的配置

  1. 给每条链接补"什么时候读我"。标题 + URL 只是目录,描述才是让代理做对选择的那一栏。批量重写用 LLM 跑,人工只做校验。
  2. 索引只管导航,正文交给 .md 兄弟文件。llms.txt 控制在 1 万 token 内,每页提供 .md 版本,llms-full.txt 只给"要一次读完"的场景(IDE 索引、RAG 管线)。正文塞进索引,等于把优势又还给了全文塞入。
  3. 把"检索"留在模型侧,而不是向量侧。llms.txt + URL 加载工具 = 以整篇文档为检索单元的 RAG,模型看描述自己决定取哪篇;这条路对方的说法是省掉调参,对站点方是省掉一堆中间层。

两条踩坑提醒

  1. 别把 llms.txt 当 AI 搜索排名手段卖。Google 明确表示没有支持计划,主流 AI 爬虫日志里访问量接近零,多项引用研究也没测出效果。它服务的是"已经在读你文档的编码代理",这个边界写进方案里,比吹效果安全得多。
  2. 描述重写会引入新的幻觉。让 LLM 重写描述时,它有可能把某页讲成另一页的内容——这比不写描述更糟,因为代理会照着错误描述去抓错页。校验方式:随机抽 10% 的条目,人工比对描述与目标页正文的 H2 标题,不一致就重跑该条。

标注

  • llms.txt 规范版本:v2(2026-08 更新,加入页面 .md 版本约定、rel="alternate" type="text/markdown" 与 rel="describedby" 等);
  • 规范状态:由 Jeremy Howard(Answer.AI)于 2024-09-03 提出,托管于 llmstxt.org,属于开放提案/事实标准,未被任何 LLM 厂商官方确认为读取协议;
  • 一手来源:Lance Martin《Vibe code benchmark》2025-04-03,实验仓库与 eval 日志公开;LangGraph llms.txt 实文件抓取于 2026-11-14;
  • 旁证来源:Mintlify 基准(2026-07-17 / 2026-09-01,服务商自述)、Ahrefs 日志研究(2026-05,经 lukeocodes.dev 转述);
  • 复盘时间:2026-11-14。