跳到主要内容

Wren AI 是什么 · 全景 · 阅读地图

30 秒导读: WrenAI 是一个开源 GenBI 引擎——让你已有的 AI agent(Claude Code、Cursor、MCP 客户端…)把一句业务问题变成受治理的 SQL / 图表,再一键部署成可分享的仪表盘。它的可信来自底下一层:一个可评审、可 Git、agent 能真正信任的上下文层(语义模型 + 业务定义 + 记忆),而不是让模型对着裸 schema 猜。

本章是整个子库的顶层入口:只讲「这是什么、大盘怎么转、有哪些部件、该读哪一章」。具体机制留给 01–05 各章,本章不下钻代码细节。


1. 这是什么(零基础也能懂)

一句话定义

WrenAI = 给 AI agent 用的「生成式 BI(GenBI)」引擎。 GenBI(Generative BI,生成式商业智能)指的不是又一个 BI 工具,而是让你已经在用的 agent 去生成答案、部署仪表盘、并对执行做治理。

README 把它讲得很直接:它让 AI agent「generate, deploy, and govern(生成、部署、治理)」商业智能,从一条 SQL 答案到一个可分享的仪表盘,横跨 22+ 数据源(README.md:45-49,"What WrenAI is")。

解决什么问题 / 给谁用

想象你在终端里对 agent 说「我们这季度销售额前十的客户是谁?」。

一个裸的 LLM agent 也能写 SQL——但它不知道你们内部「销售额」到底怎么算、哪些 join 是被认可的、status = 2 是什么意思。于是它自信地写错。README 的对比表把这点摆得很清楚:裸 agent「写 SQL ✅(但常错)」,而 WrenAI 是「✅ governed(受治理)」(README.md:69-76,"How Wren compares")。

WrenAI 要补的,是模型对着数据库时缺的那层业务语境:业务语义、被批准的定义、单位、枚举含义、示例、以及散落在文档/wiki/聊天里的非结构化知识(README.md:49)。这层被做成文件——可评审、可版本化、每个 agent 都能复用。

给谁用: agent 开发者、数据工程师、想让 agent 产出「可信 BI」而不只是「看起来合理的 SQL」的人。不适合谁: 只想从单个 CSV 出一张一次性图表、且不在乎治理的人(README.md:78-84)。

它能做什么(GenBI 的三拍)

README 把能力归纳成三拍:Generate · Deploy · Know(README.md:53-57)。

拍(beat)白话对应命令(示例)
Generate(生成)把业务问题变成受治理的 SQL 与图表:schema 感知检索 + MDL 规划 + dry-plan 校验 + 结构化报错wren query --sql '...'
Deploy(部署)把任何一个答案变成浏览器端、可分享的仪表盘,一条命令部署到你自己的 Vercel / Cloudflare Pageswren skills get genbi
Know(知道)让这一切正确的知识,活在可版本化、带证据链的文件里:语义模型(MDL)、公司定义(instructions)、什么查询有效的记忆wren skills get enrich-context

用起来什么样(最小示例)

WrenAI 设计上就是 agent 驱动的:你装 CLI、给 AI 客户端装一个约 50 行的「发现桩」,剩下让 agent 自己驱动。工作流指南住在 CLI 里、按需下发,所以内容永远和你装的版本对得上(README.md:86-114,"Quickstart")。

一次典型的端到端,大致是这样一段对话 + 命令(摘自 Quickstart,README.md:159-169):

# 装 CLI 与发现桩
pip install wrenai
npx skills add Canner/WrenAI # 自动识别 Claude Code / Cursor / Cline / Codex …

# Day 1:让 agent 驱动(它自己去 CLI 取指南)
wren skills get onboarding # 建项目 + 跑通第一条查询 (Generate)
wren skills get enrich-context # 加业务语境 (Know)
wren skills get genbi # 生成并部署仪表盘 (Deploy)

# 日常
wren query --sql '...' # 经 MDL 语义层执行查询
wren ask "谁是本季度前十客户?" --guided # 把问题包装给较弱的 agent

你几乎从不需要背命令——agent 读了发现桩,就知道去 wren skills get <name> 取当下该用的指南,再一步步执行。

一句话直觉

把 WrenAI 想成 agent 和数据库之间的一层「懂业务的翻译 + 门卫」。 agent 用业务里的模型名和列名写 SQL,翻译层(wren-core)把它改写成数据库真正能跑的物理 SQL,同时按治理规则放行或拦截;而这层翻译该怎么翻,由一叠你能在 Git 里 review 的上下文文件说了算。

本节到此不碰底层。下面看大盘。


2. 顶层全景(它大概怎么转)

一次问题的旅程(ASCII)

怎么读这张图: 从上到下是一次问题的时间顺序;左边是「谁在驱动」,中间是「经过哪些部件」,命中治理规则会被拦下。

你(自然语言问题)
│ "本季度销售额前十的客户?"

