关于 wren-generate-mdl
wren-generate-mdl 是面向 Agent 的命令行工作流,可根据数据库结构构建 Wren MDL 项目,涵盖结构发现、类型规范化、YAML 编写、验证和记忆索引。
主要功能
- 01发现表、列和约束
- 02规范化数据库类型
- 03生成 YAML 模型和关系
- 04验证并构建 MDL 项目
- 05为结构建立记忆索引
适用场景
- 01根据数据库初始化 Wren 项目
- 02将数据库结构转换为 MDL 模型
- 03验证并构建生成的项目
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ canner/ wrenai --skill wren-generate-mdl安装后在 Claude Code 中输入/wren-generate-mdl确认已加载。
详细介绍
生成 Wren MDL — CLI Agent 工作流
版本检查
静默获取 https://raw.githubusercontent.com/Canner/WrenAI/main/skills/versions.json。
将 wren-generate-mdl 键与此技能的版本(取自上方 frontmatter)进行比较。
如果远程版本较新,请在继续之前通知用户:
有可用的较新版本 wren-generate-mdl 技能。 使用以下命令更新:
npx skills add Canner/WrenAI --skill wren-generate-mdlCLI 会自动检测已安装的 Agent。若要指定 Agent,请添加
--agent <name>(例如claude-code、cursor、windsurf、cline)。
无论是否需要更新,都继续执行以下工作流。
通过发现数据库架构并将其转换为 Wren 的 YAML 项目格式来构建 MDL 项目。Agent 使用其环境中可用的数据库工具进行内省;wren CLI 负责类型规范化、验证和构建。
设置完成后有关记忆和查询的工作流,请参阅 wren-usage 技能。
前提条件
- 已安装
wrenCLI(pip install "wrenai[<datasource>]") - 可正常连接数据库(Agent 可以获取凭据)
- 已配置 wren profile(
wren profile add),或已准备好连接信息
阶段 0 — 检测现有项目
目标: 如果当前目录已位于 wren 项目内,让用户决定如何继续。
检查当前工作目录中是否存在 wren_project.yml(或从当前目录向上检查,直到仓库根目录)。如果找到:
- 告知用户检测到了现有 wren 项目,并显示其路径。
- 询问用户:
- 重置 — 清除现有项目(
models/、views/、relationships.yml、instructions.md,并重新构建wren_project.yml) ,然后在同一目录中从头重新生成。 - 新路径 — 保留现有项目不变,为新项目选择其他目录。请用户提供新路径,
然后运行
wren context init --path <new_path>,并使用该路径从阶段 1 继续。
- 重置 — 清除现有项目(
如果未检测到现有项目,直接进入阶段 1。
阶段 1 — 建立连接并确定范围
目标: 确认 Agent 可以连接数据库,并与用户商定范围。
-
使用可用工具验证连接:
- 如果使用 SQLAlchemy:测试
engine.connect() - 如果使用数据库驱动:执行类似
SELECT 1的简单查询 - 如果存在 wren profile:运行
wren profile debug检查配置 - 如果通过 wren 执行原始 SQL:运行
wren --sql "SELECT 1"(需要 profile 或连接文件)
- 如果使用 SQLAlchemy:测试
-
询问用户:
- 要包含哪些架构或数据集(只有一个时跳过)
- 要包含所有表还是其中一部分
- wren 的数据源类型(例如
postgres(包括 Aurora)、mysql(包括 Aurora)、bigquery、snowflake)——类型规范化方言需要此信息
阶段 2 — 发现架构
目标: 收集表名、列名、列类型和约束。
使用任何可用的内省方法。以下是常见方法,按便利程度排序:
选项 A:SQLAlchemy(推荐,若可用)
from sqlalchemy import create_engine, inspect
engine = create_engine(connection_url)
inspector = inspect(engine)
tables = inspector.get_table_names(schema="public")
for table in tables:
columns = inspector.get_columns(table, schema="public")
# columns → [{"name": "id", "type": INTEGER(), "nullable": False, ...}]
pk = inspector.get_pk_constraint(table, schema="public")
# pk → {"constrained_columns": ["id"], "name": "orders_pkey"}
fks = inspector.get_foreign_keys(table, schema="public")
# fks → [{"constrained_columns": ["customer_id"],
# "referred_table": "customers",
# "referred_columns": ["id"]}]
选项 B:数据库专用驱动
- psycopg / asyncpg(Postgres): 查询
information_schema.columns和information_schema.table_constraints - google-cloud-bigquery:
client.list_tables()、client.get_table()→table.schema - snowflake-connector-python:
SHOW COLUMNS IN TABLE、SHOW PRIMARY KEYS IN TABLE - clickhouse-driver:
DESCRIBE TABLE、system.tables
选项 C:通过 wren 执行原始 SQL
如果没有可用驱动,但已配置 wren profile,则通过 wren 本身查询
information_schema:
wren --sql "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'" -o json
wren --sql "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'orders'" -o json
注意:此操作经由 MDL 层,因此仅当你已有最小 MDL,或数据库支持将 information_schema 用作常规表时才有效。从零开始引导时,建议使用选项 A 或 B。
阶段 3 — 标准化类型
**目标:**将原始数据库类型转换为与 wren-core 兼容的类型。
Python 导入(推荐用于批量处理)
from wren.type_mapping import parse_type, parse_types
# Single type
normalized = parse_type("character varying(255)", "postgres") # → "VARCHAR(255)"
# Batch — entire table at once
columns = [
{"column": "id", "raw_type": "int8"},
{"column": "name", "raw_type": "character varying"},
{"column": "total", "raw_type": "numeric(10,2)"},
]
normalized_cols = parse_types(columns, dialect="postgres")
# Each dict now has a "type" key with the normalized value
CLI(如果无法使用 Python 导入)
单个类型:
wren utils parse-type --type "character varying(255)" --dialect postgres
# → VARCHAR(255)
批量(stdin JSON):
echo '[{"column":"id","raw_type":"int8"},{"column":"name","raw_type":"character varying"}]' \
| wren utils parse-types --dialect postgres
阶段 4 — 搭建并编写 MDL 项目
**目标:**创建 YAML 项目结构。
步骤 1 — 初始化项目
wren context init --path /path/to/project
这会创建:
project/
├── wren_project.yml
├── models/ # business-facing tables/models
├── views/ # named SQL statements
├── cubes/ # pre-aggregation cubes (measures + dimensions)
├── relationships.yml
└── instructions.md
**何时定义 cubes:**如果用户提出“按月统计收入”或“顶级客户”等聚合问题,请在模型旁边定义 cubes — 这样可为 Agent 提供结构化查询 API,而不必强迫它们 手动编写
GROUP BY/DATE_TRUNCSQL。请参阅 Cube 指南。
重要:
wren_project.yml中的catalog和schema这些是 Wren Engine 的内部命名空间——并非数据库原生的 catalog 或 schema。除非你有意配置多项目命名空间, 否则请保留默认值(
catalog: wren、schema: public)。数据库实际的 catalog/schema 在每个模型的
table_reference中指定 (见步骤 2)。不要将数据库的 catalog/schema 值复制到wren_project.yml中。
步骤 2 — 编写模型文件
为每个表在 models/ 下创建一个 YAML 文件。使用 snake_case
命名(构建步骤会自动将其转换为 camelCase)。
# models/orders/metadata.yml
name: orders
table_reference:
catalog: "" # database catalog (empty string if not applicable;
# for DuckDB, use the DB file name without extension,
# e.g. jaffle_shop.duckdb → catalog: jaffle_shop)
schema: public # database schema (this IS the DB schema)
table: orders # database table name
primary_key: order_id
columns:
- name: order_id
type: INTEGER
not_null: true
- name: customer_id
type: INTEGER
- name: total
type: "DECIMAL(10, 2)"
- name: status
type: VARCHAR
properties:
description: "Order status: pending, shipped, delivered, cancelled"
步骤 3 — 编写关系
根据阶段 2 中发现的外键约束:
# relationships.yml
- name: orders_customers
models:
- orders
- customers
join_type: many_to_one
condition: "orders.customer_id = customers.customer_id"
连接类型映射:
- FK 表 → PK 表:
many_to_one - PK 表 → FK 表:
one_to_many - 唯一 FK:
one_to_one - 关联表:
many_to_many
如果未找到外键,请根据命名约定推断:
- 列
<table>_id或<table_singular>_id→ 可能是指向<table>的 FK - 请用户确认推断出的关系
步骤 4 — 添加描述(可选,但很有价值)
请用户描述:
- 每个模型(用 1-2 句话说明该表代表什么)
- 关键列(尤其是计算字段或名称不直观的列)
这些描述会由 wren memory index 建立索引,并显著
提高 LLM 查询的准确性。
阶段 5 — 验证并构建
# Validate YAML structure and integrity
wren context validate --path /path/to/project
# If strict mode is desired:
wren context validate --path /path/to/project --strict
# Build JSON manifest
wren context build --path /path/to/project
# Verify against database
wren --sql "SELECT * FROM <model_name> LIMIT 1"
如果验证失败,请修复报告的问题并重新运行。常见错误:
- 模型/列名称重复
- 缺少主键
- 关系引用了不存在的模型
- 列类型无效(尝试通过
parse_type重新运行)
阶段 6 — 初始化记忆
# Index schema (generates seed NL-SQL examples automatically)
wren memory index
# Verify
wren memory status
完成此步骤后,wren memory fetch 和 wren memory recall 即可
正常使用。查询工作流请参阅 wren-usage 技能。
阶段 7 — 与用户迭代
初始 MDL 是一个起点。通过以下方式改进:
- 根据业务逻辑添加计算列
- 为常见查询模式添加视图
- 根据实际查询用法完善描述
- 如有需要,添加访问控制(RLAC/CLAC)
每次更改都遵循:编辑 YAML → wren context validate →
wren context build → wren memory index。
快速参考
| 任务 | 命令 / 方法 |
|---|---|
| 发现表 | Agent 自带工具(SQLAlchemy、驱动程序、原始 SQL) |
| 发现列和类型 | Agent 自带工具 |
| 发现约束 | Agent 自带工具 |
| 标准化类型(Python) | from wren.type_mapping import parse_type |
| 标准化类型(CLI) | wren utils parse-type --type T --dialect D |
| 标准化类型(批量) | wren utils parse-types --dialect D < columns.json |
| 搭建项目 | wren context init |
| 编写模型 | 创建 models/<name>/metadata.yml |
| 编写关系 | 编辑 relationships.yml |
| 验证 | wren context validate |
| 构建清单 | wren context build |
| 测试查询 | wren --sql "SELECT * FROM <model> LIMIT 1" |
| 建立记忆索引 | wren memory index |
应避免的事项
- 不要在 MDL 中硬编码特定于数据库的类型字符串——始终通过
parse_type进行规范化 - 构建前不要跳过验证——无效的 YAML 会悄无声息地生成损坏的清单
- 不要猜测列类型——应从实际数据库中进行内省
- 未确认联接条件前不要编写关系——错误的条件会导致查询静默出错
- 构建后不要跳过
wren memory index——过时的索引会降低召回质量