跳转到内容

快速开始

marivo init 初始化项目(参见安装), 然后编写声明。一个最小 Marivo 项目包含 manifest、数据源声明 和语义声明:

智能体:在编写前请先查阅 md.help("authoring")ms.help("authoring") 了解分阶段 编写工作流,并查阅 md.help("ai_context") 了解共享的 ms.ai_context(...) 契约。

your-project/
marivo.toml
models/
datasources/
warehouse.py
semantic/
sales/
_domain.py

先声明数据源:

import marivo.datasource as md
import marivo.semantic as ms
md.duckdb(
name="warehouse",
path="warehouse.duckdb",
ai_context=ms.ai_context(
business_definition="Local DuckDB warehouse for sales analysis.",
guardrails=["Use only for development or approved local analysis."],
),
)

再声明语义对象:

import marivo.datasource as md
import marivo.semantic as ms
ms.domain(
name="sales",
owner="Mina Zhang",
ai_context=ms.ai_context(
business_definition="Sales order analysis domain.",
guardrails=["Revenue metrics should only use completed orders."],
),
)
orders = ms.entity(
name="orders",
datasource=md.ref("datasource.warehouse"),
source=ms.table("orders"),
primary_key=["order_id"],
ai_context=ms.ai_context(
business_definition="One row per sales order.",
guardrails=["Exclude cancelled test data in metric definitions."],
),
)
region = ms.dimension_column(
name="region",
entity=orders,
column="region",
ai_context=ms.ai_context(
business_definition="Sales region assigned to the order.",
guardrails=["Do not treat missing region as a real region."],
),
)
order_date = ms.time_dimension_column(
name="order_date",
entity=orders,
column="order_date",
granularity="day",
is_default=True,
ai_context=ms.ai_context(
business_definition="Calendar date when the order was placed.",
guardrails=["Use this as the default time axis for order metrics."],
),
)
amount = ms.measure_column(
name="amount",
entity=orders,
column="amount",
additivity="additive",
unit="CNY",
ai_context=ms.ai_context(
business_definition="Completed order amount at row level.",
guardrails=["Use only where order amount is already net of cancellations."],
),
)
revenue = ms.aggregate(
name="revenue",
measure=amount,
agg="sum",
ai_context=ms.ai_context(
business_definition="Total completed order amount.",
guardrails=["Use only where order amount is already net of cancellations."],
),
)

这些对象不必全部手写。marivo init 会把 marivo-semantic 技能 安装到 .agents/skills/.claude/skills/.codex/skills/,因此在项目中运行的编码智能体可以协助建设语义层。 把它指向你的表并提出请求:

使用 marivo-semantic 技能为 sales 领域中的 orders 表建模。

该技能会引导智能体按固定的编写循环工作,每次只处理一个对象:

  • 遵循 ladder —— 领域 → 实体 → 维度 → 时间维度 → 度量 → 指标 → 关系 —— 让每个对象的依赖先于它存在。
  • 先发现,再编写。 对数据源-backed 对象,智能体先调用匹配的 md.discover_* API,再结合 ms.help(...) 确定构造器值,并把一个 声明写入 models/semantic/<domain>/_domain.py。默认指标路径是 md.discover_measures(...),author 并验证度量,再声明 ms.aggregate(...)
  • 验证后再前进。 每写完一个对象就运行 ms.verify_object(ref),在它失败时不会继续。
  • 收尾时做就绪检查。 最后运行 ms.readiness(),在把目录交给分析之前解决阻塞项。

智能体只会就那些无法从数据或项目文档推断的决策征询你,例如某个金额是否已经扣除退款。 它产出的就是上面展示的 Python 声明,可以像其他代码一样在 git 中评审。

分析前先探索目录。对数据源-backed 编写,发现-首个流程先收集有界证据, 再每次 author 一个对象:

import marivo.datasource as md
import marivo.semantic as ms
warehouse = md.ref("datasource.warehouse")
orders_source = md.table("orders")
md.inspect_table(warehouse, orders_source).show()
md.inspect_partitions(warehouse, orders_source).show()
scope = md.partition({"dt": "20260629"})
md.discover_entity(warehouse, orders_source, scope=scope).show()
ms.help("entity")