┌──────────────┐ ① 读发现桩,按需取工作流指南
│ 你的 AI │──────────────► skills/ 发现桩 + CLI 内 skills_content/
│ agent │ (wren skills get usage / onboarding / genbi …)
└──────┬───────┘
│ ② 取 schema 上下文 + 召回过往相似 SQL
│────────────────────────► memory/ (LanceDB:schema 描述 + 查询历史)
│ ③ 用【业务模型名】写 SQL

┌──────────────────────────────────────────────┐
│ core/wren — CLI / Python SDK │
│ · 解析 SQL,按引用的表裁剪出最小 manifest │
│ · 治理校验(strict_mode / denied_functions) │
└──────┬───────────────────────────────────────┘
│ ④ 交给语义引擎改写

┌──────────────────────────────────────────────┐
│ core/wren-core — Rust 语义引擎 │
│ (Apache DataFusion 分支) │
│ MDL 分析 → 逻辑计划 → 优化 → 物理方言 SQL │
│ 一路施加 RLAC/CLAC 行级/列级访问控制 │
└──────┬───────────────────────────────────────┘
│ ⑤ 受治理的物理 SQL

┌──────────────────────────────────────────────┐
│ connector/ — 各数据源连接器(22+) │
│ postgres / bigquery / snowflake / duckdb … │
└──────┬───────────────────────────────────────┘
│ ⑥ 原生执行,取回结果(Arrow 表)

结果 ─────► (可选) core/wren-core-wasm:浏览器端同一套语义引擎


GenBI 仪表盘 ──► 一键部署到 Vercel / Cloudflare

关键直觉:同一套语义规则,既在服务端(Rust,wren-core)跑,也能编进浏览器(WASM,wren-core-wasm)跑——所以部署出去的仪表盘不必回连你的数据库,也能用一致的语义。

六大部件:干什么 · 在哪

对应 README 的 "Project structure"(README.md:227-240)。表里每个部件的目录就是你下钻时的入口。

部件干什么在哪(目录)
CLI / Python SDK对外的 wren 命令与 Python SDK:解析 SQL、裁剪 manifest、治理校验、连接器执行、承载 skills/memory/genbicore/wren/
语义引擎(Rust)核心:把模型名 SQL 经 MDL 分析 → 逻辑计划 → 优化 → 物理方言 SQL,并施加访问控制;基于 Apache DataFusion(Canner 分支)core/wren-core/
manifest 类型 + MDL builder共享的 Rust crate:Model/Column/Metric/Relationship/View 等清单类型与 ManifestBuildercore/wren-core-base/
Python 绑定PyO3 绑定,把 wren-core 暴露给 Python(transform_sql 等,PyPI: wren-core)core/wren-core-py/
浏览器端引擎(WASM)把语义引擎编成 WebAssembly,让仪表盘在浏览器里做语义 SQL(npm: wren-core-wasm)core/wren-core-wasm/
发现桩(skills)一个约 50 行的桩,教 agent 去 CLI 取真正的工作流指南——内容永不与版本漂移skills/
Agent SDK 集成把 Wren 接进 agent 框架的参考集成(LangChain / LangGraph、Pydantic)sdk/wren-langchain/sdk/wren-pydantic/

备注:严格数是 7 个目录级部件;其中 core/wren-core-basecore/wren-core-pywren-core 的支撑(共享类型 / Python 绑定),归到「语义引擎」一族理解即可。

主线走一遍(高层,不进代码)

  1. 发现与取指南。 agent 读发现桩(skills/wren/SKILL.md),知道有个 wren CLI;需要做多步工作流时,先 wren skills get <name> 取当下版本对应的指南。
  2. 取语境。 写 SQL 前,agent 从 memory 取 schema 描述、并召回过往相似的 NL→SQL 例子(wren memory recall)。
  3. 用业务模型名写 SQL。 agent 按 MDL 里的模型/列名(而非物理表名)写查询。
  4. 裁剪 + 治理。 core/wren 解析 SQL,只抽出被引用到的模型,拼出最小 manifest;若开了严格模式/禁用函数,先做策略校验(core/wren/src/wren/engine.py:163,WrenEngine._plan)。
  5. 语义改写。 交给 wren-core:MDL 分析 → 逻辑计划 → 优化 → 目标方言的物理 SQL,一路施加行级/列级访问控制(经 Python 绑定 transform_sql,core/wren-core-py/src/context.rs:222)。
  6. 执行取回。 选对应连接器,在目标数据源原生执行,结果以 Arrow 表返回(core/wren/src/wren/engine.py:107,WrenEngine.query)。
  7. (可选)部署。 把答案组织成浏览器端 GenBI 应用,用同一套语义(WASM 版)在前端跑,一键部署成可分享 URL。

3. 全局『巧妙之处』总纲

这三点是 WrenAI 区别于普通 text-to-SQL 工具的设计主张,也是你读完整套文档要带走的精华。每一点在对应章节展开。

巧思一:CLI 只做「工具」,工作流做成「按需下发的 skills」

多数工具会把「怎么用我」写死进 agent 的 system prompt,一旦上游更新,prompt 就和实际版本对不上了。

