mcpField
W
wren-generate-mdl

wren-generate-mdl

github.com/canner数据与数据库18.0k253 次安装1 天前更新
代码仓库

关于 wren-generate-mdl

wren-generate-mdl 是面向 Agent 的命令行工作流,可根据数据库结构构建 Wren MDL 项目,涵盖结构发现、类型规范化、YAML 编写、验证和记忆索引。

主要功能

  1. 01发现表、列和约束
  2. 02规范化数据库类型
  3. 03生成 YAML 模型和关系
  4. 04验证并构建 MDL 项目
  5. 05为结构建立记忆索引

适用场景

  1. 01根据数据库初始化 Wren 项目
  2. 02将数据库结构转换为 MDL 模型
  3. 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-mdl

CLI 会自动检测已安装的 Agent。若要指定 Agent,请添加 --agent <name>(例如 claude-code、cursor、windsurf、cline)。

无论是否需要更新,都继续执行以下工作流。


通过发现数据库架构并将其转换为 Wren 的 YAML 项目格式来构建 MDL 项目。Agent 使用其环境中可用的数据库工具进行内省;wren CLI 负责类型规范化、验证和构建。

设置完成后有关记忆和查询的工作流,请参阅 wren-usage 技能。


前提条件

  • 已安装 wren CLI(pip install "wrenai[<datasource>]")
  • 可正常连接数据库(Agent 可以获取凭据)
  • 已配置 wren profile(wren profile add),或已准备好连接信息

阶段 0 — 检测现有项目

目标: 如果当前目录已位于 wren 项目内,让用户决定如何继续。

检查当前工作目录中是否存在 wren_project.yml(或从当前目录向上检查,直到仓库根目录)。如果找到:

  1. 告知用户检测到了现有 wren 项目,并显示其路径。
  2. 询问用户:
    • 重置 — 清除现有项目(models/、views/、 relationships.yml、instructions.md,并重新构建 wren_project.yml) ,然后在同一目录中从头重新生成。
    • 新路径 — 保留现有项目不变,为新项目选择其他目录。请用户提供新路径, 然后运行 wren context init --path <new_path>,并使用该路径从阶段 1 继续。

如果未检测到现有项目,直接进入阶段 1。


阶段 1 — 建立连接并确定范围

目标: 确认 Agent 可以连接数据库,并与用户商定范围。

  1. 使用可用工具验证连接:

    • 如果使用 SQLAlchemy:测试 engine.connect()
    • 如果使用数据库驱动:执行类似 SELECT 1 的简单查询
    • 如果存在 wren profile:运行 wren profile debug 检查配置
    • 如果通过 wren 执行原始 SQL:运行 wren --sql "SELECT 1"(需要 profile 或连接文件)
  2. 询问用户:

    • 要包含哪些架构或数据集(只有一个时跳过)
    • 要包含所有表还是其中一部分
    • 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_TRUNC SQL。请参阅 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——过时的索引会降低召回质量

评论

支持 Markdown