跳转到内容

分析流程

每次 Marivo 分析都从一个 指标 开始,并以写-运行-读循环运行:智能体写出一个 意图(一次操作调用加上它的字段),运行它,读取一个类型化结果,再决定下一步。

各组成部分:

  • 会话 持有指导问题、语义目录,以及每一步的持久化结果。
  • 意图 是一次操作调用 —— observecomparedecompose…… —— 连同它的 参数。这些参数就是分析的规格说明。
  • frame 是意图的类型化结果。Frames 是步骤之间的边界:每个操作消费特定的 frame 类型并产出另一个。
import marivo.analysis as mv
import marivo.semantic as ms
session = mv.session.get_or_create(name="revenue-investigation", question="Why did Q4 drop?")
catalog = session.catalog
revenue = catalog.get("sales.revenue") # a metric object
region = catalog.get("sales.orders.region") # a dimension object

get_or_create 是幂等的:它附着到同名的已有会话,或创建一个,并设为当前会话。 会话的精简 API 为 get_or_createcurrent()list()delete(name)

操作接受目录对象和若干共享的值对象。几乎每个意图都会复用它们:

形态含义
指标输入catalog.get("sales.revenue")一个目录指标对象或其 SemanticRef 子类(如 MetricRef)。来自 ms.aggregate(...) 的编写引用也可用。裸字符串会被拒绝。
维度输入catalog.get("sales.orders.region")一个目录维度对象,或其 DimensionRef / TimeDimensionRef(见 语义引用)。用于 dimensionswhere 的键和 axis
timescope{"start": "2026-10-01", "end": "2027-01-01"}半开时间区间 —— start 含、end 不含。
grain"day" | "week" | "month" | "quarter" | "year" | "hour" | …时间桶大小。存在 ⇒ 时间序列或面板。
dimensions[region, country]分段轴。v1 中全部必须解析到指标所属实体。
where{region: "US"}{amount: {"op": ">", "value": 100}}聚合前的行过滤(见下方运算符)。
AlignmentPolicymv.window_bucket()compare / correlate 时两个窗口如何配对。

结果的 语义类型graindimensions 决定:scalar(都没有)、 time_series(仅粒度)、segmented(仅维度)或 panel(两者皆有)。

键是目录维度;值为标量(==)、列表(in),或结构化的 {"op": ..., "value": ...} 形式:

形式含义
"US"==(相等)
["US", "CA"]in(成员)
{"op": "!=", "value": "US"}不等
{"op": ">", "value": 100}>=<<= 同理)数值比较
{"op": "between", "value": ["2026-07-01", "2026-09-30"]}闭区间(恰好两个值)

任何分析的起点:在某个时间范围和/或分段上物化一个指标。

参数类型必填默认含义
metric指标对象 / 引用要物化的指标。
timescopedictNone半开 {"start", "end"} 窗口。
grain粒度None时间桶;存在 ⇒ 时间序列或面板。
dimensionslist[ref]None分段轴。
wheredictNone聚合前的行过滤。
time_dimension引用实体默认当实体声明多个时间轴时选择其一。
expect_shape形状None守卫;若预测形状不符,在访问后端前抛错。
current = session.observe(
revenue,
timescope={"start": "2026-10-01", "end": "2027-01-01"},
grain="month",
dimensions=[region],
)

量化两个 observe 结果之间的变化(当前减 baseline)。两个 frame 必须共享指标与 语义类型。

参数类型必填默认含义
currentMetricFrame当前期 frame。
baselineMetricFrame基线期 frame。
alignmentAlignmentPolicywindow_bucket桶/分段如何配对。
baseline = session.observe(
revenue,
timescope={"start": "2025-10-01", "end": "2026-01-01"},
grain="month",
dimensions=[region],
)
delta = session.compare(current, baseline)

compare 默认用 window_bucket 配对桶。传入 alignment= 可覆盖 —— mv.dow_aligned()mv.holiday_aligned()mv.holiday_and_dow_aligned();calendar 支持的几种还接受 calendar=mv.CalendarRef(...)

把一个差值的变动归因到某一个分段轴上 —— 它为什么变了?

参数类型必填默认含义
frameDeltaFrame要解释的差值。
axis维度进行归因的分段轴。
attribution = session.decompose(delta, axis=region)
attribution.show()

在对齐的桶上度量两个指标之间的关联。

参数类型必填默认含义
abMetricFrame要关联的两个 frame。
measure_ameasure_bstrframe 度量各 frame 上的数值列。
alignmentAlignmentPolicywindow_bucket桶配对。
method"pearson""pearson"关联方法(v1:Pearson,零滞后)。

将一个时间序列或面板向前投影。

