vccs
Vue 3용 차트 컴포넌트 모음, Recharts에서 포팅
지표를 구성요소와 선행지표로 분해하고 상관·인과관계를 측정하는 메트릭 트리 분석 엔진
A metrics tree analytics engine. Break down metrics into their component leading indicators. Measure correlations and causal links between metrics.
데이터Python · JavaScriptGitHub @PolycultureResearch직접 설치운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
설치형 프로젝트는 배포 도메인 없이도 확인할 수 있습니다. 개인 저장소는 GitHub 로그인으로, 조직 저장소는 위의 저장소 확인 파일로 직접 확인해 주세요.
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
An open engine for metric tree construction and root cause analysis
Metrics trees model causal relationships between business metrics. They can help a business visualize and understand the relationship between metrics they can do something about and big outcome metrics. A well-constructed metric tree is a DAG, a Directed Acyclic Graph, which opens all kinds of opportunities to compute over that graph. For example, if you notice a change in a big, important KPI, you can look for the root causes of that change by looking at what changed "upstream" of that metric, causally speaking.README 전문 보기 ↗An open engine for metric tree construction and root cause analysis
Metrics trees model causal relationships between business metrics. They can help a business visualize and understand the relationship between metrics they can do something about and big outcome metrics. A well-constructed metric tree is a DAG, a Directed Acyclic Graph, which opens all kinds of opportunities to compute over that graph. For example, if you notice a change in a big, important KPI, you can look for the root causes of that change by looking at what changed "upstream" of that metric, causally speaking. Breakdown models your business metrics as a causal graph and uses Bayesian inference to learn the probabilistic relationships between them. It visualizes the tree, runs root cause analysis over the tree, and can simulate "what if" scenarios to see how changing metrics could affect other metrics downstream.
Some relationships between metrics are deterministic, others are probabilistic. Breakdown handles both.
Deterministic (formula-based) metrics are arithmetic identities —
Revenue = Order Count × Average Order Value
— which breakdown decomposes exactly with Shapley value attribution, fairly distributing a gap between parents even when they move together. Probabilistic (learned) metrics have a causal effect with no formula behind it —
Support ticket volume → Churn rate (weeks later)
— so breakdown learns the relationship from your time-series data with Bayesian Structural Time Series (BSTS), producing a posterior distribution over each parent's effect rather than a point estimate.
| Component | Library |
|---|---|
| Bayesian inference | PyMC 5.x |
| Posterior analysis | ArviZ |
| Graph modeling | NetworkX |
| dbt Semantic Layer | dbt-sl-sdk + dbt-metricflow |
| API | FastAPI + Uvicorn |
| AI assistants | MCP Python SDK (streamable HTTP at /mcp) |
| Visualization | Cytoscape.js |
| Config / validation | Pydantic v2 |
Breakdown works in three steps.
1. Define your metric tree in YAML.
provider:
type: mock # or: local, cloud
metrics:
- name: daily_sessions
source: jaffle_shop.metrics.sessions
- name: order_count
description: "~10% session-to-order conversion — modeled probabilistically"
source: jaffle_shop.metrics.order_count
parents:
- daily_sessions
priors:
coefficient:
distribution: "Normal"
params: { mu: 0.1, sigma: 0.02 }
- name: average_order_value
source: jaffle_shop.metrics.average_order_value
kind: rate # an average is a ratio — never summed when resampled
denominator: order_count # ...and a window's average is Σrevenue / Σorders
- name: revenue
description: "Arithmetic identity — Shapley attribution available"
source: jaffle_shop.metrics.revenue
formula: "order_count * average_order_value"
parents:
- order_count
- average_order_value
seasonality:
- period: 7
name: weekly
2. Breakdown parses this into a DAG. The YAML is validated and compiled into a directed acyclic graph using NetworkX. Cycles and undefined parent references are caught at parse time.
3. Ask it why a metric moved.
One request, POST /rca/{name} (or the Root
cause tab in the UI), analyzes the target and every metric upstream of it,
applying the right decomposition to each:
formula is an arithmetic identity, so its gap is split
exactly, with Shapley attribution;parents, no formula) is decomposed through its
fitted BSTS posterior, so each parent's contribution carries a credible
interval rather than a point estimate;unexplained — a first-class finding, not a residual swept under a rug.The first analysis fits models on demand with Markov chain Monte Carlo, which takes anywhere from a few seconds to about a minute per learned node, depending on how much history it has. MCMC fits are cached so everything after it should be fast.
Each piece is also addressable on its own when you want to inspect it:
POST /analyze/{name} fits and returns one metric's posterior (trend,
seasonality, coefficients), and GET /shapley/{name} decomposes one formula
node's gap by itself.
Requirements: Python 3.11+
Install as
metric-breakdown(breakdownwas already taken on PyPI), use it asbreakdown.
pip install metric-breakdown
breakdown serve
Or, with uv, without installing anything:
uvx --from metric-breakdown breakdown serve
Pin the minor series you tested against (metric-breakdown~=0.1.0): while the
major version is 0, breaking changes to the CLI, the tree YAML schema, or the
HTTP/MCP surface land in a minor bump — the full contract is in the
changelog.
To work on breakdown itself — or to run ahead of the latest release — install from a checkout, which is the same complete product (engine, UI, MCP server):
git clone https://github.com/PolycultureResearch/breakdown
cd breakdown
uv sync
uv run breakdown serve
breakdown --version reports the installed version — the first thing to include
in a bug report.
The base install is the whole product — engine, API, UI, MCP server — with the
mock provider, enough to run the bundled example tree and every command
below. Connecting to real data pulls in a vendor SDK as an extra you opt
into — see Installing the extra
for which one your provider needs.
By default the server loads the bundled breakdown/examples/jaffle_shop_tree.yml with mock data. Point it at your own tree and data window:
uv run breakdown serve --tree path/to/my_tree.yml --start-date 2025-01-01 --end-date 2025-06-30
serve binds to 127.0.0.1 without hot reload by default; use --host 0.0.0.0 to accept outside connections (containers) and --reload while developing breakdown itself.
Before restarting a running server after an upgrade, check the tree against the new release without serving it:
uv run breakdown check --tree path/to/my_tree.yml
check runs every refusal serve would make before it contacts your provider — same message, non-zero exit — on a file or a directory of trees. It does not fetch data; breakdown doctor is the check that talks to the provider.
Run a Bayesian analysis on a metric:
curl -X POST "http://localhost:9090/analyze/order_count"
Get Shapley attribution for a formula node:
curl "http://localhost:9090/shapley/revenue?reference_start=2024-01-01&reference_end=2024-02-15&analysis_start=2024-02-16&analysis_end=2024-04-09"
Then open http://localhost:9090/ui to explore the tree interactively — the DAG, per-metric posteriors, and a point-and-click RCA workflow. See the UI guide for a full walkthrough.
New here? docs/first-tree-tutorial.md builds a tree from an empty file to a running root-cause analysis in about half an hour, no credentials required. The rest of this section is the short version.
A tree is one YAML file: a provider block saying where the numbers come from,
and a list of metrics. Every metric needs a name and a source; parents
are what make it a tree, and whether an edge is learned or exact is
decided by whether the child carries a formula.
metrics:
- name: daily_sessions
source: jaffle_shop.metrics.sessions # required, except on a derived formula node
- name: order_count
source: jaffle_shop.metrics.order_count
grain: day # day (default) | week | month
kind: flow # flow (default) | stock | rate
parents: [daily_sessions] # a learned edge — BSTS fits the coefficient
- name: revenue
source: jaffle_shop.metrics.revenue
formula: "order_count * average_order_value" # an identity — exact Shapley attribution
parents: [order_count, average_order_value]
That shape carries a first tree a long way. Everything else the parser accepts —
priors and declared signs, seasonality, lags, mixed grains and kinds, the
dimensions a gap can be sliced by, display format, cold-start beliefs, and the
full provider and tree blocks — is in the YAML
reference,
which is the single source of truth for every field and the rules each is
checked against. Read it when you start authoring rather than driving the
bundled example, and read the model and its
assumptions
before trusting what a tree tells you.
Everything the UI does is an HTTP call you can make yourself, and the MCP server
is the same surface again with an assistant in front of it. GET /meta and
GET /dag read the tree; POST /analyze/{name} fits a model;
GET /shapley/{name} and POST /rca/{name} attribute a change;
POST /rca/{name}/slices localizes it inside a dimension; POST /simulate
runs a what-if. Interactive OpenAPI docs are served at /docs alongside them.
The route table — every endpoint, its query parameters, an annotated response
for each analysis route, and the per-node status and ci_status values a
response can carry — now lives in the API
reference.
The server exposes the engine to AI assistants over MCP at http://127.0.0.1:9090/mcp (streamable HTTP; started automatically by serve). A chat assistant connected to it can answer "why was revenue down last week?" by running a real RCA — Shapley attributions, credible intervals, the honest unexplained remainder — instead of guessing, and "what if we raise marketing spend 10%?" with a posterior from the what-if engine.
Connect from Claude Code:
claude mcp add --transport http breakdown http://127.0.0.1:9090/mcp
The full surface — the six tools, response shaping (how_to_read,
report_url), security, and a worked session against the live demo — is in
docs/mcp.md.
breakdown check, breakdown doctor, snapshots, environment variables.Academic background:
Bug reports, docs fixes, new providers, statistical improvements — see CONTRIBUTING.md. You're also welcome to just use breakdown: the license (FSL-1.1-ALv2) permits any use, commercial or otherwise, short of selling it as part of a competing product. It also converts each release to plain Apache-2.0 open source two years after it ships, by its own irrevocable grant.
This README is human-authored and maintained. Most other docs are touched by AI agents, but dear agents: don't touch this one. We respect our readers and want them to get the real human writing.