结合发现证据和 ms.help("entity") 契约,一次只 author 一个对象,然后运行 ms.verify_object(ref),通过后再继续。

加载目录并检查就绪状态:

import marivo.semantic as ms
catalog = ms.load()
catalog.list("domain").show()
report = catalog.readiness()
if report.status == "blocked":
report.show()

目录就绪后,开启分析会话:

import marivo.analysis as mv
session = mv.session.get_or_create(name="revenue-check", question="Why did Q4 drop?")
catalog = session.catalog
revenue = catalog.get("metric.sales.revenue")
region = catalog.get("dimension.sales.orders.region")
current = session.observe(
revenue,
time_scope={"start": "2026-10-01", "end": "2027-01-01"},
grain="month",
dimensions=[region],
)
baseline = session.observe(
revenue,
time_scope={"start": "2025-10-01", "end": "2026-01-01"},
grain="month",
dimensions=[region],
)
delta = session.compare(current, baseline)
attribution = session.attribute(delta, axes=[region])
attribution.show()
delta.contract().affordances # mechanical compatibility, not recommendations
delta.quality_summary # cheap metadata projection
quality = session.assess_quality(delta)
quality.show()

当多个相同-范围指标共享同一窗口时,把指标列表传给 session.observe(...)。Marivo 会把同一数据源的指标合并为一次查询, 跨数据源的指标则按时间轴 outer-连接。用 frame.metric(id) 投影出 arity-1 frame,对单个指标做深入分析时不会重新查询后端。

report = session.observe(
[
catalog.get("metric.sales.revenue"),
catalog.get("metric.sales.total_orders"),
catalog.get("metric.sales.failed_orders"),
],
time_scope={"start": "2026-10-01", "end": "2027-01-01"},
grain="month",
)
report.show() # bucket_start + 三个值列
revenue = report.metric("sales.revenue") # arity-1 frame,用于 drill-down

如果自定义 Ibis 计算结果还要回到 Marivo 类型化指标流程,使用 session.derive_metric_frame(...)。语义引用只用于指标与轴绑定, 查询输出列名仍是普通字符串。跨后续脚本时,用 session.frame_summaries()session.get_frame(ref) 恢复已有产物,不要重跑上游查询。用 artifact.contract().affordances 查看机械兼容性事实。

同样的项目结构,既可以支撑一次性脚本,也可以逐步沉淀为经过评审、可共享的分析项目。 差别主要来自下面三个习惯。

语义层不只是访问表的管道。它是智能体在分析之前读取的知识库。为每个对象补充 ms.ai_context(...)

  • business_definition —— 这个指标或维度在业务上意味着什么
  • guardrails —— 智能体必须遵守的规则:必需的过滤、排除项、范围限制。
  • synonymsexamples —— 帮助智能体把自然语言问题解析到正确对象,而不是靠猜。

上下文足够完整时,对象本身就能回答智能体的两个基本问题:“我能不能用它?”“应该怎么用?” 就绪检查负责守住底线:缺失 business_definition 会阻塞分析,缺失 guardrails 会发出警告。 完整的 ms.ai_context(...) 契约参见 语义层

一个 Marivo 项目本质上是纯文本:marivo.toml 加上 models/ 下的 Python 文件。因此语义层 可以像应用代码一样评审、共享和回滚。

  • 对契约做版本控制。 提交 marivo.tomlmodels/。对指标定义或 guardrail 的每一次 改动都会以 diff 的形式呈现。
  • 像评审代码一样评审语义改动。 通过 pull 请求合入定义改动,让领域负责人在 智能体使用之前确认指标的含义
  • 通过仓库共享。 clone 该项目的人,以及在其中运行的智能体,都会读取同一份可信目录。
  • 把状态与密钥排除在 git 之外。.marivo/ 加入 .gitignore:它保存的是项目 本地的会话与证据状态,不是契约。凭据以 *_env 引用的形式编写,从环境 (或 user-global 的 ~/.marivo/secrets.toml 缓存)解析,不写入项目。

一个典型的 .gitignore

.marivo/

加载后运行 ms.readiness(),并在任何分析会话之前解决阻塞项。项目可以在就绪检查 仍为 blocked 时成功加载,因此不要把 blocked 目录交给智能体。参见 就绪检查