WrenAI 详解:给 AI Agent 的开源 GenBI 引擎
来源:Canner/WrenAI README、官方文档 docs.getwren.ai、vercel-labs/skills。Star 数 ~18k(查询当日)。
一、它是什么 / 定位
WrenAI 是 Canner 公司开源的 GenBI(生成式 BI)引擎 ,Apache-2.0 许可。一句话定位:给你已经在用的编码 Agent(Claude Code、Cursor、Cline、Codex、MCP 客户端、LangChain)装上一个"受治理的语义层 + AI 上下文层",让它们把业务问题变成正确的 SQL、生成可分享的 dashboard,而且始终不越出你的护栏。
它的口号很直白------"Your agents generate governed SQL, deploy dashboards, and keep business definitions in Git." 支持 22+ 数据源,底层引擎是 Apache DataFusion。
二、它解决什么问题(作用)
核心矛盾:Agent 能写 SQL,但经常"自信地写错" 。因为业务逻辑(指标定义、口径、枚举、单位、认可的 join)通常活在数据库外面------在文档、聊天记录、老员工的脑子里。Agent 只看得到 schema,看不到这些,所以同一个 "revenue" 在不同地方算法不一样,答案自然不可信。
Wren 的做法是把这些"数据是什么意思"单独建成一层------不是"数据在哪",而是"数据意味着什么"------以可审阅的 YAML/Markdown 存在你自己拥有的 Git 仓库里。schema 告诉 Agent 数据在哪,Wren 告诉它数据是什么意思。
三、核心功能
1. 语义层(MDL)------这是 Wren 的骨架
Wren 本身就是个受治理的语义层,用 MDL(Modeling Definition Language) 表达:
- Models / columns / relationships / views:数据的形状,与具体数仓解耦。
- Cubes & metrics:审批过的、可复用的指标定义,让 "revenue" 在任何地方都是同一个意思。
- 超越 schema 的上下文 :枚举、单位、认可的 join,写在
instructions.md和queries.yml里。
每个答案、每个 dashboard 都是先对着 MDL 规划再生成的,不是让 LLM 凭空猜。
2. 受治理的 Text-to-SQL
问题 → 对照语义层规划成 SQL → dry-plan 预校验(执行前就发现错误)→ 执行。配套护栏:row limits(行数限制)、value profiling(值探查)、结构化错误并带提示。官方 FAQ 直接说:"Yes, and governed."
3. AI 上下文层(context layer)
这是它和普通语义层最大的区别------除了 schema,还管:业务语义、审批过的定义、示例、记忆 、治理规则。本地 LanceDB 记忆索引,混合检索(hybrid retrieval),记住过去的查询和业务上下文。
4. GenBI dashboards------不止 SQL,还出 dashboard
这是 Wren 的杀手锏。它不只给你 SQL,还能生成一个浏览器端应用(dashboard) ,用 wren-core-wasm 驱动,一键部署到 Vercel 或 Cloudflare Pages,返回一个可分享的 live URL。一个 Agent 驱动的闭环:从问题 → 受治理答案 → 可筛选可分享的 dashboard。
5. 连接器 & 引擎
- 引擎:基于 Apache DataFusion。
- 22+ 数据源:BigQuery、Snowflake、PostgreSQL、ClickHouse、Redshift、Databricks、DuckDB 等。
- 带 MCP server (可接入 MCP 客户端)和 Agent SDKs :
wren-langchain(LangChain/LangGraph)、wren-pydantic(Pydantic AI)、以及给其他技术栈的 Python 参考集成。
6. CLI + Skills(安装/使用方式)
-
pip install wrenai装 CLI/引擎;npx skills add Canner/WrenAI把 skills 装进 Agent。 -
日常命令:
bashwren skills get onboarding # 建项目 + 第一个查询 wren skills get enrich-context # 补充业务上下文 wren skills get genbi # 生成并部署 dashboard wren query --sql '...' # 通过 MDL 语义层查询 wren ask "<问题>" --guided # 给较弱的模型用 wren ask "<问题>" --direct # 给较强的模型用
7. Git Sync------团队协作(亮点)
Wren 写在笔记本上的一切都是你仓库里的纯 YAML/Markdown,git push / git pull 就是团队部署的全部接口:
- 指标像代码一样 review:改一个
net_revenue在 GitHub/GitLab PR 里就是一个可读的 diff,可跑 CI,可从 staging 提到 production。 - 仓库永远在你手里:clone、备份、喂给别的工具、随时带走。
- 无持久凭据落盘:每次 push 用 600 秒过期的临时 token,持久 key 存在
~/.wren/cloud.yml(权限0600),从不交给 git。
四、优势(对比视角)
Wren 官方自己给了一张对比表,很能说明问题:
| 能力 | 裸 LLM Agent | 传统 BI | 裸语义层 | WrenAI |
|---|---|---|---|---|
| 帮你写 SQL | ✅(常错) | ❌ | ❌ | ✅ 受治理 |
| 懂你的业务定义 | ❌ | 部分(在工具里) | ✅(仅 schema) | ✅ + 非 schema 知识 |
| 生成并部署 dashboard | ❌ | ✅(手动) | ❌ | ✅ Agent 驱动 |
| 通过 你 的 Agent(Claude/Cursor/MCP...) | ✅ | ❌ | ❌ | ✅ |
| 开放、可审阅、Git 友好 | ❌ | ❌ | 部分 | ✅ |
| 跨 22+ 数据源的受治理执行 | ❌ | 每连接器各异 | ✅(仅定义) | ✅ |
归纳成几条真优势:
- 要答案也要 dashboard------不是只吐一段可能错的 SQL,而是端到端产出可信任 BI。
- 对而不是"自信地错"------schema 感知检索 + MDL 规划 + dry-plan 校验 + 结构化错误提示,把 Agent 的 SQL 框在护栏里。
- 业务含义活在 Git 里------指标定义、枚举、认可的 join、示例都是可版本化的文件,可 review、可 diff、可带走。
- 复用你已有的 Agent------Wren 是一层,不是又一个要你改习惯的聊天 UI。
- 坐在你现有栈上------数仓、ETL、已有语义模型都能接,22+ 源跑在同一个 DataFusion 引擎。
- 默认开放------核心引擎、SDK、skills 都是 Apache-2.0,"它能在没有我们的情况下运行"。
五、实现原理(逐层拆解)
核心设计思想:把"上下文"和"执行"彻底分开
Wren 整个架构的支点就一句话------业务含义(数据是什么意思)和业务执行(怎么跑 SQL)是两件事,必须分开。
- 上下文存在你仓库的纯文本文件里:MDL、instructions、profiles、memory。
- 正确性被拆成一组 Agent 可以编排的"原语(primitives)",而不是藏在一个黑盒功能里。
这个分离带来三个好处:可移植 (换个数仓照样跑)、可审阅 (所有定义都是 Git 里的文本)、Agent 原生(Agent 看得见每一步推理)。
正确性是一个"系统",不是单个技巧
Text-to-SQL 变可靠,不是因为某个元数据字段齐全、或某段 prompt 写得巧,而是下面六根支柱一起起作用:
| 支柱 | 含义 | 在 Wren 里怎么实现 |
|---|---|---|
| Schema linking | 知道哪个问题该用哪些 model / 列 / 关系 | MDL + 记忆检索(wren memory fetch) |
| Value profiling | 知道数据里真正出现哪些值(比如 status=4 到底代表啥) |
连接器行为 + profiling + 写进记忆的 instructions |
| Ambiguity detection | 发现问题没说清楚、需要反问 | Agent 的 skill 编排 |
| Generation trace | 展示答案怎么来的:用了哪些 model、join、CTE、展开后的 SQL | wren dry-plan |
| Retry and repair | SQL 跑失败或指错对象时能恢复 | 结构化错误 + wren dry-run + Agent 重试 |
| Eval | schema / 定义 / prompt 变了以后,发现回退 | Golden NL-SQL eval(开发中) |
Wren 把这些都做成原语暴露出来,由 Agent 决定什么时候 fetch、recall、dry-plan、execute、repair、或反问。推理的 trace 始终留在 Agent 看得见的地方。
四层架构
┌─────────────────────────────────────────────┐
│ Agent workflow ← skills 引导 Agent:onboarding、生成MDL、查询、校验、更新记忆 │
├─────────────────────────────────────────────┤
│ Project context ← MDL、instructions、profiles、memory:描述数据"是什么意思" │
├─────────────────────────────────────────────┤
│ Planning engine ← SQL planner:用语义引擎把"建模后的SQL"展开成可执行SQL │
├─────────────────────────────────────────────┤
│ Execution layer ← Connectors:把规划好的 SQL 跑到 22+ 数据源,返回结果 │
└─────────────────────────────────────────────┘
一条查询的完整路径:
用户/Agent 问一个业务问题
→ Skill 回忆相似的 NL→SQL 历史对(memory)
→ Skill 取相关 schema
→ Wren CLI 提交"对着 MDL 写的 SQL"
→ Planner 加载上下文、规划 SQL
→ wren-core 展开 MDL 语义
→ Connector 通过连接器执行
→ 数据源 返回结果
→ Skill 把确认过的对子存回 memory
最关键的一层:SQL 规划(SQL planning)
这是 Wren 的"魔法"发生的地方。你在 MDL 对象上写的 SQL(比如 SELECT ... FROM orders,这里的 orders 是你定义的 model,不一定是真表),要被翻译成目标数据库能执行的 SQL。三件工具协作:
- sqlglot:解析 SQL、qualify 表和列的引用、在不同 SQL 方言间转译。
- CTE rewriter:识别引用了哪些 MDL 对象,把展开后的 model SQL 作为 CTE 注入进去。
- wren-core:展开 MDL 语义------models、relationships、计算字段、views。
text
对着 MDL 写的用户 SQL
→ 解析并 qualify
→ 识别引用了哪些 model / view
→ 抽出相关的 MDL manifest 切片
→ 通过 wren-core 展开 model 和计算字段
→ 注入展开后的 CTE
→ 跑 policy 检查
→ 转译成目标方言
↓
能在目标数据源执行的 SQL
wren-core:Rust 语义引擎(真正干活的内核)
wren-core 是 Rust 写的语义引擎(基于 Apache DataFusion ),通过 PyO3 绑定暴露给 Python,是 MDL 语义的唯一权威来源 。它负责维护 MDL session 状态、只抽出一次查询需要的 manifest 对象 (不用把整个 schema 塞给 LLM------这是省 token、提准确率的关键)、展开 table_reference / ref_sql model、解析计算字段、展开关系感知表达式。
MDL:语义的定义语言(一切业务含义都在这)
MDL(Modeling Definition Language)用 YAML 写,Git 友好。一个 Wren 项目长这样:
my_project/
├── wren_project.yml # 项目元数据(schema_version 当前是 5)
├── models/ # 模型:数据从哪来、暴露哪些列
│ ├── orders/metadata.yml # table_reference 模式(物理表)
│ └── revenue_summary/ # ref_sql 模式(用一段 SQL 定义)
├── views/ # 视图:可递归引用其他 model/view
├── cubes/ # 立方体:预聚合语义对象(measure/dimension)
├── relationships.yml # 关系:model 之间怎么 join
├── knowledge/ # 业务上下文(v5 新增,一等公民)
│ ├── rules/ # 业务规则(给 Agent 看)
│ ├── glossary/ metrics/ caveats/
│ └── sql/ # NL→SQL 对------记忆的"真相来源"
├── target/mdl.json # build 产物(gitignore,给引擎用的 wire format)
└── .wren/memory/ # 派生的 LanceDB 索引(gitignore)
几个值得注意的设计细节:
- 两种 model 来源 :
table_reference(直接映射物理表)和ref_sql(用一段 SQL 当数据源)。 - 计算列 (
is_calculated: true+expression):比如total_with_tax = amount * 1.1,查询时实时算。 - 关系列 = join 手柄 :声明
customer列指向customersmodel,计算列就能customer.first_name穿过去。已知限制 :直接在查询里SELECT orders.customer.first_name还规划不了(关系列不进 engine 的 symbol table),issue #2688 追踪中。 - 列级访问控制是"物理级"的 :model 里没暴露的列,客户端物理上就引用不到、schema introspection 也看不到------对 AI Agent 来说,你省略的列它永远查不到。这是很硬的安全边界。
- Cube 用结构化查询 (
wren cube query),不是手写 GROUP BY。 - YAML 是 snake_case,编译成
mdl.json变 camelCase(wire format)。
记忆层:让系统"越用越懂你"
记忆是 LanceDB 向量库 + sentence-transformers 本地 embedding 的检索层,两个核心集合:schema_items(models/列/关系/指令,为问题检索对的上下文)和 query_history(确认过的 NL→SQL 对,回忆以前成功过的例子)。生命周期:index → fetch → recall → store。每一次确认过的查询都可能变成下一次的示例 ------这就是"越用越准"的来源。提交到 Git 的是 knowledge/sql/*.md 文本对,不是那个二进制的 LanceDB 索引(索引从文本对重建)。
连接器、SDK 与关键依赖
- Connectors:统一接口执行规划好的 SQL,支持 Postgres、MySQL、BigQuery、Snowflake、DuckDB、ClickHouse、Trino、Databricks、Redshift、Oracle、Spark 等。
- Python SDK :
wrenai暴露和 CLI 完全一样的 plan-and-execute 管线------CLI 只是 SDK 外一层薄薄的 Typer 壳 ,结果以 PyArrow table 返回;另有wren-langchain、wren-pydantic把它包成 Agent tools。
| 依赖 | 角色 |
|---|---|
wren-core-py |
Rust 语义引擎的 Python 绑定 |
sqlglot |
SQL 解析、qualify、方言转译 |
pyarrow |
查询结果表示 |
lancedb |
记忆的向量存储 |
sentence-transformers |
记忆的本地 embedding |
typer / pydantic |
CLI 框架 / 配置与连接校验 |
2026-05-07,Wren Engine 合并进本仓库的
core/,原来的Canner/wren-engine归档;更早的"聊天优先 BI"产品现在是 Wren GenBI Classic (在legacy/v1分支,不再更新)。
六、开源边界(Open Core)
永久免费的开源部分(本仓库,Apache-2.0,可自托管):MDL 语义层、受治理 text-to-SQL、MCP server、CLI、22+ 连接器。
商业部分 (Wren AI Cloud 或自托管 Enterprise Plus):行列级安全与访问控制、GenBI UI / dashboard / 嵌入式 / API、Scenario AI harnesses(GenBI Apps、Agentic Mode 等)、高级安全审计 + 支持 SLA + 云/VPC/气隙部署。底层是同一个引擎,你的 MDL 始终留在自己的 Git 里。
七、适合 / 不适合
适合你,如果:你想让 AI Agent 产出可信任的 BI(答案 + dashboard,不只是像样的 SQL);你的业务逻辑活在数据库外面、Agent 老是搞错;你想要一个开放、可审阅、版本控制、不绑死在某家 UI 上的上下文层。
可以跳过,如果:你只需要从单个 CSV 出一张临时图;或者你乐意让 Agent 毫无治理地猜 SQL。
八、小结
WrenAI 聪明的地方在于它不跟 LLM 的 SQL 能力硬拼 ,而是退去做一层"业务含义 + 治理 + 记忆"的上下文层,并用 MDL 把口径钉死、用 dry-plan 在执行前拦错、用 Git 让业务定义可 review。再叠加"能直接生成并部署 dashboard"这一手,它和 Vanna(纯 NL-to-SQL RAG)、Cube(纯语义层)都拉开了身位------要"SQL 准确率"选 Vanna,要"语义层"选 Cube,要"受治理的端到端 BI(含 dashboard)"选 Wren。 唯一的取舍是:完整团队体验(行列级权限、UI、托管)要走商业版。