免费试用

认证

Authentication2

所有受保护端点需要在 Header 中携带 Supabase JWT:

Header
Authorization: Bearer 

后端通过 get_current_user 校验 JWT 并解析用户所属组织,数据按 org_id 行级隔离。

POST/api/auth/ensure-profile创建/获取用户资料

Supabase Auth 注册/登录后调用,创建或返回用户资料。

json
{\n  "display_name": "Ada"\n}
Response 200
{\n  "profile": {\n    "id": "user_123",\n    "org_id": "00000000-0000-0000-0000-000000000001",\n    "display_name": "Ada",\n    "role": "analyst"\n  },\n  "created": true\n}
GET/api/auth/me当前用户

返回已认证用户、组织、角色、邮箱及头像 URL。

基础路径与限制

Base Path & Limits

基础路径:/api(完整 URL 取决于部署环境,本地开发为 http://localhost:8000/api

数据隔离:所有资源按 org_id 隔离,跨组织访问返回 403

并发限制:每个项目同一时间只允许一个活跃模型运行,重复发起返回 409

AI 速率限制:每个组织每 10 秒最多一次 LLM 生成;缓存命中不受限。

注意演示端点 POST /api/agent/upload {"demo":true} 无需认证,但仅返回示例数据。

项目管理

Projects6
GET/api/projects/列出项目

返回当前组织的所有项目,包含 Champion run 摘要(如有)。

POST/api/projects/创建项目
json
{\n  "name": "Q1 Brand MMM",\n  "description": "Weekly revenue model",\n  "kpi_type": "revenue",\n  "time_granularity": "weekly",\n  "geo_level": false,\n  "model_type": "ridge"\n}
Response
{\n  "project": {\n    "id": "project_123",\n    "name": "Q1 Brand MMM",\n    "status": "draft",\n    "kpi_type": "revenue",\n    "time_granularity": "weekly",\n    "geo_level": false,\n    "model_type": "ridge"\n  }\n}
GET/api/projects/{project_id}获取项目

返回已认证用户、组织、角色、邮箱及头像 URL。

Response 200
{
  "user": {
    "id": "user_123",
    "org_id": "00000000-0000-0000-0000-000000000001",
    "email": "ada@brand.com",
    "role": "analyst",
    "display_name": "Ada",
    "avatar_url": null
  }
}
PATCH/api/projects/{project_id}更新项目

所有字段可选:

json
{\n  "name": "Q1 Brand MMM - Final",\n  "kpi_type": "revenue",\n  "time_granularity": "weekly",\n  "geo_level": true,\n  "model_type": "pymc",\n  "config": { "calendar": "us" }\n}
DELETE/api/projects/{project_id}删除项目

获取单个项目详情,包含状态、配置和 Champion run 摘要。

Response 200
{
  "project": {
    "id": "project_123",
    "name": "Q1 Brand MMM",
    "status": "active",
    "kpi_type": "revenue",
    "time_granularity": "weekly",
    "geo_level": false,
    "model_type": "ridge",
    "champion_run_id": "run_456"
  }
}
POST/api/projects/demo创建 Demo 项目

创建内置电商 demo 项目,自动上传演示数据、映射字段并启动 Ridge 运行。

数据上传与映射

Data Upload8

支持 .csv / .xlsx / .xls,最大 50 MB。

POST/api/datasets/{project_id}/upload?strategy=replace上传数据集

Content-Type: multipart/form-data

字段类型必填说明
filefile.csv / .xlsx / .xls
参数可选值默认说明
strategyreplace / append / new_rootreplace数据集版本策略
Response
{\n  "dataset": {\n    "id": "dataset_123",\n    "project_id": "project_123",\n    "file_name": "weekly_marketing.csv",\n    "row_count": 104,\n    "col_count": 9,\n    "version": 1,\n    "is_active": true,\n    "upload_status": "validated"\n  },\n  "analysis": {\n    "row_count": 104,\n    "col_count": 9,\n    "suggested_mappings": [\n      { "column": "week_start", "type": "date" },\n      { "column": "revenue_usd", "type": "kpi" }\n    ]\n  },\n  "quality": { "overall_status": "pass", "findings": [], "stats": {} }\n}
GET/api/datasets/{project_id}/datasets列出数据集版本

删除项目及其关联的数据集和运行记录。操作不可逆。

Response 200
{
  "deleted": true,
  "project_id": "project_123"
}
GET/api/datasets/{project_id}/active获取活跃数据集

返回项目的所有数据集版本,标记当前活跃版本。

Response 200
{
  "datasets": [
    {
      "id": "dataset_123",
      "file_name": "weekly_marketing.csv",
      "row_count": 104,
      "version": 1,
      "is_active": true,
      "upload_status": "validated"
    }
  ]
}
POST/api/datasets/{project_id}/activate/{dataset_id}激活数据集版本

返回当前活跃数据集及其分析摘要。

Response 200
{
  "dataset": {
    "id": "dataset_123",
    "file_name": "weekly_marketing.csv",
    "row_count": 104,
    "col_count": 9,
    "version": 1,
    "is_active": true
  }
}
GET/api/datasets/{dataset_id}/mappings获取字段映射

将指定数据集版本设为活跃。后续模型运行将使用此版本。

Response 200
{
  "dataset": { "id": "dataset_124", "is_active": true },
  "message": "Dataset version activated."
}
PUT/api/datasets/{dataset_id}/mappings更新字段映射
json
{\n  "mappings": [\n    { "source_column": "week_start", "target_type": "date" },\n    { "source_column": "revenue_usd", "target_type": "kpi" },\n    { "source_column": "google_spend", "target_type": "media_spend", "channel_name": "Google" },\n    { "source_column": "holiday_flag", "target_type": "control" }\n  ]\n}

target_type 可选值:date / kpi / media_spend / control / geo / ignore

GET/api/datasets/{dataset_id}/quality?granularity=weekly数据质量报告

返回当前字段映射配置。

Response 200
{
  "mappings": [
    { "source_column": "week_start", "target_type": "date" },
    { "source_column": "revenue_usd", "target_type": "kpi" },
    { "source_column": "google_spend", "target_type": "media_spend", "channel_name": "Google" },
    { "source_column": "holiday_flag", "target_type": "control" }
  ]
}
GET/api/datasets/{dataset_id}/edaEDA 探索性分析

返回列统计、时间序列、花费占比、相关矩阵和分布。

建模分析

Modeling6
POST/api/modeling/{project_id}/run启动模型运行
json
{\n  "model_type": "ridge",\n  "n_chains": 4,\n  "n_iterations": 2000,\n  "config": {\n    "adstock_type": "geometric",\n    "priors": {},\n    "project_settings": {\n      "kpi_type": "revenue",\n      "time_granularity": "weekly",\n      "geo_level": false\n    }\n  }\n}
Response
{\n  "run_id": "run_123",\n  "status": "pending",\n  "dispatch_mode": "subprocess",\n  "message": "Model run started. Poll the status endpoint for progress."\n}
说明Bayesian 引擎需要 n_chains ≥ 2n_iterations ≥ 100。关键数据质量问题返回 422
GET/api/modeling/{project_id}/runs列出运行

返回数据质量报告,包含总体状态和具体 findings。

Response 200
{
  "overall_status": "pass",
  "findings": [
    {
      "severity": "warning",
      "code": "low_variation",
      "message": "Channel tv_spend has low variation (CV=0.08)",
      "column": "tv_spend"
    }
  ],
  "stats": {
    "row_count": 104,
    "col_count": 9,
    "missing_pct": 0.2,
    "duplicate_periods": 0
  }
}
说明granularity 参数可选 daily / weekly / monthly
GET/api/modeling/run/{run_id}/status运行状态
Response
{\n  "id": "run_123",\n  "project_id": "project_123",\n  "status": "sampling",\n  "progress_pct": 45,\n  "current_step": "sampling",\n  "started_at": "2026-07-02T08:00:00Z",\n  "completed_at": null,\n  "duration_seconds": null,\n  "r_squared": null,\n  "mape": null,\n  "max_rhat": null,\n  "min_ess": null,\n  "error_message": null,\n  "model_type": "pymc",\n  "engine": null,\n  "run_config": {}\n}

状态流转:pending → preprocessing → sampling → completed / failed

POST/api/modeling/run/{run_id}/cancel取消运行

返回项目的所有模型运行记录,按时间倒序。

Response 200
{
  "runs": [
    {
      "id": "run_123",
      "status": "completed",
      "model_type": "ridge",
      "r_squared": 0.92,
      "mape": 4.8,
      "is_champion": true,
      "started_at": "2026-07-01T08:00:00Z",
      "duration_seconds": 25
    }
  ]
}
GET/api/modeling/latest最新运行

返回 Champion run(如有),否则返回最近一次完成的运行。

POST/api/champion/{project_id}/start-searchChampion 多引擎搜索
json
{\n  "engines": ["ridge", "pymc"],\n  "n_chains": 4,\n  "n_iterations": 2000,\n  "config": {}\n}

可选引擎:

  • ridge
  • pymc
  • stan
  • meridian
  • robyn
  • nevergrad
  • sparkx
  • sparkx-expert
  • lgbm
注意meridianrobyn 为环境依赖引擎,可能未在所有部署中启用。

结果查询

Results6
GET/api/results/run/{run_id}/summary运行摘要

返回运行元数据和渠道摘要。

GET/api/results/run/{run_id}/channels渠道结果
Response
{\n  "channels": [\n    {\n      "channel_name": "Google",\n      "roi_mean": 3.2,\n      "roi_ci_low": 2.4,\n      "roi_ci_high": 4.1,\n      "contribution_pct": 28.5,\n      "adstock_halflife_weeks": 1.8,\n      "saturation_pct": 64.0,\n      "current_spend": 12000,\n      "marginal_roi": 1.7,\n      "health_score": 82\n    }\n  ]\n}
GET/api/results/run/{run_id}/diagnostics诊断

取消正在进行的模型运行。已完成的运行不受影响。

Response 200
{
  "run_id": "run_123",
  "status": "cancelled",
  "message": "Model run cancelled."
}
注意只有 pending / preprocessing / sampling 状态可取消。
GET/api/results/run/{run_id}/predictions预测

返回时间对齐的 actual / predicted / residual 序列(如可用)。

GET/api/results/run/{run_id}/decomposition贡献分解

返回 baseline 和各渠道贡献序列(如可用)。

GET/api/results/compare/{run_a}/{run_b}对比运行

返回模型诊断指标:R-squared、MAPE、预测 vs 实际序列、残差。

Response 200
{
  "r_squared": 0.92,
  "mape": 4.8,
  "n_observations": 104,
  "predictions": [
    { "date": "2026-01-01", "actual": 128500, "predicted": 126800, "residual": 1700 }
  ]
}

预算优化

Optimization6

支持两种优化目标:给定预算最大化收入给定收入目标最小化花费

POST/api/optimizer/run/{run_id}/optimize优化预算

固定预算模式:

json
{\n  "objective": "maximize_revenue",\n  "total_budget": 250000,\n  "budget_constraints": {\n    "Google": { "min": 50000, "max": 120000 },\n    "Meta": { "min": 30000, "max": 100000 }\n  }\n}

目标收入模式:

json
{\n  "objective": "target_revenue",\n  "target_revenue": 1000000,\n  "budget_constraints": {\n    "Google": { "min": 50000, "max": 150000 }\n  }\n}
Response
{\n  "scenario": {\n    "id": "scenario_123",\n    "run_id": "run_123",\n    "total_budget": 250000,\n    "current_allocation": {},\n    "optimal_allocation": {},\n    "current_revenue": 850000,\n    "predicted_revenue": 930000,\n    "revenue_uplift_pct": 9.4,\n    "recommendations": []\n  }\n}
GET/api/optimizer/run/{run_id}/scenarios优化场景列表

对比两个运行的渠道 ROI、贡献度和诊断指标差异。

Response 200
{
  "run_a": { "id": "run_123", "model_type": "ridge", "r_squared": 0.92 },
  "run_b": { "id": "run_456", "model_type": "pymc", "r_squared": 0.94 },
  "channel_diff": [
    { "channel": "Google", "roi_a": 3.2, "roi_b": 3.5, "roi_diff": 0.3 }
  ]
}
POST/api/scenarios/run/{run_id}/simulate模拟场景
json
{\n  "allocations": {\n    "Google": 90000,\n    "Meta": 70000,\n    "TikTok": 30000\n  }\n}
POST/api/scenarios/run/{run_id}/save保存场景
json
{\n  "name": "Q3 constrained plan",\n  "allocations": { "Google": 90000, "Meta": 70000 },\n  "notes": "Finance-approved cap"\n}
GET/api/scenarios/run/{run_id}/saved列出保存的场景

返回该运行的所有优化场景。

Response 200
{
  "scenarios": [
    {
      "id": "scenario_123",
      "name": "Maximize Q3 Revenue",
      "total_budget": 250000,
      "predicted_revenue": 930000,
      "revenue_uplift_pct": 9.4
    }
  ]
}
DELETE/api/scenarios/run/{run_id}/saved/{scenario_id}删除场景

返回用户保存的 what-if 场景列表。

Response 200
{
  "scenarios": [
    {
      "id": "scenario_125",
      "name": "Q3 constrained plan",
      "allocations": { "Google": 90000, "Meta": 70000 },
      "notes": "Finance-approved cap"
    }
  ]
}

AI 洞察

AI Insights3

Claude 驱动的自然语言解读,支持中英双语。每个 section 可独立生成或重新生成。

POST/api/interpretations/run/{run_id}/generate生成 AI 洞察
json
{\n  "section": "executive_summary",\n  "force_regenerate": false,\n  "locale": "zh",\n  "custom_prompt": null\n}

可选 section

  • executive_summary — 执行摘要
  • channel_deep_dive — 渠道深度解读
  • risk_warnings — 风险提醒
  • action_plan — 行动计划
  • analyst_commentary — 分析师评论
  • budget_rationale — 预算依据
Response
{\n  "interpretation": {\n    "id": "interp_123",\n    "run_id": "run_123",\n    "section": "executive_summary",\n    "content_md": "## Executive Summary\\n...",\n    "content_structured": null,\n    "model_used": "claude-sonnet-4-20250514"\n  },\n  "cached": false\n}
速率限制每组织每 10 秒最多一次 LLM 生成。缓存命中不受限,force_regenerate=true 强制重新生成。
GET/api/interpretations/run/{run_id}获取全部洞察

删除指定的保存场景。删除后不可恢复。

Response 200
{
  "deleted": true,
  "scenario_id": "scenario_125"
}
POST/api/interpretations/run/{run_id}/chat对话追问
json
{\n  "locale": "zh",\n  "messages": [\n    { "role": "user", "content": "Which channel should I cut first?" }\n  ]\n}

数据科学诊断

Diagnostics8

面向数据科学家的模型审计与方法论透明度视图。

GET/api/analyst/run/{run_id}/diagnostics完整诊断

拟合质量、运行元数据、R-squared、MAPE、R-hat、ESS 及参数摘要。

GET/api/analyst/run/{run_id}/convergence收敛诊断

返回该运行所有已生成的 AI 洞察 section。

Response 200
{
  "interpretations": [
    {
      "id": "interp_123",
      "section": "executive_summary",
      "content_md": "## Executive Summary\n...",
      "model_used": "claude-sonnet-4-20250514"
    },
    {
      "id": "interp_124",
      "section": "risk_warnings",
      "content_md": "## Risk Warnings\n..."
    }
  ]
}
GET/api/analyst/run/{run_id}/posterior后验诊断

返回 trace / forest / pair / posterior predictive 检查(仅 Bayesian 运行)。

GET/api/analyst/run/{run_id}/posterior-download后验下载

返回 posterior NetCDF 文件的签名 URL(如可用)。

GET/api/analyst/run/{run_id}/robustness稳健性

返回 Bayesian 运行的收敛指标:R-hat、ESS、divergences。非 Bayesian 运行返回 null。

Response 200
{
  "max_rhat": 1.01,
  "min_ess": 320,
  "n_divergences": 2,
  "n_chains": 4,
  "n_iterations": 2000,
  "converged": true
}
决策规则R-hat ≥ 1.1 的运行不可用于决策。
GET/api/analyst/run/{run_id}/backtest?n_folds=5&horizon=4回测

滚动起点验证,测试样本外稳定性。

GET/api/analyst/run/{run_id}/drift漂移检测

与项目 Champion 对比,检测模型或数据漂移。

GET/api/analyst/run/{run_id}/limitations局限性

基于模型类型、拟合、不确定性和饱和度的透明告警。

报告下载

Reports2
GET/api/analyst/run/{run_id}/report.pptx下载 PowerPoint

返回二进制 .pptx 文件。

Content-Disposition: MMM_Report_{project_name}_{run_id}.pptx

GET/api/analyst/run/{run_id}/report.html下载 HTML 报告

返回自包含 HTML 报告,可直接在浏览器打开。

Agent 与 Demo Pipeline

Agent & Demo4

AutoMMM 的对话式 pipeline 接口,支持 demo 模式和文件上传模式。

POST/api/agent/upload上传或启动 Demo

Demo 模式(无需认证):

json
{\n  "demo": true,\n  "mode": "instant",\n  "locale": "zh"\n}

文件模式(multipart):

字段类型说明
filefileCSV / XLSX / XLS
modestringinstantexpert
localestringzhen
Response
{\n  "task_id": "task_123",\n  "status": "running",\n  "messages": []\n}
GET/api/agent/pipeline/{task_id}?offset=0轮询 Pipeline

返回模型稳健性评估:CI 宽度、预测精度、集中度风险。

Response 200
{
  "avg_ci_width": 0.8,
  "prediction_accuracy": 95.2,
  "concentration_risk": "low",
  "channel_stability": [
    { "channel": "Google", "ci_width": 0.6, "stable": true },
    { "channel": "TikTok", "ci_width": 1.8, "stable": false }
  ]
}
POST/api/agent/chatAgent 对话

轮询 AutoMMM pipeline 进度和消息流。offset 参数用于增量拉取新消息。

Response 200
{
  "task_id": "task_123",
  "status": "running",
  "progress_pct": 60,
  "current_step": "roi_analysis",
  "messages": [
    { "step": "data_quality", "status": "completed", "message": "Data quality check passed" },
    { "step": "eda", "status": "completed", "message": "EDA completed, 5 channels detected" },
    { "step": "roi_analysis", "status": "running", "message": "Computing channel ROI..." }
  ]
}
POST/api/agent/cancel/{task_id}取消 Pipeline

与 AutoMMM pipeline 进行对话式追问。基于当前 pipeline 结果上下文回答。

json
{
  "task_id": "task_123",
  "message": "TikTok 的 ROI 为什么这么高?"
}
Response 200
{
  "reply": "TikTok ROI 为 4.2,高于 Google(3.2)。主要原因是 TikTok 当前花费较低,处于响应曲线陡峭区间...",
  "context": { "run_id": "run_123" }
}

错误码

Error Codes

SparkX 使用标准 HTTP 状态码,错误响应包含 JSON detail 字段。

状态码含义常见原因
400请求错误无效策略、不支持的引擎、参数格式错误
401未授权缺少或无效的 JWT
403禁止访问资源属于其他组织
404未找到项目、数据集、运行、诊断或报告不存在
409冲突该项目已有活跃模型运行
413文件过大上传文件超过 50 MB
422验证失败数据质量问题、模型配置无效
429速率限制AI 生成调用过于频繁
500服务器错误存储、解析或后端异常
502上游 AI 故障LLM 提供方失败
503服务不可用LLM 未配置
结构化错误
{
  "detail": {
    "code": "data_quality_failed",
    "message": "Data quality check failed (2 critical issues)",
    "findings": []
  }
}
简单错误
{
  "detail": "Project not found"
}

代码示例

Code Examples

cURL — 上传 CSV

bash
curl -X POST "http://localhost:8000/api/datasets/project_123/upload?strategy=replace" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@weekly_marketing.csv"

cURL — 启动运行并轮询

bash
curl -X POST "http://localhost:8000/api/modeling/project_123/run" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "model_type": "ridge", "n_chains": 4, "n_iterations": 2000 }'