参数类型必填默认含义
historyMetricFrame(time_series/面板)连续历史,无 NaN。
horizonint要投影的桶数(≥ 1)。
model"naive" | "seasonal_naive" | "drift""seasonal_naive"预测策略。
seasonality_periodint按粒度覆盖季节周期(day=7、week=52、month=12、quarter=4)。
interval_levelfloat0.95预测区间的置信水平。
measure_columnstrframe 度量要预测的列。
history = session.observe(revenue, timescope={"start": "2026-01-01", "end": "2026-04-01"}, grain="day")
projection = session.forecast(history, horizon=30)

对一个 MetricFrame 运行质量检查(行数、空值比率、时间覆盖、重复键)。返回逐项检查、 阻塞性问题和推荐的后续意图。

参数类型必填默认含义
frameMetricFrame要检查的 frame。

对一个指标在两期之间均值是否变化做配对检验。

参数类型必填默认含义
abMetricFrame当前期与基线期 frame。
hypothesis"mean_changed""mean_changed"检验类型(v1)。
value_avalue_bstrframe 度量各 frame 上的数值列。
alignmentAlignmentPolicywindow_bucket检验的配对方式。
samplingSamplingPolicy推断配对/最小样本规则。
alphafloat0.05显著性水平。

发现 —— session.discover.*CandidateSet

Section titled “发现 —— session.discover.* → CandidateSet”

发现操作在一个 frame 中搜索值得注意的项,并返回排序后的 CandidateSet。当 frame 有多个数值列时传 value="<column>" 消歧;threshold 是阈值(越低 ⇒ 候选越多)。

辅助函数源形状必填关键选项
point_anomaliesMetricFrame time_series/面板valuethreshold=3.0
period_shiftsDeltaFrame time_series/面板≥ 4 个桶valuethreshold=2.0
driver_axesDeltaFramesearch_spacevaluelimit
interesting_slicesMetricFrameDeltaFramesearch_spacevaluethreshold=2.0limit
interesting_windowstime_series/面板 framevaluethreshold=2.0
cross_sectional_outliersMetricFrame segmented/面板peer_scopevaluethreshold=3.0
series = session.observe(revenue, timescope={"start": "2026-01-01", "end": "2026-04-01"}, grain="day")
candidates = session.discover.point_anomalies(series, threshold=2.0)
candidates.show()

变换在保持 frame 家族(MetricFrameMetricFrameDeltaFrameDeltaFrame)的前提下重塑 frame。

变换关键参数效果
filterpredicate(callable)保留谓词为真的行。
slicewhere(轴 → 值/列表/区间)保留匹配精确轴值的行。
rollupdrop_axes删除轴并对度量重新聚合。
topkbylimitorder按某个度量取前 N 行(默认 order="decrease")。
bottomkbylimit取后 N 行。
rankbymethodrank_column按某个度量排序并加一列 rank。
normalizemodebaselineindex / share / pct_change / per_unit / z_score(仅 MetricFrame)。
windowwindow限制到一个时间窗口。

当某一步需要内置意图未建模的东西时,降级到 scratch frame —— 再在继续之前 promote 回类型化流程。

  • session.explore_ibis(builder, datasource=...) —— 运行自定义 ibis 查询 → ExplorationResult
  • session.from_pandas(df) —— 导入外部数据 → ExplorationResult
  • session.promote_metric_frame(...) / promote_delta_frame(...) / promote_attribution_frame(...) —— 把 scratch frame 升级为类型化 frame。Promotion 从不推断元数据;你需提供 metricsemantic_kindmeasure_column 等(或带 semantic_anchorsPromotionPolicy),任何必填项缺失时它会失败即停止。

每个操作都会把证据记录到会话,使结论保持可审计。

  • session.knowledge() —— 整个会话的既定事实、驱动因素事实、未决异常和建议的后续。
  • session.evidence.findings(...).propositions(...).assessments(...).proposition(id).latest_assessment(id).trace(id) —— 查找证据对象, 并把一个命题追溯回支持它的证据项。

完整模型见 证据

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("sales.revenue")
region = catalog.get("sales.orders.region")
current = session.observe(
revenue,
timescope={"start": "2026-10-01", "end": "2027-01-01"},
grain="month",
dimensions=[region],
)
baseline = session.observe(
revenue,
timescope={"start": "2025-10-01", "end": "2026-01-01"},
grain="month",
dimensions=[region],
)
delta = session.compare(current, baseline)
attribution = session.decompose(delta, axis=region)
attribution.show()

delta 你可以分支:用 session.discover.period_shifts(delta) 找出它何时移动,或用 session.forecast(current, horizon=3) 向前投影。

Frame由谁产出
MetricFrameobserve(以及 promote_metric_frame
DeltaFramecompare
AttributionFramedecompose
AssociationResultcorrelate
ForecastFrameforecast
QualityReportassess_quality
HypothesisTestResulthypothesis_test
CandidateSetdiscover.*
ExplorationResultfrom_pandasexplore_ibis