数据截至 (上游 commit 136cd875b154)
上下文即文件系统:构建与导航
30 秒导读: nao 的核心赌注是——别把整个数据仓库的 schema 一股脑塞进模型的上下文窗口。 它先用 CLI(
nao sync)把每张表的列、预览、画像写成磁盘上一堆.md文件,按type=/database=/schema=/table=的目录层层组织;然后给 agent 一套文件系统工具 (search、grep、read、list),让它像人翻代码库一样,用到哪张表才去读哪张表。 文件夹的层级结构,天然就是"渐进式披露"。
本章讲清楚这条主线:磁盘上的上下文怎么被构建出来(CLI 侧),长什么样(布局约定), 以及 agent 怎么导航它(工具带 + 沙箱)。至于 agent 的主循环见 02-agent-loop.md,SQL 执行内部见 03-tools.md, 把这些文件装配进系统提示见 04-system-prompt.md。
1. 这是什么(零基础也能懂)
先说要解决的痛
假设你在给一支数据团队做一个"用大白话问数据"的 AI agent。用户问:"上个月复购率多少?" agent 得先知道:有哪些表、每张表有哪些列、列是什么类型、哪张表常和哪张表 join…… 这堆信息叫 schema / 元数据(metadata,描述数据的数据)。
最粗暴的做法是:把整个仓库所有表的 schema 全拼成一大段文字,每次对话都塞进模型的 上下文窗口(context window,模型一次能"看见"的文本上限)。表一多就爆:几千张表的 DDL 既超长又烧钱,而且模型 90% 的内容根本用不上。
nao 的答案:把上下文当文件系统
nao 换了个思路——把元数据落到磁盘,做成一个"上下文文件夹",让 agent 按需去翻。
- 一句话定义: nao 是一个"分析型 agent"框架;它把数据源的元数据同步成磁盘上的一棵 markdown 文件树,agent 用文件系统工具逐层发现,而不是被一次性灌满 schema。
- 给谁用: 数据团队搭 agent,业务同学用自然语言问数。
- 一句话直觉/类比: 把它想成给数据仓库生成一份"代码库"。就像你不会把整个 repo 粘进
聊天框、而是让编码 agent 自己
grep、自己read那样——nao 让数据 agent 也这么干。 上下文 窗口是内存,磁盘上的上下文文件夹是硬盘。
用起来什么样
三条 CLI 命令就把这套东西立起来(README 的 Quickstart):
nao init # 脚手架:建好 databases/ queries/ docs/ ... 空目录 + RULES.md + .naoignore
nao sync # 把数据源同步进上下文:为每张表写出 columns.md / preview.md / ...
nao chat # 起聊天 UI;agent 用文件系统工具翻这些文件来回答问题
nao sync 跑完,磁盘上会长出这样一棵树(这是 nao 自带 example 项目的真实产物):
databases/
└── type=duckdb/
└── database=jaffle_shop/
└── schema=main/
└── table=customers/
├── columns.md # 列名 + 类型
├── preview.md # 前 N 行样例数据
├── description.md # 表说明
└── profiling.md # 每列的空值率/去重数/分布画像
columns.md 里就是给模型看的、精炼过的一小段:
# customers
**Dataset:** `main`
## Columns (7)
- customer_id (int32)
- first_name (string)
- ...
关键:agent 不需要一开始就看到这些。它先看到"有个 customers 表",要用了再 read 它的
columns.md。这就是本章反复要讲的那句话——文件系统 = 渐进式披露。