curl "http://localhost:8000/api/modeling/run/run_123/status" \
  -H "Authorization: Bearer $TOKEN"

Python

python
import time, requests

BASE = "http://localhost:8000"
TOKEN = "YOUR_SUPABASE_JWT"
H = {"Authorization": f"Bearer {TOKEN}"}

project = requests.post(f"{BASE}/api/projects/",
    headers={**H, "Content-Type": "application/json"},
    json={"name": "API MMM", "kpi_type": "revenue",
          "time_granularity": "weekly", "geo_level": False,
          "model_type": "ridge"}).json()["project"]

with open("weekly_marketing.csv", "rb") as f:
    upload = requests.post(f"{BASE}/api/datasets/{project['id']}/upload",
        headers=H, files={"file": f}).json()

run = requests.post(f"{BASE}/api/modeling/{project['id']}/run",
    headers={**H, "Content-Type": "application/json"},
    json={"model_type": "ridge", "n_chains": 4,
          "n_iterations": 2000, "config": {}}).json()

run_id = run["run_id"]
while True:
    st = requests.get(f"{BASE}/api/modeling/run/{run_id}/status",
        headers=H).json()
    print(st["status"], st.get("progress_pct"), st.get("current_step"))
    if st["status"] in ("completed", "failed"):
        break
    time.sleep(5)