WrenAI 反其道:agent 客户端只装一个约 50 行的发现桩,真正的工作流指南打包在 CLI 的 wheel 里,运行时由 wren skills get <name> 现取(skills/SKILLS.md:"live inside the wren CLI itself, so they always match the installed wren-engine version";交付逻辑见 core/wren/src/wren/skills_delivery.py:48,get_skill)。

妙在:内容永远匹配你装的版本,不存在 skill 缓存漂移。 详见 01

巧思二:把「上下文」做成可评审、可 Git 的文件,而非埋进 prompt

让 SQL 正确的知识——语义模型(mdl.json)、业务规则(instructions / knowledge/rules/*.md)、确认过的 NL→SQL 例子(knowledge/sql/)——统统落成项目里的文件,和代码一起提交(core/wren/src/wren/context.py:48)。

妙在:业务定义变成可 review 的 diff,而不是黑盒 prompt。 每个 agent、每个人都能读、能改、能审。详见 02

巧思三:语义 + 治理内建为「原语」,一次改写既翻译又设防

改写 SQL 时,wren-core 不只是把模型名换成物理表名,还顺带施加行级/列级访问控制、函数白名单、strict 模式(core/wren/src/wren/engine.py:163 的策略校验 + Rust 侧访问控制)。治理不是事后加的中间件,而是改写这步的固有产物。详见 03


4. 阅读地图

建议顺序读 01 → 05:先懂「怎么被 agent 用」(01),再懂「语境从哪来」(02),然后是「引擎怎么改写与治理」(03),接着「记忆怎么补语境」(04),最后「怎么变成仪表盘发出去」(05)。

一句话讲什么读它当你想知道
01 Agent 驱动的 CLI 与 skillsCLI 只做工具,工作流做成按需下发的 skills;发现桩 + wren skills get + wren ask 的机制为什么不把用法写进 prompt?agent 如何被驱动?
02 上下文层:MDL 与项目文件MDL 语义模型、instructionsqueries 如何组成可 Git 的上下文「业务语义」到底长什么样、存在哪?
03 语义引擎与治理模型名 SQL → wren-core 改写 → 受治理的物理 SQL;裁剪 manifest、CTE 改写、RLAC/CLAC一条 SQL 在引擎里到底被怎么处理?
04 记忆与检索LanceDB 存 schema 描述 + 查询历史;get_context 按 schema 大小选全文/检索策略,召回过往 SQL写 SQL 前 agent 怎么拿到对的语境?
05 GenBI 仪表盘生成与部署从项目上下文组装 GenBI 应用,WASM 前端跑语义,一键部署到 Vercel / Cloudflare答案怎么变成可分享的仪表盘?

5. 顶层代码地图(导航索引)

只列顶层入口与主线符号,细节符号留给各章。agent 可用符号名 grep 定位,比行号抗漂移。

主题文件符号 / 关键点
CLI 入口与默认查询命令core/wren/src/wren/cli.pyapp = typer.Typer(...)(:14)、main(:355,无子命令=查询)
CLI 子应用装配(六大子命令组)core/wren/src/wren/cli.pyapp.add_typer(...)(:596–623:docs/context/cube/utils/skills/memory/genbi/profile)
查询执行主线(transpile→execute)core/wren/src/wren/engine.pyWrenEngine.query(:107)、WrenEngine.dry_plan(:87)
裁剪 manifest + 治理校验core/wren/src/wren/engine.pyWrenEngine._plan(:163)、validate_sql_policy 调用
语义改写(每模型一次 transform_sql)core/wren/src/wren/mdl/cte_rewriter.pyCTERewriter(:67)、CTERewriter.rewrite(:236)
Rust 引擎入口core/wren-core/core/src/lib.rspub mod mdl / pub mod logical_planAnalyzedWrenMDL
Python 绑定的改写调用core/wren-core-py/src/context.rstransform_sql(:222)
skills 按需下发core/wren/src/wren/skills_delivery.pyget_skill(:48)、list_skills(:82)、skills_content/(6 个指南)
发现桩(装进 AI 客户端)skills/wren/SKILL.mdfrontmatter + wren skills get 用法
ask 提示包装(guided/direct)core/wren/src/wren/ask.pyMODES(:19)、render(:26)
记忆:schema 上下文 + 召回core/wren/src/wren/memory/store.pyMemoryStore.get_context(:211)、recall_queries(:311)、index_schema(:107)
记忆:manifest → schema 描述core/wren/src/wren/memory/schema_indexer.pydescribe_schema(:39)、extract_schema_items(:220)
上下文项目文件约定core/wren/src/wren/context.py_TARGET_FILE = "mdl.json"(:18)、knowledge/rules / knowledge/sql 说明(:48)
GenBI 组装与部署core/wren/src/wren/genbi/composer.pygenbi/cli.pycompose_build_instruction(:65)、build(:64)、deploy(:299)
浏览器端语义引擎core/wren-core-wasm/src/lib.rs#[wasm_bindgen] 导出(:39 起)

全部引用 as-of sourceCommit: 0c031d60b0fdbb28925970622434721f3fd631db。行号可能随上游漂移,失效时以符号名 grep 重新定位。