summary = requests.get(f"{BASE}/api/results/run/{run_id}/summary",
    headers=H).json()
print(summary)

JavaScript

javascript
const BASE = "http://localhost:8000";
const token = "YOUR_SUPABASE_JWT";

async function api(path, options = {}) {
  const headers = new Headers(options.headers || {});
  headers.set("Authorization", "Bearer " + token);
  if (!(options.body instanceof FormData))
    headers.set("Content-Type", "application/json");
  const res = await fetch(BASE + path, { ...options, headers });
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

const { project } = await api("/api/projects/", {
  method: "POST",
  body: JSON.stringify({
    name: "JS MMM", kpi_type: "revenue",
    time_granularity: "weekly", geo_level: false, model_type: "ridge"
  })
});

const form = new FormData();
form.append("file", fileInput.files[0]);
await api("/api/datasets/" + project.id + "/upload?strategy=replace", {
  method: "POST", body: form
});

const { run_id } = await api("/api/modeling/" + project.id + "/run", {
  method: "POST",
  body: JSON.stringify({
    model_type: "ridge", n_chains: 4, n_iterations: 2000, config: {}
  })
});
const status = await api("/api/modeling/run/" + run_id + "/status");
console.log(status);

本站使用 Cookie 和类似技术以提升体验并分析流量。继续浏览即表示同意。详见隐私政策